7
7
#include <string.h>
8
8
9
9
#include "py/runtime.h"
10
+ #include "shared/runtime/interrupt_char.h"
10
11
11
12
#include "shared-bindings/_bleio/__init__.h"
12
13
#include "shared-bindings/_bleio/Characteristic.h"
13
14
#include "shared-bindings/_bleio/CharacteristicBuffer.h"
14
15
#include "shared-bindings/_bleio/Descriptor.h"
15
16
#include "shared-bindings/_bleio/PacketBuffer.h"
16
17
#include "shared-bindings/_bleio/Service.h"
18
+ #include "shared-bindings/time/__init__.h"
17
19
18
20
#include "common-hal/_bleio/Adapter.h"
19
21
#include "common-hal/_bleio/Service.h"
20
22
21
-
22
23
static int characteristic_on_ble_gap_evt (struct ble_gap_event * event , void * param );
23
24
25
+ static volatile int _completion_status ;
26
+
2851
static uint64_t _timeout_start_time ;
27
+
28
+ static void _reset_completion_status (void ) {
29
+ _completion_status = 0 ;
30
+ }
31
+
32
+ // Wait for a status change, recorded in a callback.
33
+ // Try twice because sometimes we get a BLE_HS_EAGAIN.
34
+ // Maybe we should try more than twice.
35
+ static int _wait_for_completion (uint32_t timeout_msecs ) {
36
+ for (int tries = 1 ; tries <= 2 ; tries ++ ) {
37
+ _timeout_start_time = common_hal_time_monotonic_ms ();
38
+ while ((_completion_status == 0 ) &&
39
+ (common_hal_time_monotonic_ms () < _timeout_start_time + timeout_msecs ) &&
40
+ !mp_hal_is_interrupted ()) {
41
+ RUN_BACKGROUND_TASKS ;
42
+ }
43
+ if (_completion_status != BLE_HS_EAGAIN ) {
44
+ // Quit, because either the status is either zero (OK) or it's an error.
45
+ break ;
46
+ }
47
+ }
48
+ return _completion_status ;
49
+ }
50
+
24
51
void common_hal_bleio_characteristic_construct (bleio_characteristic_obj_t * self , bleio_service_obj_t * service ,
25
52
uint16_t handle , bleio_uuid_obj_t * uuid , bleio_characteristic_properties_t props ,
26
53
bleio_attribute_security_mode_t read_perm , bleio_attribute_security_mode_t write_perm ,
@@ -34,7 +61,7 @@ void common_hal_bleio_characteristic_construct(bleio_characteristic_obj_t *self,
34
61
self -> props = props ;
35
62
self -> read_perm = read_perm ;
36
63
self -> write_perm = write_perm ;
37
- self -> observer = NULL ;
64
+ self -> observer = mp_const_none ;
38
65
39
66
// Map CP's property values to Nimble's flag values.
40
67
self -> flags = 0 ;
@@ -125,7 +152,6 @@ bleio_service_obj_t *common_hal_bleio_characteristic_get_service(bleio_character
125
152
}
126
153
127
154
typedef struct {
128
- TaskHandle_t task ;
129
155
uint8_t * buf ;
130
156
uint16_t len ;
131
157
} _read_info_t ;
@@ -148,9 +174,9 @@ static int _read_cb(uint16_t conn_handle,
148
174
// For debugging.
149
175
mp_printf (& mp_plat_print , "Read status: %d\n" , error -> status );
150
176
#endif
151
- xTaskNotify (read_info -> task , error -> status , eSetValueWithOverwrite );
152
177
break ;
153
178
}
179
+ _completion_status = error -> status ;
154
180
155
181
return 0 ;
156
182
}
@@ -163,14 +189,12 @@ size_t common_hal_bleio_characteristic_get_value(bleio_characteristic_obj_t *sel
163
189
uint16_t conn_handle = bleio_connection_get_conn_handle (self -> service -> connection );
164
190
if (common_hal_bleio_service_get_is_remote (self -> service )) {
165
191
_read_info_t read_info = {
166
- .task = xTaskGetCurrentTaskHandle (),
167
192
.buf = buf ,
168
193
.len = len
169
194
};
195
+ _reset_completion_status ();
170
196
CHECK_NIMBLE_ERROR (ble_gattc_read (conn_handle , self -> handle , _read_cb , & read_info ));
171
- int error_code ;
172
- xTaskNotifyWait (0 , 0 , (uint32_t * )& error_code , 200 );
173
- CHECK_BLE_ERROR (error_code );
197
+ CHECK_NIMBLE_ERROR (_wait_for_completion (2000 ));
174
198
return read_info .len ;
175
199
} else {
176
200
len = MIN (self -> current_value_len , len );
@@ -189,8 +213,7 @@ static int _write_cb(uint16_t conn_handle,
189
213
const struct ble_gatt_error * error ,
190
214
struct ble_gatt_attr * attr ,
191
215
void * arg ) {
192
- TaskHandle_t task = (TaskHandle_t )arg ;
193
- xTaskNotify (task , error -> status , eSetValueWithOverwrite );
216
+ _completion_status = error -> status ;
194
217
195
218
return 0 ;
196
219
}
@@ -201,10 +224,9 @@ void common_hal_bleio_characteristic_set_value(bleio_characteristic_obj_t *self,
201
224
if ((self -> props & CHAR_PROP_WRITE_NO_RESPONSE ) != 0 ) {
202
225
CHECK_NIMBLE_ERROR (ble_gattc_write_no_rsp_flat (conn_handle , self -> handle , bufinfo -> buf , bufinfo -> len ));
203
226
} else {
204
- CHECK_NIMBLE_ERROR (ble_gattc_write_flat (conn_handle , self -> handle , bufinfo -> buf , bufinfo -> len , _write_cb , xTaskGetCurrentTaskHandle ()));
205
- int error_code ;
206
- xTaskNotifyWait (0 , 0 , (uint32_t * )& error_code , 200 );
207
- CHECK_BLE_ERROR (error_code );
227
+ _reset_completion_status ();
228
+ CHECK_NIMBLE_ERROR (ble_gattc_write_flat (conn_handle , self -> handle , bufinfo -> buf , bufinfo -> len , _write_cb , NULL ));
229
+ CHECK_NIMBLE_ERROR (_wait_for_completion (2000 ));
208
230
}
209
231
<
10000
/td> } else {
210
232
// Validate data length for local characteristics only.
@@ -338,6 +360,10 @@ bleio_characteristic_properties_t common_hal_bleio_characteristic_get_properties
338
360
void common_hal_bleio_characteristic_add_descriptor (bleio_characteristic_obj_t * self ,
339
361
bleio_descriptor_obj_t * descriptor ) {
340
362
size_t i = self -> descriptor_list -> len ;
363
+ if (i >= MAX_DESCRIPTORS ) {
364
+ mp_raise_bleio_BluetoothError (MP_ERROR_TEXT ("Too many descriptors" ));
365
+ }
366
+
341
367
mp_obj_list_append (MP_OBJ_FROM_PTR (self -> descriptor_list ),
342
368
MP_OBJ_FROM_PTR (descriptor ));
343
369
@@ -368,10 +394,9 @@ void common_hal_bleio_characteristic_set_cccd(bleio_characteristic_obj_t *self,
368
394
(notify ? 1 << 0 : 0 ) |
369
395
(indicate ? 1 << 1 : 0 );
370
396
371
- CHECK_NIMBLE_ERROR (ble_gattc_write_flat (conn_handle , self -> cccd_handle , & cccd_value , 2 , _write_cb , xTaskGetCurrentTaskHandle ()));
372
- int error_code ;
373
- xTaskNotifyWait (0 , 0 , (uint32_t * )& error_code , 200 );
374
- CHECK_BLE_ERROR (error_code );
397
+ _reset_completion_status ();
398
+ CHECK_NIMBLE_ERROR (ble_gattc_write_flat (conn_handle , self -> cccd_handle , & cccd_value , 2 , _write_cb , NULL ));
399
+ CHECK_NIMBLE_ERROR (_wait_for_completion (2000 ));
375
400
}
376
401
377
402
void bleio_characteristic_set_observer (bleio_characteristic_obj_t * self , mp_obj_t observer ) {
0 commit comments