From 5ea8badc4698b05b42011032e9ef4afc088e96f0 Mon Sep 17 00:00:00 2001 From: Andrzej Kaczmarek Date: Thu, 4 Aug 2022 15:09:55 +0200 Subject: [PATCH] nimble/ll: Add vs command to change all data length parameters --- nimble/controller/include/controller/ble_ll.h | 4 - .../include/controller/ble_ll_conn.h | 1 + .../include/controller/ble_ll_hci.h | 3 + nimble/controller/src/ble_ll.c | 30 -------- nimble/controller/src/ble_ll_conn.c | 53 ++++++++++++++ nimble/controller/src/ble_ll_conn_hci.c | 39 ++-------- nimble/controller/src/ble_ll_conn_priv.h | 6 ++ nimble/controller/src/ble_ll_ctrl.c | 7 +- nimble/controller/src/ble_ll_hci.c | 73 ++++++++++--------- nimble/controller/src/ble_ll_hci_vs.c | 52 +++++++++++++ nimble/include/nimble/hci_common.h | 12 +++ 11 files changed, 180 insertions(+), 100 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll.h b/nimble/controller/include/controller/ble_ll.h index a524759a2..8535d4404 100644 --- a/nimble/controller/include/controller/ble_ll.h +++ b/nimble/controller/include/controller/ble_ll.h @@ -596,10 +596,6 @@ int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len); /* Read set of states supported by the Link Layer */ uint64_t ble_ll_read_supp_states(void); -/* Check if octets and time are valid. Returns 0 if not valid */ -int ble_ll_chk_txrx_octets(uint16_t octets); -int ble_ll_chk_txrx_time(uint16_t time); - /* Random numbers */ int ble_ll_rand_init(void); void ble_ll_rand_sample(uint8_t rnum); diff --git a/nimble/controller/include/controller/ble_ll_conn.h b/nimble/controller/include/controller/ble_ll_conn.h index 3872406f1..c84979428 100644 --- a/nimble/controller/include/controller/ble_ll_conn.h +++ b/nimble/controller/include/controller/ble_ll_conn.h @@ -230,6 +230,7 @@ struct ble_ll_conn_sm uint16_t ota_max_rx_time; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) uint16_t host_req_max_tx_time; + uint16_t host_req_max_rx_time; #endif #if (BLE_LL_BT5_PHY_SUPPORTED == 1) diff --git a/nimble/controller/include/controller/ble_ll_hci.h b/nimble/controller/include/controller/ble_ll_hci.h index 37d6d205c..b73f85275 100644 --- a/nimble/controller/include/controller/ble_ll_hci.h +++ b/nimble/controller/include/controller/ble_ll_hci.h @@ -83,6 +83,9 @@ bool ble_ll_hci_adv_mode_ext(void); /* Get TX power compensation rounded to integer dB */ int8_t ble_ll_get_tx_pwr_compensation(void); +/* Check if max octets/time are within allowed range */ +int ble_ll_hci_check_dle(uint16_t max_octets, uint16_t max_time); + #if MYNEWT_VAL(BLE_LL_HCI_VS) void ble_ll_hci_vs_register(struct ble_ll_hci_vs_cmd *cmds, uint32_t num_cmds); #endif diff --git a/nimble/controller/src/ble_ll.c b/nimble/controller/src/ble_ll.c index 90fee6bf7..356bf4afd 100644 --- a/nimble/controller/src/ble_ll.c +++ b/nimble/controller/src/ble_ll.c @@ -503,36 +503,6 @@ rxpdu_alloc_fail: return NULL; } -int -ble_ll_chk_txrx_octets(uint16_t octets) -{ - int rc; - - if ((octets < BLE_LL_CONN_SUPP_BYTES_MIN) || - (octets > BLE_LL_CONN_SUPP_BYTES_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - -int -ble_ll_chk_txrx_time(uint16_t time) -{ - int rc; - - if ((time < BLE_LL_CONN_SUPP_TIME_MIN) || - (time > BLE_LL_CONN_SUPP_TIME_MAX)) { - rc = 0; - } else { - rc = 1; - } - - return rc; -} - /** * Checks to see if the address is a resolvable private address. * diff --git a/nimble/controller/src/ble_ll_conn.c b/nimble/controller/src/ble_ll_conn.c index b625a0e35..9bfa1f8e5 100644 --- a/nimble/controller/src/ble_ll_conn.c +++ b/nimble/controller/src/ble_ll_conn.c @@ -1798,6 +1798,58 @@ ble_ll_conn_central_init(struct ble_ll_conn_sm *connsm, } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int +ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, + uint16_t tx_octets, uint16_t tx_time, + uint16_t rx_octets, uint16_t rx_time) +{ + int init_dle = 0; + + /* Note: octets/time shall be checked by caller! */ + +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) + /* Keep original values requested by host since we may want to recalculate + * after PHY changes between coded and uncoded. + */ + connsm->host_req_max_tx_time = tx_time; + connsm->host_req_max_rx_time = rx_time; + + /* If peer does not support coded, we cannot use value larger than 2120us */ + if (!ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { + tx_time = min(tx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + rx_time = min(rx_time, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); + } +#endif + + if (connsm->max_tx_time != tx_time) { + connsm->max_tx_time = tx_time; + init_dle = 1; + } + + if (connsm->max_tx_octets != tx_octets) { + connsm->max_tx_octets = tx_octets; + init_dle = 1; + } + + if (rx_time && (connsm->max_rx_time != rx_time)) { + connsm->max_rx_time = rx_time; + init_dle = 1; + } + + if (rx_octets && (connsm->max_rx_octets != rx_octets)) { + connsm->max_rx_octets = rx_octets; + init_dle = 1; + } + + if (init_dle) { + ble_ll_ctrl_initiate_dle(connsm); + } + + return 0; +} +#endif + #if (BLE_LL_BT5_PHY_SUPPORTED == 1) static void @@ -1988,6 +2040,7 @@ ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm) connsm->eff_max_rx_octets = BLE_LL_CONN_SUPP_BYTES_MIN; #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) connsm->host_req_max_tx_time = 0; + connsm->host_req_max_rx_time = 0; #endif /* Reset encryption data */ diff --git a/nimble/controller/src/ble_ll_conn_hci.c b/nimble/controller/src/ble_ll_conn_hci.c index fb77d668d..d0de63ba9 100644 --- a/nimble/controller/src/ble_ll_conn_hci.c +++ b/nimble/controller/src/ble_ll_conn_hci.c @@ -1475,8 +1475,8 @@ ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, struct ble_hci_le_set_data_len_rp *rsp = (void *) rspbuf; int rc; uint16_t handle; - uint16_t txoctets; - uint16_t txtime; + uint16_t tx_octets; + uint16_t tx_time; struct ble_ll_conn_sm *connsm; if (len != sizeof(*cmd)) { @@ -1491,42 +1491,19 @@ ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len, goto done; } - txoctets = le16toh(cmd->tx_octets); - txtime = le16toh(cmd->tx_time); + tx_octets = le16toh(cmd->tx_octets); + tx_time = le16toh(cmd->tx_time); - /* Make sure it is valid */ - if (!ble_ll_chk_txrx_octets(txoctets) || - !ble_ll_chk_txrx_time(txtime)) { - rc = BLE_ERR_INV_HCI_CMD_PARMS; - goto done; + if (!ble_ll_hci_check_dle(tx_octets, tx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; } -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY) - /* - * Keep original value requested by host since we may want to recalculate - * MaxTxTime after PHY changes between coded and uncoded. - */ - connsm->host_req_max_tx_time = txtime; - - /* If peer does not support coded, we cannot use value larger than 2120us */ - if (!ble_ll_conn_rem_feature_check(connsm, BLE_LL_FEAT_LE_CODED_PHY)) { - txtime = min(txtime, BLE_LL_CONN_SUPP_TIME_MAX_UNCODED); - } -#endif - - rc = BLE_ERR_SUCCESS; - if (connsm->max_tx_time != txtime || - connsm->max_tx_octets != txoctets) { - - connsm->max_tx_time = txtime; - connsm->max_tx_octets = txoctets; - - ble_ll_ctrl_initiate_dle(connsm); - } + rc = ble_ll_conn_set_data_len(connsm, tx_octets, tx_time, 0, 0); done: rsp->conn_handle = htole16(handle); *rsplen = sizeof(*rsp); + return rc; } #endif diff --git a/nimble/controller/src/ble_ll_conn_priv.h b/nimble/controller/src/ble_ll_conn_priv.h index 846a6b644..bb58e4b7a 100644 --- a/nimble/controller/src/ble_ll_conn_priv.h +++ b/nimble/controller/src/ble_ll_conn_priv.h @@ -252,6 +252,12 @@ bool ble_ll_conn_cth_flow_enable(bool enabled); void ble_ll_conn_cth_flow_process_cmd(const uint8_t *cmdbuf); #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int ble_ll_conn_set_data_len(struct ble_ll_conn_sm *connsm, + uint16_t tx_octets, uint16_t tx_time, + uint16_t rx_octets, uint16_t rx_time); +#endif + void ble_ll_conn_itvl_to_ticks(uint32_t itvl, uint32_t *itvl_ticks, uint8_t *itvl_usecs); diff --git a/nimble/controller/src/ble_ll_ctrl.c b/nimble/controller/src/ble_ll_ctrl.c index 38b3b6d24..948eefae3 100644 --- a/nimble/controller/src/ble_ll_ctrl.c +++ b/nimble/controller/src/ble_ll_ctrl.c @@ -2124,7 +2124,12 @@ ble_ll_ctrl_update_features(struct ble_ll_conn_sm *connsm, uint8_t *feat) } else { connsm->max_tx_time = g_ble_ll_conn_params.conn_init_max_tx_time_coded; } - connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + if (connsm->host_req_max_rx_time) { + connsm->max_rx_time = max(connsm->max_rx_time, + connsm->host_req_max_rx_time); + } else { + connsm->max_rx_time = BLE_LL_CONN_SUPP_TIME_MAX_CODED; + } } #endif diff --git a/nimble/controller/src/ble_ll_hci.c b/nimble/controller/src/ble_ll_hci.c index 054fef90f..f0151b497 100644 --- a/nimble/controller/src/ble_ll_hci.c +++ b/nimble/controller/src/ble_ll_hci.c @@ -435,6 +435,15 @@ ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) #endif #if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +int +ble_ll_hci_check_dle(uint16_t max_octets, uint16_t max_time) +{ + return (max_octets >= BLE_LL_CONN_SUPP_BYTES_MIN) && + (max_octets <= BLE_LL_CONN_SUPP_BYTES_MAX) && + (max_time >= BLE_LL_CONN_SUPP_TIME_MIN) && + (max_time <= BLE_LL_CONN_SUPP_TIME_MAX); +} + /** * HCI write suggested default data length command. * @@ -453,51 +462,47 @@ ble_ll_hci_le_set_def_phy(const uint8_t *cmdbuf, uint8_t len) static int ble_ll_hci_le_wr_sugg_data_len(const uint8_t *cmdbuf, uint8_t len) { - const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void*) cmdbuf; - uint16_t tx_oct; + const struct ble_hci_le_wr_sugg_def_data_len_cp *cmd = (const void *)cmdbuf; + uint16_t tx_octets; uint16_t tx_time; - int rc; if (len != sizeof(*cmd)) { return BLE_ERR_INV_HCI_CMD_PARMS; } /* Get suggested octets and time */ - tx_oct = le16toh(cmd->max_tx_octets); + tx_octets = le16toh(cmd->max_tx_octets); tx_time = le16toh(cmd->max_tx_time); - /* If valid, write into suggested and change connection initial times */ - if (ble_ll_chk_txrx_octets(tx_oct) && ble_ll_chk_txrx_time(tx_time)) { - g_ble_ll_conn_params.sugg_tx_octets = (uint8_t)tx_oct; - g_ble_ll_conn_params.sugg_tx_time = tx_time; - - /* - * We can disregard host suggestion, but we are a nice controller so - * let's use host suggestion, unless they exceed max supported values - * in which case we just use our max. - */ - g_ble_ll_conn_params.conn_init_max_tx_octets = - min(tx_oct, g_ble_ll_conn_params.supp_max_tx_octets); - g_ble_ll_conn_params.conn_init_max_tx_time = - min(tx_time, g_ble_ll_conn_params.supp_max_tx_time); - - /* - * Use the same for coded and uncoded defaults. These are used when PHY - * parameters are initialized and we want to use values overridden by - * host. Make sure we do not exceed max supported time on uncoded. - */ - g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = - min(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, - g_ble_ll_conn_params.conn_init_max_tx_time); - g_ble_ll_conn_params.conn_init_max_tx_time_coded = - g_ble_ll_conn_params.conn_init_max_tx_time; - - rc = BLE_ERR_SUCCESS; - } else { - rc = BLE_ERR_INV_HCI_CMD_PARMS; + if (!ble_ll_hci_check_dle(tx_octets, tx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; } - return rc; + g_ble_ll_conn_params.sugg_tx_octets = tx_octets; + g_ble_ll_conn_params.sugg_tx_time = tx_time; + + /* + * We can disregard host suggestion, but we are a nice controller so + * let's use host suggestion, unless they exceed max supported values + * in which case we just use our max. + */ + g_ble_ll_conn_params.conn_init_max_tx_octets = + min(tx_octets, g_ble_ll_conn_params.supp_max_tx_octets); + g_ble_ll_conn_params.conn_init_max_tx_time = + min(tx_time, g_ble_ll_conn_params.supp_max_tx_time); + + /* + * Use the same for coded and uncoded defaults. These are used when PHY + * parameters are initialized and we want to use values overridden by + * host. Make sure we do not exceed max supported time on uncoded. + */ + g_ble_ll_conn_params.conn_init_max_tx_time_uncoded = + min(BLE_LL_CONN_SUPP_TIME_MAX_UNCODED, + g_ble_ll_conn_params.conn_init_max_tx_time); + g_ble_ll_conn_params.conn_init_max_tx_time_coded = + g_ble_ll_conn_params.conn_init_max_tx_time; + + return 0; } /** diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c index c56fc660b..9b9cf268d 100644 --- a/nimble/controller/src/ble_ll_hci_vs.c +++ b/nimble/controller/src/ble_ll_hci_vs.c @@ -303,6 +303,54 @@ ble_ll_hci_vs_css_read_conn_slot(uint16_t ocf, const uint8_t *cmdbuf, } #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) +static int +ble_ll_hci_vs_set_data_len(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_data_len_cp *cmd = (const void *) cmdbuf; + struct ble_hci_vs_set_data_len_rp *rsp = (void *) rspbuf; + struct ble_ll_conn_sm *connsm; + uint16_t conn_handle; + uint16_t tx_octets; + uint16_t tx_time; + uint16_t rx_octets; + uint16_t rx_time; + int rc; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + conn_handle = le16toh(cmd->conn_handle); + connsm = ble_ll_conn_find_by_handle(conn_handle); + if (!connsm) { + return BLE_ERR_UNK_CONN_ID; + } + + tx_octets = le16toh(cmd->tx_octets); + tx_time = le16toh(cmd->tx_time); + rx_octets = le16toh(cmd->rx_octets); + rx_time = le16toh(cmd->rx_time); + + if (!ble_ll_hci_check_dle(tx_octets, tx_time) || + !ble_ll_hci_check_dle(rx_octets, rx_time)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + rc = ble_ll_conn_set_data_len(connsm, tx_octets, tx_time, rx_octets, + rx_time); + if (rc) { + return rc; + } + + rsp->conn_handle = htole16(conn_handle); + *rsplen = sizeof(*rsp); + + return 0; +} +#endif + static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR, ble_ll_hci_vs_rd_static_addr), @@ -322,6 +370,10 @@ static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_CSS_READ_CONN_SLOT, ble_ll_hci_vs_css_read_conn_slot), #endif +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_DATA_LEN, + ble_ll_hci_vs_set_data_len), +#endif }; static struct ble_ll_hci_vs_cmd * diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index b83c35aa1..cfcbd822a 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1168,6 +1168,18 @@ struct ble_hci_vs_css_read_conn_slot_rp { uint16_t conn_handle; uint16_t slot_idx; } __attribute__((packed)); +#define BLE_HCI_OCF_VS_SET_DATA_LEN (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0004)) +struct ble_hci_vs_set_data_len_cp { + uint16_t conn_handle; + uint16_t tx_octets; + uint16_t tx_time; + uint16_t rx_octets; + uint16_t rx_time; +} __attribute__((packed)); +struct ble_hci_vs_set_data_len_rp { + uint16_t conn_handle; +} __attribute__((packed)); + /* Command Specific Definitions */ /* --- Set controller to host flow control (OGF 0x03, OCF 0x0031) --- */