diff --git a/bt_inspector/bt_inspector.c b/bt_inspector/bt_inspector.c index d25bea3..b39c5ef 100644 --- a/bt_inspector/bt_inspector.c +++ b/bt_inspector/bt_inspector.c @@ -66,6 +66,7 @@ typedef struct { BcDevice devs[BC_MAX_DEVICES]; size_t count, sel, top; bool scanning; + uint8_t scan_err; } ScanModel; typedef struct { @@ -328,7 +329,10 @@ static void scan_draw(Canvas* c, void* m_) { canvas_set_font(c, FontPrimary); canvas_draw_str(c, 2, 9, "BT Inspector"); canvas_set_font(c, FontSecondary); - furi_string_printf(s, m->scanning ? "%u found" : "%u (stopped)", (unsigned)m->count); + if(m->scanning) + furi_string_printf(s, "%u found", (unsigned)m->count); + else + furi_string_printf(s, "err 0x%02X", m->scan_err); canvas_draw_str_aligned(c, 126, 9, AlignRight, AlignBottom, furi_string_get_cstr(s)); canvas_draw_line(c, 0, 11, 127, 11); if(!m->count) canvas_draw_str_aligned(c, 64, 40, AlignCenter, AlignCenter, "Scanning..."); @@ -389,7 +393,8 @@ static void scan_enter(void* ctx) { app->cur_view = ViewScan; bool ok = bc_scan_start(app->bc); if(!ok) app_log(app, "SCAN START FAILED 0x%02X", bc_last_error(app->bc)); - with_view_model(app->scan_view, ScanModel * m, { m->scanning = ok; }, true); + uint8_t err = ok ? 0 : bc_last_error(app->bc); + with_view_model(app->scan_view, ScanModel * m, { m->scanning = ok; m->scan_err = err; }, true); } // ---- page view (scrollable text with optional buttons) ----------------------- diff --git a/libble/ble_central.c b/libble/ble_central.c index 7088fd2..3d9cd10 100644 --- a/libble/ble_central.c +++ b/libble/ble_central.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -314,9 +315,11 @@ void bc_free(BleCentral* bc) { bool bc_scan_start(BleCentral* bc) { if(bc->scanning) return true; - // active scan, 50 ms interval / 30 ms window; no duplicate filtering so RSSI stays live - tBleStatus st = hci_le_set_scan_parameters(0x01, 0x50, 0x30, OWN_ADDR_TYPE, 0x00); - if(st == BLE_STATUS_SUCCESS) st = hci_le_set_scan_enable(0x01, 0x00); + // Active scan, 50 ms interval / 30 ms window, public address, no duplicate + // filtering (so RSSI stays live), accept-all filter policy. The firmware's + // GAP is initialised, so we must use the GAP observation procedure; raw + // hci_le_set_scan_* returns "command disallowed" in that state. + tBleStatus st = aci_gap_start_observation_proc(0x0050, 0x0030, 0x01, OWN_ADDR_TYPE, 0x00, 0x00); if(st != BLE_STATUS_SUCCESS) { FURI_LOG_E(TAG, "scan start failed: 0x%02X", st); bc->last_error = st; @@ -328,7 +331,7 @@ bool bc_scan_start(BleCentral* bc) { void bc_scan_stop(BleCentral* bc) { if(!bc->scanning) return; - hci_le_set_scan_enable(0x00, 0x00); + aci_gap_terminate_gap_proc(GAP_OBSERVATION_PROC); bc->scanning = false; } @@ -407,9 +410,11 @@ bool bc_connect(BleCentral* bc, const BcDevice* dev, uint32_t timeout_ms) { furi_event_flag_clear(bc->flags, FlagConnected | FlagConnFailed | FlagDisconnected | FlagDone); bc->connecting = true; bc->mtu = 23; + // Observation must fully stop before starting a connection procedure. + furi_delay_ms(100); // scan 60/30 ms, conn interval 30-50 ms, latency 0, supervision 5 s - tBleStatus st = hci_le_create_connection( - 0x60, 0x30, 0x00, dev->addr_type, dev->addr, OWN_ADDR_TYPE, 0x18, 0x28, 0, 0x01F4, 0, 0); + tBleStatus st = aci_gap_create_connection( + 0x60, 0x30, dev->addr_type, dev->addr, OWN_ADDR_TYPE, 0x18, 0x28, 0, 0x01F4, 0, 0); if(st != BLE_STATUS_SUCCESS) { FURI_LOG_E(TAG, "create_connection failed: 0x%02X", st); bc->connecting = false; @@ -418,7 +423,7 @@ bool bc_connect(BleCentral* bc, const BcDevice* dev, uint32_t timeout_ms) { } uint32_t f = furi_event_flag_wait(bc->flags, FlagConnected | FlagConnFailed, FuriFlagWaitAny, timeout_ms); if(f & FuriFlagError) { - hci_le_create_connection_cancel(); + aci_gap_terminate_gap_proc(GAP_DIRECT_CONNECTION_ESTABLISHMENT_PROC); f = furi_event_flag_wait(bc->flags, FlagConnected | FlagConnFailed, FuriFlagWaitAny, 2000); if(!(f & FlagConnected)) { bc->connecting = false;