diff options
| author | Dan Halbert <halbert@halwitz.org> | 2018-12-30 22:31:51 -0500 |
|---|---|---|
| committer | Dan Halbert <halbert@halwitz.org> | 2018-12-30 22:33:49 -0500 |
| commit | 1dc3957e729a7bf4d6476c587f140e3d42fd1bd5 (patch) | |
| tree | 857c9a490c17f53884c791726570ffb36df52558 /ports | |
| parent | ef39e72c7c3c3e68f73f670b7f8b7f08e813be39 (diff) | |
LocalPeripheral is now Peripheral; more work on basic GATTS support; UART not working yet
Diffstat (limited to 'ports')
| -rw-r--r-- | ports/nrf/common-hal/bleio/Characteristic.c | 84 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Peripheral.c (renamed from ports/nrf/common-hal/bleio/LocalPeripheral.c) | 24 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/Peripheral.h (renamed from ports/nrf/common-hal/bleio/LocalPeripheral.h) | 19 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/__init__.c | 23 | ||||
| -rw-r--r-- | ports/nrf/common-hal/bleio/__init__.h | 1 |
5 files changed, 117 insertions, 34 deletions
diff --git a/ports/nrf/common-hal/bleio/Characteristic.c b/ports/nrf/common-hal/bleio/Characteristic.c index 17656c269..7a32e4928 100644 --- a/ports/nrf/common-hal/bleio/Characteristic.c +++ b/ports/nrf/common-hal/bleio/Characteristic.c @@ -35,13 +35,63 @@ #include "common-hal/bleio/__init__.h" #include "shared-module/bleio/Characteristic.h" - +// TODO - should these be per object?? ***** STATIC volatile bleio_characteristic_obj_t *m_read_characteristic; STATIC volatile uint8_t m_tx_in_progress; STATIC nrf_mutex_t *m_write_mutex; +STATIC uint16_t get_cccd(bleio_characteristic_obj_t *characteristic) { + const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); + uint16_t cccd; + ble_gatts_value_t value = { + .p_value = (uint8_t*) &cccd, + .len = 2, + }; + + const uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->cccd_handle, &value); + + + if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING) { + // CCCD is not set, so say that neither Notify nor Indicate is enabled. + cccd = 0; + } else if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read CCD value, err 0x%04x"), err_code); + } + + return cccd; +} + +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 + // we can still read and write the local value. + const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); + + mp_buffer_info_t bufinfo; + ble_gatts_value_t gatts_value = { + .p_value = NULL, + .len = 0, + }; + + // Read once to find out what size buffer we need, then read again to fill buffer. + + uint32_t err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value); + if (err_code == NRF_SUCCESS) { + characteristic->value_data = mp_obj_new_bytearray_of_zeros(gatts_value.len); + mp_get_buffer_raise(characteristic->value_data, &bufinfo, MP_BUFFER_WRITE); + + // Read again, with the correct size of buffer. + err_code = sd_ble_gatts_value_get(conn_handle, characteristic->handle, &gatts_value); + } + + if (err_code != NRF_SUCCESS) { + mp_raise_OSError_msg_varg(translate("Failed to read gatts value, err 0x%04x"), err_code); + } +} + STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { + // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because + // we can still read and write the local value. const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle(characteristic->service->device); ble_gatts_value_t gatts_value = { @@ -55,12 +105,12 @@ STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in } } -STATIC void gatts_notify(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo) { +STATIC void gatts_notify_indicate(bleio_characteristic_obj_t *characteristic, mp_buffer_info_t *bufinfo, uint16_t hvx_type) { uint16_t hvx_len = bufinfo->len; ble_gatts_hvx_params_t hvx_params = { .handle = characteristic->handle, - .type = BLE_GATT_HVX_NOTIFICATION, + .type = hvx_type, .offset = 0, .p_len = &hvx_len, .p_data = bufinfo->buf, @@ -163,30 +213,46 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self) ble_drv_add_event_handler(on_ble_evt, NULL); } -void common_hal_bleio_characteristic_read_value(bleio_characteristic_obj_t *self) { +void 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); break; + case GATT_ROLE_SERVER: + gatts_read(self); + break; + default: mp_raise_RuntimeError(translate("bad GATT role")); break; } } -void common_hal_bleio_characteristic_write_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { +void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self, mp_buffer_info_t *bufinfo) { + bool sent = false; + uint16_t cccd = 0; + switch (common_hal_bleio_device_get_gatt_role(self->service->device)) { case GATT_ROLE_SERVER: - if (self->props.notify) { - gatts_notify(self, bufinfo); - } else { + 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: - // TODO: Add indications gattc_write(self, bufinfo); break; diff --git a/ports/nrf/common-hal/bleio/LocalPeripheral.c b/ports/nrf/common-hal/bleio/Peripheral.c index 2a502c8dd..d2eef596d 100644 --- a/ports/nrf/common-hal/bleio/LocalPeripheral.c +++ b/ports/nrf/common-hal/bleio/Peripheral.c @@ -4,6 +4,7 @@ * The MIT License (MIT) * * 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 @@ -35,7 +36,7 @@ #include "py/runtime.h" #include "shared-bindings/bleio/Adapter.h" #include "shared-bindings/bleio/Characteristic.h" -#include "shared-bindings/bleio/LocalPeripheral.h" +#include "shared-bindings/bleio/Peripheral.h" #include "shared-bindings/bleio/Service.h" #include "shared-bindings/bleio/UUID.h" @@ -56,7 +57,7 @@ STATIC void check_data_fit(size_t pos, size_t data_len) { } } -STATIC uint32_t add_services_to_advertisement(bleio_local_peripheral_obj_t *self, size_t* adv_data_pos_p, size_t uuid_len) { +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; @@ -99,7 +100,7 @@ STATIC uint32_t add_services_to_advertisement(bleio_local_peripheral_obj_t *self -STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) { +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; @@ -203,7 +204,7 @@ STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool m_adv_params.properties.type = BLE_GAP_ADV_TYPE_NONCONNECTABLE_NONSCANNABLE_UNDIRECTED; } - common_hal_bleio_local_peripheral_stop_advertising(self); + common_hal_bleio_peripheral_stop_advertising(self); const ble_gap_adv_data_t ble_gap_adv_data = { .adv_data.p_data = self->adv_data, @@ -221,7 +222,7 @@ STATIC uint32_t set_advertisement_data(bleio_local_peripheral_obj_t *self, bool } STATIC void on_ble_evt(ble_evt_t *ble_evt, void *self_in) { - bleio_local_peripheral_obj_t *self = (bleio_local_peripheral_obj_t*)self_in; + bleio_peripheral_obj_t *self = (bleio_peripheral_obj_t*)self_in; switch (ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: { @@ -266,14 +267,17 @@ STATIC void on_ble_evt(ble_evt_t *ble_evt, void *self_in) { break; } + default: + mp_printf(&mp_plat_print, "Unhandled event: 0x%04x\n", ble_evt->header.evt_id); + break; } } -void common_hal_bleio_local_peripheral_construct(bleio_local_peripheral_obj_t *self) { +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->gatt_role = GATT_ROLE_NONE; + self->gatt_role = GATT_ROLE_SERVER; self->conn_handle = BLE_CONN_HANDLE_INVALID; // Add all the services. @@ -301,11 +305,11 @@ void common_hal_bleio_local_peripheral_construct(bleio_local_peripheral_obj_t *s } -bool common_hal_bleio_local_peripheral_get_connected(bleio_local_peripheral_obj_t *self) { +bool common_hal_bleio_peripheral_get_connected(bleio_peripheral_obj_t *self) { return self->conn_handle != BLE_CONN_HANDLE_INVALID; } -void common_hal_bleio_local_peripheral_start_advertising(bleio_local_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) { +void common_hal_bleio_peripheral_start_advertising(bleio_peripheral_obj_t *self, bool connectable, mp_buffer_info_t *raw_data) { if (connectable) { ble_drv_add_event_handler(on_ble_evt, self); } @@ -316,7 +320,7 @@ void common_hal_bleio_local_peripheral_start_advertising(bleio_local_peripheral_ } } -void common_hal_bleio_local_peripheral_stop_advertising(bleio_local_peripheral_obj_t *self) { +void common_hal_bleio_peripheral_stop_advertising(bleio_peripheral_obj_t *self) { if (m_adv_handle == BLE_GAP_ADV_SET_HANDLE_NOT_SET) return; diff --git a/ports/nrf/common-hal/bleio/LocalPeripheral.h b/ports/nrf/common-hal/bleio/Peripheral.h index 8d84867ae..b255fe9f4 100644 --- a/ports/nrf/common-hal/bleio/LocalPeripheral.h +++ b/ports/nrf/common-hal/bleio/Peripheral.h @@ -25,8 +25,8 @@ * THE SOFTWARE. */ -#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H -#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H +#ifndef MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H +#define MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H #include <stdbool.h> @@ -35,17 +35,6 @@ #include "shared-module/bleio/__init__.h" #include "shared-module/bleio/Address.h" -// typedef struct { -// mp_obj_base_t base; -// bool is_peripheral; -// mp_obj_t name; -// bleio_address_obj_t address; -// volatile uint16_t conn_handle; -// mp_obj_t service_list; -// mp_obj_t notif_handler; -// mp_obj_t conn_handler; -// } bleio_device_obj_t; - typedef struct { mp_obj_base_t base; mp_obj_t name; @@ -59,6 +48,6 @@ typedef struct { // there are tricks to get the SD to notice (see DevZone - TBS). uint8_t adv_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX]; -} bleio_local_peripheral_obj_t; +} bleio_peripheral_obj_t; -#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_LOCALPERIPHERAL_H +#endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_PERIPHERAL_H diff --git a/ports/nrf/common-hal/bleio/__init__.c b/ports/nrf/common-hal/bleio/__init__.c index 9429aaf44..cfb701019 100644 --- a/ports/nrf/common-hal/bleio/__init__.c +++ b/ports/nrf/common-hal/bleio/__init__.c @@ -27,6 +27,7 @@ #include "shared-bindings/bleio/__init__.h" #include "shared-bindings/bleio/Adapter.h" +#include "shared-bindings/bleio/Peripheral.h" #include "common-hal/bleio/__init__.h" // Turn off BLE on a reset or reload. @@ -43,3 +44,25 @@ const super_adapter_obj_t common_hal_bleio_adapter_obj = { .type = &bleio_adapter_type, }, }; + +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 { + return GATT_ROLE_NONE; + } +} + +uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device) { + if (MP_OBJ_IS_TYPE(device, &bleio_peripheral_type)) { + return ((bleio_peripheral_obj_t*) MP_OBJ_TO_PTR(device))->conn_handle; +// 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 { + return 0; + } +} diff --git a/ports/nrf/common-hal/bleio/__init__.h b/ports/nrf/common-hal/bleio/__init__.h index aed5df5e7..9e044f37c 100644 --- a/ports/nrf/common-hal/bleio/__init__.h +++ b/ports/nrf/common-hal/bleio/__init__.h @@ -36,6 +36,7 @@ // 20 bytes max (23 - 3). #define GATT_MAX_DATA_LENGTH (BLE_GATT_ATT_MTU_DEFAULT - 3) +gatt_role_t common_hal_bleio_device_get_gatt_role(mp_obj_t device); uint16_t common_hal_bleio_device_get_conn_handle(mp_obj_t device); #endif // MICROPY_INCLUDED_COMMON_HAL_BLEIO_INIT_H |
