mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-19 00:09:58 +00:00
add APIs for multiple connect
This commit is contained in:
committed by
Abhinav Kudnar
parent
3a1db72f83
commit
d714e24fb7
@@ -1141,6 +1141,53 @@ struct ble_gap_event {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
/** @brief multiple Connection parameters */
|
||||
struct ble_gap_multi_conn_params {
|
||||
/** The type of address the stack should use for itself. */
|
||||
uint8_t own_addr_type;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/** Define on which PHYs connection attempt should be done */
|
||||
uint8_t phy_mask;
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
/** The address of the peer to connect to. */
|
||||
const ble_addr_t *peer_addr;
|
||||
|
||||
/** The duration of the discovery procedure. */
|
||||
int32_t duration_ms;
|
||||
|
||||
/**
|
||||
* Additional arguments specifying the particulars of the connect procedure. When extended
|
||||
* adv is disabled or BLE_GAP_LE_PHY_1M_MASK is set in phy_mask this parameter can't be
|
||||
* specified to null.
|
||||
*/
|
||||
const struct ble_gap_conn_params *phy_1m_conn_params;
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
/**
|
||||
* Additional arguments specifying the particulars of the connect procedure. When
|
||||
* BLE_GAP_LE_PHY_2M_MASK is set in phy_mask this parameter can't be specified to null.
|
||||
*/
|
||||
const struct ble_gap_conn_params *phy_2m_conn_params;
|
||||
|
||||
/**
|
||||
* Additional arguments specifying the particulars of the connect procedure. When
|
||||
* BLE_GAP_LE_PHY_CODED_MASK is set in phy_mask this parameter can't be specified to null.
|
||||
*/
|
||||
const struct ble_gap_conn_params *phy_coded_conn_params;
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
/**
|
||||
* The minimum length occupied by this connection in scheduler. 0 means disable the
|
||||
* optimization for this connection.
|
||||
*/
|
||||
uint32_t scheduling_len_us;
|
||||
};
|
||||
#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
|
||||
typedef int ble_gap_event_fn(struct ble_gap_event *event, void *arg);
|
||||
typedef int ble_gap_conn_foreach_handle_fn(uint16_t conn_handle, void *arg);
|
||||
|
||||
@@ -1937,6 +1984,44 @@ int ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
|
||||
const struct ble_gap_conn_params *phy_coded_conn_params,
|
||||
ble_gap_event_fn *cb, void *cb_arg);
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
/**
|
||||
* @brief Enable the optimization of multiple connections.
|
||||
*
|
||||
* @param enable Enable or disable the optimization.
|
||||
* @param common_factor The greatest common factor of all intervals in 0.625ms units.
|
||||
* @return 0 on success;
|
||||
*
|
||||
*/
|
||||
int ble_gap_common_factor_set(bool enable, uint32_t common_factor);
|
||||
|
||||
/**
|
||||
* Initiates an extended connect procedure with optimization.
|
||||
*
|
||||
* @param multi_conn_params Additional arguments specifying the particulars
|
||||
* of the connect procedure.
|
||||
* @param cb The callback to associate with this connect
|
||||
* procedure. When the connect procedure
|
||||
* completes, the result is reported through
|
||||
* this callback. If the connect procedure
|
||||
* succeeds, the connection inherits this
|
||||
* callback as its event-reporting mechanism.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EALREADY if a connection attempt is
|
||||
* already in progress;
|
||||
* BLE_HS_EBUSY if initiating a connection is not
|
||||
* possible because scanning is in progress;
|
||||
* BLE_HS_EDONE if the specified peer is already
|
||||
* connected;
|
||||
* Other nonzero on error.
|
||||
*/
|
||||
int ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params,
|
||||
ble_gap_event_fn *cb, void *cb_arg);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Aborts a connect procedure in progress.
|
||||
*
|
||||
|
||||
+180
-1
@@ -235,6 +235,17 @@ static os_membuf_t ble_gap_update_entry_mem[
|
||||
static struct os_mempool ble_gap_update_entry_pool;
|
||||
static struct ble_gap_update_entry_list ble_gap_update_entries;
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
struct ble_gap_multi_conn_state
|
||||
{
|
||||
bool enabled;
|
||||
bool scheduling_len_set;
|
||||
uint32_t common_factor;
|
||||
};
|
||||
|
||||
static struct ble_gap_multi_conn_state ble_gap_multi_conn;
|
||||
#endif
|
||||
|
||||
static void ble_gap_update_entry_free(struct ble_gap_update_entry *entry);
|
||||
|
||||
#if NIMBLE_BLE_CONNECT
|
||||
@@ -5337,6 +5348,15 @@ ble_gap_ext_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
|
||||
|
||||
STATS_INC(ble_gap_stats, initiate);
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
/* If the optimization is enabled, we disallow to invoke this API directly.
|
||||
* See @ble_gap_multi_connect()
|
||||
*/
|
||||
if (ble_gap_multi_conn.enabled && !ble_gap_multi_conn.scheduling_len_set) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
if (ble_gap_conn_active()) {
|
||||
@@ -5466,6 +5486,15 @@ ble_gap_connect(uint8_t own_addr_type, const ble_addr_t *peer_addr,
|
||||
|
||||
STATS_INC(ble_gap_stats, initiate);
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
/* If the optimization is enabled, we disallow to invoke this API directly.
|
||||
* See @ble_gap_multi_connect()
|
||||
*/
|
||||
if (ble_gap_multi_conn.enabled && !ble_gap_multi_conn.scheduling_len_set) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
#endif // MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
|
||||
ble_hs_lock();
|
||||
|
||||
if (ble_gap_conn_active()) {
|
||||
@@ -5593,9 +5622,155 @@ done:
|
||||
#else
|
||||
return BLE_HS_ENOTSUP;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
static bool
|
||||
ble_gap_interval_is_integer_multiple(uint32_t min_itvl, uint32_t max_itvl)
|
||||
{
|
||||
if (max_itvl < ble_gap_multi_conn.common_factor) {
|
||||
return false;
|
||||
}
|
||||
|
||||
max_itvl = max_itvl - (max_itvl % ble_gap_multi_conn.common_factor);
|
||||
if (max_itvl >= min_itvl) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int
|
||||
ble_gap_common_factor_set(bool enable, uint32_t common_factor)
|
||||
{
|
||||
int rc;
|
||||
uint8_t vs_cmd[5];
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
return BLE_HS_EDISABLED;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
vs_cmd[0] = common_factor & 0xfful;
|
||||
vs_cmd[1] = (common_factor >> 8) & 0xfful;
|
||||
vs_cmd[2] = (common_factor >> 16) & 0xfful;
|
||||
vs_cmd[3] = (common_factor >> 24) & 0xfful;
|
||||
vs_cmd[4] = 1;
|
||||
} else {
|
||||
memset(vs_cmd, 0, sizeof(vs_cmd));
|
||||
}
|
||||
|
||||
rc = ble_hs_hci_send_vs_cmd(0x10f, (const void *)vs_cmd, sizeof(vs_cmd), NULL, 0);
|
||||
if (rc == 0) {
|
||||
if (enable) {
|
||||
ble_gap_multi_conn.enabled = true;
|
||||
ble_gap_multi_conn.common_factor = common_factor;
|
||||
} else {
|
||||
ble_gap_multi_conn.enabled = false;
|
||||
ble_gap_multi_conn.common_factor = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_ROLE_CENTRAL)
|
||||
int
|
||||
ble_gap_multi_connect(struct ble_gap_multi_conn_params *multi_conn_params,
|
||||
ble_gap_event_fn *cb, void *cb_arg)
|
||||
{
|
||||
int rc;
|
||||
uint8_t vs_cmd[5];
|
||||
uint32_t scheduling_len_us;
|
||||
const struct ble_gap_conn_params *conn_params;
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
uint8_t phy_mask;
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
if (!ble_hs_is_enabled()) {
|
||||
return BLE_HS_EDISABLED;
|
||||
}
|
||||
|
||||
if (!ble_gap_multi_conn.enabled || (multi_conn_params == NULL)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
phy_mask = multi_conn_params->phy_mask;
|
||||
if (phy_mask == 0) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
|
||||
scheduling_len_us = multi_conn_params->scheduling_len_us;
|
||||
/* `scheduling_len_us == 0` is allowed. It indicates that the optimization for this connection
|
||||
* is disabled. The connection interval must be an integer multiple of `common factor`. Note
|
||||
* that the unit of the connection interval is 1.25ms, while the common factor's unit is 0.625ms.
|
||||
*/
|
||||
if (scheduling_len_us != 0) {
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
if (phy_mask & BLE_GAP_LE_PHY_1M_MASK) {
|
||||
conn_params = multi_conn_params->phy_1m_conn_params;
|
||||
if ((conn_params == NULL) ||
|
||||
!ble_gap_interval_is_integer_multiple(conn_params->itvl_min << 1,
|
||||
conn_params->itvl_max << 1)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
}
|
||||
if (phy_mask & BLE_GAP_LE_PHY_2M_MASK) {
|
||||
conn_params = multi_conn_params->phy_2m_conn_params;
|
||||
if ((conn_params == NULL) ||
|
||||
!ble_gap_interval_is_integer_multiple(conn_params->itvl_min << 1,
|
||||
conn_params->itvl_max << 1)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
}
|
||||
if (phy_mask & BLE_GAP_LE_PHY_CODED_MASK) {
|
||||
conn_params = multi_conn_params->phy_coded_conn_params;
|
||||
if ((conn_params == NULL) ||
|
||||
!ble_gap_interval_is_integer_multiple(conn_params->itvl_min << 1,
|
||||
conn_params->itvl_max << 1)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
}
|
||||
#else
|
||||
conn_params = multi_conn_params->phy_1m_conn_params;
|
||||
if ((conn_params == NULL) ||
|
||||
!ble_gap_interval_is_integer_multiple(conn_params->itvl_min << 1,
|
||||
conn_params->itvl_max << 1)) {
|
||||
return BLE_HS_EINVAL;
|
||||
}
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
}
|
||||
|
||||
vs_cmd[0] = 0;
|
||||
vs_cmd[1] = scheduling_len_us & 0xfful;
|
||||
vs_cmd[2] = (scheduling_len_us >> 8) & 0xfful;
|
||||
vs_cmd[3] = (scheduling_len_us >> 16) & 0xfful;
|
||||
vs_cmd[4] = (scheduling_len_us >> 24) & 0xfful;
|
||||
rc = ble_hs_hci_send_vs_cmd(0x110, (const void *)vs_cmd, sizeof(vs_cmd), NULL, 0);
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
ble_gap_multi_conn.scheduling_len_set = true;
|
||||
#if MYNEWT_VAL(BLE_EXT_ADV)
|
||||
rc = ble_gap_ext_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr,
|
||||
multi_conn_params->duration_ms, multi_conn_params->phy_mask,
|
||||
multi_conn_params->phy_1m_conn_params,
|
||||
multi_conn_params->phy_2m_conn_params,
|
||||
multi_conn_params->phy_coded_conn_params, cb, cb_arg);
|
||||
#else
|
||||
rc = ble_gap_ext_connect(multi_conn_params->own_addr_type, multi_conn_params->peer_addr,
|
||||
multi_conn_params->duration_ms, multi_conn_params->phy_1m_conn_params,
|
||||
cb, cb_arg);
|
||||
#endif // MYNEWT_VAL(BLE_EXT_ADV)
|
||||
ble_gap_multi_conn.scheduling_len_set = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
#endif // MYNEWT_VAL(BLE_ROLE_CENTRAL)
|
||||
#endif
|
||||
|
||||
int
|
||||
ble_gap_conn_active(void)
|
||||
{
|
||||
@@ -6777,6 +6952,10 @@ ble_gap_init(void)
|
||||
memset(&ble_gap_master, 0, sizeof(ble_gap_master));
|
||||
memset(ble_gap_slave, 0, sizeof(ble_gap_slave));
|
||||
|
||||
#if MYNEWT_VAL(OPTIMIZE_MULTI_CONN)
|
||||
memset(&ble_gap_multi_conn, 0, sizeof(ble_gap_multi_conn));
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_PERIODIC_ADV)
|
||||
memset(&ble_gap_sync, 0, sizeof(ble_gap_sync));
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user