diff --git a/extmod/modbluetooth.c b/extmod/modbluetooth.c index 1e67c8ce32..ed983b7946 100644 --- a/extmod/modbluetooth.c +++ b/extmod/modbluetooth.c @@ -1113,10 +1113,13 @@ void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t valu invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_INDICATE_DONE, args, 2, &status, 1, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); } -bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { +mp_int_t mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { uint16_t args[] = {conn_handle, value_handle}; mp_obj_t result = invoke_irq_handler(MP_BLUETOOTH_IRQ_GATTS_READ_REQUEST, args, 2, NULL, 0, NULL_ADDR, NULL_I8, 0, NULL_UUID, NULL_DATA, 0); - return result == mp_const_none || mp_obj_is_true(result); + // Return non-zero from IRQ handler to fail the read. + mp_int_t ret = 0; + mp_obj_get_int_maybe(result, &ret); + return ret; } void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) { @@ -1320,11 +1323,11 @@ void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t valu schedule_ringbuf(atomic_state); } -bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { +mp_int_t mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle) { (void)conn_handle; (void)value_handle; // This must be handled synchronously and therefore cannot implemented with the ringbuffer. - return true; + return MP_BLUETOOTH_GATTS_NO_ERROR; } void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value) { diff --git a/extmod/modbluetooth.h b/extmod/modbluetooth.h index 0d4296626b..9856d4a689 100644 --- a/extmod/modbluetooth.h +++ b/extmod/modbluetooth.h @@ -94,6 +94,14 @@ #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHENTICATED (0x2000) #define MP_BLUETOOTH_CHARACTERISTIC_FLAG_WRITE_AUTHORIZED (0x4000) +// Return values from _IRQ_GATTS_READ_REQUEST. +#define MP_BLUETOOTH_GATTS_NO_ERROR (0x00) +#define MP_BLUETOOTH_GATTS_ERROR_READ_NOT_PERMITTED (0x02) +#define MP_BLUETOOTH_GATTS_ERROR_WRITE_NOT_PERMITTED (0x03) +#define MP_BLUETOOTH_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION (0x05) +#define MP_BLUETOOTH_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION (0x08) +#define MP_BLUETOOTH_GATTS_ERROR_INSUFFICIENT_ENCRYPTION (0x0f) + // For mp_bluetooth_gattc_write, the mode parameter #define MP_BLUETOOTH_WRITE_MODE_NO_RESPONSE (0) #define MP_BLUETOOTH_WRITE_MODE_WITH_RESPONSE (1) @@ -185,6 +193,13 @@ _FLAG_READ_AUTHORIZED = const(0x0800) _FLAG_WRITE_ENCRYPTED = const(0x1000) _FLAG_WRITE_AUTHENTICATED = const(0x2000) _FLAG_WRITE_AUTHORIZED = const(0x4000) + +_GATTS_NO_ERROR = const(0x00) +_GATTS_ERROR_READ_NOT_PERMITTED = const(0x02) +_GATTS_ERROR_WRITE_NOT_PERMITTED = const(0x03) +_GATTS_ERROR_INSUFFICIENT_AUTHENTICATION = const(0x05) +_GATTS_ERROR_INSUFFICIENT_AUTHORIZATION = const(0x08) +_GATTS_ERROR_INSUFFICIENT_ENCRYPTION = const(0x0f) */ // bluetooth.UUID type. @@ -324,8 +339,9 @@ void mp_bluetooth_gatts_on_write(uint16_t conn_handle, uint16_t value_handle); // Call this when an acknowledgment is received for an indication. void mp_bluetooth_gatts_on_indicate_complete(uint16_t conn_handle, uint16_t value_handle, uint8_t status); -// Call this when a characteristic is read from. Return false to deny the read. -bool mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle); +// Call this when a characteristic is read from (giving the handler a chance to update the stored value). +// Return 0 to allow the read, otherwise a non-zero rejection reason (see MP_BLUETOOTH_GATTS_ERROR_*). +mp_int_t mp_bluetooth_gatts_on_read_request(uint16_t conn_handle, uint16_t value_handle); // Call this when an MTU exchange completes. void mp_bluetooth_gatts_on_mtu_exchanged(uint16_t conn_handle, uint16_t value); diff --git a/extmod/nimble/modbluetooth_nimble.c b/extmod/nimble/modbluetooth_nimble.c index 4484df937f..e79dc2d4cb 100644 --- a/extmod/nimble/modbluetooth_nimble.c +++ b/extmod/nimble/modbluetooth_nimble.c @@ -608,12 +608,13 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, mp_bluetooth_gatts_db_entry_t *entry; switch (ctxt->op) { case BLE_GATT_ACCESS_OP_READ_CHR: - case BLE_GATT_ACCESS_OP_READ_DSC: + case BLE_GATT_ACCESS_OP_READ_DSC: { // Allow Python code to override (by using gatts_write), or deny (by returning false) the read. // Note this will be a no-op if the ringbuffer implementation is being used (i.e. the stack isn't // run in the scheduler). The ringbuffer is not used on STM32 and Unix-H4 only. - if (!mp_bluetooth_gatts_on_read_request(conn_handle, value_handle)) { - return BLE_ATT_ERR_READ_NOT_PERMITTED; + int req = mp_bluetooth_gatts_on_read_request(conn_handle, value_handle); + if (req) { + return req; } entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle); @@ -626,6 +627,7 @@ static int characteristic_access_cb(uint16_t conn_handle, uint16_t value_handle, } return 0; + } case BLE_GATT_ACCESS_OP_WRITE_CHR: case BLE_GATT_ACCESS_OP_WRITE_DSC: entry = mp_bluetooth_gatts_db_lookup(MP_STATE_PORT(bluetooth_nimble_root_pointers)->gatts_db, value_handle);