Skip to content

Commit 1697ff3

Browse files
pi-anldpgeorge
authored andcommitted
extmod/modbluetooth: Allow setting char/desc enc/auth options.
This widens the characteristic/descriptor flags to 16-bit, to allow setting encryption/authentication requirements. Sets the required flags for NimBLE and btstack implementations. The BLE.FLAG_* constants will eventually be deprecated in favour of copy and paste Python constants (like the IRQs). Signed-off-by: Jim Mussared <jim.mussared@gmail.com>
1 parent 7a9aa49 commit 1697ff3

File tree

7 files changed

+93
-23
lines changed

7 files changed

+93
-23
lines changed

examples/bluetooth/ble_simple_peripheral.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,19 @@
1212
_IRQ_CENTRAL_DISCONNECT = const(2)
1313
_IRQ_GATTS_WRITE = const(3)
1414

15+
_FLAG_READ = const(0x0002)
16+
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
17+
_FLAG_WRITE = const(0x0008)
18+
_FLAG_NOTIFY = const(0x0010)
19+
1520
_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
1621
_UART_TX = (
1722
bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
18-
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
23+
_FLAG_READ | _FLAG_NOTIFY,
1924
)
2025
_UART_RX = (
2126
bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
22-
bluetooth.FLAG_WRITE | bluetooth.FLAG_WRITE_NO_RESPONSE,
27+
_FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
2328
)
2429
_UART_SERVICE = (
2530
_UART_UUID,

examples/bluetooth/ble_temperature.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
_IRQ_CENTRAL_DISCONNECT = const(2)
1616
_IRQ_GATTS_INDICATE_DONE = const(20)
1717

18+
_FLAG_READ = const(0x0002)
19+
_FLAG_NOTIFY = const(0x0010)
20+
_FLAG_INDICATE = const(0x0020)
21+
1822
# org.bluetooth.service.environmental_sensing
1923
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
2024
# org.bluetooth.characteristic.temperature
2125
_TEMP_CHAR = (
2226
bluetooth.UUID(0x2A6E),
23-
bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY | bluetooth.FLAG_INDICATE,
27+
_FLAG_READ | _FLAG_NOTIFY | _FLAG_INDICATE,
2428
)
2529
_ENV_SENSE_SERVICE = (
2630
_ENV_SENSE_UUID,

examples/bluetooth/ble_uart_peripheral.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@
99
_IRQ_CENTRAL_DISCONNECT = const(2)
1010
_IRQ_GATTS_WRITE = const(3)
1111

12+
_FLAG_WRITE = const(0x0008)
13+
_FLAG_NOTIFY = const(0x0010)
14+
1215
_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
1316
_UART_TX = (
1417
bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
15-
bluetooth.FLAG_NOTIFY,
18+
_FLAG_NOTIFY,
1619
)
1720
_UART_RX = (
1821
bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
19-
bluetooth.FLAG_WRITE,
22+
_FLAG_WRITE,
2023
)
2124
_UART_SERVICE = (
2225
_UART_UUID,

extmod/btstack/modbluetooth_btstack.c

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -893,7 +893,30 @@ STATIC inline uint16_t get_uuid16(const mp_obj_bluetooth_uuid_t *uuid) {
893893
return (uuid->data[1] << 8) | uuid->data[0];
894894
}
895895

896-
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
896+
// Map MP_BLUETOOTH_CHARACTERISTIC_FLAG_ values to btstack read/write permission values.
897+
STATIC void get_characteristic_permissions(uint16_t flags, uint16_t *read_permission, uint16_t *write_permission) {
898+
if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_ENCRYPTED) {
899+
*read_permission = ATT_SECURITY_ENCRYPTED;
900+
} else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHENTICATED) {
901+
*read_permission = ATT_SECURITY_AUTHENTICATED;
902+
} else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHORIZED) {
903+
*read_permission = ATT_SECURITY_AUTHORIZED;
904+
} else {
905+
*read_permission = ATT_SECURITY_NONE;
906+
}
907+
908+
if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_ENCRYPTED) {
909+
*write_permission = ATT_SECURITY_ENCRYPTED;
910+
} else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHENTICATED) {
911+
*write_permission = ATT_SECURITY_AUTHENTICATED;
912+
} else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHORIZED) {
913+
*write_permission = ATT_SECURITY_AUTHORIZED;
914+
} else {
915+
*write_permission = ATT_SECURITY_NONE;
916+
}
917+
}
918+
919+
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint16_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint16_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
897920
DEBUG_printf("mp_bluetooth_gatts_register_service\n");
898921
// Note: btstack expects BE UUIDs (which it immediately convertes to LE).
899922
// So we have to convert all our modbluetooth LE UUIDs to BE just for the att_db_util_add_* methods (using get_uuid16 above, and reverse_128 from btstackutil.h).
@@ -916,9 +939,9 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
916939
static uint8_t cccb_buf[2] = {0};
917940

918941
for (size_t i = 0; i < num_characteristics; ++i) {
919-
uint16_t props = characteristic_flags[i] | ATT_PROPERTY_DYNAMIC;
920-
uint16_t read_permission = ATT_SECURITY_NONE;
921-
uint16_t write_permission = ATT_SECURITY_NONE;
942+
uint16_t props = (characteristic_flags[i] & 0x7f) | ATT_PROPERTY_DYNAMIC;
943+
uint16_t read_permission, write_permission;
944+
get_characteristic_permissions(characteristic_flags[i], &read_permission, &write_permission);
922945
if (characteristic_uuids[i]->type == MP_BLUETOOTH_UUID_TYPE_16) {
923946
handles[handle_index] = att_db_util_add_characteristic_uuid16(get_uuid16(characteristic_uuids[i]), props, read_permission, write_permission, NULL, 0);
924947
} else if (characteristic_uuids[i]->type == MP_BLUETOOTH_UUID_TYPE_128) {
@@ -942,9 +965,8 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
942965
++handle_index;
943966

944967
for (size_t j = 0; j < num_descriptors[i]; ++j) {
945-
props = descriptor_flags[descriptor_index] | ATT_PROPERTY_DYNAMIC;
946-
read_permission = ATT_SECURITY_NONE;
947-
write_permission = ATT_SECURITY_NONE;
968+
props = (descriptor_flags[descriptor_index] & 0x7f) | ATT_PROPERTY_DYNAMIC;
969+
get_characteristic_permissions(descriptor_flags[descriptor_index], &read_permission, &write_permission);
948970

949971
if (descriptor_uuids[descriptor_index]->type == MP_BLUETOOTH_UUID_TYPE_16) {
950972
handles[handle_index] = att_db_util_add_descriptor_uuid16(get_uuid16(descriptor_uuids[descriptor_index]), props, read_permission, write_permission, NULL, 0);

extmod/modbluetooth.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -461,11 +461,11 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
461461

462462
// Lists of characteristic uuids and flags.
463463
mp_obj_bluetooth_uuid_t **characteristic_uuids = m_new(mp_obj_bluetooth_uuid_t *, len);
464-
uint8_t *characteristic_flags = m_new(uint8_t, len);
464+
uint16_t *characteristic_flags = m_new(uint16_t, len);
465465

466466
// Flattened list of descriptor uuids and flags. Grows (realloc) as more descriptors are encountered.
467467
mp_obj_bluetooth_uuid_t **descriptor_uuids = NULL;
468-
uint8_t *descriptor_flags = NULL;
468+
uint16_t *descriptor_flags = NULL;
469469
// How many descriptors in the flattened list per characteristic.
470470
uint8_t *num_descriptors = m_new(uint8_t, len);
471471

@@ -506,7 +506,7 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
506506

507507
// Grow the flattened uuids and flags arrays with this many more descriptors.
508508
descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
509-
descriptor_flags = m_renew(uint8_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
509+
descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
510510

511511
// Also grow the handles array.
512512
*handles = m_renew(uint16_t, *handles, *num_handles, *num_handles + num_descriptors[characteristic_index]);
@@ -894,6 +894,8 @@ STATIC const mp_rom_map_elem_t mp_module_bluetooth_globals_table[] = {
894894
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) },
895895
{ MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&mp_type_bluetooth_ble) },
896896
{ MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&mp_type_bluetooth_uuid) },
897+
898+
// TODO: Deprecate these flags (recommend copying the constants from modbluetooth.h instead).
897899
{ MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) },
898900
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) },
899901
{ MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) },

extmod/modbluetooth.h

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,28 @@
7171
// Advertisement packet lengths
7272
#define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32)
7373

74+
// Basic characteristic/descriptor flags.
7475
// These match the spec values for these flags so can be passed directly to the stack.
75-
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (1 << 1)
76-
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (1 << 2)
77-
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3)
78-
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4)
79-
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE (1 << 5)
76+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_BROADCAST (0x0001)
77+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (0x0002)
78+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (0x0004)
79+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (0x0008)
80+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (0x0010)
81+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE (0x0020)
82+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_AUTHENTICATED_SIGNED_WRITE (0x0040)
83+
84+
// TODO: NimBLE and BlueKitchen disagree on this one.
85+
// #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_RELIABLE_WRITE (0x0080)
86+
87+
// Extended flags for security and privacy.
88+
// These match NimBLE but might require mapping in the bindings for other stacks.
89+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_AUX_WRITE (0x0100)
90+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_ENCRYPTED (0x0200)
91+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHENTICATED (0x0400)
92+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHORIZED (0x0800)
93+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_ENCRYPTED (0x1000)
94+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHENTICATED (0x2000)
95+
#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHORIZED (0x4000)
8096

8197
// For mp_bluetooth_gattc_write, the mode parameter
8298
#define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0)
@@ -153,6 +169,22 @@ _IRQ_L2CAP_DISCONNECT = const(24)
153169
_IRQ_L2CAP_RECV = const(25)
154170
_IRQ_L2CAP_SEND_READY = const(26)
155171
_IRQ_GATTS_CONN_UPDATE = const(27)
172+
173+
_FLAG_BROADCAST = const(0x0001)
174+
_FLAG_READ = const(0x0002)
175+
_FLAG_WRITE_NO_RESPONSE = const(0x0004)
176+
_FLAG_WRITE = const(0x0008)
177+
_FLAG_NOTIFY = const(0x0010)
178+
_FLAG_INDICATE = const(0x0020)
179+
_FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040)
180+
181+
_FLAG_AUX_WRITE = const(0x0100)
182+
_FLAG_READ_ENCRYPTED = const(0x0200)
183+
_FLAG_READ_AUTHENTICATED = const(0x0400)
184+
_FLAG_READ_AUTHORIZED = const(0x0800)
185+
_FLAG_WRITE_ENCRYPTED = const(0x1000)
186+
_FLAG_WRITE_AUTHENTICATED = const(0x2000)
187+
_FLAG_WRITE_AUTHORIZED = const(0x4000)
156188
*/
157189

158190
// bluetooth.UUID type.
@@ -214,7 +246,7 @@ void mp_bluetooth_gap_advertise_stop(void);
214246
int mp_bluetooth_gatts_register_service_begin(bool append);
215247
// Add a service with the given list of characteristics to the queue to be registered.
216248
// The value_handles won't be valid until after mp_bluetooth_register_service_end is called.
217-
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics);
249+
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint16_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint16_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics);
218250
// Register any queued services.
219251
int mp_bluetooth_gatts_register_service_end(void);
220252

extmod/nimble/modbluetooth_nimble.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,7 @@ int mp_bluetooth_gatts_register_service_end(void) {
685685
return 0;
686686
}
687687

688-
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint8_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint8_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
688+
int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, mp_obj_bluetooth_uuid_t **characteristic_uuids, uint16_t *characteristic_flags, mp_obj_bluetooth_uuid_t **descriptor_uuids, uint16_t *descriptor_flags, uint8_t *num_descriptors, uint16_t *handles, size_t num_characteristics) {
689689
if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services == MP_BLUETOOTH_NIMBLE_MAX_SERVICES) {
690690
return MP_E2BIG;
691691
}
@@ -697,6 +697,7 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
697697
characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i], NULL);
698698
characteristics[i].access_cb = characteristic_access_cb;
699699
characteristics[i].arg = NULL;
700+
// NimBLE flags match the MP_BLUETOOTH_CHARACTERISTIC_FLAG_ ones exactly (including the security/privacy options).
700701
characteristics[i].flags = characteristic_flags[i];
701702
characteristics[i].min_key_size = 0;
702703
characteristics[i].val_handle = &handles[handle_index];
@@ -710,7 +711,8 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
710711
for (size_t j = 0; j < num_descriptors[i]; ++j) {
711712
descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index], NULL);
712713
descriptors[j].access_cb = characteristic_access_cb;
713-
descriptors[j].att_flags = descriptor_flags[descriptor_index];
714+
// NimBLE doesn't support security/privacy options on descriptors.
715+
descriptors[j].att_flags = (uint8_t)descriptor_flags[descriptor_index];
714716
descriptors[j].min_key_size = 0;
715717
// Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg.
716718
descriptors[j].arg = &handles[handle_index];

0 commit comments

Comments
 (0)