Skip to content

nordic: fix BLE MTU negotation #9441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 104 additions & 6 deletions ports/nordic/bluetooth/ble_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,112 @@
#include "py/gc.h"
#include "py/misc.h"
#include "py/mpstate.h"
#include "mpconfigport.h"

#if CIRCUITPY_SERIAL_BLE && CIRCUITPY_VERBOSE_BLE
#include "supervisor/shared/bluetooth/serial.h"
#endif

#if CIRCUITPY_VERBOSE_BLE
const char *ble_drv_evt_name(uint32_t evt) {
switch (evt) {
case BLE_GAP_EVT_CONNECTED:
return "BLE_GAP_EVT_CONNECTED";
case BLE_GAP_EVT_DISCONNECTED:
return "BLE_GAP_EVT_DISCONNECTED";
case BLE_GAP_EVT_CONN_PARAM_UPDATE:
return "BLE_GAP_EVT_CONN_PARAM_UPDATE";
case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
return "BLE_GAP_EVT_SEC_PARAMS_REQUEST";
case BLE_GAP_EVT_SEC_INFO_REQUEST:
return "BLE_GAP_EVT_SEC_INFO_REQUEST";
case BLE_GAP_EVT_PASSKEY_DISPLAY:
return "BLE_GAP_EVT_PASSKEY_DISPLAY";
case BLE_GAP_EVT_KEY_PRESSED:
return "BLE_GAP_EVT_KEY_PRESSED";
case BLE_GAP_EVT_AUTH_KEY_REQUEST:
return "BLE_GAP_EVT_AUTH_KEY_REQUEST";
case BLE_GAP_EVT_LESC_DHKEY_REQUEST:
return "BLE_GAP_EVT_LESC_DHKEY_REQUEST";
case BLE_GAP_EVT_AUTH_STATUS:
return "BLE_GAP_EVT_AUTH_STATUS";
case BLE_GAP_EVT_CONN_SEC_UPDATE:
return "BLE_GAP_EVT_CONN_SEC_UPDATE";
case BLE_GAP_EVT_TIMEOUT:
return "BLE_GAP_EVT_TIMEOUT";
case BLE_GAP_EVT_RSSI_CHANGED:
return "BLE_GAP_EVT_RSSI_CHANGED";
case BLE_GAP_EVT_ADV_REPORT:
return "BLE_GAP_EVT_ADV_REPORT";
case BLE_GAP_EVT_SEC_REQUEST:
return "BLE_GAP_EVT_SEC_REQUEST";
case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
return "BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST";
case BLE_GAP_EVT_SCAN_REQ_REPORT:
return "BLE_GAP_EVT_SCAN_REQ_REPORT";
case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
return "BLE_GAP_EVT_PHY_UPDATE_REQUEST";
case BLE_GAP_EVT_PHY_UPDATE:
return "BLE_GAP_EVT_PHY_UPDATE";
case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
return "BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST";
case BLE_GAP_EVT_DATA_LENGTH_UPDATE:
return "BLE_GAP_EVT_DATA_LENGTH_UPDATE";
case BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT:
return "BLE_GAP_EVT_QOS_CHANNEL_SURVEY_REPORT";
case BLE_GAP_EVT_ADV_SET_TERMINATED:
return "BLE_GAP_EVT_ADV_SET_TERMINATED";

case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
return "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP";
case BLE_GATTC_EVT_REL_DISC_RSP:
return "BLE_GATTC_EVT_REL_DISC_RSP";
case BLE_GATTC_EVT_CHAR_DISC_RSP:
return "BLE_GATTC_EVT_CHAR_DISC_RSP";
case BLE_GATTC_EVT_DESC_DISC_RSP:
return "BLE_GATTC_EVT_DESC_DISC_RSP";
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP:
return "BLE_GATTC_EVT_ATTR_INFO_DISC_RSP";
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
return "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP";
case BLE_GATTC_EVT_READ_RSP:
return "BLE_GATTC_EVT_READ_RSP";
case BLE_GATTC_EVT_CHAR_VALS_READ_RSP:
return "BLE_GATTC_EVT_CHAR_VALS_READ_RSP";
case BLE_GATTC_EVT_WRITE_RSP:
return "BLE_GATTC_EVT_WRITE_RSP";
case BLE_GATTC_EVT_HVX:
return "BLE_GATTC_EVT_HVX";
case BLE_GATTC_EVT_EXCHANGE_MTU_RSP:
return "BLE_GATTC_EVT_EXCHANGE_MTU_RSP";
case BLE_GATTC_EVT_TIMEOUT:
return "BLE_GATTC_EVT_TIMEOUT";
case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE:
return "BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE";

case BLE_GATTS_EVT_WRITE:
return "BLE_GATTS_EVT_WRITE";
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
return "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST";
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
return "BLE_GATTS_EVT_SYS_ATTR_MISSING";
case BLE_GATTS_EVT_HVC:
return "BLE_GATTS_EVT_HVC";
case BLE_GATTS_EVT_SC_CONFIRM:
return "BLE_GATTS_EVT_SC_CONFIRM";
case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
return "BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST";
case BLE_GATTS_EVT_TIMEOUT:
return "BLE_GATTS_EVT_TIMEOUT";
case BLE_GATTS_EVT_HVN_TX_COMPLETE:
return "BLE_GATTS_EVT_HVN_TX_COMPLETE";

default:
return "unknown EVT";
}
};
#endif

nrf_nvic_state_t nrf_nvic_state = { 0 };

// Flag indicating progress of internal flash operation.
Expand Down Expand Up @@ -143,14 +244,11 @@ void SD_EVT_IRQHandler(void) {
}

ble_evt_t *event = (ble_evt_t *)m_ble_evt_buf;

#if CIRCUITPY_VERBOSE_BLE
size_t eid = event->header.evt_id;
if (eid != 0x1d) {
if (BLE_GAP_EVT_BASE <= eid && eid <= BLE_GAP_EVT_LAST) {
mp_printf(&mp_plat_print, "BLE GAP event: %d\n", eid - BLE_GAP_EVT_BASE);
} else {
mp_printf(&mp_plat_print, "BLE event: 0x%04x\n", event->header.evt_id);
}
if (eid != BLE_GAP_EVT_ADV_REPORT) {
mp_printf(&mp_plat_print, "BLE event: %s (0x%04x)\n", ble_drv_evt_name(eid), eid);
}
#endif

Expand Down
13 changes: 9 additions & 4 deletions ports/nordic/common-hal/_bleio/Adapter.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,15 +668,20 @@ mp_obj_t common_hal_bleio_adapter_connect(bleio_adapter_obj_t *self, bleio_addre
}
}

// Negotiate for better PHY, larger MTU and data lengths since we are the central. These are
// nice-to-haves so ignore any errors.
// Negotiate for better PHY, larger MTU and data lengths since we are the central.
// The peer may decline, which is its prerogative.
ble_gap_phys_t const phys = {
.rx_phys = BLE_GAP_PHY_AUTO,
.tx_phys = BLE_GAP_PHY_AUTO,
};
sd_ble_gap_phy_update(conn_handle, &phys);
sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX);
sd_ble_gap_data_length_update(conn_handle, NULL, NULL);
// The MTU size passed here has to match the value passed in the BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST
// event handler in Connection.c, per the SD doc:
// "The value must be equal to Server RX MTU size given in
// sd_ble_gatts_exchange_mtu_reply if an ATT_MTU exchange has
// already been performed in the other direction."
check_nrf_error(sd_ble_gattc_exchange_mtu_request(conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX));
check_nrf_error(sd_ble_gap_data_length_update(conn_handle, NULL, NULL));

// Make the connection object and return it.
for (size_t i = 0; i < BLEIO_TOTAL_CONNECTION_COUNT; i++) {
Expand Down
8 changes: 5 additions & 3 deletions ports/nordic/common-hal/_bleio/Connection.c
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,15 @@ bool connection_on_ble_evt(ble_evt_t *ble_evt, void *self_in) {
if (self->mtu > 0) {
new_mtu = self->mtu;
}

self->mtu = new_mtu;
sd_ble_gatts_exchange_mtu_reply(self->conn_handle, new_mtu);
// The MTU size passed here has to match the value passed in Adapter.c, per the SD doc:
// "The value must be equal to Client RX MTU size given in
// sd_ble_gattc_exchange_mtu_request if an ATT_MTU exchange has
// already been performed in the other direction."
check_nrf_error(sd_ble_gatts_exchange_mtu_reply(self->conn_handle, BLE_GATTS_VAR_ATTR_LEN_MAX));
break;
}


case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: {
ble_gattc_evt_exchange_mtu_rsp_t *response =
&ble_evt->evt.gattc_evt.params.exchange_mtu_rsp;
Expand Down