diff --git a/nimble/host/include/host/ble_gap.h b/nimble/host/include/host/ble_gap.h index 4e79e4868..fe303909c 100644 --- a/nimble/host/include/host/ble_gap.h +++ b/nimble/host/include/host/ble_gap.h @@ -142,6 +142,8 @@ struct hci_conn_update; #define BLE_GAP_EVENT_PERIODIC_TRANSFER 24 #define BLE_GAP_EVENT_REATTEMPT_COUNT 25 #define BLE_GAP_EVENT_VS_HCI 26 +#define BLE_GAP_EVENT_DATA_LEN_CHG 27 + /*** Reason codes for the subscribe GAP event. */ @@ -1001,6 +1003,29 @@ struct ble_gap_event { } reattempt_cnt; #endif + /** + * Represent an event for LE Data length change + * + * Valid for the following event types: + * o BLE_GAP_EVENT_DATA_LEN_CHG + */ + struct { + /* Connection handle */ + uint16_t conn_handle; + + /* Max Tx Payload octotes */ + uint16_t max_tx_octets; + + /* Max Tx Time */ + uint16_t max_tx_time; + + /* Max Rx payload octet */ + uint16_t max_rx_octets; + + /* Max Rx Time */ + uint16_t max_rx_time; + } data_len_chg; + #if MYNEWT_VAL(BLE_HCI_VS) /** * Represents a received vendor-specific HCI event diff --git a/nimble/host/src/ble_gap.c b/nimble/host/src/ble_gap.c index 22b80c1b7..7854c9a82 100644 --- a/nimble/host/src/ble_gap.c +++ b/nimble/host/src/ble_gap.c @@ -2039,6 +2039,25 @@ ble_gap_rx_phy_update_complete(const struct ble_hci_ev_le_subev_phy_update_compl ble_gap_call_conn_event_cb(&event, conn_handle); } +void +ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev) +{ +#if NIMBLE_BLE_CONNECT + struct ble_gap_event event; + uint16_t conn_handle = le16toh(ev->conn_handle); + + memset(&event, 0, sizeof event); + event.type = BLE_GAP_EVENT_DATA_LEN_CHG; + event.data_len_chg.max_tx_octets = le16toh(ev->max_tx_octets); + event.data_len_chg.max_rx_octets = le16toh(ev->max_rx_octets); + event.data_len_chg.max_tx_time = le16toh(ev->max_tx_time); + event.data_len_chg.max_rx_time = le16toh(ev->max_rx_time); + + ble_gap_event_listener_call(&event); + ble_gap_call_conn_event_cb(&event, conn_handle); +#endif +} + static int32_t ble_gap_master_timer(void) { diff --git a/nimble/host/src/ble_gap_priv.h b/nimble/host/src/ble_gap_priv.h index dabba6704..3f8375aa0 100644 --- a/nimble/host/src/ble_gap_priv.h +++ b/nimble/host/src/ble_gap_priv.h @@ -152,6 +152,8 @@ int ble_gap_dbg_update_active(uint16_t conn_handle); void ble_gap_reattempt_count(uint16_t conn_handle, uint8_t count); #endif +void ble_gap_rx_data_len_change(const struct ble_hci_ev_le_subev_data_len_chg *ev); + #ifdef __cplusplus } #endif diff --git a/nimble/host/src/ble_hs_hci_evt.c b/nimble/host/src/ble_hs_hci_evt.c index 35a0fc5cf..74036218f 100644 --- a/nimble/host/src/ble_hs_hci_evt.c +++ b/nimble/host/src/ble_hs_hci_evt.c @@ -65,6 +65,7 @@ static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_adv_rpt; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_upd_complete; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_lt_key_req; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_conn_parm_req; +static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_data_len_change; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_dir_adv_rpt; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_phy_update_complete; static ble_hs_hci_evt_le_fn ble_hs_hci_evt_le_ext_adv_rpt; @@ -116,6 +117,7 @@ static ble_hs_hci_evt_le_fn * const ble_hs_hci_evt_le_dispatch[] = { [BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE] = ble_hs_hci_evt_le_conn_upd_complete, [BLE_HCI_LE_SUBEV_LT_KEY_REQ] = ble_hs_hci_evt_le_lt_key_req, [BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ] = ble_hs_hci_evt_le_conn_parm_req, + [BLE_HCI_LE_SUBEV_DATA_LEN_CHG] = ble_hs_hci_evt_le_data_len_change, [BLE_HCI_LE_SUBEV_ENH_CONN_COMPLETE] = ble_hs_hci_evt_le_enh_conn_complete, [BLE_HCI_LE_SUBEV_DIRECT_ADV_RPT] = ble_hs_hci_evt_le_dir_adv_rpt, [BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE] = ble_hs_hci_evt_le_phy_update_complete, @@ -886,6 +888,22 @@ ble_hs_hci_evt_le_phy_update_complete(uint8_t subevent, const void *data, return 0; } +static int +ble_hs_hci_evt_le_data_len_change(uint8_t subevent, const void *data, + unsigned int len) +{ + const struct ble_hci_ev_le_subev_data_len_chg *ev = data; + + if (len != sizeof(*ev)) { + return BLE_HS_ECONTROLLER; + } + + ble_gap_rx_data_len_change(ev); + + return 0; + +} + int ble_hs_hci_evt_process(const struct ble_hci_ev *ev) {