diff --git a/epicardium/ble/ble_api.h b/epicardium/ble/ble_api.h index 7e2fbbf865e7bf07deea39d4403e4acb812a7f8e..a5d0b9ccf2c314d2eaae86d3e3ad26e133963ddd 100644 --- a/epicardium/ble/ble_api.h +++ b/epicardium/ble/ble_api.h @@ -57,3 +57,4 @@ void ble_adv_stop(void); void ble_adv_start(uint8_t mode); void ble_adv_discoverable(bool discoverable); void ble_adv_proc_msg(bleMsg_t *pMsg); +void ble_close_connections_to_peripherals(void); diff --git a/epicardium/ble/ble_main.c b/epicardium/ble/ble_main.c index 53a5a35cd13c6ec37a20bd481cc1024dd3a613d5..550e804e782e6c718c59659a2f1136cdc1f7edf9 100644 --- a/epicardium/ble/ble_main.c +++ b/epicardium/ble/ble_main.c @@ -258,6 +258,20 @@ static const char * const l2c_coc_events[] = { "L2C_COC_DATA_IND", "L2C_COC_DATA_CNF" }; + +static const char * const att_internal_error_code[] = { + "ATT_ERR_MEMORY", + "ATT_ERR_TIMEOUT", + "ATT_ERR_OVERFLOW", + "ATT_ERR_INVALID_RSP", + "ATT_ERR_CANCELLED", + "ATT_ERR_UNDEFINED", + "ATT_ERR_REQ_NOT_FOUND", + "ATT_ERR_MTU_EXCEEDED", + "ATT_CONTINUING", + "ATT_RSP_PENDING" +}; + /*************************************************************************************************/ /*! * \brief Application DM callback. @@ -392,6 +406,16 @@ static void bleSetup(bleMsg_t *pMsg) epic_ble_set_mode(false, false); } +void ble_close_connections_to_peripherals(void) +{ + dmConnId_t connId = AppConnIsOpen(); + if (connId != DM_CONN_ID_NONE) { + if(DmConnRole(connId) == DM_ROLE_MASTER) { + AppConnClose(connId); + } + } +} + void epic_ble_set_mode(bool bondable, bool scanner) { if(!active) { @@ -704,6 +728,7 @@ static void BleHandlerInit(void) ble_adv_init(); /* Initialize application framework */ + AppMasterInit(); AppSlaveInit(); AppDiscInit(); @@ -737,16 +762,27 @@ static void BleHandler(wsfEventMask_t event, wsfMsgHdr_t *pMsg) /* process security-related messages */ AppSlaveSecProcDmMsg((dmEvt_t *) pMsg); - /* process discovery-related messages */ - AppDiscProcDmMsg((dmEvt_t *) pMsg); + if(DmConnRole(pMsg->param) == DM_ROLE_SLAVE) { + /* process discovery-related messages only if we are peripheral */ + AppDiscProcDmMsg((dmEvt_t *) pMsg); + } ble_epic_dm_api_event((dmEvt_t *)pMsg); + + if(DmConnRole(pMsg->param) == DM_ROLE_MASTER && pMsg->event == DM_CONN_OPEN_IND) { + /* fake the discovery so the epic api can forward the connection open */ + ble_epic_disc_cfg_complete(); + } } else if (pMsg->event >= ATT_CBACK_START && pMsg->event <= ATT_CBACK_END) { /* Don't spam the console with successful notfication/indications */ if (!(pMsg->event == ATTS_HANDLE_VALUE_CNF && pMsg->status == ATT_SUCCESS)) { - LOG_INFO("ble", "Ble got evt %d (%s): %d %d", pMsg->event, att_events[pMsg->event - ATT_CBACK_START], ((bleMsg_t *)pMsg)->att.handle, pMsg->status); + if(pMsg->status >= ATT_ERR_MEMORY && pMsg->status <= ATT_RSP_PENDING) { + LOG_INFO("ble", "Ble got evt %d (%s): %d %d (%s)", pMsg->event, att_events[pMsg->event - ATT_CBACK_START], ((bleMsg_t *)pMsg)->att.handle, pMsg->status, att_internal_error_code[pMsg->status-ATT_ERR_MEMORY]); + } else { + LOG_INFO("ble", "Ble got evt %d (%s): %d %d", pMsg->event, att_events[pMsg->event - ATT_CBACK_START], ((bleMsg_t *)pMsg)->att.handle, pMsg->status); + } } /* process discovery-related ATT messages */ AppDiscProcAttMsg((attEvt_t *) pMsg); diff --git a/epicardium/ble/epic_att_api.c b/epicardium/ble/epic_att_api.c index 54ee97361edecb22b294ed01bfbcff0d6a3ebf72..19928067f9d7661e871e2ec06093cc8fcce6730f 100644 --- a/epicardium/ble/epic_att_api.c +++ b/epicardium/ble/epic_att_api.c @@ -31,6 +31,8 @@ void ble_epic_att_api_event(attEvt_t *att_event) size_t value_len = 0; if (att_event->hdr.event == ATTC_READ_BY_GROUP_TYPE_RSP || att_event->hdr.event == ATTC_READ_BY_TYPE_RSP || + att_event->hdr.event == ATTC_READ_RSP || + att_event->hdr.event == ATTC_READ_LONG_RSP || att_event->hdr.event == ATTC_FIND_INFO_RSP || att_event->hdr.event == ATTC_HANDLE_VALUE_NTF || att_event->hdr.event == ATTC_HANDLE_VALUE_IND) { diff --git a/epicardium/ble/epic_ble_api.c b/epicardium/ble/epic_ble_api.c index 92bb398b5cd0c8d41d1f27873784ab8e7bc37e65..11dbeb573f8834e6a60c78e4dbf1e63187f61fd5 100644 --- a/epicardium/ble/epic_ble_api.c +++ b/epicardium/ble/epic_ble_api.c @@ -53,6 +53,7 @@ void ble_epic_ble_api_trigger_event(enum epic_ble_event_type type, void *data) struct epic_ble_event e = { .type = type, .data = data }; + bool bypass = false; if (type == BLE_EVENT_DM_EVENT) { dmEvt_t *dm_event = data; if (dm_event->hdr.event == DM_CONN_OPEN_IND) { @@ -62,10 +63,15 @@ void ble_epic_ble_api_trigger_event(enum epic_ble_event_type type, void *data) if (dm_event->hdr.event == DM_CONN_CLOSE_IND) { connection_open = false; } + + if (dm_event->hdr.event == DM_SCAN_STOP_IND) { + bypass = true; + } } if (!connection_open && - (type == BLE_EVENT_ATT_EVENT || type == BLE_EVENT_DM_EVENT)) { + (type == BLE_EVENT_ATT_EVENT || type == BLE_EVENT_DM_EVENT) && + !bypass) { // Don't forward DM and ATT events until epicardium is done setting up // the connection epic_ble_free_event(&e); @@ -126,6 +132,10 @@ static void send_dm_event(dmEvt_t *dm_event) void ble_epic_dm_api_event(dmEvt_t *dm_event) { + if (dm_event->hdr.event == DM_CONN_CLOSE_IND) { + xTimerStop(dm_timer, 0); + } + if (dm_event->hdr.event == DM_CONN_OPEN_IND) { /* Cache the connection open indication until * epicardium is done dicovering services. */ @@ -246,3 +256,8 @@ int epic_ble_advertise_stop(void) ble_adv_stop(); return 0; } + +void epic_ble_connect(uint8_t addr_type, const uint8_t *addr) +{ + AppConnOpen(addr_type, (uint8_t *)addr, APP_DB_HDL_NONE); +} diff --git a/epicardium/ble/stack.c b/epicardium/ble/stack.c index 4bf4696fd8639c1bf9b3101f3b58101e4220962b..f89cd1d45e665e4d35b3d1e3a2323ca2b8bac2af 100644 --- a/epicardium/ble/stack.c +++ b/epicardium/ble/stack.c @@ -168,6 +168,7 @@ void StackInit(void) DmAdvInit(); DmScanInit(); DmConnInit(); + DmConnMasterInit(); DmConnSlaveInit(); DmSecInit(); DmSecLescInit(); @@ -178,6 +179,7 @@ void StackInit(void) handlerId = WsfOsSetNextHandler(L2cSlaveHandler); L2cSlaveHandlerInit(handlerId); L2cInit(); + L2cMasterInit(); L2cSlaveInit(); handlerId = WsfOsSetNextHandler(AttHandler); @@ -189,7 +191,9 @@ void StackInit(void) handlerId = WsfOsSetNextHandler(SmpHandler); SmpHandlerInit(handlerId); + SmpiInit(); SmprInit(); + SmpiScInit(); SmprScInit(); /*TODO card10: Probably want to adjust this */ diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 6957b43bdcab90ddfde116bf0155bb998e502a9f..9ffd81d131cbeed585f740259942a7511803f2ee 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -193,6 +193,8 @@ typedef _Bool bool; #define API_BLE_INIT 0x190 #define API_BLE_DEINIT 0x191 +#define API_BLE_CONNECT 0x1A0 + /* clang-format on */ typedef uint32_t api_int_id_t; @@ -2742,5 +2744,6 @@ API(API_BLE_ATTC_WRITE_NO_RSP, int epic_ble_attc_write_no_rsp(uint8_t connId, ui /** Private API call for Pycardium BLE support. */ API(API_BLE_ATTC_WRITE, int epic_ble_attc_write(uint8_t connId, uint16_t value_handle, const uint8_t *value, uint16_t value_len)); +API(API_BLE_CONNECT, void epic_ble_connect(uint8_t addr_type, const uint8_t *addr)); #endif /* _EPICARDIUM_H */ diff --git a/epicardium/modules/hardware.c b/epicardium/modules/hardware.c index 75c4672ef7d05a0588e7a4d479ce3758f7c9ca72..0f36b1e3fea3e6e4d23c96542162d2d93b50701f 100644 --- a/epicardium/modules/hardware.c +++ b/epicardium/modules/hardware.c @@ -296,6 +296,8 @@ int hardware_reset(void) /* Reset advertisement data */ ble_adv_setup(); + ble_close_connections_to_peripherals(); + /* Start advertising again if needed */ epic_ble_set_mode(false, false); diff --git a/lib/sdk/Libraries/BTLE/meson.build b/lib/sdk/Libraries/BTLE/meson.build index 2bf03dbb6af2f7d34b6e6c376f9c632a28006d09..072c947c2c80574471418d8fb7d5f17d10ea772e 100644 --- a/lib/sdk/Libraries/BTLE/meson.build +++ b/lib/sdk/Libraries/BTLE/meson.build @@ -427,6 +427,7 @@ ble_compileargs = [ '-DINIT_PERIPHERAL', '-DINIT_ENCRYPTED', '-DINIT_OBSERVER', + '-DINIT_CENTRAL', '-DINIT_PHY', ] diff --git a/pycardium/modules/modbluetooth_card10.c b/pycardium/modules/modbluetooth_card10.c index 932930d8b959c78a0f4bc04ae42f2688de6a71d3..98df2982c633d50b55b436c39c9911f0f0d26e00 100644 --- a/pycardium/modules/modbluetooth_card10.c +++ b/pycardium/modules/modbluetooth_card10.c @@ -43,6 +43,7 @@ typedef struct { static bool active = false; static mp_obj_bluetooth_uuid_t uuid_filter; +static uint8_t roles[8]; const char *const not_implemented_message = "Not (yet) implemented on card10. See https://git.card10.badge.events.ccc.de/card10/firmware/-/issues/8"; @@ -353,11 +354,21 @@ static void handle_att_event(struct epic_att_event *att_event) static void handle_dm_event(struct epic_dm_event *dm_event) { struct epic_wsf_header *hdr = (struct epic_wsf_header *)dm_event; + if (hdr->event == DM_CONN_OPEN_IND) { struct epic_hciLeConnCmpl_event *e = (struct epic_hciLeConnCmpl_event *)dm_event; + roles[e->hdr.param] = e->role; + + uint8_t event; + if(e->role == 1) { + event = MP_BLUETOOTH_IRQ_CENTRAL_CONNECT; + } else { + event = MP_BLUETOOTH_IRQ_PERIPHERAL_CONNECT; + } + mp_bluetooth_gap_on_connected_disconnected( - MP_BLUETOOTH_IRQ_CENTRAL_CONNECT, + event, e->hdr.param, e->addrType, e->peerAddr @@ -366,12 +377,22 @@ static void handle_dm_event(struct epic_dm_event *dm_event) struct epic_hciDisconnectCmpl_event *e = (struct epic_hciDisconnectCmpl_event *)dm_event; uint8_t addr[6] = {}; + + uint8_t event; + if(roles[e->hdr.param] == 1) { + event = MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT; + } else { + event = MP_BLUETOOTH_IRQ_PERIPHERAL_DISCONNECT; + } + mp_bluetooth_gap_on_connected_disconnected( - MP_BLUETOOTH_IRQ_CENTRAL_DISCONNECT, + event, e->hdr.param, 0xFF, addr ); + } else if (hdr->event == DM_SCAN_STOP_IND) { + mp_bluetooth_gap_on_scan_complete(); } } @@ -397,6 +418,17 @@ static void handle_att_write(struct epic_att_write *att_write) mp_bluetooth_gatts_on_write(att_write->hdr.param, att_write->handle); } +static void handle_scan_report(void) +{ + struct epic_scan_report scan_report; + + while(epic_ble_get_scan_report(&scan_report) == 0) { + uint8_t adv_type = scan_report.eventType; + mp_bluetooth_gap_on_scan_result(scan_report.addrType, scan_report.addr, + adv_type, scan_report.rssi, scan_report.data, scan_report.len); + } +} + static mp_obj_t mp_ble_poll_events(mp_obj_t interrupt_id) { struct epic_ble_event ble_event; @@ -414,6 +446,9 @@ static mp_obj_t mp_ble_poll_events(mp_obj_t interrupt_id) if (ble_event.type == BLE_EVENT_ATT_WRITE) { handle_att_write(ble_event.att_write); } + if (ble_event.type == BLE_EVENT_SCAN_REPORT) { + handle_scan_report(); + } epic_ble_free_event(&ble_event); } } while (ret >= 0); @@ -802,14 +837,15 @@ int mp_bluetooth_gap_scan_start( int32_t window_us, bool active_scan ) { - raise(); + if(active_scan) raise(); + epic_ble_set_mode(false, true); return 0; } // Stop discovery (if currently active). int mp_bluetooth_gap_scan_stop(void) { - raise(); + epic_ble_set_mode(false, false); return 0; } @@ -817,7 +853,7 @@ int mp_bluetooth_gap_scan_stop(void) int mp_bluetooth_gap_peripheral_connect( uint8_t addr_type, const uint8_t *addr, int32_t duration_ms ) { - raise(); + epic_ble_connect(addr_type, addr); return 0; } diff --git a/tools/pycard10.py b/tools/pycard10.py index 5f0a870c2db5e5bf92f6b96a3e5531da63f9f95a..306529aca14fd698632c99ae1747e19d4dbff6a5 100755 --- a/tools/pycard10.py +++ b/tools/pycard10.py @@ -117,10 +117,20 @@ class PyCard10(Pyboard): self.serial.write(b"\x04") - # check if we could exec command - data = self.serial.read(2) - if data != b"OK": - raise PyboardError("could not exec command (response: %r)" % data) + while True: + # check if we could exec command + data = self.serial.read(2) + + # Catch log lines from epicardium + if data == b'\x1b[': + logline = self.serial.readline() + stdout_write_bytes(data + logline) + continue + + if data != b"OK": + raise PyboardError("could not exec command (response: %r)" % data) + else: + break def enter_raw_repl(self): """