diff options
| -rwxr-xr-x | ports/nrf/Makefile | 5 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Characteristic.c | 6 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Device.c | 166 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Scanner.c | 3 | ||||
| -rw-r--r-- | ports/nrf/drivers/bluetooth/ble_drv.c | 396 | ||||
| -rw-r--r-- | ports/nrf/drivers/bluetooth/ble_drv.h | 36 | ||||
| -rw-r--r-- | ports/nrf/drivers/bluetooth/ble_uart.h | 1 | ||||
| -rw-r--r-- | ports/nrf/modules/ubluepy/modubluepy.h | 126 | ||||
| -rw-r--r-- | ports/nrf/modules/ubluepy/ubluepy_peripheral.c | 507 | ||||
| -rw-r--r-- | ports/nrf/mpconfigport.h | 33 | ||||
| -rw-r--r-- | shared-bindings/bleio/Device.c | 348 | ||||
| -rw-r--r-- | shared-bindings/bleio/Device.h (renamed from ports/nrf/modules/ubluepy/modubluepy.c) | 30 | ||||
| -rw-r--r-- | shared-bindings/bleio/ScanEntry.c | 5 | ||||
| -rw-r--r-- | shared-bindings/bleio/ScanEntry.h | 11 | ||||
| -rw-r--r-- | shared-bindings/bleio/Service.c | 6 | ||||
| -rw-r--r-- | shared-bindings/bleio/__init__.c | 3 | ||||
| -rw-r--r-- | shared-module/bleio/AdvertisementData.h | 9 | ||||
| -rw-r--r-- | shared-module/bleio/Device.h | 45 | ||||
| -rw-r--r-- | shared-module/bleio/ScanEntry.h | 40 | ||||
| -rw-r--r-- | shared-module/bleio/Service.h | 3 |
20 files changed, 831 insertions, 948 deletions
diff --git a/ports/nrf/Makefile b/ports/nrf/Makefile index 6112678f5..b059569ab 100755 --- a/ports/nrf/Makefile +++ b/ports/nrf/Makefile @@ -127,10 +127,6 @@ SRC_C += \ peripherals/nrf/timers.c \ supervisor/shared/memory.c -DRIVERS_SRC_C += $(addprefix modules/,\ - ubluepy/modubluepy.c \ - ubluepy/ubluepy_peripheral.c \ - ) SRC_COMMON_HAL += \ analogio/AnalogIn.c \ @@ -163,6 +159,7 @@ SRC_COMMON_HAL += \ bleio/Adapter.c \ bleio/Characteristic.c \ bleio/Descriptor.c \ + bleio/Device.c \ bleio/Scanner.c \ bleio/Service.c \ bleio/UUID.c diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 56afc52c5..938289f2d 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -26,6 +26,7 @@ #include "ble_drv.h" #include "shared-module/bleio/Characteristic.h" +#include "shared-module/bleio/Device.h" void data_callback(bleio_characteristic_obj_t *self, uint16_t length, uint8_t *data) { self->value_data = mp_obj_new_bytearray(length, data); @@ -36,10 +37,9 @@ void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self } void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { - ubluepy_peripheral_obj_t *peripheral = MP_OBJ_TO_PTR(self->service->periph); - ubluepy_role_type_t role = peripheral->role; + const bleio_device_obj_t *device = MP_OBJ_TO_PTR(self->service->device); - if (role == UBLUEPY_ROLE_PERIPHERAL) { + if (device->is_peripheral) { // TODO: Add indications if (self->props.notify) { ble_drv_attr_s_notify(self, bufinfo); diff --git a/ports/nrf/common-hal/bleio/Device.c b/ports/nrf/common-hal/bleio/Device.c new file mode 100644 index 000000000..ab2898e72 --- /dev/null +++ b/ports/nrf/common-hal/bleio/Device.c @@ -0,0 +1,166 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <stdio.h> + +#include "ble_drv.h" +#include "ble_gap.h" +#include "ble_gatt.h" +#include "ble_types.h" +#include "py/runtime.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 volatile bool m_disc_evt_received; + +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; + } +} + +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 void gattc_event_handler(bleio_device_obj_t *device, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { + m_disc_evt_received = true; +} + +STATIC void disc_add_service(bleio_device_obj_t *device, ble_drv_service_data_t * service_data) { + bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t); + service->base.type = &bleio_service_type; + + bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t); + uuid->base.type = &bleio_uuid_type; + uuid->type = (service_data->uuid_type == BLE_UUID_TYPE_BLE) ? UUID_TYPE_16BIT : UUID_TYPE_128BIT; + uuid->value[0] = service_data->uuid & 0xFF; + uuid->value[1] = service_data->uuid >> 8; + + service->char_list = mp_obj_new_list(0, NULL); + service->uuid = uuid; + service->device = device; + service->handle = service_data->start_handle; + service->start_handle = service_data->start_handle; + service->end_handle = service_data->end_handle; + + mp_obj_list_append(device->service_list, service); +} + +STATIC void disc_add_char(bleio_service_obj_t *service, ble_drv_char_data_t *chara_data) { + bleio_characteristic_obj_t *chara = m_new_obj(bleio_characteristic_obj_t); + chara->base.type = &bleio_characteristic_type; + + bleio_uuid_obj_t * p_uuid = m_new_obj(bleio_uuid_obj_t); + p_uuid->base.type = &bleio_uuid_type; + + chara->uuid = p_uuid; + + p_uuid->type = chara_data->uuid_type; + p_uuid->value[0] = chara_data->uuid & 0xFF; + p_uuid->value[1] = chara_data->uuid >> 8; + + // add characteristic specific data from discovery + chara->props.broadcast = chara_data->props.broadcast; + chara->props.indicate = chara_data->props.indicate; + chara->props.notify = chara_data->props.notify; + chara->props.read = chara_data->props.read; + chara->props.write = chara_data->props.write; + chara->props.write_wo_resp = chara_data->props.write_wo_resp; + chara->handle = chara_data->value_handle; + + chara->service_handle = service->handle; + chara->service = service; + + mp_obj_list_append(service->char_list, MP_OBJ_FROM_PTR(chara)); +} + + +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); + } + + ble_drv_advertise_data(adv_data); +} + +void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device) { + (void)device; + + ble_drv_advertise_stop(); +} + +void common_hal_bleio_device_connect(bleio_device_obj_t *device) { + ble_drv_gap_event_handler_set(device, gap_event_handler); + + ble_drv_connect(device); + + while (device->conn_handle == BLE_CONN_HANDLE_INVALID) { + run_background_tasks(); +// __asm volatile ("wfi"); + } + + ble_drv_gattc_event_handler_set(device, gattc_event_handler); + + // TODO: read name + + // find services + bool found_service = ble_drv_discover_services(device, BLE_GATT_HANDLE_START, disc_add_service); + 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, disc_add_service); + } + + // find characteristics in each service + const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(device->service_list); + 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, disc_add_char); + 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]; + + const uint16_t next_handle = characteristic->handle + 1; + if (next_handle >= service->end_handle) { + break; + } + + found_char = ble_drv_discover_characteristic(device, service, next_handle, disc_add_char); + } + } +} + +void common_hal_bleio_device_disconnect(bleio_device_obj_t *device) { + ble_drv_disconnect(device); +} diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c index ed1987144..0eb50a1f6 100644 --- a/ports/nrf/common-hal/bleio/Scanner.c +++ b/ports/nrf/common-hal/bleio/Scanner.c @@ -29,8 +29,9 @@ #include "ble_drv.h" #include "py/mphal.h" -#include "shared-bindings/bleio/Scanner.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, ble_drv_adv_data_t *data) { // TODO: Don't add new entry for each item, group by address and update diff --git a/ports/nrf/drivers/bluetooth/ble_drv.c b/ports/nrf/drivers/bluetooth/ble_drv.c index e421036ae..1ab1d9337 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.c +++ b/ports/nrf/drivers/bluetooth/ble_drv.c @@ -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 @@ -34,6 +35,8 @@ #define NRF52 // Needed for SD132 v2 #endif +#include "shared-module/bleio/Device.h" +#include "py/objstr.h" #include "py/runtime.h" #include "supervisor/shared/translate.h" #include "ble_drv.h" @@ -41,15 +44,10 @@ #include "nrf_sdm.h" #include "nrfx_power.h" #include "ble_gap.h" +#include "ble_hci.h" #include "ble.h" // sd_ble_uuid_encode - -#define BLE_DRIVER_VERBOSE 0 -#if BLE_DRIVER_VERBOSE #define BLE_DRIVER_LOG printf -#else -#define BLE_DRIVER_LOG(...) -#endif #define BLE_ADV_LENGTH_FIELD_SIZE 1 #define BLE_ADV_AD_TYPE_FIELD_SIZE 1 @@ -61,8 +59,8 @@ #define APP_CFG_NON_CONN_ADV_TIMEOUT 0 // Disable timeout. #define NON_CONNECTABLE_ADV_INTERVAL MSEC_TO_UNITS(100, UNIT_0_625_MS) -#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) -#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(12, UNIT_0_625_MS) +#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) @@ -81,8 +79,8 @@ static volatile bool m_tx_in_progress; static ble_drv_gap_evt_callback_t gap_event_handler; static ble_drv_gatts_evt_callback_t gatts_event_handler; -static mp_obj_t mp_gap_observer; -static mp_obj_t mp_gatts_observer; +static bleio_device_obj_t *mp_gap_observer; +static bleio_device_obj_t *mp_gatts_observer; static volatile bool m_primary_service_found; static volatile bool m_characteristic_found; @@ -95,10 +93,11 @@ static volatile ble_drv_disc_add_char_callback_t disc_add_char_handler; static volatile ble_drv_gattc_char_data_callback_t gattc_char_data_handle; static bleio_scanner_obj_t *mp_adv_observer; -static mp_obj_t mp_gattc_observer; -static mp_obj_t mp_gattc_disc_service_observer; -static mp_obj_t mp_gattc_disc_char_observer; +static bleio_device_obj_t *mp_gattc_observer; +static bleio_device_obj_t *mp_gattc_disc_service_observer; +static bleio_service_obj_t *mp_gattc_disc_char_observer; static bleio_characteristic_obj_t *mp_gattc_char_data_observer; +static bleio_address_obj_t *mp_connect_address; #if (BLUETOOTH_SD == 140) static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET; @@ -123,18 +122,6 @@ uint32_t ble_drv_stack_enable(void) { m_adv_in_progress = false; m_tx_in_progress = false; -#if BLUETOOTH_LFCLK_RC - nrf_clock_lf_cfg_t clock_config = { - .source = NRF_CLOCK_LF_SRC_RC, - .rc_ctiv = 16, - .rc_temp_ctiv = 2, -#if (BLE_API_VERSION == 4) - .accuracy = 0 -#else - .xtal_accuracy = 0 -#endif - }; -#else nrf_clock_lf_cfg_t clock_config = { .source = NRF_CLOCK_LF_SRC_XTAL, .rc_ctiv = 0, @@ -145,23 +132,22 @@ uint32_t ble_drv_stack_enable(void) { .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM #endif }; -#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); - - BLE_DRIVER_LOG("SoftDevice enable status: " UINT_FMT "\n", (uint16_t)err_code); + 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(SWI2_EGU2_IRQn); - - BLE_DRIVER_LOG("IRQ 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)); @@ -169,48 +155,17 @@ uint32_t ble_drv_stack_enable(void) { 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; -#endif -#if (BLE_API_VERSION == 2) - uint32_t app_ram_start = 0x200039c0; + app_ram_start = 0x200039c0; err_code = sd_ble_enable(&ble_enable_params, &app_ram_start); // 8K SD headroom from linker script. - BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); #else - uint32_t app_ram_start = 0x20004000; + app_ram_start = 0x20004000; err_code = sd_ble_enable(&app_ram_start); - BLE_DRIVER_LOG("BLE ram size: " UINT_FMT "\n", (uint16_t)app_ram_start); #endif - - BLE_DRIVER_LOG("BLE enable status: " UINT_FMT "\n", (uint16_t)err_code); - - // set up security mode - ble_gap_conn_params_t gap_conn_params; - ble_gap_conn_sec_mode_t sec_mode; - - BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); - - const char device_name[] = "micr"; - - if ((err_code = sd_ble_gap_device_name_set(&sec_mode, - (const uint8_t *)device_name, - strlen(device_name))) != 0) { - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Cannot apply GAP parameters."))); - } - - // set connection parameters - memset(&gap_conn_params, 0, sizeof(gap_conn_params)); - - gap_conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; - gap_conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; - gap_conn_params.slave_latency = BLE_SLAVE_LATENCY; - gap_conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; - - if (sd_ble_gap_ppcp_set(&gap_conn_params) != 0) { - - nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_OSError, - translate("Cannot set PPCP parameters."))); + 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; @@ -223,9 +178,10 @@ void ble_drv_stack_disable(void) { uint8_t ble_drv_stack_enabled(void) { uint8_t is_enabled; uint32_t err_code = sd_softdevice_is_enabled(&is_enabled); - (void)err_code; - BLE_DRIVER_LOG("Is enabled status: " UINT_FMT "\n", (uint16_t)err_code); + if (err_code != NRF_SUCCESS) { + BLE_DRIVER_LOG("Is enabled status: " UINT_FMT "\n", (uint16_t)err_code); + } return is_enabled; } @@ -256,10 +212,10 @@ void ble_drv_address_get(ble_drv_addr_t * p_addr) { memcpy(p_addr->addr, local_ble_addr.addr, 6); } -bool ble_drv_uuid_add_vs(uint8_t * p_uuid, uint8_t * idx) { +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 *)p_uuid, idx) != 0) { + 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."))); } @@ -284,9 +240,7 @@ void ble_drv_service_add(bleio_service_obj_t *service) { service_type = BLE_GATTS_SRVC_TYPE_SECONDARY; } - if (sd_ble_gatts_service_add(service_type, - &uuid, - &service->handle) != 0) { + 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."))); } @@ -372,59 +326,66 @@ bool ble_drv_characteristic_add(bleio_characteristic_obj_t *characteristic) { return true; } -bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { +// 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]; - if (p_adv_params->device_name_len > 0) { - ble_gap_conn_sec_mode_t sec_mode; + 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, - p_adv_params->p_device_name, - p_adv_params->device_name_len) != 0) { + 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."))); } - BLE_DRIVER_LOG("Device name applied\n"); - - adv_data[byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + p_adv_params->device_name_len); + 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], p_adv_params->p_device_name, p_adv_params->device_name_len); - // increment position counter to see if it fits, and in case more content should - // follow in this adv packet. - byte_pos += p_adv_params->device_name_len; + + memcpy(&adv_data[byte_pos], name_data, name_len); + + byte_pos += name_len; } - // Add FLAGS only if manually controlled data has not been used. - if (p_adv_params->data_len == 0) { - // set flags, default to disc mode + 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; } - if (p_adv_params->num_of_services > 0) { - + 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 (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - bleio_service_obj_t * p_service = (bleio_service_obj_t *)p_adv_params->p_services[i]; - if (p_service->uuid->type == UUID_TYPE_16BIT) { + 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 (p_service->uuid->type == UUID_TYPE_128BIT) { + if (service->uuid->type == UUID_TYPE_128BIT) { type_128bit_present = true; } } @@ -441,13 +402,17 @@ bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { uint8_t uuid_total_size = 0; uint8_t encoded_size = 0; - for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - bleio_service_obj_t * p_service = (bleio_service_obj_t *)p_adv_params->p_services[i]; + 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 = p_service->uuid->type; - uuid.uuid = p_service->uuid->value[0]; - uuid.uuid += p_service->uuid->value[1] << 8; + 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, @@ -460,19 +425,8 @@ bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { translate("Can encode UUID into the advertisement packet."))); } - BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); - for (uint8_t j = 0; j < encoded_size; j++) { - BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); - } - BLE_DRIVER_LOG("\n"); - uuid_total_size += encoded_size; // size of entry byte_pos += encoded_size; // relative to adv data packet - BLE_DRIVER_LOG("ADV: uuid size: %u, type: %u, uuid: %x%x, vs_idx: %u\n", - encoded_size, p_service->p_uuid->type, - p_service->p_uuid->value[1], - p_service->p_uuid->value[0], - p_service->p_uuid->uuid_vs_idx); } adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); @@ -490,13 +444,16 @@ bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { uint8_t uuid_total_size = 0; uint8_t encoded_size = 0; - for (uint8_t i = 0; i < p_adv_params->num_of_services; i++) { - bleio_service_obj_t * p_service = (bleio_service_obj_t *)p_adv_params->p_services[i]; + 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 = p_service->uuid->uuid_vs_idx; - uuid.uuid = p_service->uuid->value[0]; - uuid.uuid += p_service->uuid->value[1] << 8; + 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) { @@ -510,51 +467,37 @@ bool ble_drv_advertise_data(ubluepy_advertise_data_t * p_adv_params) { translate("Can encode UUID into the advertisement packet."))); } - BLE_DRIVER_LOG("encoded uuid for service %u: ", 0); - for (uint8_t j = 0; j < encoded_size; j++) { - BLE_DRIVER_LOG(HEX2_FMT " ", adv_data[byte_pos + j]); - } - BLE_DRIVER_LOG("\n"); - uuid_total_size += encoded_size; // size of entry byte_pos += encoded_size; // relative to adv data packet - BLE_DRIVER_LOG("ADV: uuid size: %u, type: %x%x, uuid: %u, vs_idx: %u\n", - encoded_size, p_service->p_uuid->type, - p_service->p_uuid->value[1], - p_service->p_uuid->value[0], - p_service->p_uuid->uuid_vs_idx); } adv_data[size_byte_pos] = (BLE_ADV_AD_TYPE_FIELD_SIZE + uuid_total_size); } } - if ((p_adv_params->data_len > 0) && (p_adv_params->p_data != NULL)) { - if (p_adv_params->data_len + byte_pos > BLE_GAP_ADV_MAX_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, p_adv_params->p_data, p_adv_params->data_len); - byte_pos += p_adv_params->data_len; + memcpy(adv_data, bufinfo.buf, bufinfo.len); + byte_pos += bufinfo.len; } - // scan response data not set 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)); } - BLE_DRIVER_LOG("Set Adv data size: " UINT_FMT "\n", byte_pos); #endif static ble_gap_adv_params_t m_adv_params; // initialize advertising params memset(&m_adv_params, 0, sizeof(m_adv_params)); - if (p_adv_params->connectable) { + if (adv_params->connectable) { #if (BLUETOOTH_SD == 140) m_adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED; #else @@ -643,8 +586,8 @@ void ble_drv_attr_s_read(uint16_t conn_handle, uint16_t handle, uint16_t len, ui } void ble_drv_attr_s_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - ubluepy_peripheral_obj_t *peripheral = MP_OBJ_TO_PTR(characteristic->service->periph); - uint16_t conn_handle = peripheral->conn_handle; + 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)); @@ -662,8 +605,8 @@ void ble_drv_attr_s_write(bleio_characteristic_obj_t *characteristic, mp_buffer_ } void ble_drv_attr_s_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { - ubluepy_peripheral_obj_t *peripheral = MP_OBJ_TO_PTR(characteristic->service->periph); - uint16_t conn_handle = peripheral->conn_handle; + 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; @@ -676,7 +619,9 @@ void ble_drv_attr_s_notify(bleio_characteristic_obj_t *characteristic, mp_buffer 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; @@ -687,50 +632,49 @@ void ble_drv_attr_s_notify(bleio_characteristic_obj_t *characteristic, mp_buffer } } -void ble_drv_gap_event_handler_set(mp_obj_t obj, ble_drv_gap_evt_callback_t evt_handler) { - mp_gap_observer = obj; +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(mp_obj_t obj, ble_drv_gatts_evt_callback_t evt_handler) { - mp_gatts_observer = obj; +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_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler) { - mp_gattc_observer = obj; +void ble_drv_gattc_event_handler_set(bleio_device_obj_t *device, ble_drv_gattc_evt_callback_t evt_handler) { + mp_gattc_observer = device; gattc_event_handler = evt_handler; } -void ble_drv_adv_report_handler_set(bleio_scanner_obj_t *self, ble_drv_adv_evt_callback_t evt_handler) { - mp_adv_observer = self; +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, ble_drv_gattc_char_data_callback_t cb) { bleio_service_obj_t *service = characteristic->service; - ubluepy_peripheral_obj_t *peripheral = MP_OBJ_TO_PTR(service->periph); + bleio_device_obj_t *device = MP_OBJ_TO_PTR(service->device); mp_gattc_char_data_observer = characteristic; gattc_char_data_handle = cb; - const uint32_t err_code = sd_ble_gattc_read(peripheral->conn_handle, - characteristic->handle, - 0); + 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 (gattc_char_data_handle != 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) { - ubluepy_peripheral_obj_t *peripheral = MP_OBJ_TO_PTR(characteristic->service->periph); - uint16_t conn_handle = peripheral->conn_handle; + 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; @@ -753,10 +697,13 @@ void ble_drv_attr_c_write(bleio_characteristic_obj_t *characteristic, mp_buffer_ translate("Can not write attribute value. status: 0x%02x"), (uint16_t)err_code)); } - while (m_write_done != true) { - ; + 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(); @@ -798,109 +745,108 @@ void ble_drv_scan_stop(void) { sd_ble_gap_scan_stop(); } -void ble_drv_connect(uint8_t * p_addr, uint8_t addr_type) { - SD_TEST_OR_ENABLE(); +STATIC void ble_drv_connect_scan_callback(bleio_scanner_obj_t *scanner, ble_drv_adv_data_t *data) { + if (memcmp(data->p_peer_addr, mp_connect_address->value, BLEIO_ADDRESS_BYTES) == 0) { + ble_drv_adv_report_handler_set(NULL, NULL); - ble_gap_scan_params_t 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; // Infinite + ble_gap_scan_params_t scan_params; + memset(&scan_params, 0, sizeof(scan_params)); - ble_gap_addr_t addr; - memset(&addr, 0, sizeof(addr)); + 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; - addr.addr_type = addr_type; - memcpy(addr.addr, p_addr, 6); + ble_gap_addr_t addr; + memset(&addr, 0, sizeof(addr)); - BLE_DRIVER_LOG("GAP CONNECTING: "HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT":"HEX2_FMT", type: %d\n", - addr.addr[0], addr.addr[1], addr.addr[2], addr.addr[3], addr.addr[4], addr.addr[5], addr.addr_type); + addr.addr_type = data->addr_type; + memcpy(addr.addr, data->p_peer_addr, BLEIO_ADDRESS_BYTES); - ble_gap_conn_params_t conn_params; + 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)); + } + } +} -// (void)sd_ble_gap_ppcp_get(&conn_params); +void ble_drv_connect(bleio_device_obj_t *device) { + SD_TEST_OR_ENABLE(); - // set connection parameters - memset(&conn_params, 0, sizeof(conn_params)); + mp_connect_address = &device->address; + ble_drv_adv_report_handler_set(NULL, ble_drv_connect_scan_callback); - conn_params.min_conn_interval = BLE_MIN_CONN_INTERVAL; - conn_params.max_conn_interval = BLE_MAX_CONN_INTERVAL; - conn_params.slave_latency = BLE_SLAVE_LATENCY; - conn_params.conn_sup_timeout = BLE_CONN_SUP_TIMEOUT; + ble_drv_scan_start(100, 100); +} - 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, - translate("Can not connect. status: 0x%02x"), (uint16_t)err_code)); - } +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(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb) { - BLE_DRIVER_LOG("Discover primary services. Conn handle: 0x" HEX2_FMT "\n", - conn_handle); +bool ble_drv_discover_services(bleio_device_obj_t *device, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb) { + BLE_DRIVER_LOG("Discover primary services. Conn handle: 0x" HEX2_FMT "\n", device->conn_handle); - mp_gattc_disc_service_observer = obj; + mp_gattc_disc_service_observer = device; disc_add_service_handler = cb; m_primary_service_found = false; uint32_t err_code; - err_code = sd_ble_gattc_primary_services_discover(conn_handle, - start_handle, - NULL); + err_code = sd_ble_gattc_primary_services_discover(device->conn_handle, start_handle, NULL); if (err_code != 0) { return false; } // busy loop until last service has been iterated while (disc_add_service_handler != NULL) { - ; +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif } - if (m_primary_service_found) { - return true; - } else { - return false; - } + return m_primary_service_found; } -bool ble_drv_discover_characteristic(mp_obj_t obj, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - ble_drv_disc_add_char_callback_t cb) { - BLE_DRIVER_LOG("Discover characteristicts. Conn handle: 0x" HEX2_FMT "\n", - conn_handle); +bool ble_drv_discover_characteristic(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle, ble_drv_disc_add_char_callback_t cb) { + BLE_DRIVER_LOG("Discover characteristicts. Conn handle: 0x" HEX2_FMT "\n", device->conn_handle); - mp_gattc_disc_char_observer = obj; + mp_gattc_disc_char_observer = service; disc_add_char_handler = cb; ble_gattc_handle_range_t handle_range; handle_range.start_handle = start_handle; - handle_range.end_handle = end_handle; + handle_range.end_handle = service->end_handle; m_characteristic_found = false; - uint32_t err_code; - err_code = sd_ble_gattc_characteristics_discover(conn_handle, &handle_range); + uint32_t err_code = sd_ble_gattc_characteristics_discover(device->conn_handle, &handle_range); if (err_code != 0) { return false; } // busy loop until last service has been iterated while (disc_add_char_handler != NULL) { - ; +#ifdef MICROPY_VM_HOOK_LOOP + MICROPY_VM_HOOK_LOOP +#endif } - if (m_characteristic_found) { - return true; - } else { - return false; - } + return m_characteristic_found; } void ble_drv_discover_descriptors(void) { @@ -908,12 +854,8 @@ void ble_drv_discover_descriptors(void) { } static void ble_evt_handler(ble_evt_t * p_ble_evt) { -// S132 event ranges. -// Common 0x01 -> 0x0F -// GAP 0x10 -> 0x2F -// GATTC 0x30 -> 0x4F -// GATTS 0x50 -> 0x6F -// L2CAP 0x70 -> 0x8F + 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"); @@ -1104,7 +1046,7 @@ static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (GATT_MTU_SIZE_DEFAULT)] __attr static uint8_t m_ble_evt_buf[sizeof(ble_evt_t) + (BLE_GATT_ATT_MTU_DEFAULT)] __attribute__ ((aligned (4))); #endif -void SWI2_EGU2_IRQHandler(void) { +void SD_EVT_IRQHandler(void) { uint32_t evt_id; uint32_t err_code; do { diff --git a/ports/nrf/drivers/bluetooth/ble_drv.h b/ports/nrf/drivers/bluetooth/ble_drv.h index 8c6bd6ce3..e5282db73 100644 --- a/ports/nrf/drivers/bluetooth/ble_drv.h +++ b/ports/nrf/drivers/bluetooth/ble_drv.h @@ -32,12 +32,12 @@ #include <stdint.h> #include <stdbool.h> +#include "shared-module/bleio/AdvertisementData.h" #include "shared-module/bleio/Characteristic.h" +#include "shared-module/bleio/Device.h" #include "shared-module/bleio/Scanner.h" #include "shared-module/bleio/Service.h" -#include "modubluepy.h" - typedef struct { uint8_t addr[6]; uint8_t addr_type; @@ -75,12 +75,12 @@ typedef struct { uint16_t value_handle; } ble_drv_char_data_t; -typedef void (*ble_drv_gap_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_gatts_evt_callback_t)(mp_obj_t self, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data); -typedef void (*ble_drv_gattc_evt_callback_t)(mp_obj_t self, 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 *self, ble_drv_adv_data_t *data); -typedef void (*ble_drv_disc_add_service_callback_t)(mp_obj_t self, ble_drv_service_data_t * p_service_data); -typedef void (*ble_drv_disc_add_char_callback_t)(mp_obj_t self, ble_drv_char_data_t * p_desc_data); +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_gattc_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, ble_drv_adv_data_t *data); +typedef void (*ble_drv_disc_add_service_callback_t)(bleio_device_obj_t *device, ble_drv_service_data_t * p_service_data); +typedef void (*ble_drv_disc_add_char_callback_t)(bleio_service_obj_t *service, ble_drv_char_data_t * p_desc_data); typedef void (*ble_drv_gattc_char_data_callback_t)(bleio_characteristic_obj_t *self, uint16_t length, uint8_t * p_data); uint32_t ble_drv_stack_enable(void); @@ -97,15 +97,15 @@ 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(ubluepy_advertise_data_t * p_adv_params); +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(mp_obj_t obs, ble_drv_gap_evt_callback_t evt_handler); +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(mp_obj_t obj, ble_drv_gatts_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_gattc_event_handler_set(mp_obj_t obj, ble_drv_gattc_evt_callback_t evt_handler); +void ble_drv_gattc_event_handler_set(bleio_device_obj_t *device, ble_drv_gattc_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); @@ -125,15 +125,13 @@ 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(uint8_t * p_addr, uint8_t addr_type); +void ble_drv_connect(bleio_device_obj_t *device); + +void ble_drv_disconnect(bleio_device_obj_t *device); -bool ble_drv_discover_services(mp_obj_t obj, uint16_t conn_handle, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb); +bool ble_drv_discover_services(bleio_device_obj_t *device, uint16_t start_handle, ble_drv_disc_add_service_callback_t cb); -bool ble_drv_discover_characteristic(mp_obj_t obj, - uint16_t conn_handle, - uint16_t start_handle, - uint16_t end_handle, - ble_drv_disc_add_char_callback_t cb); +bool ble_drv_discover_characteristic(bleio_device_obj_t *device, bleio_service_obj_t *service, uint16_t start_handle, ble_drv_disc_add_char_callback_t cb); void ble_drv_discover_descriptors(void); diff --git a/ports/nrf/drivers/bluetooth/ble_uart.h b/ports/nrf/drivers/bluetooth/ble_uart.h index e67176a26..336624cd3 100644 --- a/ports/nrf/drivers/bluetooth/ble_uart.h +++ b/ports/nrf/drivers/bluetooth/ble_uart.h @@ -29,7 +29,6 @@ #if BLUETOOTH_SD -#include "modubluepy.h" #include "ble_drv.h" void ble_uart_init0(void); diff --git a/ports/nrf/modules/ubluepy/modubluepy.h b/ports/nrf/modules/ubluepy/modubluepy.h deleted file mode 100644 index e301f0476..000000000 --- a/ports/nrf/modules/ubluepy/modubluepy.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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 UBLUEPY_H__ -#define UBLUEPY_H__ - -/* Examples: - -Advertisment: - -from ubluepy import Peripheral -p = Peripheral() -p.advertise(device_name="MicroPython") - -DB setup: - -from ubluepy import Service, Characteristic, UUID, Peripheral, constants -from pyb import LED - -def event_handler(id, handle, data): - print("BLE event:", id, "handle:", handle) - print(data) - - if id == constants.EVT_GAP_CONNECTED: - # connected - LED(2).on() - elif id == constants.EVT_GAP_DISCONNECTED: - # disconnect - LED(2).off() - elif id == 80: - print("id 80, data:", data) - -# u0 = UUID("0x180D") # HRM service -# u1 = UUID("0x2A37") # HRM measurement - -u0 = UUID("6e400001-b5a3-f393-e0a9-e50e24dcca9e") -u1 = UUID("6e400002-b5a3-f393-e0a9-e50e24dcca9e") -u2 = UUID("6e400003-b5a3-f393-e0a9-e50e24dcca9e") -s = Service(u0) -c0 = Characteristic(u1, props = Characteristic.PROP_WRITE | Characteristic.PROP_WRITE_WO_RESP) -c1 = Characteristic(u2, props = Characteristic.PROP_NOTIFY, attrs = Characteristic.ATTR_CCCD) -s.addCharacteristic(c0) -s.addCharacteristic(c1) -p = Peripheral() -p.addService(s) -p.setConnectionHandler(event_handler) -p.advertise(device_name="micr", services=[s]) - -*/ - -#include "common-hal/bleio/UUID.h" -#include "py/obj.h" - -extern const mp_obj_type_t ubluepy_peripheral_type; - -typedef enum { - UBLUEPY_ADDR_TYPE_PUBLIC = 0, - UBLUEPY_ADDR_TYPE_RANDOM_STATIC = 1, - UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE = 2, - UBLUEPY_ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE = 3, -} ubluepy_addr_type_t; - -typedef enum { - UBLUEPY_ROLE_PERIPHERAL, - UBLUEPY_ROLE_CENTRAL -} ubluepy_role_type_t; - -typedef struct _ubluepy_peripheral_obj_t { - mp_obj_base_t base; - ubluepy_role_type_t role; - volatile uint16_t conn_handle; - mp_obj_t delegate; - mp_obj_t notif_handler; - mp_obj_t conn_handler; - mp_obj_t service_list; -} ubluepy_peripheral_obj_t; - -typedef struct _ubluepy_advertise_data_t { - uint8_t * p_device_name; - uint8_t device_name_len; - mp_obj_t * p_services; - uint8_t num_of_services; - uint8_t * p_data; - uint8_t data_len; - bool connectable; -} ubluepy_advertise_data_t; - -typedef enum _ubluepy_prop_t { - UBLUEPY_PROP_BROADCAST = 0x01, - UBLUEPY_PROP_READ = 0x02, - UBLUEPY_PROP_WRITE_WO_RESP = 0x04, - UBLUEPY_PROP_WRITE = 0x08, - UBLUEPY_PROP_NOTIFY = 0x10, - UBLUEPY_PROP_INDICATE = 0x20, - UBLUEPY_PROP_AUTH_SIGNED_WR = 0x40, -} ubluepy_prop_t; - -typedef enum _ubluepy_attr_t { - UBLUEPY_ATTR_CCCD = 0x01, - UBLUEPY_ATTR_SCCD = 0x02, -} ubluepy_attr_t; - -#endif // UBLUEPY_H__ diff --git a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c b/ports/nrf/modules/ubluepy/ubluepy_peripheral.c deleted file mode 100644 index 3b1a0d279..000000000 --- a/ports/nrf/modules/ubluepy/ubluepy_peripheral.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * This file is part of the MicroPython project, http://micropython.org/ - * - * The MIT License (MIT) - * - * Copyright (c) 2017 Glenn Ruben Bakke - * - * 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 <string.h> -#include "py/obj.h" -#include "py/runtime.h" -#include "py/objstr.h" -#include "py/objlist.h" - -#if MICROPY_PY_UBLUEPY - -#include "ble_drv.h" -#include "common-hal/bleio/UUID.h" -#include "shared-bindings/bleio/Characteristic.h" -#include "shared-bindings/bleio/Service.h" -#include "shared-bindings/bleio/UUID.h" - -STATIC void ubluepy_peripheral_print(const mp_print_t *print, mp_obj_t o, mp_print_kind_t kind) { - ubluepy_peripheral_obj_t * self = (ubluepy_peripheral_obj_t *)o; - (void)self; - mp_printf(print, "Peripheral(conn_handle: " HEX2_FMT ")", - self->conn_handle); -} - -STATIC void gap_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t conn_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (event_id == 16) { // connect event - self->conn_handle = conn_handle; - } else if (event_id == 17) { // disconnect event - self->conn_handle = 0xFFFF; // invalid connection handle - } - - if (self->conn_handler != mp_const_none) { - mp_obj_t args[3]; - mp_uint_t num_of_args = 3; - args[0] = MP_OBJ_NEW_SMALL_INT(event_id); - args[1] = MP_OBJ_NEW_SMALL_INT(conn_handle); - if (data != NULL) { - args[2] = mp_obj_new_bytearray_by_ref(length, data); - } else { - args[2] = mp_const_none; - } - - // for now hard-code all events to conn_handler - mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); - } - - (void)self; -} - -STATIC void gatts_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - if (self->conn_handler != mp_const_none) { - mp_obj_t args[3]; - mp_uint_t num_of_args = 3; - args[0] = MP_OBJ_NEW_SMALL_INT(event_id); - args[1] = MP_OBJ_NEW_SMALL_INT(attr_handle); - if (data != NULL) { - args[2] = mp_obj_new_bytearray_by_ref(length, data); - } else { - args[2] = mp_const_none; - } - - // for now hard-code all events to conn_handler - mp_call_function_n_kw(self->conn_handler, num_of_args, 0, args); - } - -} - -#if MICROPY_PY_UBLUEPY_CENTRAL - -static volatile bool m_disc_evt_received; - -STATIC void gattc_event_handler(mp_obj_t self_in, uint16_t event_id, uint16_t attr_handle, uint16_t length, uint8_t * data) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - (void)self; - m_disc_evt_received = true; -} -#endif - -STATIC mp_obj_t ubluepy_peripheral_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *all_args) { - enum { - ARG_NEW_DEVICE_ADDR, - ARG_NEW_ADDR_TYPE - }; - - static const mp_arg_t allowed_args[] = { - { ARG_NEW_DEVICE_ADDR, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { ARG_NEW_ADDR_TYPE, MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all_kw_array(n_args, n_kw, all_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - ubluepy_peripheral_obj_t *s = m_new_obj(ubluepy_peripheral_obj_t); - s->base.type = type; - - s->delegate = mp_const_none; - s->conn_handler = mp_const_none; - s->notif_handler = mp_const_none; - s->conn_handle = 0xFFFF; - - s->service_list = mp_obj_new_list(0, NULL); - - return MP_OBJ_FROM_PTR(s); -} - -/// \method withDelegate(DefaultDelegate) -/// Set delegate instance for handling Bluetooth LE events. -/// -STATIC mp_obj_t peripheral_with_delegate(mp_obj_t self_in, mp_obj_t delegate) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->delegate = delegate; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_with_delegate_obj, peripheral_with_delegate); - -/// \method setNotificationHandler(func) -/// Set handler for Bluetooth LE notification events. -/// -STATIC mp_obj_t peripheral_set_notif_handler(mp_obj_t self_in, mp_obj_t func) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->notif_handler = func; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_notif_handler_obj, peripheral_set_notif_handler); - -/// \method setConnectionHandler(func) -/// Set handler for Bluetooth LE connection events. -/// -STATIC mp_obj_t peripheral_set_conn_handler(mp_obj_t self_in, mp_obj_t func) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - self->conn_handler = func; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_set_conn_handler_obj, peripheral_set_conn_handler); - -#if MICROPY_PY_UBLUEPY_PERIPHERAL - -/// \method advertise(device_name, [service=[service1, service2, ...]], [data=bytearray], [connectable=True]) -/// Start advertising. Connectable advertisement type by default. -/// -STATIC mp_obj_t peripheral_advertise(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - static const mp_arg_t allowed_args[] = { - { MP_QSTR_device_name, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_services, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_data, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_OBJ, {.u_obj = mp_const_none} }, - }; - - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - - self->role = UBLUEPY_ROLE_PERIPHERAL; - - // parse args - 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); - - // ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_obj_t device_name_obj = args[0].u_obj; - mp_obj_t service_obj = args[1].u_obj; - mp_obj_t data_obj = args[2].u_obj; - mp_obj_t connectable_obj = args[3].u_obj; - - ubluepy_advertise_data_t adv_data; - memset(&adv_data, 0, sizeof(ubluepy_advertise_data_t)); - - if (device_name_obj != mp_const_none && MP_OBJ_IS_STR(device_name_obj)) { - GET_STR_DATA_LEN(device_name_obj, str_data, str_len); - - adv_data.p_device_name = (uint8_t *)str_data; - adv_data.device_name_len = str_len; - } - - if (service_obj != mp_const_none) { - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(service_obj, &num_services, &services); - - if (num_services > 0) { - adv_data.p_services = services; - adv_data.num_of_services = num_services; - } - } - - if (data_obj != mp_const_none) { - mp_buffer_info_t bufinfo; - mp_get_buffer_raise(data_obj, &bufinfo, MP_BUFFER_READ); - - if (bufinfo.len > 0) { - adv_data.p_data = bufinfo.buf; - adv_data.data_len = bufinfo.len; - } - } - - adv_data.connectable = true; - if (connectable_obj != mp_const_none && !(mp_obj_is_true(connectable_obj))) { - adv_data.connectable = false; - } else { - ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); - ble_drv_gatts_event_handler_set(MP_OBJ_FROM_PTR(self), gatts_event_handler); - } - - (void)ble_drv_advertise_data(&adv_data); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_advertise_obj, 0, peripheral_advertise); - -/// \method advertise_stop() -/// Stop advertisement if any onging advertisement. -/// -STATIC mp_obj_t peripheral_advertise_stop(mp_obj_t self_in) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - ble_drv_advertise_stop(); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_advertise_stop_obj, peripheral_advertise_stop); - -#endif // MICROPY_PY_UBLUEPY_PERIPHERAL - -/// \method disconnect() -/// disconnect connection. -/// -STATIC mp_obj_t peripheral_disconnect(mp_obj_t self_in) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(self_in); - - (void)self; - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_disconnect_obj, peripheral_disconnect); - -/// \method addService(Service) -/// Add service to the Peripheral. -/// -STATIC mp_obj_t peripheral_add_service(mp_obj_t self_in, mp_obj_t service) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - bleio_service_obj_t * p_service = MP_OBJ_TO_PTR(service); - - p_service->periph = self_in; - - mp_obj_list_append(self->service_list, service); - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_2(ubluepy_peripheral_add_service_obj, peripheral_add_service); - -/// \method getServices() -/// Return list with all service registered in the Peripheral. -/// -STATIC mp_obj_t peripheral_get_services(mp_obj_t self_in) { - ubluepy_peripheral_obj_t * self = MP_OBJ_TO_PTR(self_in); - - return self->service_list; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_1(ubluepy_peripheral_get_services_obj, peripheral_get_services); - -#if MICROPY_PY_UBLUEPY_CENTRAL - -void static disc_add_service(mp_obj_t self, ble_drv_service_data_t * p_service_data) { - bleio_service_obj_t * p_service = m_new_obj(bleio_service_obj_t); - p_service->base.type = &bleio_service_type; - - bleio_uuid_obj_t * p_uuid = m_new_obj(bleio_uuid_obj_t); - p_uuid->base.type = &bleio_uuid_type; - - p_service->uuid = p_uuid; - - p_uuid->type = p_service_data->uuid_type; - p_uuid->value[0] = p_service_data->uuid & 0xFF; - p_uuid->value[1] = p_service_data->uuid >> 8; - - p_service->handle = p_service_data->start_handle; - p_service->start_handle = p_service_data->start_handle; - p_service->end_handle = p_service_data->end_handle; - - p_service->char_list = mp_obj_new_list(0, NULL); - - peripheral_add_service(self, MP_OBJ_FROM_PTR(p_service)); -} - -void static disc_add_char(mp_obj_t service_in, ble_drv_char_data_t * p_desc_data) { - bleio_service_obj_t * p_service = MP_OBJ_TO_PTR(service_in); - bleio_characteristic_obj_t * p_char = m_new_obj(bleio_characteristic_obj_t); - p_char->base.type = &bleio_characteristic_type; - - bleio_uuid_obj_t * p_uuid = m_new_obj(bleio_uuid_obj_t); - p_uuid->base.type = &bleio_uuid_type; - - p_char->uuid = p_uuid; - - p_uuid->type = p_desc_data->uuid_type; - p_uuid->value[0] = p_desc_data->uuid & 0xFF; - p_uuid->value[1] = p_desc_data->uuid >> 8; - - // add characteristic specific data from discovery - p_char->props.broadcast = p_desc_data->props.broadcast; - p_char->props.indicate = p_desc_data->props.indicate; - p_char->props.notify = p_desc_data->props.notify; - p_char->props.read = p_desc_data->props.read; - p_char->props.write = p_desc_data->props.write; - p_char->props.write_wo_resp = p_desc_data->props.write_wo_resp; - p_char->handle = p_desc_data->value_handle; - - // equivalent to ubluepy_service.c - service_add_characteristic() - // except the registration of the characteristic towards the bluetooth stack - p_char->service_handle = p_service->handle; - p_char->service = p_service; - - mp_obj_list_append(p_service->char_list, MP_OBJ_FROM_PTR(p_char)); -} - -/// \method connect(device_address [, addr_type=ADDR_TYPE_PUBLIC]) -/// Connect to device peripheral with the given device address. -/// addr_type can be either ADDR_TYPE_PUBLIC (default) or -/// ADDR_TYPE_RANDOM_STATIC. -/// -STATIC mp_obj_t peripheral_connect(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { - ubluepy_peripheral_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); - mp_obj_t dev_addr = pos_args[1]; - - self->role = UBLUEPY_ROLE_CENTRAL; - - static const mp_arg_t allowed_args[] = { - { MP_QSTR_addr_type, MP_ARG_KW_ONLY | MP_ARG_INT, {.u_int = UBLUEPY_ADDR_TYPE_PUBLIC } }, - }; - - // parse args - mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; - mp_arg_parse_all(n_args - 2, pos_args + 2, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); - - uint8_t addr_type = args[0].u_int; - - ble_drv_gap_event_handler_set(MP_OBJ_FROM_PTR(self), gap_event_handler); - - if (MP_OBJ_IS_STR(dev_addr)) { - GET_STR_DATA_LEN(dev_addr, str_data, str_len); - if (str_len == 17) { // Example "11:22:33:aa:bb:cc" - - uint8_t * p_addr = m_new(uint8_t, 6); - - p_addr[0] = unichar_xdigit_value(str_data[16]); - p_addr[0] += unichar_xdigit_value(str_data[15]) << 4; - p_addr[1] = unichar_xdigit_value(str_data[13]); - p_addr[1] += unichar_xdigit_value(str_data[12]) << 4; - p_addr[2] = unichar_xdigit_value(str_data[10]); - p_addr[2] += unichar_xdigit_value(str_data[9]) << 4; - p_addr[3] = unichar_xdigit_value(str_data[7]); - p_addr[3] += unichar_xdigit_value(str_data[6]) << 4; - p_addr[4] = unichar_xdigit_value(str_data[4]); - p_addr[4] += unichar_xdigit_value(str_data[3]) << 4; - p_addr[5] = unichar_xdigit_value(str_data[1]); - p_addr[5] += unichar_xdigit_value(str_data[0]) << 4; - - ble_drv_connect(p_addr, addr_type); - - m_del(uint8_t, p_addr, 6); - } - } - - // block until connected - while (self->conn_handle == 0xFFFF) { - ; - } - - ble_drv_gattc_event_handler_set(MP_OBJ_FROM_PTR(self), gattc_event_handler); - - bool service_disc_retval = ble_drv_discover_services(self, self->conn_handle, 0x0001, disc_add_service); - - // continue discovery of primary services ... - while (service_disc_retval) { - // locate the last added service - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(self->service_list, &num_services, &services); - - bleio_service_obj_t * p_service = (bleio_service_obj_t *)services[num_services - 1]; - - service_disc_retval = ble_drv_discover_services(self, - self->conn_handle, - p_service->end_handle + 1, - disc_add_service); - } - - // For each service perform a characteristic discovery - mp_obj_t * services = NULL; - mp_uint_t num_services; - mp_obj_get_array(self->service_list, &num_services, &services); - - for (uint16_t s = 0; s < num_services; s++) { - bleio_service_obj_t * p_service = (bleio_service_obj_t *)services[s]; - bool char_disc_retval = ble_drv_discover_characteristic(p_service, - self->conn_handle, - p_service->start_handle, - p_service->end_handle, - disc_add_char); - // continue discovery of characteristics ... - while (char_disc_retval) { - mp_obj_t * characteristics = NULL; - mp_uint_t num_chars; - mp_obj_get_array(p_service->char_list, &num_chars, &characteristics); - - bleio_characteristic_obj_t * p_char = (bleio_characteristic_obj_t *)characteristics[num_chars - 1]; - uint16_t next_handle = p_char->handle + 1; - if ((next_handle) < p_service->end_handle) { - char_disc_retval = ble_drv_discover_characteristic(p_service, - self->conn_handle, - next_handle, - p_service->end_handle, - disc_add_char); - } else { - break; - } - } - } - - return mp_const_none; -} -STATIC MP_DEFINE_CONST_FUN_OBJ_KW(ubluepy_peripheral_connect_obj, 2, peripheral_connect); - -#endif - -STATIC const mp_rom_map_elem_t ubluepy_peripheral_locals_dict_table[] = { - { MP_ROM_QSTR(MP_QSTR_withDelegate), MP_ROM_PTR(&ubluepy_peripheral_with_delegate_obj) }, - { MP_ROM_QSTR(MP_QSTR_setNotificationHandler), MP_ROM_PTR(&ubluepy_peripheral_set_notif_handler_obj) }, - { MP_ROM_QSTR(MP_QSTR_setConnectionHandler), MP_ROM_PTR(&ubluepy_peripheral_set_conn_handler_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServices), MP_ROM_PTR(&ubluepy_peripheral_get_services_obj) }, -#if MICROPY_PY_UBLUEPY_CENTRAL - { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&ubluepy_peripheral_connect_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_getServiceByUUID), MP_ROM_PTR(&ubluepy_peripheral_get_service_by_uuid_obj) }, - { MP_ROM_QSTR(MP_QSTR_getCharacteristics), MP_ROM_PTR(&ubluepy_peripheral_get_chars_obj) }, - { MP_ROM_QSTR(MP_QSTR_getDescriptors), MP_ROM_PTR(&ubluepy_peripheral_get_descs_obj) }, - { MP_ROM_QSTR(MP_QSTR_waitForNotifications), MP_ROM_PTR(&ubluepy_peripheral_wait_for_notif_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, -#endif // 0 -#endif // MICROPY_PY_UBLUEPY_CENTRAL -#if MICROPY_PY_UBLUEPY_PERIPHERAL - { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, - { MP_ROM_QSTR(MP_QSTR_advertise_stop), MP_ROM_PTR(&ubluepy_peripheral_advertise_stop_obj) }, - { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&ubluepy_peripheral_disconnect_obj) }, - { MP_ROM_QSTR(MP_QSTR_addService), MP_ROM_PTR(&ubluepy_peripheral_add_service_obj) }, -#if 0 - { MP_ROM_QSTR(MP_QSTR_addCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_add_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_addDescriptor), MP_ROM_PTR(&ubluepy_peripheral_add_desc_obj) }, - { MP_ROM_QSTR(MP_QSTR_writeCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_write_char_obj) }, - { MP_ROM_QSTR(MP_QSTR_readCharacteristic), MP_ROM_PTR(&ubluepy_peripheral_read_char_obj) }, -#endif -#endif -#if MICROPY_PY_UBLUEPY_BROADCASTER - { MP_ROM_QSTR(MP_QSTR_advertise), MP_ROM_PTR(&ubluepy_peripheral_advertise_obj) }, -#endif -#if MICROPY_PY_UBLUEPY_OBSERVER - // Nothing yet. -#endif -}; - -STATIC MP_DEFINE_CONST_DICT(ubluepy_peripheral_locals_dict, ubluepy_peripheral_locals_dict_table); - -const mp_obj_type_t ubluepy_peripheral_type = { - { &mp_type_type }, - .name = MP_QSTR_Peripheral, - .print = ubluepy_peripheral_print, - .make_new = ubluepy_peripheral_make_new, - .locals_dict = (mp_obj_dict_t*)&ubluepy_peripheral_locals_dict -}; - -#endif // MICROPY_PY_UBLUEPY diff --git a/ports/nrf/mpconfigport.h b/ports/nrf/mpconfigport.h index b710808b9..62a041ae9 100644 --- a/ports/nrf/mpconfigport.h +++ b/ports/nrf/mpconfigport.h @@ -129,21 +129,15 @@ #define CIRCUITPY_GAMEPAD_TICKS 0x1f #if BLUETOOTH_SD -#define MICROPY_PY_BLEIO (1) -#define MICROPY_PY_BLE_NUS (0) -#define MICROPY_PY_UBLUEPY (1) -#define MICROPY_PY_UBLUEPY_PERIPHERAL (1) -#define MICROPY_PY_UBLUEPY_CENTRAL (1) -#define BLUETOOTH_WEBBLUETOOTH_REPL (0) -#endif - -#ifndef MICROPY_PY_BLEIO -#define MICROPY_PY_BLEIO (0) + #define MICROPY_PY_BLEIO (1) + #define MICROPY_PY_BLE_NUS (0) + #define BLUETOOTH_WEBBLUETOOTH_REPL (0) +#else + #ifndef MICROPY_PY_BLEIO + #define MICROPY_PY_BLEIO (0) + #endif #endif -#ifndef MICROPY_PY_UBLUEPY -#define MICROPY_PY_UBLUEPY (0) -#endif // type definitions for the specific machine @@ -184,16 +178,8 @@ extern const struct _mp_obj_module_t neopixel_write_module; extern const struct _mp_obj_module_t usb_hid_module; extern const struct _mp_obj_module_t bleio_module; -extern const struct _mp_obj_module_t mp_module_ubluepy; - -#if MICROPY_PY_UBLUEPY -#define UBLUEPY_MODULE { MP_ROM_QSTR(MP_QSTR_ubluepy), MP_ROM_PTR(&mp_module_ubluepy) }, -#else -#define UBLUEPY_MODULE -#endif - #if MICROPY_PY_BLEIO -#define BLEIO_MODULE { MP_ROM_QSTR(MP_QSTR_bleio), MP_ROM_PTR(&bleio_module) }, +#define BLEIO_MODULE { MP_ROM_QSTR(MP_QSTR_bleio), MP_ROM_PTR(&bleio_module) }, #else #define BLEIO_MODULE #endif @@ -221,8 +207,7 @@ extern const struct _mp_obj_module_t mp_module_ubluepy; { MP_OBJ_NEW_QSTR (MP_QSTR_gamepad ), (mp_obj_t)&gamepad_module }, \ { MP_OBJ_NEW_QSTR (MP_QSTR_time ), (mp_obj_t)&time_module }, \ USBHID_MODULE \ - BLEIO_MODULE \ - UBLUEPY_MODULE \ + BLEIO_MODULE // extra built in names to add to the global namespace #define MICROPY_PORT_BUILTINS \ diff --git a/shared-bindings/bleio/Device.c b/shared-bindings/bleio/Device.c new file mode 100644 index 000000000..15ebd51ed --- /dev/null +++ b/shared-bindings/bleio/Device.c @@ -0,0 +1,348 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * 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 + * 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 <string.h> +#include <stdio.h> + +#include "ble_drv.h" +#include "py/objarray.h" +#include "py/objproperty.h" +#include "py/objstr.h" +#include "py/runtime.h" +#include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/AddressType.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" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" + +//| .. currentmodule:: bleio +//| +//| :class:`Device` -- BLE device +//| ========================================================= +//| +//| Provides access a to BLE device, either in a Peripheral or Central role. +//| When a device is created without any parameter passed to the constructor, +//| it will be set to the Peripheral role. If a address is passed, the device +//| will be a Central. For a Peripheral you can set the `name`, add services +//| via `add_service` and then start and stop advertising via `start_advertising` +//| and `stop_advertising`. For the Central, you can `bleio.Device.connect` and `bleio.Device.disconnect` +//| to the device, once a connection is established, the device's services can +//| be accessed using `services`. +//| +//| Usage:: +//| +//| import bleio +//| +//| # Peripheral +//| periph = bleio.Device() +//| +//| serv = bleio.Service(bleio.UUID(0x180f)) +//| p.add_service(serv) +//| +//| chara = bleio.Characteristic(bleio.UUID(0x2919)) +//| chara.read = True +//| chara.notify = True +//| serv.add_characteristic(chara) +//| +//| periph.start_advertising() +//| +//| # Central +//| scanner = bleio.Scanner() +//| entries = scanner.scan(2500) +//| +//| my_entry = None +//| for entry in entries: +//| if entry.name is not None and entry.name == 'MyDevice': +//| my_entry = entry +//| break +//| +//| central = bleio.Device(my_entry.address) +//| central.connect() +//| + +//| .. class:: Device(address=None) +//| +//| Create a new Device object. If the `address` parameter is not `None`, +//| the role is set to Central, otherwise it's set to Peripheral. +//| +//| :param bleio.Address address: The address of the device to connect to +//| + +//| .. attribute:: name +//| +//| For the Peripheral role, this property can be used to read and write the device's name. +//| For the Central role, this property will equal the name of the remote device, if one was +//| advertised by the device. In the Central role this property is read-only. +//| + +//| .. attribute:: services +//| +//| A `list` of `bleio.Service` that are offered by this device. (read-only) +//| For a Peripheral device, this list will contain services added using `add_service`, +//| for a Central, this list will be empty until a connection is established, at which point +//| it will be filled with the remote device's services. +//| + +//| .. method:: add_service(service) +//| +//| Appends the :py:data:`service` to the list of this devices's services. +//| This method can only be called for Peripheral devices. +//| +//| :param bleio.Service service: the service to append +//| + +//| .. method:: connect() +//| +//| Attempts a connection to the remote device. If the connection is successful, +//| the device's services are available via `services`. +//| This method can only be called for Central devices. +//| + +//| .. method:: disconnect() +//| +//| Disconnects from the remote device. +//| This method can only be called for Central devices. +//| + +//| .. method:: start_advertising(connectable=True) +//| +//| Starts advertising the device. The device's name and +//| services are put into the advertisement packets. +//| If :py:data:`connectable` is `True` then other devices are allowed to conncet to this device. +//| This method can only be called for Peripheral devices. +//| + +//| .. method:: stop_advertising() +//| +//| Disconnects from the remote device. +//| This method can only be called for Peripheral devices. +//| +static const char default_name[] = "CIRCUITPY"; + +STATIC void bleio_device_print(const mp_print_t *print, mp_obj_t self_in, mp_print_kind_t kind) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + mp_printf(print, "Device(role: %s)", self->is_peripheral ? "Peripheral" : "Central"); +} + +STATIC mp_obj_t bleio_device_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *pos_args) { + mp_arg_check_num(n_args, n_kw, 0, 1, true); + bleio_device_obj_t *self = m_new_obj(bleio_device_obj_t); + self->base.type = &bleio_device_type; + self->service_list = mp_obj_new_list(0, NULL); + self->notif_handler = mp_const_none; + self->conn_handler = mp_const_none; + self->conn_handle = 0xFFFF; + self->is_peripheral = true; + + mp_map_t kw_args; + mp_map_init_fixed_table(&kw_args, n_kw, pos_args + n_args); + + //TODO: Add ScanEntry + enum { ARG_address }; + static const mp_arg_t allowed_args[] = { + { ARG_address, MP_ARG_OBJ, {.u_obj = mp_const_none} }, + }; + + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, &kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + + const mp_obj_t address_obj = args[ARG_address].u_obj; + + if (address_obj != mp_const_none) { + bleio_address_obj_t *address = MP_OBJ_TO_PTR(address_obj); + + self->is_peripheral = false; + self->address.type = address->type; + memcpy(self->address.value, address->value, BLEIO_ADDRESS_BYTES); + } else { + self->name = mp_obj_new_str(default_name, strlen(default_name), false); + common_hal_bleio_adapter_get_address(&self->address); + } + + return MP_OBJ_FROM_PTR(self); +} + +STATIC mp_obj_t bleio_device_add_service(mp_obj_t self_in, mp_obj_t service_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Can't add services in Central mode")); + } + + service->device = self_in; + + mp_obj_list_append(self->service_list, service); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_add_service_obj, bleio_device_add_service); + +STATIC mp_obj_t bleio_device_connect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Can't connect in Peripheral mode")); + } + + common_hal_bleio_device_connect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_connect_obj, bleio_device_connect); + +STATIC mp_obj_t bleio_device_disconnect(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + common_hal_bleio_device_disconnect(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_disconnect_obj, bleio_device_disconnect); + +STATIC mp_obj_t bleio_device_get_name(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->name; +} +MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_name_obj, bleio_device_get_name); + +static mp_obj_t bleio_device_set_name(mp_obj_t self_in, mp_obj_t value) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Can't change the name in Central mode")); + } + + self->name = value; + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(bleio_device_set_name_obj, bleio_device_set_name); + +const mp_obj_property_t bleio_device_name_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_name_obj, + (mp_obj_t)&bleio_device_set_name_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC mp_obj_t bleio_device_start_advertising(mp_uint_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(pos_args[0]); + + if (!self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Can't advertise in Central mode")); + } + + enum { ARG_connectable }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_connectable, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = true} }, + }; + + 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); + + // TODO: data + bleio_advertisement_data_t adv_data = { + .device_name = self->name, + .services = mp_obj_new_list(0, NULL), + .data = mp_obj_new_bytearray(0, NULL), + .connectable = args[ARG_connectable].u_bool + }; + + mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list); + for (size_t i = 0; i < service_list->len; ++i) { + bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[i]); + if (!service->is_secondary) { + mp_obj_list_append(adv_data.services, service_list->items[i]); + } + } + + common_hal_bleio_device_start_advertising(self, &adv_data); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_KW(bleio_device_start_advertising_obj, 0, bleio_device_start_advertising); + +STATIC mp_obj_t bleio_device_stop_advertising(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + if (self->is_peripheral) { + nlr_raise(mp_obj_new_exception_msg_varg(&mp_type_ValueError, + "Can't advertise in Central mode")); + } + + common_hal_bleio_device_stop_advertising(self); + + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_stop_advertising_obj, bleio_device_stop_advertising); + +STATIC mp_obj_t bleio_device_get_services(mp_obj_t self_in) { + bleio_device_obj_t *self = MP_OBJ_TO_PTR(self_in); + + return self->service_list; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(bleio_device_get_services_obj, bleio_device_get_services); + +const mp_obj_property_t bleio_device_services_obj = { + .base.type = &mp_type_property, + .proxy = { (mp_obj_t)&bleio_device_get_services_obj, + (mp_obj_t)&mp_const_none_obj, + (mp_obj_t)&mp_const_none_obj }, +}; + +STATIC const mp_rom_map_elem_t bleio_device_locals_dict_table[] = { + // Methods + { MP_ROM_QSTR(MP_QSTR_add_service), MP_ROM_PTR(&bleio_device_add_service_obj) }, + { MP_ROM_QSTR(MP_QSTR_connect), MP_ROM_PTR(&bleio_device_connect_obj) }, + { MP_ROM_QSTR(MP_QSTR_disconnect), MP_ROM_PTR(&bleio_device_disconnect_obj) }, + { MP_ROM_QSTR(MP_QSTR_start_advertising), MP_ROM_PTR(&bleio_device_start_advertising_obj) }, + { MP_ROM_QSTR(MP_QSTR_stop_advertising), MP_ROM_PTR(&bleio_device_stop_advertising_obj) }, + + // Properties + { MP_ROM_QSTR(MP_QSTR_name), MP_ROM_PTR(&bleio_device_name_obj) }, + { MP_ROM_QSTR(MP_QSTR_services), MP_ROM_PTR(&bleio_device_services_obj) }, +}; + +STATIC MP_DEFINE_CONST_DICT(bleio_device_locals_dict, bleio_device_locals_dict_table); + +const mp_obj_type_t bleio_device_type = { + { &mp_type_type }, + .name = MP_QSTR_Device, + .print = bleio_device_print, + .make_new = bleio_device_make_new, + .locals_dict = (mp_obj_dict_t*)&bleio_device_locals_dict +}; diff --git a/ports/nrf/modules/ubluepy/modubluepy.c b/shared-bindings/bleio/Device.h index f8266a82d..d099e5c43 100644 --- a/ports/nrf/modules/ubluepy/modubluepy.c +++ b/shared-bindings/bleio/Device.h @@ -3,7 +3,7 @@ * * The MIT License (MIT) * - * Copyright (c) 2017 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 @@ -24,25 +24,17 @@ * THE SOFTWARE. */ -#include "py/obj.h" +#ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H +#define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H -#if MICROPY_PY_UBLUEPY +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/Device.h" -extern const mp_obj_type_t ubluepy_peripheral_type; -extern const mp_obj_type_t ubluepy_service_type; +extern const mp_obj_type_t bleio_device_type; -STATIC const mp_rom_map_elem_t mp_module_ubluepy_globals_table[] = { - { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluepy) }, -#if MICROPY_PY_UBLUEPY_PERIPHERAL - { MP_ROM_QSTR(MP_QSTR_Peripheral), MP_ROM_PTR(&ubluepy_peripheral_type) }, -#endif -}; +extern void common_hal_bleio_device_start_advertising(bleio_device_obj_t *device, bleio_advertisement_data_t *adv_data); +extern void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device); +extern void common_hal_bleio_device_connect(bleio_device_obj_t *device); +extern void common_hal_bleio_device_disconnect(bleio_device_obj_t *device); -STATIC MP_DEFINE_CONST_DICT(mp_module_ubluepy_globals, mp_module_ubluepy_globals_table); - -const mp_obj_module_t mp_module_ubluepy = { - .base = { &mp_type_module }, - .globals = (mp_obj_dict_t*)&mp_module_ubluepy_globals, -}; - -#endif // MICROPY_PY_UBLUEPY +#endif // MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_DEVICE_H diff --git a/shared-bindings/bleio/ScanEntry.c b/shared-bindings/bleio/ScanEntry.c index e38a08909..2eed24cd8 100644 --- a/shared-bindings/bleio/ScanEntry.c +++ b/shared-bindings/bleio/ScanEntry.c @@ -32,9 +32,10 @@ #include "py/objstr.h" #include "py/objtuple.h" #include "shared-bindings/bleio/Address.h" -#include "shared-module/bleio/AdvertisementData.h" -#include "shared-bindings/bleio/UUID.h" #include "shared-bindings/bleio/ScanEntry.h" +#include "shared-bindings/bleio/UUID.h" +#include "shared-module/bleio/AdvertisementData.h" +#include "shared-module/bleio/ScanEntry.h" //| .. currentmodule:: bleio //| diff --git a/shared-bindings/bleio/ScanEntry.h b/shared-bindings/bleio/ScanEntry.h index 4a201124e..2b44ba3f4 100644 --- a/shared-bindings/bleio/ScanEntry.h +++ b/shared-bindings/bleio/ScanEntry.h @@ -28,16 +28,7 @@ #ifndef MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H #define MICROPY_INCLUDED_SHARED_BINDINGS_BLEIO_SCANENTRY_H -#include "shared-module/bleio/Address.h" -#include "py/objtype.h" - -typedef struct { - mp_obj_base_t base; - bleio_address_obj_t address; - bool connectable; - int8_t rssi; - mp_obj_t data; -} bleio_scanentry_obj_t; +#include "py/obj.h" extern const mp_obj_type_t bleio_scanentry_type; diff --git a/shared-bindings/bleio/Service.c b/shared-bindings/bleio/Service.c index 6451991e9..5b61a2966 100644 --- a/shared-bindings/bleio/Service.c +++ b/shared-bindings/bleio/Service.c @@ -73,7 +73,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, mp_arg_check_num(n_args, n_kw, 1, 1, true); bleio_service_obj_t *self = m_new_obj(bleio_service_obj_t); self->base.type = &bleio_service_type; - self->periph = mp_const_none; + self->device = mp_const_none; self->char_list = mp_obj_new_list(0, NULL); mp_map_t kw_args; @@ -81,7 +81,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, enum { ARG_uuid, ARG_secondary }; static const mp_arg_t allowed_args[] = { - { ARG_uuid, MP_ARG_OBJ, {.u_obj = MP_OBJ_NULL} }, + { ARG_uuid, MP_ARG_OBJ, {.u_obj = mp_const_none} }, { MP_QSTR_secondary, MP_ARG_KW_ONLY | MP_ARG_BOOL, {.u_bool = false} }, }; @@ -92,7 +92,7 @@ STATIC mp_obj_t bleio_service_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t uuid = args[ARG_uuid].u_obj; - if (uuid == MP_OBJ_NULL) { + if (uuid == mp_const_none) { return MP_OBJ_FROM_PTR(self); } diff --git a/shared-bindings/bleio/__init__.c b/shared-bindings/bleio/__init__.c index 9f5a8f8f2..98099422c 100644 --- a/shared-bindings/bleio/__init__.c +++ b/shared-bindings/bleio/__init__.c @@ -31,6 +31,7 @@ #include "shared-bindings/bleio/AdvertisementData.h" #include "shared-bindings/bleio/Characteristic.h" #include "shared-bindings/bleio/Descriptor.h" +#include "shared-bindings/bleio/Device.h" #include "shared-bindings/bleio/ScanEntry.h" #include "shared-bindings/bleio/Scanner.h" #include "shared-bindings/bleio/Service.h" @@ -57,6 +58,7 @@ //| Adapter //| Characteristic //| Descriptor +//| Device //| ScanEntry //| Scanner //| Service @@ -76,6 +78,7 @@ STATIC const mp_rom_map_elem_t bleio_module_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_AdvertisementData), MP_ROM_PTR(&bleio_advertisementdata_type) }, { MP_ROM_QSTR(MP_QSTR_Characteristic), MP_ROM_PTR(&bleio_characteristic_type) }, { MP_ROM_QSTR(MP_QSTR_Descriptor), MP_ROM_PTR(&bleio_descriptor_type) }, + { MP_ROM_QSTR(MP_QSTR_Device), MP_ROM_PTR(&bleio_device_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) }, diff --git a/shared-module/bleio/AdvertisementData.h b/shared-module/bleio/AdvertisementData.h index 2a9addf57..738d53b23 100644 --- a/shared-module/bleio/AdvertisementData.h +++ b/shared-module/bleio/AdvertisementData.h @@ -27,6 +27,8 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H +#include "py/obj.h" + // Taken from https://www.bluetooth.com/specifications/assigned-numbers/generic-access-profile enum { AdFlags = 0x01, @@ -73,4 +75,11 @@ enum { AdManufacturerSpecificData = 0xFF, }; +typedef struct { + mp_obj_t device_name; + mp_obj_t services; + mp_obj_t data; + bool connectable; +} bleio_advertisement_data_t; + #endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_ADVERTISEMENTDATA_H diff --git a/shared-module/bleio/Device.h b/shared-module/bleio/Device.h new file mode 100644 index 000000000..afbd8f063 --- /dev/null +++ b/shared-module/bleio/Device.h @@ -0,0 +1,45 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H + +#include <stdbool.h> + +#include "shared-module/bleio/Address.h" + +typedef struct { + mp_obj_base_t base; + bool is_peripheral; + mp_obj_t name; + bleio_address_obj_t address; + uint16_t conn_handle; + mp_obj_t service_list; + mp_obj_t notif_handler; + mp_obj_t conn_handler; +} bleio_device_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_DEVICE_H diff --git a/shared-module/bleio/ScanEntry.h b/shared-module/bleio/ScanEntry.h new file mode 100644 index 000000000..2f01669e2 --- /dev/null +++ b/shared-module/bleio/ScanEntry.h @@ -0,0 +1,40 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2018 Artur Pacholec + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H +#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H + +#include "shared-module/bleio/Address.h" + +typedef struct { + mp_obj_base_t base; + bleio_address_obj_t address; + bool connectable; + int8_t rssi; + mp_obj_t data; +} bleio_scanentry_obj_t; + +#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SCANENTRY_H diff --git a/shared-module/bleio/Service.h b/shared-module/bleio/Service.h index bd359a41d..1e3f09119 100644 --- a/shared-module/bleio/Service.h +++ b/shared-module/bleio/Service.h @@ -27,7 +27,6 @@ #ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H #define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_SERVICE_H -#include "modubluepy.h" #include "common-hal/bleio/UUID.h" typedef struct { @@ -35,7 +34,7 @@ typedef struct { uint16_t handle; bool is_secondary; bleio_uuid_obj_t *uuid; - mp_obj_t periph; + mp_obj_t device; mp_obj_t char_list; uint16_t start_handle; uint16_t end_handle; |
