diff --git a/docs/library/ubluetooth.rst b/docs/library/ubluetooth.rst index 3d435a7beda5..2aa0b91506ea 100644 --- a/docs/library/ubluetooth.rst +++ b/docs/library/ubluetooth.rst @@ -365,7 +365,12 @@ A central device can connect to peripherals that it has discovered using the obs See :meth:`gap_scan ` for details about address types. - On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. + To cancel an outstanding connection attempt early, call + ``gap_connect(None)``. + + On success, the ``_IRQ_PERIPHERAL_CONNECT`` event will be raised. If + cancelling a connection attempt, the ``_IRQ_PERIPHERAL_DISCONNECT`` event + will be raised. Peripheral Role diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index 5f047e32541f..bae6a48f8b7b 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -1234,6 +1234,11 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, return btstack_error_to_errno(gap_connect(btstack_addr, addr_type)); } +int mp_bluetooth_gap_peripheral_connect_cancel(void) { + DEBUG_printf("mp_bluetooth_gap_peripheral_connect_cancel\n"); + return btstack_error_to_errno(gap_connect_cancel()); +} + #endif // MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index e379a8c6a304..a01fa5ff3aa0 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -630,6 +630,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_2(bluetooth_ble_gatts_register_services_obj, blue #if MICROPY_PY_BLUETOOTH_ENABLE_CENTRAL_MODE STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { + if (n_args == 2) { + if (args[1] == mp_const_none) { + int err = mp_bluetooth_gap_peripheral_connect_cancel(); + return bluetooth_handle_errno(err); + } + mp_raise_TypeError(MP_ERROR_TEXT("None or addr_type and addr required")); + } uint8_t addr_type = mp_obj_get_int(args[1]); mp_buffer_info_t bufinfo = {0}; mp_get_buffer_raise(args[2], &bufinfo, MP_BUFFER_READ); @@ -644,7 +651,7 @@ STATIC mp_obj_t bluetooth_ble_gap_connect(size_t n_args, const mp_obj_t *args) { int err = mp_bluetooth_gap_peripheral_connect(addr_type, bufinfo.buf, scan_duration_ms); return bluetooth_handle_errno(err); } -STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 3, 4, bluetooth_ble_gap_connect); +STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_gap_connect_obj, 2, 4, bluetooth_ble_gap_connect); STATIC mp_obj_t bluetooth_ble_gap_scan(size_t n_args, const mp_obj_t *args) { // Default is indefinite scan, with the NimBLE "background scan" interval and window. diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index d126ad6c1134..5dc5db3f0db0 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -374,6 +374,10 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, #endif #if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT + +// Cancel in-progress connection to a peripheral. +int mp_bluetooth_gap_peripheral_connect_cancel(void); + // Find all primary services on the connected peripheral. int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_obj_bluetooth_uuid_t *uuid); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index e3a2f872e5ec..51310062edeb 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -1220,6 +1220,15 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, return ble_hs_err_to_errno(err); } +int mp_bluetooth_gap_peripheral_connect_cancel(void) { + DEBUG_printf("mp_bluetooth_gap_peripheral_connect_cancel\n"); + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } + int err = ble_gap_conn_cancel(); + return ble_hs_err_to_errno(err); +} + STATIC int ble_gattc_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) { DEBUG_printf("ble_gattc_service_cb: conn_handle=%d status=%d start_handle=%d\n", conn_handle, error->status, service ? service->start_handle : -1); if (!mp_bluetooth_is_active()) {