3535#include "common-hal/bleio/__init__.h"
3636#include "shared-module/bleio/Characteristic.h"
3737
38-
38+ // TODO - should these be per object?? *****
3939STATIC volatile bleio_characteristic_obj_t * m_read_characteristic ;
4040STATIC volatile uint8_t m_tx_in_progress ;
4141STATIC nrf_mutex_t * m_write_mutex ;
4242
43+ STATIC uint16_t get_cccd (bleio_characteristic_obj_t * characteristic ) {
44+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle (characteristic -> service -> device );
45+ uint16_t cccd ;
46+ ble_gatts_value_t value = {
47+ .p_value = (uint8_t * ) & cccd ,
48+ .len = 2 ,
49+ };
50+
51+ const uint32_t err_code = sd_ble_gatts_value_get (conn_handle , characteristic -> cccd_handle , & value );
52+
53+
54+ if (err_code == BLE_ERROR_GATTS_SYS_ATTR_MISSING ) {
55+ // CCCD is not set, so say that neither Notify nor Indicate is enabled.
56+ cccd = 0 ;
57+ } else if (err_code != NRF_SUCCESS ) {
58+ mp_raise_OSError_msg_varg (translate ("Failed to read CCD value, err 0x%04x" ), err_code );
59+ }
60+
61+ return cccd ;
62+ }
63+
64+ STATIC void gatts_read (bleio_characteristic_obj_t * characteristic ) {
65+ // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
66+ // we can still read and write the local value.
67+ const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle (characteristic -> service -> device );
68+
69+ mp_buffer_info_t bufinfo ;
70+ ble_gatts_value_t gatts_value = {
71+ .p_value = NULL ,
72+ .len = 0 ,
73+ };
74+
75+ // Read once to find out what size buffer we need, then read again to fill buffer.
76+
77+ uint32_t err_code = sd_ble_gatts_value_get (conn_handle , characteristic -> handle , & gatts_value );
78+ if (err_code == NRF_SUCCESS ) {
79+ characteristic -> value_data = mp_obj_new_bytearray_of_zeros (gatts_value .len );
80+ mp_get_buffer_raise (characteristic -> value_data , & bufinfo , MP_BUFFER_WRITE );
81+
82+ // Read again, with the correct size of buffer.
83+ err_code = sd_ble_gatts_value_get (conn_handle , characteristic -> handle , & gatts_value );
84+ }
85+
86+ if (err_code != NRF_SUCCESS ) {
87+ mp_raise_OSError_msg_varg (translate ("Failed to read gatts value, err 0x%04x" ), err_code );
88+ }
89+ }
90+
4391
4492STATIC void gatts_write (bleio_characteristic_obj_t * characteristic , mp_buffer_info_t * bufinfo ) {
93+ // This might be BLE_CONN_HANDLE_INVALID if we're not conected, but that's OK, because
94+ // we can still read and write the local value.
4595 const uint16_t conn_handle = common_hal_bleio_device_get_conn_handle (characteristic -> service -> device );
4696
4797 ble_gatts_value_t gatts_value = {
@@ -55,12 +105,12 @@ STATIC void gatts_write(bleio_characteristic_obj_t *characteristic, mp_buffer_in
55105 }
56106}
57107
58- STATIC void gatts_notify (bleio_characteristic_obj_t * characteristic , mp_buffer_info_t * bufinfo ) {
108+ STATIC void gatts_notify_indicate (bleio_characteristic_obj_t * characteristic , mp_buffer_info_t * bufinfo , uint16_t hvx_type ) {
59109 uint16_t hvx_len = bufinfo -> len ;
60110
61111 ble_gatts_hvx_params_t hvx_params = {
62112 .handle = characteristic -> handle ,
63- .type = BLE_GATT_HVX_NOTIFICATION ,
113+ .type = hvx_type ,
64114 .offset = 0 ,
65115 .p_len = & hvx_len ,
66116 .p_data = bufinfo -> buf ,
@@ -163,30 +213,46 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self)
163213 ble_drv_add_event_handler (on_ble_evt , NULL );
164214}
165215
166- void common_hal_bleio_characteristic_read_value (bleio_characteristic_obj_t * self ) {
216+ void common_hal_bleio_characteristic_get_value (bleio_characteristic_obj_t * self ) {
167217 switch (common_hal_bleio_device_get_gatt_role (self -> service -> device )) {
168218 case GATT_ROLE_CLIENT :
169219 gattc_read (self );
170220 break ;
171221
222+ case GATT_ROLE_SERVER :
223+ gatts_read (self );
224+ break ;
225+
172226 default :
173227 mp_raise_RuntimeError (translate ("bad GATT role" ));
174228 break ;
175229 }
176230}
177231
178- void common_hal_bleio_characteristic_write_value (bleio_characteristic_obj_t * self , mp_buffer_info_t * bufinfo ) {
232+ void common_hal_bleio_characteristic_set_value (bleio_characteristic_obj_t * self , mp_buffer_info_t * bufinfo ) {
233+ bool sent = false;
234+ uint16_t cccd = 0 ;
235+
179236 switch (common_hal_bleio_device_get_gatt_role (self -> service -> device )) {
180237 case GATT_ROLE_SERVER :
181- if (self -> props .notify ) {
182- gatts_notify (self , bufinfo );
183- } else {
238+ if (self -> props .notify || self -> props .indicate ) {
239+ cccd = get_cccd (self );
240+ }
241+ // It's possible that both notify and indicate are set.
242+ if (self -> props .notify && (cccd & BLE_GATT_HVX_NOTIFICATION )) {
243+ gatts_notify_indicate (self , bufinfo , BLE_GATT_HVX_NOTIFICATION );
244+ sent = true;
245+ }
246+ if (self -> props .indicate && (cccd & BLE_GATT_HVX_INDICATION )) {
247+ gatts_notify_indicate (self , bufinfo , BLE_GATT_HVX_INDICATION );
248+ sent = true;
249+ }
250+ if (!sent ) {
184251 gatts_write (self , bufinfo );
185252 }
186253 break ;
187254
188255 case GATT_ROLE_CLIENT :
189- // TODO: Add indications
190256 gattc_write (self , bufinfo );
191257 break ;
192258
0 commit comments