From a7a24096f469b1ee95242d4e7f58929cad3699ed Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 7 Dec 2018 16:52:47 -0500 Subject: [PATCH] bleio WIP: redo for more immutability; use sd_* routines for internal flash write --- ports/nrf/common-hal/bleio/Characteristic.c | 2 +- ports/nrf/common-hal/bleio/Device.c | 2 +- ports/nrf/common-hal/bleio/Service.c | 2 +- ports/nrf/supervisor/internal_flash.c | 44 ++++- shared-bindings/bleio/Characteristic.c | 193 ++++++++------------ shared-bindings/bleio/Service.c | 88 ++++----- shared-module/bleio/Characteristic.h | 2 +- 7 files changed, 154 insertions(+), 179 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 002d145c7a..5a0025d1c0 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -107,7 +107,7 @@ STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in .len = bufinfo->len, }; - if (characteristic->props.write_wo_resp) { + if (characteristic->props.write_no_response) { write_params.write_op = BLE_GATT_OP_WRITE_CMD; err_code = sd_mutex_acquire(m_write_mutex); diff --git a/ports/nrf/common-hal/bleio/Device.c b/ports/nrf/common-hal/bleio/Device.c index 454f0b602c..50c738abee 100644 --- a/ports/nrf/common-hal/bleio/Device.c +++ b/ports/nrf/common-hal/bleio/Device.c @@ -360,7 +360,7 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio 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_wo_resp = gattc_char->char_props.write_wo_resp; + characteristic->props.write_no_response = gattc_char->char_props.write_wo_resp; characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 5189fb9458..29d96e8277 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -34,7 +34,7 @@ void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, blei ble_gatts_char_md_t char_md = { .char_props.broadcast = characteristic->props.broadcast, .char_props.read = characteristic->props.read, - .char_props.write_wo_resp = characteristic->props.write_wo_resp, + .char_props.write_wo_resp = characteristic->props.write_no_response, .char_props.write = characteristic->props.write, .char_props.notify = characteristic->props.notify, .char_props.indicate = characteristic->props.indicate, diff --git a/ports/nrf/supervisor/internal_flash.c b/ports/nrf/supervisor/internal_flash.c index a648afa173..ad7a8d0815 100644 --- a/ports/nrf/supervisor/internal_flash.c +++ b/ports/nrf/supervisor/internal_flash.c @@ -70,16 +70,52 @@ uint32_t supervisor_flash_get_block_count(void) { return ((uint32_t) __fatfs_flash_length) / FILESYSTEM_BLOCK_SIZE ; } -// TODO support flashing with SD enabled +#ifdef BLUETOOTH_SD +STATIC bool wait_for_flash_operation() { + do { + sd_app_evt_wait(); + uint32 evt_id; + uint32_t result = sd_evt_get(&evt_id); + if (result == NRF_SUCCESS) { + switch (evt_id) { + case NRF_EVT_FLASH_OPERATION_SUCCESS: + return true; + + case NRF_EVT_FLASH_OPERATION_ERROR: + return false; + + default: + // Some other event. Wait for a flash event. + continue; + } + } + return false; + } while (true); +} +#endif + void supervisor_flash_flush(void) { if (_flash_page_addr == NO_CACHE) return; // Skip if data is the same if (memcmp(_flash_cache, (void *)_flash_page_addr, FL_PAGE_SZ) != 0) { -// _is_flashing = true; + +#ifdef BLUETOOTH_SD + uint8_t sd_en = 0; + (void) sd_softdevice_is_enabled(&sd_en); + + if (sd_en) { + sd_flash_page_erase(_flash_page_addr / FL_PAGE_SZ); + wait_for_flash_operation(); // TODO: handle error return. + sd_flash_write(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); + wait_for_flash_operation(); + } else { +#endif nrf_nvmc_page_erase(_flash_page_addr); nrf_nvmc_write_words(_flash_page_addr, (uint32_t *)_flash_cache, FL_PAGE_SZ / sizeof(uint32_t)); +#ifdef BLUETOOTH_SD } +#endif _flash_page_addr = NO_CACHE; } @@ -101,10 +137,6 @@ mp_uint_t supervisor_flash_write_blocks(const uint8_t *src, uint32_t lba, uint32 if (page_addr != _flash_page_addr) { supervisor_flash_flush(); - // writing previous cached data, skip current data until flashing is done - // tinyusb stack will invoke write_block() with the same parameters later on - // if ( _is_flashing ) return; - _flash_page_addr = page_addr; memcpy(_flash_cache, (void *)page_addr, FL_PAGE_SZ); } diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 68d70700f5..4fb71de470 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -38,63 +38,13 @@ //| Stores information about a BLE service characteristic and allows to read //| and write the characteristic's value. //| - -//| .. class:: Characteristic(uuid) +//| +//| .. class:: Characteristic(uuid, *, broadcast=False, indicate=False, notify=False, read=False, write=False, write_no_response=False) //| //| Create a new Characteristic object identified by the specified UUID. //| -//| :param bleio.UUID uuid: The uuid of the characteristic +//| :param bleio.UUID uuid: The uuid of the characteristic (read_only) //| - -//| .. attribute:: broadcast -//| -//| A `bool` specifying if the characteristic allows broadcasting its value. -//| - -//| .. attribute:: indicate -//| -//| A `bool` specifying if the characteristic allows indicating its value. -//| - -//| .. attribute:: notify -//| -//| A `bool` specifying if the characteristic allows notifying its value. -//| - -//| .. attribute:: read -//| -//| A `bool` specifying if the characteristic allows reading its value. -//| - -//| .. attribute:: uuid -//| -//| The UUID of this characteristic. (read-only) -//| - -//| .. attribute:: value -//| -//| The value of this characteristic. The value can be written to if the `write` property allows it. -//| If the `read` property allows it, the value can be read. If the `notify` property is set, writting -//| to the value will generate a BLE notification. -//| - -//| .. attribute:: write -//| -//| A `bool` specifying if the characteristic allows writing to its value. -//| - -//| .. attribute:: write_no_resp -//| -//| A `bool` specifying if the characteristic allows writing to its value without response. -//| -STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - mp_printf(print, "Characteristic("); - bleio_uuid_print(print, self->uuid, kind); - mp_printf(print, ")"); -} - STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { mp_arg_check_num(n_args, n_kw, 1, 1, true); bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); @@ -105,9 +55,15 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_uuid }; + enum { ARG_uuid, ARG_broadcast, ARG_indicate, ARG_notify, ARG_read, ARG_write, ARG_write_no_response }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_uuid, MP_ARG_REQUIRED| MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_broadcast, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_indicate, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_notify, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_read, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_write, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, + { MP_QSTR_write_no_response, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -120,11 +76,31 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t } self->uuid = MP_OBJ_TO_PTR(uuid); + + self->props.broadcast = args[ARG_broadcast].u_bool; + self->props.indicate = args[ARG_indicate].u_bool; + self->props.notify = args[ARG_notify].u_bool; + self->props.read = args[ARG_read].u_bool; + self->props.write = args[ARG_write].u_bool; + self->props.write_no_response = args[ARG_write_no_response].u_bool; + common_hal_bleio_characteristic_construct(self); return MP_OBJ_FROM_PTR(self); } +STATIC void bleio_characteristic_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Characteristic("); + bleio_uuid_print(print, self->uuid, kind); + mp_printf(print, ")"); +} + +//| .. attribute:: broadcast +//| +//| A `bool` specifying if the characteristic allows broadcasting its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -132,22 +108,17 @@ STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); -STATIC mp_obj_t bleio_characteristic_set_broadcast(mp_obj_t self_in, mp_obj_t broadcast_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.broadcast = mp_obj_is_true(broadcast_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_broadcast_obj, bleio_characteristic_set_broadcast); - const mp_obj_property_t bleio_characteristic_broadcast_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_broadcast_obj, - (mp_obj_t)&bleio_characteristic_set_broadcast_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: indicate +//| +//| A `bool` specifying if the characteristic allows indicating its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -155,22 +126,18 @@ STATIC mp_obj_t bleio_characteristic_get_indicate(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_indicate); -STATIC mp_obj_t bleio_characteristic_set_indicate(mp_obj_t self_in, mp_obj_t indicate_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.indicate = mp_obj_is_true(indicate_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_indicate_obj, bleio_characteristic_set_indicate); const mp_obj_property_t bleio_characteristic_indicate_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_indicate_obj, - (mp_obj_t)&bleio_characteristic_set_indicate_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: notify +//| +//| A `bool` specifying if the characteristic allows notifying its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -178,22 +145,17 @@ STATIC mp_obj_t bleio_characteristic_get_notify(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_notify); -STATIC mp_obj_t bleio_characteristic_set_notify(mp_obj_t self_in, mp_obj_t notify_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.notify = mp_obj_is_true(notify_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_notify_obj, bleio_characteristic_set_notify); - const mp_obj_property_t bleio_characteristic_notify_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_notify_obj, - (mp_obj_t)&bleio_characteristic_set_notify_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: read +//| +//| A `bool` specifying if the characteristic allows reading its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -201,22 +163,17 @@ STATIC mp_obj_t bleio_characteristic_get_read(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_read); -STATIC mp_obj_t bleio_characteristic_set_read(mp_obj_t self_in, mp_obj_t read_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.read = mp_obj_is_true(read_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_read_obj, bleio_characteristic_set_read); - const mp_obj_property_t bleio_characteristic_read_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_read_obj, - (mp_obj_t)&bleio_characteristic_set_read_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: write +//| +//| A `bool` specifying if the characteristic allows writing to its value. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -224,45 +181,35 @@ STATIC mp_obj_t bleio_characteristic_get_write(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_write); -STATIC mp_obj_t bleio_characteristic_set_write(mp_obj_t self_in, mp_obj_t write_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.write = mp_obj_is_true(write_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_obj, bleio_characteristic_set_write); - const mp_obj_property_t bleio_characteristic_write_obj = { .base.type = &mp_type_property, .proxy = { (mp_obj_t)&bleio_characteristic_get_write_obj, - (mp_obj_t)&bleio_characteristic_set_write_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; -STATIC mp_obj_t bleio_characteristic_get_write_wo_resp(mp_obj_t self_in) { +//| .. attribute:: write_no_response +//| +//| A `bool` specifying if the characteristic allows writing to its value without response. (read-only) +//| +STATIC mp_obj_t bleio_characteristic_get_write_no_response(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool(self->props.write_wo_resp); + return mp_obj_new_bool(self->props.write_no_response); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_wo_resp_obj, bleio_characteristic_get_write_wo_resp); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_no_response_obj, bleio_characteristic_get_write_no_response); -STATIC mp_obj_t bleio_characteristic_set_write_wo_resp(mp_obj_t self_in, mp_obj_t write_wo_resp_in) { - bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->props.write_wo_resp = mp_obj_is_true(write_wo_resp_in); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_characteristic_set_write_wo_resp_obj, bleio_characteristic_set_write_wo_resp); - -const mp_obj_property_t bleio_characteristic_write_wo_resp_obj = { +const mp_obj_property_t bleio_characteristic_write_no_response_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_characteristic_get_write_wo_resp_obj, - (mp_obj_t)&bleio_characteristic_set_write_wo_resp_obj, + .proxy = { (mp_obj_t)&bleio_characteristic_get_write_no_response_obj, + (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: uuid +//| +//| The UUID of this characteristic. (read-only) +//| STATIC mp_obj_t bleio_characteristic_get_uuid(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -277,6 +224,12 @@ const mp_obj_property_t bleio_characteristic_uuid_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: value +//| +//| The value of this characteristic. The value can be written to if the `write` property allows it. +//| If the `read` property allows it, the value can be read. If the `notify` property is set, writing +//| to the value will generate a BLE notification. +//| STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -313,7 +266,7 @@ STATIC const mp_rom_map_elem_t bleio_characteristic_locals_dict_table[] = { { 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) }, - { MP_ROM_QSTR(MP_QSTR_write_wo_resp), MP_ROM_PTR(&bleio_characteristic_write_wo_resp_obj) }, + { MP_ROM_QSTR(MP_QSTR_write_no_response), MP_ROM_PTR(&bleio_characteristic_write_no_response_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table); diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index 0326d6ba71..129a1d0b73 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -27,6 +27,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" @@ -38,7 +39,7 @@ //| Stores information about a BLE service and its characteristics. //| -//| .. class:: Service(uuid, secondary=False) +//| .. class:: Service(uuid, characteristics, *, secondary=False) //| //| Create a new Service object identified by the specified UUID. //| To mark the service as secondary, pass `True` as :py:data:`secondary`. @@ -47,22 +48,6 @@ //| :param bool secondary: If the service is a secondary one //| -//| .. method:: add_characteristic(characteristic) -//| -//| Appends the :py:data:`characteristic` to the list of this service's characteristics. -//| -//| :param bleio.Characteristic characteristic: the characteristic to append -//| - -//| .. attribute:: characteristics -//| -//| A `list` of `bleio.Characteristic` that are offered by this service. (read-only) -//| - -//| .. attribute:: uuid -//| -//| The UUID of this service. (read-only) -//| STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -72,19 +57,20 @@ STATIC void bleio_service_print(const mp_print_t *print, mp_obj_t self_in, mp_pr } STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { - mp_arg_check_num(n_args, n_kw, 1, 1, true); + mp_arg_check_num(n_args, n_kw, 2, 3, true); bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t); + self->char_list = mp_obj_new_list(0, NULL); self->base.type = &bleio_service_type; self->device = NULL; - self->char_list = mp_obj_new_list(0, NULL); self->handle = 0xFFFF; mp_map_t kw_args; mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); - enum { ARG_uuid, ARG_secondary }; + enum { ARG_uuid, ARG_characteristics, ARG_secondary }; static const mp_arg_t allowed_args[] = { - { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { ARG_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, + { MP_QSTR_characteristics, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; @@ -95,41 +81,42 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t uuid = args[ARG_uuid].u_obj; - if (uuid == mp_const_none) { - return MP_OBJ_FROM_PTR(self); + if (!MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { + mp_raise_ValueError(translate("Expected a UUID")); } - if (MP_OBJ_IS_TYPE(uuid, &bleio_uuid_type)) { - self->uuid = MP_OBJ_TO_PTR(uuid); - } else { - mp_raise_ValueError(translate("Expected a UUID or None")); - } + self->uuid = MP_OBJ_TO_PTR(uuid); + // If characteristics is not an iterable, an exception will be thrown. + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(args[ARG_characteristics].u_obj, &iter_buf); + mp_obj_t characteristic; + + while ((characteristic = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(characteristic, &bleio_characteristic_type)) { + mp_raise_ValueError(translate("characteristics includes an object that is not a Characteristic")); + } + bleio_characteristic_obj_t *characteristic_ptr = MP_OBJ_TO_PTR(characteristic); + if (common_hal_bleio_uuid_get_uuid128_reference(uuid) != + common_hal_bleio_uuid_get_uuid128_reference(characteristic_ptr->uuid)) { + // The descriptor base UUID doesn't match the characteristic base UUID. + mp_raise_ValueError(translate("Characteristic UUID doesn't match Service UUID")); + } + characteristic_ptr->service = self; + mp_obj_list_append(self->char_list, characteristic); + } return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t bleio_service_add_characteristic(mp_obj_t self_in, mp_obj_t characteristic_in) { - bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); - bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(characteristic_in); - - if (common_hal_bleio_uuid_get_uuid128_reference(self->uuid) != - common_hal_bleio_uuid_get_uuid128_reference(characteristic->uuid)) { - // The descriptor base UUID doesn't match the characteristic base UUID. - mp_raise_ValueError(translate("Characteristic UUID doesn't match Descriptor UUID")); - } - - characteristic->service = self; - - mp_obj_list_append(self->char_list, characteristic); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_service_add_characteristic_obj, bleio_service_add_characteristic); - +//| .. attribute:: characteristics +//| +//| A `list` 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); - - return self->char_list; + // Return list as a tuple so user won't be able to change it. + mp_obj_list_t *char_list = MP_OBJ_TO_PTR(self->char_list); + return mp_obj_new_tuple(char_list->len, char_list->items); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_characteristics_obj, bleio_service_get_characteristics); @@ -140,6 +127,10 @@ const mp_obj_property_t bleio_service_characteristics_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: uuid +//| +//| The UUID of this service. (read-only) +//| STATIC mp_obj_t bleio_service_get_uuid(mp_obj_t self_in) { bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -155,7 +146,6 @@ const mp_obj_property_t bleio_service_uuid_obj = { }; STATIC const mp_rom_map_elem_t bleio_service_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_add_characteristic), MP_ROM_PTR(&bleio_service_add_characteristic_obj) }, { MP_ROM_QSTR(MP_QSTR_characteristics), MP_ROM_PTR(&bleio_service_characteristics_obj) }, { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_service_uuid_obj) }, }; diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h index 94c43f81e0..977ec81976 100644 --- a/shared-module/bleio/Characteristic.h +++ b/shared-module/bleio/Characteristic.h @@ -39,7 +39,7 @@ typedef struct { struct { bool broadcast : 1; bool read : 1; - bool write_wo_resp : 1; + bool write_no_response : 1; bool write : 1; bool notify : 1; bool indicate : 1;