summaryrefslogtreecommitdiff
path: root/ports
diff options
context:
space:
mode:
authorDan Halbert <halbert@halwitz.org>2019-07-09 00:21:46 -0400
committerDan Halbert <halbert@halwitz.org>2019-07-09 00:21:46 -0400
commit118b26b335c7153eeb4847e04019cdc0829ca960 (patch)
treeed771061cbba183ee8421b59c8008aa001ba391c /ports
parent09ddff8df1349c590e6c0533b6f5085fbcb92483 (diff)
UARTClient now works both directions
Diffstat (limited to 'ports')
-rw-r--r--ports/nrf/common-hal/bleio/Central.c59
-rw-r--r--ports/nrf/common-hal/bleio/Characteristic.c53
-rw-r--r--ports/nrf/common-hal/bleio/Descriptor.c4
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.c4
-rw-r--r--ports/nrf/common-hal/bleio/Peripheral.h1
-rw-r--r--ports/nrf/common-hal/bleio/Service.c6
6 files changed, 97 insertions, 30 deletions
diff --git a/ports/nrf/common-hal/bleio/Central.c b/ports/nrf/common-hal/bleio/Central.c
index f7077f4b9..d90737411 100644
--- a/ports/nrf/common-hal/bleio/Central.c
+++ b/ports/nrf/common-hal/bleio/Central.c
@@ -97,7 +97,7 @@ STATIC bool discover_next_descriptors(bleio_central_obj_t *self, bleio_character
m_discovery_successful = false;
m_discovery_in_process = true;
- uint32_t err_code = sd_ble_gattc_characteristics_discover(self->conn_handle, &handle_range);
+ uint32_t err_code = sd_ble_gattc_descriptors_discover(self->conn_handle, &handle_range);
if (err_code != NRF_SUCCESS) {
return false;
}
@@ -116,8 +116,10 @@ STATIC void on_primary_srv_discovery_rsp(ble_gattc_evt_prim_srvc_disc_rsp_t *res
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->characteristic_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;
@@ -152,6 +154,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio
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) {
@@ -174,8 +178,8 @@ STATIC void on_char_discovery_rsp(ble_gattc_evt_char_disc_rsp_t *response, bleio
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 set up evt handler.
- common_hal_bleio_characteristic_construct(characteristic, uuid, props);
+ // 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;
@@ -192,6 +196,27 @@ STATIC void on_desc_discovery_rsp(ble_gattc_evt_desc_disc_rsp_t *response, bleio
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;
@@ -251,6 +276,7 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
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);
@@ -265,7 +291,7 @@ STATIC void central_on_ble_evt(ble_evt_t *ble_evt, void *central_in) {
default:
// For debugging.
- mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
+ // mp_printf(&mp_plat_print, "Unhandled central event: 0x%04x\n", ble_evt->header.evt_id);
break;
}
}
@@ -330,13 +356,13 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
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.
+ // 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;
+ // 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;
@@ -384,10 +410,11 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
}
// Got characteristics for this service. Now discover descriptors for each characteristic.
- for (size_t char_idx = 0; char_idx < service->characteristic_list->len; ++char_idx) {
+ 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 == service->characteristic_list->len - 1;
+ 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]);
@@ -402,13 +429,15 @@ void common_hal_bleio_central_connect(bleio_central_obj_t *self, bleio_address_o
// 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;
+ : 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 &&
- discover_next_descriptors(self, characteristic, next_desc_start_handle, next_desc_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.
diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c
index 1db0a9378..17417a5e6 100644
--- a/ports/nrf/common-hal/bleio/Characteristic.c
+++ b/ports/nrf/common-hal/bleio/Characteristic.c
@@ -162,7 +162,6 @@ STATIC void gattc_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in
check_connected(conn_handle);
ble_gattc_write_params_t write_params = {
- .flags = BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL,
.write_op = characteristic->props.write_no_response ? BLE_GATT_OP_WRITE_CMD : BLE_GATT_OP_WRITE_REQ,
.handle = characteristic->handle,
.p_value = bufinfo->buf,
@@ -210,19 +209,19 @@ STATIC void characteristic_on_ble_evt(ble_evt_t *ble_evt, void *param) {
}
-void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self, bleio_uuid_obj_t *uuid, bleio_characteristic_properties_t props) {
+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 = 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);
-
}
-void common_hal_bleio_characteristic_set_service(bleio_characteristic_obj_t *self, bleio_service_obj_t *service) {
- self->service = service;
+mp_obj_list_t *common_hal_bleio_characteristic_get_descriptor_list(bleio_characteristic_obj_t *self) {
+ return self->descriptor_list;
}
mp_obj_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *self) {
@@ -284,3 +283,47 @@ bleio_uuid_obj_t *common_hal_bleio_characteristic_get_uuid(bleio_characteristic_
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;
+ }
+
+ // Write with response will return NRF_ERROR_BUSY if the response has not been received.
+ // Write without reponse will return NRF_ERROR_RESOURCES if too many writes are pending.
+ if (err_code == NRF_ERROR_BUSY || err_code == NRF_ERROR_RESOURCES) {
+ // We could wait for an event indicating the write is complete, but just retrying is easier.
+ MICROPY_VM_HOOK_LOOP;
+ continue;
+ }
+
+ // Some real error occurred.
+ mp_raise_OSError_msg_varg(translate("Failed to write CCCD, err 0x%04x"), err_code);
+ }
+
+}
diff --git a/ports/nrf/common-hal/bleio/Descriptor.c b/ports/nrf/common-hal/bleio/Descriptor.c
index d3f2a0ff8..005af6eaa 100644
--- a/ports/nrf/common-hal/bleio/Descriptor.c
+++ b/ports/nrf/common-hal/bleio/Descriptor.c
@@ -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/Peripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c
index b31bb84b0..608bd1342 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.c
+++ b/ports/nrf/common-hal/bleio/Peripheral.c
@@ -135,13 +135,13 @@ void common_hal_bleio_peripheral_construct(bleio_peripheral_obj_t *self, mp_obj_
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]);
- common_hal_bleio_service_set_device(service, MP_OBJ_FROM_PTR(self));
+ 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;
}
diff --git a/ports/nrf/common-hal/bleio/Peripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h
index 725bc1431..2a1251715 100644
--- a/ports/nrf/common-hal/bleio/Peripheral.h
+++ b/ports/nrf/common-hal/bleio/Peripheral.h
@@ -44,7 +44,6 @@ typedef struct {
gatt_role_t gatt_role;
volatile uint16_t conn_handle;
mp_obj_list_t *service_list;
- mp_obj_t conn_handler;
// The advertising data and scan response buffers are held by us, not by the SD, so we must
// maintain them and not change it. If we need to change the contents during advertising,
// there are tricks to get the SD to notice (see DevZone - TBS).
diff --git a/ports/nrf/common-hal/bleio/Service.c b/ports/nrf/common-hal/bleio/Service.c
index 9939de775..b6fcde827 100644
--- a/ports/nrf/common-hal/bleio/Service.c
+++ b/ports/nrf/common-hal/bleio/Service.c
@@ -44,7 +44,7 @@ void common_hal_bleio_service_construct(bleio_service_obj_t *self, bleio_uuid_ob
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]);
- common_hal_bleio_characteristic_set_service(characteristic, self);
+ characteristic->service = self;
}
}
@@ -61,10 +61,6 @@ bool common_hal_bleio_service_get_is_secondary(bleio_service_obj_t *self) {
return self->is_secondary;
}
-void common_hal_bleio_service_set_device(bleio_service_obj_t *self, mp_obj_t device) {
- self->device = device;
-}
-
// 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.