From 28ca05ccdcf674ad128f357ac8f54a1931560331 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Sat, 27 Jul 2019 13:20:59 -0400 Subject: [PATCH 1/9] allow discovery from central or peripheral --- ports/nrf/boards/make-pins.py | 208 ---------- ports/nrf/common-hal/bleio/Central.c | 335 +--------------- ports/nrf/common-hal/bleio/Central.h | 4 +- ports/nrf/common-hal/bleio/Characteristic.c | 70 ++-- .../common-hal/bleio/CharacteristicBuffer.c | 2 +- ports/nrf/common-hal/bleio/Peripheral.c | 15 +- ports/nrf/common-hal/bleio/Peripheral.h | 6 +- ports/nrf/common-hal/bleio/Service.c | 5 + ports/nrf/common-hal/bleio/Service.h | 2 + ports/nrf/common-hal/bleio/__init__.c | 369 +++++++++++++++++- ports/nrf/common-hal/bleio/__init__.h | 8 +- ports/nrf/nrfx_config.h | 1 + ports/nrf/peripherals/nrf/timers.c | 2 +- shared-bindings/bleio/Central.c | 77 ++-- shared-bindings/bleio/Central.h | 2 +- shared-bindings/bleio/Peripheral.c | 72 +++- shared-bindings/bleio/Peripheral.h | 2 +- shared-bindings/bleio/Service.c | 22 ++ shared-bindings/bleio/Service.h | 1 + shared-bindings/bleio/__init__.h | 11 + shared-module/bleio/__init__.h | 6 - 21 files changed, 568 insertions(+), 652 deletions(-) delete mode 100644 ports/nrf/boards/make-pins.py diff --git a/ports/nrf/boards/make-pins.py b/ports/nrf/boards/make-pins.py deleted file mode 100644 index d1cfd5b706..0000000000 --- a/ports/nrf/boards/make-pins.py +++ /dev/null @@ -1,208 +0,0 @@ -#!/usr/bin/env python -"""Creates the pin file for the nRF5.""" - -from __future__ import print_function - -import argparse -import sys -import csv - - -def parse_port_pin(name_str): - """Parses a string and returns a (port-num, pin-num) tuple.""" - if len(name_str) < 4: - raise ValueError("Expecting pin name to be at least 5 charcters.") - if name_str[0] != 'P': - raise ValueError("Expecting pin name to start with P") - if name_str[1] not in ('0', '1'): - raise ValueError("Expecting pin port to be in 0 or 1") - port = ord(name_str[1]) - ord('0') - pin_str = name_str[3:] - if not pin_str.isdigit(): - raise ValueError("Expecting numeric pin number.") - return (port, int(pin_str)) - - -class Pin(object): - """Holds the information associated with a pin.""" - - def __init__(self, port, pin): - self.port = port - self.pin = pin - self.adc_channel = '0' - self.board_pin = False - - def cpu_pin_name(self): - return 'P{:d}_{:02d}'.format(self.port, self.pin) - - def is_board_pin(self): - return self.board_pin - - def set_is_board_pin(self): - self.board_pin = True - - def parse_adc(self, adc_str): - if (adc_str[:3] != 'AIN'): - return - self.adc_channel = 'SAADC_CH_PSELP_PSELP_AnalogInput%d' % int(adc_str[3]) - - def print(self): - print('const pin_obj_t pin_{:s} = PIN({:s}, {:d}, {:d}, {:s});'.format( - self.cpu_pin_name(), self.cpu_pin_name(), - self.port, self.pin, self.adc_channel)) - - def print_header(self, hdr_file): - hdr_file.write('extern const pin_obj_t pin_{:s};\n'. - format(self.cpu_pin_name())) - - -class NamedPin(object): - - def __init__(self, name, pin): - self._name = name - self._pin = pin - - def pin(self): - return self._pin - - def name(self): - return self._name - - -class Pins(object): - - def __init__(self): - self.cpu_pins = [] # list of NamedPin objects - self.board_pins = [] # list of NamedPin objects - - def find_pin(self, port_num, pin_num): - for named_pin in self.cpu_pins: - pin = named_pin.pin() - if pin.port == port_num and pin.pin == pin_num: - return pin - - def parse_af_file(self, filename): - with open(filename, 'r') as csvfile: - rows = csv.reader(csvfile) - for row in rows: - try: - (port_num, pin_num) = parse_port_pin(row[0]) - except: - continue - pin = Pin(port_num, pin_num) - if len(row) > 1: - pin.parse_adc(row[1]) - self.cpu_pins.append(NamedPin(pin.cpu_pin_name(), pin)) - - def parse_board_file(self, filename): - with open(filename, 'r') as csvfile: - rows = csv.reader(csvfile) - for row in rows: - try: - (port_num, pin_num) = parse_port_pin(row[1]) - except: - continue - pin = self.find_pin(port_num, pin_num) - if pin: - pin.set_is_board_pin() - self.board_pins.append(NamedPin(row[0], pin)) - - def print_named(self, label, named_pins): - print('') - print('STATIC const mp_rom_map_elem_t {:s}_table[] = {{'.format(label)) - for named_pin in named_pins: - pin = named_pin.pin() - if pin.is_board_pin(): - print(' {{ MP_ROM_QSTR(MP_QSTR_{:s}), MP_ROM_PTR(&pin_{:s}) }},'.format(named_pin.name(), pin.cpu_pin_name())) - print('};') - print('MP_DEFINE_CONST_DICT({:s}, {:s}_table);'.format(label, label)) - - def print(self): - for named_pin in self.cpu_pins: - pin = named_pin.pin() - if pin.is_board_pin(): - pin.print() - self.print_named('mcu_pin_globals', self.cpu_pins) - self.print_named('board_module_globals', self.board_pins) - - def print_header(self, hdr_filename): - with open(hdr_filename, 'wt') as hdr_file: - for named_pin in self.cpu_pins: - pin = named_pin.pin() - if pin.is_board_pin(): - pin.print_header(hdr_file) - - def print_qstr(self, qstr_filename): - with open(qstr_filename, 'wt') as qstr_file: - qstr_set = set([]) - for named_pin in self.cpu_pins: - pin = named_pin.pin() - if pin.is_board_pin(): - qstr_set |= set([named_pin.name()]) - for named_pin in self.board_pins: - qstr_set |= set([named_pin.name()]) - for qstr in sorted(qstr_set): - print('Q({})'.format(qstr), file=qstr_file) - - -def main(): - parser = argparse.ArgumentParser( - prog="make-pins.py", - usage="%(prog)s [options] [command]", - description="Generate board specific pin file" - ) - parser.add_argument( - "-a", "--af", - dest="af_filename", - help="Specifies the alternate function file for the chip", - default="nrf_af.csv" - ) - parser.add_argument( - "-b", "--board", - dest="board_filename", - help="Specifies the board file", - ) - parser.add_argument( - "-p", "--prefix", - dest="prefix_filename", - help="Specifies beginning portion of generated pins file", - default="nrf52_prefix.c" - ) - parser.add_argument( - "-q", "--qstr", - dest="qstr_filename", - help="Specifies name of generated qstr header file", - default="build/pins_qstr.h" - ) - parser.add_argument( - "-r", "--hdr", - dest="hdr_filename", - help="Specifies name of generated pin header file", - default="build/pins.h" - ) - args = parser.parse_args(sys.argv[1:]) - - pins = Pins() - - print('// This file was automatically generated by make-pins.py') - print('//') - if args.af_filename: - print('// --af {:s}'.format(args.af_filename)) - pins.parse_af_file(args.af_filename) - - if args.board_filename: - print('// --board {:s}'.format(args.board_filename)) - pins.parse_board_file(args.board_filename) - - if args.prefix_filename: - print('// --prefix {:s}'.format(args.prefix_filename)) - print('') - with open(args.prefix_filename, 'r') as prefix_file: - print(prefix_file.read()) - pins.print() - pins.print_header(args.hdr_filename) - pins.print_qstr(args.qstr_filename) - - -if __name__ == "__main__": - main() diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c index d90737411f..c42a2084ac 100644 --- a/ports/nrf/common-hal/bleio/Central.c +++ b/ports/nrf/common-hal/bleio/Central.c @@ -35,216 +35,8 @@ #include "py/objstr.h" #include "py/runtime.h" #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; - -// service_uuid may be NULL, to discover all services. -STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle, ble_uuid_t *service_uuid) { - m_discovery_successful = false; - m_discovery_in_process = true; - - uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, service_uuid); - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg(translate("Failed to discover services")); - } - - // Wait for a discovery event. - while (m_discovery_in_process) { - MICROPY_VM_HOOK_LOOP; - } - return m_discovery_successful; -} - -STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_service_obj_t *service, uint16_t start_handle) { - m_char_discovery_service = service; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = service->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 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_descriptors_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]; - - 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->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; - - if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { - // Known service UUID. - 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_service->uuid); - service->uuid = uuid; - service->device = MP_OBJ_FROM_PTR(central); - } 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. - service->uuid = NULL; - } - - mp_obj_list_append(central->service_list, service); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - m_discovery_in_process = false; -} - -STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_central_obj_t *central) { - for (size_t i = 0; i < response->count; ++i) { - ble_gattc_char_t *gattc_char = &response->chars[i]; - - 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) { - // Known characteristic UUID. - 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); - } 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. - } - - 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 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; - - mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); - } - - if (response->count > 0) { - m_discovery_successful = true; - } - 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]; - - // 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; - - 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; -} +#include "common-hal/bleio/__init__.h" 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; @@ -262,20 +54,6 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { case BLE_GAP_EVT_DISCONNECTED: central->conn_handle = BLE_CONN_HANDLE_INVALID; - m_discovery_successful = false; - m_discovery_in_process = false; - break; - - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, central); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - 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); break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: @@ -288,7 +66,6 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { 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); @@ -299,12 +76,11 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) { void common_hal_bleio_central_construct(bleio_central_obj_t *self) { common_hal_bleio_adapter_set_enabled(true); - self->service_list = mp_obj_new_list(0, NULL); - self->gatt_role = GATT_ROLE_CLIENT; + self->remote_services_list = mp_obj_new_list(0, NULL); self->conn_handle = BLE_CONN_HANDLE_INVALID; } -void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids) { +void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout) { common_hal_bleio_adapter_set_enabled(true); ble_drv_add_event_handler(central_on_ble_evt, self); @@ -345,109 +121,6 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o if (self->conn_handle == BLE_CONN_HANDLE_INVALID) { mp_raise_OSError_msg(translate("Failed to connect: timeout")); } - - // Connection successful. - // Now discover services on the remote peripheral. - - if (service_uuids == mp_const_none) { - - // List of service UUID's not given, so discover all available services. - - 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. - - // 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; - mp_obj_t iterable = mp_getiter(service_uuids, &iter_buf); - mp_obj_t uuid_obj; - while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { - if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { - mp_raise_ValueError(translate("non-UUID found in service_uuids")); - } - bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); - - ble_uuid_t nrf_uuid; - bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); - - // Service might or might not be discovered; that's ok. Caller has to check - // Central.remote_services to find out. - // We only need to call this once for each service to discover. - discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid); - } - } - - - 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_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. - // 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)) { - - - // 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 = - 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. - 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 == char_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 - 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 && - 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. - 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; - } - } - - } } void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) { @@ -459,5 +132,5 @@ bool common_hal_bleio_central_get_connected(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; + return self->remote_services_list; } diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/bleio/Central.h index ac16700888..8b0d811bd5 100644 --- a/ports/nrf/common-hal/bleio/Central.h +++ b/ports/nrf/common-hal/bleio/Central.h @@ -36,10 +36,10 @@ typedef struct { mp_obj_base_t base; - gatt_role_t gatt_role; volatile bool waiting_to_connect; volatile uint16_t conn_handle; - mp_obj_list_t *service_list; + // Services discovered after connecting to a remote peripheral. + mp_obj_list_t *remote_services_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 17417a5e64..e9f0225cf4 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -33,8 +33,10 @@ #include "nrf_soc.h" #include "py/runtime.h" -#include "common-hal/bleio/__init__.h" -#include "common-hal/bleio/Characteristic.h" + +#include "shared-bindings/bleio/__init__.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Service.h" STATIC volatile bleio_characteristic_obj_t *m_read_characteristic; @@ -225,53 +227,39 @@ mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_charact } mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { - switch (common_hal_bleio_device_get_gatt_role(self->service->device)) { - case GATT_ROLE_CLIENT: + if (common_hal_bleio_service_get_is_remote(self->service)) { gattc_read(self); - break; - - case GATT_ROLE_SERVER: + } else { gatts_read(self); - break; - - default: - mp_raise_RuntimeError(translate("bad GATT role")); - break; } return self->value_data; } void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { - bool sent = false; - uint16_t cccd = 0; - - switch (common_hal_bleio_device_get_gatt_role(self->service->device)) { - case GATT_ROLE_SERVER: - if (self->props.notify || self->props.indicate) { - cccd = get_cccd(self); - } - // It's possible that both notify and indicate are set. - if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { - gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION); - sent = true; - } - if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) { - gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION); - sent = true; - } - if (!sent) { - gatts_write(self, bufinfo); - } - break; - - case GATT_ROLE_CLIENT: + if (common_hal_bleio_service_get_is_remote(self->service)) { gattc_write(self, bufinfo); - break; + } else { + bool sent = false; + uint16_t cccd = 0; - default: - mp_raise_RuntimeError(translate("bad GATT role")); - break; + if (self->props.notify || self->props.indicate) { + cccd = get_cccd(self); + } + + // It's possible that both notify and indicate are set. + if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { + gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION); + sent = true; + } + if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) { + gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION); + sent = true; + } + + if (!sent) { + gatts_write(self, bufinfo); + } } } @@ -289,8 +277,8 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, 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")); + if (!common_hal_bleio_service_get_is_remote(self->service)) { + mp_raise_ValueError(translate("Can't set CCCD on local Characteristic")); } uint16_t cccd_value = diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c index 59eaaf02b9..a6d834d7d8 100644 --- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c +++ b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c @@ -37,7 +37,7 @@ #include "tick.h" -#include "common-hal/bleio/__init__.h" +#include "shared-bindings/bleio/__init__.h" #include "common-hal/bleio/CharacteristicBuffer.h" STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) { diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index 608bd1342b..9300005345 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -120,20 +120,21 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { } } -void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name) { +void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *services_list, mp_obj_t name) { common_hal_bleio_adapter_set_enabled(true); - self->service_list = service_list; + self->services_list = services_list; + // Used only for discovery when acting as a client. + self->remote_services_list = mp_obj_new_list(0, NULL); self->name = name; - self->gatt_role = GATT_ROLE_SERVER; self->conn_handle = BLE_CONN_HANDLE_INVALID; self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; // Add all the services. - 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]); + for (size_t service_idx = 0; service_idx < services_list->len; ++service_idx) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(services_list->items[service_idx]); service->device = MP_OBJ_FROM_PTR(self); @@ -156,8 +157,8 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_ } -mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self) { - return self->service_list; +mp_obj_list_t *common_hal_bleio_peripheral_get_services_list(bleio_peripheral_obj_t *self) { + return self->services_list; } bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) { diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h index 2a12517159..3127a527f9 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.h +++ b/ports/nrf/common-hal/bleio/Peripheral.h @@ -41,9 +41,11 @@ typedef struct { mp_obj_base_t base; mp_obj_t name; - gatt_role_t gatt_role; volatile uint16_t conn_handle; - mp_obj_list_t *service_list; + // Services provided by this peripheral. + mp_obj_list_t *services_list; + // Remote services discovered when this peripheral is acting as a client. + mp_obj_list_t *remote_services_list; // 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 b6fcde8277..02c2ac1f9a 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -39,6 +39,7 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob self->handle = 0xFFFF; self->uuid = uuid; self->characteristic_list = characteristic_list; + self->is_remote = false; self->is_secondary = is_secondary; for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) { @@ -57,6 +58,10 @@ mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_ob return self->characteristic_list; } +bool common_hal_bleio_service_get_is_remote(bleio_service_obj_t *self) { + return self->is_remote; +} + bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) { return self->is_secondary; } diff --git a/ports/nrf/common-hal/bleio/Service.h b/ports/nrf/common-hal/bleio/Service.h index 583593fb80..03ac2bca80 100644 --- a/ports/nrf/common-hal/bleio/Service.h +++ b/ports/nrf/common-hal/bleio/Service.h @@ -35,6 +35,8 @@ typedef struct { mp_obj_base_t base; // Handle for this service. uint16_t handle; + // True if created during discovery. + bool is_remote; bool is_secondary; bleio_uuid_obj_t *uuid; // May be a Peripheral, Central, etc. diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index 2dba5780c1..a24898b0a4 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -26,12 +26,24 @@ * THE SOFTWARE. */ +#include "py/runtime.h" #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Central.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Peripheral.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/UUID.h" + #include "common-hal/bleio/__init__.h" +static volatile bool m_discovery_in_process; +static volatile bool m_discovery_successful; + +static bleio_service_obj_t *m_char_discovery_service; +static bleio_characteristic_obj_t *m_desc_discovery_characteristic; + // Turn off BLE on a reset or reload. void bleio_reset() { if (common_hal_bleio_adapter_get_enabled()) { @@ -47,16 +59,6 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = { }, }; -gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) { - if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { - return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role; - } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { - return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role; - } else { - return GATT_ROLE_NONE; - } -} - uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; @@ -66,3 +68,350 @@ uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { return 0; } } + +mp_obj_list_t *common_hal_bleio_device_get_remote_services_list(mp_obj_t device) { + if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { + return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->remote_services_list; + } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { + return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->remote_services_list; + } else { + return NULL; + } +} + +// service_uuid may be NULL, to discover all services. +STATIC bool discover_next_services(mp_obj_t device, uint16_t start_handle, ble_uuid_t *service_uuid) { + m_discovery_successful = false; + m_discovery_in_process = true; + + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); + uint32_t err_code = sd_ble_gattc_primary_services_discover(conn_handle, start_handle, service_uuid); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg(translate("Failed to discover services")); + } + + // Wait for a discovery event. + while (m_discovery_in_process) { + MICROPY_VM_HOOK_LOOP; + } + return m_discovery_successful; +} + +STATIC bool discover_next_characteristics(mp_obj_t device, bleio_service_obj_t *service, uint16_t start_handle) { + m_char_discovery_service = service; + + ble_gattc_handle_range_t handle_range; + handle_range.start_handle = start_handle; + handle_range.end_handle = service->end_handle; + + m_discovery_successful = false; + m_discovery_in_process = true; + + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); + uint32_t err_code = sd_ble_gattc_characteristics_discover(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 bool discover_next_descriptors(mp_obj_t device, 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; + + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(device); + uint32_t err_code = sd_ble_gattc_descriptors_discover(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, mp_obj_t device) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_service_t *gattc_service = &response->services[i]; + + 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 = device; + service->is_remote = true; + 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; + + if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) { + // Known service UUID. + 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_service->uuid); + service->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. + service->uuid = NULL; + } + + mp_obj_list_append(common_hal_bleio_device_get_remote_services_list(device), service); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_obj_t device) { + for (size_t i = 0; i < response->count; ++i) { + ble_gattc_char_t *gattc_char = &response->chars[i]; + + 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) { + // Known characteristic UUID. + 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); + } 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. + } + + 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 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; + + mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + m_discovery_in_process = false; +} + +STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_obj_t device) { + 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; + + 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 discovery_on_ble_evt(ble_evt_t *ble_evt, mp_obj_t device) { + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_DISCONNECTED: + m_discovery_successful = false; + m_discovery_in_process = false; + break; + + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, device); + break; + + case BLE_GATTC_EVT_CHAR_DISC_RSP: + on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, device); + break; + + case BLE_GATTC_EVT_DESC_DISC_RSP: + on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, device); + break; + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled discovery event: 0x%04x\n", ble_evt->header.evt_id); + break; + } +} + + +void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist) { + mp_obj_list_t *remote_services_list = common_hal_bleio_device_get_remote_services_list(device); + + ble_drv_add_event_handler(discovery_on_ble_evt, device); + + if (service_uuids_whitelist == mp_const_none) { + // List of service UUID's not given, so discover all available services. + + uint16_t next_service_start_handle = BLE_GATT_HANDLE_START; + + while (discover_next_services(device, next_service_start_handle, MP_OBJ_NULL)) { + // discover_next_services() appends to remote_services_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(remote_services_list->items[remote_services_list->len - 1]); + next_service_start_handle = service->end_handle + 1; + } + } else { + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(service_uuids_whitelist, &iter_buf); + mp_obj_t uuid_obj; + while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) { + mp_raise_ValueError(translate("non-UUID found in service_uuids_whitelist")); + } + bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); + + ble_uuid_t nrf_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid); + + // Service might or might not be discovered; that's ok. Caller has to check + // Central.remote_services to find out. + // We only need to call this once for each service to discover. + discover_next_services(device, BLE_GATT_HANDLE_START, &nrf_uuid); + } + } + + + for (size_t service_idx = 0; service_idx < remote_services_list->len; ++service_idx) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(remote_services_list->items[service_idx]); + + // Skip the service if it had an unknown (unregistered) UUID. + if (service->uuid == NULL) { + continue; + } + + 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. + // discover_next_characteristics() appends to the characteristic_list. + while (next_char_start_handle <= service->end_handle && + discover_next_characteristics(device, service, next_char_start_handle)) { + + + // 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 = + 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. + 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 == char_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 - 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 && + next_desc_start_handle < next_desc_end_handle && + discover_next_descriptors(device, 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; + } + } + } + + // This event handler is no longer needed. + ble_drv_remove_event_handler(discovery_on_ble_evt, device); + +} diff --git a/ports/nrf/common-hal/bleio/__init__.h b/ports/nrf/common-hal/bleio/__init__.h index 0c46b631fc..c0bba37994 100644 --- a/ports/nrf/common-hal/bleio/__init__.h +++ b/ports/nrf/common-hal/bleio/__init__.h @@ -27,16 +27,10 @@ #ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H -#include "shared-bindings/bleio/__init__.h" -#include "shared-bindings/bleio/Adapter.h" - -#include "shared-module/bleio/__init__.h" +void bleio_reset(void); // We assume variable length data. // 20 bytes max (23 - 3). #define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) -gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device); -uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); - #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H diff --git a/ports/nrf/nrfx_config.h b/ports/nrf/nrfx_config.h index a2b48065dd..8fa6721e2c 100644 --- a/ports/nrf/nrfx_config.h +++ b/ports/nrf/nrfx_config.h @@ -78,6 +78,7 @@ // TIMERS #define NRFX_TIMER_ENABLED 1 // Don't enable TIMER0: it's used by the SoftDevice. +#define NRFX_TIMER0_ENABLED 0 #define NRFX_TIMER1_ENABLED 1 #define NRFX_TIMER2_ENABLED 1 diff --git a/ports/nrf/peripherals/nrf/timers.c b/ports/nrf/peripherals/nrf/timers.c index 7f7a003d3b..88f3dd4681 100644 --- a/ports/nrf/peripherals/nrf/timers.c +++ b/ports/nrf/peripherals/nrf/timers.c @@ -36,7 +36,7 @@ STATIC nrfx_timer_t nrfx_timers[] = { #if NRFX_CHECK(NRFX_TIMER0_ENABLED) - // Note that TIMER0 is reserved for use by the SoftDevice, so it should not usually be enabled. + #error NRFX_TIMER0_ENABLED should not be on: TIMER0 is used by the SoftDevice NRFX_TIMER_INSTANCE(0), #endif #if NRFX_CHECK(NRFX_TIMER1_ENABLED) diff --git a/shared-bindings/bleio/Central.c b/shared-bindings/bleio/Central.c index fc00bce5cc..70b270c65f 100644 --- a/shared-bindings/bleio/Central.c +++ b/shared-bindings/bleio/Central.c @@ -34,6 +34,7 @@ #include "py/objproperty.h" #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Address.h" #include "shared-bindings/bleio/Characteristic.h" @@ -56,12 +57,16 @@ //| //| my_entry = None //| for entry in entries: -//| if entry.name is not None and entry.name == 'MyPeripheral': +//| if entry.name is not None and entry.name == 'InterestingPeripheral': //| my_entry = entry //| break //| -//| central = bleio.Central(my_entry.address) -//| central.connect(10.0) # timeout after 10 seconds +//| if not my_entry: +//| raise Exception("'InterestingPeripheral' not found") +//| +//| central = bleio.Central() +//| central.connect(my_entry.address, 10) # timeout after 10 seconds +//| central.discover_remote_services() //| //| .. class:: Central() @@ -79,24 +84,11 @@ STATIC mp_obj_t bleio_central_make_new(const mp_obj_type_t *type, size_t n_args, return MP_OBJ_FROM_PTR(self); } -//| .. method:: connect(address, timeout, *, service_uuids=None) -//| Attempts a connection to the remote peripheral. If the connection is successful, -//| Do BLE discovery for the listed services, to find their handles and characteristics. -//| The attribute `remote_services` will contain a list of all discovered services. +//| .. method:: connect(address, timeout, *, service_uuids_whitelist=None) +//| Attempts a connection to the remote peripheral. //| //| :param bleio.Address address: The address of the peripheral to connect to //| :param float/int timeout: Try to connect for timeout seconds. -//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services -//| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored. -//| If a service in service_uuids is not found during discovery, it will not -//| appear in `remote_services`. -//| -//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. -//| -//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you -//| you must have already created a :py:class:~`UUID` object for that UUID in order for the -//| service or characteristic to be discovered. (This restriction may be lifted in the future.) //| STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -105,7 +97,6 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args static const mp_arg_t allowed_args[] = { { MP_QSTR_address, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_timeout, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_service_uuids_whitelist, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -119,7 +110,7 @@ STATIC mp_obj_t bleio_central_connect(mp_uint_t n_args, const mp_obj_t *pos_args mp_float_t timeout = mp_obj_get_float(args[ARG_timeout].u_obj); // common_hal_bleio_central_connect() will validate that services is an iterable or None. - common_hal_bleio_central_connect(self, address, timeout, args[ARG_service_uuids_whitelist].u_obj); + common_hal_bleio_central_connect(self, address, timeout); return mp_const_none; } @@ -139,6 +130,47 @@ STATIC mp_obj_t bleio_central_disconnect(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_disconnect); +//| .. method:: discover_remote_services(service_uuids_whitelist=None) +//| Do BLE discovery for all services or for the given service UUIDS, +//| to find their handles and characteristics. +//| The attribute `remote_services` will contain a list of all discovered services. +//| `Central.connected` must be True. +//| +//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services +//| provided by the peripheral that you want to use. +//| The peripheral may provide more services, but services not listed are ignored. +//| If a service in service_uuids_whitelist is not found during discovery, it will not +//| appear in `remote_services`. +//| +//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. +//| +//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you +//| you must have already created a :py:class:~`UUID` object for that UUID in order for the +//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered +//| for use. (This restriction may be lifted in the future.) +//| +STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_service_uuids_whitelist }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + 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); + + if (!common_hal_bleio_central_get_connected(self)) { + mp_raise_ValueError(translate("Not connected")); + } + + common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), + args[ARG_service_uuids_whitelist].u_obj); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services); + //| .. attribute:: connected //| //| True if connected to a remove peripheral. @@ -181,8 +213,9 @@ const mp_obj_property_t bleio_central_remote_services_obj = { STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = { // Methods - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_central_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_central_discover_remote_services_obj) }, // Properties { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) }, diff --git a/shared-bindings/bleio/Central.h b/shared-bindings/bleio/Central.h index 0e84037f91..1d7fb62483 100644 --- a/shared-bindings/bleio/Central.h +++ b/shared-bindings/bleio/Central.h @@ -34,7 +34,7 @@ extern const mp_obj_type_t bleio_central_type; extern void common_hal_bleio_central_construct(bleio_central_obj_t *self); -extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids); +extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout); extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self); extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self); extern mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self); diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index 1302c96523..69bc72d92d 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -35,6 +35,7 @@ #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Peripheral.h" @@ -107,15 +108,15 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar self->base.type = &bleio_peripheral_type; // Copy the services list and validate its items. - mp_obj_t service_list_obj = mp_obj_new_list(0, NULL); - mp_obj_list_t *service_list = MP_OBJ_FROM_PTR(service_list_obj); + mp_obj_t services_list_obj = mp_obj_new_list(0, NULL); + mp_obj_list_t *services_list = MP_OBJ_FROM_PTR(services_list_obj); mp_obj_t service; while ((service = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { if (!MP_OBJ_IS_TYPE(service, &bleio_service_type)) { mp_raise_ValueError(translate("non-Service found in services")); } - mp_obj_list_append(service_list, service); + mp_obj_list_append(services_list, service); } const mp_obj_t name = args[ARG_name].u_obj; @@ -128,7 +129,7 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar mp_raise_ValueError(translate("name must be a string")); } - common_hal_bleio_peripheral_construct(self, service_list, name_str); + common_hal_bleio_peripheral_construct(self, services_list, name_str); return MP_OBJ_FROM_PTR(self); } @@ -158,8 +159,8 @@ const mp_obj_property_t bleio_peripheral_connected_obj = { STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) { bleio_peripheral_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 *service_list = common_hal_bleio_peripheral_get_service_list(self); - return mp_obj_new_tuple(service_list->len, service_list->items); + mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services_list(self); + return mp_obj_new_tuple(services_list->len, services_list->items); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services); @@ -265,16 +266,63 @@ STATIC mp_obj_t bleio_peripheral_disconnect(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripheral_disconnect); +//| .. method:: discover_remote_services(service_uuids_whitelist=None) +//| Do BLE discovery for all services or for the given service UUIDS, +//| to find their handles and characteristics. +//| The attribute `remote_services` will contain a list of all discovered services. +//| `Peripheral.connected` must be True. +//| +//| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services +//| provided by the peripheral that you want to use. +//| The peripheral may provide more services, but services not listed are ignored. +//| If a service in service_uuids_whitelist is not found during discovery, it will not +//| appear in `remote_services`. +//| +//| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. +//| +//| If the service UUID is 128-bit, or its characteristic UUID's are 128-bit, you +//| you must have already created a :py:class:~`UUID` object for that UUID in order for the +//| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered +//| for use. (This restriction may be lifted in the future.) +//| +//| Thought it is unusual for a peripheral to act as a BLE client, it can do so, and +//| needs to be able to do discovery on its peer (a central). +//| Examples include a peripheral accessing a central that provides Current Time Service, +//| Apple Notification Center Service, or Battery Service. +//| +STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + enum { ARG_service_uuids_whitelist }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_service_uuids_whitelist, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + 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); + + if (!common_hal_bleio_peripheral_get_connected(self)) { + mp_raise_ValueError(translate("Not connected")); + } + + common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), + args[ARG_service_uuids_whitelist].u_obj); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services); + STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { // Methods - { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, - { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table); diff --git a/shared-bindings/bleio/Peripheral.h b/shared-bindings/bleio/Peripheral.h index 846250a5fc..7dad0bccd1 100644 --- a/shared-bindings/bleio/Peripheral.h +++ b/shared-bindings/bleio/Peripheral.h @@ -33,7 +33,7 @@ extern const mp_obj_type_t bleio_peripheral_type; extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name); -extern mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self); +extern mp_obj_list_t *common_hal_bleio_peripheral_get_services_list(bleio_peripheral_obj_t *self); extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self); extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self); extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index db06069913..b4aeab2bd2 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -43,12 +43,16 @@ //| .. 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`. //| //| :param bleio.UUID uuid: The uuid of the service //| :param iterable characteristics: the Characteristic objects for this service //| :param bool secondary: If the service is a secondary one //| +//| A Service may be remote (:py:data:`remote` is ``True``), but a remote Service +//| cannot be constructed directly. It is created by `Central.discover_remote_services()` +//| or `Peripheral.discover_remote_services()`. STATIC mp_obj_t bleio_service_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_uuid, ARG_characteristics, ARG_secondary }; @@ -119,6 +123,24 @@ const mp_obj_property_t bleio_service_characteristics_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: remote +//| +//| True if this is a service provided by a remote device. (read-only) +//| +STATIC mp_obj_t bleio_service_get_remote(mp_obj_t self_in) { + bleio_service_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return mp_obj_new_bool(common_hal_bleio_service_get_is_remote(self)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_service_get_remote_obj, bleio_service_get_remote); + +const mp_obj_property_t bleio_service_remote_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_service_get_remote_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + //| .. attribute:: secondary //| //| True if this is a secondary service. (read-only) diff --git a/shared-bindings/bleio/Service.h b/shared-bindings/bleio/Service.h index f646c81a9b..716c2e8a96 100644 --- a/shared-bindings/bleio/Service.h +++ b/shared-bindings/bleio/Service.h @@ -35,6 +35,7 @@ const mp_obj_type_t bleio_service_type; extern void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, mp_obj_list_t *characteristic_list, bool is_secondary); 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_remote(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_add_all_characteristics(bleio_service_obj_t *self); diff --git a/shared-bindings/bleio/__init__.h b/shared-bindings/bleio/__init__.h index 4aa6dd45b7..dd6e552046 100644 --- a/shared-bindings/bleio/__init__.h +++ b/shared-bindings/bleio/__init__.h @@ -29,8 +29,19 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H +#include "py/objlist.h" + +#include "shared-bindings/bleio/__init__.h" +#include "shared-bindings/bleio/Adapter.h" + +#include "shared-module/bleio/__init__.h" #include "common-hal/bleio/Adapter.h" extern const super_adapter_obj_t common_hal_bleio_adapter_obj; +extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); +extern mp_obj_list_t *common_hal_bleio_device_get_remote_services_list(mp_obj_t device); +extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); + + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H diff --git a/shared-module/bleio/__init__.h b/shared-module/bleio/__init__.h index 07d1485946..f8f0e06606 100644 --- a/shared-module/bleio/__init__.h +++ b/shared-module/bleio/__init__.h @@ -27,12 +27,6 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H -typedef enum { - GATT_ROLE_NONE, - GATT_ROLE_SERVER, - GATT_ROLE_CLIENT, -} gatt_role_t; - extern void bleio_reset(void); #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H From 83129b8c63e58596add0d111360701aab51ce62b Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 30 Jul 2019 14:26:26 -0400 Subject: [PATCH 2/9] BLE: peripheral client pairing (not yet bonding); fix time doc formatting --- ports/nrf/common-hal/bleio/Characteristic.c | 2 +- ports/nrf/common-hal/bleio/Peripheral.c | 89 +++++++++++++++++++-- ports/nrf/common-hal/bleio/Peripheral.h | 8 +- shared-bindings/bleio/Peripheral.c | 44 +++++++++- shared-bindings/bleio/Peripheral.h | 4 +- shared-bindings/time/__init__.c | 21 ++--- 6 files changed, 146 insertions(+), 22 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index e9f0225cf4..b318ae81c6 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -203,8 +203,8 @@ STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) { break; } - // For debugging. default: + // For debugging. // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); break; } diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index 9300005345..c45041ad04 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -52,6 +52,19 @@ #define BLE_ADV_AD_TYPE_FIELD_SIZE 1 #define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 +static const ble_gap_sec_params_t pairing_sec_params = { + .bond = 0, // TODO: add bonding + .mitm = 0, + .lesc = 0, + .keypress = 0, + .oob = 0, + .io_caps = BLE_GAP_IO_CAPS_NONE, + .min_key_size = 7, + .max_key_size = 16, + .kdist_own = { .enc = 1, .id = 1}, + .kdist_peer = { .enc = 1, .id = 1}, +}; + STATIC void check_data_fit(size_t data_len) { if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) { mp_raise_ValueError(translate("Data too large for advertisement packet")); @@ -61,6 +74,9 @@ STATIC void check_data_fit(size_t data_len) { STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in; + // For debugging. + // mp_printf(&mp_plat_print, "Peripheral event: 0x%04x\n", ble_evt->header.evt_id); + switch (ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { // Central has connected. @@ -89,10 +105,6 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // Someday may handle timeouts or limit reached. break; - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL); - break; - 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; @@ -113,6 +125,50 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0); break; + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, &pairing_sec_params, NULL); + break; + + case BLE_GAP_EVT_LESC_DHKEY_REQUEST: + // TODO for LESC pairing: + // sd_ble_gap_lesc_dhkey_reply(...); + break; + + case BLE_GAP_EVT_AUTH_STATUS: { + // Pairing process completed + ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; + if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { + mp_printf(&mp_plat_print, "Pairing succeeded, status: 0x%04x\n", status->auth_status); + self->pair_status = PAIR_PAIRED; + } else { + mp_printf(&mp_plat_print, "Pairing failed, status: 0x%04x\n", status->auth_status); + self->pair_status = PAIR_NOT_PAIRED; + } + break; + } + + case BLE_GAP_EVT_CONN_SEC_UPDATE: { + ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; + mp_printf(&mp_plat_print, "sm: %d, lv: %d\n", conn_sec->sec_mode.sm, conn_sec->sec_mode.lv); + if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { + // Security setup did not succeed: + // mode 0, level 0 means no access + // mode 1, level 1 means open link + // mode >=1 and/or level >=1 means encryption is set up + self->pair_status = PAIR_NOT_PAIRED; + mp_printf(&mp_plat_print, "PAIR_NOT_PAIRED\n"); + } else { + // TODO: see Bluefruit lib + // if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { + // sd_ble_gatts_sys_attr_set(_conn_hdl, NULL, 0, 0); + // } + self->pair_status = PAIR_PAIRED; + mp_printf(&mp_plat_print, "PAIR_PAIRED\n"); + } + break; + } + + default: // For debugging. // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id); @@ -130,6 +186,7 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_ self->conn_handle = BLE_CONN_HANDLE_INVALID; self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + self->pair_status = PAIR_NOT_PAIRED; // Add all the services. @@ -157,7 +214,7 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_ } -mp_obj_list_t *common_hal_bleio_peripheral_get_services_list(bleio_peripheral_obj_t *self) { +mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self) { return self->services_list; } @@ -248,3 +305,25 @@ void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) { sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); } + +mp_obj_list_t *common_hal_bleio_peripheral_get_remote_services(bleio_peripheral_obj_t *self) { + return self->remote_services_list; +} + +void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) { + self->pair_status = PAIR_WAITING; + + uint32_t err_code = sd_ble_gap_authenticate(self->conn_handle, &pairing_sec_params); + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to start pairing, error 0x%04x"), err_code); + } + + while (self->pair_status == PAIR_WAITING) { + MICROPY_VM_HOOK_LOOP; + } + + if (self->pair_status == PAIR_NOT_PAIRED) { + mp_raise_OSError_msg(translate("Failed to pair")); + } +} diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h index 3127a527f9..e4a664b01f 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.h +++ b/ports/nrf/common-hal/bleio/Peripheral.h @@ -38,6 +38,12 @@ #include "shared-module/bleio/__init__.h" #include "shared-module/bleio/Address.h" +typedef enum { + PAIR_NOT_PAIRED, + PAIR_WAITING, + PAIR_PAIRED, +} pair_status_t; + typedef struct { mp_obj_base_t base; mp_obj_t name; @@ -52,7 +58,7 @@ typedef struct { uint8_t* advertising_data; uint8_t* scan_response_data; uint8_t adv_handle; - + pair_status_t pair_status; } bleio_peripheral_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index 69bc72d92d..981ea2246a 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -159,7 +159,7 @@ const mp_obj_property_t bleio_peripheral_connected_obj = { STATIC mp_obj_t bleio_peripheral_get_services(mp_obj_t self_in) { bleio_peripheral_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 *services_list = common_hal_bleio_peripheral_get_services_list(self); + mp_obj_list_t *services_list = common_hal_bleio_peripheral_get_services(self); return mp_obj_new_tuple(services_list->len, services_list->items); } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_services_obj, bleio_peripheral_get_services); @@ -312,17 +312,53 @@ STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, cons } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services); +//| .. attribute:: remote_services (read-only) +//| +//| A tuple of services provided by the remote central. +//| If discovery did not occur, an empty tuple will be returned. +//| +STATIC mp_obj_t bleio_peripheral_get_remote_services(mp_obj_t self_in) { + bleio_peripheral_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 *service_list = common_hal_bleio_peripheral_get_remote_services(self); + return mp_obj_new_tuple(service_list->len, service_list->items); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_remote_services_obj, bleio_peripheral_get_remote_services); + +//| .. method:: pair() +//| +//| Request pairing with connected central. +STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) { + bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_peripheral_pair(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair); + +const mp_obj_property_t bleio_peripheral_remote_services_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_peripheral_get_remote_services_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + + STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_peripheral_stop_advertising_obj) }, { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_peripheral_disconnect_obj) }, { MP_ROM_QSTR(MP_QSTR_discover_remote_services), MP_ROM_PTR(&bleio_peripheral_discover_remote_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_pair) , MP_ROM_PTR(&bleio_peripheral_pair_obj) }, // Properties - { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, - { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_remote_services), MP_ROM_PTR(&bleio_peripheral_remote_services_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_peripheral_locals_dict, bleio_peripheral_locals_dict_table); diff --git a/shared-bindings/bleio/Peripheral.h b/shared-bindings/bleio/Peripheral.h index 7dad0bccd1..d9b72b2c31 100644 --- a/shared-bindings/bleio/Peripheral.h +++ b/shared-bindings/bleio/Peripheral.h @@ -33,11 +33,13 @@ extern const mp_obj_type_t bleio_peripheral_type; extern void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name); -extern mp_obj_list_t *common_hal_bleio_peripheral_get_services_list(bleio_peripheral_obj_t *self); +extern mp_obj_list_t *common_hal_bleio_peripheral_get_services(bleio_peripheral_obj_t *self); extern bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self); extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self); extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device); extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device); +extern mp_obj_list_t *common_hal_bleio_peripheral_get_remote_services(bleio_peripheral_obj_t *self); +extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H diff --git a/shared-bindings/time/__init__.c b/shared-bindings/time/__init__.c index 70c01c2d83..f34cb9c466 100644 --- a/shared-bindings/time/__init__.c +++ b/shared-bindings/time/__init__.c @@ -99,16 +99,17 @@ mp_obj_t struct_time_make_new(const mp_obj_type_t *type, size_t n_args, const mp //| //| Structure used to capture a date and time. Note that it takes a tuple! //| -//| :param Tuple[tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst] time_tuple: Tuple of time info. -//| * the year, 2017 for example -//| * the month, range [1, 12] -//| * the day of the month, range [1, 31] -//| * the hour, range [0, 23] -//| * the minute, range [0, 59] -//| * the second, range [0, 61] -//| * the day of the week, range [0, 6], Monday is 0 -//| * the day of the year, range [1, 366], -1 indicates not known -//| * 1 when in daylight savings, 0 when not, -1 if unknown. +//| :param tuple time_tuple: Tuple of time info: ``(tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)`` +//| +//| * ``tm_year``: the year, 2017 for example +//| * ``tm_month``: the month, range [1, 12] +//| * ``tm_mday``: the day of the month, range [1, 31] +//| * ``tm_hour``: the hour, range [0, 23] +//| * ``tm_minute``: the minute, range [0, 59] +//| * ``tm_sec``: the second, range [0, 61] +//| * ``tm_wday``: the day of the week, range [0, 6], Monday is 0 +//| * ``tm_yday``: the day of the year, range [1, 366], -1 indicates not known +//| * ``tm_isdst``: 1 when in daylight savings, 0 when not, -1 if unknown. //| const mp_obj_namedtuple_type_t struct_time_type_obj = { .base = { From 91d791afd091ba38bb61689e88a7fc03b9679e00 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 31 Jul 2019 00:30:24 -0400 Subject: [PATCH 3/9] cleanup adapter.address; add uniquish suffix to BLE device name --- ports/nrf/common-hal/bleio/Adapter.c | 45 +++++++++++++++++++++------- py/objstr.c | 6 ++++ py/objstr.h | 3 ++ shared-bindings/bleio/Adapter.c | 36 +++++++++++++++------- shared-bindings/bleio/Adapter.h | 3 +- shared-bindings/bleio/Address.c | 17 ++++------- shared-bindings/bleio/Peripheral.c | 21 +++++-------- supervisor/shared/usb/usb.c | 5 ++-- 8 files changed, 86 insertions(+), 50 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c index 9d0912930b..936dfcb9b0 100644 --- a/ports/nrf/common-hal/bleio/Adapter.c +++ b/ports/nrf/common-hal/bleio/Adapter.c @@ -34,10 +34,11 @@ #include "nrfx_power.h" #include "nrf_nvic.h" #include "nrf_sdm.h" +#include "py/objstr.h" #include "py/runtime.h" -#include "shared-bindings/bleio/Adapter.h" - #include "supervisor/usb.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/Address.h" STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { mp_raise_msg_varg(&mp_type_AssertionError, @@ -132,20 +133,42 @@ bool common_hal_bleio_adapter_get_enabled(void) { return is_enabled; } -void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) { - ble_gap_addr_t local_address; +void get_address(ble_gap_addr_t *address) { uint32_t err_code; common_hal_bleio_adapter_set_enabled(true); - err_code = sd_ble_gap_addr_get(&local_address); + err_code = sd_ble_gap_addr_get(address); if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg(translate("Failed to get local address")); } - - address->type = local_address.addr_type; - - mp_buffer_info_t buf_info; - mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ); - memcpy(address->bytes, buf_info.buf, NUM_BLEIO_ADDRESS_BYTES); +} + +bleio_address_obj_t *common_hal_bleio_adapter_get_address(void) { + common_hal_bleio_adapter_set_enabled(true); + + ble_gap_addr_t local_address; + get_address(&local_address); + + bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t); + address->base.type = &bleio_address_type; + + common_hal_bleio_address_construct(address, local_address.addr, local_address.addr_type); + return address; +} + +mp_obj_t common_hal_bleio_adapter_get_default_name(void) { + common_hal_bleio_adapter_set_enabled(true); + + ble_gap_addr_t local_address; + get_address(&local_address); + + char name[] = { 'C', 'I', 'R', 'C', 'U', 'I', 'T', 'P', 'Y', 0, 0, 0, 0 }; + + name[sizeof(name) - 4] = nibble_to_hex_lower[local_address.addr[1] >> 4 & 0xf]; + name[sizeof(name) - 3] = nibble_to_hex_lower[local_address.addr[1] & 0xf]; + name[sizeof(name) - 2] = nibble_to_hex_lower[local_address.addr[0] >> 4 & 0xf]; + name[sizeof(name) - 1] = nibble_to_hex_lower[local_address.addr[0] & 0xf]; + + return mp_obj_new_str(name, sizeof(name)); } diff --git a/py/objstr.c b/py/objstr.c index ebd11d5cc2..afe11f00f8 100644 --- a/py/objstr.c +++ b/py/objstr.c @@ -41,6 +41,12 @@ STATIC mp_obj_t str_modulo_format(mp_obj_t pattern, size_t n_args, const mp_obj_ STATIC mp_obj_t mp_obj_new_bytes_iterator(mp_obj_t str, mp_obj_iter_buf_t *iter_buf); STATIC NORETURN void bad_implicit_conversion(mp_obj_t self_in); +const char nibble_to_hex_upper[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'A', 'B', 'C', 'D', 'E', 'F'}; + +const char nibble_to_hex_lower[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f'}; + /******************************************************************************/ /* str */ diff --git a/py/objstr.h b/py/objstr.h index 0efe62a801..61a11d0bd6 100644 --- a/py/objstr.h +++ b/py/objstr.h @@ -77,6 +77,9 @@ const byte *str_index_to_ptr(const mp_obj_type_t *type, const byte *self_data, s mp_obj_t index, bool is_slice); const byte *find_subbytes(const byte *haystack, size_t hlen, const byte *needle, size_t nlen, int direction); +const char nibble_to_hex_upper[16]; +const char nibble_to_hex_lower[16]; + MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_encode_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_find_obj); MP_DECLARE_CONST_FUN_OBJ_VAR_BETWEEN(str_rfind_obj); diff --git a/shared-bindings/bleio/Adapter.c b/shared-bindings/bleio/Adapter.c index 7b8df51034..2bb7f34653 100644 --- a/shared-bindings/bleio/Adapter.c +++ b/shared-bindings/bleio/Adapter.c @@ -53,12 +53,6 @@ //| //| State of the BLE adapter. //| - -//| .. attribute:: adapter.address -//| -//| MAC address of the BLE adapter. (read-only) -//| - STATIC mp_obj_t bleio_adapter_get_enabled(mp_obj_t self) { return mp_obj_new_bool(common_hal_bleio_adapter_get_enabled()); } @@ -80,13 +74,13 @@ const mp_obj_property_t bleio_adapter_enabled_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: adapter.address +//| +//| MAC address of the BLE adapter. (read-only) +//| STATIC mp_obj_t bleio_adapter_get_address(mp_obj_t self) { - mp_obj_t obj = bleio_address_type.make_new(&bleio_address_type, 1, 0, mp_const_none); - bleio_address_obj_t *address = MP_OBJ_TO_PTR(obj); + return MP_OBJ_FROM_PTR(common_hal_bleio_adapter_get_address()); - common_hal_bleio_adapter_get_address(address); - - return obj; } MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_address_obj, bleio_adapter_get_address); @@ -97,9 +91,29 @@ const mp_obj_property_t bleio_adapter_address_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: adapter.default_name +//| +//| default_name of the BLE adapter. (read-only) +//| The name is "CIRCUITPY" + the last four hex digits of ``adapter.address``, +//| to make it easy to distinguish multiple CircuitPython boards. +//| +STATIC mp_obj_t bleio_adapter_get_default_name(mp_obj_t self) { + return common_hal_bleio_adapter_get_default_name(); + +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_adapter_get_default_name_obj, bleio_adapter_get_default_name); + +const mp_obj_property_t bleio_adapter_default_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_adapter_get_default_name_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + STATIC const mp_rom_map_elem_t bleio_adapter_locals_dict_table[] = { { MP_ROM_QSTR(MP_QSTR_enabled), MP_ROM_PTR(&bleio_adapter_enabled_obj) }, { MP_ROM_QSTR(MP_QSTR_address), MP_ROM_PTR(&bleio_adapter_address_obj) }, + { MP_ROM_QSTR(MP_QSTR_default_name), MP_ROM_PTR(&bleio_adapter_default_name_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_adapter_locals_dict, bleio_adapter_locals_dict_table); diff --git a/shared-bindings/bleio/Adapter.h b/shared-bindings/bleio/Adapter.h index de9d1d6db1..72382616ca 100644 --- a/shared-bindings/bleio/Adapter.h +++ b/shared-bindings/bleio/Adapter.h @@ -34,6 +34,7 @@ const mp_obj_type_t bleio_adapter_type; extern bool common_hal_bleio_adapter_get_enabled(void); extern void common_hal_bleio_adapter_set_enabled(bool enabled); -extern void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address); +extern bleio_address_obj_t *common_hal_bleio_adapter_get_address(void); +extern mp_obj_t common_hal_bleio_adapter_get_default_name(void); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ADAPTER_H diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c index 37f01042ce..475fc9427d 100644 --- a/shared-bindings/bleio/Address.c +++ b/shared-bindings/bleio/Address.c @@ -147,18 +147,13 @@ STATIC mp_obj_t bleio_address_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_o STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { bleio_address_obj_t *self = MP_OBJ_TO_PTR(self_in); - if (kind == PRINT_STR) { - mp_buffer_info_t buf_info; - mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self); - mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ); + mp_buffer_info_t buf_info; + mp_obj_t address_bytes = common_hal_bleio_address_get_address_bytes(self); + mp_get_buffer_raise(address_bytes, &buf_info, MP_BUFFER_READ); - const uint8_t *buf = (uint8_t *) buf_info.buf; - mp_printf(print, - "%02x:%02x:%02x:%02x:%02x:%02x", - buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); - } else { - mp_printf(print, "
"); - } + const uint8_t *buf = (uint8_t *) buf_info.buf; + mp_printf(print, "
", + buf[5], buf[4], buf[3], buf[2], buf[1], buf[0]); } //| .. data:: PUBLIC diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index 981ea2246a..6cd077999c 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -45,8 +45,6 @@ #include "common-hal/bleio/Peripheral.h" -static const char default_name[] = "CIRCUITPY"; - #define ADV_INTERVAL_DEFAULT (1.0f) #define ADV_INTERVAL_MIN (0.0020f) #define ADV_INTERVAL_MIN_STRING "0.0020" @@ -81,14 +79,14 @@ static const char default_name[] = "CIRCUITPY"; //| # Wait for connection. //| pass //| -//| .. class:: Peripheral(services=(), \*, name='CIRCUITPY') +//| .. class:: Peripheral(services=(), \*, name=None) //| //| 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 +//| :param str name: The name used when advertising this peripheral. If name is None, +//| bleio.adapter.default_name will be used. //| 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 }; @@ -119,22 +117,19 @@ STATIC mp_obj_t bleio_peripheral_make_new(const mp_obj_type_t *type, size_t n_ar mp_obj_list_append(services_list, service); } - const mp_obj_t name = args[ARG_name].u_obj; - mp_obj_t name_str; + mp_obj_t name = args[ARG_name].u_obj; if (name == MP_OBJ_NULL || name == mp_const_none) { - name_str = mp_obj_new_str(default_name, strlen(default_name)); - } else if (MP_OBJ_IS_STR(name)) { - name_str = name; - } else { + name = common_hal_bleio_adapter_get_default_name(); + } else if (!MP_OBJ_IS_STR(name)) { mp_raise_ValueError(translate("name must be a string")); } - common_hal_bleio_peripheral_construct(self, services_list, name_str); + common_hal_bleio_peripheral_construct(self, services_list, name); return MP_OBJ_FROM_PTR(self); } -//| .. attribute:: connected +//| .. attribute:: connected (read-only) //| //| True if connected to a BLE Central device. //| diff --git a/supervisor/shared/usb/usb.c b/supervisor/shared/usb/usb.c index 0678a3a3fc..c1d70c5b0f 100644 --- a/supervisor/shared/usb/usb.c +++ b/supervisor/shared/usb/usb.c @@ -25,6 +25,7 @@ */ #include "tick.h" +#include "py/objstr.h" #include "shared-bindings/microcontroller/Processor.h" #include "shared-module/usb_midi/__init__.h" #include "supervisor/port.h" @@ -43,13 +44,11 @@ void load_serial_number(void) { uint8_t raw_id[COMMON_HAL_MCU_PROCESSOR_UID_LENGTH]; common_hal_mcu_processor_get_uid(raw_id); - static const char nibble_to_hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', - 'A', 'B', 'C', 'D', 'E', 'F'}; for (int i = 0; i < COMMON_HAL_MCU_PROCESSOR_UID_LENGTH; i++) { for (int j = 0; j < 2; j++) { uint8_t nibble = (raw_id[i] >> (j * 4)) & 0xf; // Strings are UTF-16-LE encoded. - usb_serial_number[1 + i * 2 + j] = nibble_to_hex[nibble]; + usb_serial_number[1 + i * 2 + j] = nibble_to_hex_upper[nibble]; } } } From 7ce3776b8086abbe0d01056651904a59bf4f8bec Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 2 Aug 2019 17:56:44 -0400 Subject: [PATCH 4/9] WIP: rework of Characteristic properties; enhance Descriptor; not tested --- ports/nrf/common-hal/bleio/Attribute.c | 60 +++++ .../nrf/common-hal/bleio/Attribute.h | 8 +- ports/nrf/common-hal/bleio/Central.h | 1 - ports/nrf/common-hal/bleio/Characteristic.c | 21 +- ports/nrf/common-hal/bleio/Characteristic.h | 6 +- ports/nrf/common-hal/bleio/Descriptor.c | 6 +- ports/nrf/common-hal/bleio/Descriptor.h | 7 +- ports/nrf/common-hal/bleio/Peripheral.c | 4 +- ports/nrf/common-hal/bleio/Peripheral.h | 1 - ports/nrf/common-hal/bleio/Service.c | 74 +++++-- ports/nrf/common-hal/bleio/__init__.c | 29 +-- py/circuitpy_defns.mk | 11 +- py/obj.h | 1 + py/objlist.c | 5 + shared-bindings/bleio/Address.c | 12 +- shared-bindings/bleio/Attribute.c | 93 ++++++++ shared-bindings/bleio/Attribute.h | 38 ++++ shared-bindings/bleio/Characteristic.c | 207 ++++++------------ shared-bindings/bleio/Characteristic.h | 3 +- shared-bindings/bleio/Descriptor.c | 90 ++------ shared-bindings/bleio/Descriptor.h | 21 +- shared-bindings/bleio/__init__.c | 38 ++-- shared-bindings/bleio/__init__.h | 1 - shared-module/bleio/Attribute.c | 46 ++++ shared-module/bleio/Attribute.h | 41 ++++ shared-module/bleio/Characteristic.h | 21 +- 26 files changed, 518 insertions(+), 327 deletions(-) create mode 100644 ports/nrf/common-hal/bleio/Attribute.c rename shared-module/bleio/__init__.h => ports/nrf/common-hal/bleio/Attribute.h (86%) create mode 100644 shared-bindings/bleio/Attribute.c create mode 100644 shared-bindings/bleio/Attribute.h create mode 100644 shared-module/bleio/Attribute.c create mode 100644 shared-module/bleio/Attribute.h diff --git a/ports/nrf/common-hal/bleio/Attribute.c b/ports/nrf/common-hal/bleio/Attribute.c new file mode 100644 index 0000000000..bffe682549 --- /dev/null +++ b/ports/nrf/common-hal/bleio/Attribute.c @@ -0,0 +1,60 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * 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. + */ + +#include "shared-bindings/bleio/Attribute.h" + +// Convert a bleio security mode to a ble_gap_conn_sec_mode_t setting. +void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) { + switch (security_mode) { + case SEC_MODE_NO_ACCESS: + BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm); + break; + + case SEC_MODE_OPEN: + BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm); + break; + + case SEC_MODE_ENC_NO_MITM: + BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm); + break; + + case SEC_MODE_ENC_WITH_MITM: + BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm); + break; + + case SEC_MODE_LESC_ENC_WITH_MITM: + BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm); + break; + + case SEC_MODE_SIGNED_NO_MITM: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm); + break; + + case SEC_MODE_SIGNED_WITH_MITM: + BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm); + break; + } +} diff --git a/shared-module/bleio/__init__.h b/ports/nrf/common-hal/bleio/Attribute.h similarity index 86% rename from shared-module/bleio/__init__.h rename to ports/nrf/common-hal/bleio/Attribute.h index f8f0e06606..44c2fdfa17 100644 --- a/shared-module/bleio/__init__.h +++ b/ports/nrf/common-hal/bleio/Attribute.h @@ -24,9 +24,9 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H -#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H +#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H +#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H -extern void bleio_reset(void); +// Nothing yet. -#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_INIT_H +#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_ATTRIBUTE_H diff --git a/ports/nrf/common-hal/bleio/Central.h b/ports/nrf/common-hal/bleio/Central.h index 8b0d811bd5..b7a9050b86 100644 --- a/ports/nrf/common-hal/bleio/Central.h +++ b/ports/nrf/common-hal/bleio/Central.h @@ -31,7 +31,6 @@ #include #include "py/objlist.h" -#include "shared-module/bleio/__init__.h" #include "shared-module/bleio/Address.h" typedef struct { diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index b318ae81c6..41fcdd1f19 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -164,7 +164,8 @@ STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in check_connected(conn_handle); ble_gattc_write_params_t write_params = { - .write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ, + .write_op = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) + ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, .handle = characteristic->handle, .p_value = bufinfo->buf, .len = bufinfo->len, @@ -211,12 +212,14 @@ 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, mp_obj_list_t *descriptor_list) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t security_mode, mp_obj_t descriptors) { self->service = mp_const_none; self->uuid = uuid; self->value_data = mp_const_none; self->props = props; - self->descriptor_list = descriptor_list; + self->security_mode = security_mode; + self->descriptor_list = mp_obj_new_list_from_iter(descriptors); + self->handle = BLE_GATT_HANDLE_INVALID; ble_drv_add_event_handler(characteristic_on_ble_evt, self); @@ -238,21 +241,23 @@ mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *s void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { if (common_hal_bleio_service_get_is_remote(self->service)) { - gattc_write(self, bufinfo); + gattc_write(self, bufinfo); } else { bool sent = false; uint16_t cccd = 0; - if (self->props.notify || self->props.indicate) { - cccd = get_cccd(self); + const bool notify = self->props & CHAR_PROP_NOTIFY; + const bool indicate = self->props & CHAR_PROP_INDICATE; + if (notify | indicate) { + cccd = get_cccd(self); } // It's possible that both notify and indicate are set. - if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { + if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION); sent = true; } - if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) { + if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION); sent = true; } diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h index 7cb2275968..8c8309f09d 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.h +++ b/ports/nrf/common-hal/bleio/Characteristic.h @@ -28,17 +28,19 @@ #ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H +#include "shared-bindings/bleio/Attribute.h" +#include "shared-module/bleio/Characteristic.h" #include "common-hal/bleio/Service.h" #include "common-hal/bleio/UUID.h" -#include "shared-module/bleio/Characteristic.h" typedef struct { mp_obj_base_t base; bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; - volatile mp_obj_t value_data; + mp_obj_t value_data; uint16_t handle; bleio_characteristic_properties_t props; + bleio_attribute_security_mode_t security_mode; mp_obj_list_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c index 005af6eaae..ad62b25355 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.c +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2018 Dan Halbert for Adafruit Industries + * Copyright (c) 2019 Dan Halbert for Adafruit Industries * Copyright (c) 2018 Artur Pacholec * Copyright (c) 2016 Glenn Ruben Bakke * @@ -33,10 +33,6 @@ void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_u self->uuid = uuid; } -mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) { - return self->handle; -} - 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/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h index b7af6a42f9..ad94a0bb98 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.h +++ b/ports/nrf/common-hal/bleio/Descriptor.h @@ -30,14 +30,17 @@ #define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H #include "py/obj.h" -#include "common-hal/bleio/Characteristic.h" + +#include "shared-bindings/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; + mp_obj_t value_data; + uint16_t handle; + bleio_attribute_security_mode_t security_mode; } bleio_descriptor_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index c45041ad04..905b26835e 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -138,10 +138,10 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { // Pairing process completed ble_gap_evt_auth_status_t* status = &ble_evt->evt.gap_evt.params.auth_status; if (BLE_GAP_SEC_STATUS_SUCCESS == status->auth_status) { - mp_printf(&mp_plat_print, "Pairing succeeded, status: 0x%04x\n", status->auth_status); + // mp_printf(&mp_plat_print, "Pairing succeeded, status: 0x%04x\n", status->auth_status); self->pair_status = PAIR_PAIRED; } else { - mp_printf(&mp_plat_print, "Pairing failed, status: 0x%04x\n", status->auth_status); + // mp_printf(&mp_plat_print, "Pairing failed, status: 0x%04x\n", status->auth_status); self->pair_status = PAIR_NOT_PAIRED; } break; diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h index e4a664b01f..e75a1641a3 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.h +++ b/ports/nrf/common-hal/bleio/Peripheral.h @@ -35,7 +35,6 @@ #include "py/obj.h" #include "py/objlist.h" -#include "shared-module/bleio/__init__.h" #include "shared-module/bleio/Address.h" typedef enum { diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 02c2ac1f9a..cdcbad7c41 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -29,8 +29,8 @@ #include "ble.h" #include "py/runtime.h" #include "common-hal/bleio/__init__.h" -#include "common-hal/bleio/Characteristic.h" #include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/Adapter.h" @@ -74,12 +74,12 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]); 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_no_response, - .char_props.write = characteristic->props.write, - .char_props.notify = characteristic->props.notify, - .char_props.indicate = characteristic->props.indicate, + .char_props.broadcast = (bool) characteristic->props & CHAR_PROP_BROADCAST, + .char_props.read = (bool) characteristic->props & CHAR_PROP_READ, + .char_props.write_wo_resp = (bool) characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE, + .char_props.write = (bool) characteristic->props & CHAR_PROP_WRITE, + .char_props.notify = (bool) characteristic->props & CHAR_PROP_NOTIFY, + .char_props.indicate = (bool) characteristic->props & CHAR_PROP_INDICATE, }; ble_gatts_attr_md_t cccd_md = { @@ -93,28 +93,28 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) char_md.p_cccd_md = &cccd_md; } - ble_uuid_t uuid; - bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &uuid); + ble_uuid_t char_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(characteristic->uuid, &char_uuid); - ble_gatts_attr_md_t attr_md = { + ble_gatts_attr_md_t char_attr_md = { .vloc = BLE_GATTS_VLOC_STACK, .vlen = 1, }; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.write_perm); - ble_gatts_attr_t attr_char_value = { - .p_uuid = &uuid, - .p_attr_md = &attr_md, + ble_gatts_attr_t char_attr = { + .p_uuid = &char_uuid, + .p_attr_md = &char_attr_md, .init_len = sizeof(uint8_t), .max_len = GATT_MAX_DATA_LENGTH, }; - ble_gatts_char_handles_t handles; + ble_gatts_char_handles_t char_handles; uint32_t err_code; - err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &attr_char_value, &handles); + err_code = sd_ble_gatts_characteristic_add(self->handle, &char_md, &char_attr, &char_handles); if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code); } @@ -123,9 +123,41 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) mp_raise_ValueError(translate("Characteristic already in use by another Service.")); } - characteristic->user_desc_handle = handles.user_desc_handle; - characteristic->cccd_handle = handles.cccd_handle; - characteristic->sccd_handle = handles.sccd_handle; - characteristic->handle = handles.value_handle; + characteristic->user_desc_handle = char_handles.user_desc_handle; + characteristic->cccd_handle = char_handles.cccd_handle; + characteristic->sccd_handle = char_handles.sccd_handle; + characteristic->handle = char_handles.value_handle; + + // Add the descriptors for this characteristic. + for (size_t descriptor_idx = 0; descriptor_idx < characteristic->descriptor_list->len; ++descriptor_idx) { + bleio_descriptor_obj_t *descriptor = + MP_OBJ_TO_PTR(characteristic->descriptor_list->items[descriptor_idx]); + + ble_uuid_t desc_uuid; + bleio_uuid_convert_to_nrf_ble_uuid(descriptor->uuid, &desc_uuid); + + ble_gatts_attr_md_t desc_attr_md = { + // Data passed is not in a permanent location and should be copied. + .vloc = BLE_GATTS_VLOC_STACK, + .vlen = 1, + }; + + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.write_perm); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(descriptor->value_data, &bufinfo, MP_BUFFER_READ); + + ble_gatts_attr_t desc_attr = { + .p_uuid = &desc_uuid, + .p_attr_md = &desc_attr_md, + .init_len = bufinfo.len, + .p_value = bufinfo.buf, + .init_offs = 0, + .max_len = GATT_MAX_DATA_LENGTH, + }; + + err_code = sd_ble_gatts_descriptor_add(characteristic->handle, &desc_attr, &descriptor->handle); + } } } diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index a24898b0a4..303e707978 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -204,17 +204,16 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob // For now, just leave the UUID as NULL. } - 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; + bleio_characteristic_properties_t props = + (gattc_char->char_props.broadcast ? CHAR_PROP_BROADCAST : 0) | + (gattc_char->char_props.indicate ? CHAR_PROP_INDICATE : 0) | + (gattc_char->char_props.notify ? CHAR_PROP_NOTIFY : 0) | + (gattc_char->char_props.read ? CHAR_PROP_READ : 0) | + (gattc_char->char_props.write ? CHAR_PROP_WRITE : 0) | + (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); // 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)); + common_hal_bleio_characteristic_construct(characteristic, uuid, props, SEC_MODE_OPEN, mp_const_empty_tuple); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; @@ -233,15 +232,15 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob // Remember handles for certain well-known descriptors. switch (gattc_desc->uuid.uuid) { - case DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION: + case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG: m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle; break; - case DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION: + case BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG: m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle; break; - case DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION: + case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC: m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle; break; @@ -268,7 +267,8 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob // For now, just leave the UUID as NULL. } - common_hal_bleio_descriptor_construct(descriptor, uuid); + // TODO: can we find out security mode? + common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN); descriptor->handle = gattc_desc->handle; descriptor->characteristic = m_desc_discovery_characteristic; @@ -313,6 +313,9 @@ void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t ble_drv_add_event_handler(discovery_on_ble_evt, device); + // Start over with an empty list. + mp_obj_list_clear(MP_OBJ_FROM_PTR(common_hal_bleio_device_get_remote_services_list(device))); + if (service_uuids_whitelist == mp_const_none) { // List of service UUID's not given, so discover all available services. diff --git a/py/circuitpy_defns.mk b/py/circuitpy_defns.mk index bdefc18cc0..5e5ebeaa87 100644 --- a/py/circuitpy_defns.mk +++ b/py/circuitpy_defns.mk @@ -227,6 +227,7 @@ $(filter $(SRC_PATTERNS), \ audioio/AudioOut.c \ bleio/__init__.c \ bleio/Adapter.c \ + bleio/Attribute.c \ bleio/Central.c \ bleio/Characteristic.c \ bleio/CharacteristicBuffer.c \ @@ -276,6 +277,9 @@ $(filter $(SRC_PATTERNS), \ # All possible sources are listed here, and are filtered by SRC_PATTERNS. SRC_BINDINGS_ENUMS = \ $(filter $(SRC_PATTERNS), \ + bleio/Address.c \ + bleio/Attribute.c \ + bleio/ScanEntry.c \ digitalio/Direction.c \ digitalio/DriveMode.c \ digitalio/Pull.c \ @@ -289,12 +293,6 @@ SRC_BINDINGS_ENUMS += \ help.c \ util.c -SRC_BINDINGS_ENUMS += \ -$(filter $(SRC_PATTERNS), \ - bleio/Address.c \ - bleio/ScanEntry.c \ -) - # All possible sources are listed here, and are filtered by SRC_PATTERNS. SRC_SHARED_MODULE = \ $(filter $(SRC_PATTERNS), \ @@ -314,6 +312,7 @@ $(filter $(SRC_PATTERNS), \ bitbangio/__init__.c \ board/__init__.c \ bleio/Address.c \ + bleio/Attribute.c \ bleio/ScanEntry.c \ busio/OneWire.c \ displayio/Bitmap.c \ diff --git a/py/obj.h b/py/obj.h index 6eead377db..c719c2945a 100644 --- a/py/obj.h +++ b/py/obj.h @@ -668,6 +668,7 @@ mp_obj_t mp_obj_new_gen_wrap(mp_obj_t fun); mp_obj_t mp_obj_new_closure(mp_obj_t fun, size_t n_closed, const mp_obj_t *closed); mp_obj_t mp_obj_new_tuple(size_t n, const mp_obj_t *items); mp_obj_t mp_obj_new_list(size_t n, mp_obj_t *items); +mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable); mp_obj_t mp_obj_new_dict(size_t n_args); mp_obj_t mp_obj_new_set(size_t n_args, mp_obj_t *items); mp_obj_t mp_obj_new_slice(mp_obj_t start, mp_obj_t stop, mp_obj_t step); diff --git a/py/objlist.c b/py/objlist.c index 558c4c6115..ea38e64e55 100644 --- a/py/objlist.c +++ b/py/objlist.c @@ -68,6 +68,11 @@ STATIC mp_obj_t list_extend_from_iter(mp_obj_t list, mp_obj_t iterable) { return list; } +mp_obj_t mp_obj_new_list_from_iter(mp_obj_t iterable) { + mp_obj_t list = mp_obj_new_list(0, NULL); + return list_extend_from_iter(list, iterable); +} + STATIC mp_obj_t list_make_new(const mp_obj_type_t *type_in, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { (void)type_in; mp_arg_check_num(n_args, kw_args, 0, 1, false); diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c index 475fc9427d..d77cfa4048 100644 --- a/shared-bindings/bleio/Address.c +++ b/shared-bindings/bleio/Address.c @@ -174,13 +174,13 @@ STATIC void bleio_address_print(const mp_print_t *print, mp_obj_t self_in, mp_pr //| A randomly generated address that changes on every connection. //| STATIC const mp_rom_map_elem_t bleio_address_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) }, - { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) }, + { MP_ROM_QSTR(MP_QSTR_address_bytes), MP_ROM_PTR(&bleio_address_address_bytes_obj) }, + { MP_ROM_QSTR(MP_QSTR_type), MP_ROM_PTR(&bleio_address_type_obj) }, // These match the BLE_GAP_ADDR_TYPES values used by the nRF library. - { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_OBJ_NEW_SMALL_INT(0) }, - { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_OBJ_NEW_SMALL_INT(1) }, - { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(2) }, - { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_OBJ_NEW_SMALL_INT(3) }, + { MP_ROM_QSTR(MP_QSTR_PUBLIC), MP_ROM_INT(0) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_STATIC), MP_ROM_INT(1) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_RESOLVABLE), MP_ROM_INT(2) }, + { MP_ROM_QSTR(MP_QSTR_RANDOM_PRIVATE_NON_RESOLVABLE), MP_ROM_INT(3) }, }; diff --git a/shared-bindings/bleio/Attribute.c b/shared-bindings/bleio/Attribute.c new file mode 100644 index 0000000000..f640cc05c6 --- /dev/null +++ b/shared-bindings/bleio/Attribute.c @@ -0,0 +1,93 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * 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. + */ + +#include "py/objproperty.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/UUID.h" + +// + +//| .. currentmodule:: bleio +//| +//| :class:`Attribute` -- BLE Attribute +//| ========================================================= +//| +//| Definitions associated with all BLE attributes: characteristics, descriptors, etc. +//| `Attribute` is, notionally, a superclass of `Characteristic` and `Descriptor`, +//| but is not defined as a Python superclass of those classes. +//| +//| .. class:: Attribute() +//| +//| You cannot create an instance of `Attribute`. +//| + +STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { + +//| .. data:: NO_ACCESS +//| +//| security mode: access not allowed +//| +//| .. data:: OPEN +//| +//| security_mode: no security (link is not encrypted) +//| +//| .. data:: ENCRYPT_NO_MITM +//| +//| security_mode: unauthenticated encryption, without man-in-the-middle protection +//| +//| .. data:: ENCRYPT_WITH_MITM +//| +//| security_mode: authenticated encryption, with man-in-the-middle protection +//| +//| .. data:: LESC_ENCRYPT_WITH_MITM +//| +//| security_mode: LESC encryption, with man-in-the-middle protection +//| +//| .. data:: SIGNED_NO_MITM +//| +//| security_mode: unauthenticated data signing, without man-in-the-middle protection +//| +//| .. data:: SIGNED_WITH_MITM +//| +//| security_mode: authenticated data signing, without man-in-the-middle protection +//| + { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SEC_MODE_NO_ACCESS) }, + { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SEC_MODE_OPEN) }, + { MP_ROM_QSTR(MP_QSTR_ENCRYPT_NO_MITM), MP_ROM_INT(SEC_MODE_ENC_NO_MITM) }, + { MP_ROM_QSTR(MP_QSTR_ENCRYPT_WITH_MITM), MP_ROM_INT(SEC_MODE_ENC_WITH_MITM) }, + { MP_ROM_QSTR(MP_QSTR_LESC_ENCRYPT_WITH_MITM), MP_ROM_INT(SEC_MODE_LESC_ENC_WITH_MITM) }, + { MP_ROM_QSTR(MP_QSTR_SIGNED_NO_MITM), MP_ROM_INT(SEC_MODE_SIGNED_NO_MITM) }, + { MP_ROM_QSTR(MP_QSTR_SIGNED_WITH_MITM), MP_ROM_INT(SEC_MODE_SIGNED_WITH_MITM) }, + +}; +STATIC MP_DEFINE_CONST_DICT(bleio_attribute_locals_dict, bleio_attribute_locals_dict_table); + +const mp_obj_type_t bleio_attribute_type = { + { &mp_type_type }, + .name = MP_QSTR_Attribute, + .locals_dict = (mp_obj_dict_t*)&bleio_attribute_locals_dict, +}; diff --git a/shared-bindings/bleio/Attribute.h b/shared-bindings/bleio/Attribute.h new file mode 100644 index 0000000000..06a6eb5a9a --- /dev/null +++ b/shared-bindings/bleio/Attribute.h @@ -0,0 +1,38 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * 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_ATTRIBUTE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H + +#include "py/obj.h" + +#include "shared-module/bleio/Attribute.h" + +extern const mp_obj_type_t bleio_attribute_type; + +extern void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode); + +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_ATTRIBUTE_H diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 3bf0476ab5..09ed48ef95 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -28,6 +28,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Attribute.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/UUID.h" @@ -40,30 +41,25 @@ //| and writing of the characteristic's value. //| //| -//| .. class:: Characteristic(uuid, *, broadcast=False, indicate=False, notify=False, read=False, write=False, write_no_response=False) +//| .. class:: Characteristic(uuid, *, properties=0, security_mode=`Attribute.OPEN`, descriptors=None) //| //| Create a new Characteristic object identified by the specified UUID. //| //| :param bleio.UUID uuid: The uuid of the characteristic -//| :param bool broadcast: Allowed in advertising packets -//| :param bool indicate: Server will indicate to the client when the value is set and wait for a response -//| :param bool notify: Server will notify the client when the value is set -//| :param bool read: Clients may read this characteristic -//| :param bool write: Clients may write this characteristic; a response will be sent back -//| :param bool write_no_response: Clients may write this characteristic; no response will be sent back +//| :param int properties: bitmask of these values bitwise-or'd together: `BROADCAST`, `INDICATE`, +//| `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE` +//| :param int security_mode: one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`, +//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`, +//| `Attribute.SIGNED_NO_MITM`, `Attribute.SIGNED_WITH_MITM`. +//| :param iterable descriptors: BLE descriptors for this characteristic. //| STATIC mp_obj_t bleio_characteristic_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_uuid, ARG_broadcast, ARG_indicate, ARG_notify, ARG_read, ARG_write, ARG_write_no_response, - }; + enum { ARG_uuid, ARG_properties, ARG_security_mode, ARG_descriptors }; static const mp_arg_t allowed_args[] = { { 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_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0 } }, + { MP_QSTR_security_mode, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_descriptors, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -76,129 +72,41 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t } bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj); + const bleio_characteristic_properties_t properties = args[ARG_properties].u_int; + if (properties & ~CHAR_PROP_ALL) { + mp_raise_ValueError(translate("Invalid properties")); + } + + const bleio_attribute_security_mode_t security_mode = args[ARG_security_mode].u_int; + common_hal_bleio_attribute_security_mode_check_valid(security_mode); + + mp_obj_t descriptors = args[ARG_descriptors].u_obj; + if (descriptors == mp_const_none) { + descriptors = mp_const_empty_tuple; + } + bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); self->base.type = &bleio_characteristic_type; - bleio_characteristic_properties_t properties; - - properties.broadcast = args[ARG_broadcast].u_bool; - properties.indicate = args[ARG_indicate].u_bool; - properties.notify = args[ARG_notify].u_bool; - properties.read = args[ARG_read].u_bool; - properties.write = args[ARG_write].u_bool; - properties.write_no_response = args[ARG_write_no_response].u_bool; - - // Initialize, with an empty descriptor list. - common_hal_bleio_characteristic_construct(self, uuid, properties, mp_obj_new_list(0, NULL)); + common_hal_bleio_characteristic_construct(self, uuid, properties, security_mode, descriptors); return MP_OBJ_FROM_PTR(self); } -//| .. attribute:: broadcast +//| .. attribute:: properties //| -//| A `bool` specifying if the characteristic allows broadcasting its value. (read-only) +//| An int bitmask representing which properties are set. //| -STATIC mp_obj_t bleio_characteristic_get_broadcast(mp_obj_t self_in) { +STATIC mp_obj_t bleio_characteristic_get_properties(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); - return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).broadcast); + return MP_OBJ_NEW_SMALL_INT(common_hal_bleio_characteristic_get_properties(self)); } -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_broadcast_obj, bleio_characteristic_get_broadcast); +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_properties_obj, bleio_characteristic_get_properties); -const mp_obj_property_t bleio_characteristic_broadcast_obj = { +const mp_obj_property_t bleio_characteristic_properties_obj = { .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_characteristic_get_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); - - return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).indicate); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_indicate_obj, bleio_characteristic_get_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)&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); - - return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).notify); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_notify_obj, bleio_characteristic_get_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)&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); - - return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).read); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_read_obj, bleio_characteristic_get_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)&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); - - return mp_obj_new_bool(common_hal_bleio_characteristic_get_properties(self).write); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_obj, bleio_characteristic_get_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)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - -//| .. 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(common_hal_bleio_characteristic_get_properties(self).write_no_response); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_write_no_response_obj, bleio_characteristic_get_write_no_response); - -const mp_obj_property_t bleio_characteristic_write_no_response_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_characteristic_get_write_no_response_obj, + .proxy = { (mp_obj_t)&bleio_characteristic_get_properties_obj, (mp_obj_t)&mp_const_none_obj, (mp_obj_t)&mp_const_none_obj }, }; @@ -301,16 +209,43 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_characteristic_set_cccd_obj, 1, bleio_ch 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) }, - { MP_ROM_QSTR(MP_QSTR_write_no_response), MP_ROM_PTR(&bleio_characteristic_write_no_response_obj) }, + { MP_ROM_QSTR(MP_QSTR_properties), MP_ROM_PTR(&bleio_characteristic_get_properties) }, + { 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) }, + + // Bitmask constants to represent properties +//| .. data:: BROADCAST +//| +//| property: allowed in advertising packets +//| +//| .. data:: INDICATE +//| +//| property: server will indicate to the client when the value is set and wait for a response +//| +//| .. data:: NOTIFY +//| +//| property: server will notify the client when the value is set +//| +//| .. data:: READ +//| +//| property: clients may read this characteristic +//| +//| .. data:: WRITE +//| +//| property: clients may write this characteristic; a response will be sent back +//| +//| .. data:: WRITE_NO_RESPONSE +//| +//| property: clients may write this characteristic; no response will be sent back +//| + { MP_ROM_QSTR(MP_QSTR_BROADCAST), MP_ROM_INT(CHAR_PROP_BROADCAST) }, + { MP_ROM_QSTR(MP_QSTR_INDICATE), MP_ROM_INT(CHAR_PROP_INDICATE) }, + { MP_ROM_QSTR(MP_QSTR_NOTIFY), MP_ROM_INT(CHAR_PROP_NOTIFY) }, + { MP_ROM_QSTR(MP_QSTR_READ), MP_ROM_INT(CHAR_PROP_READ) }, + { MP_ROM_QSTR(MP_QSTR_WRITE), MP_ROM_INT(CHAR_PROP_WRITE) }, + { MP_ROM_QSTR(MP_QSTR_WRITE_NO_RESPONSE), MP_ROM_INT(CHAR_PROP_WRITE_NO_RESPONSE) }, + }; STATIC MP_DEFINE_CONST_DICT(bleio_characteristic_locals_dict, bleio_characteristic_locals_dict_table); @@ -330,5 +265,5 @@ const mp_obj_type_t bleio_characteristic_type = { .name = MP_QSTR_Characteristic, .make_new = bleio_characteristic_make_new, .print = bleio_characteristic_print, - .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict + .locals_dict = (mp_obj_dict_t*)&bleio_characteristic_locals_dict, }; diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h index d450c42b4e..379f9b4bfd 100644 --- a/shared-bindings/bleio/Characteristic.h +++ b/shared-bindings/bleio/Characteristic.h @@ -28,12 +28,13 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CHARACTERISTIC_H +#include "shared-bindings/bleio/Attribute.h" #include "shared-module/bleio/Characteristic.h" #include "common-hal/bleio/Characteristic.h" 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, mp_obj_list_t *descriptor_list); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t security_mode, mp_obj_t descriptors); 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); diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c index f2e5aa01df..b709f3aa78 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -28,6 +28,7 @@ #include "py/objproperty.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Attribute.h" #include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/UUID.h" @@ -41,23 +42,15 @@ //| information about the characteristic. //| -//| .. class:: Descriptor(uuid) +//| .. class:: Descriptor(uuid, security_mode=`Attribute.OPEN`) //| -//| Create a new descriptor object with the UUID uuid. +//| Create a new descriptor object with the UUID uuid and the given value, if any. -//| .. attribute:: handle -//| -//| The descriptor handle. (read-only) -//| - -//| .. attribute:: uuid -//| -//| The descriptor uuid. (read-only) -//| STATIC mp_obj_t bleio_descriptor_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_uuid }; + enum { ARG_uuid, ARG_security_mode }; static const mp_arg_t allowed_args[] = { - { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_security_mode, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -69,28 +62,22 @@ STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_ar mp_raise_ValueError(translate("Expected a UUID")); } + const bleio_attribute_security_mode_t security_mode = args[ARG_security_mode].u_int; + common_hal_bleio_attribute_security_mode_check_valid(security_mode); + bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t); self->base.type = type; bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_arg); - common_hal_bleio_descriptor_construct(self, uuid); + + common_hal_bleio_descriptor_construct(self, uuid, security_mode); return MP_OBJ_FROM_PTR(self); } -STATIC mp_obj_t bleio_descriptor_get_handle(mp_obj_t self_in) { - bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); - - return mp_obj_new_int(common_hal_bleio_descriptor_get_handle(self)); -} -MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_handle_obj, bleio_descriptor_get_handle); - -const mp_obj_property_t bleio_descriptor_handle_obj = { - .base.type = &mp_type_property, - .proxy = {(mp_obj_t)&bleio_descriptor_get_handle_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj}, -}; - +//| .. attribute:: uuid +//| +//| The descriptor uuid. (read-only) +//| STATIC mp_obj_t bleio_descriptor_get_uuid(mp_obj_t self_in) { bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); @@ -108,54 +95,7 @@ const mp_obj_property_t bleio_descriptor_uuid_obj = { STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { // Properties - { MP_ROM_QSTR(MP_QSTR_handle), MP_ROM_PTR(&bleio_descriptor_handle_obj) }, { 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(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); diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h index fd11ea08cd..a7daee574d 100644 --- a/shared-bindings/bleio/Descriptor.h +++ b/shared-bindings/bleio/Descriptor.h @@ -28,31 +28,14 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H +#include "shared-module/bleio/Attribute.h" #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); extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self); extern mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); +extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t security_mode); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index ba3bae6c75..7a6f964363 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -31,21 +31,26 @@ #include "shared-bindings/bleio/Central.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/CharacteristicBuffer.h" -// #include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Peripheral.h" #include "shared-bindings/bleio/ScanEntry.h" #include "shared-bindings/bleio/Scanner.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" -//| :mod:`bleio` --- Bluetooth Low Energy functionality +//| :mod:`bleio` --- Bluetooth Low Energy (BLE) communication //| ================================================================ //| //| .. module:: bleio //| :synopsis: Bluetooth Low Energy functionality //| :platform: nRF //| -//| The `bleio` module contains methods for managing the BLE adapter. +//| The `bleio` module provides necessary low-level functionality for communicating +//| using Bluetooth Low Energy (BLE). We recommend you use `bleio` in conjunction +//| with the `adafruit_ble `_ +//| CircuitPython library, which builds on `bleio`, and +//| provides higher-level convenience functionality, including predefined beacons, clients, +//| servers. //| //| Libraries //| @@ -72,20 +77,23 @@ //| STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, - { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, - { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, - { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, - { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, -// { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, - { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) }, - { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) }, - { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) }, - { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) }, - { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, + { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, + { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, + { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, + { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, + { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, + { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, + { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&bleio_peripheral_type) }, + { MP_ROM_QSTR(MP_QSTR_ScanEntry), MP_ROM_PTR(&bleio_scanentry_type) }, + { MP_ROM_QSTR(MP_QSTR_Scanner), MP_ROM_PTR(&bleio_scanner_type) }, + { MP_ROM_QSTR(MP_QSTR_Service), MP_ROM_PTR(&bleio_service_type) }, + { MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&bleio_uuid_type) }, // Properties - { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, + + // constants + { MP_ROM_QSTR(MP_QSTR_SEC), MP_ROM_PTR(&bleio_uuid_type) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); diff --git a/shared-bindings/bleio/__init__.h b/shared-bindings/bleio/__init__.h index dd6e552046..626b188a98 100644 --- a/shared-bindings/bleio/__init__.h +++ b/shared-bindings/bleio/__init__.h @@ -34,7 +34,6 @@ #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" -#include "shared-module/bleio/__init__.h" #include "common-hal/bleio/Adapter.h" extern const super_adapter_obj_t common_hal_bleio_adapter_obj; diff --git a/shared-module/bleio/Attribute.c b/shared-module/bleio/Attribute.c new file mode 100644 index 0000000000..ac854ec6b3 --- /dev/null +++ b/shared-module/bleio/Attribute.c @@ -0,0 +1,46 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * 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. + */ + +#include + +#include "py/runtime.h" +#include "shared-bindings/bleio/Attribute.h" + +void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode) { + switch (security_mode) { + case SEC_MODE_NO_ACCESS: + case SEC_MODE_OPEN: + case SEC_MODE_ENC_NO_MITM: + case SEC_MODE_ENC_WITH_MITM: + case SEC_MODE_LESC_ENC_WITH_MITM: + case SEC_MODE_SIGNED_NO_MITM: + case SEC_MODE_SIGNED_WITH_MITM: + break; + default: + mp_raise_ValueError(translate("Invalid security_mode")); + break; + } +} diff --git a/shared-module/bleio/Attribute.h b/shared-module/bleio/Attribute.h new file mode 100644 index 0000000000..62615f1b5e --- /dev/null +++ b/shared-module/bleio/Attribute.h @@ -0,0 +1,41 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2019 Dan Halbert for Adafruit Industries + * + * 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_MODULE_BLEIO_ATTRIBUTE_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H + +// BLE security modes: 0x +typedef enum { + SEC_MODE_NO_ACCESS = 0x00, + SEC_MODE_OPEN = 0x11, + SEC_MODE_ENC_NO_MITM = 0x21, + SEC_MODE_ENC_WITH_MITM = 0x31, + SEC_MODE_LESC_ENC_WITH_MITM = 0x41, + SEC_MODE_SIGNED_NO_MITM = 0x12, + SEC_MODE_SIGNED_WITH_MITM = 0x22, +} bleio_attribute_security_mode_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H diff --git a/shared-module/bleio/Characteristic.h b/shared-module/bleio/Characteristic.h index 27b43588fa..409a57c76e 100644 --- a/shared-module/bleio/Characteristic.h +++ b/shared-module/bleio/Characteristic.h @@ -27,14 +27,17 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H -// Flags for each characteristic property. Common across ports. -typedef struct { - bool broadcast : 1; - bool read : 1; - bool write_no_response : 1; - bool write : 1; - bool notify : 1; - bool indicate : 1; -} bleio_characteristic_properties_t; +typedef enum { + CHAR_PROP_NONE = 0, + CHAR_PROP_BROADCAST = 1u << 0, + CHAR_PROP_INDICATE = 1u << 1, + CHAR_PROP_NOTIFY = 1u << 2, + CHAR_PROP_READ = 1u << 3, + CHAR_PROP_WRITE = 1u << 4, + CHAR_PROP_WRITE_NO_RESPONSE = 1u << 5, + CHAR_PROP_ALL = (CHAR_PROP_BROADCAST | CHAR_PROP_INDICATE | CHAR_PROP_NOTIFY | + CHAR_PROP_READ | CHAR_PROP_WRITE | CHAR_PROP_WRITE_NO_RESPONSE) +} bleio_characteristic_properties_enum_t; +typedef uint8_t bleio_characteristic_properties_t; #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CHARACTERISTIC_H From d74c8b9425d38fe2dce56e044b128ab5693f5f06 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Tue, 6 Aug 2019 22:55:25 -0400 Subject: [PATCH 5/9] WIP: more Descriptor work; refactor gattc/gatts read/write --- ports/nrf/common-hal/bleio/Characteristic.c | 199 ++++++-------------- ports/nrf/common-hal/bleio/Characteristic.h | 6 +- ports/nrf/common-hal/bleio/Descriptor.c | 84 ++++++++- ports/nrf/common-hal/bleio/Descriptor.h | 6 +- ports/nrf/common-hal/bleio/Service.c | 3 +- ports/nrf/common-hal/bleio/__init__.c | 89 ++++++++- shared-bindings/bleio/Address.c | 16 +- shared-bindings/bleio/Attribute.c | 4 +- shared-bindings/bleio/Characteristic.c | 62 +++++- shared-bindings/bleio/Characteristic.h | 3 +- shared-bindings/bleio/Descriptor.c | 46 ++++- shared-bindings/bleio/Descriptor.h | 6 +- shared-bindings/bleio/Service.c | 3 + shared-bindings/bleio/__init__.c | 1 + shared-bindings/bleio/__init__.h | 6 + 15 files changed, 362 insertions(+), 172 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 41fcdd1f19..e0ddf1e813 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -25,30 +25,23 @@ * THE SOFTWARE. */ -#include -#include - -#include "ble_drv.h" -#include "ble_gatts.h" -#include "nrf_soc.h" - #include "py/runtime.h" #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/Service.h" -STATIC volatile bleio_characteristic_obj_t *m_read_characteristic; +static volatile bleio_characteristic_obj_t *m_read_characteristic; -STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) { - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); +STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_handle) { uint16_t cccd; ble_gatts_value_t value = { .p_value = (uint8_t*) &cccd, .len = 2, }; - const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value); + const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value); if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) { @@ -61,64 +54,39 @@ STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) { return cccd; } -STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) { - // This might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because - // we can still read and write the local value. - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); +STATIC void characteristic_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { + switch (ble_evt->header.evt_id) { - mp_buffer_info_t bufinfo; - ble_gatts_value_t gatts_value = { - .p_value = NULL, - .len = 0, - }; + // More events may be handled later, so keep this as a switch. - // Read once to find out what size buffer we need, then read again to fill buffer. + case BLE_GATTC_EVT_READ_RSP: { + ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp; + if (m_read_characteristic) { + m_read_characteristic->value = mp_obj_new_bytearray(response->len, response->data); + } + // Indicate to busy-wait loop that we've read the attribute value. + m_read_characteristic = NULL; + break; + } - uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value); - if (err_code == NRF_SUCCESS) { - characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len); - mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE); - gatts_value.p_value = bufinfo.buf; - - // Read again, with the correct size of buffer. - err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value); - } - - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code); + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id); + break; } } - -STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because - // we can still read and write the local value. - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - - ble_gatts_value_t gatts_value = { - .p_value = bufinfo->buf, - .len = bufinfo->len, - }; - - const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value); - if (err_code != NRF_SUCCESS) { - mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code); - } -} - -STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { +STATIC void characteristic_gatts_notify_indicate(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { uint16_t hvx_len = bufinfo->len; ble_gatts_hvx_params_t hvx_params = { - .handle = characteristic->handle, + .handle = handle, .type = hvx_type, .offset = 0, .p_len = &hvx_len, .p_data = bufinfo->buf, }; - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - while (1) { const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params); if (err_code == NRF_SUCCESS) { @@ -134,21 +102,17 @@ STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp // Some real error has occurred. mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code); } - } -STATIC void check_connected(uint16_t conn_handle) { - if (conn_handle == BLE_CONN_HANDLE_INVALID) { - mp_raise_OSError_msg(translate("Not connected")); - } -} - -STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { +STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic) { const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - check_connected(conn_handle); + common_hal_bleio_check_connected(conn_handle); + // Set to NULL in event loop after event. m_read_characteristic = characteristic; + ble_drv_add_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); + const uint32_t err_code = sd_ble_gattc_read(conn_handle, characteristic->handle, 0); if (err_code != NRF_SUCCESS) { mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); @@ -157,91 +121,54 @@ STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { while (m_read_characteristic != NULL) { MICROPY_VM_HOOK_LOOP; } + + ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); } -STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); - check_connected(conn_handle); - - ble_gattc_write_params_t write_params = { - .write_op = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) - ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, - .handle = characteristic->handle, - .p_value = bufinfo->buf, - .len = bufinfo->len, - }; - - 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 attribute value, err 0x%04x"), err_code); - } - -} - -STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) { - switch (ble_evt->header.evt_id) { - - // 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; - } - - default: - // For debugging. - // 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, bleio_attribute_security_mode_t security_mode, mp_obj_t descriptors) { - self->service = mp_const_none; +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_obj_list_t *descriptor_list) { + self->service = MP_OBJ_NULL; self->uuid = uuid; - self->value_data = mp_const_none; - self->props = props; - self->security_mode = security_mode; - self->descriptor_list = mp_obj_new_list_from_iter(descriptors); - + self->value = mp_const_none; self->handle = BLE_GATT_HANDLE_INVALID; + self->props = props; + self->read_perm = read_perm; + self->write_perm = write_perm; + self->descriptor_list = descriptor_list; - ble_drv_add_event_handler(characteristic_on_ble_evt, self); + for (size_t descriptor_idx = 0; descriptor_idx < descriptor_list->len; ++descriptor_idx) { + bleio_descriptor_obj_t *descriptor = + MP_OBJ_TO_PTR(descriptor_list->items[descriptor_idx]); + descriptor->characteristic = self; + } } mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) { return self->descriptor_list; } +bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_characteristic_obj_t *self) { + return self->service; +} + mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); if (common_hal_bleio_service_get_is_remote(self->service)) { - gattc_read(self); + // self->value is set by evt handler. + characteristic_gattc_read(self); } else { - gatts_read(self); + self->value = common_hal_bleio_gatts_read(self->handle, conn_handle); } - return self->value_data; + return self->value; } void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + if (common_hal_bleio_service_get_is_remote(self->service)) { - gattc_write(self, bufinfo); + // Last argument is true if write-no-reponse desired. + common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, + (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); } else { bool sent = false; uint16_t cccd = 0; @@ -249,26 +176,25 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, const bool notify = self->props & CHAR_PROP_NOTIFY; const bool indicate = self->props & CHAR_PROP_INDICATE; if (notify | indicate) { - cccd = get_cccd(self); + cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); } // It's possible that both notify and indicate are set. if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { - gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION); + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); sent = true; } if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { - gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION); + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); sent = true; } if (!sent) { - gatts_write(self, bufinfo); + common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); } } } - bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) { return self->uuid; } @@ -286,14 +212,13 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, mp_raise_ValueError(translate("Can't set CCCD on local Characteristic")); } + const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + common_hal_bleio_check_connected(conn_handle); + 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, diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h index 8c8309f09d..46f46eee54 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.h +++ b/ports/nrf/common-hal/bleio/Characteristic.h @@ -35,12 +35,14 @@ typedef struct { mp_obj_base_t base; + // Will be MP_OBJ_NULL before being assigned to a Service. bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; - mp_obj_t value_data; + mp_obj_t value; uint16_t handle; bleio_characteristic_properties_t props; - bleio_attribute_security_mode_t security_mode; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; mp_obj_list_t *descriptor_list; uint16_t user_desc_handle; uint16_t cccd_handle; diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c index ad62b25355..d6473a64fd 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.c +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -26,13 +26,93 @@ * THE SOFTWARE. */ -#include "common-hal/bleio/Descriptor.h" +#include "py/runtime.h" + +#include "shared-bindings/bleio/__init__.h" +#include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" -void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) { +static volatile bleio_descriptor_obj_t *m_read_descriptor; + +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm) { + self->characteristic = MP_OBJ_NULL; self->uuid = uuid; + self->value = mp_const_none; + self->handle = BLE_CONN_HANDLE_INVALID; + self->read_perm = read_perm; + self->write_perm = write_perm; } bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { return self->uuid; } + +mp_obj_t common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { + return self->characteristic; +} + +STATIC void descriptor_on_gattc_read_rsp_evt(ble_evt_t *ble_evt, void *param) { + switch (ble_evt->header.evt_id) { + + // 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; + if (m_read_descriptor) { + m_read_descriptor->value = mp_obj_new_bytearray(response->len, response->data); + } + // Indicate to busy-wait loop that we've read the attribute value. + m_read_descriptor = NULL; + break; + } + + default: + // For debugging. + // mp_printf(&mp_plat_print, "Unhandled descriptor event: 0x%04x\n", ble_evt->header.evt_id); + break; + } +} + +STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) { + const uint16_t conn_handle = + common_hal_bleio_device_get_conn_handle(descriptor->characteristic->service->device); + common_hal_bleio_check_connected(conn_handle); + + // Set to NULL in event loop after event. + m_read_descriptor = descriptor; + + ble_drv_add_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); + + const uint32_t err_code = sd_ble_gattc_read(conn_handle, descriptor->handle, 0); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code); + } + + while (m_read_descriptor != NULL) { + MICROPY_VM_HOOK_LOOP; + } + + ble_drv_remove_event_handler(descriptor_on_gattc_read_rsp_evt, descriptor); +} + +mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) { + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + descriptor_gattc_read(self); + } else { + self->value = common_hal_bleio_gatts_read( + self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device)); + } + + return self->value; +} + +void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device); + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + // false means WRITE_REQ, not write-no-response + common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); + } else { + common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + } +} diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h index ad94a0bb98..2fae8cba6f 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.h +++ b/ports/nrf/common-hal/bleio/Descriptor.h @@ -36,11 +36,13 @@ typedef struct { mp_obj_base_t base; + // Will be MP_OBJ_NULL before being assigned to a Characteristic. bleio_characteristic_obj_t *characteristic; bleio_uuid_obj_t *uuid; - mp_obj_t value_data; + mp_obj_t value; uint16_t handle; - bleio_attribute_security_mode_t security_mode; + bleio_attribute_security_mode_t read_perm; + bleio_attribute_security_mode_t write_perm; } bleio_descriptor_obj_t; #endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index cdcbad7c41..6d2d9d74f8 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -47,7 +47,6 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]); characteristic->service = self; } - } bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) { @@ -146,7 +145,7 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.write_perm); mp_buffer_info_t bufinfo; - mp_get_buffer_raise(descriptor->value_data, &bufinfo, MP_BUFFER_READ); + mp_get_buffer_raise(descriptor->value, &bufinfo, MP_BUFFER_READ); ble_gatts_attr_t desc_attr = { .p_uuid = &desc_uuid, diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index 303e707978..9879a9ff43 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -59,13 +59,19 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = { }, }; +void common_hal_bleio_check_connected(uint16_t conn_handle) { + if (conn_handle == BLE_CONN_HANDLE_INVALID) { + mp_raise_OSError_msg(translate("Not connected")); + } +} + uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) { return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; } else { - return 0; + return BLE_CONN_HANDLE_INVALID; } } @@ -213,7 +219,7 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. - common_hal_bleio_characteristic_construct(characteristic, uuid, props, SEC_MODE_OPEN, mp_const_empty_tuple); + common_hal_bleio_characteristic_construct(characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, mp_const_empty_tuple); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; @@ -267,8 +273,7 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob // For now, just leave the UUID as NULL. } - // TODO: can we find out security mode? - common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN); + common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN, SEC_MODE_OPEN); descriptor->handle = gattc_desc->handle; descriptor->characteristic = m_desc_discovery_characteristic; @@ -418,3 +423,79 @@ void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t ble_drv_remove_event_handler(discovery_on_ble_evt, device); } + +// GATTS read of a Characteristic or Descriptor. +mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle) { + // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because + // we can still read and write the local value. + + mp_buffer_info_t bufinfo; + ble_gatts_value_t gatts_value = { + .p_value = NULL, + .len = 0, + }; + + // Read once to find out what size buffer we need, then read again to fill buffer. + + mp_obj_t value = mp_const_none; + uint32_t err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); + if (err_code == NRF_SUCCESS) { + value = mp_obj_new_bytearray_of_zeros(gatts_value.len); + mp_get_buffer_raise(value, &bufinfo, MP_BUFFER_WRITE); + gatts_value.p_value = bufinfo.buf; + + // Read again, with the correct size of buffer. + err_code = sd_ble_gatts_value_get(conn_handle, handle, &gatts_value); + } + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code); + } + + return value; +} + +void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo) { + // conn_handle might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because + // we can still read and write the local value. + + ble_gatts_value_t gatts_value = { + .p_value = bufinfo->buf, + .len = bufinfo->len, + }; + + const uint32_t err_code = sd_ble_gatts_value_set(conn_handle, handle, &gatts_value); + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to write gatts value, err 0x%04x"), err_code); + } +} + +void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response) { + common_hal_bleio_check_connected(conn_handle); + + ble_gattc_write_params_t write_params = { + .write_op = write_no_response ? BLE_GATT_OP_WRITE_CMD: BLE_GATT_OP_WRITE_REQ, + .handle = handle, + .p_value = bufinfo->buf, + .len = bufinfo->len, + }; + + 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 attribute value, err 0x%04x"), err_code); + } + +} diff --git a/shared-bindings/bleio/Address.c b/shared-bindings/bleio/Address.c index d77cfa4048..baeb6d7c0a 100644 --- a/shared-bindings/bleio/Address.c +++ b/shared-bindings/bleio/Address.c @@ -83,7 +83,21 @@ STATIC mp_obj_t bleio_address_make_new(const mp_obj_type_t *type, size_t n_args, //| .. attribute:: address_bytes //| -//| The bytes that make up the device address (read-only) +//| The bytes that make up the device address (read-only). +//| +//| Note that the ``bytes`` object returned is in little-endian order: +//| The least significant byte is ``address_bytes[0]``. So the address will +//| appear to be reversed if you print the raw ``bytes`` object. If you print +//| or use `str()` on the :py:class:`~bleio.Attribute` object itself, the address will be printed +//| in the expected order. For example: +//| +//| .. code-block:: pycon +//| +//| >>> import bleio +//| >>> bleio.adapter.address +//|
+//| >>> bleio.adapter.address.address_bytes +//| b'5\xa8\xed\xf5\x1d\xc8' //| 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); diff --git a/shared-bindings/bleio/Attribute.c b/shared-bindings/bleio/Attribute.c index f640cc05c6..ef6b17253b 100644 --- a/shared-bindings/bleio/Attribute.c +++ b/shared-bindings/bleio/Attribute.c @@ -37,12 +37,12 @@ //| ========================================================= //| //| Definitions associated with all BLE attributes: characteristics, descriptors, etc. -//| `Attribute` is, notionally, a superclass of `Characteristic` and `Descriptor`, +//| :py:class:`~bleio.Attribute` is, notionally, a superclass of `Characteristic` and `Descriptor`, //| but is not defined as a Python superclass of those classes. //| //| .. class:: Attribute() //| -//| You cannot create an instance of `Attribute`. +//| You cannot create an instance of :py:class:`~bleio.Attribute`. //| STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 09ed48ef95..45bec6c28d 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -30,6 +30,7 @@ #include "py/runtime.h" #include "shared-bindings/bleio/Attribute.h" #include "shared-bindings/bleio/Characteristic.h" +#include "shared-bindings/bleio/Descriptor.h" #include "shared-bindings/bleio/UUID.h" //| .. currentmodule:: bleio @@ -41,24 +42,28 @@ //| and writing of the characteristic's value. //| //| -//| .. class:: Characteristic(uuid, *, properties=0, security_mode=`Attribute.OPEN`, descriptors=None) +//| .. class:: Characteristic(uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, descriptors=None) //| //| Create a new Characteristic object identified by the specified UUID. //| //| :param bleio.UUID uuid: The uuid of the characteristic //| :param int properties: bitmask of these values bitwise-or'd together: `BROADCAST`, `INDICATE`, //| `NOTIFY`, `READ`, `WRITE`, `WRITE_NO_RESPONSE` -//| :param int security_mode: one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`, +//| :param int read_perm: Specifies whether the characteristic can be read by a client, and if so, which +//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`, //| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`, -//| `Attribute.SIGNED_NO_MITM`, `Attribute.SIGNED_WITH_MITM`. +//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. +//| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which +//| security mode is required. Values allowed are the same as `read_perm`. //| :param iterable descriptors: BLE descriptors for this characteristic. //| STATIC mp_obj_t bleio_characteristic_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_uuid, ARG_properties, ARG_security_mode, ARG_descriptors }; + enum { ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm, ARG_descriptors }; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0 } }, - { MP_QSTR_security_mode, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, { MP_QSTR_descriptors, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; @@ -77,8 +82,11 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t mp_raise_ValueError(translate("Invalid properties")); } - const bleio_attribute_security_mode_t security_mode = args[ARG_security_mode].u_int; - common_hal_bleio_attribute_security_mode_check_valid(security_mode); + const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int; + common_hal_bleio_attribute_security_mode_check_valid(read_perm); + + const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int; + common_hal_bleio_attribute_security_mode_check_valid(write_perm); mp_obj_t descriptors = args[ARG_descriptors].u_obj; if (descriptors == mp_const_none) { @@ -88,7 +96,27 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); self->base.type = &bleio_characteristic_type; - common_hal_bleio_characteristic_construct(self, uuid, properties, security_mode, descriptors); + // If descriptors is not an iterable, an exception will be thrown. + mp_obj_iter_buf_t iter_buf; + mp_obj_t iterable = mp_getiter(args[ARG_descriptors].u_obj, &iter_buf); + +// Copy the descriptors list and validate its items. + mp_obj_t desc_list_obj = mp_obj_new_list(0, NULL); + mp_obj_list_t *desc_list = MP_OBJ_TO_PTR(desc_list_obj); + + mp_obj_t descriptor_obj; + while ((descriptor_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + if (!MP_OBJ_IS_TYPE(descriptor_obj, &bleio_descriptor_type)) { + mp_raise_ValueError(translate("descriptors includes an object that is not a Descriptors")); + } + bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(descriptor_obj); + if (common_hal_bleio_descriptor_get_characteristic(descriptor) != mp_const_none) { + mp_raise_ValueError(translate("Descriptor is already attached to a Characteristic")); + } + mp_obj_list_append(desc_list_obj, descriptor_obj); + } + + common_hal_bleio_characteristic_construct(self, uuid, properties, read_perm, write_perm, desc_list); return MP_OBJ_FROM_PTR(self); } @@ -182,6 +210,24 @@ const mp_obj_property_t bleio_characteristic_descriptors_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: service (read-only) +//| +//| The Service this Characteristic is a part of. None if not yet assigned to a Service. +//| +STATIC mp_obj_t bleio_characteristic_get_service(mp_obj_t self_in) { + bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_bleio_characteristic_get_service(self); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_characteristic_get_service_obj, bleio_characteristic_get_service); + +const mp_obj_property_t bleio_characteristic_service_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_characteristic_get_service_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. diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h index 379f9b4bfd..1d532d7489 100644 --- a/shared-bindings/bleio/Characteristic.h +++ b/shared-bindings/bleio/Characteristic.h @@ -34,12 +34,13 @@ 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, bleio_attribute_security_mode_t security_mode, mp_obj_t descriptors); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, 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 bleio_service_obj_t *common_hal_bleio_characteristic_get_service(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 b709f3aa78..1ab8c9ecdb 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -42,15 +42,24 @@ //| information about the characteristic. //| -//| .. class:: Descriptor(uuid, security_mode=`Attribute.OPEN`) +//| .. class:: Descriptor(uuid, *, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`) +//| +//| Create a new descriptor object with the UUID uuid +//| +//| :param bleio.UUID uuid: The uuid of the descriptor +//| :param int read_perm: Specifies whether the descriptor can be read by a client, and if so, which +//| security mode is required. Must be one of the integer values `Attribute.NO_ACCESS`, `Attribute.OPEN`, +//| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`, +//| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. +//| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which +//| security mode is required. Values allowed are the same as `read_perm`. //| -//| Create a new descriptor object with the UUID uuid and the given value, if any. - STATIC mp_obj_t bleio_descriptor_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_uuid, ARG_security_mode }; + enum { ARG_uuid, ARG_read_perm, ARG_write_perm }; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_security_mode, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -62,14 +71,17 @@ STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_ar mp_raise_ValueError(translate("Expected a UUID")); } - const bleio_attribute_security_mode_t security_mode = args[ARG_security_mode].u_int; - common_hal_bleio_attribute_security_mode_check_valid(security_mode); + const bleio_attribute_security_mode_t read_perm = args[ARG_read_perm].u_int; + common_hal_bleio_attribute_security_mode_check_valid(read_perm); + + const bleio_attribute_security_mode_t write_perm = args[ARG_write_perm].u_int; + common_hal_bleio_attribute_security_mode_check_valid(write_perm); bleio_descriptor_obj_t *self = m_new_obj(bleio_descriptor_obj_t); self->base.type = type; bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_arg); - common_hal_bleio_descriptor_construct(self, uuid, security_mode); + common_hal_bleio_descriptor_construct(self, uuid, read_perm, write_perm); return MP_OBJ_FROM_PTR(self); } @@ -93,6 +105,24 @@ const mp_obj_property_t bleio_descriptor_uuid_obj = { (mp_obj_t)&mp_const_none_obj}, }; +//| .. attribute:: characteristic (read-only) +//| +//| The Characteristic this Descriptor is a part of. None if not yet assigned to a Characteristic. +//| +STATIC mp_obj_t bleio_descriptor_get_characteristic(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_bleio_descriptor_get_characteristic(self); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_characteristic_obj, bleio_descriptor_get_characteristic); + +const mp_obj_property_t bleio_descriptor_characteristic_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_descriptor_get_characteristic_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) }, diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h index a7daee574d..eefce03d11 100644 --- a/shared-bindings/bleio/Descriptor.h +++ b/shared-bindings/bleio/Descriptor.h @@ -34,8 +34,8 @@ extern const mp_obj_type_t bleio_descriptor_type; -extern mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self); -extern mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); -extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t security_mode); +extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm); +extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); +extern mp_obj_t common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index b4aeab2bd2..6961b0b522 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -96,6 +96,9 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, // The descriptor base UUID doesn't match the characteristic base UUID. mp_raise_ValueError(translate("Characteristic UUID doesn't match Service UUID")); } + if (common_hal_bleio_characteristic_get_service(characteristic) != MP_OBJ_NULL) { + mp_raise_ValueError(translate("Characteristic is already attached to a Service")); + } mp_obj_list_append(char_list_obj, characteristic_obj); } diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 7a6f964363..0009cf1135 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -59,6 +59,7 @@ //| //| Address //| Adapter +//| Attribute //| Central //| Characteristic //| CharacteristicBuffer diff --git a/shared-bindings/bleio/__init__.h b/shared-bindings/bleio/__init__.h index 626b188a98..6a4c804f55 100644 --- a/shared-bindings/bleio/__init__.h +++ b/shared-bindings/bleio/__init__.h @@ -38,9 +38,15 @@ extern const super_adapter_obj_t common_hal_bleio_adapter_obj; +extern void common_hal_bleio_check_connected(uint16_t conn_handle); + extern uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); extern mp_obj_list_t *common_hal_bleio_device_get_remote_services_list(mp_obj_t device); extern void common_hal_bleio_device_discover_remote_services(mp_obj_t device, mp_obj_t service_uuids_whitelist); +extern mp_obj_t common_hal_bleio_gatts_read(uint16_t handle, uint16_t conn_handle); +extern void common_hal_bleio_gatts_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo); +extern void common_hal_bleio_gattc_write(uint16_t handle, uint16_t conn_handle, mp_buffer_info_t *bufinfo, bool write_no_response); + #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO___INIT___H From d047b73a9cd0f17f9e11d60f3004ada473b2c803 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 7 Aug 2019 11:10:21 -0400 Subject: [PATCH 6/9] fix newly-introduced bugs; UART client/server working again --- ports/nrf/common-hal/bleio/Service.c | 12 ++++++------ ports/nrf/common-hal/bleio/__init__.c | 5 ++--- shared-bindings/bleio/Characteristic.c | 12 ++++++------ shared-bindings/bleio/__init__.c | 2 ++ 4 files changed, 16 insertions(+), 15 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 6d2d9d74f8..0ac0107f55 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -73,12 +73,12 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]); ble_gatts_char_md_t char_md = { - .char_props.broadcast = (bool) characteristic->props & CHAR_PROP_BROADCAST, - .char_props.read = (bool) characteristic->props & CHAR_PROP_READ, - .char_props.write_wo_resp = (bool) characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE, - .char_props.write = (bool) characteristic->props & CHAR_PROP_WRITE, - .char_props.notify = (bool) characteristic->props & CHAR_PROP_NOTIFY, - .char_props.indicate = (bool) characteristic->props & CHAR_PROP_INDICATE, + .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, + .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, + .char_props.write_wo_resp = (characteristic->props & CHAR_PROP_WRITE_NO_RESPONSE) ? 1 : 0, + .char_props.write = (characteristic->props & CHAR_PROP_WRITE) ? 1 : 0, + .char_props.notify = (characteristic->props & CHAR_PROP_NOTIFY) ? 1 : 0, + .char_props.indicate = (characteristic->props & CHAR_PROP_INDICATE) ? 1 : 0, }; ble_gatts_attr_md_t cccd_md = { diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index 9879a9ff43..d09b6f5aff 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -195,8 +195,6 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob 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) { @@ -219,7 +217,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob (gattc_char->char_props.write_wo_resp ? CHAR_PROP_WRITE_NO_RESPONSE : 0); // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. - common_hal_bleio_characteristic_construct(characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, mp_const_empty_tuple); + common_hal_bleio_characteristic_construct( + characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, mp_obj_new_list(0, NULL)); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 45bec6c28d..4adc897ebe 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -96,16 +96,16 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t bleio_characteristic_obj_t *self = m_new_obj(bleio_characteristic_obj_t); self->base.type = &bleio_characteristic_type; - // If descriptors is not an iterable, an exception will be thrown. - mp_obj_iter_buf_t iter_buf; - mp_obj_t iterable = mp_getiter(args[ARG_descriptors].u_obj, &iter_buf); - -// Copy the descriptors list and validate its items. + // Copy the descriptors list and validate its items. mp_obj_t desc_list_obj = mp_obj_new_list(0, NULL); mp_obj_list_t *desc_list = MP_OBJ_TO_PTR(desc_list_obj); + // If descriptors is not an iterable, an exception will be thrown. + mp_obj_iter_buf_t iter_buf; + mp_obj_t descriptors_iter = mp_getiter(descriptors, &iter_buf); + mp_obj_t descriptor_obj; - while ((descriptor_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) { + while ((descriptor_obj = mp_iternext(descriptors_iter)) != MP_OBJ_STOP_ITERATION) { if (!MP_OBJ_IS_TYPE(descriptor_obj, &bleio_descriptor_type)) { mp_raise_ValueError(translate("descriptors includes an object that is not a Descriptors")); } diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 0009cf1135..05be48ddc7 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -28,6 +28,7 @@ #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Address.h" +#include "shared-bindings/bleio/Attribute.h" #include "shared-bindings/bleio/Central.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/CharacteristicBuffer.h" @@ -80,6 +81,7 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bleio) }, { MP_ROM_QSTR(MP_QSTR_Address), MP_ROM_PTR(&bleio_address_type) }, + { MP_ROM_QSTR(MP_QSTR_Attribute), MP_ROM_PTR(&bleio_attribute_type) }, { MP_ROM_QSTR(MP_QSTR_Central), MP_ROM_PTR(&bleio_central_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_CharacteristicBuffer), MP_ROM_PTR(&bleio_characteristic_buffer_type) }, From 1570ef2dd493dbf813e14ac853ce8d4e069fb6c4 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Wed, 7 Aug 2019 23:49:09 -0400 Subject: [PATCH 7/9] specifying attribute length; fix up value setting --- ports/nrf/common-hal/bleio/Characteristic.c | 88 +++++++++++++-------- ports/nrf/common-hal/bleio/Characteristic.h | 2 + ports/nrf/common-hal/bleio/Descriptor.c | 53 +++++++++---- ports/nrf/common-hal/bleio/Descriptor.h | 2 + ports/nrf/common-hal/bleio/Peripheral.c | 3 - ports/nrf/common-hal/bleio/Service.c | 37 +++++---- ports/nrf/common-hal/bleio/__init__.c | 7 +- shared-bindings/bleio/Characteristic.c | 26 ++++-- shared-bindings/bleio/Characteristic.h | 2 +- shared-bindings/bleio/Descriptor.c | 45 ++++++++++- shared-bindings/bleio/Descriptor.h | 6 +- 11 files changed, 191 insertions(+), 80 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index e0ddf1e813..f8b6ce06c3 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -43,7 +43,6 @@ STATIC uint16_t characteristic_get_cccd(uint16_t cccd_handle, uint16_t conn_hand const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, cccd_handle, &value); - if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) { // CCCD is not set, so say that neither Notify nor Indicate is enabled. cccd = 0; @@ -125,16 +124,24 @@ STATIC void characteristic_gattc_read(bleio_characteristic_obj_t *characteristic ble_drv_remove_event_handler(characteristic_on_gattc_read_rsp_evt, characteristic); } -void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_obj_list_t *descriptor_list) { +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, mp_obj_list_t *descriptor_list) { self->service = MP_OBJ_NULL; self->uuid = uuid; - self->value = mp_const_none; + self->value = mp_const_empty_bytes; self->handle = BLE_GATT_HANDLE_INVALID; self->props = props; self->read_perm = read_perm; self->write_perm = write_perm; self->descriptor_list = descriptor_list; + const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; + if (max_length < 0 || max_length > max_length_max) { + mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"), + max_length_max, fixed_length ? "True" : "False"); + } + self->max_length = max_length; + self->fixed_length = fixed_length; + for (size_t descriptor_idx = 0; descriptor_idx < descriptor_list->len; ++descriptor_idx) { bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(descriptor_list->items[descriptor_idx]); @@ -151,48 +158,63 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character } mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); - if (common_hal_bleio_service_get_is_remote(self->service)) { - // self->value is set by evt handler. - characteristic_gattc_read(self); - } else { - self->value = common_hal_bleio_gatts_read(self->handle, conn_handle); + // Do GATT operations only if this characteristic has been added to a registered service. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + if (common_hal_bleio_service_get_is_remote(self->service)) { + // self->value is set by evt handler. + characteristic_gattc_read(self); + } else { + self->value = common_hal_bleio_gatts_read(self->handle, conn_handle); + } } return self->value; } void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); + // Do GATT operations only if this characteristic has been added to a registered service. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device); - if (common_hal_bleio_service_get_is_remote(self->service)) { - // Last argument is true if write-no-reponse desired. - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, - (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); - } else { - bool sent = false; - uint16_t cccd = 0; + if (common_hal_bleio_service_get_is_remote(self->service)) { + // Last argument is true if write-no-reponse desired. + common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, + (self->props & CHAR_PROP_WRITE_NO_RESPONSE)); + } else { + if (self->fixed_length && bufinfo->len != self->max_length) { + mp_raise_ValueError(translate("Value length required fixed length")); + } + if (bufinfo->len > self->max_length) { + mp_raise_ValueError(translate("Value length > max_length")); + } - const bool notify = self->props & CHAR_PROP_NOTIFY; - const bool indicate = self->props & CHAR_PROP_INDICATE; - if (notify | indicate) { - cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); - } + bool sent = false; + uint16_t cccd = 0; - // It's possible that both notify and indicate are set. - if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); - sent = true; - } - if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { - characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); - sent = true; - } + const bool notify = self->props & CHAR_PROP_NOTIFY; + const bool indicate = self->props & CHAR_PROP_INDICATE; + if (notify | indicate) { + cccd = characteristic_get_cccd(self->cccd_handle, conn_handle); + } - if (!sent) { - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + // It's possible that both notify and indicate are set. + if (notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_NOTIFICATION); + sent = true; + } + if (indicate && (cccd & BLE_GATT_HVX_INDICATION)) { + characteristic_gatts_notify_indicate(self->handle, conn_handle, bufinfo, BLE_GATT_HVX_INDICATION); + sent = true; + } + + if (!sent) { + common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + } } } + + self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); } bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) { diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h index 46f46eee54..fb6a4c6cef 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.h +++ b/ports/nrf/common-hal/bleio/Characteristic.h @@ -39,6 +39,8 @@ typedef struct { bleio_service_obj_t *service; bleio_uuid_obj_t *uuid; mp_obj_t value; + uint16_t max_length; + bool fixed_length; uint16_t handle; bleio_characteristic_properties_t props; bleio_attribute_security_mode_t read_perm; diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c index d6473a64fd..2a2019277d 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.c +++ b/ports/nrf/common-hal/bleio/Descriptor.c @@ -35,20 +35,28 @@ static volatile bleio_descriptor_obj_t *m_read_descriptor; -void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm) { +void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length) { self->characteristic = MP_OBJ_NULL; self->uuid = uuid; - self->value = mp_const_none; - self->handle = BLE_CONN_HANDLE_INVALID; + self->value = mp_const_empty_bytes; + self->handle = BLE_GATT_HANDLE_INVALID; self->read_perm = read_perm; self->write_perm = write_perm; + + const mp_int_t max_length_max = fixed_length ? BLE_GATTS_FIX_ATTR_LEN_MAX : BLE_GATTS_VAR_ATTR_LEN_MAX; + if (max_length < 0 || max_length > max_length_max) { + mp_raise_ValueError_varg(translate("max_length must be 0-%d when fixed_length is %s"), + max_length_max, fixed_length ? "True" : "False"); + } + self->max_length = max_length; + self->fixed_length = fixed_length; } bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) { return self->uuid; } -mp_obj_t common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { +bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self) { return self->characteristic; } @@ -97,22 +105,37 @@ STATIC void descriptor_gattc_read(bleio_descriptor_obj_t *descriptor) { } mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self) { - if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - descriptor_gattc_read(self); - } else { - self->value = common_hal_bleio_gatts_read( - self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device)); + // Do GATT operations only if this descriptor has been registered + if (self->handle != BLE_GATT_HANDLE_INVALID) { + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + descriptor_gattc_read(self); + } else { + self->value = common_hal_bleio_gatts_read( + self->handle, common_hal_bleio_device_get_conn_handle(self->characteristic->service->device)); + } } return self->value; } void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo) { - uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device); - if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { - // false means WRITE_REQ, not write-no-response - common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); - } else { - common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + // Do GATT operations only if this descriptor has been registered. + if (self->handle != BLE_GATT_HANDLE_INVALID) { + uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->characteristic->service->device); + if (common_hal_bleio_service_get_is_remote(self->characteristic->service)) { + // false means WRITE_REQ, not write-no-response + common_hal_bleio_gattc_write(self->handle, conn_handle, bufinfo, false); + } else { + if (self->fixed_length && bufinfo->len != self->max_length) { + mp_raise_ValueError(translate("Value length != required fixed length")); + } + if (bufinfo->len > self->max_length) { + mp_raise_ValueError(translate("Value length > max_length")); + } + + common_hal_bleio_gatts_write(self->handle, conn_handle, bufinfo); + } } + + self->value = mp_obj_new_bytes(bufinfo->buf, bufinfo->len); } diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h index 2fae8cba6f..6db4d7be37 100644 --- a/ports/nrf/common-hal/bleio/Descriptor.h +++ b/ports/nrf/common-hal/bleio/Descriptor.h @@ -40,6 +40,8 @@ typedef struct { bleio_characteristic_obj_t *characteristic; bleio_uuid_obj_t *uuid; mp_obj_t value; + uint16_t max_length; + bool fixed_length; uint16_t handle; bleio_attribute_security_mode_t read_perm; bleio_attribute_security_mode_t write_perm; diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index 905b26835e..640b931809 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -149,21 +149,18 @@ STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) { case BLE_GAP_EVT_CONN_SEC_UPDATE: { ble_gap_conn_sec_t* conn_sec = &ble_evt->evt.gap_evt.params.conn_sec_update.conn_sec; - mp_printf(&mp_plat_print, "sm: %d, lv: %d\n", conn_sec->sec_mode.sm, conn_sec->sec_mode.lv); if (conn_sec->sec_mode.sm <= 1 && conn_sec->sec_mode.lv <= 1) { // Security setup did not succeed: // mode 0, level 0 means no access // mode 1, level 1 means open link // mode >=1 and/or level >=1 means encryption is set up self->pair_status = PAIR_NOT_PAIRED; - mp_printf(&mp_plat_print, "PAIR_NOT_PAIRED\n"); } else { // TODO: see Bluefruit lib // if ( !bond_load_cccd(_role, _conn_hdl, _ediv) ) { // sd_ble_gatts_sys_attr_set(_conn_hdl, NULL, 0, 0); // } self->pair_status = PAIR_PAIRED; - mp_printf(&mp_plat_print, "PAIR_PAIRED\n"); } break; } diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index 0ac0107f55..a7a3a6db09 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -72,6 +72,10 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) bleio_characteristic_obj_t *characteristic = MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]); + if (characteristic->handle != BLE_GATT_HANDLE_INVALID) { + mp_raise_ValueError(translate("Characteristic already in use by another Service.")); + } + ble_gatts_char_md_t char_md = { .char_props.broadcast = (characteristic->props & CHAR_PROP_BROADCAST) ? 1 : 0, .char_props.read = (characteristic->props & CHAR_PROP_READ) ? 1 : 0, @@ -97,17 +101,22 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) ble_gatts_attr_md_t char_attr_md = { .vloc = BLE_GATTS_VLOC_STACK, - .vlen = 1, + .vlen = !characteristic->fixed_length, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&char_attr_md.write_perm); + mp_buffer_info_t char_value_bufinfo; + mp_get_buffer_raise(characteristic->value, &char_value_bufinfo, MP_BUFFER_READ); + ble_gatts_attr_t char_attr = { .p_uuid = &char_uuid, .p_attr_md = &char_attr_md, - .init_len = sizeof(uint8_t), - .max_len = GATT_MAX_DATA_LENGTH, + .init_len = char_value_bufinfo.len, + .p_value = char_value_bufinfo.buf, + .init_offs = 0, + .max_len = characteristic->max_length, }; ble_gatts_char_handles_t char_handles; @@ -118,10 +127,6 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) mp_raise_OSError_msg_varg(translate("Failed to add characteristic, err 0x%04x"), err_code); } - if (characteristic->handle != BLE_GATT_HANDLE_INVALID) { - mp_raise_ValueError(translate("Characteristic already in use by another Service.")); - } - characteristic->user_desc_handle = char_handles.user_desc_handle; characteristic->cccd_handle = char_handles.cccd_handle; characteristic->sccd_handle = char_handles.sccd_handle; @@ -138,25 +143,27 @@ void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) ble_gatts_attr_md_t desc_attr_md = { // Data passed is not in a permanent location and should be copied. .vloc = BLE_GATTS_VLOC_STACK, - .vlen = 1, + .vlen = !descriptor->fixed_length, }; BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.read_perm); BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_attr_md.write_perm); - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(descriptor->value, &bufinfo, MP_BUFFER_READ); + mp_buffer_info_t desc_value_bufinfo; + mp_get_buffer_raise(descriptor->value, &desc_value_bufinfo, MP_BUFFER_READ); ble_gatts_attr_t desc_attr = { .p_uuid = &desc_uuid, .p_attr_md = &desc_attr_md, - .init_len = bufinfo.len, - .p_value = bufinfo.buf, + .init_len = desc_value_bufinfo.len, + .p_value = desc_value_bufinfo.buf, .init_offs = 0, - .max_len = GATT_MAX_DATA_LENGTH, + .max_len = descriptor->max_length, }; err_code = sd_ble_gatts_descriptor_add(characteristic->handle, &desc_attr, &descriptor->handle); - } - } + + } // loop over descriptors + + } // loop over characteristics } diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index d09b6f5aff..2d144f8b52 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -218,7 +218,9 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. common_hal_bleio_characteristic_construct( - characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, mp_obj_new_list(0, NULL)); + characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc + mp_obj_new_list(0, NULL)); characteristic->handle = gattc_char->handle_value; characteristic->service = m_char_discovery_service; @@ -272,7 +274,8 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob // For now, just leave the UUID as NULL. } - common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN, SEC_MODE_OPEN); + common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN, SEC_MODE_OPEN, + GATT_MAX_DATA_LENGTH, false); descriptor->handle = gattc_desc->handle; descriptor->characteristic = m_desc_discovery_characteristic; diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 4adc897ebe..7bcfc6b6da 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -42,7 +42,7 @@ //| and writing of the characteristic's value. //| //| -//| .. class:: Characteristic(uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, descriptors=None) +//| .. class:: Characteristic(uuid, *, properties=0, read_perm=`Attribute.OPEN`, write_perm=`Attribute.OPEN`, max_length=20, fixed_length=False, descriptors=None) //| //| Create a new Characteristic object identified by the specified UUID. //| @@ -55,15 +55,22 @@ //| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. //| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which //| security mode is required. Values allowed are the same as `read_perm`. +//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is +//| is 512, or possibly 510 if `fixed_length` is False. The default, 20, is the maximum +//| number of data bytes that fit in a single BLE 4.x ATT packet. +//| :param bool fixed_length: True if the characteristic value is of fixed length. //| :param iterable descriptors: BLE descriptors for this characteristic. //| STATIC mp_obj_t bleio_characteristic_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_uuid, ARG_properties, ARG_read_perm, ARG_write_perm, ARG_descriptors }; + enum { ARG_uuid, ARG_properties, ARG_read_perm, ARG_write_perm, + ARG_max_length, ARG_fixed_length, ARG_descriptors }; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0 } }, - { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, - { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} }, + { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN} }, + { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN} }, + { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} }, + { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_descriptors, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} }, }; @@ -110,13 +117,18 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t mp_raise_ValueError(translate("descriptors includes an object that is not a Descriptors")); } bleio_descriptor_obj_t *descriptor = MP_OBJ_TO_PTR(descriptor_obj); - if (common_hal_bleio_descriptor_get_characteristic(descriptor) != mp_const_none) { + if (common_hal_bleio_descriptor_get_characteristic(descriptor) != MP_OBJ_NULL) { mp_raise_ValueError(translate("Descriptor is already attached to a Characteristic")); } mp_obj_list_append(desc_list_obj, descriptor_obj); } - common_hal_bleio_characteristic_construct(self, uuid, properties, read_perm, write_perm, desc_list); + // Range checking on max_length arg is done by the common_hal layer, because + // it may vary depending on underlying BLE implementation. + common_hal_bleio_characteristic_construct(self, uuid, properties, + read_perm, write_perm, + args[ARG_max_length].u_int, args[ARG_fixed_length].u_bool, + desc_list); return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/bleio/Characteristic.h b/shared-bindings/bleio/Characteristic.h index 1d532d7489..87942c8e90 100644 --- a/shared-bindings/bleio/Characteristic.h +++ b/shared-bindings/bleio/Characteristic.h @@ -34,7 +34,7 @@ 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, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_obj_list_t *descriptor_list); +extern void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length, 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); diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c index 1ab8c9ecdb..2d4c8df9f2 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -53,13 +53,19 @@ //| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. //| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which //| security mode is required. Values allowed are the same as `read_perm`. +//| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is +//| is 512, or possibly 510 if `fixed_length` is False. The default, 20, is the maximum +//| number of data bytes that fit in a single BLE 4.x ATT packet. +//| :param bool fixed_length: True if the characteristic value is of fixed length. //| STATIC mp_obj_t bleio_descriptor_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_uuid, ARG_read_perm, ARG_write_perm }; + enum { ARG_uuid, ARG_read_perm, ARG_write_perm, ARG_max_length, ARG_fixed_length }; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} }, + { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, }; mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; @@ -81,7 +87,10 @@ STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_ar self->base.type = type; bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_arg); - common_hal_bleio_descriptor_construct(self, uuid, read_perm, write_perm); + // Range checking on max_length arg is done by the common_hal layer, because + // it may vary depending on underlying BLE implementation. + common_hal_bleio_descriptor_construct(self, uuid, read_perm, write_perm, + args[ARG_max_length].u_int, args[ARG_fixed_length].u_bool); return MP_OBJ_FROM_PTR(self); } @@ -123,9 +132,41 @@ const mp_obj_property_t bleio_descriptor_characteristic_obj = { (mp_obj_t)&mp_const_none_obj }, }; +//| .. attribute:: value +//| +//| The value of this descriptor. +//| +STATIC mp_obj_t bleio_descriptor_get_value(mp_obj_t self_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return common_hal_bleio_descriptor_get_value(self); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_descriptor_get_value_obj, bleio_descriptor_get_value); + +STATIC mp_obj_t bleio_descriptor_set_value(mp_obj_t self_in, mp_obj_t value_in) { + bleio_descriptor_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_buffer_info_t bufinfo; + mp_get_buffer_raise(value_in, &bufinfo, MP_BUFFER_READ); + + common_hal_bleio_descriptor_set_value(self, &bufinfo); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_descriptor_set_value_obj, bleio_descriptor_set_value); + +const mp_obj_property_t bleio_descriptor_value_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_descriptor_get_value_obj, + (mp_obj_t)&bleio_descriptor_set_value_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + STATIC const mp_rom_map_elem_t bleio_descriptor_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_uuid), MP_ROM_PTR(&bleio_descriptor_uuid_obj) }, + { MP_ROM_QSTR(MP_QSTR_characteristic), MP_ROM_PTR(&bleio_descriptor_characteristic_obj) }, + { MP_ROM_QSTR(MP_QSTR_value), MP_ROM_PTR(&bleio_descriptor_value_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_descriptor_locals_dict, bleio_descriptor_locals_dict_table); diff --git a/shared-bindings/bleio/Descriptor.h b/shared-bindings/bleio/Descriptor.h index eefce03d11..430c0d0b62 100644 --- a/shared-bindings/bleio/Descriptor.h +++ b/shared-bindings/bleio/Descriptor.h @@ -34,8 +34,10 @@ 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, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm); +extern void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid, bleio_attribute_security_mode_t read_perm, bleio_attribute_security_mode_t write_perm, mp_int_t max_length, bool fixed_length); extern bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self); -extern mp_obj_t common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self); +extern bleio_characteristic_obj_t *common_hal_bleio_descriptor_get_characteristic(bleio_descriptor_obj_t *self); +extern mp_obj_t common_hal_bleio_descriptor_get_value(bleio_descriptor_obj_t *self); +extern void common_hal_bleio_descriptor_set_value(bleio_descriptor_obj_t *self, mp_buffer_info_t *bufinfo); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DESCRIPTOR_H From af29fc3ea8440445c9ae32eee1090c544bd848e9 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Thu, 15 Aug 2019 21:54:52 -0400 Subject: [PATCH 8/9] make translate and fix sphinx issues --- locale/ID.po | 72 ++++++++++++++++++----- locale/circuitpython.pot | 72 ++++++++++++++++++----- locale/de_DE.po | 72 ++++++++++++++++++----- locale/en_US.po | 72 ++++++++++++++++++----- locale/en_x_pirate.po | 72 ++++++++++++++++++----- locale/es.po | 75 +++++++++++++++++++----- locale/fil.po | 72 ++++++++++++++++++----- locale/fr.po | 75 +++++++++++++++++++----- locale/it_IT.po | 72 ++++++++++++++++++----- locale/pl.po | 75 +++++++++++++++++++----- locale/pt_BR.po | 72 ++++++++++++++++++----- locale/zh_Latn_pinyin.po | 80 +++++++++++++++++++++----- shared-bindings/bleio/Attribute.c | 3 +- shared-bindings/bleio/Characteristic.c | 8 +-- shared-bindings/bleio/Descriptor.c | 4 +- 15 files changed, 731 insertions(+), 165 deletions(-) diff --git a/locale/ID.po b/locale/ID.po index e8fdf3595f..438dca55f0 100644 --- a/locale/ID.po +++ b/locale/ID.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -364,7 +364,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -433,6 +433,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -508,6 +512,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "Tidak bisa menyesuaikan data ke dalam paket advertisment" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -602,7 +610,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Gagal untuk melanjutkan scanning, status: 0x%08lX" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "Gagal untuk menemukan layanan, status: 0x%08lX" @@ -622,17 +630,22 @@ msgstr "Gagal untuk mendapatkan status softdevice, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, fuzzy, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Gagal untuk membaca nilai atribut, status: 0x%08lX" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX" @@ -662,6 +675,11 @@ msgstr "Gagal untuk memulai advertisement, status: 0x%08lX" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" @@ -677,12 +695,12 @@ msgstr "Gagal untuk memberhentikan advertisement, status: 0x%08lX" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Gagal untuk menulis nilai atribut, status: 0x%08lX" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Gagal untuk menulis nilai gatts, status: 0x%08lX" @@ -828,10 +846,18 @@ msgstr "Pin-pin tidak valid" msgid "Invalid polarity" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "" @@ -950,8 +976,9 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Tidak dapat menyambungkan ke AP" @@ -1289,6 +1316,19 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1388,10 +1428,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "mode compile buruk" @@ -1709,6 +1745,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "'except' standar harus terakhir" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2048,6 +2088,12 @@ msgstr "" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2147,8 +2193,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/circuitpython.pot b/locale/circuitpython.pot index a2e66cc5d8..8cfbcfe858 100644 --- a/locale/circuitpython.pot +++ b/locale/circuitpython.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -359,7 +359,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -423,6 +423,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -497,6 +501,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -590,7 +598,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "" @@ -607,17 +615,22 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "" @@ -647,6 +660,11 @@ msgstr "" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -662,12 +680,12 @@ msgstr "" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "" @@ -813,10 +831,18 @@ msgstr "" msgid "Invalid polarity" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "" @@ -935,8 +961,9 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1265,6 +1292,19 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1355,10 +1395,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1675,6 +1711,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2014,6 +2054,12 @@ msgstr "" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2112,8 +2158,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/de_DE.po b/locale/de_DE.po index 3037a5369d..7551b1e6db 100644 --- a/locale/de_DE.po +++ b/locale/de_DE.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: Pascal Deneaux\n" "Language-Team: Sebastian Plamauer, Pascal Deneaux\n" @@ -363,7 +363,7 @@ msgid "Can not use dotstar with %s" msgstr "Kann dotstar nicht mit %s verwenden" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -427,6 +427,10 @@ msgstr "Characteristic UUID stimmt nicht mit der Service-UUID überein" msgid "Characteristic already in use by another Service." msgstr "Characteristic wird bereits von einem anderen Dienst verwendet." +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "Schreiben von CharacteristicBuffer ist nicht vorgesehen" @@ -501,6 +505,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "Zu vielen Daten für das advertisement packet" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Die Zielkapazität ist kleiner als destination_length." @@ -594,7 +602,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Der Scanvorgang kann nicht fortgesetzt werden. Status: 0x%04x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "Es konnten keine Dienste gefunden werden" @@ -611,17 +619,22 @@ msgstr "Fehler beim Abrufen des Softdevice-Status" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Kann CCCD value nicht lesen. Status: 0x%04x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "gatts value konnte nicht gelesen werden. Status: 0x%04x" @@ -651,6 +664,11 @@ msgstr "Kann advertisement nicht starten. Status: 0x%04x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -666,12 +684,12 @@ msgstr "Kann advertisement nicht stoppen. Status: 0x%04x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Kann den Attributwert nicht schreiben. Status: 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "gatts value konnte nicht geschrieben werden. Status: 0x%04x" @@ -819,10 +837,18 @@ msgstr "Ungültige Pins" msgid "Invalid polarity" msgstr "Ungültige Polarität" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Ungültiger Ausführungsmodus" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "Ungültige Anzahl von Stimmen" @@ -948,8 +974,9 @@ msgstr "Kein Speicherplatz auf Gerät" msgid "No such file/directory" msgstr "Keine solche Datei/Verzeichnis" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "Nicht verbunden" @@ -1296,6 +1323,19 @@ msgstr "Nicht unterstützte Operation" msgid "Unsupported pull value." msgstr "Nicht unterstützter Pull-Wert" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "Viper-Funktionen unterstützen derzeit nicht mehr als 4 Argumente" @@ -1395,10 +1435,6 @@ msgstr "Array/Bytes auf der rechten Seite erforderlich" msgid "attributes not supported yet" msgstr "Attribute werden noch nicht unterstützt" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1715,6 +1751,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "Die Standart-Ausnahmebehandlung muss als letztes sein" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2061,6 +2101,12 @@ msgstr "map buffer zu klein" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "maximale Rekursionstiefe überschritten" @@ -2159,8 +2205,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/en_US.po b/locale/en_US.po index 6d15af4dd7..fd176c869a 100644 --- a/locale/en_US.po +++ b/locale/en_US.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: \n" @@ -359,7 +359,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -423,6 +423,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -497,6 +501,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -590,7 +598,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "" @@ -607,17 +615,22 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "" @@ -647,6 +660,11 @@ msgstr "" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -662,12 +680,12 @@ msgstr "" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "" @@ -813,10 +831,18 @@ msgstr "" msgid "Invalid polarity" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "" @@ -935,8 +961,9 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1265,6 +1292,19 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1355,10 +1395,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1675,6 +1711,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2014,6 +2054,12 @@ msgstr "" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2112,8 +2158,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/en_x_pirate.po b/locale/en_x_pirate.po index 57bb45380b..f0aa992939 100644 --- a/locale/en_x_pirate.po +++ b/locale/en_x_pirate.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-07-27 11:55-0700\n" "Last-Translator: \n" "Language-Team: @sommersoft, @MrCertainly\n" @@ -363,7 +363,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -427,6 +427,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -501,6 +505,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -594,7 +602,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "" @@ -611,17 +619,22 @@ msgstr "" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "" @@ -651,6 +664,11 @@ msgstr "" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -666,12 +684,12 @@ msgstr "" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "" @@ -817,10 +835,18 @@ msgstr "" msgid "Invalid polarity" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "" @@ -939,8 +965,9 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "" @@ -1269,6 +1296,19 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1359,10 +1399,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1679,6 +1715,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2018,6 +2058,12 @@ msgstr "" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2116,8 +2162,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/es.po b/locale/es.po index a3ffe57991..c90be4e02c 100644 --- a/locale/es.po +++ b/locale/es.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-31 16:30-0500\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-08-24 22:56-0500\n" "Last-Translator: \n" "Language-Team: \n" @@ -367,7 +367,7 @@ msgid "Can not use dotstar with %s" msgstr "No se puede usar dotstar con %s" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -431,6 +431,10 @@ msgstr "Características UUID no concide con el Service UUID" msgid "Characteristic already in use by another Service." msgstr "Características ya esta en uso por otro Serivice" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "CharateristicBuffer escritura no proporcionada" @@ -505,6 +509,10 @@ msgstr "Trozo de datos debe seguir fmt chunk" msgid "Data too large for advertisement packet" msgstr "Data es muy grande para el paquete de advertisement." +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Capacidad de destino es mas pequeña que destination_length." @@ -598,7 +606,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "No se puede iniciar el escaneo. err: 0x%02x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "No se puede descubrir servicios" @@ -616,17 +624,22 @@ msgstr "No se puede obtener el estado del softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Error al notificar o indicar el valor del atributo, err 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "No se puede leer el valor del atributo. err 0x%02x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Error al leer valor del atributo, err 0x%04" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "No se puede escribir el valor del atributo. status: 0x%02x" @@ -656,6 +669,11 @@ msgstr "No se puede inicar el anuncio. err: 0x%04x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -671,12 +689,12 @@ msgstr "No se puede detener el anuncio. err: 0x%04x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "No se puede escribir el valor del atributo. err: 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "No se puede escribir el valor del atributo. err: 0x%04x" @@ -824,10 +842,18 @@ msgstr "pines inválidos" msgid "Invalid polarity" msgstr "Polaridad inválida" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Modo de ejecución inválido." +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "Cuenta de voces inválida" @@ -950,8 +976,9 @@ msgstr "No queda espacio en el dispositivo" msgid "No such file/directory" msgstr "No existe el archivo/directorio" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "No conectado" @@ -1306,6 +1333,19 @@ msgstr "Operación no soportada" msgid "Unsupported pull value." msgstr "valor pull no soportado." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "funciones Viper actualmente no soportan más de 4 argumentos." @@ -1404,10 +1444,6 @@ msgstr "array/bytes requeridos en el lado derecho" msgid "attributes not supported yet" msgstr "atributos aún no soportados" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "mal GATT role" - #: py/builtinevex.c msgid "bad compile mode" msgstr "modo de compilación erroneo" @@ -1729,6 +1765,10 @@ msgstr "números decimales no soportados" msgid "default 'except' must be last" msgstr "'except' por defecto deberia estar de último" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2073,6 +2113,12 @@ msgstr "map buffer muy pequeño" msgid "math domain error" msgstr "error de dominio matemático" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profundidad máxima de recursión excedida" @@ -2171,8 +2217,8 @@ msgstr "no hay tal atributo" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c @@ -2866,6 +2912,9 @@ msgstr "paso cero" #~ msgstr "" #~ "Usa esptool para borrar la flash y vuelve a cargar Python en su lugar" +#~ msgid "bad GATT role" +#~ msgstr "mal GATT role" + #~ msgid "buffer too long" #~ msgstr "buffer demasiado largo" diff --git a/locale/fil.po b/locale/fil.po index f834298829..d2535cc383 100644 --- a/locale/fil.po +++ b/locale/fil.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-31 16:30-0500\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-12-20 22:15-0800\n" "Last-Translator: Timothy \n" "Language-Team: fil\n" @@ -366,7 +366,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -431,6 +431,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -508,6 +512,10 @@ msgstr "Dapat sunurin ng Data chunk ang fmt chunk" msgid "Data too large for advertisement packet" msgstr "Hindi makasya ang data sa loob ng advertisement packet" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -605,7 +613,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Hindi maituloy ang pag scan, status: 0x%0xlX" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "Nabigo sa pagdiscover ng services, status: 0x%08lX" @@ -625,17 +633,22 @@ msgstr "Nabigo sa pagkuha ng softdevice state, error: 0x%08lX" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, fuzzy, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Hindi mabasa ang value ng attribute, status: 0x%08lX" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Hindi maisulat ang gatts value, status: 0x%08lX" @@ -665,6 +678,11 @@ msgstr "Hindi masimulaan ang advertisement, status: 0x%08lX" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" @@ -680,12 +698,12 @@ msgstr "Hindi mahinto ang advertisement, status: 0x%08lX" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Hindi maisulat ang attribute value, status: 0x%08lX" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Hindi maisulat ang gatts value, status: 0x%08lX" @@ -833,10 +851,18 @@ msgstr "Mali ang pins" msgid "Invalid polarity" msgstr "Mali ang polarity" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Mali ang run mode." +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "Maling bilang ng voice" @@ -959,8 +985,9 @@ msgstr "" msgid "No such file/directory" msgstr "Walang file/directory" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Hindi maka connect sa AP" @@ -1310,6 +1337,19 @@ msgstr "Hindi sinusuportahang operasyon" msgid "Unsupported pull value." msgstr "Hindi suportado ang pull value." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1408,10 +1448,6 @@ msgstr "array/bytes kinakailangan sa kanang bahagi" msgid "attributes not supported yet" msgstr "attributes hindi sinusuportahan" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "masamang mode ng compile" @@ -1735,6 +1771,10 @@ msgstr "decimal numbers hindi sinusuportahan" msgid "default 'except' must be last" msgstr "default 'except' ay dapat sa huli" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2084,6 +2124,12 @@ msgstr "masyadong maliit ang buffer map" msgid "math domain error" msgstr "may pagkakamali sa math domain" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "lumagpas ang maximum recursion depth" @@ -2183,8 +2229,8 @@ msgstr "walang ganoon na attribute" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/fr.po b/locale/fr.po index 07355526fd..999d8c4f0d 100644 --- a/locale/fr.po +++ b/locale/fr.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: 0.1\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-31 16:30-0500\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2019-04-14 20:05+0100\n" "Last-Translator: Pierrick Couturier \n" "Language-Team: fr\n" @@ -371,7 +371,7 @@ msgid "Can not use dotstar with %s" msgstr "Impossible d'utiliser 'dotstar' avec %s" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -437,6 +437,10 @@ msgstr "L'UUID de 'Characteristic' ne correspond pas à l'UUID du Service" msgid "Characteristic already in use by another Service." msgstr "'Characteristic' déjà en utilisation par un autre service" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "Ecriture sur 'CharacteristicBuffer' non fournie" @@ -513,6 +517,10 @@ msgstr "Un bloc de données doit suivre un bloc de format" msgid "Data too large for advertisement packet" msgstr "Données trop volumineuses pour un paquet de diffusion" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "La capacité de destination est plus petite que 'destination_length'." @@ -609,7 +617,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Impossible de poursuivre le scan, err 0x%04x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "Echec de la découverte de services" @@ -630,17 +638,22 @@ msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" "Impossible de notifier ou d'indiquer la valeur de l'attribut, err 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, fuzzy, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossible de lire la valeur 'CCCD', err 0x%04x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Impossible de lire la valeur de l'attribut, err 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Impossible de lire la valeur de 'gatts', err 0x%04x" @@ -670,6 +683,11 @@ msgstr "Impossible de commencer à diffuser, err 0x%04x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" @@ -685,12 +703,12 @@ msgstr "Echec de l'arrêt de diffusion, err 0x%04x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Impossible d'écrire la valeur de l'attribut, err 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Impossible d'écrire la valeur de 'gatts', err 0x%04x" @@ -841,10 +859,18 @@ msgstr "Broches invalides" msgid "Invalid polarity" msgstr "Polarité invalide" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Mode de lancement invalide." +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c #, fuzzy msgid "Invalid voice count" @@ -968,8 +994,9 @@ msgstr "Il n'y a plus d'espace libre sur le périphérique" msgid "No such file/directory" msgstr "Fichier/dossier introuvable" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Non connecté" @@ -1335,6 +1362,19 @@ msgstr "Opération non supportée" msgid "Unsupported pull value." msgstr "Valeur de tirage 'pull' non supportée." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1433,10 +1473,6 @@ msgstr "tableau/octets requis à droite" msgid "attributes not supported yet" msgstr "attribut pas encore supporté" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "mauvais rôle GATT" - #: py/builtinevex.c msgid "bad compile mode" msgstr "mauvais mode de compilation" @@ -1771,6 +1807,10 @@ msgstr "nombres décimaux non supportés" msgid "default 'except' must be last" msgstr "l''except' par défaut doit être en dernier" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2117,6 +2157,12 @@ msgstr "tampon trop petit" msgid "math domain error" msgstr "erreur de domaine math" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profondeur maximale de récursivité dépassée" @@ -2217,8 +2263,8 @@ msgstr "pas de tel attribut" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c @@ -2917,6 +2963,9 @@ msgstr "'step' nul" #~ msgstr "" #~ "Utilisez 'esptool' pour effacer la flash et recharger Python à la place" +#~ msgid "bad GATT role" +#~ msgstr "mauvais rôle GATT" + #~ msgid "buffer too long" #~ msgstr "tampon trop long" diff --git a/locale/it_IT.po b/locale/it_IT.po index 4360cd2214..411c9125af 100644 --- a/locale/it_IT.po +++ b/locale/it_IT.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-31 16:30-0500\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-10-02 16:27+0200\n" "Last-Translator: Enrico Paganin \n" "Language-Team: \n" @@ -366,7 +366,7 @@ msgid "Can not use dotstar with %s" msgstr "dotstar non può essere usato con %s" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -432,6 +432,10 @@ msgstr "caratteristico UUID non assomiglia servizio UUID" msgid "Characteristic already in use by another Service." msgstr "caratteristico già usato da un altro servizio" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "CharacteristicBuffer scritura non dato" @@ -509,6 +513,10 @@ msgstr "" msgid "Data too large for advertisement packet" msgstr "Impossibile inserire dati nel pacchetto di advertisement." +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "La capacità di destinazione è più piccola di destination_length." @@ -605,7 +613,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Impossible iniziare la scansione. status: 0x%02x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "Impossibile fermare advertisement. status: 0x%02x" @@ -624,17 +632,22 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Notificamento o indicazione di attribute value fallito, err 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, fuzzy, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Impossibile leggere valore dell'attributo. status: 0x%02x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Tentative leggere attribute value fallito, err 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x" @@ -664,6 +677,11 @@ msgstr "Impossibile avviare advertisement. status: 0x%02x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" @@ -679,12 +697,12 @@ msgstr "Impossibile fermare advertisement. status: 0x%02x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Impossibile scrivere valore dell'attributo. status: 0x%02x" @@ -834,10 +852,18 @@ msgstr "Pin non validi" msgid "Invalid polarity" msgstr "Polarità non valida" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Modalità di esecuzione non valida." +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c #, fuzzy msgid "Invalid voice count" @@ -958,8 +984,9 @@ msgstr "Non che spazio sul dispositivo" msgid "No such file/directory" msgstr "Nessun file/directory esistente" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Impossible connettersi all'AP" @@ -1309,6 +1336,19 @@ msgstr "Operazione non supportata" msgid "Unsupported pull value." msgstr "Valore di pull non supportato." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "Le funzioni Viper non supportano più di 4 argomenti al momento" @@ -1402,10 +1442,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "attributi non ancora supportati" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1728,6 +1764,10 @@ msgstr "numeri decimali non supportati" msgid "default 'except' must be last" msgstr "'except' predefinito deve essere ultimo" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2077,6 +2117,12 @@ msgstr "map buffer troppo piccolo" msgid "math domain error" msgstr "errore di dominio matematico" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "profondità massima di ricorsione superata" @@ -2177,8 +2223,8 @@ msgstr "attributo inesistente" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/pl.po b/locale/pl.po index 0a38aa9144..caa5df76df 100644 --- a/locale/pl.po +++ b/locale/pl.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: \n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2019-03-19 18:37-0700\n" "Last-Translator: Radomir Dopieralski \n" "Language-Team: pl\n" @@ -362,7 +362,7 @@ msgid "Can not use dotstar with %s" msgstr "Nie można używać dotstar z %s" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -426,6 +426,10 @@ msgstr "UUID charakterystyki inny niż UUID serwisu" msgid "Characteristic already in use by another Service." msgstr "Charakterystyka w użyciu w innym serwisie" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "Pisanie do CharacteristicBuffer niewspierane" @@ -500,6 +504,10 @@ msgstr "Fragment danych musi następować po fragmencie fmt" msgid "Data too large for advertisement packet" msgstr "Zbyt dużo danych pakietu rozgłoszeniowego" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Pojemność celu mniejsza od destination_length." @@ -593,7 +601,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Nie udała się kontynuacja skanowania, błąd 0x%04x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "Nie udało się odkryć serwisów" @@ -610,17 +618,22 @@ msgstr "Nie udało się odczytać stanu softdevice" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Nie udało się powiadomić o wartości atrybutu, błąd 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Nie udało się odczytać CCCD, błąd 0x%04x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Nie udało się odczytać wartości atrybutu, błąd 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Nie udało się odczytać gatts, błąd 0x%04x" @@ -650,6 +663,11 @@ msgstr "Nie udało się rozpocząć rozgłaszania, błąd 0x%04x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -665,12 +683,12 @@ msgstr "Nie udało się zatrzymać rozgłaszania, błąd 0x%04x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Nie udało się zapisać atrybutu, błąd 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Nie udało się zapisać gatts, błąd 0x%04x" @@ -818,10 +836,18 @@ msgstr "Złe nóżki" msgid "Invalid polarity" msgstr "Zła polaryzacja" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Zły tryb uruchomienia" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "Zła liczba głosów" @@ -945,8 +971,9 @@ msgstr "Brak miejsca" msgid "No such file/directory" msgstr "Brak pliku/katalogu" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "Nie podłączono" @@ -1285,6 +1312,19 @@ msgstr "Zła operacja" msgid "Unsupported pull value." msgstr "Zła wartość podciągnięcia." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "Funkcje Viper nie obsługują obecnie więcej niż 4 argumentów" @@ -1379,10 +1419,6 @@ msgstr "tablica/bytes wymagane po prawej stronie" msgid "attributes not supported yet" msgstr "atrybuty nie są jeszcze obsługiwane" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "zła rola GATT" - #: py/builtinevex.c msgid "bad compile mode" msgstr "zły tryb kompilacji" @@ -1699,6 +1735,10 @@ msgstr "liczby dziesiętne nieobsługiwane" msgid "default 'except' must be last" msgstr "domyślny 'except' musi być ostatni" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2039,6 +2079,12 @@ msgstr "bufor mapy zbyt mały" msgid "math domain error" msgstr "błąd domeny" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "przekroczono dozwoloną głębokość rekurencji" @@ -2137,8 +2183,8 @@ msgstr "nie ma takiego atrybutu" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c @@ -2708,6 +2754,9 @@ msgstr "zerowy krok" #~ msgid "UUID integer value not in range 0 to 0xffff" #~ msgstr "Wartość UUID poza zakresem 0 do 0xffff" +#~ msgid "bad GATT role" +#~ msgstr "zła rola GATT" + #~ msgid "interval not in range 0.0020 to 10.24" #~ msgstr "przedział poza zakresem 0.0020 do 10.24" diff --git a/locale/pt_BR.po b/locale/pt_BR.po index defeb3e44c..79a83d2f65 100644 --- a/locale/pt_BR.po +++ b/locale/pt_BR.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-07-31 16:30-0500\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2018-10-02 21:14-0000\n" "Last-Translator: \n" "Language-Team: \n" @@ -363,7 +363,7 @@ msgid "Can not use dotstar with %s" msgstr "" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" +msgid "Can't set CCCD on local Characteristic" msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c @@ -428,6 +428,10 @@ msgstr "" msgid "Characteristic already in use by another Service." msgstr "" +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "" @@ -504,6 +508,10 @@ msgstr "Pedaço de dados deve seguir o pedaço de cortes" msgid "Data too large for advertisement packet" msgstr "Não é possível ajustar dados no pacote de anúncios." +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "" @@ -600,7 +608,7 @@ msgstr "" msgid "Failed to continue scanning, err 0x%04x" msgstr "Não é possível iniciar o anúncio. status: 0x%02x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy msgid "Failed to discover services" msgstr "Não pode parar propaganda. status: 0x%02x" @@ -619,17 +627,22 @@ msgstr "Não pode parar propaganda. status: 0x%02x" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, fuzzy, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Não é possível ler o valor do atributo. status: 0x%02x" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" @@ -659,6 +672,11 @@ msgstr "Não é possível iniciar o anúncio. status: 0x%02x" msgid "Failed to start connecting, error 0x%04x" msgstr "" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, fuzzy, c-format msgid "Failed to start scanning, err 0x%04x" @@ -674,12 +692,12 @@ msgstr "Não pode parar propaganda. status: 0x%02x" msgid "Failed to write CCCD, err 0x%04x" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, fuzzy, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Não é possível gravar o valor do atributo. status: 0x%02x" @@ -827,10 +845,18 @@ msgstr "Pinos inválidos" msgid "Invalid polarity" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "" +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c #, fuzzy msgid "Invalid voice count" @@ -950,8 +976,9 @@ msgstr "" msgid "No such file/directory" msgstr "" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c #, fuzzy msgid "Not connected" msgstr "Não é possível conectar-se ao AP" @@ -1286,6 +1313,19 @@ msgstr "" msgid "Unsupported pull value." msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "" @@ -1376,10 +1416,6 @@ msgstr "" msgid "attributes not supported yet" msgstr "atributos ainda não suportados" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "" - #: py/builtinevex.c msgid "bad compile mode" msgstr "" @@ -1699,6 +1735,10 @@ msgstr "" msgid "default 'except' must be last" msgstr "" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2039,6 +2079,12 @@ msgstr "" msgid "math domain error" msgstr "" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "" @@ -2138,8 +2184,8 @@ msgstr "" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c diff --git a/locale/zh_Latn_pinyin.po b/locale/zh_Latn_pinyin.po index c0537202cc..a42f8bae49 100644 --- a/locale/zh_Latn_pinyin.po +++ b/locale/zh_Latn_pinyin.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: circuitpython-cn\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2019-08-05 17:52-0700\n" +"POT-Creation-Date: 2019-08-15 21:44-0400\n" "PO-Revision-Date: 2019-04-13 10:10-0700\n" "Last-Translator: hexthat\n" "Language-Team: Chinese Hanyu Pinyin\n" @@ -363,8 +363,8 @@ msgid "Can not use dotstar with %s" msgstr "Wúfǎ yǔ dotstar yīqǐ shǐyòng %s" #: ports/nrf/common-hal/bleio/Characteristic.c -msgid "Can't set CCCD for local Characteristic" -msgstr "Wúfǎ wéi běndì tèzhēng shèzhì CCCD" +msgid "Can't set CCCD on local Characteristic" +msgstr "" #: shared-bindings/displayio/Bitmap.c shared-bindings/pulseio/PulseIn.c msgid "Cannot delete values" @@ -427,6 +427,10 @@ msgstr "Zìfú UUID bù fúhé fúwù UUID" msgid "Characteristic already in use by another Service." msgstr "Qítā fúwù bùmén yǐ shǐyòng de gōngnéng." +#: shared-bindings/bleio/Service.c +msgid "Characteristic is already attached to a Service" +msgstr "" + #: shared-bindings/bleio/CharacteristicBuffer.c msgid "CharacteristicBuffer writing not provided" msgstr "Wèi tígōng zìfú huǎncún xiě rù" @@ -501,6 +505,10 @@ msgstr "Shùjù kuài bìxū zūnxún fmt qū kuài" msgid "Data too large for advertisement packet" msgstr "Guǎnggào bāo de shùjù tài dà" +#: shared-bindings/bleio/Characteristic.c +msgid "Descriptor is already attached to a Characteristic" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "Destination capacity is smaller than destination_length." msgstr "Mùbiāo róngliàng xiǎoyú mùdì de_chángdù." @@ -594,7 +602,7 @@ msgstr "Liánjiē shībài: Chāoshí" msgid "Failed to continue scanning, err 0x%04x" msgstr "Jìxù sǎomiáo shībài, err 0x%04x" -#: ports/nrf/common-hal/bleio/Central.c +#: ports/nrf/common-hal/bleio/__init__.c msgid "Failed to discover services" msgstr "Fāxiàn fúwù shībài" @@ -611,17 +619,22 @@ msgstr "Wúfǎ huòdé ruǎnjiàn shèbèi zhuàngtài" msgid "Failed to notify or indicate attribute value, err 0x%04x" msgstr "Wúfǎ tōngzhī huò xiǎnshì shǔxìng zhí, err 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +msgid "Failed to pair" +msgstr "" + #: ports/nrf/common-hal/bleio/Characteristic.c #, c-format msgid "Failed to read CCCD value, err 0x%04x" msgstr "Dòu qǔ CCCD zhí, err 0x%04x shībài" #: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c #, c-format msgid "Failed to read attribute value, err 0x%04x" msgstr "Dòu qǔ shǔxìng zhí shībài, err 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to read gatts value, err 0x%04x" msgstr "Wúfǎ dòu qǔ gatts zhí, err 0x%04x" @@ -651,6 +664,11 @@ msgstr "Qǐdòng guǎnggào shībài, err 0x%04x" msgid "Failed to start connecting, error 0x%04x" msgstr "Wúfǎ kāishǐ liánjiē, cuòwù 0x%04x" +#: ports/nrf/common-hal/bleio/Peripheral.c +#, c-format +msgid "Failed to start pairing, error 0x%04x" +msgstr "" + #: ports/nrf/common-hal/bleio/Scanner.c #, c-format msgid "Failed to start scanning, err 0x%04x" @@ -666,12 +684,12 @@ msgstr "Wúfǎ tíngzhǐ guǎnggào, err 0x%04x" msgid "Failed to write CCCD, err 0x%04x" msgstr "Wúfǎ xiě rù CCCD, cuòwù 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write attribute value, err 0x%04x" msgstr "Xiě rù shǔxìng zhí shībài, err 0x%04x" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c #, c-format msgid "Failed to write gatts value, err 0x%04x" msgstr "Xiě rù gatts zhí,err 0x%04x shībài" @@ -819,10 +837,18 @@ msgstr "Wúxiào de yǐn jiǎo" msgid "Invalid polarity" msgstr "Wúxiào liǎng jí zhí" +#: shared-bindings/bleio/Characteristic.c +msgid "Invalid properties" +msgstr "" + #: shared-bindings/microcontroller/__init__.c msgid "Invalid run mode." msgstr "Wúxiào de yùnxíng móshì." +#: shared-module/bleio/Attribute.c +msgid "Invalid security_mode" +msgstr "" + #: shared-bindings/audiocore/Mixer.c msgid "Invalid voice count" msgstr "Wúxiào de yǔyīn jìshù" @@ -945,8 +971,9 @@ msgstr "Shèbèi shàng méiyǒu kònggé" msgid "No such file/directory" msgstr "Méiyǒu cǐ lèi wénjiàn/mùlù" -#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/__init__.c shared-bindings/bleio/Central.c #: shared-bindings/bleio/CharacteristicBuffer.c +#: shared-bindings/bleio/Peripheral.c msgid "Not connected" msgstr "Wèi liánjiē" @@ -1292,6 +1319,19 @@ msgstr "Bù zhīchí de cāozuò" msgid "Unsupported pull value." msgstr "Bù zhīchí de lādòng zhí." +#: ports/nrf/common-hal/bleio/Characteristic.c +msgid "Value length required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length != required fixed length" +msgstr "" + +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +msgid "Value length > max_length" +msgstr "" + #: py/emitnative.c msgid "Viper functions don't currently support more than 4 arguments" msgstr "Viper hánshù mùqián bù zhīchí chāoguò 4 gè cānshù" @@ -1389,10 +1429,6 @@ msgstr "yòu cè xūyào shùzǔ/zì jié" msgid "attributes not supported yet" msgstr "shǔxìng shàngwèi zhīchí" -#: ports/nrf/common-hal/bleio/Characteristic.c -msgid "bad GATT role" -msgstr "zǒng xiédìng de bùliáng juésè" - #: py/builtinevex.c msgid "bad compile mode" msgstr "biānyì móshì cuòwù" @@ -1711,6 +1747,10 @@ msgstr "bù zhīchí xiǎoshù shù" msgid "default 'except' must be last" msgstr "mòrèn 'except' bìxū shì zuìhòu yīgè" +#: shared-bindings/bleio/Characteristic.c +msgid "descriptors includes an object that is not a Descriptors" +msgstr "" + #: shared-bindings/audiobusio/PDMIn.c msgid "" "destination buffer must be a bytearray or array of type 'B' for bit_depth = 8" @@ -2052,6 +2092,12 @@ msgstr "dìtú huǎnchōng qū tài xiǎo" msgid "math domain error" msgstr "shùxué yù cuòwù" +#: ports/nrf/common-hal/bleio/Characteristic.c +#: ports/nrf/common-hal/bleio/Descriptor.c +#, c-format +msgid "max_length must be 0-%d when fixed_length is %s" +msgstr "" + #: py/runtime.c msgid "maximum recursion depth exceeded" msgstr "chāochū zuìdà dìguī shēndù" @@ -2151,8 +2197,8 @@ msgstr "méiyǒu cǐ shǔxìng" msgid "non-Service found in services" msgstr "" -#: ports/nrf/common-hal/bleio/Central.c -msgid "non-UUID found in service_uuids" +#: ports/nrf/common-hal/bleio/__init__.c +msgid "non-UUID found in service_uuids_whitelist" msgstr "" #: py/compile.c @@ -2674,6 +2720,9 @@ msgstr "líng bù" #~ msgid "Can't connect in Peripheral mode" #~ msgstr "Wúfǎ zài biānyuán móshì zhōng liánjiē" +#~ msgid "Can't set CCCD for local Characteristic" +#~ msgstr "Wúfǎ wéi běndì tèzhēng shèzhì CCCD" + #~ msgid "Data too large for the advertisement packet" #~ msgstr "Guǎnggào bāo de shùjù tài dà" @@ -2734,6 +2783,9 @@ msgstr "líng bù" #~ msgid "UUID integer value not in range 0 to 0xffff" #~ msgstr "UUID zhěngshù zhí bùzài fànwéi 0 zhì 0xffff" +#~ msgid "bad GATT role" +#~ msgstr "zǒng xiédìng de bùliáng juésè" + #~ msgid "expected a DigitalInOut" #~ msgstr "qídài de DigitalInOut" diff --git a/shared-bindings/bleio/Attribute.c b/shared-bindings/bleio/Attribute.c index ef6b17253b..cbbc07b9e3 100644 --- a/shared-bindings/bleio/Attribute.c +++ b/shared-bindings/bleio/Attribute.c @@ -37,7 +37,8 @@ //| ========================================================= //| //| Definitions associated with all BLE attributes: characteristics, descriptors, etc. -//| :py:class:`~bleio.Attribute` is, notionally, a superclass of `Characteristic` and `Descriptor`, +//| :py:class:`~bleio.Attribute` is, notionally, a superclass of +//| :py:class:`~Characteristic` and :py:class:`~Descriptor`, //| but is not defined as a Python superclass of those classes. //| //| .. class:: Attribute() diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index 7bcfc6b6da..c9e0f37575 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -54,9 +54,9 @@ //| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`, //| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. //| :param int write_perm: Specifies whether the characteristic can be written by a client, and if so, which -//| security mode is required. Values allowed are the same as `read_perm`. +//| security mode is required. Values allowed are the same as ``read_perm``. //| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is -//| is 512, or possibly 510 if `fixed_length` is False. The default, 20, is the maximum +//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum //| number of data bytes that fit in a single BLE 4.x ATT packet. //| :param bool fixed_length: True if the characteristic value is of fixed length. //| :param iterable descriptors: BLE descriptors for this characteristic. @@ -173,9 +173,7 @@ const mp_obj_property_t bleio_characteristic_uuid_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. +//| The value of this characteristic. //| STATIC mp_obj_t bleio_characteristic_get_value(mp_obj_t self_in) { bleio_characteristic_obj_t *self = MP_OBJ_TO_PTR(self_in); diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c index 2d4c8df9f2..95477336e4 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -52,9 +52,9 @@ //| `Attribute.ENCRYPT_NO_MITM`, `Attribute.ENCRYPT_WITH_MITM`, `Attribute.LESC_ENCRYPT_WITH_MITM`, //| `Attribute.SIGNED_NO_MITM`, or `Attribute.SIGNED_WITH_MITM`. //| :param int write_perm: Specifies whether the descriptor can be written by a client, and if so, which -//| security mode is required. Values allowed are the same as `read_perm`. +//| security mode is required. Values allowed are the same as ``read_perm``. //| :param int max_length: Maximum length in bytes of the characteristic value. The maximum allowed is -//| is 512, or possibly 510 if `fixed_length` is False. The default, 20, is the maximum +//| is 512, or possibly 510 if ``fixed_length`` is False. The default, 20, is the maximum //| number of data bytes that fit in a single BLE 4.x ATT packet. //| :param bool fixed_length: True if the characteristic value is of fixed length. //| From 630c92392abef67b0e6f81c98316dea93d3b2376 Mon Sep 17 00:00:00 2001 From: Dan Halbert Date: Fri, 16 Aug 2019 15:18:53 -0400 Subject: [PATCH 9/9] address review comments; avoid calling common_hal_bleio_device... routines from shared-bindings --- ports/nrf/common-hal/bleio/Attribute.c | 14 ++++---- ports/nrf/common-hal/bleio/Central.c | 11 +++++- ports/nrf/common-hal/bleio/Peripheral.c | 11 ++++-- ports/nrf/common-hal/bleio/__init__.c | 4 +-- shared-bindings/bleio/Attribute.c | 14 ++++---- shared-bindings/bleio/Central.c | 45 ++++++------------------- shared-bindings/bleio/Central.h | 3 +- shared-bindings/bleio/Characteristic.c | 4 +-- shared-bindings/bleio/Descriptor.c | 4 +-- shared-bindings/bleio/Peripheral.c | 41 +++++----------------- shared-bindings/bleio/Peripheral.h | 3 +- shared-bindings/bleio/__init__.c | 3 -- shared-module/bleio/Attribute.c | 14 ++++---- shared-module/bleio/Attribute.h | 14 ++++---- 14 files changed, 74 insertions(+), 111 deletions(-) diff --git a/ports/nrf/common-hal/bleio/Attribute.c b/ports/nrf/common-hal/bleio/Attribute.c index bffe682549..fd1e7538da 100644 --- a/ports/nrf/common-hal/bleio/Attribute.c +++ b/ports/nrf/common-hal/bleio/Attribute.c @@ -29,31 +29,31 @@ // Convert a bleio security mode to a ble_gap_conn_sec_mode_t setting. void bleio_attribute_gatts_set_security_mode(ble_gap_conn_sec_mode_t *perm, bleio_attribute_security_mode_t security_mode) { switch (security_mode) { - case SEC_MODE_NO_ACCESS: + case SECURITY_MODE_NO_ACCESS: BLE_GAP_CONN_SEC_MODE_SET_NO_ACCESS(perm); break; - case SEC_MODE_OPEN: + case SECURITY_MODE_OPEN: BLE_GAP_CONN_SEC_MODE_SET_OPEN(perm); break; - case SEC_MODE_ENC_NO_MITM: + case SECURITY_MODE_ENC_NO_MITM: BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(perm); break; - case SEC_MODE_ENC_WITH_MITM: + case SECURITY_MODE_ENC_WITH_MITM: BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(perm); break; - case SEC_MODE_LESC_ENC_WITH_MITM: + case SECURITY_MODE_LESC_ENC_WITH_MITM: BLE_GAP_CONN_SEC_MODE_SET_LESC_ENC_WITH_MITM(perm); break; - case SEC_MODE_SIGNED_NO_MITM: + case SECURITY_MODE_SIGNED_NO_MITM: BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(perm); break; - case SEC_MODE_SIGNED_WITH_MITM: + case SECURITY_MODE_SIGNED_WITH_MITM: BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(perm); break; } diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c index c42a2084ac..d771437d6c 100644 --- a/ports/nrf/common-hal/bleio/Central.c +++ b/ports/nrf/common-hal/bleio/Central.c @@ -34,9 +34,9 @@ #include "nrf_soc.h" #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Central.h" -#include "common-hal/bleio/__init__.h" 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; @@ -131,6 +131,15 @@ bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) { return self->conn_handle != BLE_CONN_HANDLE_INVALID; } +mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist) { + common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); + // Convert to a tuple and then clear the list so the callee will take ownership. + mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_services_list->len, + self->remote_services_list->items); + mp_obj_list_clear(self->remote_services_list); + return services_tuple; +} + mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) { return self->remote_services_list; } diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index 640b931809..ed35516fc9 100644 --- a/ports/nrf/common-hal/bleio/Peripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -36,12 +36,12 @@ #include "py/objlist.h" #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Peripheral.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" -#include "common-hal/bleio/Service.h" #define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS) #define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS) @@ -303,8 +303,13 @@ void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) { sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); } -mp_obj_list_t *common_hal_bleio_peripheral_get_remote_services(bleio_peripheral_obj_t *self) { - return self->remote_services_list; +mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist) { + common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), service_uuids_whitelist); + // Convert to a tuple and then clear the list so the callee will take ownership. + mp_obj_tuple_t *services_tuple = mp_obj_new_tuple(self->remote_services_list->len, + self->remote_services_list->items); + mp_obj_list_clear(self->remote_services_list); + return services_tuple; } void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *self) { diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index 2d144f8b52..2e26ac07d0 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -218,7 +218,7 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, mp_ob // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler. common_hal_bleio_characteristic_construct( - characteristic, uuid, props, SEC_MODE_OPEN, SEC_MODE_OPEN, + characteristic, uuid, props, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, GATT_MAX_DATA_LENGTH, false, // max_length, fixed_length: values may not matter for gattc mp_obj_new_list(0, NULL)); characteristic->handle = gattc_char->handle_value; @@ -274,7 +274,7 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, mp_ob // For now, just leave the UUID as NULL. } - common_hal_bleio_descriptor_construct(descriptor, uuid, SEC_MODE_OPEN, SEC_MODE_OPEN, + common_hal_bleio_descriptor_construct(descriptor, uuid, SECURITY_MODE_OPEN, SECURITY_MODE_OPEN, GATT_MAX_DATA_LENGTH, false); descriptor->handle = gattc_desc->handle; descriptor->characteristic = m_desc_discovery_characteristic; diff --git a/shared-bindings/bleio/Attribute.c b/shared-bindings/bleio/Attribute.c index cbbc07b9e3..2cc9ef6d05 100644 --- a/shared-bindings/bleio/Attribute.c +++ b/shared-bindings/bleio/Attribute.c @@ -76,13 +76,13 @@ STATIC const mp_rom_map_elem_t bleio_attribute_locals_dict_table[] = { //| //| security_mode: authenticated data signing, without man-in-the-middle protection //| - { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SEC_MODE_NO_ACCESS) }, - { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SEC_MODE_OPEN) }, - { MP_ROM_QSTR(MP_QSTR_ENCRYPT_NO_MITM), MP_ROM_INT(SEC_MODE_ENC_NO_MITM) }, - { MP_ROM_QSTR(MP_QSTR_ENCRYPT_WITH_MITM), MP_ROM_INT(SEC_MODE_ENC_WITH_MITM) }, - { MP_ROM_QSTR(MP_QSTR_LESC_ENCRYPT_WITH_MITM), MP_ROM_INT(SEC_MODE_LESC_ENC_WITH_MITM) }, - { MP_ROM_QSTR(MP_QSTR_SIGNED_NO_MITM), MP_ROM_INT(SEC_MODE_SIGNED_NO_MITM) }, - { MP_ROM_QSTR(MP_QSTR_SIGNED_WITH_MITM), MP_ROM_INT(SEC_MODE_SIGNED_WITH_MITM) }, + { MP_ROM_QSTR(MP_QSTR_NO_ACCESS), MP_ROM_INT(SECURITY_MODE_NO_ACCESS) }, + { MP_ROM_QSTR(MP_QSTR_OPEN), MP_ROM_INT(SECURITY_MODE_OPEN) }, + { MP_ROM_QSTR(MP_QSTR_ENCRYPT_NO_MITM), MP_ROM_INT(SECURITY_MODE_ENC_NO_MITM) }, + { MP_ROM_QSTR(MP_QSTR_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_ENC_WITH_MITM) }, + { MP_ROM_QSTR(MP_QSTR_LESC_ENCRYPT_WITH_MITM), MP_ROM_INT(SECURITY_MODE_LESC_ENC_WITH_MITM) }, + { MP_ROM_QSTR(MP_QSTR_SIGNED_NO_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_NO_MITM) }, + { MP_ROM_QSTR(MP_QSTR_SIGNED_WITH_MITM), MP_ROM_INT(SECURITY_MODE_SIGNED_WITH_MITM) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_attribute_locals_dict, bleio_attribute_locals_dict_table); diff --git a/shared-bindings/bleio/Central.c b/shared-bindings/bleio/Central.c index 70b270c65f..1fc455d8db 100644 --- a/shared-bindings/bleio/Central.c +++ b/shared-bindings/bleio/Central.c @@ -34,7 +34,6 @@ #include "py/objproperty.h" #include "py/objstr.h" #include "py/runtime.h" -#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Address.h" #include "shared-bindings/bleio/Characteristic.h" @@ -66,7 +65,7 @@ //| //| central = bleio.Central() //| central.connect(my_entry.address, 10) # timeout after 10 seconds -//| central.discover_remote_services() +//| remote_services = central.discover_remote_services() //| //| .. class:: Central() @@ -132,15 +131,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_dis //| .. method:: discover_remote_services(service_uuids_whitelist=None) //| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics. -//| The attribute `remote_services` will contain a list of all discovered services. -//| `Central.connected` must be True. +//| to find their handles and characteristics, and return the discovered services. +//| `Peripheral.connected` must be True. //| //| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services //| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored. -//| If a service in service_uuids_whitelist is not found during discovery, it will not -//| appear in `remote_services`. +//| The peripheral may provide more services, but services not listed are ignored +//| and will not be returned. //| //| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. //| @@ -149,6 +146,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_disconnect_obj, bleio_central_dis //| service or characteristic to be discovered. Creating the UUID causes the UUID to be registered //| for use. (This restriction may be lifted in the future.) //| +//| :return: A tuple of services provided by the remote peripheral. +//| STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_central_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -164,10 +163,9 @@ STATIC mp_obj_t bleio_central_discover_remote_services(mp_uint_t n_args, const m mp_raise_ValueError(translate("Not connected")); } - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj); - - return mp_const_none; + return MP_OBJ_FROM_PTR(common_hal_bleio_central_discover_remote_services( + MP_OBJ_FROM_PTR(self), + args[ARG_service_uuids_whitelist].u_obj)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_central_discover_remote_services_obj, 1, bleio_central_discover_remote_services); @@ -189,28 +187,6 @@ const mp_obj_property_t bleio_central_connected_obj = { (mp_obj_t)&mp_const_none_obj }, }; - -//| .. attribute:: remote_services (read-only) -//| -//| A tuple of services provided by the remote peripheral. -//| If the Central is not connected, an empty tuple will be returned. -//| -STATIC mp_obj_t bleio_central_get_remote_services(mp_obj_t self_in) { - bleio_central_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 *service_list = common_hal_bleio_central_get_remote_services(self); - return mp_obj_new_tuple(service_list->len, service_list->items); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_central_get_remote_services_obj, bleio_central_get_remote_services); - -const mp_obj_property_t bleio_central_remote_services_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_central_get_remote_services_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_central_connect_obj) }, @@ -219,7 +195,6 @@ STATIC const mp_rom_map_elem_t bleio_central_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_central_connected_obj) }, - { MP_ROM_QSTR(MP_QSTR_remote_services), MP_ROM_PTR(&bleio_central_remote_services_obj) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_central_locals_dict, bleio_central_locals_dict_table); diff --git a/shared-bindings/bleio/Central.h b/shared-bindings/bleio/Central.h index 1d7fb62483..cbc437087b 100644 --- a/shared-bindings/bleio/Central.h +++ b/shared-bindings/bleio/Central.h @@ -28,6 +28,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H +#include "py/objtuple.h" #include "common-hal/bleio/Central.h" #include "common-hal/bleio/Service.h" @@ -37,6 +38,6 @@ extern void common_hal_bleio_central_construct(bleio_central_obj_t *self); extern void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout); extern void common_hal_bleio_central_disconnect(bleio_central_obj_t *self); extern bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self); -extern mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_central_discover_remote_services(bleio_central_obj_t *self, mp_obj_t service_uuids_whitelist); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_CENTRAL_H diff --git a/shared-bindings/bleio/Characteristic.c b/shared-bindings/bleio/Characteristic.c index c9e0f37575..4894ad114a 100644 --- a/shared-bindings/bleio/Characteristic.c +++ b/shared-bindings/bleio/Characteristic.c @@ -67,8 +67,8 @@ STATIC mp_obj_t bleio_characteristic_make_new(const mp_obj_type_t *type, size_t static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_properties, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 0} }, - { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN} }, - { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN} }, + { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} }, + { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN} }, { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} }, { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, { MP_QSTR_descriptors, MP_ARG_KW_ONLY| MP_ARG_OBJ, {.u_obj = mp_const_none} }, diff --git a/shared-bindings/bleio/Descriptor.c b/shared-bindings/bleio/Descriptor.c index 95477336e4..d7c2a85c74 100644 --- a/shared-bindings/bleio/Descriptor.c +++ b/shared-bindings/bleio/Descriptor.c @@ -62,8 +62,8 @@ STATIC mp_obj_t bleio_descriptor_make_new(const mp_obj_type_t *type, size_t n_ar enum { ARG_uuid, ARG_read_perm, ARG_write_perm, ARG_max_length, ARG_fixed_length }; static const mp_arg_t allowed_args[] = { { MP_QSTR_uuid, MP_ARG_REQUIRED | MP_ARG_OBJ }, - { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, - { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SEC_MODE_OPEN } }, + { MP_QSTR_read_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN } }, + { MP_QSTR_write_perm, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = SECURITY_MODE_OPEN } }, { MP_QSTR_max_length, MP_ARG_KW_ONLY| MP_ARG_INT, {.u_int = 20} }, { MP_QSTR_fixed_length, MP_ARG_KW_ONLY| MP_ARG_BOOL, {.u_bool = false} }, }; diff --git a/shared-bindings/bleio/Peripheral.c b/shared-bindings/bleio/Peripheral.c index b42ca37844..630e6ed364 100644 --- a/shared-bindings/bleio/Peripheral.c +++ b/shared-bindings/bleio/Peripheral.c @@ -35,7 +35,6 @@ #include "py/objstr.h" #include "py/runtime.h" -#include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Peripheral.h" @@ -263,15 +262,13 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripher //| .. method:: discover_remote_services(service_uuids_whitelist=None) //| Do BLE discovery for all services or for the given service UUIDS, -//| to find their handles and characteristics. -//| The attribute `remote_services` will contain a list of all discovered services. +//| to find their handles and characteristics, and return the discovered services. //| `Peripheral.connected` must be True. //| //| :param iterable service_uuids_whitelist: an iterable of :py:class:~`UUID` objects for the services //| provided by the peripheral that you want to use. -//| The peripheral may provide more services, but services not listed are ignored. -//| If a service in service_uuids_whitelist is not found during discovery, it will not -//| appear in `remote_services`. +//| The peripheral may provide more services, but services not listed are ignored +//| and will not be returned. //| //| If service_uuids_whitelist is None, then all services will undergo discovery, which can be slow. //| @@ -285,6 +282,8 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_disconnect_obj, bleio_peripher //| Examples include a peripheral accessing a central that provides Current Time Service, //| Apple Notification Center Service, or Battery Service. //| +//| :return: A tuple of services provided by the remote central. +//| STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { bleio_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); @@ -300,27 +299,12 @@ STATIC mp_obj_t bleio_peripheral_discover_remote_services(mp_uint_t n_args, cons mp_raise_ValueError(translate("Not connected")); } - common_hal_bleio_device_discover_remote_services(MP_OBJ_FROM_PTR(self), - args[ARG_service_uuids_whitelist].u_obj); - - return mp_const_none; + return MP_OBJ_FROM_PTR(common_hal_bleio_peripheral_discover_remote_services( + MP_OBJ_FROM_PTR(self), + args[ARG_service_uuids_whitelist].u_obj)); } STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_peripheral_discover_remote_services_obj, 1, bleio_peripheral_discover_remote_services); -//| .. attribute:: remote_services (read-only) -//| -//| A tuple of services provided by the remote central. -//| If discovery did not occur, an empty tuple will be returned. -//| -STATIC mp_obj_t bleio_peripheral_get_remote_services(mp_obj_t self_in) { - bleio_peripheral_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 *service_list = common_hal_bleio_peripheral_get_remote_services(self); - return mp_obj_new_tuple(service_list->len, service_list->items); -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_get_remote_services_obj, bleio_peripheral_get_remote_services); - //| .. method:: pair() //| //| Request pairing with connected central. @@ -333,14 +317,6 @@ STATIC mp_obj_t bleio_peripheral_pair(mp_obj_t self_in) { } STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_peripheral_pair_obj, bleio_peripheral_pair); -const mp_obj_property_t bleio_peripheral_remote_services_obj = { - .base.type = &mp_type_property, - .proxy = { (mp_obj_t)&bleio_peripheral_get_remote_services_obj, - (mp_obj_t)&mp_const_none_obj, - (mp_obj_t)&mp_const_none_obj }, -}; - - STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { // Methods { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_peripheral_start_advertising_obj) }, @@ -352,7 +328,6 @@ STATIC const mp_rom_map_elem_t bleio_peripheral_locals_dict_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_connected), MP_ROM_PTR(&bleio_peripheral_connected_obj) }, { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_peripheral_name_obj) }, - { MP_ROM_QSTR(MP_QSTR_remote_services), MP_ROM_PTR(&bleio_peripheral_remote_services_obj) }, { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_peripheral_services_obj) }, }; diff --git a/shared-bindings/bleio/Peripheral.h b/shared-bindings/bleio/Peripheral.h index d9b72b2c31..597b65ce29 100644 --- a/shared-bindings/bleio/Peripheral.h +++ b/shared-bindings/bleio/Peripheral.h @@ -28,6 +28,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H +#include "py/objtuple.h" #include "common-hal/bleio/Peripheral.h" extern const mp_obj_type_t bleio_peripheral_type; @@ -39,7 +40,7 @@ extern mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *sel extern void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *device, bool connectable, float interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo); extern void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *device); extern void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *device); -extern mp_obj_list_t *common_hal_bleio_peripheral_get_remote_services(bleio_peripheral_obj_t *self); +extern mp_obj_tuple_t *common_hal_bleio_peripheral_discover_remote_services(bleio_peripheral_obj_t *self, mp_obj_t service_uuids_whitelist); extern void common_hal_bleio_peripheral_pair(bleio_peripheral_obj_t *device); #endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_PERIPHERAL_H diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 05be48ddc7..739f461a58 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -94,9 +94,6 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { // Properties { MP_ROM_QSTR(MP_QSTR_adapter), MP_ROM_PTR(&common_hal_bleio_adapter_obj) }, - - // constants - { MP_ROM_QSTR(MP_QSTR_SEC), MP_ROM_PTR(&bleio_uuid_type) }, }; STATIC MP_DEFINE_CONST_DICT(bleio_module_globals, bleio_module_globals_table); diff --git a/shared-module/bleio/Attribute.c b/shared-module/bleio/Attribute.c index ac854ec6b3..2275003c93 100644 --- a/shared-module/bleio/Attribute.c +++ b/shared-module/bleio/Attribute.c @@ -31,13 +31,13 @@ void common_hal_bleio_attribute_security_mode_check_valid(bleio_attribute_security_mode_t security_mode) { switch (security_mode) { - case SEC_MODE_NO_ACCESS: - case SEC_MODE_OPEN: - case SEC_MODE_ENC_NO_MITM: - case SEC_MODE_ENC_WITH_MITM: - case SEC_MODE_LESC_ENC_WITH_MITM: - case SEC_MODE_SIGNED_NO_MITM: - case SEC_MODE_SIGNED_WITH_MITM: + case SECURITY_MODE_NO_ACCESS: + case SECURITY_MODE_OPEN: + case SECURITY_MODE_ENC_NO_MITM: + case SECURITY_MODE_ENC_WITH_MITM: + case SECURITY_MODE_LESC_ENC_WITH_MITM: + case SECURITY_MODE_SIGNED_NO_MITM: + case SECURITY_MODE_SIGNED_WITH_MITM: break; default: mp_raise_ValueError(translate("Invalid security_mode")); diff --git a/shared-module/bleio/Attribute.h b/shared-module/bleio/Attribute.h index 62615f1b5e..a498a14a51 100644 --- a/shared-module/bleio/Attribute.h +++ b/shared-module/bleio/Attribute.h @@ -29,13 +29,13 @@ // BLE security modes: 0x typedef enum { - SEC_MODE_NO_ACCESS = 0x00, - SEC_MODE_OPEN = 0x11, - SEC_MODE_ENC_NO_MITM = 0x21, - SEC_MODE_ENC_WITH_MITM = 0x31, - SEC_MODE_LESC_ENC_WITH_MITM = 0x41, - SEC_MODE_SIGNED_NO_MITM = 0x12, - SEC_MODE_SIGNED_WITH_MITM = 0x22, + SECURITY_MODE_NO_ACCESS = 0x00, + SECURITY_MODE_OPEN = 0x11, + SECURITY_MODE_ENC_NO_MITM = 0x21, + SECURITY_MODE_ENC_WITH_MITM = 0x31, + SECURITY_MODE_LESC_ENC_WITH_MITM = 0x41, + SECURITY_MODE_SIGNED_NO_MITM = 0x12, + SECURITY_MODE_SIGNED_WITH_MITM = 0x22, } bleio_attribute_security_mode_t; #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ATTRIBUTE_H