summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Leech <andrew.leech@planetinnovation.com.au>2020-08-27 09:13:25 +1000
committerDamien George <damien@micropython.org>2020-12-02 14:36:50 +1100
commit1697ff335db523ff0809051d42871beb9c86012d (patch)
tree1728bc84edc6ddf6cb759d575fc5fa604c99b891
parent7a9aa49595e1c523a5765397db135ff8f00515b1 (diff)
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>
-rw-r--r--examples/bluetooth/ble_simple_peripheral.py9
-rw-r--r--examples/bluetooth/ble_temperature.py6
-rw-r--r--examples/bluetooth/ble_uart_peripheral.py7
-rw-r--r--extmod/btstack/modbluetooth_btstack.c36
-rw-r--r--extmod/modbluetooth.c8
-rw-r--r--extmod/modbluetooth.h44
-rw-r--r--extmod/nimble/modbluetooth_nimble.c6
7 files changed, 93 insertions, 23 deletions
diff --git a/examples/bluetooth/ble_simple_peripheral.py b/examples/bluetooth/ble_simple_peripheral.py
index d2b134e71..0ebe43176 100644
--- a/examples/bluetooth/ble_simple_peripheral.py
+++ b/examples/bluetooth/ble_simple_peripheral.py
@@ -12,14 +12,19 @@ _IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
+_FLAG_READ = const(0x0002)
+_FLAG_WRITE_NO_RESPONSE = const(0x0004)
+_FLAG_WRITE = const(0x0008)
+_FLAG_NOTIFY = const(0x0010)
+
_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
_UART_TX = (
bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
- bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY,
+ _FLAG_READ | _FLAG_NOTIFY,
)
_UART_RX = (
bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
- bluetooth.FLAG_WRITE | bluetooth.FLAG_WRITE_NO_RESPONSE,
+ _FLAG_WRITE | _FLAG_WRITE_NO_RESPONSE,
)
_UART_SERVICE = (
_UART_UUID,
diff --git a/examples/bluetooth/ble_temperature.py b/examples/bluetooth/ble_temperature.py
index d375a62ff..e6378ebee 100644
--- a/examples/bluetooth/ble_temperature.py
+++ b/examples/bluetooth/ble_temperature.py
@@ -15,12 +15,16 @@ _IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_INDICATE_DONE = const(20)
+_FLAG_READ = const(0x0002)
+_FLAG_NOTIFY = const(0x0010)
+_FLAG_INDICATE = const(0x0020)
+
# org.bluetooth.service.environmental_sensing
_ENV_SENSE_UUID = bluetooth.UUID(0x181A)
# org.bluetooth.characteristic.temperature
_TEMP_CHAR = (
bluetooth.UUID(0x2A6E),
- bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY | bluetooth.FLAG_INDICATE,
+ _FLAG_READ | _FLAG_NOTIFY | _FLAG_INDICATE,
)
_ENV_SENSE_SERVICE = (
_ENV_SENSE_UUID,
diff --git a/examples/bluetooth/ble_uart_peripheral.py b/examples/bluetooth/ble_uart_peripheral.py
index 6d167a871..b4e352be9 100644
--- a/examples/bluetooth/ble_uart_peripheral.py
+++ b/examples/bluetooth/ble_uart_peripheral.py
@@ -9,14 +9,17 @@ _IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_WRITE = const(3)
+_FLAG_WRITE = const(0x0008)
+_FLAG_NOTIFY = const(0x0010)
+
_UART_UUID = bluetooth.UUID("6E400001-B5A3-F393-E0A9-E50E24DCCA9E")
_UART_TX = (
bluetooth.UUID("6E400003-B5A3-F393-E0A9-E50E24DCCA9E"),
- bluetooth.FLAG_NOTIFY,
+ _FLAG_NOTIFY,
)
_UART_RX = (
bluetooth.UUID("6E400002-B5A3-F393-E0A9-E50E24DCCA9E"),
- bluetooth.FLAG_WRITE,
+ _FLAG_WRITE,
)
_UART_SERVICE = (
_UART_UUID,
diff --git a/extmod/btstack/modbluetooth_btstack.c b/extmod/btstack/modbluetooth_btstack.c
index 9faae26e4..da9a6f732 100644
--- a/extmod/btstack/modbluetooth_btstack.c
+++ b/extmod/btstack/modbluetooth_btstack.c
@@ -893,7 +893,30 @@ STATIC inline uint16_t get_uuid16(const mp_obj_bluetooth_uuid_t *uuid) {
return (uuid->data[1] << 8) | uuid->data[0];
}
-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) {
+// Map MP_BLUETOOTH_CHARACTERISTIC_FLAG_ values to btstack read/write permission values.
+STATIC void get_characteristic_permissions(uint16_t flags, uint16_t *read_permission, uint16_t *write_permission) {
+ if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_ENCRYPTED) {
+ *read_permission = ATT_SECURITY_ENCRYPTED;
+ } else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHENTICATED) {
+ *read_permission = ATT_SECURITY_AUTHENTICATED;
+ } else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHORIZED) {
+ *read_permission = ATT_SECURITY_AUTHORIZED;
+ } else {
+ *read_permission = ATT_SECURITY_NONE;
+ }
+
+ if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_ENCRYPTED) {
+ *write_permission = ATT_SECURITY_ENCRYPTED;
+ } else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHENTICATED) {
+ *write_permission = ATT_SECURITY_AUTHENTICATED;
+ } else if (flags & MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHORIZED) {
+ *write_permission = ATT_SECURITY_AUTHORIZED;
+ } else {
+ *write_permission = ATT_SECURITY_NONE;
+ }
+}
+
+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) {
DEBUG_printf("mp_bluetooth_gatts_register_service\n");
// Note: btstack expects BE UUIDs (which it immediately convertes to LE).
// 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
static uint8_t cccb_buf[2] = {0};
for (size_t i = 0; i < num_characteristics; ++i) {
- uint16_t props = characteristic_flags[i] | ATT_PROPERTY_DYNAMIC;
- uint16_t read_permission = ATT_SECURITY_NONE;
- uint16_t write_permission = ATT_SECURITY_NONE;
+ uint16_t props = (characteristic_flags[i] & 0x7f) | ATT_PROPERTY_DYNAMIC;
+ uint16_t read_permission, write_permission;
+ get_characteristic_permissions(characteristic_flags[i], &read_permission, &write_permission);
if (characteristic_uuids[i]->type == MP_BLUETOOTH_UUID_TYPE_16) {
handles[handle_index] = att_db_util_add_characteristic_uuid16(get_uuid16(characteristic_uuids[i]), props, read_permission, write_permission, NULL, 0);
} 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
++handle_index;
for (size_t j = 0; j < num_descriptors[i]; ++j) {
- props = descriptor_flags[descriptor_index] | ATT_PROPERTY_DYNAMIC;
- read_permission = ATT_SECURITY_NONE;
- write_permission = ATT_SECURITY_NONE;
+ props = (descriptor_flags[descriptor_index] & 0x7f) | ATT_PROPERTY_DYNAMIC;
+ get_characteristic_permissions(descriptor_flags[descriptor_index], &read_permission, &write_permission);
if (descriptor_uuids[descriptor_index]->type == MP_BLUETOOTH_UUID_TYPE_16) {
handles[handle_index] = att_db_util_add_descriptor_uuid16(get_uuid16(descriptor_uuids[descriptor_index]), props, read_permission, write_permission, NULL, 0);
diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c
index dc1084acc..1e67c8ce3 100644
--- a/extmod/modbluetooth.c
+++ b/extmod/modbluetooth.c
@@ -461,11 +461,11 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
// Lists of characteristic uuids and flags.
mp_obj_bluetooth_uuid_t **characteristic_uuids = m_new(mp_obj_bluetooth_uuid_t *, len);
- uint8_t *characteristic_flags = m_new(uint8_t, len);
+ uint16_t *characteristic_flags = m_new(uint16_t, len);
// Flattened list of descriptor uuids and flags. Grows (realloc) as more descriptors are encountered.
mp_obj_bluetooth_uuid_t **descriptor_uuids = NULL;
- uint8_t *descriptor_flags = NULL;
+ uint16_t *descriptor_flags = NULL;
// How many descriptors in the flattened list per characteristic.
uint8_t *num_descriptors = m_new(uint8_t, len);
@@ -506,7 +506,7 @@ STATIC int bluetooth_gatts_register_service(mp_obj_t uuid_in, mp_obj_t character
// Grow the flattened uuids and flags arrays with this many more descriptors.
descriptor_uuids = m_renew(mp_obj_bluetooth_uuid_t *, descriptor_uuids, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
- descriptor_flags = m_renew(uint8_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
+ descriptor_flags = m_renew(uint16_t, descriptor_flags, descriptor_index, descriptor_index + num_descriptors[characteristic_index]);
// Also grow the handles array.
*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[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_ubluetooth) },
{ MP_ROM_QSTR(MP_QSTR_BLE), MP_ROM_PTR(&mp_type_bluetooth_ble) },
{ MP_ROM_QSTR(MP_QSTR_UUID), MP_ROM_PTR(&mp_type_bluetooth_uuid) },
+
+ // TODO: Deprecate these flags (recommend copying the constants from modbluetooth.h instead).
{ MP_ROM_QSTR(MP_QSTR_FLAG_READ), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ) },
{ MP_ROM_QSTR(MP_QSTR_FLAG_WRITE), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE) },
{ MP_ROM_QSTR(MP_QSTR_FLAG_NOTIFY), MP_ROM_INT(MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY) },
diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h
index 2619e7189..0d4296626 100644
--- a/extmod/modbluetooth.h
+++ b/extmod/modbluetooth.h
@@ -71,12 +71,28 @@
// Advertisement packet lengths
#define MP_BLUETOOTH_GAP_ADV_MAX_LEN (32)
+// Basic characteristic/descriptor flags.
// These match the spec values for these flags so can be passed directly to the stack.
-#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (1 << 1)
-#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (1 << 2)
-#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (1 << 3)
-#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (1 << 4)
-#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE (1 << 5)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_BROADCAST (0x0001)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ (0x0002)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_NO_RESPONSE (0x0004)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE (0x0008)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_NOTIFY (0x0010)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_INDICATE (0x0020)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_AUTHENTICATED_SIGNED_WRITE (0x0040)
+
+// TODO: NimBLE and BlueKitchen disagree on this one.
+// #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_RELIABLE_WRITE (0x0080)
+
+// Extended flags for security and privacy.
+// These match NimBLE but might require mapping in the bindings for other stacks.
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_AUX_WRITE (0x0100)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_ENCRYPTED (0x0200)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHENTICATED (0x0400)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_READ_AUTHORIZED (0x0800)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_ENCRYPTED (0x1000)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHENTICATED (0x2000)
+#define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHORIZED (0x4000)
// For mp_bluetooth_gattc_write, the mode parameter
#define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0)
@@ -153,6 +169,22 @@ _IRQ_L2CAP_DISCONNECT = const(24)
_IRQ_L2CAP_RECV = const(25)
_IRQ_L2CAP_SEND_READY = const(26)
_IRQ_GATTS_CONN_UPDATE = const(27)
+
+_FLAG_BROADCAST = const(0x0001)
+_FLAG_READ = const(0x0002)
+_FLAG_WRITE_NO_RESPONSE = const(0x0004)
+_FLAG_WRITE = const(0x0008)
+_FLAG_NOTIFY = const(0x0010)
+_FLAG_INDICATE = const(0x0020)
+_FLAG_AUTHENTICATED_SIGNED_WRITE = const(0x0040)
+
+_FLAG_AUX_WRITE = const(0x0100)
+_FLAG_READ_ENCRYPTED = const(0x0200)
+_FLAG_READ_AUTHENTICATED = const(0x0400)
+_FLAG_READ_AUTHORIZED = const(0x0800)
+_FLAG_WRITE_ENCRYPTED = const(0x1000)
+_FLAG_WRITE_AUTHENTICATED = const(0x2000)
+_FLAG_WRITE_AUTHORIZED = const(0x4000)
*/
// bluetooth.UUID type.
@@ -214,7 +246,7 @@ void mp_bluetooth_gap_advertise_stop(void);
int mp_bluetooth_gatts_register_service_begin(bool append);
// Add a service with the given list of characteristics to the queue to be registered.
// The value_handles won't be valid until after mp_bluetooth_register_service_end is called.
-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);
+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);
// Register any queued services.
int mp_bluetooth_gatts_register_service_end(void);
diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c
index 3983d1869..4484df937 100644
--- a/extmod/nimble/modbluetooth_nimble.c
+++ b/extmod/nimble/modbluetooth_nimble.c
@@ -685,7 +685,7 @@ int mp_bluetooth_gatts_register_service_end(void) {
return 0;
}
-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) {
+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) {
if (MP_STATE_PORT(bluetooth_nimble_root_pointers)->n_services == MP_BLUETOOTH_NIMBLE_MAX_SERVICES) {
return MP_E2BIG;
}
@@ -697,6 +697,7 @@ int mp_bluetooth_gatts_register_service(mp_obj_bluetooth_uuid_t *service_uuid, m
characteristics[i].uuid = create_nimble_uuid(characteristic_uuids[i], NULL);
characteristics[i].access_cb = characteristic_access_cb;
characteristics[i].arg = NULL;
+ // NimBLE flags match the MP_BLUETOOTH_CHARACTERISTIC_FLAG_ ones exactly (including the security/privacy options).
characteristics[i].flags = characteristic_flags[i];
characteristics[i].min_key_size = 0;
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
for (size_t j = 0; j < num_descriptors[i]; ++j) {
descriptors[j].uuid = create_nimble_uuid(descriptor_uuids[descriptor_index], NULL);
descriptors[j].access_cb = characteristic_access_cb;
- descriptors[j].att_flags = descriptor_flags[descriptor_index];
+ // NimBLE doesn't support security/privacy options on descriptors.
+ descriptors[j].att_flags = (uint8_t)descriptor_flags[descriptor_index];
descriptors[j].min_key_size = 0;
// Unlike characteristic, Nimble doesn't provide an automatic way to remember the handle, so use the arg.
descriptors[j].arg = &handles[handle_index];