diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c index f7077f4b9a..d90737411f 100644 --- a/ports/nrf/common-hal/bleio/Central.c +++ b/ports/nrf/common-hal/bleio/Central.c @@ -97,7 +97,7 @@ STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_character m_discovery_successful = false; m_discovery_in_process = true; - uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range); + uint32_t err_code = sd_ble_gattc_descriptors_discover(self->conn_handle, &handle_range); if (err_code != NRF_SUCCESS) { return false; } @@ -116,8 +116,10 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); service->base.type = &bleio_service_type; + // Initialize several fields at once. + common_hal_bleio_service_construct(service, NULL, mp_obj_new_list(0, NULL), false); + service->device = MP_OBJ_FROM_PTR(central); - service->characteristic_list = mp_obj_new_list(0, NULL); service->start_handle = gattc_service->handle_range.start_handle; service->end_handle = gattc_service->handle_range.end_handle; service->handle = gattc_service->handle_range.start_handle; @@ -152,6 +154,8 @@ 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; + characteristic->descriptor_list = mp_obj_new_list(0, NULL); + bleio_uuid_obj_t *uuid = NULL; if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) { @@ -174,8 +178,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio 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); + // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. + common_hal_bleio_characteristic_construct(characteristic, uuid, props, mp_obj_new_list(0, NULL)); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; @@ -192,6 +196,27 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio for (size_t i = 0; i < response->count; ++i) { ble_gattc_desc_t *gattc_desc = &response->descs[i]; + // Remember handles for certain well-known descriptors. + switch (gattc_desc->uuid.uuid) { + case DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION: + m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; + break; + + case DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION: + m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; + break; + + case DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION: + m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; + break; + + default: + // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors, + // so ignore those. + // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors + break; + } + bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t); descriptor->base.type = &bleio_descriptor_type; @@ -251,6 +276,7 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { case BLE_GATTC_EVT_DESC_DISC_RSP: on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, central); + break; 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); @@ -265,7 +291,7 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { default: // For debugging. - mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); + // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id); break; } } @@ -330,13 +356,13 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) { - // discover_next_services() appends to service_list. + // discover_next_services() appends to 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 = - MP_OBJ_TO_PTR(self->service_list->items[self->service_list->len - 1]); - next_service_start_handle = service->end_handle + 1; + // 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 = + 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; @@ -384,10 +410,11 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o } // 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) { + size_t char_list_len = service->characteristic_list->len; + for (size_t char_idx = 0; char_idx < char_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; + const bool last_characteristic = char_idx == char_list_len - 1; bleio_characteristic_obj_t *next_characteristic = last_characteristic ? NULL : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]); @@ -402,13 +429,15 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o // 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; + : next_characteristic->handle - 1; // 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)) { + next_desc_start_handle < next_desc_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. diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 1db0a9378d..17417a5e64 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -162,7 +162,6 @@ STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in check_connected(conn_handle); ble_gattc_write_params_t write_params = { - .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL, .write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ, .handle = characteristic->handle, .p_value = bufinfo->buf, @@ -210,19 +209,19 @@ STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) { } -void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list) { self->service = mp_const_none; self->uuid = uuid; self->value_data = mp_const_none; self->props = props; + self->descriptor_list = descriptor_list; self->handle = BLE_GATT_HANDLE_INVALID; ble_drv_add_event_handler(characteristic_on_ble_evt, self); - } -void common_hal_bleio_characteristic_set_service(bleio_characteristic_obj_t *self, bleio_service_obj_t *service) { - self->service = service; +mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { + return self->descriptor_list; } mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { @@ -284,3 +283,47 @@ bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) { return self->props; } + +void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) { + if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) { + mp_raise_ValueError(translate("No CCCD for this Characteristic")); + } + + if (common_hal_bleio_device_get_gatt_role(self->service->device) != GATT_ROLE_CLIENT) { + mp_raise_ValueError(translate("Can't set CCCD for local Characteristic")); + } + + uint16_t cccd_value = + (notify ? BLE_GATT_HVX_NOTIFICATION : 0) | + (indicate ? BLE_GATT_HVX_INDICATION : 0); + + const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + check_connected(conn_handle); + + + ble_gattc_write_params_t write_params = { + .write_op = BLE_GATT_OP_WRITE_REQ, + .handle = self->cccd_handle, + .p_value = (uint8_t *) &cccd_value, + .len = 2, + }; + + while (1) { + uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); + if (err_code == NRF_SUCCESS) { + break; + } + + // Write with response will return NRF_ERROR_BUSY if the response has not been received. + // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending. + if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) { + // We could wait for an event indicating the write is complete, but just retrying is easier. + MICROPY_VM_HOOK_LOOP; + continue; + } + + // Some real error occurred. + mp_raise_OSError_msg_varg(translate("Failed to write CCCD, err 0x%04x"), err_code); + } + +} diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c index d3f2a0ff84..005af6eaae 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.c +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -37,6 +37,6 @@ mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) { return self->handle; } -mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { - return MP_OBJ_FROM_PTR(self->uuid); +bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { + return self->uuid; } diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index b31bb84b0c..608bd1342b 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -135,13 +135,13 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_ for (size_t service_idx = 0; service_idx < service_list->len; ++service_idx) { bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[service_idx]); - common_hal_bleio_service_set_device(service, MP_OBJ_FROM_PTR(self)); + service->device = MP_OBJ_FROM_PTR(self); ble_uuid_t uuid; bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid); uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; - if (service->is_secondary) { + if (common_hal_bleio_service_get_is_secondary(service)) { service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; } diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h index 725bc14314..2a12517159 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.h +++ b/ports/nrf/common-hal/bleio/Peripheral.h @@ -44,7 +44,6 @@ typedef struct { gatt_role_t gatt_role; volatile uint16_t conn_handle; mp_obj_list_t *service_list; - mp_obj_t conn_handler; // The advertising data and scan response buffers are held by us, not by the SD, so we must // maintain them and not change it. If we need to change the contents during advertising, // there are tricks to get the SD to notice (see DevZone - TBS). diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 9939de775d..b6fcde8277 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -44,7 +44,7 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob 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]); - common_hal_bleio_characteristic_set_service(characteristic, self); + characteristic->service = self; } } @@ -61,10 +61,6 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { return self->is_secondary; } -void common_hal_bleio_service_set_device(bleio_service_obj_t *self, mp_obj_t device) { - self->device = device; -} - // 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. diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c index 0e094c2e35..cfad8fc11d 100644 --- a/shared-bindings/bleio/Address.c +++ b/shared-bindings/bleio/Address.c @@ -49,10 +49,10 @@ //| //| :param buf address: The address value to encapsulate. A buffer object (bytearray, bytes) of 6 bytes. //| :param int address_type: one of these integers: -//| - `bleio.Address.PUBLIC` = 0 -//| - `bleio.Address.RANDOM_STATIC` = 1 -//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE` = 2 -//| - `bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE` = 3 +//| - ``bleio.Address.PUBLIC`` = 0 +//| - ``bleio.Address.RANDOM_STATIC`` = 1 +//| - ``bleio.Address.RANDOM_PRIVATE_RESOLVABLE`` = 2 +//| - ``bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE`` = 3 //| STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { @@ -89,11 +89,6 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, //| //| The bytes that make up the device address (read-only) //| -//| - `bleio.Address.PUBLIC` -//| - `bleio.Address.RANDOM_STATIC` -//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE` -//| - `bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE` -//| STATIC mp_obj_t bleio_address_get_address_bytes(mp_obj_t self_in) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -112,10 +107,10 @@ const mp_obj_property_t bleio_address_address_bytes_obj = { //| //| The address type (read-only). One of these integers: //| -//| - `bleio.Address.PUBLIC` -//| - `bleio.Address.RANDOM_STATIC` -//| - `bleio.Address.RANDOM_PRIVATE_RESOLVABLE` -//| - `bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE` +//| - ``bleio.Address.PUBLIC`` = 0 +//| - ``bleio.Address.RANDOM_STATIC`` = 1 +//| - ``bleio.Address.RANDOM_PRIVATE_RESOLVABLE`` = 2 +//| - ``bleio.Address.RANDOM_PRIVATE_NON_RESOLVABLE`` = 3 //| STATIC mp_obj_t bleio_address_get_type(mp_obj_t self_in) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/bleio/AdvertisementData.h b/shared-bindings/bleio/AdvertisementData.h deleted file mode 100644 index 3313cde3b2..0000000000 --- a/shared-bindings/bleio/AdvertisementData.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2019 Dan Halbert for Adafruit Industries - * Copyright (c) 2018 Artur Pacholec - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H -#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H - -#include "py/obj.h" - -extern const mp_obj_type_t bleio_advertisementdata_type; - -#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADVERTISEMENTDATA_H diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index ede38c86b3..0d5f8f79ac 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -88,7 +88,8 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t properties.write = args[ARG_write].u_bool; properties.write_no_response = args[ARG_write_no_response].u_bool; - common_hal_bleio_characteristic_construct(self, uuid, properties); + // Initialize, with an empty descriptor list. + common_hal_bleio_characteristic_construct(self, uuid, properties, mp_obj_new_list(0, NULL)); return MP_OBJ_FROM_PTR(self); } @@ -254,11 +255,58 @@ const mp_obj_property_t bleio_characteristic_value_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: descriptors +//| +//| A tuple of `bleio.Descriptor` that describe this characteristic. (read-only) +//| +STATIC mp_obj_t bleio_characteristic_get_descriptors(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + // Return list as a tuple so user won't be able to change it. + mp_obj_list_t *char_list = common_hal_bleio_characteristic_get_descriptor_list(self); + return mp_obj_new_tuple(char_list->len, char_list->items); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_descriptors_obj, bleio_characteristic_get_descriptors); + +const mp_obj_property_t bleio_characteristic_descriptors_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_descriptors_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +//| .. method:: set_cccd(*, notify=False, indicate=False) +//| +//| Set the remote characteristic's CCCD to enable or disable notification and indication. +//| +//| :param bool notify: True if Characteristic should receive notifications of remote writes +//| :param float indicate: True if Characteristic should receive indications of remote writes +//| +STATIC mp_obj_t bleio_characteristic_set_cccd(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_notify, ARG_indicate }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_notify, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_indicate, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args - 1, pos_args + 1, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + common_hal_bleio_characteristic_set_cccd(self, args[ARG_notify].u_bool, args[ARG_indicate].u_bool); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_characteristic_set_cccd); + + STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_broadcast), MP_ROM_PTR(&bleio_characteristic_broadcast_obj) }, + { MP_ROM_QSTR(MP_QSTR_descriptors), MP_ROM_PTR(&bleio_characteristic_descriptors_obj) }, { MP_ROM_QSTR(MP_QSTR_indicate), MP_ROM_PTR(&bleio_characteristic_indicate_obj) }, { MP_ROM_QSTR(MP_QSTR_notify), MP_ROM_PTR(&bleio_characteristic_notify_obj) }, { MP_ROM_QSTR(MP_QSTR_read), MP_ROM_PTR(&bleio_characteristic_read_obj) }, + { MP_ROM_QSTR(MP_QSTR_set_cccd), MP_ROM_PTR(&bleio_characteristic_set_cccd_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_characteristic_uuid_obj) }, { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_characteristic_value_obj) }, { MP_ROM_QSTR(MP_QSTR_write), MP_ROM_PTR(&bleio_characteristic_write_obj) }, diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h index 1938845a9a..d450c42b4e 100644 --- a/shared-bindings/bleio/Characteristic.h +++ b/shared-bindings/bleio/Characteristic.h @@ -33,11 +33,12 @@ extern const mp_obj_type_t bleio_characteristic_type; -extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props); -extern void common_hal_bleio_characteristic_set_service(bleio_characteristic_obj_t *self, bleio_service_obj_t *service); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list); extern mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self); extern void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo); extern bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self); extern bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self); +extern mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self); +extern void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c index 723352ea12..f392838926 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -31,24 +31,6 @@ #include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/UUID.h" -enum { - DescriptorUuidCharacteristicExtendedProperties = 0x2900, - DescriptorUuidCharacteristicUserDescription = 0x2901, - DescriptorUuidClientCharacteristicConfiguration = 0x2902, - DescriptorUuidServerCharacteristicConfiguration = 0x2903, - DescriptorUuidCharacteristicPresentationFormat = 0x2904, - DescriptorUuidCharacteristicAggregateFormat = 0x2905, - DescriptorUuidValidRange = 0x2906, - DescriptorUuidExternalReportReference = 0x2907, - DescriptorUuidReportReference = 0x2908, - DescriptorUuidNumberOfDigitals = 0x2909, - DescriptorUuidValueTriggerSetting = 0x290A, - DescriptorUuidEnvironmentalSensingConfiguration = 0x290B, - DescriptorUuidEnvironmentalSensingMeasurement = 0x290C, - DescriptorUuidEnvironmentalSensingTriggerSetting = 0x290D, - DescriptorUuidTimeTriggerSetting = 0x290E, -}; - //| .. currentmodule:: bleio //| //| :class:`Descriptor` -- BLE descriptor @@ -111,7 +93,9 @@ const mp_obj_property_t bleio_descriptor_handle_obj = { STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) { bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); - return common_hal_bleio_descriptor_get_uuid(self); + + bleio_uuid_obj_t *uuid = common_hal_bleio_descriptor_get_uuid(self); + return uuid ? MP_OBJ_FROM_PTR(uuid) : mp_const_none; } MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_uuid_obj, bleio_descriptor_get_uuid); @@ -128,28 +112,69 @@ STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) }, // Static variables - { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES), MP_ROM_INT(DescriptorUuidCharacteristicExtendedProperties) }, - { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION), MP_ROM_INT(DescriptorUuidCharacteristicUserDescription) }, - { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidClientCharacteristicConfiguration) }, - { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION), MP_ROM_INT(DescriptorUuidServerCharacteristicConfiguration) }, - { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicPresentationFormat) }, - { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT), MP_ROM_INT(DescriptorUuidCharacteristicAggregateFormat) }, - { MP_ROM_QSTR(MP_QSTR_VALID_RANGE), MP_ROM_INT(DescriptorUuidValidRange) }, - { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidExternalReportReference) }, - { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE), MP_ROM_INT(DescriptorUuidReportReference) }, - { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS), MP_ROM_INT(DescriptorUuidNumberOfDigitals) }, - { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidValueTriggerSetting) }, - { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION), MP_ROM_INT(DescriptorUuidEnvironmentalSensingConfiguration) }, - { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ), MP_ROM_INT(DescriptorUuidEnvironmentalSensingMeasurement) }, - { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidEnvironmentalSensingTriggerSetting) }, - { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING), MP_ROM_INT(DescriptorUuidTimeTriggerSetting) } + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_EXTENDED_PROPERTIES), + MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES) }, + + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_USER_DESCRIPTION), + MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION) }, + + { MP_ROM_QSTR(MP_QSTR_CLIENT_CHARACTERISTIC_CONFIGURATION), + MP_ROM_INT(DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION) }, + + { MP_ROM_QSTR(MP_QSTR_SERVER_CHARACTERISTIC_CONFIGURATION), + MP_ROM_INT(DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION) }, + + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_PRESENTATION_FORMAT), + MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT) }, + + { MP_ROM_QSTR(MP_QSTR_CHARACTERISTIC_AGGREGATE_FORMAT), + MP_ROM_INT(DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT) }, + + { MP_ROM_QSTR(MP_QSTR_VALID_RANGE), + MP_ROM_INT(DESCRIPTOR_UUID_VALID_RANGE) }, + + { MP_ROM_QSTR(MP_QSTR_EXTERNAL_REPORT_REFERENCE), + MP_ROM_INT(DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE) }, + + { MP_ROM_QSTR(MP_QSTR_REPORT_REFERENCE), + MP_ROM_INT(DESCRIPTOR_UUID_REPORT_REFERENCE) }, + + { MP_ROM_QSTR(MP_QSTR_NUMBER_OF_DIGITALS), + MP_ROM_INT(DESCRIPTOR_UUID_NUMBER_OF_DIGITALS) }, + + { MP_ROM_QSTR(MP_QSTR_VALUE_TRIGGER_SETTING), + MP_ROM_INT(DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING) }, + + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_CONFIGURATION), + MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION) }, + + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_MEASUREMENT ), + MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT) }, + + { MP_ROM_QSTR(MP_QSTR_ENVIRONMENTAL_SENSING_TRIGGER_SETTING), + MP_ROM_INT(DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING) }, + + { MP_ROM_QSTR(MP_QSTR_TIME_TRIGGER_SETTING), + MP_ROM_INT(DESCRIPTOR_UUID_TIME_TRIGGER_SETTING) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table); +STATIC void bleio_descriptor_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + mp_printf(print, "Descriptor("); + if (self->uuid) { + bleio_uuid_print(print, MP_OBJ_FROM_PTR(self->uuid), kind); + } else { + mp_printf(print, "Unregistered uUID"); + } + mp_printf(print, ")"); +} + const mp_obj_type_t bleio_descriptor_type = { { &mp_type_type }, .name = MP_QSTR_Descriptor, .make_new = bleio_descriptor_make_new, + .print = bleio_descriptor_print, .locals_dict = (mp_obj_dict_t*)&bleio_descriptor_locals_dict }; diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h index f4634d3933..fd11ea08cd 100644 --- a/shared-bindings/bleio/Descriptor.h +++ b/shared-bindings/bleio/Descriptor.h @@ -31,6 +31,24 @@ #include "common-hal/bleio/Descriptor.h" #include "common-hal/bleio/UUID.h" +enum { + DESCRIPTOR_UUID_CHARACTERISTIC_EXTENDED_PROPERTIES = 0x2900, + DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION = 0x2901, + DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION = 0x2902, + DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION = 0x2903, + DESCRIPTOR_UUID_CHARACTERISTIC_PRESENTATION_FORMAT = 0x2904, + DESCRIPTOR_UUID_CHARACTERISTIC_AGGREGATE_FORMAT = 0x2905, + DESCRIPTOR_UUID_VALID_RANGE = 0x2906, + DESCRIPTOR_UUID_EXTERNAL_REPORT_REFERENCE = 0x2907, + DESCRIPTOR_UUID_REPORT_REFERENCE = 0x2908, + DESCRIPTOR_UUID_NUMBER_OF_DIGITALS = 0x2909, + DESCRIPTOR_UUID_VALUE_TRIGGER_SETTING = 0x290A, + DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_CONFIGURATION = 0x290B, + DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_MEASUREMENT = 0x290C, + DESCRIPTOR_UUID_ENVIRONMENTAL_SENSING_TRIGGER_SETTING = 0x290D, + DESCRIPTOR_UUID_TIME_TRIGGER_SETTING = 0x290E, +}; + extern const mp_obj_type_t bleio_descriptor_type; extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid); diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index 320d834718..b8d4c39753 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -82,13 +82,12 @@ static const char default_name[] = "CIRCUITPY"; //| .. class:: Peripheral(services=(), \*, name='CIRCUITPY') //| //| Create a new Peripheral object. - +//| //| :param iterable services: the Service objects representing services available from this peripheral, if any. //| A non-connectable peripheral will have no services. //| :param str name: The name used when advertising this peripheral. Use ``None`` when a name is not needed, //| such as when the peripheral is a beacon //| - STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { enum { ARG_services, ARG_name }; static const mp_arg_t allowed_args[] = { diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index f8993ef619..af215c6a50 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -102,7 +102,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, //| .. attribute:: characteristics //| -//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) +//| A tuple of `bleio.Characteristic` that are offered by this service. (read-only) //| STATIC mp_obj_t bleio_service_get_characteristics(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h index 6693cc3bb3..f646c81a9b 100644 --- a/shared-bindings/bleio/Service.h +++ b/shared-bindings/bleio/Service.h @@ -36,7 +36,6 @@ extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_ extern bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self); extern mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self); extern bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self); -extern void common_hal_bleio_service_set_device(bleio_service_obj_t *self, mp_obj_t device); extern void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SERVICE_H diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 9e80b49e37..ba3bae6c75 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -53,15 +53,14 @@ //| :maxdepth: 3 //| //| Address -//| AdvertisementData //| Adapter //| Central //| Characteristic //| CharacteristicBuffer -// Descriptor +//| Descriptor //| Peripheral -//| ScanEntry -//| Scanner +//| ScanEntry +//| Scanner //| Service //| UUID //|