mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-10-18 11:17:54 +00:00
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:
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user