Skip to content

Commit a44a1fb

Browse files
authored
feat(hid_service): Allow example to support multiple bonded devices (#370)
* feat(hid_service): Allow example to support multiple bonded devices * Implement device callback for handling bond storage overflow * Print bonded devices when booting up * Print bonded devices when a device connects * Update defaults to support 5 devices bonded at a time Helps showcase multiple device support with storage management callback Build and run `hid_service/example on QtPy ESP32S3 and ensure it can bond to the number of bonded devices configured * fix sa
1 parent 7bff95f commit a44a1fb

File tree

2 files changed

+74
-0
lines changed

2 files changed

+74
-0
lines changed

components/hid_service/example/main/hid_service_example.cpp

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,52 @@
88

99
using namespace std::chrono_literals;
1010

11+
// make a callback for managing the pairing table when it fills up
12+
class BleDeviceCallbacks : public NimBLEDeviceCallbacks {
13+
espp::Logger logger =
14+
espp::Logger({.tag = "NimBLEDeviceCallbacks", .level = espp::Logger::Verbosity::INFO});
15+
16+
public:
17+
/**
18+
* @brief Indicates an inability to perform a store operation.
19+
* This callback should do one of two things:
20+
* -Address the problem and return 0, indicating that the store operation
21+
* should proceed.
22+
* -Return nonzero to indicate that the store operation should be aborted.
23+
* @param event Describes the store event being reported.
24+
* BLE_STORE_EVENT_FULL; or
25+
* BLE_STORE_EVENT_OVERFLOW
26+
* @return 0 if the store operation should proceed;
27+
* nonzero if the store operation should be aborted.
28+
*/
29+
virtual int onStoreStatus(struct ble_store_status_event *event, void *arg) {
30+
// see
31+
// https://github.com/apache/mynewt-nimble/blob/master/nimble/host/include/host/ble_store.h#L180
32+
// for definition of ble_store_status_event
33+
if (event->event_code == BLE_STORE_EVENT_FULL) {
34+
logger.info("Store full event: {}", event->event_code);
35+
// if the store is full, then we should delete some old devices
36+
// to make room for new ones
37+
//
38+
// the connection handle for the connection which prompted the write is
39+
// found at event->full->conn_handle.
40+
return ble_store_util_status_rr(event, arg);
41+
} else if (event->event_code == BLE_STORE_EVENT_OVERFLOW) {
42+
logger.info("Store overflow event: {}", event->event_code);
43+
// if the store overflows, then we should delete some old devices
44+
// to make room for new ones
45+
//
46+
// The object that failed to be written is found in
47+
// event->overflow->value (ble_store_value*)
48+
return ble_store_util_status_rr(event, arg);
49+
} else {
50+
logger.error("Unknown store event: {}", event->event_code);
51+
return ble_store_util_status_rr(event, arg);
52+
}
53+
}
54+
};
55+
static BleDeviceCallbacks device_callbacks;
56+
1157
extern "C" void app_main(void) {
1258
espp::Logger logger({.tag = "Hid Service Example", .level = espp::Logger::Verbosity::INFO});
1359
logger.info("Starting");
@@ -53,6 +99,21 @@ extern "C" void app_main(void) {
5399
ble_gatt_server.set_advertise_on_disconnect(true);
54100
#endif
55101

102+
// NOTE: for information about the low-level NVS storage on esp chips, see
103+
// ~/esp/esp-idf/components/bt/host/nimble/nimble/nimble/host/store/config/src/ble_store_nvs.c
104+
//
105+
// now set the device callbacks to override the default one from esp-nimble-cpp
106+
NimBLEDevice::setDeviceCallbacks(&device_callbacks);
107+
uint8_t max_bonds = MYNEWT_VAL(BLE_STORE_MAX_BONDS);
108+
logger.info("Max bonds: {}", max_bonds);
109+
110+
// print the bonded devices as well
111+
auto paired_device_addresses = ble_gatt_server.get_paired_devices();
112+
logger.info("Paired devices: {}", paired_device_addresses.size());
113+
for (const auto &addr : paired_device_addresses) {
114+
logger.info(" Addr: {}", addr.toString());
115+
}
116+
56117
// for HID we need to set some security
57118
bool bonding = true;
58119
bool mitm = false;
@@ -259,6 +320,13 @@ extern "C" void app_main(void) {
259320
logger.info(" Model: {}", model_number);
260321
logger.info(" PnP: {}", pnp_id);
261322
}
323+
324+
// print the bonded devices as well
325+
paired_device_addresses = ble_gatt_server.get_paired_devices();
326+
logger.info("Paired devices: {}", paired_device_addresses.size());
327+
for (const auto &addr : paired_device_addresses) {
328+
logger.info(" Addr: {}", addr.toString());
329+
}
262330
}
263331
} else if (!ble_gatt_server.is_connected()) {
264332
was_connected = false;

components/hid_service/example/sdkconfig.defaults

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ CONFIG_BT_NIMBLE_NVS_PERSIST=y
2828
CONFIG_BT_NIMBLE_GAP_DEVICE_NAME_MAX_LEN=100
2929
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=8192
3030

31+
# NOTE: the MAX_CCCDS must be 4 * MAX_BONDS, otherwise the number of bonded
32+
# devices allowed will be limited by the number of CCCDs / 4.
33+
CONFIG_BT_NIMBLE_MAX_BONDS=5
34+
# should be 4 * MAX_BONDS
35+
CONFIG_BT_NIMBLE_MAX_CCCDS=20
36+
3137
# NOTE: we can support extended advertising (longer advertisement packets) by
3238
# enabling the following:
3339
# CONFIG_BT_NIMBLE_EXT_ADV=y

0 commit comments

Comments
 (0)