Embedded SDK
Embedded SDK
Loading...
Searching...
No Matches
ledger_ble.c
Go to the documentation of this file.
1
2/*******************************************************************************
3 * Ledger Nano S - Secure firmware
4 * (c) 2022 Ledger
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 ********************************************************************************/
18
19/* Includes ------------------------------------------------------------------*/
20#include "os.h"
21#include "os_settings.h"
22#include "os_io_seproxyhal.h"
23
24#include "ble_hci_le.h"
25#include "ble_hal_aci.h"
26#include "ble_gap_aci.h"
27#include "ble_l2cap_aci.h"
28#include "ble_gatt_aci.h"
29#include "ble_legacy.h"
30
31#include "lcx_rng.h"
32
33#include "ledger_protocol.h"
34#include "ledger_ble.h"
35
36/* Private enumerations ------------------------------------------------------*/
45
62
71
72/* Private types, structures, unions -----------------------------------------*/
90
141
142/* Private defines------------------------------------------------------------*/
143#define MAX_MTU_SIZE 156
144
145#define BLE_SLAVE_CONN_INTERVAL_MIN 12 // 15ms
146#define BLE_SLAVE_CONN_INTERVAL_MAX 24 // 30ms
147
148#define BLE_ADVERTISING_INTERVAL_MIN 48 // 30ms
149#define BLE_ADVERTISING_INTERVAL_MAX 96 // 60ms
150
151#ifdef HAVE_PRINTF
152#define LOG_BLE PRINTF
153#else // !HAVE_PRINTF
154#define LOG_BLE(...)
155#endif // !HAVE_PRINTF
156
157/* Private macros-------------------------------------------------------------*/
158
159/* Private functions prototypes ----------------------------------------------*/
160static void get_device_name(void);
161static void configure_advertising_mngr(uint16_t opcode);
162static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length);
163static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length);
164static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length);
165static void hci_evt_vendor(const uint8_t *buffer, uint16_t length);
166#ifdef HAVE_INAPP_BLE_PAIRING
167static void end_pairing_ux(uint8_t pairing_ok);
168static void ask_user_pairing_numeric_comparison(uint32_t code);
169static void rsp_user_pairing_numeric_comparison(unsigned int status);
170static void ask_user_pairing_passkey(void);
171static void rsp_user_pairing_passkey(unsigned int status);
172#endif // HAVE_INAPP_BLE_PAIRING
173static void attribute_modified(const uint8_t *buffer, uint16_t length);
174static void write_permit_request(const uint8_t *buffer, uint16_t length);
175static void advertising_enable(uint8_t enable);
176static void start_advertising(void);
177static void notify_chunk(void);
178static void check_transfer_mode(uint8_t enable);
179
180/* Exported variables --------------------------------------------------------*/
181
182/* Private variables ---------------------------------------------------------*/
183// clang-format off
184#ifdef TARGET_FLEX
185const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
186const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
187const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
188const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x30,0x97,0x2C,0x00,0x34,0xD6,0x13,};
189#endif
190
191#ifdef TARGET_STAX
192const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
193const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
194const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
195const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x60,0x97,0x2C,0x00,0x34,0xD6,0x13,};
196#endif
197
198#ifdef TARGET_NANOX
199const uint8_t service_uuid[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x00,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
200const uint8_t charUuidTX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x01,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
201const uint8_t charUuidRX[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x02,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
202const uint8_t charUuidRX2[16] = {0x72,0x65,0x67,0x64,0x65,0x4c,0x03,0x00,0x04,0x00,0x97,0x2C,0x00,0x34,0xD6,0x13,};
203#endif
204// clang-format on
205
206static ledger_protocol_t ledger_protocol_data;
207static ledger_ble_data_t ledger_ble_data;
208
209/* Private functions ---------------------------------------------------------*/
210static void copy_apdu_to_app(bool update_wait_status)
211{
212 // `rx_apdu_length` is already checked to be less than
213 // `rx_apdu_buffer_max_length` in `process_apdu_chunk()`
214 memcpy(ledger_protocol_data.rx_dst_buffer,
215 ledger_protocol_data.rx_apdu_buffer,
216 ledger_protocol_data.rx_apdu_length);
217 G_io_app.apdu_length = ledger_protocol_data.rx_apdu_length;
218 G_io_app.apdu_state = APDU_BLE;
219 G_io_app.apdu_media = IO_APDU_MEDIA_BLE;
220 ledger_protocol_data.rx_apdu_length = 0;
221 if (update_wait_status) {
222 ledger_protocol_data.rx_apdu_status = APDU_STATUS_WAITING;
223 }
224}
225
226static void get_device_name(void)
227{
228 memset(ledger_ble_data.device_name, 0, sizeof(ledger_ble_data.device_name));
229 ledger_ble_data.device_name_length = os_setting_get(OS_SETTING_DEVICENAME,
230 (uint8_t *) ledger_ble_data.device_name,
231 sizeof(ledger_ble_data.device_name) - 1);
232}
233
234static void configure_advertising_mngr(uint16_t opcode)
235{
236 if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) {
237 // Unexpected event => BLE_TODO
238 return;
239 }
240
241 uint8_t buffer[31];
242 uint8_t index = 0;
243
244 if (ledger_ble_data.adv_step == BLE_CONFIG_ADV_STEP_IDLE) {
245 ledger_ble_data.connection.connection_handle = 0xFFFF;
246 ledger_ble_data.advertising_enabled = 0;
247 LOG_BLE("CONFIGURE ADVERTISING START\n");
248 }
249 else if (ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1)) {
250 ledger_ble_data.advertising_enabled = 1;
251 }
252
253 ledger_ble_data.adv_step++;
254 if ((ledger_ble_data.adv_step == (BLE_CONFIG_ADV_STEP_END - 1))
255 && (!ledger_ble_data.adv_enable)) {
256 ledger_ble_data.adv_step++;
257 }
258
259 switch (ledger_ble_data.adv_step) {
261 // Flags
262 buffer[index++] = 2;
263 buffer[index++] = AD_TYPE_FLAGS;
264 buffer[index++] = FLAG_BIT_BR_EDR_NOT_SUPPORTED | FLAG_BIT_LE_GENERAL_DISCOVERABLE_MODE;
265
266 // Complete Local Name
267 get_device_name();
268 buffer[index++] = ledger_ble_data.device_name_length + 1;
269 buffer[index++] = AD_TYPE_COMPLETE_LOCAL_NAME;
270 memcpy(&buffer[index], ledger_ble_data.device_name, ledger_ble_data.device_name_length);
271 index += ledger_ble_data.device_name_length;
272
273 ledger_ble_data.hci_cmd_opcode = 0xfc8e;
274 aci_gap_update_adv_data(index, buffer);
275 break;
276
278 // Incomplete List of 128-bit Service UUIDs
279 buffer[index++] = sizeof(service_uuid) + 1;
280 buffer[index++] = AD_TYPE_128_BIT_SERV_UUID;
281 memcpy(&buffer[index], service_uuid, sizeof(service_uuid));
282 index += sizeof(service_uuid);
283
284 // Slave Connection Interval Range
285 buffer[index++] = 5;
286 buffer[index++] = AD_TYPE_SLAVE_CONN_INTERVAL;
287 buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MIN;
288 buffer[index++] = 0;
289 buffer[index++] = BLE_SLAVE_CONN_INTERVAL_MAX;
290 buffer[index++] = 0;
291
292 ledger_ble_data.hci_cmd_opcode = 0x2009;
293 hci_le_set_scan_response_data(index, buffer);
294 break;
295
297 ledger_ble_data.hci_cmd_opcode = 0xfd06;
298 aci_gatt_update_char_value(ledger_ble_data.gap_service_handle,
300 0,
301 ledger_ble_data.device_name_length,
302 (uint8_t *) ledger_ble_data.device_name);
303 break;
304
306 ledger_ble_data.hci_cmd_opcode = 0xfc83;
307 advertising_enable(1);
308 break;
309
310 default:
311 LOG_BLE("CONFIGURE ADVERTISING END\n");
312 if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) {
313 ledger_ble_data.state = BLE_STATE_INITIALIZED;
314 }
315 break;
316 }
317}
318
319static void init_mngr(uint16_t opcode, const uint8_t *buffer, uint16_t length)
320{
321 UNUSED(length);
322
323 if ((ledger_ble_data.hci_cmd_opcode != 0xFFFF) && (opcode != ledger_ble_data.hci_cmd_opcode)) {
324 // Unexpected event => BLE_TODO
325 return;
326 }
327
328 if (ledger_ble_data.init_step == BLE_INIT_STEP_IDLE) {
329 LOG_BLE("INIT START\n");
330 }
331 else if ((length >= 6) && (ledger_ble_data.init_step == BLE_INIT_STEP_GAP_INIT)) {
332 ledger_ble_data.gap_service_handle = U2LE(buffer, 1);
333 ledger_ble_data.gap_device_name_characteristic_handle = U2LE(buffer, 3);
334 ledger_ble_data.gap_appearance_characteristic_handle = U2LE(buffer, 5);
335 }
336 else if ((length >= 2) && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_SERVICE)) {
337 ledger_ble_data.ledger_gatt_service_handle = U2LE(buffer, 1);
338 }
339 else if ((length >= 2)
341 ledger_ble_data.ledger_gatt_notification_characteristic_handle = U2LE(buffer, 1);
342 }
343 else if ((length >= 2)
344 && (ledger_ble_data.init_step == BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC)) {
345 ledger_ble_data.ledger_gatt_write_characteristic_handle = U2LE(buffer, 1);
346 }
347 else if ((length >= 2)
349 ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle = U2LE(buffer, 1);
350 }
351 else if (ledger_ble_data.init_step == BLE_INIT_STEP_CONFIGURE_ADVERTISING) {
352 ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
353 configure_advertising_mngr(opcode);
354 if (ledger_ble_data.adv_step != BLE_CONFIG_ADV_STEP_END) {
355 return;
356 }
357 }
358
359 ledger_ble_data.init_step++;
360
361 switch (ledger_ble_data.init_step) {
363 hci_reset();
364 break;
365
367 ledger_ble_data.hci_cmd_opcode = 0xfc0c;
368 aci_hal_write_config_data(CONFIG_DATA_RANDOM_ADDRESS_OFFSET,
369 CONFIG_DATA_RANDOM_ADDRESS_LEN,
370 ledger_ble_data.random_address);
371 break;
372
374 ledger_ble_data.hci_cmd_opcode = 0xfd01;
375 aci_gatt_init();
376 break;
377
379 ledger_ble_data.hci_cmd_opcode = 0xfc8a;
380 aci_gap_init(GAP_PERIPHERAL_ROLE,
381 PRIVACY_DISABLED,
382 sizeof(ledger_ble_data.device_name) - 1,
383 &ledger_ble_data.gap_service_handle,
385 &ledger_ble_data.gap_appearance_characteristic_handle);
386 break;
387
389 ledger_ble_data.hci_cmd_opcode = 0xfc85;
390 aci_gap_set_io_capability(IO_CAP_DISPLAY_YES_NO);
391 break;
392
394 ledger_ble_data.hci_cmd_opcode = 0xfc86;
395 aci_gap_set_authentication_requirement(
396 BONDING,
397 MITM_PROTECTION_REQUIRED,
398 0x01, // LE Secure connections pairing supported but optional
399 KEYPRESS_NOT_SUPPORTED,
400 MIN_ENCRY_KEY_SIZE + 1,
401 MAX_ENCRY_KEY_SIZE,
402 DONOT_USE_FIXED_PIN_FOR_PAIRING,
403 0,
404 STATIC_RANDOM_ADDR);
405 break;
406
408 ledger_ble_data.hci_cmd_opcode = 0xfd02;
409 aci_gatt_add_service(UUID_TYPE_128,
410 (const Service_UUID_t *) service_uuid,
411 PRIMARY_SERVICE,
412 9,
413 &ledger_ble_data.ledger_gatt_service_handle);
414 break;
415
417 ledger_ble_data.hci_cmd_opcode = 0xfd04;
418 aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
419 UUID_TYPE_128,
420 (const Char_UUID_t *) charUuidTX,
422 CHAR_PROP_NOTIFY,
423 ATTR_PERMISSION_AUTHEN_WRITE,
424 GATT_DONT_NOTIFY_EVENTS,
425 MAX_ENCRY_KEY_SIZE,
426 CHAR_VALUE_LEN_VARIABLE,
428 break;
429
431 ledger_ble_data.hci_cmd_opcode = 0xfd04;
432 aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
433 UUID_TYPE_128,
434 (const Char_UUID_t *) charUuidRX,
436 CHAR_PROP_WRITE,
437 ATTR_PERMISSION_AUTHEN_WRITE,
438 GATT_NOTIFY_WRITE_REQ_AND_WAIT_FOR_APPL_RESP,
439 MAX_ENCRY_KEY_SIZE,
440 CHAR_VALUE_LEN_VARIABLE,
442 break;
443
445 ledger_ble_data.hci_cmd_opcode = 0xfd04;
446 aci_gatt_add_char(ledger_ble_data.ledger_gatt_service_handle,
447 UUID_TYPE_128,
448 (const Char_UUID_t *) charUuidRX2,
450 CHAR_PROP_WRITE_WITHOUT_RESP,
451 ATTR_PERMISSION_AUTHEN_WRITE,
452 GATT_NOTIFY_ATTRIBUTE_WRITE,
453 MAX_ENCRY_KEY_SIZE,
454 CHAR_VALUE_LEN_VARIABLE,
456 break;
457
459 ledger_ble_data.hci_cmd_opcode = 0xfc0f;
460 aci_hal_set_tx_power_level(1, // High power (ignored)
461#if defined(TARGET_STAX) || defined(TARGET_FLEX)
462 0x19); // 0 dBm
463#else // !TARGET_STAX
464 0x07); // -14.1 dBm
465#endif // !TARGET_STAX
466 break;
467
469 ledger_ble_data.hci_cmd_opcode = 0xFFFF;
470 ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE;
471 ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
472 configure_advertising_mngr(0);
473 break;
474
476 LOG_BLE("INIT END\n");
477 if (ledger_ble_data.clear_pairing == 0xC1) {
478 ledger_ble_data.clear_pairing = 0;
479 aci_gap_clear_security_db();
480 }
481 G_io_app.ble_ready = 1;
482 ledger_ble_data.state = BLE_STATE_INITIALIZED;
483 break;
484
485 default:
486 break;
487 }
488}
489
490static void hci_evt_cmd_complete(const uint8_t *buffer, uint16_t length)
491{
492 if (length < 3) {
493 return;
494 }
495
496 uint16_t opcode = U2LE(buffer, 1);
497
498 if (ledger_ble_data.state == BLE_STATE_INITIALIZING) {
499 init_mngr(opcode, &buffer[3], length);
500 }
501 else if (ledger_ble_data.state == BLE_STATE_CONFIGURE_ADVERTISING) {
502 configure_advertising_mngr(opcode);
503 }
504 else if (opcode == 0xfd26) {
505 // ACI_GATT_WRITE_RESP
506 if (ledger_ble_data.wait_write_resp_ack != 0) {
507 ledger_ble_data.wait_write_resp_ack = 0;
508 if (ledger_protocol_data.tx_chunk_length >= 2) {
509 G_io_app.ble_xfer_timeout = 2000;
510 notify_chunk();
511 }
512 }
513 }
514 else if (opcode == 0xfd06) {
515 // ACI_GATT_UPDATE_CHAR_VALUE
516 ledger_protocol_data.tx_chunk_length = 0;
517 if (ledger_ble_data.transfer_mode_enable) {
518 if ((ledger_protocol_data.rx_apdu_length)
519 && (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE)) {
520 copy_apdu_to_app(false);
521 }
522 }
523 else {
524 if (ledger_protocol_data.tx_apdu_buffer) {
525 LEDGER_PROTOCOL_tx(&ledger_protocol_data, NULL, 0);
526 notify_chunk();
527 }
528 if (!ledger_protocol_data.tx_apdu_buffer) {
529 ledger_protocol_data.tx_chunk_length = 0;
530 G_io_app.ble_xfer_timeout = 0;
531 G_io_app.apdu_state = APDU_IDLE;
532 if ((!ledger_ble_data.connection_updated)
534 ledger_ble_data.connection_updated = 1;
535 aci_l2cap_connection_parameter_update_req(
536 ledger_ble_data.connection.connection_handle,
539 ledger_ble_data.connection.conn_latency,
540 ledger_ble_data.connection.supervision_timeout);
541 }
542 }
543 }
544 }
545 else if ((opcode == 0xfc81) || (opcode == 0xfc83)) {
546 LOG_BLE("HCI_LE_SET_ADVERTISE_ENABLE %04X %d %d\n",
547 ledger_ble_data.connection.connection_handle,
548 G_io_app.disabling_advertising,
549 G_io_app.enabling_advertising);
550 if (ledger_ble_data.connection.connection_handle != 0xFFFF) {
551 if (G_io_app.disabling_advertising) {
552 // Connected & ordered to disable ble, force disconnection
553#ifdef HAVE_INAPP_BLE_PAIRING
554 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
555#endif // HAVE_INAPP_BLE_PAIRING
557 }
558 }
559 else if (G_io_app.disabling_advertising) {
560 ledger_ble_data.advertising_enabled = 0;
561 if (G_io_app.name_changed) {
562 start_advertising();
563 }
564 }
565 else if (G_io_app.enabling_advertising) {
566 ledger_ble_data.advertising_enabled = 1;
567 }
568 else {
569 ledger_ble_data.advertising_enabled = 1;
570 }
571 G_io_app.disabling_advertising = 0;
572 G_io_app.enabling_advertising = 0;
573 }
574 else if (opcode == 0xfca5) {
575 LOG_BLE("ACI_GAP_NUMERIC_COMPARISON_VALUE_CONFIRM_YESNO\n");
576 }
577 else if (opcode == 0xfc94) {
578 LOG_BLE("ACI_GAP_CLEAR_SECURITY_DB\n");
579 }
580 else if (opcode == 0xfd25) {
581 LOG_BLE("ACI_GATT_CONFIRM_INDICATION\n");
582 }
583 else {
584 LOG_BLE("HCI EVT CMD COMPLETE 0x%04X\n", opcode);
585 }
586}
587
588static void hci_evt_le_meta_evt(const uint8_t *buffer, uint16_t length)
589{
590 if (!length) {
591 return;
592 }
593
594 switch (buffer[0]) {
595 case HCI_LE_CONNECTION_COMPLETE_SUBEVT_CODE:
596 ledger_ble_data.connection.connection_handle = U2LE(buffer, 2);
597 ledger_ble_data.connection.role_slave = buffer[4];
598 ledger_ble_data.connection.peer_address_random = buffer[5];
599 memcpy(ledger_ble_data.connection.peer_address, &buffer[6], 6);
600 ledger_ble_data.connection.conn_interval = U2LE(buffer, 12);
601 ledger_ble_data.connection.conn_latency = U2LE(buffer, 14);
602 ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 16);
603 ledger_ble_data.connection.master_clock_accuracy = buffer[18];
604 ledger_ble_data.connection.encrypted = 0;
605 ledger_ble_data.transfer_mode_enable = 0;
606 LOG_BLE("LE CONNECTION COMPLETE %04X - %04X- %04X- %04X\n",
607 ledger_ble_data.connection.connection_handle,
608 ledger_ble_data.connection.conn_interval,
609 ledger_ble_data.connection.conn_latency,
610 ledger_ble_data.connection.supervision_timeout);
611 ledger_protocol_data.mtu = ATT_MTU - 3 + 2;
612 ledger_ble_data.notifications_enabled = 0;
613 ledger_ble_data.advertising_enabled = 0;
614 ledger_protocol_data.mtu_negotiated = 0;
615 ledger_ble_data.connection_updated = 0;
616 break;
617
618 case HCI_LE_CONNECTION_UPDATE_COMPLETE_SUBEVT_CODE:
619 ledger_ble_data.connection.connection_handle = U2LE(buffer, 2);
620 ledger_ble_data.connection.conn_interval = U2LE(buffer, 4);
621 ledger_ble_data.connection.conn_latency = U2LE(buffer, 6);
622 ledger_ble_data.connection.supervision_timeout = U2LE(buffer, 8);
623 LOG_BLE("LE CONNECTION UPDATE %04X - %04X- %04X- %04X\n",
624 ledger_ble_data.connection.connection_handle,
625 ledger_ble_data.connection.conn_interval,
626 ledger_ble_data.connection.conn_latency,
627 ledger_ble_data.connection.supervision_timeout);
628 break;
629
630 case HCI_LE_DATA_LENGTH_CHANGE_SUBEVT_CODE:
631 if (U2LE(buffer, 1) == ledger_ble_data.connection.connection_handle) {
632 ledger_ble_data.connection.max_tx_octets = U2LE(buffer, 3);
633 ledger_ble_data.connection.max_tx_time = U2LE(buffer, 5);
634 ledger_ble_data.connection.max_rx_octets = U2LE(buffer, 7);
635 ledger_ble_data.connection.max_rx_time = U2LE(buffer, 9);
636 LOG_BLE("LE DATA LENGTH CHANGE %04X - %04X- %04X- %04X\n",
637 ledger_ble_data.connection.max_tx_octets,
638 ledger_ble_data.connection.max_tx_time,
639 ledger_ble_data.connection.max_rx_octets,
640 ledger_ble_data.connection.max_rx_time);
641 }
642 break;
643
644 case HCI_LE_PHY_UPDATE_COMPLETE_SUBEVT_CODE:
645 if (U2LE(buffer, 2) == ledger_ble_data.connection.connection_handle) {
646 ledger_ble_data.connection.tx_phy = buffer[4];
647 ledger_ble_data.connection.rx_phy = buffer[5];
648 LOG_BLE("LE PHY UPDATE %02X - %02X\n",
649 ledger_ble_data.connection.tx_phy,
650 ledger_ble_data.connection.rx_phy);
651 }
652 break;
653
654 default:
655 LOG_BLE("HCI LE META 0x%02X\n", buffer[0]);
656 break;
657 }
658}
659
660static void hci_evt_vendor(const uint8_t *buffer, uint16_t length)
661{
662 if (length < 4) {
663 return;
664 }
665
666 uint16_t opcode = U2LE(buffer, 0);
667
668 if (U2LE(buffer, 2) != ledger_ble_data.connection.connection_handle) {
669 return;
670 }
671
672 switch (opcode) {
673#ifdef HAVE_INAPP_BLE_PAIRING
674 case ACI_GAP_PAIRING_COMPLETE_VSEVT_CODE:
675 LOG_BLE("PAIRING");
676 switch (buffer[4]) {
677 case SMP_PAIRING_STATUS_SUCCESS:
678 LOG_BLE(" SUCCESS\n");
679 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_SUCCESS);
680 break;
681
682 case SMP_PAIRING_STATUS_SMP_TIMEOUT:
683 LOG_BLE(" TIMEOUT\n");
684 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_TIMEOUT);
685 break;
686
687 case SMP_PAIRING_STATUS_PAIRING_FAILED:
688 LOG_BLE(" FAILED : %02X\n", buffer[5]);
689 if (buffer[5] == 0x08) { // UNSPECIFIED_REASON
690 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCELLED_FROM_REMOTE);
691 }
692 else {
693 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
694 }
695 break;
696
697 default:
698 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
699 break;
700 }
701 ledger_ble_data.pairing_in_progress = 0;
702 break;
703
704 case ACI_GAP_PASS_KEY_REQ_VSEVT_CODE:
705 LOG_BLE("PASSKEY REQ\n");
706 ask_user_pairing_passkey();
707 break;
708
709 case ACI_GAP_NUMERIC_COMPARISON_VALUE_VSEVT_CODE:
710 LOG_BLE("NUMERIC COMP : %d\n", U4LE(buffer, 4));
711 ask_user_pairing_numeric_comparison(U4LE(buffer, 4));
712 break;
713#endif // HAVE_INAPP_BLE_PAIRING
714
715 case ACI_GATT_ATTRIBUTE_MODIFIED_VSEVT_CODE:
716 attribute_modified(&buffer[4], length - 4);
717 break;
718
719 case ACI_ATT_EXCHANGE_MTU_RESP_VSEVT_CODE:
720 ledger_protocol_data.mtu = U2LE(buffer, 4) - 3 + 2;
721 ledger_protocol_data.mtu_negotiated = 1;
722 LOG_BLE("MTU : %d\n", U2LE(buffer, 4));
723 break;
724
725 case ACI_L2CAP_CONNECTION_UPDATE_RESP_VSEVT_CODE:
726 LOG_BLE("CONNECTION UPDATE RESP %d\n", buffer[4]);
727 break;
728
729 case ACI_GATT_WRITE_PERMIT_REQ_VSEVT_CODE:
730 write_permit_request(&buffer[4], length - 4);
731 break;
732
733 case ACI_GATT_INDICATION_VSEVT_CODE:
734 LOG_BLE("INDICATION EVT\n");
735 aci_gatt_confirm_indication(ledger_ble_data.connection.connection_handle);
736 break;
737
738 case ACI_GATT_PROC_COMPLETE_VSEVT_CODE:
739 LOG_BLE("PROCEDURE COMPLETE\n");
740 break;
741
742 case ACI_GATT_PROC_TIMEOUT_VSEVT_CODE:
743 LOG_BLE("PROCEDURE TIMEOUT\n");
744#ifdef HAVE_INAPP_BLE_PAIRING
745 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
746#endif // HAVE_INAPP_BLE_PAIRING
748 break;
749
750 default:
751 LOG_BLE("HCI VENDOR 0x%04X\n", opcode);
752 break;
753 }
754}
755
756#ifdef HAVE_INAPP_BLE_PAIRING
757static void end_pairing_ux(uint8_t pairing_ok)
758{
759 bolos_ux_params_t ux_params;
760
761 LOG_BLE("end_pairing_ux : %d (%d)\n", pairing_ok, ledger_ble_data.pairing_in_progress);
762 if (ledger_ble_data.pairing_in_progress) {
763 ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_CANCEL;
764 ux_params.u.pairing_status.pairing_ok = pairing_ok;
765 ux_params.len = sizeof(ux_params.u.pairing_status);
766 G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
767 os_ux(&ux_params);
768 }
769}
770
771static void ask_user_pairing_numeric_comparison(uint32_t code)
772{
773 bolos_ux_params_t ux_params;
774
775 ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_NUMCOMP;
776 ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST;
777 ux_params.len = sizeof(ux_params.u.pairing_request);
778 ledger_ble_data.pairing_in_progress = 1;
779 ux_params.u.pairing_request.pairing_info_len = 6;
780 SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", (unsigned int) code);
781#if defined(TARGET_STAX) || defined(TARGET_FLEX)
782 G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
783#else // !TARGET_STAX
784 G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_numeric_comparison;
785#endif // !TARGET_STAX
786 os_ux(&ux_params);
787}
788
789static void rsp_user_pairing_numeric_comparison(unsigned int status)
790{
791 if (status == BOLOS_UX_OK) {
792 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_YES);
793 aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
794 1);
795 }
796 else if (status == BOLOS_UX_IGNORE) {
797 ledger_ble_data.pairing_in_progress = 0;
798 aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
799 0);
800 }
801 else {
802 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CONFIRM_CODE_NO);
803 aci_gap_numeric_comparison_value_confirm_yesno(ledger_ble_data.connection.connection_handle,
804 0);
805 }
806}
807
808static void ask_user_pairing_passkey(void)
809{
810 bolos_ux_params_t ux_params;
811
812 ux_params.u.pairing_request.type = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST_PASSKEY;
813 ux_params.ux_id = BOLOS_UX_ASYNCHMODAL_PAIRING_REQUEST;
814 ux_params.len = sizeof(ux_params.u.pairing_request);
815 ledger_ble_data.pairing_in_progress = 1;
816 ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32);
817 ux_params.u.pairing_request.pairing_info_len = 6;
818 SPRINTF(ux_params.u.pairing_request.pairing_info, "%06d", ledger_ble_data.pairing_code);
819#if defined(TARGET_STAX) || defined(TARGET_FLEX)
820 G_io_asynch_ux_callback.asynchmodal_end_callback = NULL;
821#else // !TARGET_STAX
822 G_io_asynch_ux_callback.asynchmodal_end_callback = rsp_user_pairing_passkey;
823#endif // !TARGET_STAX
824 os_ux(&ux_params);
825}
826
827static void rsp_user_pairing_passkey(unsigned int status)
828{
829 if (status == BOLOS_UX_OK) {
830 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_ACCEPT_PASSKEY);
831 ledger_ble_data.pairing_code = cx_rng_u32_range_func(0, 1000000, cx_rng_u32);
832 aci_gap_pass_key_resp(ledger_ble_data.connection.connection_handle,
833 ledger_ble_data.pairing_code);
834 }
835 else if (status == BOLOS_UX_IGNORE) {
836 ledger_ble_data.pairing_in_progress = 0;
837 }
838 else {
839 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_CANCEL_PASSKEY);
840 }
841}
842#endif // HAVE_INAPP_BLE_PAIRING
843
844static void attribute_modified(const uint8_t *buffer, uint16_t length)
845{
846 if (length < 6) {
847 return;
848 }
849
850 uint16_t att_handle = U2LE(buffer, 0);
851 uint16_t offset = U2LE(buffer, 2);
852 uint16_t att_data_length = U2LE(buffer, 4);
853
854 if ((att_handle == ledger_ble_data.ledger_gatt_notification_characteristic_handle + 2)
855 && (att_data_length == 2) && (offset == 0)) {
856 // Peer device registering/unregistering for notifications
857 if (U2LE(buffer, 6) != 0) {
858 LOG_BLE("REGISTERED FOR NOTIFICATIONS\n");
859 ledger_ble_data.notifications_enabled = 1;
860 if (!ledger_protocol_data.mtu_negotiated) {
861 aci_gatt_exchange_config(ledger_ble_data.connection.connection_handle);
862 }
863 }
864 else {
865 LOG_BLE("NOT REGISTERED FOR NOTIFICATIONS\n");
866 ledger_ble_data.notifications_enabled = 0;
867 }
868 }
869 else if ((att_handle == ledger_ble_data.ledger_gatt_write_cmd_characteristic_handle + 1)
870 && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted)
871 && (att_data_length)) {
872 LOG_BLE("WRITE CMD %d\n", length - 4);
873 LEDGER_PROTOCOL_rx(&ledger_protocol_data, &buffer[4], length - 4);
874
875 if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
876 check_transfer_mode(G_io_app.transfer_mode);
877 if (ledger_ble_data.transfer_mode_enable) {
878 if (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS) {
879 LOG_BLE("Transfer failed 0x%04x\n", U2BE(ledger_ble_data.resp, 0));
880 G_io_app.transfer_mode = 0;
881 check_transfer_mode(G_io_app.transfer_mode);
882 copy_apdu_to_app(true);
883 }
884 else if (ledger_ble_data.resp_length) {
885 LEDGER_PROTOCOL_tx(
886 &ledger_protocol_data, ledger_ble_data.resp, ledger_ble_data.resp_length);
887 ledger_ble_data.resp_length = 0;
888 notify_chunk();
889 }
890 }
891 else {
892 copy_apdu_to_app(true);
893 }
894 }
895 else if (ledger_protocol_data.tx_chunk_length >= 2) {
896 G_io_app.ble_xfer_timeout = 2000;
897 notify_chunk();
898 G_io_app.apdu_state = APDU_BLE;
899 }
900 }
901 else {
902 LOG_BLE("ATT MODIFIED %04X %d bytes at offset %d\n", att_handle, att_data_length, offset);
903 }
904}
905
906static void write_permit_request(const uint8_t *buffer, uint16_t length)
907{
908 if (length < 3) {
909 return;
910 }
911
912 uint16_t att_handle = U2LE(buffer, 0);
913 uint8_t data_length = buffer[2];
914
915 ledger_ble_data.wait_write_resp_ack = 1;
916
917 if ((att_handle == ledger_ble_data.ledger_gatt_write_characteristic_handle + 1)
918 && (ledger_ble_data.notifications_enabled) && (ledger_ble_data.connection.encrypted)
919 && (data_length)) {
920 LEDGER_PROTOCOL_rx(&ledger_protocol_data, &buffer[1], length - 1);
921 aci_gatt_write_resp(ledger_ble_data.connection.connection_handle,
922 att_handle,
923 0,
924 HCI_SUCCESS_ERR_CODE,
925 data_length,
926 &buffer[3]);
927 if (ledger_protocol_data.rx_apdu_status == APDU_STATUS_COMPLETE) {
928 copy_apdu_to_app(true);
929 }
930 }
931 else {
932 LOG_BLE("ATT WRITE %04X %d bytes\n", att_handle, data_length);
933 ledger_protocol_data.tx_chunk_length = 0;
934 aci_gatt_write_resp(ledger_ble_data.connection.connection_handle,
935 att_handle,
936 0,
937 HCI_SUCCESS_ERR_CODE,
938 data_length,
939 &buffer[3]);
940 }
941}
942
943static void advertising_enable(uint8_t enable)
944{
945 if (enable) {
946 uint8_t buffer[31];
947
948 get_device_name();
949 buffer[0] = AD_TYPE_COMPLETE_LOCAL_NAME;
950 memcpy(&buffer[1], ledger_ble_data.device_name, ledger_ble_data.device_name_length);
951 aci_gap_set_discoverable(ADV_IND,
954 RANDOM_ADDR,
955 NO_WHITE_LIST_USE,
956 ledger_ble_data.device_name_length + 1,
957 buffer,
958 0,
959 NULL,
960 0,
961 0);
962 }
963 else {
964 aci_gap_set_non_discoverable();
965 }
966}
967
968static void start_advertising(void)
969{
970 if (G_io_app.name_changed) {
971 G_io_app.name_changed = 0;
972 ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING;
973 ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_IDLE;
974 }
975 else {
976 ledger_ble_data.state = BLE_STATE_CONFIGURE_ADVERTISING;
977 ledger_ble_data.adv_step = BLE_CONFIG_ADV_STEP_START - 1;
978 }
979 ledger_ble_data.hci_cmd_opcode = 0xFFFF;
980 ledger_ble_data.adv_enable = !os_setting_get(OS_SETTING_PLANEMODE, NULL, 0);
981 configure_advertising_mngr(0);
982}
983
984static void notify_chunk(void)
985{
986 if (ledger_protocol_data.tx_chunk_length >= 2) {
987 aci_gatt_update_char_value(ledger_ble_data.ledger_gatt_service_handle,
989 0,
990 ledger_protocol_data.tx_chunk_length - 2,
991 &ledger_protocol_data.tx_chunk[2]);
992 }
993}
994
995static void check_transfer_mode(uint8_t enable)
996{
997 if (ledger_ble_data.transfer_mode_enable != enable) {
998 LOG_BLE("LEDGER_BLE_set_transfer_mode %d\n", enable);
999 }
1000
1001 if ((ledger_ble_data.transfer_mode_enable == 0) && (enable != 0)) {
1002 ledger_ble_data.resp_length = 2;
1003 U2BE_ENCODE(ledger_ble_data.resp, 0, SWO_SUCCESS);
1004 }
1005
1006 ledger_ble_data.transfer_mode_enable = enable;
1007}
1008
1009/* Exported functions --------------------------------------------------------*/
1011{
1012 G_io_app.enabling_advertising = 0;
1013 G_io_app.disabling_advertising = 0;
1014
1015 if (ledger_ble_data.clear_pairing == 0xC1) {
1016 memset(&ledger_ble_data, 0, sizeof(ledger_ble_data));
1017 ledger_ble_data.clear_pairing = 0xC1;
1018 }
1019 else {
1020 memset(&ledger_ble_data, 0, sizeof(ledger_ble_data));
1021 }
1022
1024 ledger_ble_data.hci_cmd_opcode = 0xFFFF;
1025 ledger_ble_data.state = BLE_STATE_INITIALIZING;
1026 ledger_ble_data.init_step = BLE_INIT_STEP_IDLE;
1027
1028 memset(&ledger_protocol_data, 0, sizeof(ledger_protocol_data));
1029 ledger_protocol_data.rx_apdu_buffer = ledger_ble_data.apdu_buffer;
1030 ledger_protocol_data.rx_apdu_buffer_max_length = sizeof(ledger_ble_data.apdu_buffer);
1031#ifdef HAVE_LOCAL_APDU_BUFFER
1032 ledger_protocol_data.rx_dst_buffer = NULL;
1033#else
1034 ledger_protocol_data.rx_dst_buffer = G_io_apdu_buffer;
1035#endif
1036 LEDGER_PROTOCOL_init(&ledger_protocol_data);
1037
1038 init_mngr(0, NULL, 0);
1039}
1040
1041void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length)
1042{
1043 ledger_protocol_data.rx_dst_buffer = buffer;
1044 ledger_protocol_data.rx_apdu_buffer_max_length
1045 = MIN(buffer_length, sizeof(ledger_ble_data.apdu_buffer));
1046}
1047
1048void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length)
1049{
1050 if ((ledger_ble_data.transfer_mode_enable != 0) && (packet_length == 2)) {
1051 G_io_app.apdu_state = APDU_IDLE;
1052 ledger_ble_data.resp_length = 2;
1053 ledger_ble_data.resp[0] = packet[0];
1054 ledger_ble_data.resp[1] = packet[1];
1055 if (ledger_protocol_data.rx_apdu_length) {
1056 LEDGER_PROTOCOL_tx(&ledger_protocol_data, packet, packet_length);
1057 notify_chunk();
1058 }
1059 }
1060 else {
1061 if ((ledger_ble_data.resp_length != 0) && (U2BE(ledger_ble_data.resp, 0) != SWO_SUCCESS)) {
1062 LEDGER_PROTOCOL_tx(
1063 &ledger_protocol_data, ledger_ble_data.resp, ledger_ble_data.resp_length);
1064 }
1065 else {
1066 LEDGER_PROTOCOL_tx(&ledger_protocol_data, packet, packet_length);
1067 }
1068 ledger_ble_data.resp_length = 0;
1069
1070 if (ledger_ble_data.wait_write_resp_ack == 0) {
1071 notify_chunk();
1072 }
1073 }
1074}
1075
1076void LEDGER_BLE_receive(const uint8_t *spi_buffer)
1077{
1078 if (spi_buffer[3] == HCI_EVENT_PKT_TYPE) {
1079 switch (spi_buffer[4]) {
1080 case HCI_DISCONNECTION_COMPLETE_EVT_CODE:
1081 LOG_BLE("HCI DISCONNECTION COMPLETE code %02X\n", spi_buffer[9]);
1082 ledger_ble_data.connection.connection_handle = 0xFFFF;
1083 ledger_ble_data.advertising_enabled = 0;
1084 ledger_ble_data.connection.encrypted = 0;
1085 ledger_ble_data.transfer_mode_enable = 0;
1086 G_io_app.transfer_mode = 0;
1087#ifdef HAVE_INAPP_BLE_PAIRING
1088 end_pairing_ux(BOLOS_UX_ASYNCHMODAL_PAIRING_STATUS_FAILED);
1089#endif // HAVE_INAPP_BLE_PAIRING
1090 if (spi_buffer[9] != 0x28) { // Error code : Instant Passed
1091 start_advertising();
1092 }
1093 else {
1094 // Workaround to avoid unexpected start advertising event in loop (seems to be a
1095 // bug in the stack)
1097 }
1098 break;
1099
1100 case HCI_ENCRYPTION_CHANGE_EVT_CODE:
1101 if (U2LE(spi_buffer, 7) == ledger_ble_data.connection.connection_handle) {
1102 if (spi_buffer[9]) {
1103 LOG_BLE("Link encrypted\n");
1104 ledger_ble_data.connection.encrypted = 1;
1105 }
1106 else {
1107 LOG_BLE("Link not encrypted\n");
1108 ledger_ble_data.connection.encrypted = 0;
1109 }
1110 }
1111 else {
1112 LOG_BLE("HCI ENCRYPTION CHANGE EVT %d on connection handle \n",
1113 spi_buffer[9],
1114 U2LE(spi_buffer, 7));
1115 }
1116 break;
1117
1118 case HCI_COMMAND_COMPLETE_EVT_CODE:
1119 hci_evt_cmd_complete(&spi_buffer[6], spi_buffer[5]);
1120 break;
1121
1122 case HCI_COMMAND_STATUS_EVT_CODE:
1123 LOG_BLE("HCI COMMAND_STATUS\n");
1124 break;
1125
1126 case HCI_ENCRYPTION_KEY_REFRESH_COMPLETE_EVT_CODE:
1127 LOG_BLE("HCI KEY_REFRESH_COMPLETE\n");
1128 break;
1129
1130 case HCI_LE_META_EVT_CODE:
1131 hci_evt_le_meta_evt(&spi_buffer[6], spi_buffer[5]);
1132 break;
1133
1134 case HCI_VENDOR_SPECIFIC_DEBUG_EVT_CODE:
1135 hci_evt_vendor(&spi_buffer[6], spi_buffer[5]);
1136 break;
1137
1138 default:
1139 break;
1140 }
1141 }
1142}
1143
1145{
1146 if ((G_io_app.name_changed) && (G_io_app.ble_ready) && (!enable)
1147 && (ledger_ble_data.connection.connection_handle != 0xFFFF)) {
1148 G_io_app.name_changed = 0;
1149 }
1150 else if (G_io_app.ble_ready) {
1151 if (enable) {
1152 G_io_app.enabling_advertising = 1;
1153 G_io_app.disabling_advertising = 0;
1154 }
1155 else {
1156 G_io_app.enabling_advertising = 0;
1157 G_io_app.disabling_advertising = 1;
1158 }
1159 advertising_enable(enable);
1160 }
1161}
1162
1164{
1165 if (G_io_app.ble_ready) {
1166 if (ledger_ble_data.connection.connection_handle != 0xFFFF) {
1167 // Connected => force disconnection before clearing
1168 ledger_ble_data.clear_pairing = 0xC1;
1170 }
1171 else {
1172 aci_gap_clear_security_db();
1173 }
1174 }
1175}
1176
1178{
1179 if (ledger_ble_data.pairing_in_progress == 1) {
1180 rsp_user_pairing_numeric_comparison(status);
1181 }
1182 else if (ledger_ble_data.pairing_in_progress == 2) {
1183 rsp_user_pairing_passkey(status);
1184 }
1185}
1186
1187int hci_send_req(struct hci_request *p_cmd, uint8_t async)
1188{
1189 UNUSED(async);
1190
1191 uint16_t opcode = ((p_cmd->ocf) & 0x03ff) | ((p_cmd->ogf) << 10);
1192
1193 uint8_t tag_buffer[5];
1194 tag_buffer[0] = SEPROXYHAL_TAG_BLE_SEND;
1195 tag_buffer[1] = (p_cmd->clen + 2) >> 8;
1196 tag_buffer[2] = (p_cmd->clen + 2);
1197 tag_buffer[3] = opcode >> 8;
1198 tag_buffer[4] = opcode;
1199 io_seproxyhal_spi_send(tag_buffer, 5);
1200 io_seproxyhal_spi_send(p_cmd->cparam, p_cmd->clen);
1201 return 0;
1202}
1203
1204void BLE_power(unsigned char powered, const char *discovered_name)
1205{
1206 UNUSED(discovered_name);
1207
1208 LOG_BLE("BLE_power %d\n", powered);
1209 if (powered) {
1211 }
1212}
Random Number Generation.
#define BLE_ADVERTISING_INTERVAL_MIN
Definition ledger_ble.c:148
ble_config_adv_step_t
Definition ledger_ble.c:63
@ BLE_CONFIG_ADV_STEP_START
Definition ledger_ble.c:68
@ BLE_CONFIG_ADV_STEP_SET_ADV_DATAS
Definition ledger_ble.c:65
@ BLE_CONFIG_ADV_STEP_SET_GAP_DEVICE_NAME
Definition ledger_ble.c:67
@ BLE_CONFIG_ADV_STEP_SET_SCAN_RSP_DATAS
Definition ledger_ble.c:66
@ BLE_CONFIG_ADV_STEP_END
Definition ledger_ble.c:69
@ BLE_CONFIG_ADV_STEP_IDLE
Definition ledger_ble.c:64
#define LOG_BLE(...)
Definition ledger_ble.c:154
#define BLE_ADVERTISING_INTERVAL_MAX
Definition ledger_ble.c:149
void LEDGER_BLE_receive(const uint8_t *spi_buffer)
void BLE_power(unsigned char powered, const char *discovered_name)
void LEDGER_BLE_reset_pairings(void)
int hci_send_req(struct hci_request *p_cmd, uint8_t async)
ble_state_t
Definition ledger_ble.c:37
@ BLE_STATE_DISCONNECTING
Definition ledger_ble.c:43
@ BLE_STATE_CONFIGURE_ADVERTISING
Definition ledger_ble.c:40
@ BLE_STATE_INITIALIZING
Definition ledger_ble.c:38
@ BLE_STATE_CONNECTED
Definition ledger_ble.c:42
@ BLE_STATE_INITIALIZED
Definition ledger_ble.c:39
@ BLE_STATE_CONNECTING
Definition ledger_ble.c:41
#define MAX_MTU_SIZE
Definition ledger_ble.c:143
void LEDGER_BLE_enable_advertising(uint8_t enable)
ble_init_step_t
Definition ledger_ble.c:46
@ BLE_INIT_STEP_SET_IO_CAPABILITIES
Definition ledger_ble.c:52
@ BLE_INIT_STEP_ADD_NOTIFICATION_CHARACTERISTIC
Definition ledger_ble.c:55
@ BLE_INIT_STEP_SET_AUTH_REQUIREMENTS
Definition ledger_ble.c:53
@ BLE_INIT_STEP_CONFIGURE_ADVERTISING
Definition ledger_ble.c:59
@ BLE_INIT_STEP_ADD_WRITE_CHARACTERISTIC
Definition ledger_ble.c:56
@ BLE_INIT_STEP_SET_TX_POWER_LEVEL
Definition ledger_ble.c:58
@ BLE_INIT_STEP_END
Definition ledger_ble.c:60
@ BLE_INIT_STEP_IDLE
Definition ledger_ble.c:47
@ BLE_INIT_STEP_STATIC_ADDRESS
Definition ledger_ble.c:49
@ BLE_INIT_STEP_GAP_INIT
Definition ledger_ble.c:51
@ BLE_INIT_STEP_ADD_WRITE_COMMAND_CHARACTERISTIC
Definition ledger_ble.c:57
@ BLE_INIT_STEP_ADD_SERVICE
Definition ledger_ble.c:54
@ BLE_INIT_STEP_GATT_INIT
Definition ledger_ble.c:50
@ BLE_INIT_STEP_RESET
Definition ledger_ble.c:48
void LEDGER_BLE_set_recv_buffer(uint8_t *buffer, uint16_t buffer_length)
#define BLE_SLAVE_CONN_INTERVAL_MIN
Definition ledger_ble.c:145
void LEDGER_BLE_send(const uint8_t *packet, uint16_t packet_length)
void LEDGER_BLE_accept_pairing(uint8_t status)
void LEDGER_BLE_init(void)
#define BLE_SLAVE_CONN_INTERVAL_MAX
Definition ledger_ble.c:146
#define LEDGER_BLE_get_mac_address(address)
Definition ledger_ble.h:45
#define MIN(x, y)
Definition nbgl_types.h:98
uint8_t peer_address_random
Definition ledger_ble.c:76
uint16_t max_rx_time
Definition ledger_ble.c:87
uint16_t connection_handle
Definition ledger_ble.c:74
uint8_t encrypted
Definition ledger_ble.c:88
uint8_t peer_address[6]
Definition ledger_ble.c:77
uint16_t supervision_timeout
Definition ledger_ble.c:80
uint16_t conn_interval
Definition ledger_ble.c:78
uint16_t max_tx_octets
Definition ledger_ble.c:84
uint16_t max_tx_time
Definition ledger_ble.c:85
uint16_t max_rx_octets
Definition ledger_ble.c:86
uint8_t master_clock_accuracy
Definition ledger_ble.c:81
uint16_t conn_latency
Definition ledger_ble.c:79
uint8_t role_slave
Definition ledger_ble.c:75
uint8_t random_address[CONFIG_DATA_RANDOM_ADDRESS_LEN]
Definition ledger_ble.c:96
uint8_t pairing_in_progress
Definition ledger_ble.c:115
uint8_t apdu_buffer[IO_APDU_BUFFER_SIZE]
Definition ledger_ble.c:133
ble_state_t state
Definition ledger_ble.c:93
uint8_t wait_write_resp_ack
Definition ledger_ble.c:131
uint16_t gap_device_name_characteristic_handle
Definition ledger_ble.c:110
uint8_t transfer_mode_enable
Definition ledger_ble.c:136
ble_connection_t connection
Definition ledger_ble.c:113
uint16_t ledger_gatt_notification_characteristic_handle
Definition ledger_ble.c:122
uint8_t advertising_enabled
Definition ledger_ble.c:112
uint16_t pairing_code
Definition ledger_ble.c:114
uint16_t ledger_gatt_write_characteristic_handle
Definition ledger_ble.c:123
ble_config_adv_step_t adv_step
Definition ledger_ble.c:102
uint16_t gap_appearance_characteristic_handle
Definition ledger_ble.c:111
uint16_t ledger_gatt_service_handle
Definition ledger_ble.c:121
uint16_t apdu_buffer_length
Definition ledger_ble.c:132
uint16_t hci_cmd_opcode
Definition ledger_ble.c:106
uint8_t resp[2]
Definition ledger_ble.c:138
uint8_t connection_updated
Definition ledger_ble.c:118
uint16_t ledger_gatt_write_cmd_characteristic_handle
Definition ledger_ble.c:124
char device_name[20+1]
Definition ledger_ble.c:94
uint8_t clear_pairing
Definition ledger_ble.c:128
uint8_t notifications_enabled
Definition ledger_ble.c:125
ble_init_step_t init_step
Definition ledger_ble.c:99
uint16_t gap_service_handle
Definition ledger_ble.c:109
unsigned short uint16_t
Definition usbd_conf.h:54
unsigned char uint8_t
Definition usbd_conf.h:53