nimble/ll: Allow to locally update connection min/max CE length

Updating Min/Max CE Length can be done without triggering LL procedure.
We can do that if current connection parameters fits parameters
parameters provided in HCI command. Note that this is also valid
for Connections Strict Scheduling.
This commit is contained in:
Szymon Janc
2023-05-08 17:58:33 +02:00
parent abd16e6186
commit 631380aab0
6 changed files with 82 additions and 17 deletions
@@ -38,7 +38,7 @@ extern "C" {
*/
#define BLE_LL_CFG_NUM_HCI_CMD_PKTS (1)
typedef void (*ble_ll_hci_post_cmd_complete_cb)(void);
typedef void (*ble_ll_hci_post_cmd_complete_cb)(void *user_data);
#if MYNEWT_VAL(BLE_LL_HCI_VS)
typedef int (* ble_ll_hci_vs_cb_t)(uint16_t ocf,
@@ -81,6 +81,9 @@ int ble_ll_hci_check_dle(uint16_t max_octets, uint16_t max_time);
void ble_ll_hci_supp_cmd_get(uint8_t *buf);
/* Used to set post HCI command hook */
void ble_ll_hci_post_cmd_cb_set(ble_ll_hci_post_cmd_complete_cb cb, void *user_data);
#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
@@ -34,7 +34,7 @@ struct ble_ll_scan_addr_data;
struct ble_ll_sync_sm;
int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
int ble_ll_sync_cancel(void);
int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len);
int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len);
+52 -3
View File
@@ -946,6 +946,34 @@ ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len)
return BLE_ERR_SUCCESS;
}
static bool
ble_ll_conn_params_in_range(struct ble_ll_conn_sm *connsm,
const struct ble_hci_le_conn_update_cp *cmd)
{
if (!IN_RANGE(connsm->conn_itvl, le16toh(cmd->conn_itvl_min),
le16toh(cmd->conn_itvl_max))) {
return false;
}
if (connsm->periph_latency != le16toh(cmd->conn_latency)) {
return false;
}
if (connsm->supervision_tmo != le16toh(cmd->supervision_timeout)) {
return false;
}
return true;
}
static void
ble_ll_conn_hci_update_complete_event(void *user_data)
{
struct ble_ll_conn_sm *connsm = user_data;
ble_ll_hci_ev_conn_update(connsm, BLE_ERR_SUCCESS);
}
/**
* Called to process a connection update command.
*
@@ -962,6 +990,7 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len)
uint16_t handle;
struct ble_ll_conn_sm *connsm;
struct hci_conn_update *hcu;
uint16_t max_ce_len;
/*
* XXX: must deal with peripheral not supporting this feature and using
@@ -979,6 +1008,26 @@ ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len)
return BLE_ERR_UNK_CONN_ID;
}
/* if current connection parameters fit updated values we don't have to
* trigger LL procedure and just update local values (Min/Max CE Length)
*
* Note that this is also allowed for CSS as nothing changes WRT connections
* scheduling.
*/
if (ble_ll_conn_params_in_range(connsm, cmd)) {
max_ce_len = le16toh(cmd->max_ce_len);
if (le16toh(cmd->min_ce_len) > max_ce_len) {
return BLE_ERR_INV_HCI_CMD_PARMS;
}
connsm->max_ce_len_ticks = ble_ll_tmr_u2t_up(max_ce_len * BLE_LL_CONN_CE_USECS);
ble_ll_hci_post_cmd_cb_set(ble_ll_conn_hci_update_complete_event, connsm);
return BLE_ERR_SUCCESS;
}
#if MYNEWT_VAL(BLE_LL_CONN_STRICT_SCHED)
/* Do not allow connection update if css in enabled, we only allow to move
* anchor point (i.e. change slot) via dedicated HCI command.
@@ -1198,7 +1247,7 @@ done:
* safe to use g_ble_ll_conn_comp_ev
*/
static void
ble_ll_conn_hci_cancel_conn_complete_event(void)
ble_ll_conn_hci_cancel_conn_complete_event(void *user_data)
{
BLE_LL_ASSERT(g_ble_ll_conn_comp_ev);
@@ -1216,7 +1265,7 @@ ble_ll_conn_hci_cancel_conn_complete_event(void)
* @return int
*/
int
ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
ble_ll_conn_create_cancel(void)
{
int rc;
struct ble_ll_conn_sm *connsm;
@@ -1236,7 +1285,7 @@ ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
ble_ll_scan_sm_stop(1);
ble_ll_conn_end(connsm, BLE_ERR_UNK_CONN_ID);
*post_cmd_cb = ble_ll_conn_hci_cancel_conn_complete_event;
ble_ll_hci_post_cmd_cb_set(ble_ll_conn_hci_cancel_conn_complete_event, NULL);
rc = BLE_ERR_SUCCESS;
} else {
+1 -1
View File
@@ -204,7 +204,7 @@ int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len,
uint8_t *rspbuf, uint8_t *rsplen);
int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
int ble_ll_conn_create_cancel(void);
void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
uint8_t *evbuf, struct ble_ll_adv_sm *advsm);
+21 -8
View File
@@ -56,6 +56,9 @@ static uint64_t g_ble_ll_hci_event_mask2;
static int16_t rx_path_pwr_compensation;
static int16_t tx_path_pwr_compensation;
static ble_ll_hci_post_cmd_complete_cb hci_cmd_post_cb = NULL;
static void *hci_cmd_post_cb_user_data = NULL;
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
static enum {
ADV_MODE_ANY,
@@ -879,8 +882,7 @@ ble_ll_hci_le_set_host_chan_class(const uint8_t *cmdbuf, uint8_t len)
*/
static int
ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
uint8_t *rspbuf, uint8_t *rsplen,
ble_ll_hci_post_cmd_complete_cb *cb)
uint8_t *rspbuf, uint8_t *rsplen)
{
int rc;
@@ -960,7 +962,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
break;
case BLE_HCI_OCF_LE_CREATE_CONN_CANCEL:
if (len == 0) {
rc = ble_ll_conn_create_cancel(cb);
rc = ble_ll_conn_create_cancel();
}
break;
#endif
@@ -1187,7 +1189,7 @@ ble_ll_hci_le_cmd_proc(const uint8_t *cmdbuf, uint8_t len, uint16_t ocf,
break;
case BLE_HCI_OCF_LE_PERIODIC_ADV_CREATE_SYNC_CANCEL:
if (len == 0) {
rc = ble_ll_sync_cancel(cb);
rc = ble_ll_sync_cancel();
}
break;
case BLE_HCI_OCF_LE_PERIODIC_ADV_TERM_SYNC:
@@ -1736,6 +1738,15 @@ ble_ll_hci_cmd_fake_dual_mode(uint16_t opcode, uint8_t *cmdbuf, uint8_t len,
}
#endif
void
ble_ll_hci_post_cmd_cb_set(ble_ll_hci_post_cmd_complete_cb cb, void *user_data)
{
BLE_LL_ASSERT(hci_cmd_post_cb == NULL);
hci_cmd_post_cb = cb;
hci_cmd_post_cb_user_data = user_data;
}
/**
* Called to process an HCI command from the host.
*
@@ -1750,7 +1761,6 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
struct ble_hci_cmd *cmd;
uint16_t opcode;
uint16_t ocf;
ble_ll_hci_post_cmd_complete_cb post_cb = NULL;
struct ble_hci_ev *hci_ev;
struct ble_hci_ev_command_status *cmd_status;
struct ble_hci_ev_command_complete *cmd_complete;
@@ -1817,7 +1827,7 @@ ble_ll_hci_cmd_proc(struct ble_npl_event *ev)
rc = ble_ll_hci_status_params_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen);
break;
case BLE_HCI_OGF_LE:
rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen, &post_cb);
rc = ble_ll_hci_le_cmd_proc(cmd->data, cmd->length, ocf, rspbuf, &rsplen);
break;
#if MYNEWT_VAL(BLE_LL_HCI_VS)
case BLE_HCI_OGF_VENDOR:
@@ -1875,8 +1885,11 @@ send_cc_cs:
ble_ll_hci_event_send(hci_ev);
/* Call post callback if set by command handler */
if (post_cb) {
post_cb();
if (hci_cmd_post_cb) {
hci_cmd_post_cb(hci_cmd_post_cb_user_data);
hci_cmd_post_cb = NULL;
hci_cmd_post_cb_user_data = NULL;
}
BLE_LL_DEBUG_GPIO(HCI_CMD, 0);
+3 -3
View File
@@ -1559,13 +1559,13 @@ ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len)
}
static void
ble_ll_sync_cancel_complete_event(void)
ble_ll_sync_cancel_complete_event(void *user_data)
{
ble_ll_sync_est_event_failed(BLE_ERR_OPERATION_CANCELLED);
}
int
ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
ble_ll_sync_cancel(void)
{
struct ble_ll_sync_sm *sm;
os_sr_t sr;
@@ -1596,7 +1596,7 @@ ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb)
OS_EXIT_CRITICAL(sr);
/* g_ble_ll_sync_create_comp_ev will be cleared by this callback */
*post_cmd_cb = ble_ll_sync_cancel_complete_event;
ble_ll_hci_post_cmd_cb_set(ble_ll_sync_cancel_complete_event, NULL);
return BLE_ERR_SUCCESS;
}