Skip to content

Commit cacc96d

Browse files
jimmodpgeorge
authored andcommitted
extmod/modbluetooth: Replace def_handle with end_handle in char IRQ.
This is technically a breaking change, but: a) We need the end handle to do descriptor discovery properly. b) We have no possible use for the existing definition handle in the characteristic result IRQ. None of the methods can use it, and therefore no existing code should be using it in a way that changing it to a different integer value should break. Unfortunately NimBLE doesn't make it easy to get the end handle, so also implement a mechanism to use the following characteristic to calculate the previous characteristic's end handle. Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 82fc16f commit cacc96d

File tree

6 files changed

+86
-17
lines changed

6 files changed

+86
-17
lines changed

docs/library/bluetooth.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Event Handling
166166
conn_handle, status = data
167167
elif event == _IRQ_GATTC_CHARACTERISTIC_RESULT:
168168
# Called for each characteristic found by gattc_discover_services().
169-
conn_handle, def_handle, value_handle, properties, uuid = data
169+
conn_handle, end_handle, value_handle, properties, uuid = data
170170
elif event == _IRQ_GATTC_CHARACTERISTIC_DONE:
171171
# Called once service discovery is complete.
172172
# Note: Status will be zero on success, implementation-specific value otherwise.

extmod/btstack/modbluetooth_btstack.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ STATIC void btstack_packet_handler(uint8_t packet_type, uint8_t *packet, uint8_t
450450
gatt_client_characteristic_t characteristic;
451451
gatt_event_characteristic_query_result_get_characteristic(packet, &characteristic);
452452
mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(characteristic.uuid16, characteristic.uuid128);
453-
mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.start_handle, characteristic.value_handle, characteristic.properties, &characteristic_uuid);
453+
mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic.value_handle, characteristic.end_handle, characteristic.properties, &characteristic_uuid);
454454
} else if (event_type == GATT_EVENT_ALL_CHARACTERISTIC_DESCRIPTORS_QUERY_RESULT) {
455455
DEBUG_printf(" --> gatt descriptor query result\n");
456456
uint16_t conn_handle = gatt_event_all_characteristic_descriptors_query_result_get_handle(packet);

extmod/modbluetooth.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1101,7 +1101,7 @@ STATIC mp_obj_t bluetooth_ble_invoke_irq(mp_obj_t none_in) {
11011101
// conn_handle, start_handle, end_handle, uuid
11021102
ringbuf_extract(&o->ringbuf, data_tuple, 3, 0, NULL, 0, &o->irq_data_uuid, NULL);
11031103
} else if (event == MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT) {
1104-
// conn_handle, def_handle, value_handle, properties, uuid
1104+
// conn_handle, end_handle, value_handle, properties, uuid
11051105
ringbuf_extract(&o->ringbuf, data_tuple, 3, 1, NULL, 0, &o->irq_data_uuid, NULL);
11061106
} else if (event == MP_BLUETOOTH_IRQ_GATTC_DESCRIPTOR_RESULT) {
11071107
// conn_handle, handle, uuid
@@ -1375,8 +1375,9 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
13751375
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_SERVICE_RESULT, args, 3, 0, NULL_ADDR, service_uuid, NULL_DATA, NULL_DATA_LEN, 0);
13761376
}
13771377

1378-
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
1379-
mp_int_t args[] = {conn_handle, def_handle, value_handle, properties};
1378+
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
1379+
// Note: "end_handle" replaces "def_handle" from the original version of this event.
1380+
mp_int_t args[] = {conn_handle, end_handle, value_handle, properties};
13801381
invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT, args, 4, 0, NULL_ADDR, characteristic_uuid, NULL_DATA, NULL_DATA_LEN, 0);
13811382
}
13821383

@@ -1588,12 +1589,13 @@ void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t
15881589
schedule_ringbuf(atomic_state);
15891590
}
15901591

1591-
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
1592+
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid) {
15921593
MICROPY_PY_BLUETOOTH_ENTER
15931594
mp_obj_bluetooth_ble_t *o = MP_OBJ_TO_PTR(MP_STATE_VM(bluetooth));
15941595
if (enqueue_irq(o, 2 + 2 + 2 + 1 + characteristic_uuid->type, MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_RESULT)) {
15951596
ringbuf_put16(&o->ringbuf, conn_handle);
1596-
ringbuf_put16(&o->ringbuf, def_handle);
1597+
// Note: "end_handle" replaces "def_handle" from the original version of this event.
1598+
ringbuf_put16(&o->ringbuf, end_handle);
15971599
ringbuf_put16(&o->ringbuf, value_handle);
15981600
ringbuf_put(&o->ringbuf, properties);
15991601
ringbuf_put_uuid(&o->ringbuf, characteristic_uuid);

extmod/modbluetooth.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ void mp_bluetooth_gap_on_scan_result(uint8_t addr_type, const uint8_t *addr, uin
459459
void mp_bluetooth_gattc_on_primary_service_result(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle, mp_obj_bluetooth_uuid_t *service_uuid);
460460

461461
// Notify modbluetooth that a characteristic was found (either by discover-all-on-service, or discover-by-uuid-on-service).
462-
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t def_handle, uint16_t value_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
462+
void mp_bluetooth_gattc_on_characteristic_result(uint16_t conn_handle, uint16_t value_handle, uint16_t end_handle, uint8_t properties, mp_obj_bluetooth_uuid_t *characteristic_uuid);
463463

464464
// Notify modbluetooth that a descriptor was found.
465465
void mp_bluetooth_gattc_on_descriptor_result(uint16_t conn_handle, uint16_t handle, mp_obj_bluetooth_uuid_t *descriptor_uuid);

extmod/nimble/modbluetooth_nimble.c

Lines changed: 61 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1310,15 +1310,51 @@ int mp_bluetooth_gattc_discover_primary_services(uint16_t conn_handle, const mp_
13101310
return ble_hs_err_to_errno(err);
13111311
}
13121312

1313+
STATIC bool match_char_uuid(const mp_obj_bluetooth_uuid_t *filter_uuid, const ble_uuid_any_t *result_uuid) {
1314+
if (!filter_uuid) {
1315+
return true;
1316+
}
1317+
ble_uuid_any_t filter_uuid_nimble;
1318+
create_nimble_uuid(filter_uuid, &filter_uuid_nimble);
1319+
return ble_uuid_cmp(&result_uuid->u, &filter_uuid_nimble.u) == 0;
1320+
}
1321+
13131322
STATIC int ble_gattc_characteristic_cb(uint16_t conn_handle, const struct ble_gatt_error *error, const struct ble_gatt_chr *characteristic, void *arg) {
13141323
DEBUG_printf("ble_gattc_characteristic_cb: conn_handle=%d status=%d def_handle=%d val_handle=%d\n", conn_handle, error->status, characteristic ? characteristic->def_handle : -1, characteristic ? characteristic->val_handle : -1);
13151324
if (!mp_bluetooth_is_active()) {
13161325
return 0;
13171326
}
1327+
1328+
mp_bluetooth_nimble_pending_characteristic_t *pending = &MP_STATE_PORT(bluetooth_nimble_root_pointers)->pending_char_result;
1329+
if (pending->ready) {
1330+
// If there's a pending characteristic, we now know what it's end handle is, report it up to modbluetooth.
1331+
pending->ready = 0;
1332+
1333+
// The end handle will either be the end of the query range (there are
1334+
// no more results), or one before the current result's definition
1335+
// handle.
1336+
uint16_t end_handle = MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle;
1337+
if (error->status == 0) {
1338+
end_handle = characteristic->def_handle - 1;
1339+
}
1340+
1341+
// Assume same conn_handle because we're limiting to a single active discovery.
1342+
mp_bluetooth_gattc_on_characteristic_result(conn_handle, pending->value_handle, end_handle, pending->properties, &pending->uuid);
1343+
}
1344+
13181345
if (error->status == 0) {
1319-
mp_obj_bluetooth_uuid_t characteristic_uuid = create_mp_uuid(&characteristic->uuid);
1320-
mp_bluetooth_gattc_on_characteristic_result(conn_handle, characteristic->def_handle, characteristic->val_handle, characteristic->properties, &characteristic_uuid);
1346+
// If there's no filter, or the filter matches, then save this result.
1347+
if (match_char_uuid(MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid, &characteristic->uuid)) {
1348+
pending->value_handle = characteristic->val_handle;
1349+
pending->properties = characteristic->properties;
1350+
pending->uuid = create_mp_uuid(&characteristic->uuid);
1351+
pending->ready = 1;
1352+
}
13211353
} else {
1354+
// Finished (or failed). Allow another characteristic discovery to start.
1355+
MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = 0;
1356+
1357+
// Report completion.
13221358
mp_bluetooth_gattc_on_discover_complete(MP_BLUETOOTH_IRQ_GATTC_CHARACTERISTIC_DONE, conn_handle, error->status == BLE_HS_EDONE ? 0 : error->status);
13231359
}
13241360
return 0;
@@ -1328,13 +1364,29 @@ int mp_bluetooth_gattc_discover_characteristics(uint16_t conn_handle, uint16_t s
13281364
if (!mp_bluetooth_is_active()) {
13291365
return ERRNO_BLUETOOTH_NOT_ACTIVE;
13301366
}
1331-
int err;
1332-
if (uuid) {
1333-
ble_uuid_any_t nimble_uuid;
1334-
create_nimble_uuid(uuid, &nimble_uuid);
1335-
err = ble_gattc_disc_chrs_by_uuid(conn_handle, start_handle, end_handle, &nimble_uuid.u, &ble_gattc_characteristic_cb, NULL);
1336-
} else {
1337-
err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
1367+
1368+
// The implementation of characteristic discovery queries for all
1369+
// characteristics, and then UUID filtering is applied by NimBLE on each
1370+
// characteristic. Unfortunately, each characteristic result does not
1371+
// include its end handle, so you need to know the next characteristic
1372+
// before you can raise the previous one to modbluetooth. But if we let
1373+
// NimBLE do the filtering, then we don't necessarily see the next one.
1374+
// So we make NimBLE return all results and do the filtering here instead.
1375+
1376+
if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle) {
1377+
// Only allow a single discovery (otherwise we'd need to track a
1378+
// pending characteristic per conn handle).
1379+
return MP_EBUSY;
1380+
}
1381+
1382+
// Set the uuid filter (if any). This needs to be a root pointer,
1383+
// otherwise we'd use ble_gattc_disc_all_chrs's arg param.
1384+
MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_filter_uuid = uuid;
1385+
1386+
int err = ble_gattc_disc_all_chrs(conn_handle, start_handle, end_handle, &ble_gattc_characteristic_cb, NULL);
1387+
if (!err) {
1388+
// Lock out concurrent characteristic discovery.
1389+
MP_STATE_PORT(bluetooth_nimble_root_pointers)->char_disc_end_handle = end_handle;
13381390
}
13391391
return ble_hs_err_to_errno(err);
13401392
}

extmod/nimble/modbluetooth_nimble.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,13 @@
3131

3232
#define MP_BLUETOOTH_NIMBLE_MAX_SERVICES (8)
3333

34+
typedef struct _mp_bluetooth_nimble_pending_characteristic_t {
35+
uint16_t value_handle;
36+
uint8_t properties;
37+
mp_obj_bluetooth_uuid_t uuid;
38+
uint8_t ready;
39+
} mp_bluetooth_nimble_pending_characteristic_t;
40+
3441
typedef struct _mp_bluetooth_nimble_root_pointers_t {
3542
// Characteristic (and descriptor) value storage.
3643
mp_gatts_db_t gatts_db;
@@ -44,6 +51,14 @@ typedef struct _mp_bluetooth_nimble_root_pointers_t {
4451
struct _mp_bluetooth_nimble_l2cap_channel_t *l2cap_chan;
4552
bool l2cap_listening;
4653
#endif
54+
55+
#if MICROPY_PY_BLUETOOTH_ENABLE_GATT_CLIENT
56+
// Workaround to allow us to get the end_handle of each characteristic
57+
// during discovery. See mp_bluetooth_gattc_discover_characteristics().
58+
uint16_t char_disc_end_handle;
59+
const mp_obj_bluetooth_uuid_t *char_filter_uuid;
60+
mp_bluetooth_nimble_pending_characteristic_t pending_char_result;
61+
#endif
4762
} mp_bluetooth_nimble_root_pointers_t;
4863

4964
enum {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy