diff options
-rw-r--r-- | extmod/btstack/modbluetooth_btstack.c | 2 | ||||
-rw-r--r-- | extmod/modbluetooth.c | 2 | ||||
-rw-r--r-- | extmod/modbluetooth.h | 4 | ||||
-rw-r--r-- | extmod/nimble/modbluetooth_nimble.c | 93 | ||||
-rw-r--r-- | extmod/nimble/modbluetooth_nimble.h | 1 |
5 files changed, 96 insertions, 6 deletions
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c index f5ae40a3a..285f2c816 100644 --- a/extmod/btstack/modbluetooth_btstack.c +++ b/extmod/btstack/modbluetooth_btstack.c @@ -271,7 +271,7 @@ void mp_bluetooth_deinit(void) { MP_STATE_PORT(bluetooth_btstack_root_pointers) = NULL; } -bool mp_bluetooth_is_enabled(void) { +bool mp_bluetooth_is_active(void) { return mp_bluetooth_btstack_state == MP_BLUETOOTH_BTSTACK_STATE_ACTIVE; } diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 75fbeedb5..37fa31476 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -275,7 +275,7 @@ STATIC mp_obj_t bluetooth_ble_active(size_t n_args, const mp_obj_t *args) { } } // Return current state. - return mp_obj_new_bool(mp_bluetooth_is_enabled()); + return mp_obj_new_bool(mp_bluetooth_is_active()); } STATIC MP_DEFINE_CONST_FUN_OBJ_VAR_BETWEEN(bluetooth_ble_active_obj, 1, 2, bluetooth_ble_active); diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index ed280e389..bead2387d 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -164,8 +164,8 @@ int mp_bluetooth_init(void); // Disables the Bluetooth stack. Is a no-op when not enabled. void mp_bluetooth_deinit(void); -// Returns true when the Bluetooth stack is enabled. -bool mp_bluetooth_is_enabled(void); +// Returns true when the Bluetooth stack is active. +bool mp_bluetooth_is_active(void); // Gets the MAC addr of this device in big-endian format. void mp_bluetooth_get_device_addr(uint8_t *addr); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index 8ef7c6f31..436783f29 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -46,6 +46,8 @@ #define DEBUG_EVENT_printf(...) //printf(__VA_ARGS__) +#define ERRNO_BLUETOOTH_NOT_ACTIVE MP_ENODEV + STATIC int8_t ble_hs_err_to_errno_table[] = { [BLE_HS_EAGAIN] = MP_EAGAIN, [BLE_HS_EALREADY] = MP_EALREADY, @@ -195,6 +197,9 @@ STATIC void sync_cb(void) { } STATIC void gatts_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { + if (!mp_bluetooth_is_active()) { + return; + } switch (ctxt->op) { case BLE_GATT_REGISTER_OP_SVC: // Called when a service is successfully registered. @@ -234,6 +239,9 @@ STATIC void gatts_register_cb(struct ble_gatt_register_ctxt *ctxt, void *arg) { STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_event_cb: type=%d\n", event->type); + if (!mp_bluetooth_is_active()) { + return 0; + } struct ble_gap_conn_desc desc; uint8_t addr[6] = {0}; @@ -261,6 +269,7 @@ STATIC int gap_event_cb(struct ble_gap_event *event, void *arg) { } int mp_bluetooth_init(void) { + DEBUG_EVENT_printf("mp_bluetooth_init\n"); // Clean up if necessary. mp_bluetooth_deinit(); @@ -287,6 +296,7 @@ int mp_bluetooth_init(void) { while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE) { MICROPY_EVENT_POLL_HOOK } + DEBUG_EVENT_printf("mp_bluetooth_init: ready\n"); return 0; } @@ -299,6 +309,7 @@ STATIC void ble_hs_shutdown_stop_cb(int status, void *arg) { STATIC struct ble_hs_stop_listener ble_hs_shutdown_stop_listener; void mp_bluetooth_deinit(void) { + DEBUG_EVENT_printf("mp_bluetooth_deinit\n"); if (mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { return; } @@ -308,6 +319,8 @@ void mp_bluetooth_deinit(void) { mp_bluetooth_gap_scan_stop(); #endif + mp_bluetooth_nimble_ble_state = MP_BLUETOOTH_NIMBLE_BLE_STATE_STOPPING; + ble_hs_stop(&ble_hs_shutdown_stop_listener, ble_hs_shutdown_stop_cb, NULL); while (mp_bluetooth_nimble_ble_state != MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF) { @@ -317,9 +330,10 @@ void mp_bluetooth_deinit(void) { mp_bluetooth_nimble_port_deinit(); MP_STATE_PORT(bluetooth_nimble_root_pointers) = NULL; + DEBUG_EVENT_printf("mp_bluetooth_deinit: shut down\n"); } -bool mp_bluetooth_is_enabled(void) { +bool mp_bluetooth_is_active(void) { return mp_bluetooth_nimble_ble_state == MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE; } @@ -332,10 +346,13 @@ void mp_bluetooth_get_device_addr(uint8_t *addr) { } int mp_bluetooth_gap_advertise_start(bool connectable, int32_t interval_us, const uint8_t *adv_data, size_t adv_data_len, const uint8_t *sr_data, size_t sr_data_len) { - int ret; + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } mp_bluetooth_gap_advertise_stop(); + int ret; if (adv_data) { ret = ble_gap_adv_set_data(adv_data, adv_data_len); if (ret != 0) { @@ -387,6 +404,9 @@ void mp_bluetooth_gap_advertise_stop(void) { static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, struct ble_gatt_access_ctxt *ctxt, void *arg) { DEBUG_EVENT_printf("characteristic_access_cb: conn_handle=%u value_handle=%u op=%u\n", conn_handle, value_handle, ctxt->op); + if (!mp_bluetooth_is_active()) { + return 0; + } mp_bluetooth_gatts_db_entry_t *entry; switch (ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: @@ -428,6 +448,9 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, } int mp_bluetooth_gatts_register_service_begin(bool append) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int ret = ble_gatts_reset(); if (ret != 0) { return ble_hs_err_to_errno(ret); @@ -523,26 +546,41 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m } int mp_bluetooth_gap_disconnect(uint16_t conn_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } return ble_hs_err_to_errno(ble_gap_terminate(conn_handle, BLE_ERR_REM_USER_CONN_TERM)); } int mp_bluetooth_gatts_read(uint16_t value_handle, uint8_t **value, size_t *value_len) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } return mp_bluetooth_gatts_db_read(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, value, value_len); } int mp_bluetooth_gatts_write(uint16_t value_handle, const uint8_t *value, size_t value_len) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } return mp_bluetooth_gatts_db_write(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, value, value_len); } // TODO: Could use ble_gatts_chr_updated to send to all subscribed centrals. int mp_bluetooth_gatts_notify(uint16_t conn_handle, uint16_t value_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } // Confusingly, notify/notify_custom/indicate are "gattc" function (even though they're used by peripherals (i.e. gatt servers)). // See https://www.mail-archive.com/dev@mynewt.apache.org/msg01293.html return ble_hs_err_to_errno(ble_gattc_notify(conn_handle, value_handle)); } int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } struct os_mbuf *om = ble_hs_mbuf_from_flat(value, *value_len); if (om == NULL) { return -1; @@ -552,10 +590,16 @@ int mp_bluetooth_gatts_notify_send(uint16_t conn_handle, uint16_t value_handle, } int mp_bluetooth_gatts_indicate(uint16_t conn_handle, uint16_t value_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } return ble_hs_err_to_errno(ble_gattc_indicate(conn_handle, value_handle)); } int mp_bluetooth_gatts_set_buffer(uint16_t value_handle, size_t len, bool append) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } return mp_bluetooth_gatts_db_resize(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle, len, append); } @@ -577,6 +621,9 @@ STATIC void gattc_on_data_available(uint16_t event, uint16_t conn_handle, uint16 STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("gap_scan_cb: event=%d type=%d\n", event->type, event->type == BLE_GAP_EVENT_DISC ? event->disc.event_type : -1); + if (!mp_bluetooth_is_active()) { + return 0; + } if (event->type == BLE_GAP_EVENT_DISC_COMPLETE) { mp_bluetooth_gap_on_scan_complete(); @@ -602,6 +649,9 @@ STATIC int gap_scan_cb(struct ble_gap_event *event, void *arg) { } int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_t window_us) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } if (duration_ms == 0) { duration_ms = BLE_HS_FOREVER; } @@ -618,6 +668,9 @@ int mp_bluetooth_gap_scan_start(int32_t duration_ms, int32_t interval_us, int32_ } int mp_bluetooth_gap_scan_stop(void) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } if (!ble_gap_disc_active()) { return 0; } @@ -632,6 +685,9 @@ int mp_bluetooth_gap_scan_stop(void) { // Central role: GAP events for a connected peripheral. STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { DEBUG_EVENT_printf("peripheral_gap_event_cb: event=%d\n", event->type); + if (!mp_bluetooth_is_active()) { + return 0; + } struct ble_gap_conn_desc desc; uint8_t addr[6] = {0}; @@ -676,6 +732,9 @@ STATIC int peripheral_gap_event_cb(struct ble_gap_event *event, void *arg) { } int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, int32_t duration_ms) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } if (ble_gap_disc_active()) { mp_bluetooth_gap_scan_stop(); } @@ -699,6 +758,9 @@ int mp_bluetooth_gap_peripheral_connect(uint8_t addr_type, const uint8_t *addr, STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_svc *service, void *arg) { DEBUG_EVENT_printf("peripheral_discover_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()) { + return 0; + } if (error->status == 0) { mp_obj_bluetooth_uuid_t service_uuid = create_mp_uuid(&service->uuid); mp_bluetooth_gattc_on_primary_service_result(conn_handle, service->start_handle, service->end_handle, &service_uuid); @@ -707,12 +769,18 @@ STATIC int peripheral_discover_service_cb(uint16_t conn_handle, const struct ble } int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int err = ble_gattc_disc_all_svcs(conn_handle, &peripheral_discover_service_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) { DEBUG_EVENT_printf("ble_gatt_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1); + if (!mp_bluetooth_is_active()) { + return 0; + } if (error->status == 0) { mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid); mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid); @@ -721,12 +789,18 @@ STATIC int ble_gatt_characteristic_cb(uint16_t conn_handle, const struct ble_gat } int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gatt_characteristic_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_error *error, uint16_t characteristic_val_handle, const struct ble_gatt_dsc *descriptor, void *arg) { DEBUG_EVENT_printf("ble_gatt_descriptor_cb: conn_handle=%d status=%d chr_handle=%d dsc_handle=%d\n", conn_handle, error->status, characteristic_val_handle, descriptor ? descriptor->handle : -1); + if (!mp_bluetooth_is_active()) { + return 0; + } if (error->status == 0) { mp_obj_bluetooth_uuid_t descriptor_uuid = create_mp_uuid(&descriptor->uuid); mp_bluetooth_gattc_on_descriptor_result(conn_handle, descriptor->handle, &descriptor_uuid); @@ -735,12 +809,18 @@ STATIC int ble_gatt_descriptor_cb(uint16_t conn_handle, const struct ble_gatt_er } int mp_bluetooth_gattc_discover_descriptors(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int err = ble_gattc_disc_all_dscs(conn_handle, start_handle, end_handle, &ble_gatt_descriptor_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { DEBUG_EVENT_printf("ble_gatt_attr_read_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); + if (!mp_bluetooth_is_active()) { + return 0; + } // TODO: Maybe send NULL if error->status non-zero. if (error->status == 0) { gattc_on_data_available(MP_BLUETOOTH_IRQ_GATTC_READ_RESULT, conn_handle, attr->handle, attr->om); @@ -750,18 +830,27 @@ STATIC int ble_gatt_attr_read_cb(uint16_t conn_handle, const struct ble_gatt_err // Initiate read of a value from the remote peripheral. int mp_bluetooth_gattc_read(uint16_t conn_handle, uint16_t value_handle) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int err = ble_gattc_read(conn_handle, value_handle, &ble_gatt_attr_read_cb, NULL); return ble_hs_err_to_errno(err); } STATIC int ble_gatt_attr_write_cb(uint16_t conn_handle, const struct ble_gatt_error *error, struct ble_gatt_attr *attr, void *arg) { DEBUG_EVENT_printf("ble_gatt_attr_write_cb: conn_handle=%d status=%d handle=%d\n", conn_handle, error->status, attr ? attr->handle : -1); + if (!mp_bluetooth_is_active()) { + return 0; + } mp_bluetooth_gattc_on_write_status(conn_handle, attr->handle, error->status); return 0; } // Write the value to the remote peripheral. int mp_bluetooth_gattc_write(uint16_t conn_handle, uint16_t value_handle, const uint8_t *value, size_t *value_len, unsigned int mode) { + if (!mp_bluetooth_is_active()) { + return ERRNO_BLUETOOTH_NOT_ACTIVE; + } int err; if (mode == MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE) { err = ble_gattc_write_no_rsp_flat(conn_handle, value_handle, value, *value_len); diff --git a/extmod/nimble/modbluetooth_nimble.h b/extmod/nimble/modbluetooth_nimble.h index 745ff9682..f44e1d69d 100644 --- a/extmod/nimble/modbluetooth_nimble.h +++ b/extmod/nimble/modbluetooth_nimble.h @@ -44,6 +44,7 @@ enum { MP_BLUETOOTH_NIMBLE_BLE_STATE_OFF, MP_BLUETOOTH_NIMBLE_BLE_STATE_STARTING, MP_BLUETOOTH_NIMBLE_BLE_STATE_ACTIVE, + MP_BLUETOOTH_NIMBLE_BLE_STATE_STOPPING, }; extern volatile int mp_bluetooth_nimble_ble_state; |