From 17f13ecc2cf10975bf5ff0631ce4326b9ffbbcf5 Mon Sep 17 00:00:00 2001 From: arturo182 Date: Sun, 22 Jul 2018 16:06:19 +0200 Subject: nrf: Cleanup of the ble driver Moved the functions to classes that they belong to. --- ports/nrf/common-hal/bleio/Adapter.c | 117 ++- ports/nrf/common-hal/bleio/Characteristic.c | 159 +++- ports/nrf/common-hal/bleio/Device.c | 535 +++++++++++++- ports/nrf/common-hal/bleio/Scanner.c | 72 +- ports/nrf/common-hal/bleio/Service.c | 85 ++- ports/nrf/common-hal/bleio/UUID.c | 48 +- ports/nrf/drivers/bluetooth/ble_drv.c | 1038 ++------------------------- ports/nrf/drivers/bluetooth/ble_drv.h | 68 +- ports/nrf/drivers/bluetooth/ble_uart.h | 4 +- 9 files changed, 1007 insertions(+), 1119 deletions(-) (limited to 'ports/nrf') diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c index bee9bd395..dd2fd00dd 100644 --- a/ports/nrf/common-hal/bleio/Adapter.c +++ b/ports/nrf/common-hal/bleio/Adapter.c @@ -28,32 +28,133 @@ #include #include +#include "ble.h" #include "ble_drv.h" -#include "nrfx.h" -#include "nrf_error.h" +#include "nrfx_power.h" +#include "nrf_nvic.h" #include "nrf_sdm.h" #include "py/nlr.h" -#include "shared-module/bleio/Address.h" +#include "shared-bindings/bleio/Adapter.h" + +STATIC void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_AssertionError, + "Soft device assert, id: 0x%08lX, pc: 0x%08lX", id, pc)); +} + +STATIC uint32_t ble_stack_enable(void) { + nrf_clock_lf_cfg_t clock_config = { + .source = NRF_CLOCK_LF_SRC_XTAL, +#if (BLE_API_VERSION == 4) + .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM +#else + .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM +#endif + }; + +#if (BLUETOOTH_SD == 140) + // The SD takes over the POWER IRQ and will fail if the IRQ is already in use + nrfx_power_uninit(); +#endif + + uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler); + if (err_code != NRF_SUCCESS) + return err_code; + + err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn); + if (err_code != NRF_SUCCESS) + return err_code; + + uint32_t app_ram_start; +#if (BLE_API_VERSION == 2) + ble_enable_params_t ble_enable_params = { + .gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT, + .gap_enable_params.central_conn_count = 1, + .gap_enable_params.periph_conn_count = 1, + }; + + app_ram_start = 0x200039c0; + err_code = sd_ble_enable(&ble_enable_params, &app_ram_start); +#else + app_ram_start = 0x20004000; + + ble_cfg_t ble_conf; + ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; + ble_conf.conn_cfg.params.gap_conn_cfg.conn_count = BLE_GAP_CONN_COUNT_DEFAULT; + ble_conf.conn_cfg.params.gap_conn_cfg.event_length = BLE_GAP_EVENT_LENGTH_DEFAULT; + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GAP, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.gap_cfg.role_count_cfg.periph_role_count = 1; + ble_conf.gap_cfg.role_count_cfg.central_role_count = 1; + err_code = sd_ble_cfg_set(BLE_GAP_CFG_ROLE_COUNT, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + memset(&ble_conf, 0, sizeof(ble_conf)); + ble_conf.conn_cfg.conn_cfg_tag = BLE_CONN_CFG_TAG_CUSTOM; + ble_conf.conn_cfg.params.gatts_conn_cfg.hvn_tx_queue_size = MAX_TX_IN_PROGRESS; + err_code = sd_ble_cfg_set(BLE_CONN_CFG_GATTS, &ble_conf, app_ram_start); + if (err_code != NRF_SUCCESS) + return err_code; + + err_code = sd_ble_enable(&app_ram_start); +#endif + + return err_code; +} void common_hal_bleio_adapter_set_enabled(bool enabled) { - uint32_t err_code; + const bool is_enabled = common_hal_bleio_adapter_get_enabled(); + // Don't enable or disable twice + if ((is_enabled && enabled) || (!is_enabled && !enabled)) { + return; + } + + uint32_t err_code; if (enabled) { - err_code = ble_drv_stack_enable(); + err_code = ble_stack_enable(); } else { err_code = sd_softdevice_disable(); } if (err_code != NRF_SUCCESS) { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - "Failed to change softdevice status, error: 0x%08lX", err_code)); + "Failed to change softdevice state, error: 0x%08lX", err_code)); } } bool common_hal_bleio_adapter_get_enabled(void) { - return ble_drv_stack_enabled(); + uint8_t is_enabled; + + const uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to get softdevice state, error: 0x%08lX", err_code)); + } + + return is_enabled; } void common_hal_bleio_adapter_get_address(bleio_address_obj_t *address) { - ble_drv_address_get(address); + ble_gap_addr_t local_address; + uint32_t err_code; + + common_hal_bleio_adapter_set_enabled(true); + +#if (BLE_API_VERSION == 2) + err_code = sd_ble_gap_address_get(&local_address); +#else + err_code = sd_ble_gap_addr_get(&local_address); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to get local address, error: 0x%08lX", err_code)); + } + + address->type = local_address.addr_type; + memcpy(address->value, local_address.addr, BLEIO_ADDRESS_BYTES); } diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 35b4f5e24..040cacc3f 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -24,26 +24,173 @@ * THE SOFTWARE. */ +#include +#include + #include "ble_drv.h" +#include "ble_gatts.h" +#include "nrf_soc.h" +#include "py/nlr.h" #include "shared-module/bleio/Characteristic.h" -#include "shared-module/bleio/Device.h" + +static volatile bleio_characteristic_obj_t *m_read_characteristic; +static volatile uint8_t m_tx_in_progress; +static nrf_mutex_t *m_write_mutex; +//static volatile bool m_write_done; + +STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + const uint16_t conn_handle = device->conn_handle; + + 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) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to write gatts value, status: 0x%08lX", err_code)); + } +} + +STATIC void gatts_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + uint16_t hvx_len = bufinfo->len; + + ble_gatts_hvx_params_t hvx_params = { + .handle = characteristic->handle, + .type = BLE_GATT_HVX_NOTIFICATION, + .p_len = &hvx_len, + .p_data = bufinfo->buf, + }; + + while (m_tx_in_progress > MAX_TX_IN_PROGRESS) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + const uint32_t err_code = sd_ble_gatts_hvx(device->conn_handle, &hvx_params); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to notify attribute value, status: 0x%08lX", err_code)); + } + + m_tx_in_progress += 1; +} + +STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) { + bleio_service_obj_t *service = characteristic->service; + bleio_device_obj_t *device = service->device; + + m_read_characteristic = characteristic; + + const uint32_t err_code = sd_ble_gattc_read(device->conn_handle, characteristic->handle, 0); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to read attribute value, status: 0x%08lX", err_code)); + } + + while (m_read_characteristic != NULL) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } +} + +STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + bleio_device_obj_t *device = characteristic->service->device; + uint16_t conn_handle = device->conn_handle; + uint32_t err_code; + + ble_gattc_write_params_t write_params; + write_params.write_op = BLE_GATT_OP_WRITE_REQ; + + if (characteristic->props.write_wo_resp) { + write_params.write_op = BLE_GATT_OP_WRITE_CMD; + } + + write_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL; + write_params.handle = characteristic->handle; + write_params.offset = 0; + write_params.len = bufinfo->len; + write_params.p_value = bufinfo->buf; + + if (write_params.write_op == BLE_GATT_OP_WRITE_CMD) { + err_code = sd_mutex_acquire(m_write_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to acquire mutex, status: 0x%08lX", err_code)); + } + } + + err_code = sd_ble_gattc_write(conn_handle, &write_params); + if (err_code != 0) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to write attribute value, status: 0x%08lX", err_code)); + } + + while (sd_mutex_acquire(m_write_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_write_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to release mutex, status: 0x%08lX", err_code)); + } +} + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *param) { + switch (ble_evt->header.evt_id) { +#if (BLE_API_VERSION == 4) + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + m_tx_in_progress -= ble_evt->evt.gatts_evt.params.hvn_tx_complete.count; + break; +#else + case BLE_EVT_TX_COMPLETE: + m_tx_in_progress -= ble_evt->evt.common_evt.params.tx_complete.count; + break; +#endif + + 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); + m_read_characteristic = NULL; + break; + } + + case BLE_GATTC_EVT_WRITE_RSP: + sd_mutex_release(m_write_mutex); +// m_write_done = true; + break; + } +} + +void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self) { + ble_drv_add_event_handler(on_ble_evt, NULL); +} void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self) { - ble_drv_attr_c_read(self); + gattc_read(self); } void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { - const bleio_device_obj_t *device = MP_OBJ_TO_PTR(self->service->device); + const bleio_device_obj_t *device = self->service->device; if (device->is_peripheral) { // TODO: Add indications if (self->props.notify) { - ble_drv_attr_s_notify(self, bufinfo); + gatts_notify(self, bufinfo); } else { - ble_drv_attr_s_write(self, bufinfo); + gatts_write(self, bufinfo); } } else { - ble_drv_attr_c_write(self, bufinfo); + gattc_write(self, bufinfo); } } diff --git a/ports/nrf/common-hal/bleio/Device.c b/ports/nrf/common-hal/bleio/Device.c index 9e7b382dd..195b6cd32 100644 --- a/ports/nrf/common-hal/bleio/Device.c +++ b/ports/nrf/common-hal/bleio/Device.c @@ -24,49 +24,528 @@ * THE SOFTWARE. */ +#include #include +#include "ble.h" #include "ble_drv.h" -#include "ble_gap.h" -#include "ble_gatt.h" -#include "ble_types.h" +#include "ble_hci.h" +#include "nrf_soc.h" +#include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Device.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" -STATIC void gap_event_handler(bleio_device_obj_t *device, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { - if (event_id == BLE_GAP_EVT_CONNECTED) { - device->conn_handle = conn_handle; - } else if (event_id == BLE_GAP_EVT_DISCONNECTED) { - device->conn_handle = BLE_CONN_HANDLE_INVALID; +#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) +#define BLE_SLAVE_LATENCY 0 +#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) + +#define BLE_ADV_LENGTH_FIELD_SIZE 1 +#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 +#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 + +#ifndef BLE_GAP_ADV_MAX_SIZE +#define BLE_GAP_ADV_MAX_SIZE 31 +#endif + +static bleio_service_obj_t *m_char_discovery_service; +static volatile bool m_discovery_successful; +static nrf_mutex_t *m_discovery_mutex; + +#if (BLUETOOTH_SD == 140) +static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; + +static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; + +static ble_data_t m_scan_buffer = { + .p_data = m_scan_buffer_data, + .len = BLE_GAP_SCAN_BUFFER_MIN +}; +#endif + +STATIC uint32_t set_advertisement_data(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) { + common_hal_bleio_adapter_set_enabled(true); + + uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE]; + uint8_t byte_pos = 0; + uint32_t err_code; + +#define ADD_FIELD(field, len) \ + do { \ + if (byte_pos + (len) > BLE_GAP_ADV_MAX_SIZE) { \ + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, \ + "Can not fit data into the advertisment packet")); \ + } \ + adv_data[byte_pos] = (field); \ + byte_pos += (len); \ + } while (0) + + GET_STR_DATA_LEN(device->name, name_data, name_len); + if (name_len > 0) { + ble_gap_conn_sec_mode_t sec_mode; + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); + + err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + // TODO: Shorten if too long + + ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + name_len, BLE_ADV_LENGTH_FIELD_SIZE); + ADD_FIELD(BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, BLE_ADV_AD_TYPE_FIELD_SIZE); + + memcpy(&adv_data[byte_pos], name_data, name_len); + byte_pos += name_len; + } + + // set flags, default to disc mode + if (raw_data->len == 0) { + ADD_FIELD(BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE, BLE_ADV_LENGTH_FIELD_SIZE); + ADD_FIELD(BLE_GAP_AD_TYPE_FLAGS, BLE_AD_TYPE_FLAGS_DATA_SIZE); + ADD_FIELD(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE, BLE_AD_TYPE_FLAGS_DATA_SIZE); + } else { + if (byte_pos + raw_data->len > BLE_GAP_ADV_MAX_SIZE) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Can not fit data into the advertisment packet")); + } + + memcpy(&adv_data[byte_pos], raw_data->buf, raw_data->len); + byte_pos += raw_data->len; + } + + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); + if (service_list->len > 0) { + bool has_128bit_services = false; + bool has_16bit_services = false; + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + + if (service->is_secondary) { + continue; + } + + if (service->uuid->type == UUID_TYPE_16BIT) { + has_16bit_services = true; + } + + if (service->uuid->type == UUID_TYPE_128BIT) { + has_128bit_services = true; + } + } + + if (has_16bit_services) { + const uint8_t size_byte_pos = byte_pos; + uint8_t uuid_total_size = 0; + + // skip length byte for now, apply total length post calculation + byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; + + ADD_FIELD(BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE); + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + uint8_t encoded_size = 0; + + if ((service->uuid->type != UUID_TYPE_16BIT) || service->is_secondary) { + continue; + } + + ble_uuid_t uuid; + uuid.type = BLE_UUID_TYPE_BLE; + uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); + + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + uuid_total_size += encoded_size; + byte_pos += encoded_size; + } + + adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); + } + + if (has_128bit_services) { + const uint8_t size_byte_pos = byte_pos; + uint8_t uuid_total_size = 0; + + // skip length byte for now, apply total length post calculation + byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; + + ADD_FIELD(BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE, BLE_ADV_AD_TYPE_FIELD_SIZE); + + for (size_t i = 0; i < service_list->len; ++i) { + const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + uint8_t encoded_size = 0; + + if ((service->uuid->type != UUID_TYPE_128BIT) || service->is_secondary) { + continue; + } + + ble_uuid_t uuid; + uuid.type = service->uuid->uuid_vs_idx; + uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); + + err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + uuid_total_size += encoded_size; + byte_pos += encoded_size; + } + + adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); + } + } + +#if (BLUETOOTH_SD == 132) + err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0); + if (err_code != NRF_SUCCESS) { + return err_code; + } +#endif + + static ble_gap_adv_params_t m_adv_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED, + .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED, + .filter_policy = BLE_GAP_ADV_FP_ANY, + .primary_phy = BLE_GAP_PHY_1MBPS, +#else + .type = BLE_GAP_ADV_TYPE_ADV_IND, + .fp = BLE_GAP_ADV_FP_ANY, +#endif + }; + + if (!connectable) { +#if (BLUETOOTH_SD == 140) + m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; +#else + m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; +#endif } + + common_hal_bleio_device_stop_advertising(device); + +#if (BLUETOOTH_SD == 140) + const ble_gap_adv_data_t ble_gap_adv_data = { + .adv_data.p_data = adv_data, + .adv_data.len = byte_pos, + }; + + err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params); + if (err_code != NRF_SUCCESS) { + return err_code; + } + + err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM); +#elif (BLUETOOTH_SD == 132 && BLE_API_VERSION == 4) + err_code = sd_ble_gap_adv_start(&m_adv_params, BLE_CONN_CFG_TAG_CUSTOM); +#else + err_code = sd_ble_gap_adv_start(&m_adv_params); +#endif + + return err_code; } -STATIC void gatts_event_handler(bleio_device_obj_t *device, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { +STATIC bool discover_services(bleio_device_obj_t *device, uint16_t start_handle) { + m_discovery_successful = false; + + uint32_t err_code = sd_ble_gattc_primary_services_discover(device->conn_handle, start_handle, NULL); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to discover serivices, status: 0x%08lX", err_code)); + } + + err_code = sd_mutex_acquire(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to acquire mutex, status: 0x%08lX", err_code)); + } + + while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to release mutex, status: 0x%08lX", err_code)); + } + return m_discovery_successful; } -void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bleio_advertisement_data_t *adv_data) { - if (adv_data->connectable) { - ble_drv_gap_event_handler_set(device, gap_event_handler); - ble_drv_gatts_event_handler_set(device, gatts_event_handler); +STATIC bool discover_characteristics(bleio_device_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; + + uint32_t err_code = sd_ble_gattc_characteristics_discover(device->conn_handle, &handle_range); + if (err_code != 0) { + return false; + } + + err_code = sd_mutex_acquire(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to acquire mutex, status: 0x%08lX", err_code)); } - ble_drv_advertise_data(adv_data); + while (sd_mutex_acquire(m_discovery_mutex) == NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN) { +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif + } + + err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to release mutex, status: 0x%08lX", err_code)); + } + + return m_discovery_successful; +} + +STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_device_obj_t *device) { + for (size_t i = 0; i < response->count; ++i) { + const 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; + service->device = device; + service->char_list = mp_obj_new_list(0, NULL); + service->start_handle = gattc_service->handle_range.start_handle; + service->end_handle = gattc_service->handle_range.end_handle; + service->handle = gattc_service->handle_range.start_handle; + + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + uuid->type = (gattc_service->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; + uuid->value[0] = gattc_service->uuid.uuid & 0xFF; + uuid->value[1] = gattc_service->uuid.uuid >> 8; + service->uuid = uuid; + + mp_obj_list_append(device->service_list, service); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + + const uint32_t err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to release mutex, status: 0x%08lX", err_code)); + } +} + +STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_device_obj_t *device) { + for (size_t i = 0; i < response->count; ++i) { + const 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; + + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + uuid->type = (gattc_char->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; + uuid->value[0] = gattc_char->uuid.uuid & 0xFF; + uuid->value[1] = gattc_char->uuid.uuid >> 8; + characteristic->uuid = uuid; + + characteristic->props.broadcast = gattc_char->char_props.broadcast; + characteristic->props.indicate = gattc_char->char_props.indicate; + characteristic->props.notify = gattc_char->char_props.notify; + characteristic->props.read = gattc_char->char_props.read; + characteristic->props.write = gattc_char->char_props.write; + characteristic->props.write_wo_resp = gattc_char->char_props.write_wo_resp; + characteristic->handle = gattc_char->handle_value; + + characteristic->service_handle = m_char_discovery_service->handle; + characteristic->service = m_char_discovery_service; + + mp_obj_list_append(m_char_discovery_service->char_list, MP_OBJ_FROM_PTR(characteristic)); + } + + if (response->count > 0) { + m_discovery_successful = true; + } + + const uint32_t err_code = sd_mutex_release(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to release mutex, status: 0x%08lX", err_code)); + } +} + +STATIC void on_adv_report(ble_gap_evt_adv_report_t *report, bleio_device_obj_t *device) { + uint32_t err_code; + + if (memcmp(report->peer_addr.addr, device->address.value, BLEIO_ADDRESS_BYTES) != 0) { +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to continue scanning, status: 0x%0xlX", err_code)); + } +#endif + return; + } + + ble_gap_scan_params_t scan_params = { + .active = 1, + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), + }; + + ble_gap_addr_t addr; + memset(&addr, 0, sizeof(addr)); + + addr.addr_type = report->peer_addr.addr_type; + memcpy(addr.addr, report->peer_addr.addr, BLEIO_ADDRESS_BYTES); + + ble_gap_conn_params_t conn_params = { + .min_conn_interval = BLE_MIN_CONN_INTERVAL, + .max_conn_interval = BLE_MAX_CONN_INTERVAL, + .conn_sup_timeout = BLE_CONN_SUP_TIMEOUT, + .slave_latency = BLE_SLAVE_LATENCY, + }; + +#if (BLE_API_VERSION == 2) + err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params); +#else + err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to connect, status: 0x%08lX", err_code)); + } +} + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *device_in) { + bleio_device_obj_t *device = (bleio_device_obj_t*)device_in; + + switch (ble_evt->header.evt_id) { + case BLE_GAP_EVT_CONNECTED: + { + ble_gap_conn_params_t conn_params; + device->conn_handle = ble_evt->evt.gap_evt.conn_handle; + + sd_ble_gap_ppcp_get(&conn_params); + sd_ble_gap_conn_param_update(ble_evt->evt.gap_evt.conn_handle, &conn_params); + break; + } + + case BLE_GAP_EVT_DISCONNECTED: + device->conn_handle = BLE_CONN_HANDLE_INVALID; + break; + + case BLE_GAP_EVT_ADV_REPORT: + on_adv_report(&ble_evt->evt.gap_evt.params.adv_report, device); + 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_GATTS_EVT_SYS_ATTR_MISSING: + sd_ble_gatts_sys_attr_set(ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); + break; + +#if (BLE_API_VERSION == 4) + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + sd_ble_gatts_exchange_mtu_reply(device->conn_handle, BLE_GATT_ATT_MTU_DEFAULT); + break; +#endif + + case BLE_GAP_EVT_SEC_PARAMS_REQUEST: + sd_ble_gap_sec_params_reply(device->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; + sd_ble_gap_conn_param_update(device->conn_handle, &request->conn_params); + break; + } + } +} + +void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bool connectable, mp_buffer_info_t *raw_data) { + if (connectable) { + ble_drv_add_event_handler(on_ble_evt, device); + } + + const uint32_t err_code = set_advertisement_data(device, connectable, raw_data); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to start advertisment, status: 0x%08lX", err_code)); + } } void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device) { - (void)device; + uint32_t err_code; + +#if (BLUETOOTH_SD == 140) + if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) + return; - ble_drv_advertise_stop(); + err_code = sd_ble_gap_adv_stop(m_adv_handle); +#else + err_code = sd_ble_gap_adv_stop(); +#endif + + if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to stop advertisment, status: 0x%08lX", err_code)); + } } void common_hal_bleio_device_connect(bleio_device_obj_t *device) { - ble_drv_gap_event_handler_set(device, gap_event_handler); + ble_drv_add_event_handler(on_ble_evt, device); - ble_drv_connect(device); + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(100, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(100, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .scan_phys = BLE_GAP_PHY_1MBPS, +#endif + }; + + common_hal_bleio_adapter_set_enabled(true); + + uint32_t err_code; +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); +#else + err_code = sd_ble_gap_scan_start(&scan_params); +#endif + + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to start scanning, status: 0x%0xlX", err_code)); + } while (device->conn_handle == BLE_CONN_HANDLE_INVALID) { #ifdef MICROPY_VM_HOOK_LOOP @@ -76,13 +555,23 @@ void common_hal_bleio_device_connect(bleio_device_obj_t *device) { // TODO: read name + if (m_discovery_mutex == NULL) { + m_discovery_mutex = m_new_ll(nrf_mutex_t, 1); + + err_code = sd_mutex_new(m_discovery_mutex); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to create mutex, status: 0x%0xlX", err_code)); + } + } + // find services - bool found_service = ble_drv_discover_services(device, BLE_GATT_HANDLE_START); + bool found_service = discover_services(device, BLE_GATT_HANDLE_START); while (found_service) { const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); const bleio_service_obj_t *service = service_list->items[service_list->len - 1]; - found_service = ble_drv_discover_services(device, service->end_handle + 1); + found_service = discover_services(device, service->end_handle + 1); } // find characteristics in each service @@ -90,7 +579,7 @@ void common_hal_bleio_device_connect(bleio_device_obj_t *device) { for (size_t i = 0; i < service_list->len; ++i) { bleio_service_obj_t *service = service_list->items[i]; - bool found_char = ble_drv_discover_characteristic(device, service, service->start_handle); + bool found_char = discover_characteristics(device, service, service->start_handle); while (found_char) { const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list); const bleio_characteristic_obj_t *characteristic = char_list->items[char_list->len - 1]; @@ -100,11 +589,11 @@ void common_hal_bleio_device_connect(bleio_device_obj_t *device) { break; } - found_char = ble_drv_discover_characteristic(device, service, next_handle); + found_char = discover_characteristics(device, service, next_handle); } } } void common_hal_bleio_device_disconnect(bleio_device_obj_t *device) { - ble_drv_disconnect(device); + sd_ble_gap_disconnect(device->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); } diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c index 150c417a3..17af49621 100644 --- a/ports/nrf/common-hal/bleio/Scanner.c +++ b/ports/nrf/common-hal/bleio/Scanner.c @@ -28,25 +28,83 @@ #include #include "ble_drv.h" +#include "ble_gap.h" #include "py/mphal.h" +#include "py/nlr.h" +#include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/ScanEntry.h" #include "shared-bindings/bleio/Scanner.h" #include "shared-module/bleio/ScanEntry.h" -STATIC void adv_event_handler(bleio_scanner_obj_t *self, bleio_scanentry_obj_t *entry) { +#if (BLUETOOTH_SD == 140) +static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; + +static ble_data_t m_scan_buffer = { + m_scan_buffer_data, + BLE_GAP_SCAN_BUFFER_MIN +}; +#endif + +STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) { + bleio_scanner_obj_t *scanner = (bleio_scanner_obj_t*)scanner_in; + ble_gap_evt_adv_report_t *report = &ble_evt->evt.gap_evt.params.adv_report; + + if (ble_evt->header.evt_id != BLE_GAP_EVT_ADV_REPORT) { + return; + } + // TODO: Don't add new entry for each item, group by address and update + bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); + entry->base.type = &bleio_scanentry_type; + entry->rssi = report->rssi; - mp_obj_list_append(self->adv_reports, entry); + entry->address.type = report->peer_addr.addr_type; + memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES); - ble_drv_scan_continue(); +#if (BLUETOOTH_SD == 140) + entry->data = mp_obj_new_bytearray(report->data.len, report->data.p_data); +#else + entry->data = mp_obj_new_bytearray(report->dlen, report->data); +#endif + + mp_obj_list_append(scanner->adv_reports, entry); + +#if (BLUETOOTH_SD == 140) + const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to continue scanning, status: 0x%0xlX", err_code)); + } +#endif } void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout) { - ble_drv_adv_report_handler_set(self, adv_event_handler); + ble_drv_add_event_handler(on_ble_evt, self); + + ble_gap_scan_params_t scan_params = { + .interval = MSEC_TO_UNITS(self->interval, UNIT_0_625_MS), + .window = MSEC_TO_UNITS(self->window, UNIT_0_625_MS), +#if (BLUETOOTH_SD == 140) + .scan_phys = BLE_GAP_PHY_1MBPS, +#endif + }; + + common_hal_bleio_adapter_set_enabled(true); - ble_drv_scan_start(self->interval, self->window); + uint32_t err_code; +#if (BLUETOOTH_SD == 140) + err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer); +#else + err_code = sd_ble_gap_scan_start(&scan_params); +#endif - mp_hal_delay_ms(timeout); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to start scanning, status: 0x%0xlX", err_code)); + } - ble_drv_scan_stop(); + if (timeout > 0) { + mp_hal_delay_ms(timeout); + sd_ble_gap_scan_stop(); + } } diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c index b6e0595b1..9e376b333 100644 --- a/ports/nrf/common-hal/bleio/Service.c +++ b/ports/nrf/common-hal/bleio/Service.c @@ -25,14 +25,91 @@ */ #include "ble_drv.h" -#include "shared-module/bleio/Service.h" +#include "ble.h" +#include "py/nlr.h" +#include "shared-bindings/bleio/Service.h" +#include "shared-bindings/bleio/Adapter.h" void common_hal_bleio_service_construct(bleio_service_obj_t *self) { - ble_drv_service_add(self); + ble_uuid_t uuid = { + .type = BLE_UUID_TYPE_BLE, + .uuid = self->uuid->value[0] | (self->uuid->value[1] << 8) + }; + + if (self->uuid->type == UUID_TYPE_128BIT) { + uuid.type = self->uuid->uuid_vs_idx; + } + + uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; + if (self->is_secondary) { + service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; + } + + common_hal_bleio_adapter_set_enabled(true); + + const uint32_t err_code = sd_ble_gatts_service_add(service_type, &uuid, &self->handle); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to add service, status: 0x%08lX", err_code)); + } } void common_hal_bleio_service_add_characteristic(bleio_service_obj_t *self, bleio_characteristic_obj_t *characteristic) { - if (ble_drv_characteristic_add(characteristic)) { - characteristic->service = self; + ble_gatts_char_md_t char_md = { + .char_props.broadcast = characteristic->props.broadcast, + .char_props.read = characteristic->props.read, + .char_props.write_wo_resp = characteristic->props.write_wo_resp, + .char_props.write = characteristic->props.write, + .char_props.notify = characteristic->props.notify, + .char_props.indicate = characteristic->props.indicate, + }; + + ble_gatts_attr_md_t cccd_md = { + .vloc = BLE_GATTS_VLOC_STACK, + }; + + if (char_md.char_props.notify || char_md.char_props.indicate) { + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); + BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); + + char_md.p_cccd_md = &cccd_md; } + + ble_uuid_t uuid = { + .type = BLE_UUID_TYPE_BLE, + .uuid = characteristic->uuid->value[0] | (characteristic->uuid->value[1] << 8), + }; + + if (characteristic->uuid->type == UUID_TYPE_128BIT) + uuid.type = characteristic->uuid->uuid_vs_idx; + + ble_gatts_attr_md_t 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_gatts_attr_t attr_char_value = { + .p_uuid = &uuid, + .p_attr_md = &attr_md, + .init_len = sizeof(uint8_t), + .max_len = (BLE_GATT_ATT_MTU_DEFAULT - 3), + }; + + ble_gatts_char_handles_t handles; + + uint32_t err_code; + err_code = sd_ble_gatts_characteristic_add(characteristic->service_handle, &char_md, &attr_char_value, &handles); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to add characteristic, status: 0x%08lX", err_code)); + } + + 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->service = self; } diff --git a/ports/nrf/common-hal/bleio/UUID.c b/ports/nrf/common-hal/bleio/UUID.c index e655589a6..4d4c8c9fb 100644 --- a/ports/nrf/common-hal/bleio/UUID.c +++ b/ports/nrf/common-hal/bleio/UUID.c @@ -25,10 +25,13 @@ * THE SOFTWARE. */ +#include "ble.h" #include "ble_drv.h" #include "common-hal/bleio/UUID.h" +#include "nrf_error.h" #include "py/objstr.h" #include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/UUID.h" #define UUID_STR_16BIT_LEN 6 @@ -59,37 +62,44 @@ void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uui } else if (str_len == UUID_STR_128BIT_LEN) { self->type = UUID_TYPE_128BIT; - uint8_t buffer[16]; - buffer[0] = xdigit_8b_value(str_data[35], str_data[34]); - buffer[1] = xdigit_8b_value(str_data[33], str_data[32]); - buffer[2] = xdigit_8b_value(str_data[31], str_data[30]); - buffer[3] = xdigit_8b_value(str_data[29], str_data[28]); - buffer[4] = xdigit_8b_value(str_data[27], str_data[26]); - buffer[5] = xdigit_8b_value(str_data[25], str_data[24]); + ble_uuid128_t vs_uuid; + vs_uuid.uuid128[0] = xdigit_8b_value(str_data[35], str_data[34]); + vs_uuid.uuid128[1] = xdigit_8b_value(str_data[33], str_data[32]); + vs_uuid.uuid128[2] = xdigit_8b_value(str_data[31], str_data[30]); + vs_uuid.uuid128[3] = xdigit_8b_value(str_data[29], str_data[28]); + vs_uuid.uuid128[4] = xdigit_8b_value(str_data[27], str_data[26]); + vs_uuid.uuid128[5] = xdigit_8b_value(str_data[25], str_data[24]); // 23 '-' - buffer[6] = xdigit_8b_value(str_data[22], str_data[21]); - buffer[7] = xdigit_8b_value(str_data[20], str_data[19]); + vs_uuid.uuid128[6] = xdigit_8b_value(str_data[22], str_data[21]); + vs_uuid.uuid128[7] = xdigit_8b_value(str_data[20], str_data[19]); // 18 '-' - buffer[8] = xdigit_8b_value(str_data[17], str_data[16]); - buffer[9] = xdigit_8b_value(str_data[15], str_data[14]); + vs_uuid.uuid128[8] = xdigit_8b_value(str_data[17], str_data[16]); + vs_uuid.uuid128[9] = xdigit_8b_value(str_data[15], str_data[14]); // 13 '-' - buffer[10] = xdigit_8b_value(str_data[12], str_data[11]); - buffer[11] = xdigit_8b_value(str_data[10], str_data[9]); + vs_uuid.uuid128[10] = xdigit_8b_value(str_data[12], str_data[11]); + vs_uuid.uuid128[11] = xdigit_8b_value(str_data[10], str_data[9]); // 8 '-' self->value[0] = xdigit_8b_value(str_data[7], str_data[6]); self->value[1] = xdigit_8b_value(str_data[5], str_data[4]); - buffer[14] = xdigit_8b_value(str_data[3], str_data[2]); - buffer[15] = xdigit_8b_value(str_data[1], str_data[0]); + vs_uuid.uuid128[14] = xdigit_8b_value(str_data[3], str_data[2]); + vs_uuid.uuid128[15] = xdigit_8b_value(str_data[1], str_data[0]); + + common_hal_bleio_adapter_set_enabled(true); + + const uint32_t err_code = sd_ble_uuid_vs_add(&vs_uuid, &self->uuid_vs_idx); + if (err_code != NRF_SUCCESS) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, + "Failed to add Vendor Specific UUID, status: 0x%08lX", err_code)); + } - ble_drv_uuid_add_vs(buffer, &self->uuid_vs_idx); } else { nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, - "Invalid UUID string length")); + "Invalid UUID string length")); } return; @@ -113,10 +123,10 @@ void common_hal_bleio_uuid_construct(bleio_uuid_obj_t *self, const mp_obj_t *uui void common_hal_bleio_uuid_print(bleio_uuid_obj_t *self, const mp_print_t *print) { if (self->type == UUID_TYPE_16BIT) { mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ")", - self->value[1], self->value[0]); + self->value[1], self->value[0]); } else { mp_printf(print, "UUID(uuid: 0x" HEX2_FMT HEX2_FMT ", VS idx: " HEX2_FMT ")", - self->value[1], self->value[0], self->uuid_vs_idx); + self->value[1], self->value[0], self->uuid_vs_idx); } } diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c index 6d32ff6f9..0b6daf711 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ b/ports/nrf/drivers/bluetooth/ble_drv.c @@ -25,1027 +25,73 @@ * THE SOFTWARE. */ -#if BLUETOOTH_SD - -#include -#include #include +#include -#if (BLUETOOTH_SD == 132) -#define NRF52 // Needed for SD132 v2 -#endif - -#include "shared-bindings/bleio/Characteristic.h" -#include "shared-bindings/bleio/ScanEntry.h" -#include "shared-bindings/bleio/Service.h" -#include "shared-bindings/bleio/UUID.h" -#include "shared-module/bleio/Device.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "supervisor/shared/translate.h" +#include "ble.h" #include "ble_drv.h" #include "nrf_nvic.h" #include "nrf_sdm.h" -#include "nrfx_power.h" -#include "py/objstr.h" -#include "py/runtime.h" -#include "shared-bindings/bleio/Characteristic.h" -#include "shared-bindings/bleio/ScanEntry.h" -#include "shared-bindings/bleio/UUID.h" - -#define BLE_DRIVER_LOG printf - -#define BLE_ADV_LENGTH_FIELD_SIZE 1 -#define BLE_ADV_AD_TYPE_FIELD_SIZE 1 -#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1 - -#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) -#define UNIT_0_625_MS (625) -#define UNIT_10_MS (10000) - -#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) -#define BLE_SLAVE_LATENCY 0 -#define BLE_CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) - -#ifndef BLE_GAP_ADV_MAX_SIZE -#define BLE_GAP_ADV_MAX_SIZE 31 -#endif - -#define SD_TEST_OR_ENABLE() \ -if (ble_drv_stack_enabled() == 0) { \ - (void)ble_drv_stack_enable(); \ -} - -static ble_drv_adv_evt_callback_t adv_event_handler; -static ble_drv_gatts_evt_callback_t gatts_event_handler; -static ble_drv_gap_evt_callback_t gap_event_handler; - -static bleio_characteristic_obj_t *mp_gattc_char_data_observer; -static bleio_device_obj_t *mp_gattc_disc_service_observer; -static bleio_service_obj_t *mp_gattc_disc_char_observer; -static bleio_address_obj_t *mp_connect_address; -static bleio_device_obj_t *mp_gatts_observer; -static bleio_scanner_obj_t *mp_adv_observer; -static bleio_device_obj_t *mp_gap_observer; - -static volatile bool m_primary_service_found; -static volatile bool m_characteristic_found; -static volatile bool m_tx_in_progress; -static volatile bool m_write_done; +#include "py/misc.h" nrf_nvic_state_t nrf_nvic_state = { 0 }; -#if (BLUETOOTH_SD == 140) -static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; -static uint8_t m_scan_buffer_data[BLE_GAP_SCAN_BUFFER_MIN]; - -static ble_data_t m_scan_buffer = -{ - m_scan_buffer_data, - BLE_GAP_SCAN_BUFFER_MIN -}; -#endif - -void softdevice_assert_handler(uint32_t id, uint32_t pc, uint32_t info) { - BLE_DRIVER_LOG("ERROR: SoftDevice assert!!!"); -} - -uint32_t ble_drv_stack_enable(void) { - nrf_clock_lf_cfg_t clock_config = { - .source = NRF_CLOCK_LF_SRC_XTAL, - .rc_ctiv = 0, - .rc_temp_ctiv = 0, -#if (BLE_API_VERSION == 4) - .accuracy = NRF_CLOCK_LF_ACCURACY_20_PPM -#else - .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM -#endif - }; - -#if (BLUETOOTH_SD == 140) - // The SD takes over the POWER IRQ and will fail if the IRQ is already in use - nrfx_power_uninit(); -#endif - - uint32_t err_code = sd_softdevice_enable(&clock_config, softdevice_assert_handler); - if (err_code != NRF_SUCCESS) - BLE_DRIVER_LOG("SoftDevice enable status: " UINT_FMT "\n", (uint16_t)err_code); - - err_code = sd_nvic_EnableIRQ(SD_EVT_IRQn); - if (err_code != NRF_SUCCESS) - BLE_DRIVER_LOG("IRQ enable status: " UINT_FMT "\n", (uint16_t)err_code); - - // Enable BLE stack. - uint32_t app_ram_start; -#if (BLE_API_VERSION == 2) - ble_enable_params_t ble_enable_params; - memset(&ble_enable_params, 0x00, sizeof(ble_enable_params)); - ble_enable_params.gatts_enable_params.attr_tab_size = BLE_GATTS_ATTR_TAB_SIZE_DEFAULT; - ble_enable_params.gatts_enable_params.service_changed = 0; - ble_enable_params.gap_enable_params.periph_conn_count = 1; - ble_enable_params.gap_enable_params.central_conn_count = 1; - - app_ram_start = 0x200039c0; - err_code = sd_ble_enable(&ble_enable_params, &app_ram_start); // 8K SD headroom from linker script. -#else - app_ram_start = 0x20004000; - err_code = sd_ble_enable(&app_ram_start); -#endif - - if (err_code != NRF_SUCCESS) { - BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); - BLE_DRIVER_LOG("BLE enable status: " UINT_FMT "\n", (uint16_t)err_code); - } - - return err_code; -} - -uint8_t ble_drv_stack_enabled(void) { - uint8_t is_enabled; - uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); - - if (err_code != NRF_SUCCESS) { - BLE_DRIVER_LOG("Is enabled status: " UINT_FMT "\n", (uint16_t)err_code); - } - - return is_enabled; -} - -void ble_drv_address_get(bleio_address_obj_t *address) { - SD_TEST_OR_ENABLE(); - - ble_gap_addr_t local_ble_addr; -#if (BLE_API_VERSION == 2) - uint32_t err_code = sd_ble_gap_address_get(&local_ble_addr); -#else - uint32_t err_code = sd_ble_gap_addr_get(&local_ble_addr); -#endif - - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not query for the device address."))); - } - - BLE_DRIVER_LOG("ble address, type: " HEX2_FMT ", " \ - "address: " HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT ":" \ - HEX2_FMT ":" HEX2_FMT ":" HEX2_FMT "\n", \ - local_ble_addr.addr_type, \ - local_ble_addr.addr[5], local_ble_addr.addr[4], local_ble_addr.addr[3], \ - local_ble_addr.addr[2], local_ble_addr.addr[1], local_ble_addr.addr[0]); - - address->type = local_ble_addr.addr_type; - memcpy(address->value, local_ble_addr.addr, BLEIO_ADDRESS_BYTES); -} - -bool ble_drv_uuid_add_vs(uint8_t *uuid, uint8_t *idx) { - SD_TEST_OR_ENABLE(); - - if (sd_ble_uuid_vs_add((ble_uuid128_t const *)uuid, idx) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Vendor Specific 128-bit UUID."))); - } - - return true; -} - -void ble_drv_service_add(bleio_service_obj_t *service) { - SD_TEST_OR_ENABLE(); - - ble_uuid_t uuid = { - .type = BLE_UUID_TYPE_BLE, - .uuid = service->uuid->value[0] | (service->uuid->value[1] << 8) - }; - - if (service->uuid->type == UUID_TYPE_128BIT) { - uuid.type = service->uuid->uuid_vs_idx; - } - - uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY; - if (service->is_secondary) { - service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; - } - - if (sd_ble_gatts_service_add(service_type, &uuid, &service->handle) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Service."))); - } -} - -bool ble_drv_characteristic_add(bleio_characteristic_obj_t *characteristic) { - ble_gatts_char_md_t char_md; - ble_gatts_attr_md_t cccd_md; - ble_gatts_attr_t attr_char_value; - ble_uuid_t uuid; - ble_gatts_attr_md_t attr_md; - - memset(&char_md, 0, sizeof(char_md)); - - char_md.char_props.broadcast = characteristic->props.broadcast; - char_md.char_props.read = characteristic->props.read; - char_md.char_props.write_wo_resp = characteristic->props.write_wo_resp; - char_md.char_props.write = characteristic->props.write; - char_md.char_props.notify = characteristic->props.notify; - char_md.char_props.indicate = characteristic->props.indicate; - - char_md.p_char_user_desc = NULL; - char_md.p_char_pf = NULL; - char_md.p_user_desc_md = NULL; - char_md.p_sccd_md = NULL; - - if (characteristic->props.notify || characteristic->props.notify) { - memset(&cccd_md, 0, sizeof(cccd_md)); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm); - cccd_md.vloc = BLE_GATTS_VLOC_STACK; - char_md.p_cccd_md = &cccd_md; - } else { - char_md.p_cccd_md = NULL; - } - - uuid.type = BLE_UUID_TYPE_BLE; - if (characteristic->uuid->type == UUID_TYPE_128BIT) - uuid.type = characteristic->uuid->uuid_vs_idx; - - uuid.uuid = characteristic->uuid->value[0]; - uuid.uuid += characteristic->uuid->value[1] << 8; - - memset(&attr_md, 0, sizeof(attr_md)); - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm); - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm); - - attr_md.vloc = BLE_GATTS_VLOC_STACK; - attr_md.rd_auth = 0; - attr_md.wr_auth = 0; - attr_md.vlen = 1; - - memset(&attr_char_value, 0, sizeof(attr_char_value)); - - attr_char_value.p_uuid = &uuid; - attr_char_value.p_attr_md = &attr_md; - attr_char_value.init_len = sizeof(uint8_t); - attr_char_value.init_offs = 0; -#if (BLE_API_VERSION == 2) - attr_char_value.max_len = (GATT_MTU_SIZE_DEFAULT - 3); -#else - attr_char_value.max_len = (BLE_GATT_ATT_MTU_DEFAULT - 3); -#endif - - ble_gatts_char_handles_t handles; - - uint32_t err_code = sd_ble_gatts_characteristic_add(characteristic->service_handle, - &char_md, - &attr_char_value, - &handles); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not add Characteristic. status: 0x%08lX"), err_code)); - } - - // apply handles to object instance - characteristic->handle = handles.value_handle; - characteristic->user_desc_handle = handles.user_desc_handle; - characteristic->cccd_handle = handles.cccd_handle; - characteristic->sccd_handle = handles.sccd_handle; - - return true; -} - -// TODO: Replace with just bleio_device_obj_t + data -bool ble_drv_advertise_data(bleio_advertisement_data_t *adv_params) { - SD_TEST_OR_ENABLE(); - - uint8_t byte_pos = 0; - uint8_t adv_data[BLE_GAP_ADV_MAX_SIZE]; - - GET_STR_DATA_LEN(adv_params->device_name, name_data, name_len); - - if (name_len > 0) { - ble_gap_conn_sec_mode_t sec_mode; - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - if (sd_ble_gap_device_name_set(&sec_mode, - name_data, - name_len) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply device name in the stack."))); - } - - adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + name_len); - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - - // TODO: Shorten if too long - adv_data[byte_pos] = BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; - - memcpy(&adv_data[byte_pos], name_data, name_len); - - byte_pos += name_len; - } - - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(adv_params->data, &bufinfo, MP_BUFFER_WRITE); - - // set flags, default to disc mode - if (bufinfo.len == 0) { - adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + BLE_AD_TYPE_FLAGS_DATA_SIZE); - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - - adv_data[byte_pos] = BLE_GAP_AD_TYPE_FLAGS; - byte_pos += BLE_AD_TYPE_FLAGS_DATA_SIZE; - - adv_data[byte_pos] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; - byte_pos += 1; - } - - const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(adv_params->services); - if (service_list->len > 0) { - bool type_16bit_present = false; - bool type_128bit_present = false; - - for (size_t i = 0; i < service_list->len; ++i) { - const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); - - if (service->uuid->type == UUID_TYPE_16BIT) { - type_16bit_present = true; - } - - if (service->uuid->type == UUID_TYPE_128BIT) { - type_128bit_present = true; - } - } - - if (type_16bit_present) { - uint8_t size_byte_pos = byte_pos; - - // skip length byte for now, apply total length post calculation - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; +__attribute__((aligned(4))) +static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)]; - adv_data[byte_pos] = BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; +typedef struct event_handler { + struct event_handler *next; + void *param; + ble_drv_evt_handler_t func; +} event_handler_t; - uint8_t uuid_total_size = 0; - uint8_t encoded_size = 0; +static event_handler_t *m_event_handlers; - for (size_t i = 0; i < service_list->len; ++i) { - const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); - - if (service->uuid->type != UUID_TYPE_16BIT) { - continue; - } - - ble_uuid_t uuid; - uuid.type = BLE_UUID_TYPE_BLE; - uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); - - // calculate total size of uuids - if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not encode UUID, to check length."))); - } - - // do encoding into the adv buffer - if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can encode UUID into the advertisement packet."))); - } - - uuid_total_size += encoded_size; // size of entry - byte_pos += encoded_size; // relative to adv data packet - } - - adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); - } - - if (type_128bit_present) { - uint8_t size_byte_pos = byte_pos; - - // skip length byte for now, apply total length post calculation - byte_pos += BLE_ADV_LENGTH_FIELD_SIZE; - - adv_data[byte_pos] = BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE; - byte_pos += BLE_ADV_AD_TYPE_FIELD_SIZE; - - uint8_t uuid_total_size = 0; - uint8_t encoded_size = 0; - - for (size_t i = 0; i < service_list->len; ++i) { - const bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); - - if (service->uuid->type != UUID_TYPE_128BIT) { - continue; - } - - ble_uuid_t uuid; - uuid.type = service->uuid->uuid_vs_idx; - uuid.uuid = service->uuid->value[0] | (service->uuid->value[1] << 8); - - // calculate total size of uuids - if (sd_ble_uuid_encode(&uuid, &encoded_size, NULL) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not encode UUID, to check length."))); - } - - // do encoding into the adv buffer - if (sd_ble_uuid_encode(&uuid, &encoded_size, &adv_data[byte_pos]) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can encode UUID into the advertisement packet."))); - } - - uuid_total_size += encoded_size; // size of entry - byte_pos += encoded_size; // relative to adv data packet - } +void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param) { + event_handler_t *handler = m_new_ll(event_handler_t, 1); + handler->next = NULL; + handler->param = param; + handler->func = func; - adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); - } - } - - if (bufinfo.len > 0) { - if (byte_pos + bufinfo.len > BLE_GAP_ADV_MAX_SIZE) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not fit data into the advertisement packet."))); - } - - memcpy(adv_data, bufinfo.buf, bufinfo.len); - byte_pos += bufinfo.len; - } - - uint32_t err_code; -#if (BLUETOOTH_SD == 132) - if ((err_code = sd_ble_gap_adv_data_set(adv_data, byte_pos, NULL, 0)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply advertisement data. status: 0x%02x"), (uint16_t)err_code)); - } -#endif - - static ble_gap_adv_params_t m_adv_params; - - // initialize advertising params - memset(&m_adv_params, 0, sizeof(m_adv_params)); - if (adv_params->connectable) { -#if (BLUETOOTH_SD == 140) - m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; -#else - m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND; -#endif - } else { -#if (BLUETOOTH_SD == 140) - m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; -#else - m_adv_params.type = BLE_GAP_ADV_TYPE_ADV_NONCONN_IND; -#endif - } - - m_adv_params.p_peer_addr = NULL; // undirected advertisement - m_adv_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); // approx 8 ms -#if (BLUETOOTH_SD == 140) - m_adv_params.duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED; - m_adv_params.filter_policy = BLE_GAP_ADV_FP_ANY; - m_adv_params.primary_phy = BLE_GAP_PHY_1MBPS; -#else - m_adv_params.fp = BLE_GAP_ADV_FP_ANY; - m_adv_params.timeout = 0; // infinite advertisement -#endif - - ble_drv_advertise_stop(); - -#if (BLUETOOTH_SD == 140) - const ble_gap_adv_data_t ble_gap_adv_data = { - .adv_data = { - .p_data = adv_data, - .len = byte_pos - } - }; - - if ((err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not apply advertisement data. status: 0x%02x"), (uint16_t)err_code)); - } - err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_DEFAULT); -#elif (BLUETOOTH_SD == 132 && BLE_API_VERSION == 4) - err_code = sd_ble_gap_adv_start(&m_adv_params, BLE_CONN_CFG_TAG_DEFAULT); -#else - err_code = sd_ble_gap_adv_start(&m_adv_params); -#endif - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not start advertisement. status: 0x%02x"), (uint16_t)err_code)); - } - - return true; -} - -void ble_drv_advertise_stop(void) { - uint32_t err_code; - -#if (BLUETOOTH_SD == 140) - if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) + if (m_event_handlers == NULL) { + m_event_handlers = handler; return; - - err_code = sd_ble_gap_adv_stop(m_adv_handle); -#else - err_code = sd_ble_gap_adv_stop(); -#endif - - if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not stop advertisement. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data) { - ble_gatts_value_t gatts_value; - memset(&gatts_value, 0, sizeof(gatts_value)); - - gatts_value.len = len; - gatts_value.offset = 0; - gatts_value.p_value = p_data; - - uint32_t err_code = sd_ble_gatts_value_get(conn_handle, - handle, - &gatts_value); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not read attribute value. status: 0x%02x"), (uint16_t)err_code)); } -} - -void ble_drv_attr_s_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - bleio_device_obj_t *device = MP_OBJ_TO_PTR(characteristic->service->device); - uint16_t conn_handle = device->conn_handle; - ble_gatts_value_t gatts_value; - - memset(&gatts_value, 0, sizeof(gatts_value)); - - gatts_value.len = bufinfo->len; - gatts_value.offset = 0; - gatts_value.p_value = bufinfo->buf; - - uint32_t err_code = sd_ble_gatts_value_set(conn_handle, characteristic->handle, &gatts_value); - - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not write attribute value. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_attr_s_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - bleio_device_obj_t *device = MP_OBJ_TO_PTR(characteristic->service->device); - uint16_t conn_handle = device->conn_handle; - ble_gatts_hvx_params_t hvx_params; - uint16_t hvx_len = bufinfo->len; - - memset(&hvx_params, 0, sizeof(hvx_params)); - - hvx_params.handle = characteristic->handle; - hvx_params.type = BLE_GATT_HVX_NOTIFICATION; - hvx_params.offset = 0; - hvx_params.p_len = &hvx_len; - hvx_params.p_data = bufinfo->buf; - - while (m_tx_in_progress) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP -#endif - } - - m_tx_in_progress = true; - uint32_t err_code; - if ((err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not notify attribute value. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_gap_event_handler_set(bleio_device_obj_t *device, ble_drv_gap_evt_callback_t evt_handler) { - mp_gap_observer = device; - gap_event_handler = evt_handler; -} - -void ble_drv_gatts_event_handler_set(bleio_device_obj_t *device, ble_drv_gatts_evt_callback_t evt_handler) { - mp_gatts_observer = device; - gatts_event_handler = evt_handler; -} - -void ble_drv_adv_report_handler_set(bleio_scanner_obj_t *device, ble_drv_adv_evt_callback_t evt_handler) { - mp_adv_observer = device; - adv_event_handler = evt_handler; -} - -void ble_drv_attr_c_read(bleio_characteristic_obj_t *characteristic) { - bleio_service_obj_t *service = characteristic->service; - bleio_device_obj_t *device = MP_OBJ_TO_PTR(service->device); - - mp_gattc_char_data_observer = characteristic; - - const uint32_t err_code = sd_ble_gattc_read(device->conn_handle, characteristic->handle, 0); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not read attribute value. status: 0x%02x"), (uint16_t)err_code)); - } - - while (mp_gattc_char_data_observer != NULL) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP -#endif - } -} - -void ble_drv_attr_c_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - bleio_device_obj_t *device = MP_OBJ_TO_PTR(characteristic->service->device); - uint16_t conn_handle = device->conn_handle; - - ble_gattc_write_params_t write_params; - write_params.write_op = BLE_GATT_OP_WRITE_REQ; - - if (characteristic->props.write_wo_resp) { - write_params.write_op = BLE_GATT_OP_WRITE_CMD; - } - - write_params.flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL; - write_params.handle = characteristic->handle; - write_params.offset = 0; - write_params.len = bufinfo->len; - write_params.p_value = bufinfo->buf; - - m_write_done = (write_params.write_op == BLE_GATT_OP_WRITE_CMD); - - uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params); - if (err_code != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not write attribute value. status: 0x%02x"), (uint16_t)err_code)); - } - - while (m_write_done != true) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP -#endif - } -} - -void ble_drv_scan_start(uint16_t interval, uint16_t window) { - SD_TEST_OR_ENABLE(); - - ble_gap_scan_params_t scan_params; - memset(&scan_params, 0, sizeof(ble_gap_scan_params_t)); - - scan_params.active = 1; - scan_params.interval = MSEC_TO_UNITS(interval, UNIT_0_625_MS); - scan_params.window = MSEC_TO_UNITS(window, UNIT_0_625_MS); -#if (BLUETOOTH_SD == 140) - scan_params.scan_phys = BLE_GAP_PHY_1MBPS; -#endif - scan_params.timeout = 0; // Infinite - - uint32_t err_code; -#if (BLUETOOTH_SD == 140) - if ((err_code = sd_ble_gap_scan_start(&scan_params, &m_scan_buffer)) != 0) { -#else - if ((err_code = sd_ble_gap_scan_start(&scan_params)) != 0) { -#endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Can not start scanning. status: 0x%02x"), (uint16_t)err_code)); - } -} - -void ble_drv_scan_continue(void) { - SD_TEST_OR_ENABLE(); - -#if (BLUETOOTH_SD == 140) - uint32_t err_code; - if ((err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer)) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - "Can not continue scanning. status: 0x" HEX2_FMT, (uint16_t)err_code)); - } -#endif -} - -void ble_drv_scan_stop(void) { - sd_ble_gap_scan_stop(); -} - -STATIC void ble_drv_connect_scan_callback(bleio_scanner_obj_t *scanner, bleio_scanentry_obj_t *entry) { - if (memcmp(entry->address.value, mp_connect_address->value, BLEIO_ADDRESS_BYTES) == 0) { - ble_drv_adv_report_handler_set(NULL, NULL); - - ble_gap_scan_params_t scan_params; - memset(&scan_params, 0, sizeof(scan_params)); - - scan_params.active = 1; - scan_params.interval = MSEC_TO_UNITS(100, UNIT_0_625_MS); - scan_params.window = MSEC_TO_UNITS(100, UNIT_0_625_MS); - scan_params.timeout = 0; - - ble_gap_addr_t addr; - memset(&addr, 0, sizeof(addr)); - - addr.addr_type = entry->address.type; - memcpy(addr.addr, entry->address.value, BLEIO_ADDRESS_BYTES); - - BLE_DRIVER_LOG("GAP CONNECTING: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT", type: %d\n", - addr.addr[5], addr.addr[4], addr.addr[3], addr.addr[2], addr.addr[1], addr.addr[0], addr.addr_type); - - ble_gap_conn_params_t conn_params = { - .min_conn_interval = BLE_MIN_CONN_INTERVAL, - .max_conn_interval = BLE_MAX_CONN_INTERVAL, - .conn_sup_timeout = BLE_CONN_SUP_TIMEOUT, - .slave_latency = BLE_SLAVE_LATENCY, - }; - - uint32_t err_code; - #if (BLE_API_VERSION == 2) - if ((err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params)) != 0) { - #else - if ((err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_DEFAULT)) != 0) { - #endif - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - "Can not connect. status: 0x" HEX2_FMT, (uint16_t)err_code)); + event_handler_t *it = m_event_handlers; + while (it->next != NULL) { + if ((it->func == func) && (it->param == param)) { + m_free(handler); + return; } - } -} - -void ble_drv_connect(bleio_device_obj_t *device) { - SD_TEST_OR_ENABLE(); - - mp_connect_address = &device->address; - ble_drv_adv_report_handler_set(NULL, ble_drv_connect_scan_callback); - - ble_drv_scan_start(100, 100); -} - -void ble_drv_disconnect(bleio_device_obj_t *device) { - sd_ble_gap_disconnect(device->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); -} - -bool ble_drv_discover_services(bleio_device_obj_t *device, uint16_t start_handle) { - mp_gattc_disc_service_observer = device; - - m_primary_service_found = false; - - uint32_t err_code = sd_ble_gattc_primary_services_discover(device->conn_handle, start_handle, NULL); - if (err_code != NRF_SUCCESS) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - "Failed to discover serivices. status: 0x" HEX2_FMT, (uint16_t)err_code)); - } - while (mp_gattc_disc_service_observer != NULL) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP -#endif + it = it->next; } - return m_primary_service_found; + it->next = handler; } -bool ble_drv_discover_characteristic(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle) { - BLE_DRIVER_LOG("Discover characteristicts. Conn handle: 0x" HEX2_FMT "\n", device->conn_handle); - - mp_gattc_disc_char_observer = service; - - ble_gattc_handle_range_t handle_range; - handle_range.start_handle = start_handle; - handle_range.end_handle = service->end_handle; - - m_characteristic_found = false; - - uint32_t err_code = sd_ble_gattc_characteristics_discover(device->conn_handle, &handle_range); - if (err_code != 0) { - return false; - } - - while (mp_gattc_disc_char_observer != NULL) { -#ifdef MICROPY_VM_HOOK_LOOP - MICROPY_VM_HOOK_LOOP -#endif - } - - return m_characteristic_found; -} - -void ble_drv_discover_descriptors(void) { - -} - -STATIC void on_adv_report(ble_gap_evt_adv_report_t *report) { - bleio_scanentry_obj_t *entry = m_new_obj(bleio_scanentry_obj_t); - entry->base.type = &bleio_scanentry_type; - - entry->rssi = report->rssi; - - entry->address.type = report->peer_addr.addr_type; - memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES); - -#if (BLUETOOTH_SD == 140) - entry->data = mp_obj_new_bytearray(report->data.len, report->data.p_data); -#else - entry->data = mp_obj_new_bytearray(report->dlen, report->data); -#endif - - if (adv_event_handler != NULL) { - adv_event_handler(mp_adv_observer, entry); - } -} - -STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response) { - BLE_DRIVER_LOG(">>> service count: %d\n", response->count); - - for (size_t i = 0; i < response->count; ++i) { - const 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; - service->char_list = mp_obj_new_list(0, NULL); - service->start_handle = gattc_service->handle_range.start_handle; - service->end_handle = gattc_service->handle_range.end_handle; - service->handle = gattc_service->handle_range.start_handle; - service->device = mp_gattc_disc_service_observer; - - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - uuid->type = (gattc_service->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; - uuid->value[0] = gattc_service->uuid.uuid & 0xFF; - uuid->value[1] = gattc_service->uuid.uuid >> 8; - service->uuid = uuid; - - mp_obj_list_append(mp_gattc_disc_service_observer->service_list, service); - } - - if (response->count > 0) { - m_primary_service_found = true; - } - - // mark end of service discovery - mp_gattc_disc_service_observer = NULL; -} - -STATIC void on_characteristic_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response) { - BLE_DRIVER_LOG(">>> characteristic count: %d\n", response->count); - - for (size_t i = 0; i < response->count; ++i) { - const 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; - - bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); - uuid->base.type = &bleio_uuid_type; - uuid->type = (gattc_char->uuid.type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; - uuid->value[0] = gattc_char->uuid.uuid & 0xFF; - uuid->value[1] = gattc_char->uuid.uuid >> 8; - characteristic->uuid = uuid; - - characteristic->props.broadcast = gattc_char->char_props.broadcast; - characteristic->props.indicate = gattc_char->char_props.indicate; - characteristic->props.notify = gattc_char->char_props.notify; - characteristic->props.read = gattc_char->char_props.read; - characteristic->props.write = gattc_char->char_props.write; - characteristic->props.write_wo_resp = gattc_char->char_props.write_wo_resp; - characteristic->handle = gattc_char->handle_value; - - characteristic->service_handle = mp_gattc_disc_char_observer->handle; - characteristic->service = mp_gattc_disc_char_observer; - - mp_obj_list_append(mp_gattc_disc_char_observer->char_list, MP_OBJ_FROM_PTR(characteristic)); - } - - if (response->count > 0) { - m_characteristic_found = true; +void SD_EVT_IRQHandler(void) { + uint32_t evt_id; + while (sd_evt_get(&evt_id) != NRF_ERROR_NOT_FOUND) { +// sd_evt_handler(evt_id); } - // mark end of characteristic discovery - mp_gattc_disc_char_observer = NULL; -} - -STATIC void on_read_rsp(ble_gattc_evt_read_rsp_t *response) { - mp_gattc_char_data_observer->value_data = mp_obj_new_bytearray(response->len, response->data); - - mp_gattc_char_data_observer = NULL; -} - -STATIC void ble_evt_handler(ble_evt_t *p_ble_evt) { - printf("%s - 0x%02X\r\n", __func__, p_ble_evt->header.evt_id); - - switch (p_ble_evt->header.evt_id) { - case BLE_GAP_EVT_CONNECTED: - BLE_DRIVER_LOG("GAP CONNECT\n"); - gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - - ble_gap_conn_params_t conn_params; - (void)sd_ble_gap_ppcp_get(&conn_params); - (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, &conn_params); - break; - - case BLE_GAP_EVT_DISCONNECTED: - BLE_DRIVER_LOG("GAP DISCONNECT\n"); - gap_event_handler(mp_gap_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - break; - - case BLE_GATTS_EVT_HVC: - gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, p_ble_evt->evt.gatts_evt.params.hvc.handle, p_ble_evt->header.evt_len - (2 * sizeof(uint16_t)), NULL); - break; - - case BLE_GATTS_EVT_WRITE: - BLE_DRIVER_LOG("GATTS write\n"); - - uint16_t handle = p_ble_evt->evt.gatts_evt.params.write.handle; - uint16_t data_len = p_ble_evt->evt.gatts_evt.params.write.len; - uint8_t * p_data = &p_ble_evt->evt.gatts_evt.params.write.data[0]; - - gatts_event_handler(mp_gatts_observer, p_ble_evt->header.evt_id, handle, data_len, p_data); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE: - BLE_DRIVER_LOG("GAP CONN PARAM UPDATE\n"); - break; - - case BLE_GATTS_EVT_SYS_ATTR_MISSING: - // No system attributes have been stored. - (void)sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0, 0); - break; - -#if (BLE_API_VERSION == 4) - case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: - BLE_DRIVER_LOG("GATTS EVT EXCHANGE MTU REQUEST\n"); - (void)sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle, 23); // MAX MTU size - break; -#endif - -#if (BLE_API_VERSION == 4) - case BLE_GATTS_EVT_HVN_TX_COMPLETE: -#else - case BLE_EVT_TX_COMPLETE: -#endif - BLE_DRIVER_LOG("BLE EVT TX COMPLETE\n"); - m_tx_in_progress = false; - break; - - case BLE_GAP_EVT_SEC_PARAMS_REQUEST: - BLE_DRIVER_LOG("BLE EVT SEC PARAMS REQUEST\n"); - // pairing not supported - (void)sd_ble_gap_sec_params_reply(p_ble_evt->evt.gatts_evt.conn_handle, - BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, - NULL, NULL); - break; - - case BLE_GAP_EVT_ADV_REPORT: - on_adv_report(&p_ble_evt->evt.gap_evt.params.adv_report); - break; - - case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: - BLE_DRIVER_LOG("BLE EVT CONN PARAM UPDATE REQUEST\n"); - - (void)sd_ble_gap_conn_param_update(p_ble_evt->evt.gap_evt.conn_handle, - &p_ble_evt->evt.gap_evt.params.conn_param_update_request.conn_params); - break; - - case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: - on_primary_srv_discovery_rsp(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp); - break; - - case BLE_GATTC_EVT_CHAR_DISC_RSP: - on_characteristic_discovery_rsp(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp); - break; - - case BLE_GATTC_EVT_READ_RSP: - on_read_rsp(&p_ble_evt->evt.gattc_evt.params.read_rsp); - break; - - case BLE_GATTC_EVT_WRITE_RSP: - BLE_DRIVER_LOG("BLE EVT WRITE RESPONSE\n"); - m_write_done = true; - break; + while (1) { + uint16_t evt_len = sizeof(m_ble_evt_buf); + const uint32_t err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); + if (err_code != NRF_SUCCESS) { + if (err_code == NRF_ERROR_DATA_SIZE) { + printf("NRF_ERROR_DATA_SIZE\n"); + } - case BLE_GATTC_EVT_HVX: - BLE_DRIVER_LOG("BLE EVT HVX RESPONSE\n"); break; + } - default: - BLE_DRIVER_LOG(">>> unhandled evt: 0x" HEX2_FMT "\n", p_ble_evt->header.evt_id); - break; + event_handler_t *it = m_event_handlers; + while (it != NULL) { + it->func((ble_evt_t *)m_ble_evt_buf, it->param); + it = it->next; + } } } - -#if (BLE_API_VERSION == 2) -static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (GATT_MTU_SIZE_DEFAULT)] __attribute__ ((aligned (4))); -#else -static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)] __attribute__ ((aligned (4))); -#endif - -void SD_EVT_IRQHandler(void) { - uint32_t evt_id; - uint32_t err_code; - do { - err_code = sd_evt_get(&evt_id); - // TODO: handle non ble events - } while (err_code != NRF_ERROR_NOT_FOUND && err_code != NRF_SUCCESS); - - uint16_t evt_len = sizeof(m_ble_evt_buf); - do { - err_code = sd_ble_evt_get(m_ble_evt_buf, &evt_len); - ble_evt_handler((ble_evt_t *)m_ble_evt_buf); - } while (err_code != NRF_ERROR_NOT_FOUND && err_code != NRF_SUCCESS); -} - -#endif // BLUETOOTH_SD diff --git a/ports/nrf/drivers/bluetooth/ble_drv.h b/ports/nrf/drivers/bluetooth/ble_drv.h index 3b065c7a9..426354a19 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.h +++ b/ports/nrf/drivers/bluetooth/ble_drv.h @@ -4,6 +4,7 @@ * The MIT License (MIT) * * Copyright (c) 2016 Glenn Ruben Bakke + * Copyright (c) 2018 Artur Pacholec * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -27,65 +28,26 @@ #ifndef BLUETOOTH_LE_DRIVER_H__ #define BLUETOOTH_LE_DRIVER_H__ -#if BLUETOOTH_SD +#include "ble.h" -#include "shared-bindings/bleio/Device.h" -#include "shared-bindings/bleio/Scanner.h" -#include "shared-bindings/bleio/Service.h" -#include "shared-module/bleio/ScanEntry.h" +#if (BLUETOOTH_SD == 132) && (BLE_API_VERSION == 2) +#define NRF52 +#endif -typedef void (*ble_drv_gap_evt_callback_t)(bleio_device_obj_t *device, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_gatts_evt_callback_t)(bleio_device_obj_t *device, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_adv_evt_callback_t)(bleio_scanner_obj_t *scanner, bleio_scanentry_obj_t *entry); +#define MAX_TX_IN_PROGRESS 10 -uint32_t ble_drv_stack_enable(void); +#ifndef BLE_GATT_ATT_MTU_DEFAULT + #define BLE_GATT_ATT_MTU_DEFAULT GATT_MTU_SIZE_DEFAULT +#endif -uint8_t ble_drv_stack_enabled(void); +#define BLE_CONN_CFG_TAG_CUSTOM 1 -void ble_drv_address_get(bleio_address_obj_t *address); +#define MSEC_TO_UNITS(TIME, RESOLUTION) (((TIME) * 1000) / (RESOLUTION)) +#define UNIT_0_625_MS (625) +#define UNIT_10_MS (10000) -bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx); +typedef void (*ble_drv_evt_handler_t)(ble_evt_t*, void*); -void ble_drv_service_add(bleio_service_obj_t *service); - -bool ble_drv_characteristic_add(bleio_characteristic_obj_t *characteristic); - -bool ble_drv_advertise_data(bleio_advertisement_data_t *p_adv_params); - -void ble_drv_advertise_stop(void); - -void ble_drv_gap_event_handler_set(bleio_device_obj_t *device, ble_drv_gap_evt_callback_t evt_handler); - -void ble_drv_gatts_event_handler_set(bleio_device_obj_t *device, ble_drv_gatts_evt_callback_t evt_handler); - -void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, uint8_t * p_data); - -void ble_drv_attr_c_read(bleio_characteristic_obj_t *characteristic); - -void ble_drv_attr_s_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo); - -void ble_drv_attr_s_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo); - -void ble_drv_attr_c_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo); - -void ble_drv_scan_start(uint16_t interval, uint16_t window); - -void ble_drv_scan_continue(void); - -void ble_drv_scan_stop(void); - -void ble_drv_adv_report_handler_set(bleio_scanner_obj_t *self, ble_drv_adv_evt_callback_t evt_handler); - -void ble_drv_connect(bleio_device_obj_t *device); - -void ble_drv_disconnect(bleio_device_obj_t *device); - -bool ble_drv_discover_services(bleio_device_obj_t *device, uint16_t start_handle); - -bool ble_drv_discover_characteristic(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle); - -void ble_drv_discover_descriptors(void); - -#endif // BLUETOOTH_SD +void ble_drv_add_event_handler(ble_drv_evt_handler_t func, void *param); #endif // BLUETOOTH_LE_DRIVER_H__ diff --git a/ports/nrf/drivers/bluetooth/ble_uart.h b/ports/nrf/drivers/bluetooth/ble_uart.h index 336624cd3..b57a75229 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.h +++ b/ports/nrf/drivers/bluetooth/ble_uart.h @@ -27,7 +27,7 @@ #ifndef BLUETOOTH_LE_UART_H__ #define BLUETOOTH_LE_UART_H__ -#if BLUETOOTH_SD +#include #include "ble_drv.h" @@ -36,6 +36,4 @@ void ble_uart_advertise(void); bool ble_uart_connected(void); bool ble_uart_enabled(void); -#endif // BLUETOOTH_SD - #endif // BLUETOOTH_LE_UART_H__ -- cgit v1.2.3