summaryrefslogtreecommitdiff
path: root/ports/nrf/common-hal
diff options
context:
space:
mode:
authorScott Shawcroft <scott@adafruit.com>2019-07-18 10:08:58 -0700
committerGitHub <noreply@github.com>2019-07-18 10:08:58 -0700
commit74be29cbf923fc2a40c103ab722e996045b72827 (patch)
tree30e6f405cd6da1fc0067ca304c2b0ebd4460e9fe /ports/nrf/common-hal
parentd12e1a8d74ebb8d5d32ab0de47d3097e80c5d4fd (diff)
parent1c31cf5f6a6d9cff6f086114f6e0a03b5247c623 (diff)
Merge pull request #1993 from dhalbert/ble-scanner5.0.0-alpha.0
bleio: add central and scanner functionality, cleanup bleio API, some code restructure
Diffstat (limited to 'ports/nrf/common-hal')
-rw-r--r--ports/nrf/common-hal/analogio/AnalogIn.c2
-rw-r--r--ports/nrf/common-hal/bleio/Adapter.c11
-rw-r--r--ports/nrf/common-hal/bleio/Adapter.h3
-rw-r--r--ports/nrf/common-hal/bleio/Broadcaster.c98
-rw-r--r--ports/nrf/common-hal/bleio/Central.c463
-rw-r--r--ports/nrf/common-hal/bleio/Central.h (renamed from ports/nrf/common-hal/bleio/Broadcaster.h)24
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.c228
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.h14
-rw-r--r--ports/nrf/common-hal/bleio/CharacteristicBuffer.c45
-rw-r--r--ports/nrf/common-hal/bleio/CharacteristicBuffer.h8
-rw-r--r--ports/nrf/common-hal/bleio/Descriptor.c8
-rw-r--r--ports/nrf/common-hal/bleio/Descriptor.h5
-rw-r--r--ports/nrf/common-hal/bleio/Device.c601
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.c359
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.h23
-rw-r--r--ports/nrf/common-hal/bleio/Scanner.c57
-rw-r--r--ports/nrf/common-hal/bleio/Scanner.h40
-rw-r--r--ports/nrf/common-hal/bleio/Service.c34
-rw-r--r--ports/nrf/common-hal/bleio/Service.h48
-rw-r--r--ports/nrf/common-hal/bleio/UUID.c3
-rw-r--r--ports/nrf/common-hal/bleio/UUID.h3
-rw-r--r--ports/nrf/common-hal/bleio/__init__.c14
-rw-r--r--ports/nrf/common-hal/bleio/__init__.h6
-rw-r--r--ports/nrf/common-hal/busio/I2C.c5
-rw-r--r--ports/nrf/common-hal/busio/SPI.c8
25 files changed, 978 insertions, 1132 deletions
diff --git a/ports/nrf/common-hal/analogio/AnalogIn.c b/ports/nrf/common-hal/analogio/AnalogIn.c
index 1e572f7cb..f20802ac9 100644
--- a/ports/nrf/common-hal/analogio/AnalogIn.c
+++ b/ports/nrf/common-hal/analogio/AnalogIn.c
@@ -3,8 +3,8 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2016 Scott Shawcroft for Adafruit Industries
- * Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/common-hal/bleio/Adapter.c b/ports/nrf/common-hal/bleio/Adapter.c
index 540659aa1..9d0912930 100644
--- a/ports/nrf/common-hal/bleio/Adapter.c
+++ b/ports/nrf/common-hal/bleio/Adapter.c
@@ -3,6 +3,7 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2016 Glenn Ruben Bakke
* Copyright (c) 2018 Artur Pacholec
*
@@ -136,17 +137,15 @@ void common_hal_bleio_adapter_get_address(bleio_address_obj_t *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) {
mp_raise_OSError_msg(translate("Failed to get local address"));
}
address->type = local_address.addr_type;
- memcpy(address->value, local_address.addr, BLEIO_ADDRESS_BYTES);
+
+ mp_buffer_info_t buf_info;
+ mp_get_buffer_raise(address, &buf_info, MP_BUFFER_READ);
+ memcpy(address->bytes, buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
}
diff --git a/ports/nrf/common-hal/bleio/Adapter.h b/ports/nrf/common-hal/bleio/Adapter.h
index 0497f9ac9..5dcc62540 100644
--- a/ports/nrf/common-hal/bleio/Adapter.h
+++ b/ports/nrf/common-hal/bleio/Adapter.h
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
diff --git a/ports/nrf/common-hal/bleio/Broadcaster.c b/ports/nrf/common-hal/bleio/Broadcaster.c
deleted file mode 100644
index a70209a7f..000000000
--- a/ports/nrf/common-hal/bleio/Broadcaster.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * This file is part of the MicroPython project, http://micropython.org/
- *
- * The MIT License (MIT)
- *
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-
-#include <string.h>
-
-#include "ble.h"
-#include "ble_drv.h"
-#include "ble_hci.h"
-#include "nrf_soc.h"
-#include "py/runtime.h"
-
-#include "common-hal/bleio/Broadcaster.h"
-#include "shared-bindings/bleio/Adapter.h"
-#include "shared-bindings/bleio/Broadcaster.h"
-
-static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
-
-void common_hal_bleio_broadcaster_construct(bleio_broadcaster_obj_t *self, mp_float_t interval) {
- common_hal_bleio_adapter_set_enabled(true); // TODO -- Do this somewhere else maybe bleio __init__
- const mp_float_t min = BLE_GAP_ADV_INTERVAL_MIN * ADV_INTERVAL_UNIT_FLOAT_SECS;
- const mp_float_t max = BLE_GAP_ADV_INTERVAL_MAX * ADV_INTERVAL_UNIT_FLOAT_SECS;
-
- if (interval < min || interval > max) {
- // Would like to print range using the constants above, but vargs would convert to double.
- mp_raise_ValueError(translate("interval not in range 0.0020 to 10.24"));
- }
- self->interval = interval;
-}
-
-
-void common_hal_bleio_broadcaster_start_advertising(bleio_broadcaster_obj_t *self, mp_buffer_info_t *data) {
- uint32_t err_code;
-
- if (data->len >= BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
- mp_raise_ValueError(translate("Data too large for advertisement packet"));
- }
- memcpy(self->adv_data, data->buf, data->len);
-
- ble_gap_adv_params_t m_adv_params = {
- .interval = (uint32_t) (self->interval / ADV_INTERVAL_UNIT_FLOAT_SECS),
- .properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_SCANNABLE_UNDIRECTED,
- .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
- .filter_policy = BLE_GAP_ADV_FP_ANY,
- .primary_phy = BLE_GAP_PHY_1MBPS,
- };
-
- common_hal_bleio_broadcaster_stop_advertising(self);
-
- const ble_gap_adv_data_t ble_gap_adv_data = {
- .adv_data.p_data = self->adv_data,
- .adv_data.len = data->len,
- };
-
- err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &ble_gap_adv_data, &m_adv_params);
- if (err_code == NRF_SUCCESS) {
- err_code = sd_ble_gap_adv_start(m_adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
- }
-
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code);
- }
-}
-
-void common_hal_bleio_broadcaster_stop_advertising(bleio_broadcaster_obj_t *self) {
-
- if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) {
- return;
- }
-
- const uint32_t err_code = sd_ble_gap_adv_stop(m_adv_handle);
-
- if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) {
- mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code);
- }
-}
diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c
new file mode 100644
index 000000000..d90737411
--- /dev/null
+++ b/ports/nrf/common-hal/bleio/Central.c
@@ -0,0 +1,463 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <string.h>
+#include <stdio.h>
+
+#include "ble.h"
+#include "ble_drv.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/Central.h"
+#include "shared-bindings/bleio/Descriptor.h"
+#include "shared-bindings/bleio/Service.h"
+#include "shared-bindings/bleio/UUID.h"
+
+static bleio_service_obj_t *m_char_discovery_service;
+static bleio_characteristic_obj_t *m_desc_discovery_characteristic;
+
+static volatile bool m_discovery_in_process;
+static volatile bool m_discovery_successful;
+
+// service_uuid may be NULL, to discover all services.
+STATIC bool discover_next_services(bleio_central_obj_t *self, uint16_t start_handle, ble_uuid_t *service_uuid) {
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint32_t err_code = sd_ble_gattc_primary_services_discover(self->conn_handle, start_handle, service_uuid);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg(translate("Failed to discover services"));
+ }
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC bool discover_next_characteristics(bleio_central_obj_t *self, bleio_service_obj_t *service, uint16_t start_handle) {
+ m_char_discovery_service = service;
+
+ ble_gattc_handle_range_t handle_range;
+ handle_range.start_handle = start_handle;
+ handle_range.end_handle = service->end_handle;
+
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range);
+ if (err_code != NRF_SUCCESS) {
+ return false;
+ }
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_characteristic_obj_t *characteristic, uint16_t start_handle, uint16_t end_handle) {
+ m_desc_discovery_characteristic = characteristic;
+
+ ble_gattc_handle_range_t handle_range;
+ handle_range.start_handle = start_handle;
+ handle_range.end_handle = end_handle;
+
+ m_discovery_successful = false;
+ m_discovery_in_process = true;
+
+ uint32_t err_code = sd_ble_gattc_descriptors_discover(self->conn_handle, &handle_range);
+ if (err_code != NRF_SUCCESS) {
+ return false;
+ }
+
+ // Wait for a discovery event.
+ while (m_discovery_in_process) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+ return m_discovery_successful;
+}
+
+STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *response, bleio_central_obj_t *central) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_service_t *gattc_service = &response->services[i];
+
+ bleio_service_obj_t *service = m_new_obj(bleio_service_obj_t);
+ service->base.type = &bleio_service_type;
+
+ // Initialize several fields at once.
+ common_hal_bleio_service_construct(service, NULL, mp_obj_new_list(0, NULL), false);
+
+ service->device = MP_OBJ_FROM_PTR(central);
+ service->start_handle = gattc_service->handle_range.start_handle;
+ service->end_handle = gattc_service->handle_range.end_handle;
+ service->handle = gattc_service->handle_range.start_handle;
+
+ if (gattc_service->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known service UUID.
+ bleio_uuid_obj_t *uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
+ service->uuid = uuid;
+ service->device = MP_OBJ_FROM_PTR(central);
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just set the UUID to NULL.
+ service->uuid = NULL;
+ }
+
+ mp_obj_list_append(central->service_list, service);
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio_central_obj_t *central) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_char_t *gattc_char = &response->chars[i];
+
+ bleio_characteristic_obj_t *characteristic = m_new_obj(bleio_characteristic_obj_t);
+ characteristic->base.type = &bleio_characteristic_type;
+
+ characteristic->descriptor_list = mp_obj_new_list(0, NULL);
+
+ bleio_uuid_obj_t *uuid = NULL;
+
+ if (gattc_char->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known characteristic UUID.
+ uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just leave the UUID as NULL.
+ }
+
+ bleio_characteristic_properties_t props;
+
+ props.broadcast = gattc_char->char_props.broadcast;
+ props.indicate = gattc_char->char_props.indicate;
+ props.notify = gattc_char->char_props.notify;
+ props.read = gattc_char->char_props.read;
+ props.write = gattc_char->char_props.write;
+ props.write_no_response = gattc_char->char_props.write_wo_resp;
+
+ // Call common_hal_bleio_characteristic_construct() to initalize some fields and set up evt handler.
+ common_hal_bleio_characteristic_construct(characteristic, uuid, props, mp_obj_new_list(0, NULL));
+ characteristic->handle = gattc_char->handle_value;
+ characteristic->service = m_char_discovery_service;
+
+ mp_obj_list_append(m_char_discovery_service->characteristic_list, MP_OBJ_FROM_PTR(characteristic));
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio_central_obj_t *central) {
+ for (size_t i = 0; i < response->count; ++i) {
+ ble_gattc_desc_t *gattc_desc = &response->descs[i];
+
+ // Remember handles for certain well-known descriptors.
+ switch (gattc_desc->uuid.uuid) {
+ case DESCRIPTOR_UUID_CLIENT_CHARACTERISTIC_CONFIGURATION:
+ m_desc_discovery_characteristic->cccd_handle = gattc_desc->handle;
+ break;
+
+ case DESCRIPTOR_UUID_SERVER_CHARACTERISTIC_CONFIGURATION:
+ m_desc_discovery_characteristic->sccd_handle = gattc_desc->handle;
+ break;
+
+ case DESCRIPTOR_UUID_CHARACTERISTIC_USER_DESCRIPTION:
+ m_desc_discovery_characteristic->user_desc_handle = gattc_desc->handle;
+ break;
+
+ default:
+ // TODO: sd_ble_gattc_descriptors_discover() can return things that are not descriptors,
+ // so ignore those.
+ // https://devzone.nordicsemi.com/f/nordic-q-a/49500/sd_ble_gattc_descriptors_discover-is-returning-attributes-that-are-not-descriptors
+ break;
+ }
+
+ bleio_descriptor_obj_t *descriptor = m_new_obj(bleio_descriptor_obj_t);
+ descriptor->base.type = &bleio_descriptor_type;
+
+ bleio_uuid_obj_t *uuid = NULL;
+
+ if (gattc_desc->uuid.type != BLE_UUID_TYPE_UNKNOWN) {
+ // Known descriptor UUID.
+ uuid = m_new_obj(bleio_uuid_obj_t);
+ uuid->base.type = &bleio_uuid_type;
+ bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_desc->uuid);
+ } else {
+ // The discovery response contained a 128-bit UUID that has not yet been registered with the
+ // softdevice via sd_ble_uuid_vs_add(). We need to fetch the 128-bit value and register it.
+ // For now, just leave the UUID as NULL.
+ }
+
+ common_hal_bleio_descriptor_construct(descriptor, uuid);
+ descriptor->handle = gattc_desc->handle;
+ descriptor->characteristic = m_desc_discovery_characteristic;
+
+ mp_obj_list_append(m_desc_discovery_characteristic->descriptor_list, MP_OBJ_FROM_PTR(descriptor));
+ }
+
+ if (response->count > 0) {
+ m_discovery_successful = true;
+ }
+ m_discovery_in_process = false;
+}
+
+STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
+ bleio_central_obj_t *central = (bleio_central_obj_t*)central_in;
+
+ switch (ble_evt->header.evt_id) {
+ case BLE_GAP_EVT_CONNECTED:
+ central->conn_handle = ble_evt->evt.gap_evt.conn_handle;
+ central->waiting_to_connect = false;
+ break;
+
+ case BLE_GAP_EVT_TIMEOUT:
+ // Handle will be invalid.
+ central->waiting_to_connect = false;
+ break;
+
+ case BLE_GAP_EVT_DISCONNECTED:
+ central->conn_handle = BLE_CONN_HANDLE_INVALID;
+ m_discovery_successful = false;
+ m_discovery_in_process = false;
+ break;
+
+ case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
+ on_primary_srv_discovery_rsp(&ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp, central);
+ break;
+
+ case BLE_GATTC_EVT_CHAR_DISC_RSP:
+ on_char_discovery_rsp(&ble_evt->evt.gattc_evt.params.char_disc_rsp, central);
+ break;
+
+ case BLE_GATTC_EVT_DESC_DISC_RSP:
+ on_desc_discovery_rsp(&ble_evt->evt.gattc_evt.params.desc_disc_rsp, central);
+ break;
+
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+ sd_ble_gap_sec_params_reply(central->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(central->conn_handle, &request->conn_params);
+ break;
+ }
+
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
+ }
+}
+
+void common_hal_bleio_central_construct(bleio_central_obj_t *self) {
+ common_hal_bleio_adapter_set_enabled(true);
+
+ self->service_list = mp_obj_new_list(0, NULL);
+ self->gatt_role = GATT_ROLE_CLIENT;
+ self->conn_handle = BLE_CONN_HANDLE_INVALID;
+}
+
+void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_obj_t *address, mp_float_t timeout, mp_obj_t service_uuids) {
+ common_hal_bleio_adapter_set_enabled(true);
+ ble_drv_add_event_handler(central_on_ble_evt, self);
+
+ ble_gap_addr_t addr;
+
+ addr.addr_type = address->type;
+ mp_buffer_info_t address_buf_info;
+ mp_get_buffer_raise(address->bytes, &address_buf_info, MP_BUFFER_READ);
+ memcpy(addr.addr, (uint8_t *) address_buf_info.buf, NUM_BLEIO_ADDRESS_BYTES);
+
+ 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),
+ .scan_phys = BLE_GAP_PHY_1MBPS,
+ // timeout of 0 means no timeout
+ .timeout = SEC_TO_UNITS(timeout, UNIT_10_MS),
+ };
+
+ ble_gap_conn_params_t conn_params = {
+ .conn_sup_timeout = MSEC_TO_UNITS(4000, UNIT_10_MS),
+ .min_conn_interval = MSEC_TO_UNITS(15, UNIT_1_25_MS),
+ .max_conn_interval = MSEC_TO_UNITS(300, UNIT_1_25_MS),
+ .slave_latency = 0, // number of conn events
+ };
+
+ self->waiting_to_connect = true;
+
+ uint32_t err_code = sd_ble_gap_connect(&addr, &scan_params, &conn_params, BLE_CONN_CFG_TAG_CUSTOM);
+
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to start connecting, error 0x%04x"), err_code);
+ }
+
+ while (self->waiting_to_connect) {
+ MICROPY_VM_HOOK_LOOP;
+ }
+
+ if (self->conn_handle == BLE_CONN_HANDLE_INVALID) {
+ mp_raise_OSError_msg(translate("Failed to connect: timeout"));
+ }
+
+ // Connection successful.
+ // Now discover services on the remote peripheral.
+
+ if (service_uuids == mp_const_none) {
+
+ // List of service UUID's not given, so discover all available services.
+
+ uint16_t next_service_start_handle = BLE_GATT_HANDLE_START;
+
+ while (discover_next_services(self, next_service_start_handle, MP_OBJ_NULL)) {
+ // discover_next_services() appends to service_list.
+
+ // Get the most recently discovered service, and then ask for services
+ // whose handles start after the last attribute handle inside that service.
+ const bleio_service_obj_t *service =
+ MP_OBJ_TO_PTR(self->service_list->items[self->service_list->len - 1]);
+ next_service_start_handle = service->end_handle + 1;
+ }
+ } else {
+ mp_obj_iter_buf_t iter_buf;
+ mp_obj_t iterable = mp_getiter(service_uuids, &iter_buf);
+ mp_obj_t uuid_obj;
+ while ((uuid_obj = mp_iternext(iterable)) != MP_OBJ_STOP_ITERATION) {
+ if (!MP_OBJ_IS_TYPE(uuid_obj, &bleio_uuid_type)) {
+ mp_raise_ValueError(translate("non-UUID found in service_uuids"));
+ }
+ bleio_uuid_obj_t *uuid = MP_OBJ_TO_PTR(uuid_obj);
+
+ ble_uuid_t nrf_uuid;
+ bleio_uuid_convert_to_nrf_ble_uuid(uuid, &nrf_uuid);
+
+ // Service might or might not be discovered; that's ok. Caller has to check
+ // Central.remote_services to find out.
+ // We only need to call this once for each service to discover.
+ discover_next_services(self, BLE_GATT_HANDLE_START, &nrf_uuid);
+ }
+ }
+
+
+ for (size_t service_idx = 0; service_idx < self->service_list->len; ++service_idx) {
+ bleio_service_obj_t *service = MP_OBJ_TO_PTR(self->service_list->items[service_idx]);
+
+ // Skip the service if it had an unknown (unregistered) UUID.
+ if (service->uuid == NULL) {
+ continue;
+ }
+
+ uint16_t next_char_start_handle = service->start_handle;
+
+ // Stop when we go past the end of the range of handles for this service or
+ // discovery call returns nothing.
+ // discover_next_characteristics() appends to the characteristic_list.
+ while (next_char_start_handle <= service->end_handle &&
+ discover_next_characteristics(self, service, next_char_start_handle)) {
+
+
+ // Get the most recently discovered characteristic, and then ask for characteristics
+ // whose handles start after the last attribute handle inside that characteristic.
+ const bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(service->characteristic_list->items[service->characteristic_list->len - 1]);
+ next_char_start_handle = characteristic->handle + 1;
+ }
+
+ // Got characteristics for this service. Now discover descriptors for each characteristic.
+ size_t char_list_len = service->characteristic_list->len;
+ for (size_t char_idx = 0; char_idx < char_list_len; ++char_idx) {
+ bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx]);
+ const bool last_characteristic = char_idx == char_list_len - 1;
+ bleio_characteristic_obj_t *next_characteristic = last_characteristic
+ ? NULL
+ : MP_OBJ_TO_PTR(service->characteristic_list->items[char_idx + 1]);
+
+ // Skip the characteristic if it had an unknown (unregistered) UUID.
+ if (characteristic->uuid == NULL) {
+ continue;
+ }
+
+ uint16_t next_desc_start_handle = characteristic->handle + 1;
+
+ // Don't run past the end of this service or the beginning of the next characteristic.
+ uint16_t next_desc_end_handle = next_characteristic == NULL
+ ? service->end_handle
+ : next_characteristic->handle - 1;
+
+ // Stop when we go past the end of the range of handles for this service or
+ // discovery call returns nothing.
+ // discover_next_descriptors() appends to the descriptor_list.
+ while (next_desc_start_handle <= service->end_handle &&
+ next_desc_start_handle < next_desc_end_handle &&
+ discover_next_descriptors(self, characteristic,
+ next_desc_start_handle, next_desc_end_handle)) {
+
+ // Get the most recently discovered descriptor, and then ask for descriptors
+ // whose handles start after that descriptor's handle.
+ const bleio_descriptor_obj_t *descriptor =
+ MP_OBJ_TO_PTR(characteristic->descriptor_list->items[characteristic->descriptor_list->len - 1]);
+ next_desc_start_handle = descriptor->handle + 1;
+ }
+ }
+
+ }
+}
+
+void common_hal_bleio_central_disconnect(bleio_central_obj_t *self) {
+ sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+}
+
+bool common_hal_bleio_central_get_connected(bleio_central_obj_t *self) {
+ return self->conn_handle != BLE_CONN_HANDLE_INVALID;
+}
+
+mp_obj_list_t *common_hal_bleio_central_get_remote_services(bleio_central_obj_t *self) {
+ return self->service_list;
+}
diff --git a/ports/nrf/common-hal/bleio/Broadcaster.h b/ports/nrf/common-hal/bleio/Central.h
index 72f93a443..ac1670088 100644
--- a/ports/nrf/common-hal/bleio/Broadcaster.h
+++ b/ports/nrf/common-hal/bleio/Central.h
@@ -3,8 +3,8 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,23 +25,21 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
-#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
+#ifndef MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H
+#define MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H
-#include "ble.h"
+#include <stdbool.h>
+#include "py/objlist.h"
#include "shared-module/bleio/__init__.h"
#include "shared-module/bleio/Address.h"
typedef struct {
mp_obj_base_t base;
- // In seconds.
- mp_float_t interval;
- // The advertising data buffer is held by us, not by the SD, so we must
- // maintain it and not change it. If we need to change its contents during advertising,
- // there are tricks to get the SD to notice (see DevZone - TBS).
- uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
+ gatt_role_t gatt_role;
+ volatile bool waiting_to_connect;
+ volatile uint16_t conn_handle;
+ mp_obj_list_t *service_list;
+} bleio_central_obj_t;
-} bleio_broadcaster_obj_t;
-
-#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_BROADCASTER_H
+#endif // MICROPY_INCLUDED_SHARED_MODULE_BLEIO_CENTRAL_H
diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c
index 9409b73ce..17417a5e6 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.c
+++ b/ports/nrf/common-hal/bleio/Characteristic.c
@@ -3,6 +3,7 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -34,12 +35,8 @@
#include "py/runtime.h"
#include "common-hal/bleio/__init__.h"
#include "common-hal/bleio/Characteristic.h"
-#include "shared-module/bleio/Characteristic.h"
STATIC volatile bleio_characteristic_obj_t *m_read_characteristic;
-STATIC volatile uint8_t m_tx_in_progress;
-// Serialize gattc writes that send a response. This might be done per object?
-STATIC nrf_mutex_t *m_write_mutex;
STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
@@ -63,7 +60,7 @@ STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) {
}
STATIC void gatts_read(bleio_characteristic_obj_t *characteristic) {
- // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
+ // This might be BLE_CONN_HANDLE_INVALID if we're not connected, but that's OK, because
// we can still read and write the local value.
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
@@ -118,24 +115,35 @@ STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp
.p_data = bufinfo->buf,
};
- while (m_tx_in_progress >= MAX_TX_IN_PROGRESS) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
- }
-
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- m_tx_in_progress++;
- const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
- if (err_code != NRF_SUCCESS) {
- m_tx_in_progress--;
+
+ while (1) {
+ const uint32_t err_code = sd_ble_gatts_hvx(conn_handle, &hvx_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
+ // TX buffer is full
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ if (err_code == NRF_ERROR_RESOURCES) {
+ MICROPY_VM_HOOK_LOOP;
+ continue;
+ }
+
+ // Some real error has occurred.
mp_raise_OSError_msg_varg(translate("Failed to notify or indicate attribute value, err 0x%04x"), err_code);
}
}
+STATIC void check_connected(uint16_t conn_handle) {
+ if (conn_handle == BLE_CONN_HANDLE_INVALID) {
+ mp_raise_OSError_msg(translate("Not connected"));
+ }
+}
+
STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) {
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
+ check_connected(conn_handle);
m_read_characteristic = characteristic;
@@ -144,100 +152,79 @@ STATIC void gattc_read(bleio_characteristic_obj_t *characteristic) {
mp_raise_OSError_msg_varg(translate("Failed to read attribute value, err 0x%04x"), err_code);
}
-//
while (m_read_characteristic != NULL) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
+ MICROPY_VM_HOOK_LOOP;
}
}
STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) {
const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device);
- uint32_t err_code;
+ check_connected(conn_handle);
ble_gattc_write_params_t write_params = {
- .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL,
- .write_op = BLE_GATT_OP_WRITE_REQ,
+ .write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ,
.handle = characteristic->handle,
.p_value = bufinfo->buf,
.len = bufinfo->len,
};
- if (characteristic->props.write_no_response) {
- write_params.write_op = BLE_GATT_OP_WRITE_CMD;
+ while (1) {
+ uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
+ }
- err_code = sd_mutex_acquire(m_write_mutex);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg_varg(translate("Failed to acquire mutex, err 0x%04x"), err_code);
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ MICROPY_VM_HOOK_LOOP;
+ continue;
}
- }
- err_code = sd_ble_gattc_write(conn_handle, &write_params);
- if (err_code != NRF_SUCCESS) {
+ // Some real error occurred.
mp_raise_OSError_msg_varg(translate("Failed to write attribute value, err 0x%04x"), 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) {
- mp_raise_OSError_msg_varg(translate("Failed to release mutex, err 0x%04x"), err_code);
- }
}
STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) {
switch (ble_evt->header.evt_id) {
- case BLE_GATTS_EVT_HVN_TX_COMPLETE:
- {
- uint8_t count = ble_evt->evt.gatts_evt.params.hvn_tx_complete.count;
- // Don't underflow the count.
- if (count >= m_tx_in_progress) {
- m_tx_in_progress = 0;
- } else {
- m_tx_in_progress -= count;
- }
- break;
- }
- 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);
- // Flag to busy-wait loop that we've read the characteristic.
- m_read_characteristic = NULL;
- break;
- }
+ // More events may be handled later, so keep this as a switch.
- case BLE_GATTC_EVT_WRITE_RSP:
- // Someone else can write now.
- sd_mutex_release(m_write_mutex);
- break;
+ case BLE_GATTC_EVT_READ_RSP: {
+ ble_gattc_evt_read_rsp_t *response = &ble_evt->evt.gattc_evt.params.read_rsp;
+ m_read_characteristic->value_data = mp_obj_new_bytearray(response->len, response->data);
+ // Indicate to busy-wait loop that we've read the characteristic.
+ m_read_characteristic = NULL;
+ break;
+ }
- // For debugging.
- default:
- // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
- break;
+ // For debugging.
+ default:
+ // mp_printf(&mp_plat_print, "Unhandled characteristic event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
}
}
-void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props) {
- self->service = NULL;
+void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props, mp_obj_list_t *descriptor_list) {
+ self->service = mp_const_none;
self->uuid = uuid;
- self->value_data = NULL;
+ self->value_data = mp_const_none;
self->props = props;
+ self->descriptor_list = descriptor_list;
self->handle = BLE_GATT_HANDLE_INVALID;
ble_drv_add_event_handler(characteristic_on_ble_evt, self);
+}
+mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
+ return self->descriptor_list;
}
-void common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
+mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
case GATT_ROLE_CLIENT:
gattc_read(self);
@@ -251,6 +238,8 @@ void common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self)
mp_raise_RuntimeError(translate("bad GATT role"));
break;
}
+
+ return self->value_data;
}
void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) {
@@ -258,30 +247,83 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
uint16_t cccd = 0;
switch (common_hal_bleio_device_get_gatt_role(self->service->device)) {
- case GATT_ROLE_SERVER:
- if (self->props.notify || self->props.indicate) {
- cccd = get_cccd(self);
- }
- // It's possible that both notify and indicate are set.
- if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
- sent = true;
- }
- if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
- gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
- sent = true;
- }
- if (!sent) {
- gatts_write(self, bufinfo);
+ case GATT_ROLE_SERVER:
+ if (self->props.notify || self->props.indicate) {
+ cccd = get_cccd(self);
+ }
+ // It's possible that both notify and indicate are set.
+ if (self->props.notify && (cccd & BLE_GATT_HVX_NOTIFICATION)) {
+ gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_NOTIFICATION);
+ sent = true;
+ }
+ if (self->props.indicate && (cccd & BLE_GATT_HVX_INDICATION)) {
+ gatts_notify_indicate(self, bufinfo, BLE_GATT_HVX_INDICATION);
+ sent = true;
+ }
+ if (!sent) {
+ gatts_write(self, bufinfo);
+ }
+ break;
+
+ case GATT_ROLE_CLIENT:
+ gattc_write(self, bufinfo);
+ break;
+
+ default:
+ mp_raise_RuntimeError(translate("bad GATT role"));
+ break;
+ }
+}
+
+
+bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_obj_t *self) {
+ return self->uuid;
+}
+
+bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties(bleio_characteristic_obj_t *self) {
+ return self->props;
+}
+
+void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self, bool notify, bool indicate) {
+ if (self->cccd_handle == BLE_GATT_HANDLE_INVALID) {
+ mp_raise_ValueError(translate("No CCCD for this Characteristic"));
+ }
+
+ if (common_hal_bleio_device_get_gatt_role(self->service->device) != GATT_ROLE_CLIENT) {
+ mp_raise_ValueError(translate("Can't set CCCD for local Characteristic"));
+ }
+
+ uint16_t cccd_value =
+ (notify ? BLE_GATT_HVX_NOTIFICATION : 0) |
+ (indicate ? BLE_GATT_HVX_INDICATION : 0);
+
+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(self->service->device);
+ check_connected(conn_handle);
+
+
+ ble_gattc_write_params_t write_params = {
+ .write_op = BLE_GATT_OP_WRITE_REQ,
+ .handle = self->cccd_handle,
+ .p_value = (uint8_t *) &cccd_value,
+ .len = 2,
+ };
+
+ while (1) {
+ uint32_t err_code = sd_ble_gattc_write(conn_handle, &write_params);
+ if (err_code == NRF_SUCCESS) {
+ break;
}
- break;
- case GATT_ROLE_CLIENT:
- gattc_write(self, bufinfo);
- break;
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ MICROPY_VM_HOOK_LOOP;
+ continue;
+ }
- default:
- mp_raise_RuntimeError(translate("bad GATT role"));
- break;
+ // Some real error occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to write CCCD, err 0x%04x"), err_code);
}
+
}
diff --git a/ports/nrf/common-hal/bleio/Characteristic.h b/ports/nrf/common-hal/bleio/Characteristic.h
index bce1eec1d..7cb227596 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.h
+++ b/ports/nrf/common-hal/bleio/Characteristic.h
@@ -3,6 +3,7 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -24,23 +25,24 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
-#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
-#include "shared-module/bleio/Characteristic.h"
-#include "shared-module/bleio/Service.h"
+#include "common-hal/bleio/Service.h"
#include "common-hal/bleio/UUID.h"
+#include "shared-module/bleio/Characteristic.h"
typedef struct {
mp_obj_base_t base;
bleio_service_obj_t *service;
bleio_uuid_obj_t *uuid;
- mp_obj_t value_data;
+ volatile mp_obj_t value_data;
uint16_t handle;
bleio_characteristic_properties_t props;
+ mp_obj_list_t *descriptor_list;
uint16_t user_desc_handle;
uint16_t cccd_handle;
uint16_t sccd_handle;
} bleio_characteristic_obj_t;
-#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTIC_H
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTIC_H
diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
index 19b3b85ea..59eaaf02b 100644
--- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
+++ b/ports/nrf/common-hal/bleio/CharacteristicBuffer.c
@@ -40,25 +40,42 @@
#include "common-hal/bleio/__init__.h"
#include "common-hal/bleio/CharacteristicBuffer.h"
+STATIC void write_to_ringbuf(bleio_characteristic_buffer_obj_t *self, uint8_t *data, uint16_t len) {
+ // Push all the data onto the ring buffer.
+ uint8_t is_nested_critical_region;
+ sd_nvic_critical_region_enter(&is_nested_critical_region);
+ for (size_t i = 0; i < len; i++) {
+ ringbuf_put(&self->ringbuf, data[i]);
+ }
+ sd_nvic_critical_region_exit(is_nested_critical_region);
+}
+
STATIC void characteristic_buffer_on_ble_evt(ble_evt_t *ble_evt, void *param) {
bleio_characteristic_buffer_obj_t *self = (bleio_characteristic_buffer_obj_t *) param;
switch (ble_evt->header.evt_id) {
- case BLE_GATTS_EVT_WRITE: {
- ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
- // Event handle must match the handle for my characteristic.
- if (evt_write->handle == self->characteristic->handle) {
- // Push all the data onto the ring buffer.
- uint8_t is_nested_critical_region;
- sd_nvic_critical_region_enter(&is_nested_critical_region);
- for (size_t i = 0; i < evt_write->len; i++) {
- ringbuf_put(&self->ringbuf, evt_write->data[i]);
+ case BLE_GATTS_EVT_WRITE: {
+ // A client wrote to this server characteristic.
+
+ ble_gatts_evt_write_t *evt_write = &ble_evt->evt.gatts_evt.params.write;
+ // Event handle must match the handle for my characteristic.
+ if (evt_write->handle == self->characteristic->handle) {
+ write_to_ringbuf(self, evt_write->data, evt_write->len);
}
- sd_nvic_critical_region_exit(is_nested_critical_region);
break;
}
- }
- }
+ case BLE_GATTC_EVT_HVX: {
+ // A remote service wrote to this characteristic.
+
+ ble_gattc_evt_hvx_t* evt_hvx = &ble_evt->evt.gattc_evt.params.hvx;
+ // Must be a notification, and event handle must match the handle for my characteristic.
+ if (evt_hvx->type == BLE_GATT_HVX_NOTIFICATION &&
+ evt_hvx->handle == self->characteristic->handle) {
+ write_to_ringbuf(self, evt_hvx->data, evt_hvx->len);
+ }
+ break;
+ }
+ }
}
// Assumes that timeout and buffer_size have been validated before call.
@@ -82,13 +99,11 @@ int common_hal_bleio_characteristic_buffer_read(bleio_characteristic_buffer_obj_
// Wait for all bytes received or timeout
while ( (ringbuf_count(&self->ringbuf) < len) && (ticks_ms - start_ticks < self->timeout_ms) ) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP ;
+ MICROPY_VM_HOOK_LOOP;
// Allow user to break out of a timeout with a KeyboardInterrupt.
if ( mp_hal_is_interrupted() ) {
return 0;
}
-#endif
}
// Copy received data. Lock out write interrupt handler while copying.
diff --git a/ports/nrf/common-hal/bleio/CharacteristicBuffer.h b/ports/nrf/common-hal/bleio/CharacteristicBuffer.h
index b36f63fec..db8fd2fad 100644
--- a/ports/nrf/common-hal/bleio/CharacteristicBuffer.h
+++ b/ports/nrf/common-hal/bleio/CharacteristicBuffer.h
@@ -3,7 +3,7 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
-#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
#include "nrf_soc.h"
@@ -40,4 +40,4 @@ typedef struct {
ringbuf_t ringbuf;
} bleio_characteristic_buffer_obj_t;
-#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_CHARACTERISTICBUFFER_H
diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c
index 8282be8f2..005af6eaa 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.c
+++ b/ports/nrf/common-hal/bleio/Descriptor.c
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
@@ -29,7 +30,6 @@
#include "shared-bindings/bleio/UUID.h"
void common_hal_bleio_descriptor_construct(bleio_descriptor_obj_t *self, bleio_uuid_obj_t *uuid) {
- // TODO: set handle ???
self->uuid = uuid;
}
@@ -37,6 +37,6 @@ mp_int_t common_hal_bleio_descriptor_get_handle(bleio_descriptor_obj_t *self) {
return self->handle;
}
-mp_obj_t common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
- return MP_OBJ_FROM_PTR(self->uuid);
+bleio_uuid_obj_t *common_hal_bleio_descriptor_get_uuid(bleio_descriptor_obj_t *self) {
+ return self->uuid;
}
diff --git a/ports/nrf/common-hal/bleio/Descriptor.h b/ports/nrf/common-hal/bleio/Descriptor.h
index ee0886c22..b7af6a42f 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.h
+++ b/ports/nrf/common-hal/bleio/Descriptor.h
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
@@ -29,11 +30,13 @@
#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_DESCRIPTOR_H
#include "py/obj.h"
+#include "common-hal/bleio/Characteristic.h"
#include "common-hal/bleio/UUID.h"
typedef struct {
mp_obj_base_t base;
uint16_t handle;
+ bleio_characteristic_obj_t *characteristic;
bleio_uuid_obj_t *uuid;
} bleio_descriptor_obj_t;
diff --git a/ports/nrf/common-hal/bleio/Device.c b/ports/nrf/common-hal/bleio/Device.c
deleted file mode 100644
index 5f625829e..000000000
--- a/ports/nrf/common-hal/bleio/Device.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * 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 <string.h>
-#include <stdio.h>
-
-#include "ble.h"
-#include "ble_drv.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"
-
-#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) { \
- mp_raise_ValueError(translate("Data too large for the advertisement 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) {
- mp_raise_ValueError(translate("Data too large for the advertisement 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;
- }
-
- switch (common_hal_bleio_uuid_get_size(service->uuid)) {
- case 16:
- has_16bit_services = true;
- break;
- case 128:
- has_128bit_services = true;
- break;
- }
- }
-
- 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 (common_hal_bleio_uuid_get_size(service->uuid) != 16 || service->is_secondary) {
- continue;
- }
-
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
-
- 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 (common_hal_bleio_uuid_get_size(service->uuid) != 16 || service->is_secondary) {
- continue;
- }
-
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
-
- 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 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) {
- mp_raise_OSError_msg(translate("Failed to discover services"));
- }
-
- // Serialize discovery.
- err_code = sd_mutex_acquire(m_discovery_mutex);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg(translate("Failed to acquire mutex"));
- }
-
- // Wait for someone else to release m_discovery_mutex.
- 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) {
- mp_raise_OSError_msg(translate("Failed to release mutex"));
- }
-
- return m_discovery_successful;
-}
-
-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 != NRF_SUCCESS) {
- return false;
- }
-
- err_code = sd_mutex_acquire(m_discovery_mutex);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg(translate("Failed to acquire mutex"));
- }
-
- 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) {
- mp_raise_OSError_msg(translate("Failed to release mutex"));
- }
-
- 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) {
- 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);
- bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_service->uuid);
- 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) {
- mp_raise_OSError_msg(translate("Failed to release mutex"));
- }
-}
-
-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) {
- 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;
- bleio_uuid_construct_from_nrf_ble_uuid(uuid, &gattc_char->uuid);
- 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_no_response = gattc_char->char_props.write_wo_resp;
- characteristic->handle = gattc_char->handle_value;
- 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) {
- mp_raise_OSError_msg(translate("Failed to release mutex"));
- }
-}
-
-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) {
- mp_raise_OSError_msg(translate("Failed to continue scanning"));
- }
-#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) {
- mp_raise_OSError_msg(translate("Failed to connect:"));
- }
-}
-
-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_add_service(bleio_device_obj_t *device, bleio_service_obj_t *service) {
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
-
- uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
- if (service->is_secondary) {
- 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, &service->handle);
- if (err_code != NRF_SUCCESS) {
- mp_raise_OSError_msg(translate("Failed to add service"));
- }
-
- const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(service->char_list);
- for (size_t i = 0; i < char_list->len; ++i) {
- bleio_characteristic_obj_t *characteristic = char_list->items[i];
- common_hal_bleio_service_add_characteristic(service, characteristic);
- }
-}
-
-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) {
- mp_raise_OSError_msg(translate("Failed to start advertising"));
- }
-}
-
-void common_hal_bleio_device_stop_advertising(bleio_device_obj_t *device) {
- uint32_t err_code;
-
-#if (BLUETOOTH_SD == 140)
- if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
- 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)) {
- mp_raise_OSError_msg(translate("Failed to stop advertising"));
- }
-}
-
-void common_hal_bleio_device_connect(bleio_device_obj_t *device) {
- ble_drv_add_event_handler(on_ble_evt, 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) {
- mp_raise_OSError_msg(translate("Failed to start scanning"));
- }
-
- while (device->conn_handle == BLE_CONN_HANDLE_INVALID) {
-#ifdef MICROPY_VM_HOOK_LOOP
- MICROPY_VM_HOOK_LOOP
-#endif
- }
-
- // 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) {
- mp_raise_OSError_msg(translate("Failed to create mutex"));
- }
- }
-
- // find services
- 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 = discover_services(device, service->end_handle + 1);
- }
-
- // 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 = 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];
-
- const uint16_t next_handle = characteristic->handle + 1;
- if (next_handle >= service->end_handle) {
- break;
- }
-
- found_char = discover_characteristics(device, service, next_handle);
- }
- }
-}
-
-void common_hal_bleio_device_disconnect(bleio_device_obj_t *device) {
- sd_ble_gap_disconnect(device->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
-}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c
index 0a5a8069d..608bd1342 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/bleio/Peripheral.c
@@ -3,8 +3,8 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2018 Artur Pacholec
* Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -32,6 +32,8 @@
#include "ble_drv.h"
#include "ble_hci.h"
#include "nrf_soc.h"
+#include "py/gc.h"
+#include "py/objlist.h"
#include "py/objstr.h"
#include "py/runtime.h"
#include "shared-bindings/bleio/Adapter.h"
@@ -39,6 +41,7 @@
#include "shared-bindings/bleio/Peripheral.h"
#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/UUID.h"
+#include "common-hal/bleio/Service.h"
#define BLE_MIN_CONN_INTERVAL MSEC_TO_UNITS(15, UNIT_0_625_MS)
#define BLE_MAX_CONN_INTERVAL MSEC_TO_UNITS(300, UNIT_0_625_MS)
@@ -49,261 +52,96 @@
#define BLE_ADV_AD_TYPE_FIELD_SIZE 1
#define BLE_AD_TYPE_FLAGS_DATA_SIZE 1
-static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
-
-STATIC void check_data_fit(size_t pos, size_t data_len) {
- if (pos + data_len >= BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
+STATIC void check_data_fit(size_t data_len) {
+ if (data_len > BLE_GAP_ADV_SET_DATA_SIZE_MAX) {
mp_raise_ValueError(translate("Data too large for advertisement packet"));
}
}
-STATIC uint32_t add_services_to_advertisement(bleio_peripheral_obj_t *self, size_t* adv_data_pos_p, size_t uuid_len) {
- uint32_t uuids_total_size = 0;
- const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
- uint32_t err_code = NRF_SUCCESS;
-
- check_data_fit(*adv_data_pos_p, 1 + 1);
-
- // Remember where length byte is; fill in later when we know the size.
- const size_t length_pos = *adv_data_pos_p;
- (*adv_data_pos_p)++;
-
- self->adv_data[(*adv_data_pos_p)++] = (uuid_len == 16)
- ? BLE_GAP_AD_TYPE_16BIT_SERVICE_UUID_COMPLETE
- : BLE_GAP_AD_TYPE_128BIT_SERVICE_UUID_COMPLETE;
-
- 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;
-
- // Skip services of the wrong length and secondary services.
- if (common_hal_bleio_uuid_get_size(service->uuid) != uuid_len || service->is_secondary) {
- continue;
- }
-
- ble_uuid_t uuid;
- bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
-
- err_code = sd_ble_uuid_encode(&uuid, &encoded_size, &(self->adv_data[*adv_data_pos_p]));
- if (err_code != NRF_SUCCESS) {
- return err_code;
- }
-
- check_data_fit(*adv_data_pos_p, encoded_size);
- uuids_total_size += encoded_size;
- (*adv_data_pos_p) += encoded_size;
- }
-
- self->adv_data[length_pos] = 1 + uuids_total_size; // 1 for the field type.
- return err_code;
-}
-
-
-
-// if raw_data is a zero-length buffer, generate an advertising packet that advertises the
-// services passed in when this Peripheral was created.
-// If raw_data contains some bytes, use those bytes as the advertising packet.
-// TODO: Generate the advertising packet in Python, not here.
-STATIC uint32_t set_advertisement_data(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
- common_hal_bleio_adapter_set_enabled(true);
-
- size_t adv_data_pos = 0;
- uint32_t err_code;
-
- GET_STR_DATA_LEN(self->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);
-
- // We'll add the name after everything else, shortening it if necessary.
- err_code = sd_ble_gap_device_name_set(&sec_mode, name_data, name_len);
- if (err_code != NRF_SUCCESS) {
- return err_code;
- }
- }
-
- if (raw_data->len != 0) {
- // User-supplied advertising packet.
- check_data_fit(adv_data_pos, raw_data->len);
- memcpy(&(self->adv_data[adv_data_pos]), raw_data->buf, raw_data->len);
- adv_data_pos += raw_data->len;
- } else {
- // Build up advertising packet.
- check_data_fit(adv_data_pos, 1 + 1 + 1);
- self->adv_data[adv_data_pos++] = 2;
- self->adv_data[adv_data_pos++] = BLE_GAP_AD_TYPE_FLAGS;
- self->adv_data[adv_data_pos++] = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
-
- // The 16-bit ids and 128-bit ids are grouped together by length, so find it whether we have
- // 16 and/or 128-bit service UUIDs.
-
- const mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->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;
- }
-
- switch (common_hal_bleio_uuid_get_size(service->uuid)) {
- case 16:
- has_16bit_services = true;
- break;
- case 128:
- has_128bit_services = true;
- break;
- }
- }
-
- // Add 16-bit service UUID's in a group, then 128-bit service UUID's.
-
- if (has_16bit_services) {
- err_code = add_services_to_advertisement(self, &adv_data_pos, 16);
- if (err_code != NRF_SUCCESS) {
- return err_code;
- }
- }
-
- if (has_128bit_services) {
- err_code = add_services_to_advertisement(self, &adv_data_pos, 128);
- if (err_code != NRF_SUCCESS) {
- return err_code;
- }
- }
- }
-
- // Always include TX power.
- check_data_fit(adv_data_pos, 1 + 1 + 1);
- self->adv_data[adv_data_pos++] = 1 + 1;
- self->adv_data[adv_data_pos++] = BLE_GAP_AD_TYPE_TX_POWER_LEVEL;
- self->adv_data[adv_data_pos++] = 0; // TODO - allow power level to be set later.
-
- // We need room for at least a one-character name.
- check_data_fit(adv_data_pos, 1 + 1 + 1);
-
- // How big a name can we fit?
- size_t bytes_left = BLE_GAP_ADV_SET_DATA_SIZE_MAX - adv_data_pos - 1 - 1;
- size_t partial_name_len = MIN(bytes_left, name_len);
- self->adv_data[adv_data_pos++] = 1 + partial_name_len;
- self->adv_data[adv_data_pos++] = (partial_name_len == name_len)
- ? BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME
- : BLE_GAP_AD_TYPE_SHORT_LOCAL_NAME;
- memcpy(&(self->adv_data[adv_data_pos]), name_data, partial_name_len);
- adv_data_pos += partial_name_len;
- } // end of advertising packet construction
-
- static ble_gap_adv_params_t m_adv_params = {
- .interval = MSEC_TO_UNITS(1000, UNIT_0_625_MS),
- .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,
- };
-
- if (!connectable) {
- m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED;
- }
-
- common_hal_bleio_peripheral_stop_advertising(self);
-
- const ble_gap_adv_data_t ble_gap_adv_data = {
- .adv_data.p_data = self->adv_data,
- .adv_data.len = adv_data_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);
-
- return err_code;
-}
-
STATIC void peripheral_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in;
switch (ble_evt->header.evt_id) {
- case BLE_GAP_EVT_CONNECTED: {
- // Central has connected.
- ble_gap_conn_params_t conn_params;
- self->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_CONNECTED: {
+ // Central has connected.
+ ble_gap_conn_params_t conn_params;
+ self->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:
- // Central has disconnected.
- self->conn_handle = BLE_CONN_HANDLE_INVALID;
- break;
-
- case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
- ble_gap_phys_t const phys = {
- .rx_phys = BLE_GAP_PHY_AUTO,
- .tx_phys = BLE_GAP_PHY_AUTO,
- };
- sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys);
- break;
- }
+ case BLE_GAP_EVT_DISCONNECTED:
+ // Central has disconnected.
+ self->conn_handle = BLE_CONN_HANDLE_INVALID;
+ break;
+
+ case BLE_GAP_EVT_PHY_UPDATE_REQUEST: {
+ ble_gap_phys_t const phys = {
+ .rx_phys = BLE_GAP_PHY_AUTO,
+ .tx_phys = BLE_GAP_PHY_AUTO,
+ };
+ sd_ble_gap_phy_update(ble_evt->evt.gap_evt.conn_handle, &phys);
+ break;
+ }
- case BLE_GAP_EVT_ADV_SET_TERMINATED:
- // Someday may handle timeouts or limit reached.
- break;
+ case BLE_GAP_EVT_ADV_SET_TERMINATED:
+ // Someday may handle timeouts or limit reached.
+ break;
- case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
- sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
- break;
+ case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
+ sd_ble_gap_sec_params_reply(self->conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
+ break;
- case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST: {
- ble_gap_evt_conn_param_update_request_t *request = &ble_evt->evt.gap_evt.params.conn_param_update_request;
- sd_ble_gap_conn_param_update(self->conn_handle, &request->conn_params);
- 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(self->conn_handle, &request->conn_params);
+ break;
+ }
- case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
- sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL);
- break;
+ case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
+ sd_ble_gap_data_length_update(self->conn_handle, NULL, NULL);
+ break;
- case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
- sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
- break;
- }
+ case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: {
+ sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATT_ATT_MTU_DEFAULT);
+ break;
+ }
- case BLE_GATTS_EVT_SYS_ATTR_MISSING:
- sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
- break;
+ case BLE_GATTS_EVT_SYS_ATTR_MISSING:
+ sd_ble_gatts_sys_attr_set(self->conn_handle, NULL, 0, 0);
+ break;
- default:
- // For debugging.
- // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
- break;
+ default:
+ // For debugging.
+ // mp_printf(&mp_plat_print, "Unhandled peripheral event: 0x%04x\n", ble_evt->header.evt_id);
+ break;
}
}
+void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_list_t *service_list, mp_obj_t name) {
+ common_hal_bleio_adapter_set_enabled(true);
-void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self) {
- common_hal_bleio_adapter_set_enabled(true); // TODO -- Do this somewhere else maybe bleio __init__
+ self->service_list = service_list;
+ self->name = name;
self->gatt_role = GATT_ROLE_SERVER;
self->conn_handle = BLE_CONN_HANDLE_INVALID;
+ self->adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;
// Add all the services.
- mp_obj_list_t *service_list = MP_OBJ_TO_PTR(self->service_list);
for (size_t service_idx = 0; service_idx < service_list->len; ++service_idx) {
bleio_service_obj_t *service = MP_OBJ_TO_PTR(service_list->items[service_idx]);
+ service->device = MP_OBJ_FROM_PTR(self);
+
ble_uuid_t uuid;
bleio_uuid_convert_to_nrf_ble_uuid(service->uuid, &uuid);
uint8_t service_type = BLE_GATTS_SRVC_TYPE_PRIMARY;
- if (service->is_secondary) {
+ if (common_hal_bleio_service_get_is_secondary(service)) {
service_type = BLE_GATTS_SRVC_TYPE_SECONDARY;
}
@@ -318,29 +156,94 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self) {
}
+mp_obj_list_t *common_hal_bleio_peripheral_get_service_list(bleio_peripheral_obj_t *self) {
+ return self->service_list;
+}
+
bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) {
return self->conn_handle != BLE_CONN_HANDLE_INVALID;
}
-void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) {
+mp_obj_t common_hal_bleio_peripheral_get_name(bleio_peripheral_obj_t *self) {
+ return self->name;
+}
+
+void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_float_t interval, mp_buffer_info_t *advertising_data_bufinfo, mp_buffer_info_t *scan_response_data_bufinfo) {
+
+ // interval value has already been validated.
+
if (connectable) {
ble_drv_add_event_handler(peripheral_on_ble_evt, self);
}
- const uint32_t err_code = set_advertisement_data(self, connectable, raw_data);
+ common_hal_bleio_adapter_set_enabled(true);
+
+ uint32_t err_code;
+
+ GET_STR_DATA_LEN(self->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) {
+ mp_raise_OSError_msg_varg(translate("Failed to set device name, err 0x%04x"), err_code);
+
+ }
+ }
+
+ check_data_fit(advertising_data_bufinfo->len);
+ // The advertising data buffers must not move, because the SoftDevice depends on them.
+ // So make them long-lived.
+ self->advertising_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true);
+ memcpy(self->advertising_data, advertising_data_bufinfo->buf, advertising_data_bufinfo->len);
+
+ check_data_fit(scan_response_data_bufinfo->len);
+ self->scan_response_data = (uint8_t *) gc_alloc(BLE_GAP_ADV_SET_DATA_SIZE_MAX * sizeof(uint8_t), false, true);
+ memcpy(self->scan_response_data, scan_response_data_bufinfo->buf, scan_response_data_bufinfo->len);
+
+
+ ble_gap_adv_params_t adv_params = {
+ .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS),
+ .properties.type = connectable ? BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED
+ : BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED,
+ .duration = BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED,
+ .filter_policy = BLE_GAP_ADV_FP_ANY,
+ .primary_phy = BLE_GAP_PHY_1MBPS,
+ };
+
+ common_hal_bleio_peripheral_stop_advertising(self);
+
+ const ble_gap_adv_data_t ble_gap_adv_data = {
+ .adv_data.p_data = self->advertising_data,
+ .adv_data.len = advertising_data_bufinfo->len,
+ .scan_rsp_data.p_data = scan_response_data_bufinfo-> len > 0 ? self->scan_response_data : NULL,
+ .scan_rsp_data.len = scan_response_data_bufinfo->len,
+ };
+
+ err_code = sd_ble_gap_adv_set_configure(&self->adv_handle, &ble_gap_adv_data, &adv_params);
+ if (err_code != NRF_SUCCESS) {
+ mp_raise_OSError_msg_varg(translate("Failed to configure advertising, err 0x%04x"), err_code);
+ }
+
+ err_code = sd_ble_gap_adv_start(self->adv_handle, BLE_CONN_CFG_TAG_CUSTOM);
+
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Failed to start advertising, err 0x%04x"), err_code);
}
}
void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) {
-
- if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
+ if (self->adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET)
return;
- const uint32_t err_code = sd_ble_gap_adv_stop(m_adv_handle);
+ const uint32_t err_code = sd_ble_gap_adv_stop(self->adv_handle);
if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_INVALID_STATE)) {
mp_raise_OSError_msg_varg(translate("Failed to stop advertising, err 0x%04x"), err_code);
}
}
+
+void common_hal_bleio_peripheral_disconnect(bleio_peripheral_obj_t *self) {
+ sd_ble_gap_disconnect(self->conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
+}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h
index b255fe9f4..2a1251715 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.h
+++ b/ports/nrf/common-hal/bleio/Peripheral.h
@@ -3,8 +3,8 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
- * Copyright (c) 2018 Dan Halbert for Adafruit Industries
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,13 +25,16 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
-#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H
#include <stdbool.h>
#include "ble.h"
+#include "py/obj.h"
+#include "py/objlist.h"
+
#include "shared-module/bleio/__init__.h"
#include "shared-module/bleio/Address.h"
@@ -40,14 +43,14 @@ typedef struct {
mp_obj_t name;
gatt_role_t gatt_role;
volatile uint16_t conn_handle;
- mp_obj_t service_list;
- mp_obj_t notif_handler;
- mp_obj_t conn_handler;
- // The advertising data buffer is held by us, not by the SD, so we must
- // maintain it and not change it. If we need to change its contents during advertising,
+ mp_obj_list_t *service_list;
+ // The advertising data and scan response buffers are held by us, not by the SD, so we must
+ // maintain them and not change it. If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
- uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];
+ uint8_t* advertising_data;
+ uint8_t* scan_response_data;
+ uint8_t adv_handle;
} bleio_peripheral_obj_t;
-#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_PERIPHERAL_H
diff --git a/ports/nrf/common-hal/bleio/Scanner.c b/ports/nrf/common-hal/bleio/Scanner.c
index d2e19b5f9..57ce940ab 100644
--- a/ports/nrf/common-hal/bleio/Scanner.c
+++ b/ports/nrf/common-hal/bleio/Scanner.c
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
@@ -30,22 +31,21 @@
#include "ble_drv.h"
#include "ble_gap.h"
#include "py/mphal.h"
+#include "py/objlist.h"
#include "py/runtime.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"
-#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) {
+STATIC void scanner_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;
@@ -53,56 +53,53 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *scanner_in) {
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;
- entry->address.type = report->peer_addr.addr_type;
- memcpy(entry->address.value, report->peer_addr.addr, BLEIO_ADDRESS_BYTES);
+ bleio_address_obj_t *address = m_new_obj(bleio_address_obj_t);
+ address->base.type = &bleio_address_type;
+ common_hal_bleio_address_construct(MP_OBJ_TO_PTR(address),
+ report->peer_addr.addr, report->peer_addr.addr_type);
+ entry->address = address;
-#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
+ entry->data = mp_obj_new_bytes(report->data.p_data, report->data.len);
- mp_obj_list_append(scanner->adv_reports, entry);
+ mp_obj_list_append(scanner->scan_entries, MP_OBJ_FROM_PTR(entry));
-#if (BLUETOOTH_SD == 140)
const uint32_t err_code = sd_ble_gap_scan_start(NULL, &m_scan_buffer);
if (err_code != NRF_SUCCESS) {
mp_raise_OSError_msg_varg(translate("Failed to continue scanning, err 0x%04x"), err_code);
}
-#endif
}
-void common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_int_t timeout) {
- ble_drv_add_event_handler(on_ble_evt, self);
+void common_hal_bleio_scanner_construct(bleio_scanner_obj_t *self) {
+}
+
+mp_obj_t common_hal_bleio_scanner_scan(bleio_scanner_obj_t *self, mp_float_t timeout, mp_float_t interval, mp_float_t window) {
+ common_hal_bleio_adapter_set_enabled(true);
+ ble_drv_add_event_handler(scanner_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)
+ .interval = SEC_TO_UNITS(interval, UNIT_0_625_MS),
+ .window = SEC_TO_UNITS(window, UNIT_0_625_MS),
.scan_phys = BLE_GAP_PHY_1MBPS,
-#endif
};
- common_hal_bleio_adapter_set_enabled(true);
+ self->scan_entries = mp_obj_new_list(0, NULL);
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) {
mp_raise_OSError_msg_varg(translate("Failed to start scanning, err 0x%04x"), err_code);
}
- if (timeout > 0) {
- mp_hal_delay_ms(timeout);
- sd_ble_gap_scan_stop();
- }
+ mp_hal_delay_ms(timeout * 1000);
+ sd_ble_gap_scan_stop();
+
+ // Return list, and don't hang on to it, so it can be GC'd.
+ mp_obj_t entries = self->scan_entries;
+ self->scan_entries = MP_OBJ_NULL;
+ return entries;
}
diff --git a/ports/nrf/common-hal/bleio/Scanner.h b/ports/nrf/common-hal/bleio/Scanner.h
new file mode 100644
index 000000000..3768a52cb
--- /dev/null
+++ b/ports/nrf/common-hal/bleio/Scanner.h
@@ -0,0 +1,40 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H
+
+#include "py/obj.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ mp_obj_t scan_entries;
+ uint16_t interval;
+ uint16_t window;
+} bleio_scanner_obj_t;
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SCANNER_H
diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c
index 26a1f1cff..b6fcde827 100644
--- a/ports/nrf/common-hal/bleio/Service.c
+++ b/ports/nrf/common-hal/bleio/Service.c
@@ -3,6 +3,7 @@
*
* The MIT License (MIT)
*
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,18 +30,43 @@
#include "py/runtime.h"
#include "common-hal/bleio/__init__.h"
#include "common-hal/bleio/Characteristic.h"
+#include "shared-bindings/bleio/Characteristic.h"
#include "shared-bindings/bleio/Service.h"
#include "shared-bindings/bleio/Adapter.h"
-void common_hal_bleio_service_construct(bleio_service_obj_t *self) {
+void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_obj_t *uuid, mp_obj_list_t *characteristic_list, bool is_secondary) {
+ self->device = mp_const_none;
+ self->handle = 0xFFFF;
+ self->uuid = uuid;
+ self->characteristic_list = characteristic_list;
+ self->is_secondary = is_secondary;
+
+ for (size_t characteristic_idx = 0; characteristic_idx < characteristic_list->len; ++characteristic_idx) {
+ bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(characteristic_list->items[characteristic_idx]);
+ characteristic->service = self;
+ }
+
+}
+
+bleio_uuid_obj_t *common_hal_bleio_service_get_uuid(bleio_service_obj_t *self) {
+ return self->uuid;
+}
+
+mp_obj_list_t *common_hal_bleio_service_get_characteristic_list(bleio_service_obj_t *self) {
+ return self->characteristic_list;
+}
+
+bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
+ return self->is_secondary;
}
// Call this after the Service has been added to the Peripheral.
void common_hal_bleio_service_add_all_characteristics(bleio_service_obj_t *self) {
// Add all the characteristics.
- const mp_obj_list_t *char_list = MP_OBJ_TO_PTR(self->char_list);
- for (size_t char_idx = 0; char_idx < char_list->len; ++char_idx) {
- bleio_characteristic_obj_t *characteristic = char_list->items[char_idx];
+ for (size_t characteristic_idx = 0; characteristic_idx < self->characteristic_list->len; ++characteristic_idx) {
+ bleio_characteristic_obj_t *characteristic =
+ MP_OBJ_TO_PTR(self->characteristic_list->items[characteristic_idx]);
ble_gatts_char_md_t char_md = {
.char_props.broadcast = characteristic->props.broadcast,
diff --git a/ports/nrf/common-hal/bleio/Service.h b/ports/nrf/common-hal/bleio/Service.h
new file mode 100644
index 000000000..583593fb8
--- /dev/null
+++ b/ports/nrf/common-hal/bleio/Service.h
@@ -0,0 +1,48 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
+ * Copyright (c) 2018 Artur Pacholec
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H
+
+#include "py/objlist.h"
+#include "common-hal/bleio/UUID.h"
+
+typedef struct {
+ mp_obj_base_t base;
+ // Handle for this service.
+ uint16_t handle;
+ bool is_secondary;
+ bleio_uuid_obj_t *uuid;
+ // May be a Peripheral, Central, etc.
+ mp_obj_t device;
+ mp_obj_list_t *characteristic_list;
+ // Range of attribute handles of this service.
+ uint16_t start_handle;
+ uint16_t end_handle;
+} bleio_service_obj_t;
+
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_SERVICE_H
diff --git a/ports/nrf/common-hal/bleio/UUID.c b/ports/nrf/common-hal/bleio/UUID.c
index 23e643433..ebd6b6d1f 100644
--- a/ports/nrf/common-hal/bleio/UUID.c
+++ b/ports/nrf/common-hal/bleio/UUID.c
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
diff --git a/ports/nrf/common-hal/bleio/UUID.h b/ports/nrf/common-hal/bleio/UUID.h
index b464093ea..7d3a6204e 100644
--- a/ports/nrf/common-hal/bleio/UUID.h
+++ b/ports/nrf/common-hal/bleio/UUID.h
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c
index cfb701019..2dba5780c 100644
--- a/ports/nrf/common-hal/bleio/__init__.c
+++ b/ports/nrf/common-hal/bleio/__init__.c
@@ -3,8 +3,9 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Glenn Ruben Bakke
+ * Copyright (c) 2018 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2016 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
@@ -27,6 +28,7 @@
#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Adapter.h"
+#include "shared-bindings/bleio/Central.h"
#include "shared-bindings/bleio/Peripheral.h"
#include "common-hal/bleio/__init__.h"
@@ -48,9 +50,8 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = {
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
-// Does not exist yet.
-// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
-// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
+ } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
+ return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->gatt_role;
} else {
return GATT_ROLE_NONE;
}
@@ -59,9 +60,8 @@ gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device) {
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) {
if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) {
return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
-// Does not exist yet.
-// } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
-// return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
+ } else if (MP_OBJ_IS_TYPE(device, &bleio_central_type)) {
+ return ((bleio_central_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle;
} else {
return 0;
}
diff --git a/ports/nrf/common-hal/bleio/__init__.h b/ports/nrf/common-hal/bleio/__init__.h
index 9e044f37c..0c46b631f 100644
--- a/ports/nrf/common-hal/bleio/__init__.h
+++ b/ports/nrf/common-hal/bleio/__init__.h
@@ -24,8 +24,8 @@
* THE SOFTWARE.
*/
-#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
-#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
+#ifndef MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
+#define MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
#include "shared-bindings/bleio/__init__.h"
#include "shared-bindings/bleio/Adapter.h"
@@ -39,4 +39,4 @@
gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device);
uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device);
-#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H
+#endif // MICROPY_INCLUDED_NRF_COMMON_HAL_BLEIO_INIT_H
diff --git a/ports/nrf/common-hal/busio/I2C.c b/ports/nrf/common-hal/busio/I2C.c
index 05106d490..538c87f2d 100644
--- a/ports/nrf/common-hal/busio/I2C.c
+++ b/ports/nrf/common-hal/busio/I2C.c
@@ -3,9 +3,10 @@
*
* The MIT License (MIT)
*
- * Copyright (c) 2016 Sandeep Mistry All right reserved.
- * Copyright (c) 2017 hathach
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 hathach
+ * Copyright (c) 2016 Sandeep Mistry All right reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
diff --git a/ports/nrf/common-hal/busio/SPI.c b/ports/nrf/common-hal/busio/SPI.c
index 8881bdc6b..6ab6d9493 100644
--- a/ports/nrf/common-hal/busio/SPI.c
+++ b/ports/nrf/common-hal/busio/SPI.c
@@ -1,9 +1,11 @@
/*
* SPI Master library for nRF5x.
- * Copyright (c) 2015 Arduino LLC
- * Copyright (c) 2016 Sandeep Mistry All right reserved.
- * Copyright (c) 2017 hathach
+ *
+ * Copyright (c) 2019 Dan Halbert for Adafruit Industries
* Copyright (c) 2018 Artur Pacholec
+ * Copyright (c) 2017 hathach
+ * Copyright (c) 2016 Sandeep Mistry All right reserved.
+ * Copyright (c) 2015 Arduino LLC
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public