From 086d327c1beb6ae6a8b8bca08e7328660e88e341 Mon Sep 17 00:00:00 2001 From: David Lechner Date: Sun, 21 Jan 2024 16:08:08 -0600 Subject: [PATCH] drv/bluetooth_stm32_cc2640: respond to prepared write If a host tries to write more than MTU - 3 bytes to an attribute, the host should do a prepared write to split up the write into multiple long writes. We currently don't support this. So we need to send an error response to the prepared write request. The host may also follow this with an execute write command to cancel the prepared write, so we need to respond to that too. Issue: https://github.com/pybricks/support/issues/947 --- lib/ble5stack/central/att.c | 9 ++++++++ lib/ble5stack/central/att.h | 6 +++--- .../drv/bluetooth/bluetooth_stm32_cc2640.c | 21 +++++++++++++++++++ 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/ble5stack/central/att.c b/lib/ble5stack/central/att.c index 95b2d3d5e..bd055d0e7 100644 --- a/lib/ble5stack/central/att.c +++ b/lib/ble5stack/central/att.c @@ -81,6 +81,15 @@ bStatus_t ATT_WriteRsp(uint16_t connHandle) { return HCI_sendHCICommand(ATT_CMD_WRITE_RSP, buf, 2); } +bStatus_t ATT_ExecuteWriteRsp(uint16_t connHandle) { + uint8_t buf[2]; + + buf[0] = connHandle & 0xFF; + buf[1] = (connHandle >> 8) & 0xFF; + + return HCI_sendHCICommand(ATT_CMD_EXECUTE_WRITE_RSP, buf, 2); +} + bStatus_t ATT_HandleValueNoti(uint16_t connHandle, attHandleValueNoti_t *pNoti) { uint8_t buf[32]; diff --git a/lib/ble5stack/central/att.h b/lib/ble5stack/central/att.h index 1b8a4500a..18ae6f352 100755 --- a/lib/ble5stack/central/att.h +++ b/lib/ble5stack/central/att.h @@ -97,7 +97,7 @@ extern "C" #define ATT_CMD_PREPAREWRITEREQ 0xFD16 #define ATT_CMD_PREPAREWRITERSP 0xFD17 #define ATT_CMD_EXECUTEWRITEREQ 0xFD18 -#define ATT_CMD_EXECUTEWRITERSP 0xFD19 +#define ATT_CMD_EXECUTE_WRITE_RSP 0xFD19 #define ATT_CMD_HANDLE_VALUE_NOTI 0xFD1B #define ATT_CMD_HANDLEVALUEIND 0xFD1D #define ATT_CMD_HANDLEVALUECFM 0xFD1E @@ -125,9 +125,9 @@ extern "C" #define ATT_EVENT_READ_BY_GRP_TYPE_RSP 0x0511 #define ATT_EVENT_WRITE_REQ 0x0512 #define ATT_EVENT_WRITE_RSP 0x0513 -#define ATT_EVENT_PREPAREWRITEREQ 0x0516 +#define ATT_EVENT_PREPARE_WRITE_REQ 0x0516 #define ATT_EVENT_PREPAREWRITERSP 0x0517 -#define ATT_EVENT_EXECUTEWRITEREQ 0x0518 +#define ATT_EVENT_EXECUTE_WRITE_REQ 0x0518 #define ATT_EVENT_EXECUTEWRITERSP 0x0519 #define ATT_EVENT_HANDLE_VALUE_NOTI 0x051B #define ATT_EVENT_HANDLEVALUEIND 0x051D diff --git a/lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c b/lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c index 63970e4dc..121d4efb1 100644 --- a/lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c +++ b/lib/pbio/drv/bluetooth/bluetooth_stm32_cc2640.c @@ -1433,6 +1433,27 @@ static void handle_event(uint8_t *packet) { } break; + case ATT_EVENT_PREPARE_WRITE_REQ: { + uint16_t char_handle = (data[7] << 8) | data[6]; + + // long writes are not currently supported for any characteristic + attErrorRsp_t rsp; + rsp.reqOpcode = ATT_PREPARE_WRITE_REQ; + rsp.handle = char_handle; + rsp.errCode = ATT_ERR_ATTR_NOT_LONG; + ATT_ErrorRsp(connection_handle, &rsp); + } + break; + + case ATT_EVENT_EXECUTE_WRITE_REQ: { + // uint8_t flags = data[6]; + + // Send this to keep host happy. Should only be receiving + // cancel since we don't support long writes. + ATT_ExecuteWriteRsp(connection_handle); + } + break; + case ATT_EVENT_HANDLE_VALUE_NOTI: { // TODO: match callback to handle // uint8_t attr_handle = (data[7] << 8) | data[6];