diff options
| author | Dan Halbert <halbert@halwitz.org> | 2019-07-07 00:07:47 -0400 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2019-07-07 00:07:47 -0400 |
| commit | 09ddff8df1349c590e6c0533b6f5085fbcb92483 (patch) | |
| tree | 0d7e167b231f892937eaead1390a2fcaee65b6ce /ports | |
| parent | bf8a35b2f835fbc97d54867f8e21b486a46c245b (diff) | |
WIP: Need descriptors for Central CCCD discovery; not done yet
Diffstat (limited to 'ports')
| -rw-r--r-- | ports/nrf/common-hal/bleio/Central.c | 163 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Central.h | 3 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Characteristic.c | 27 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Characteristic.h | 3 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Descriptor.c | 1 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Descriptor.h | 2 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Peripheral.c | 4 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Service.c | 9 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Service.h | 3 |
9 files changed, 164 insertions, 51 deletions
diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c index 5bd5a6321..f7077f4b9 100644 --- a/ports/nrf/common-hal/bleio/Central.c +++ b/ports/nrf/common-hal/bleio/Central.c @@ -37,10 +37,13 @@ #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Central.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" static bleio_service_obj_t *m_char_discovery_service; +static bleio_characteristic_obj_t *m_desc_discovery_characteristic; + static volatile bool m_discovery_in_process; static volatile bool m_discovery_successful; @@ -84,6 +87,28 @@ STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_servi return m_discovery_successful; } +STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) { + m_desc_discovery_characteristic = characteristic; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range); + if (err_code != NRF_SUCCESS) { + return false; + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_central_obj_t *central) { for (size_t i = 0; i < response->count; ++i) { ble_gattc_service_t *gattc_service = &response->services[i]; @@ -127,25 +152,30 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t); characteristic->base.type = &bleio_characteristic_type; + bleio_uuid_obj_t *uuid = NULL; + if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { // Known characteristic UUID. - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid = m_new_obj(bleio_uuid_obj_t); uuid->base.type = &bleio_uuid_type; bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid); - characteristic->uuid = uuid; } else { // The discovery response contained a 128-bit UUID that has not yet been registered with the // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. - // For now, just set the UUID to NULL. - characteristic->uuid = NULL; + // For now, just leave the UUID as NULL. } - characteristic->props.broadcast = gattc_char->char_props.broadcast; - characteristic->props.indicate = gattc_char->char_props.indicate; - characteristic->props.notify = gattc_char->char_props.notify; - characteristic->props.read = gattc_char->char_props.read; - characteristic->props.write = gattc_char->char_props.write; - characteristic->props.write_no_response = gattc_char->char_props.write_wo_resp; + bleio_characteristic_properties_t props; + + props.broadcast = gattc_char->char_props.broadcast; + props.indicate = gattc_char->char_props.indicate; + props.notify = gattc_char->char_props.notify; + props.read = gattc_char->char_props.read; + props.write = gattc_char->char_props.write; + props.write_no_response = gattc_char->char_props.write_wo_resp; + + // Call common_hal_bleio_characteristic_construct() to set up evt handler. + common_hal_bleio_characteristic_construct(characteristic, uuid, props); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; @@ -158,6 +188,39 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio m_discovery_in_process = false; } +STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_central_obj_t *central) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_desc_t *gattc_desc = &response->descs[i]; + + bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); + descriptor->base.type = &bleio_descriptor_type; + + bleio_uuid_obj_t *uuid = NULL; + + if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known descriptor UUID. + uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid); + } else { + // The discovery response contained a 128-bit UUID that has not yet been registered with the + // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it. + // For now, just leave the UUID as NULL. + } + + common_hal_bleio_descriptor_construct(descriptor, uuid); + descriptor->handle = gattc_desc->handle; + descriptor->characteristic = m_desc_discovery_characteristic; + + mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { bleio_central_obj_t *central = (bleio_central_obj_t*)central_in; @@ -186,17 +249,24 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, central); break; + case BLE_GATTC_EVT_DESC_DISC_RSP: + on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, central); + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: sd_ble_gap_sec_params_reply(central->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); break; - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: - { + case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: { ble_gap_evt_conn_param_update_request_t *request = &ble_evt->evt.gap_evt.params.conn_param_update_request; sd_ble_gap_conn_param_update(central->conn_handle, &request->conn_params); break; } + + default: + // For debugging. + mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); + break; } } @@ -257,16 +327,16 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o // List of service UUID's not given, so discover all available services. - uint16_t next_start_handle = BLE_GATT_HANDLE_START; + uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; - while (discover_next_services(self, next_start_handle, MP_OBJ_NULL)) { + while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) { // discover_next_services() appends to service_list. - const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); // Get the most recently discovered service, and then ask for services // whose handles start after the last attribute handle inside that service. - const bleio_service_obj_t *service = service_list->items[service_list->len - 1]; - next_start_handle = service->end_handle + 1; + const bleio_service_obj_t *service = + MP_OBJ_TO_PTR(self->service_list->items[self->service_list->len - 1]); + next_service_start_handle = service->end_handle + 1; } } else { mp_obj_iter_buf_t iter_buf; @@ -289,30 +359,65 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o } - const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); - for (size_t i = 0; i < service_list->len; ++i) { - bleio_service_obj_t *service = service_list->items[i]; + for (size_t service_idx = 0; service_idx < self->service_list->len; ++service_idx) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->service_list->items[service_idx]); // Skip the service if it had an unknown (unregistered) UUID. if (service->uuid == NULL) { continue; } - uint16_t next_start_handle = service->start_handle; + uint16_t next_char_start_handle = service->start_handle; // Stop when we go past the end of the range of handles for this service or // discovery call returns nothing. - while (next_start_handle <= service->end_handle && - discover_next_characteristics(self, service, next_start_handle)) { + // discover_next_characteristics() appends to the characteristic_list. + while (next_char_start_handle <= service->end_handle && + discover_next_characteristics(self, service, next_char_start_handle)) { - // discover_next_characteristics() appends to the characteristic_list. - const mp_obj_list_t *characteristic_list = MP_OBJ_TO_PTR(service->characteristic_list); - // Get the most recently discovered characteristic. + // Get the most recently discovered characteristic, and then ask for characteristics + // whose handles start after the last attribute handle inside that characteristic. const bleio_characteristic_obj_t *characteristic = - characteristic_list->items[characteristic_list->len - 1]; - next_start_handle = characteristic->handle + 1; + MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]); + next_char_start_handle = characteristic->handle + 1; + } + + // Got characteristics for this service. Now discover descriptors for each characteristic. + for (size_t char_idx = 0; char_idx < service->characteristic_list->len; ++char_idx) { + bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]); + const bool last_characteristic = char_idx == service->characteristic_list->len - 1; + bleio_characteristic_obj_t *next_characteristic = last_characteristic + ? NULL + : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); + + // Skip the characteristic if it had an unknown (unregistered) UUID. + if (characteristic->uuid == NULL) { + continue; + } + + uint16_t next_desc_start_handle = characteristic->handle + 1; + + // Don't run past the end of this service or the beginning of the next characteristic. + uint16_t next_desc_end_handle = next_characteristic == NULL + ? service->end_handle + : next_characteristic->handle; + + // Stop when we go past the end of the range of handles for this service or + // discovery call returns nothing. + // discover_next_descriptors() appends to the descriptor_list. + while (next_desc_start_handle <= service->end_handle && + discover_next_descriptors(self, characteristic, next_desc_start_handle, next_desc_end_handle)) { + + // Get the most recently discovered descriptor, and then ask for descriptors + // whose handles start after that descriptor's handle. + const bleio_descriptor_obj_t *descriptor = + MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]); + next_desc_start_handle = descriptor->handle + 1; + } } + } } @@ -324,6 +429,6 @@ bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) { return self->conn_handle != BLE_CONN_HANDLE_INVALID; } -mp_obj_t common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) { +mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) { return self->service_list; } diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/bleio/Central.h index 8b38e87ac..ac1670088 100644 --- a/ports/nrf/common-hal/bleio/Central.h +++ b/ports/nrf/common-hal/bleio/Central.h @@ -30,6 +30,7 @@ #include <stdbool.h> +#include "py/objlist.h" #include "shared-module/bleio/__init__.h" #include "shared-module/bleio/Address.h" @@ -38,7 +39,7 @@ typedef struct { gatt_role_t gatt_role; volatile bool waiting_to_connect; volatile uint16_t conn_handle; - mp_obj_t service_list; + mp_obj_list_t *service_list; } bleio_central_obj_t; #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index c00d8c30b..1db0a9378 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -194,27 +194,26 @@ STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) { // More events may be handled later, so keep this as a switch. - case BLE_GATTC_EVT_READ_RSP: - { - ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; - m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data); - // Indicate to busy-wait loop that we've read the characteristic. - m_read_characteristic = NULL; - break; - } + case BLE_GATTC_EVT_READ_RSP: { + ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; + m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data); + // Indicate to busy-wait loop that we've read the characteristic. + m_read_characteristic = NULL; + break; + } - // For debugging. - default: - // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); - break; + // For debugging. + default: + // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); + break; } } void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props) { - self->service = NULL; + self->service = mp_const_none; self->uuid = uuid; - self->value_data = NULL; + self->value_data = mp_const_none; self->props = props; self->handle = BLE_GATT_HANDLE_INVALID; diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h index 451bae471..7cb227596 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.h +++ b/ports/nrf/common-hal/bleio/Characteristic.h @@ -36,9 +36,10 @@ typedef struct { mp_obj_base_t base; bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; - mp_obj_t value_data; + volatile mp_obj_t value_data; uint16_t handle; bleio_characteristic_properties_t props; + mp_obj_list_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; uint16_t sccd_handle; diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c index 418cc07c1..d3f2a0ff8 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.c +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -30,7 +30,6 @@ #include "shared-bindings/bleio/UUID.h" void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) { - // TODO: set handle ??? self->uuid = uuid; } diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h index 47552f39d..b7af6a42f 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.h +++ b/ports/nrf/common-hal/bleio/Descriptor.h @@ -30,11 +30,13 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H #include "py/obj.h" +#include "common-hal/bleio/Characteristic.h" #include "common-hal/bleio/UUID.h" typedef struct { mp_obj_base_t base; uint16_t handle; + bleio_characteristic_obj_t *characteristic; bleio_uuid_obj_t *uuid; } bleio_descriptor_obj_t; diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index fc9a146c3..b31bb84b0 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -243,3 +243,7 @@ void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code); } } + +void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) { + sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); +} diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 55193c5cb..9939de775 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -42,7 +42,8 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob self->is_secondary = is_secondary; for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) { - bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]); + bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]); common_hal_bleio_characteristic_set_service(characteristic, self); } @@ -67,9 +68,9 @@ void common_hal_bleio_service_set_device(bleio_service_obj_t *self, mp_obj_t dev // Call this after the Service has been added to the Peripheral. void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) { // Add all the characteristics. - const mp_obj_list_t *characteristic_list = MP_OBJ_TO_PTR(self->characteristic_list); - for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) { - bleio_characteristic_obj_t *characteristic = characteristic_list->items[characteristic_idx]; + for (size_t characteristic_idx = 0; characteristic_idx < self->characteristic_list->len; ++characteristic_idx) { + bleio_characteristic_obj_t *characteristic = + MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]); ble_gatts_char_md_t char_md = { .char_props.broadcast = characteristic->props.broadcast, diff --git a/ports/nrf/common-hal/bleio/Service.h b/ports/nrf/common-hal/bleio/Service.h index 90f52027d..583593fb8 100644 --- a/ports/nrf/common-hal/bleio/Service.h +++ b/ports/nrf/common-hal/bleio/Service.h @@ -28,6 +28,7 @@ #ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H +#include "py/objlist.h" #include "common-hal/bleio/UUID.h" typedef struct { @@ -38,7 +39,7 @@ typedef struct { bleio_uuid_obj_t *uuid; // May be a Peripheral, Central, etc. mp_obj_t device; - mp_obj_t characteristic_list; + mp_obj_list_t *characteristic_list; // Range of attribute handles of this service. uint16_t start_handle; uint16_t end_handle; |
