Bluetooth: host: Add non-connectable directed advertising support
This patch introduces two major changes to the directed advertising feature of the bluetooth host. Deprecating the bt_conn_create_slave_le, and removing bt_conn_le_create_slave which has never been released. This behaviour has now been moved by to providing the peer direct address into the advertising parameters. Introducing directed advertising support for nonconnectable directed extended advertising, both scannable and non-scannable. A bug was also fixed in the the directed-adv command in the shell when the argument "low" was given. The advertiseng parameter pointer declared with BT_LE_ADV_CONN_DIR_LOW_DUTY was declared in a scope that was no longer valid when it was used to start the advertiser. Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
This commit is contained in:
parent
5a149dfca6
commit
18bee9178f
10 changed files with 267 additions and 219 deletions
|
@ -321,6 +321,8 @@ enum {
|
|||
* connection happens. If this option is not set the stack will
|
||||
* take care of keeping advertising enabled even as connections
|
||||
* occur.
|
||||
* If Advertising directed and connectable then this behaviour is
|
||||
* the default behaviour and this flag has no effect.
|
||||
*/
|
||||
BT_LE_ADV_OPT_ONE_TIME = BIT(1),
|
||||
|
||||
|
@ -337,8 +339,7 @@ enum {
|
|||
BT_LE_ADV_OPT_USE_NAME = BIT(3),
|
||||
|
||||
/** Use low duty directed advertising mode, otherwise high duty mode
|
||||
* will be used. This option is only effective when used with
|
||||
* bt_conn_create_slave_le().
|
||||
* will be used.
|
||||
*/
|
||||
BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY = BIT(4),
|
||||
|
||||
|
@ -450,13 +451,27 @@ struct bt_le_adv_param {
|
|||
u8_t secondary_max_skip;
|
||||
|
||||
/** Bit-field of advertising options */
|
||||
u32_t options;
|
||||
u32_t options;
|
||||
|
||||
/** Minimum Advertising Interval (N * 0.625) */
|
||||
u32_t interval_min;
|
||||
|
||||
/** Maximum Advertising Interval (N * 0.625) */
|
||||
u32_t interval_max;
|
||||
|
||||
/** Directed advertising to peer
|
||||
*
|
||||
* When this parameter is set the advertiser will send directed
|
||||
* advertising to the remote device.
|
||||
*
|
||||
* The advertising type will either be high duty cycle, or low duty
|
||||
* cycle if the BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY option is enabled.
|
||||
*
|
||||
* In case of connectable high duty cycle if the connection could not
|
||||
* be established within the timeout the connected() callback will be
|
||||
* called with the status set to @ref BT_HCI_ERR_ADV_TIMEOUT.
|
||||
*/
|
||||
const bt_addr_le_t *peer;
|
||||
};
|
||||
|
||||
/** Helper to declare advertising parameters inline
|
||||
|
@ -464,8 +479,10 @@ struct bt_le_adv_param {
|
|||
* @param _options Advertising Options
|
||||
* @param _int_min Minimum advertising interval
|
||||
* @param _int_max Maximum advertising interval
|
||||
* @param _peer Peer address, set to NULL for undirected advertising or
|
||||
* address of peer for directed advertising.
|
||||
*/
|
||||
#define BT_LE_ADV_PARAM(_options, _int_min, _int_max) \
|
||||
#define BT_LE_ADV_PARAM(_options, _int_min, _int_max, _peer) \
|
||||
((struct bt_le_adv_param[]) { { \
|
||||
.id = BT_ID_DEFAULT, \
|
||||
.sid = 0, \
|
||||
|
@ -473,37 +490,46 @@ struct bt_le_adv_param {
|
|||
.options = (_options), \
|
||||
.interval_min = (_int_min), \
|
||||
.interval_max = (_int_max), \
|
||||
.peer = (_peer), \
|
||||
} })
|
||||
|
||||
#define BT_LE_ADV_CONN_DIR(_peer) BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
|
||||
BT_LE_ADV_OPT_ONE_TIME, 0, 0,\
|
||||
_peer)
|
||||
|
||||
|
||||
#define BT_LE_ADV_CONN BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE, \
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2)
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
|
||||
#define BT_LE_ADV_CONN_NAME BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
|
||||
BT_LE_ADV_OPT_USE_NAME, \
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2)
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
|
||||
#define BT_LE_ADV_CONN_DIR_LOW_DUTY \
|
||||
#define BT_LE_ADV_CONN_DIR_LOW_DUTY(_peer) \
|
||||
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_ONE_TIME | \
|
||||
BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY, \
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2)
|
||||
|
||||
#define BT_LE_ADV_CONN_DIR BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | \
|
||||
BT_LE_ADV_OPT_ONE_TIME, 0, 0)
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, BT_GAP_ADV_FAST_INT_MAX_2, \
|
||||
_peer)
|
||||
|
||||
#define BT_LE_ADV_NCONN BT_LE_ADV_PARAM(0, BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2)
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
|
||||
#define BT_LE_ADV_NCONN_NAME BT_LE_ADV_PARAM(BT_LE_ADV_OPT_USE_NAME, \
|
||||
BT_GAP_ADV_FAST_INT_MIN_2, \
|
||||
BT_GAP_ADV_FAST_INT_MAX_2)
|
||||
BT_GAP_ADV_FAST_INT_MAX_2, NULL)
|
||||
|
||||
/** @brief Start advertising
|
||||
*
|
||||
* Set advertisement data, scan response data, advertisement parameters
|
||||
* and start advertising.
|
||||
*
|
||||
* When the advertisement parameter peer address has been set the advertising
|
||||
* will be directed to the peer. In this case advertisement data and scan
|
||||
* response data parameters are ignored. If the mode is high duty cycle
|
||||
* the timeout will be @ref BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT.
|
||||
*
|
||||
* @param param Advertising parameters.
|
||||
* @param ad Data to be used in advertisement packets.
|
||||
* @param ad_len Number of elements in ad
|
||||
|
@ -569,6 +595,10 @@ struct bt_le_ext_adv_start_param {
|
|||
* Application will be notified by the advertiser sent callback.
|
||||
* Set to zero for no timeout.
|
||||
*
|
||||
* When using high duty cycle directed connectable advertising then
|
||||
* this parameters must be set to a non-zero value less than or equal
|
||||
* to the maximum of @ref BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT.
|
||||
*
|
||||
* If privacy :option:`CONFIG_BT_PRIVACY` is enabled then the timeout
|
||||
* must be less than :option:`CONFIG_BT_RPA_TIMEOUT`.
|
||||
*/
|
||||
|
|
|
@ -471,27 +471,26 @@ int bt_le_set_auto_conn(const bt_addr_le_t *addr,
|
|||
* The caller gets a new reference to the connection object which must be
|
||||
* released with bt_conn_unref() once done using the object.
|
||||
*
|
||||
* @param[in] peer Remote address.
|
||||
* @param[in] param Directed advertising parameters.
|
||||
* @param[out] conn Valid connection object on success.
|
||||
* @param peer Remote address.
|
||||
* @param param Directed advertising parameters.
|
||||
*
|
||||
* @return Zero on success or (negative) error code on failure.
|
||||
* @return Valid connection object on success or NULL otherwise.
|
||||
*/
|
||||
int bt_conn_le_create_slave(const bt_addr_le_t *peer,
|
||||
const struct bt_le_adv_param *param,
|
||||
struct bt_conn **conn);
|
||||
|
||||
__deprecated static inline
|
||||
struct bt_conn *bt_conn_create_slave_le(const bt_addr_le_t *peer,
|
||||
const struct bt_le_adv_param *param)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
struct bt_le_adv_param adv_param = *param;
|
||||
|
||||
if (bt_conn_le_create_slave(peer, param, &conn)) {
|
||||
adv_param.options |= (BT_LE_ADV_OPT_CONNECTABLE |
|
||||
BT_LE_ADV_OPT_ONE_TIME);
|
||||
adv_param.peer = peer;
|
||||
|
||||
if (!bt_le_adv_start(&adv_param, NULL, 0, NULL, 0)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return conn;
|
||||
return bt_conn_lookup_addr_le(param->id, peer);
|
||||
}
|
||||
|
||||
/** Security level. */
|
||||
|
@ -622,9 +621,9 @@ struct bt_conn_cb {
|
|||
* @ref bt_conn_disconnect or by the timeout in the host through
|
||||
* @ref bt_conn_le_create_param timeout parameter, which defaults to
|
||||
* :option:`CONFIG_BT_CREATE_CONN_TIMEOUT` seconds.
|
||||
* - @p BT_HCI_ERR_ADV_TIMEOUT Directed advertiser started by @ref
|
||||
* bt_conn_create_slave_le with high duty cycle timed out after 1.28
|
||||
* seconds.
|
||||
* - @p BT_HCI_ERR_ADV_TIMEOUT High duty cycle directed connectable
|
||||
* advertiser started by @ref bt_le_adv_start or bt_le_ext_adv_start
|
||||
* failed to be connected within the timeout.
|
||||
*/
|
||||
void (*connected)(struct bt_conn *conn, u8_t err);
|
||||
|
||||
|
|
|
@ -123,6 +123,11 @@ enum {
|
|||
#define BT_GAP_SID_INVALID 0xff
|
||||
#define BT_GAP_NO_TIMEOUT 0x0000
|
||||
|
||||
/* The maximum allowed high duty cycle directed advertising timeout, 1.28
|
||||
* seconds in 10 ms unit.
|
||||
*/
|
||||
#define BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT 128
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1088,12 +1088,6 @@ struct bt_hci_cp_le_set_ext_scan_rsp_data {
|
|||
u8_t data[251];
|
||||
} __packed;
|
||||
|
||||
/* If the advertising is high duty cycle connectable directed advertising, then
|
||||
* Duration[i] shall be less than or equal to 1.28 seconds and shall not be
|
||||
* equal to 0.
|
||||
*/
|
||||
#define BT_HCI_LE_EXT_ADV_DURATION_HI_DC_MAX 128
|
||||
|
||||
#define BT_HCI_OP_LE_SET_EXT_ADV_ENABLE BT_OP(BT_OGF_LE, 0x0039)
|
||||
struct bt_hci_ext_adv_set {
|
||||
u8_t handle;
|
||||
|
|
|
@ -38,9 +38,9 @@ static K_THREAD_STACK_DEFINE(pwr_thread_stack, 320);
|
|||
|
||||
static const s8_t txp[DEVICE_BEACON_TXPOWER_NUM] = {4, 0, -3, -8,
|
||||
-15, -18, -23, -30};
|
||||
static const struct bt_le_adv_param *param = BT_LE_ADV_PARAM
|
||||
(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_NAME,
|
||||
0x0020, 0x0020);
|
||||
static const struct bt_le_adv_param *param =
|
||||
BT_LE_ADV_PARAM(BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_NAME,
|
||||
0x0020, 0x0020, NULL);
|
||||
|
||||
static void read_conn_rssi(u16_t handle, s8_t *rssi)
|
||||
{
|
||||
|
|
|
@ -1553,6 +1553,27 @@ void bt_conn_process_tx(struct bt_conn *conn)
|
|||
}
|
||||
}
|
||||
|
||||
bool bt_conn_exists_le(u8_t id, const bt_addr_le_t *peer)
|
||||
{
|
||||
struct bt_conn *conn = bt_conn_lookup_addr_le(id, peer);
|
||||
|
||||
if (conn) {
|
||||
/* Connection object already exists.
|
||||
* If the connection state is not "disconnected",then the
|
||||
* connection was created but has not yet been disconnected.
|
||||
* If the connection state is "disconnected" then the connection
|
||||
* still has valid references. The last reference of the stack
|
||||
* is released after the disconnected callback.
|
||||
*/
|
||||
BT_WARN("Found valid connection in %s state",
|
||||
state2str(conn->state));
|
||||
bt_conn_unref(conn);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
struct bt_conn *bt_conn_add_le(u8_t id, const bt_addr_le_t *peer)
|
||||
{
|
||||
struct bt_conn *conn = conn_new();
|
||||
|
@ -2068,6 +2089,7 @@ int bt_conn_disconnect(struct bt_conn *conn, u8_t reason)
|
|||
}
|
||||
return 0;
|
||||
case BT_CONN_CONNECT_DIR_ADV:
|
||||
BT_WARN("Deprecated: Use bt_le_adv_stop instead");
|
||||
conn->err = reason;
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
|
||||
|
@ -2273,19 +2295,7 @@ int bt_conn_le_create(const bt_addr_le_t *peer,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_addr_le(BT_ID_DEFAULT, peer);
|
||||
if (conn) {
|
||||
/* Connection object already exists.
|
||||
* If the connection state is "connect" or "connected" then
|
||||
* this connection object was created using this API but has not
|
||||
* yet been disconnected.
|
||||
* If the connection state is "disconnected" then the connection
|
||||
* still has valid references. The last reference of the stack
|
||||
* is released after the disconnected callback.
|
||||
*/
|
||||
BT_WARN("Found valid connection in %s state",
|
||||
state2str(conn->state));
|
||||
bt_conn_unref(conn);
|
||||
if (bt_conn_exists_le(BT_ID_DEFAULT, peer)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -2398,53 +2408,6 @@ int bt_le_set_auto_conn(const bt_addr_le_t *addr,
|
|||
#endif /* !defined(CONFIG_BT_WHITELIST) */
|
||||
#endif /* CONFIG_BT_CENTRAL */
|
||||
|
||||
#if defined(CONFIG_BT_PERIPHERAL)
|
||||
int bt_conn_le_create_slave(const bt_addr_le_t *peer,
|
||||
const struct bt_le_adv_param *param,
|
||||
struct bt_conn **ret_conn)
|
||||
{
|
||||
int err;
|
||||
struct bt_conn *conn;
|
||||
struct bt_le_adv_param param_int;
|
||||
|
||||
memcpy(¶m_int, param, sizeof(param_int));
|
||||
param_int.options |= (BT_LE_ADV_OPT_CONNECTABLE |
|
||||
BT_LE_ADV_OPT_ONE_TIME);
|
||||
|
||||
conn = bt_conn_lookup_addr_le(param->id, peer);
|
||||
if (conn) {
|
||||
/* Connection object already exists.
|
||||
* If the connection state is "connect-dir-adv" or "connected"
|
||||
* then this connection object was created using this API but
|
||||
* has not yet been disconnected.
|
||||
* If the connection state is "disconnected" then the connection
|
||||
* still has valid references. The last reference of the stack
|
||||
* is released after the disconnected callback.
|
||||
*/
|
||||
BT_WARN("Found valid connection in %s state",
|
||||
state2str(conn->state));
|
||||
bt_conn_unref(conn);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
conn = bt_conn_add_le(param->id, peer);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV);
|
||||
|
||||
err = bt_le_adv_start_internal(¶m_int, NULL, 0, NULL, 0, peer);
|
||||
if (err) {
|
||||
bt_conn_unref(conn);
|
||||
return err;
|
||||
}
|
||||
|
||||
*ret_conn = conn;
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_BT_PERIPHERAL */
|
||||
|
||||
int bt_conn_le_conn_update(struct bt_conn *conn,
|
||||
const struct bt_le_conn_param *param)
|
||||
{
|
||||
|
|
|
@ -171,6 +171,9 @@ static inline int bt_conn_send(struct bt_conn *conn, struct net_buf *buf)
|
|||
return bt_conn_send_cb(conn, buf, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Check if a connection object with the peer already exists */
|
||||
bool bt_conn_exists_le(u8_t id, const bt_addr_le_t *peer);
|
||||
|
||||
/* Add a new LE connection */
|
||||
struct bt_conn *bt_conn_add_le(u8_t id, const bt_addr_le_t *peer);
|
||||
|
||||
|
|
|
@ -1753,7 +1753,7 @@ static struct bt_conn *find_pending_connect(u8_t role, bt_addr_le_t *peer_addr)
|
|||
|
||||
/*
|
||||
* Make lookup to check if there's a connection object in
|
||||
* CONNECT or DIR_ADV state associated with passed peer LE address.
|
||||
* CONNECT or CONNECT_AUTO state associated with passed peer LE address.
|
||||
*/
|
||||
if (IS_ENABLED(CONFIG_BT_CENTRAL) && role == BT_HCI_ROLE_MASTER) {
|
||||
conn = bt_conn_lookup_state_le(BT_ID_DEFAULT, peer_addr,
|
||||
|
@ -6934,8 +6934,30 @@ bool bt_addr_le_is_bonded(u8_t id, const bt_addr_le_t *addr)
|
|||
}
|
||||
}
|
||||
|
||||
static bool valid_adv_param(const struct bt_le_adv_param *param, bool dir_adv)
|
||||
static bool valid_adv_ext_param(const struct bt_le_adv_param *param)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
||||
BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
|
||||
if (param->peer &&
|
||||
!(param->options & BT_LE_ADV_OPT_EXT_ADV) &&
|
||||
!(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
||||
/* Cannot do directed non-connectable advertising
|
||||
* without extended advertising.
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(param->options & BT_LE_ADV_OPT_EXT_ADV) &&
|
||||
param->options & (BT_LE_ADV_OPT_EXT_ADV |
|
||||
BT_LE_ADV_OPT_NO_2M |
|
||||
BT_LE_ADV_OPT_CODED |
|
||||
BT_LE_ADV_OPT_ANONYMOUS |
|
||||
BT_LE_ADV_OPT_USE_TX_POWER)) {
|
||||
/* Extended options require extended advertising. */
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (param->id >= bt_dev.id_count ||
|
||||
!bt_addr_le_cmp(&bt_dev.id_addr[param->id], BT_ADDR_LE_ANY)) {
|
||||
return false;
|
||||
|
@ -6954,7 +6976,8 @@ static bool valid_adv_param(const struct bt_le_adv_param *param, bool dir_adv)
|
|||
}
|
||||
}
|
||||
|
||||
if ((param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) || !dir_adv) {
|
||||
if ((param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) ||
|
||||
!param->peer) {
|
||||
if (param->interval_min > param->interval_max ||
|
||||
param->interval_min < 0x0020 ||
|
||||
param->interval_max > 0x4000) {
|
||||
|
@ -6965,6 +6988,19 @@ static bool valid_adv_param(const struct bt_le_adv_param *param, bool dir_adv)
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool valid_adv_param(const struct bt_le_adv_param *param)
|
||||
{
|
||||
if (param->options & BT_LE_ADV_OPT_EXT_ADV) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (param->peer && !(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return valid_adv_ext_param(param);
|
||||
}
|
||||
|
||||
static inline bool ad_has_name(const struct bt_data *ad, size_t ad_len)
|
||||
{
|
||||
size_t i;
|
||||
|
@ -7077,8 +7113,8 @@ static u8_t get_filter_policy(u8_t options)
|
|||
}
|
||||
}
|
||||
|
||||
int le_adv_set_random_addr(struct bt_le_ext_adv *adv, u32_t options,
|
||||
bool dir_adv, u8_t *own_addr_type)
|
||||
static int le_adv_set_random_addr(struct bt_le_ext_adv *adv, u32_t options,
|
||||
bool dir_adv, u8_t *own_addr_type)
|
||||
{
|
||||
const bt_addr_le_t *id_addr;
|
||||
int err = 0;
|
||||
|
@ -7173,15 +7209,63 @@ int le_adv_set_random_addr(struct bt_le_ext_adv *adv, u32_t options,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int le_adv_start_add_conn(const struct bt_le_ext_adv *adv,
|
||||
struct bt_conn **out_conn)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) {
|
||||
/* Undirected advertising */
|
||||
conn = bt_conn_add_le(adv->id, BT_ADDR_LE_NONE);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_ADV);
|
||||
*out_conn = conn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bt_conn_exists_le(adv->id, &adv->target_addr)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
conn = bt_conn_add_le(adv->id, &adv->target_addr);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_DIR_ADV);
|
||||
*out_conn = conn;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void le_adv_stop_free_conn(const struct bt_le_ext_adv *adv)
|
||||
{
|
||||
struct bt_conn *conn;
|
||||
|
||||
if (!bt_addr_le_cmp(&adv->target_addr, BT_ADDR_LE_ANY)) {
|
||||
conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE,
|
||||
BT_CONN_CONNECT_ADV);
|
||||
} else {
|
||||
conn = bt_conn_lookup_state_le(adv->id, &adv->target_addr,
|
||||
BT_CONN_CONNECT_DIR_ADV);
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
}
|
||||
|
||||
int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len,
|
||||
const bt_addr_le_t *peer)
|
||||
const struct bt_data *sd, size_t sd_len)
|
||||
{
|
||||
struct bt_hci_cp_le_set_adv_param set_param;
|
||||
struct bt_conn *conn = NULL;
|
||||
struct net_buf *buf;
|
||||
bool dir_adv = (peer != NULL);
|
||||
bool dir_adv = (param->peer != NULL);
|
||||
int err;
|
||||
struct bt_le_ext_adv *adv;
|
||||
|
||||
|
@ -7189,7 +7273,7 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!valid_adv_param(param, dir_adv)) {
|
||||
if (!valid_adv_param(param)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -7225,6 +7309,12 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (dir_adv) {
|
||||
bt_addr_le_copy(&adv->target_addr, param->peer);
|
||||
} else {
|
||||
bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY);
|
||||
}
|
||||
|
||||
if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
||||
if (dir_adv) {
|
||||
if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) {
|
||||
|
@ -7233,7 +7323,7 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
set_param.type = BT_HCI_ADV_DIRECT_IND;
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&set_param.direct_addr, peer);
|
||||
bt_addr_le_copy(&set_param.direct_addr, param->peer);
|
||||
} else {
|
||||
set_param.type = BT_HCI_ADV_IND;
|
||||
}
|
||||
|
@ -7264,15 +7354,13 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
||||
conn = bt_conn_add_le(param->id, BT_ADDR_LE_NONE);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_ADV);
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
||||
err = le_adv_start_add_conn(adv, &conn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7283,6 +7371,7 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -7295,7 +7384,7 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING,
|
||||
atomic_set_bit_to(bt_dev.flags, BT_DEV_KEEP_ADVERTISING, !dir_adv &&
|
||||
!(param->options & BT_LE_ADV_OPT_ONE_TIME));
|
||||
|
||||
atomic_set_bit_to(bt_dev.flags, BT_DEV_ADVERTISING_NAME,
|
||||
|
@ -7312,11 +7401,10 @@ int bt_le_adv_start_legacy(const struct bt_le_adv_param *param,
|
|||
|
||||
static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
|
||||
const struct bt_le_adv_param *param,
|
||||
const bt_addr_le_t *peer,
|
||||
bool has_scan_data)
|
||||
{
|
||||
struct bt_hci_cp_le_set_ext_adv_param *cp;
|
||||
bool dir_adv = peer != NULL;
|
||||
bool dir_adv = param->peer != NULL;
|
||||
struct net_buf *buf, *rsp;
|
||||
int err;
|
||||
|
||||
|
@ -7334,6 +7422,12 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
|
|||
return err;
|
||||
}
|
||||
|
||||
if (dir_adv) {
|
||||
bt_addr_le_copy(&adv->target_addr, param->peer);
|
||||
} else {
|
||||
bt_addr_le_copy(&adv->target_addr, BT_ADDR_LE_ANY);
|
||||
}
|
||||
|
||||
sys_put_le24(param->interval_min, cp->prim_min_interval);
|
||||
sys_put_le24(param->interval_max, cp->prim_max_interval);
|
||||
cp->prim_channel_map = 0x07;
|
||||
|
@ -7372,15 +7466,7 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
|
|||
|
||||
if (param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
||||
cp->props |= BT_HCI_LE_ADV_PROP_CONN;
|
||||
if (dir_adv) {
|
||||
cp->props |= BT_HCI_LE_ADV_PROP_DIRECT;
|
||||
if (!(param->options &
|
||||
BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
|
||||
cp->props |= BT_HCI_LE_ADV_PROP_HI_DC_CONN;
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&cp->peer_addr, peer);
|
||||
} else if (!(param->options & BT_LE_ADV_OPT_EXT_ADV)) {
|
||||
if (!dir_adv && !(param->options & BT_LE_ADV_OPT_EXT_ADV)) {
|
||||
/* When using non-extended adv packets then undirected
|
||||
* advertising has to be scannable as well.
|
||||
* We didn't require this option to be set before, so
|
||||
|
@ -7394,6 +7480,15 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
|
|||
cp->props |= BT_HCI_LE_ADV_PROP_SCAN;
|
||||
}
|
||||
|
||||
if (dir_adv) {
|
||||
cp->props |= BT_HCI_LE_ADV_PROP_DIRECT;
|
||||
if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
|
||||
cp->props |= BT_HCI_LE_ADV_PROP_HI_DC_CONN;
|
||||
}
|
||||
|
||||
bt_addr_le_copy(&cp->peer_addr, param->peer);
|
||||
}
|
||||
|
||||
cp->sid = param->sid;
|
||||
|
||||
err = bt_hci_cmd_send_sync(BT_HCI_OP_LE_SET_EXT_ADV_PARAM, buf, &rsp);
|
||||
|
@ -7436,14 +7531,13 @@ static int le_ext_adv_param_set(struct bt_le_ext_adv *adv,
|
|||
int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
|
||||
const struct bt_le_adv_param *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len,
|
||||
const bt_addr_le_t *peer)
|
||||
const struct bt_data *sd, size_t sd_len)
|
||||
{
|
||||
struct bt_le_ext_adv_start_param start_param = {
|
||||
.timeout = 0,
|
||||
.num_events = 0,
|
||||
};
|
||||
bool dir_adv = (peer != NULL);
|
||||
bool dir_adv = (param->peer != NULL);
|
||||
struct bt_conn *conn = NULL;
|
||||
int err;
|
||||
|
||||
|
@ -7451,7 +7545,7 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
|
|||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!valid_adv_param(param, dir_adv)) {
|
||||
if (!valid_adv_param(param)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
|
@ -7461,7 +7555,7 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
|
|||
|
||||
adv->id = param->id;
|
||||
|
||||
err = le_ext_adv_param_set(adv, param, peer, sd ||
|
||||
err = le_ext_adv_param_set(adv, param, sd ||
|
||||
(param->options & BT_LE_ADV_OPT_USE_NAME));
|
||||
if (err) {
|
||||
return err;
|
||||
|
@ -7474,19 +7568,20 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
|
|||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
param->options & BT_LE_ADV_OPT_CONNECTABLE) {
|
||||
conn = bt_conn_add_le(param->id, BT_ADDR_LE_NONE);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_ADV);
|
||||
} else {
|
||||
if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
|
||||
start_param.timeout =
|
||||
BT_GAP_ADV_HIGH_DUTY_CYCLE_MAX_TIMEOUT;
|
||||
atomic_set_bit(adv->flags, BT_ADV_LIMITED);
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
(param->options & BT_LE_ADV_OPT_CONNECTABLE)) {
|
||||
err = le_adv_start_add_conn(adv, &conn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
} else if (!(param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY)) {
|
||||
start_param.timeout = BT_HCI_LE_EXT_ADV_DURATION_HI_DC_MAX;
|
||||
atomic_set_bit(adv->flags, BT_ADV_LIMITED);
|
||||
}
|
||||
|
||||
err = set_le_adv_enable_ext(adv, true, &start_param);
|
||||
|
@ -7518,10 +7613,9 @@ int bt_le_adv_start_ext(struct bt_le_ext_adv *adv,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len,
|
||||
const bt_addr_le_t *peer)
|
||||
int bt_le_adv_start(const struct bt_le_adv_param *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len)
|
||||
{
|
||||
if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
||||
BT_FEAT_LE_EXT_ADV(bt_dev.le.features)) {
|
||||
|
@ -7532,8 +7626,7 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
err = bt_le_adv_start_ext(adv, param, ad, ad_len, sd, sd_len,
|
||||
peer);
|
||||
err = bt_le_adv_start_ext(adv, param, ad, ad_len, sd, sd_len);
|
||||
if (err) {
|
||||
adv_delete_legacy();
|
||||
}
|
||||
|
@ -7541,18 +7634,7 @@ int bt_le_adv_start_internal(const struct bt_le_adv_param *param,
|
|||
return err;
|
||||
}
|
||||
|
||||
return bt_le_adv_start_legacy(param, ad, ad_len, sd, sd_len, peer);
|
||||
}
|
||||
|
||||
int bt_le_adv_start(const struct bt_le_adv_param *param,
|
||||
const struct bt_data *ad, size_t ad_len,
|
||||
const struct bt_data *sd, size_t sd_len)
|
||||
{
|
||||
if (param->options & BT_LE_ADV_OPT_DIR_MODE_LOW_DUTY) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return bt_le_adv_start_internal(param, ad, ad_len, sd, sd_len, NULL);
|
||||
return bt_le_adv_start_legacy(param, ad, ad_len, sd, sd_len);
|
||||
}
|
||||
|
||||
int bt_le_adv_stop(void)
|
||||
|
@ -7565,27 +7647,19 @@ int bt_le_adv_stop(void)
|
|||
atomic_clear_bit(bt_dev.flags, BT_DEV_KEEP_ADVERTISING);
|
||||
|
||||
if (!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING)) {
|
||||
/* Legacy advertiser exists, but is not currently advertising.
|
||||
* This happens when keep advertising behavior is active but
|
||||
* no conn object is available to do connectable advertising.
|
||||
*/
|
||||
adv_delete_legacy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) {
|
||||
struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE,
|
||||
BT_CONN_CONNECT_ADV);
|
||||
if (conn) {
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_state_le(adv->id, NULL,
|
||||
BT_CONN_CONNECT_DIR_ADV);
|
||||
if (conn) {
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
le_adv_stop_free_conn(adv);
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_EXT_ADV) &&
|
||||
|
@ -7631,7 +7705,7 @@ int bt_le_adv_stop(void)
|
|||
void bt_le_adv_resume(void)
|
||||
{
|
||||
struct bt_le_ext_adv *adv = bt_adv_lookup_legacy();
|
||||
struct bt_conn *adv_conn;
|
||||
struct bt_conn *conn;
|
||||
int err;
|
||||
|
||||
if (!adv) {
|
||||
|
@ -7641,13 +7715,13 @@ void bt_le_adv_resume(void)
|
|||
|
||||
BT_ASSERT(atomic_test_bit(bt_dev.flags,
|
||||
BT_DEV_ADVERTISING_CONNECTABLE));
|
||||
|
||||
adv_conn = bt_conn_add_le(adv->id, BT_ADDR_LE_NONE);
|
||||
if (!adv_conn) {
|
||||
err = le_adv_start_add_conn(adv, &conn);
|
||||
if (err) {
|
||||
BT_DBG("Cannot resume connectable advertising (%d)", err);
|
||||
return;
|
||||
}
|
||||
|
||||
bt_conn_set_state(adv_conn, BT_CONN_CONNECT_ADV);
|
||||
BT_DBG("Resuming connectable advertising");
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PRIVACY) &&
|
||||
!atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_IDENTITY)) {
|
||||
|
@ -7656,23 +7730,17 @@ void bt_le_adv_resume(void)
|
|||
|
||||
err = set_le_adv_enable(adv, true);
|
||||
if (err) {
|
||||
bt_conn_set_state(adv_conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
}
|
||||
|
||||
/* Since we don't give the application a reference to manage in
|
||||
* this case, we need to release this reference here.
|
||||
*/
|
||||
bt_conn_unref(adv_conn);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_BT_PERIPHERAL) */
|
||||
|
||||
#if defined(CONFIG_BT_EXT_ADV)
|
||||
static bool valid_adv_ext_param(const struct bt_le_adv_param *param)
|
||||
{
|
||||
return valid_adv_param(param, false);
|
||||
}
|
||||
|
||||
int bt_le_ext_adv_get_info(const struct bt_le_ext_adv *adv,
|
||||
struct bt_le_ext_adv_info *info)
|
||||
{
|
||||
|
@ -7705,7 +7773,7 @@ int bt_le_ext_adv_create(const struct bt_le_adv_param *param,
|
|||
adv->id = param->id;
|
||||
adv->cb = cb;
|
||||
|
||||
err = le_ext_adv_param_set(adv, param, NULL, false);
|
||||
err = le_ext_adv_param_set(adv, param, false);
|
||||
if (err) {
|
||||
adv_delete(adv);
|
||||
return err;
|
||||
|
@ -7730,7 +7798,7 @@ int bt_le_ext_adv_update_param(struct bt_le_ext_adv *adv,
|
|||
atomic_clear_bit(adv->flags, BT_ADV_RPA_VALID);
|
||||
}
|
||||
|
||||
return le_ext_adv_param_set(adv, param, NULL, false);
|
||||
return le_ext_adv_param_set(adv, param, false);
|
||||
}
|
||||
|
||||
int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
|
||||
|
@ -7741,12 +7809,10 @@ int bt_le_ext_adv_start(struct bt_le_ext_adv *adv,
|
|||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) {
|
||||
conn = bt_conn_add_le(adv->id, BT_ADDR_LE_NONE);
|
||||
if (!conn) {
|
||||
return -ENOMEM;
|
||||
err = le_adv_start_add_conn(adv, &conn);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECT_ADV);
|
||||
}
|
||||
|
||||
atomic_set_bit_to(adv->flags, BT_ADV_LIMITED, param &&
|
||||
|
@ -7793,22 +7859,9 @@ int bt_le_ext_adv_stop(struct bt_le_ext_adv *adv)
|
|||
#endif
|
||||
}
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL)) {
|
||||
struct bt_conn *conn;
|
||||
|
||||
conn = bt_conn_lookup_state_le(adv->id, BT_ADDR_LE_NONE,
|
||||
BT_CONN_CONNECT_ADV);
|
||||
if (conn) {
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
conn = bt_conn_lookup_state_le(adv->id, NULL,
|
||||
BT_CONN_CONNECT_DIR_ADV);
|
||||
if (conn) {
|
||||
bt_conn_set_state(conn, BT_CONN_DISCONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
if (IS_ENABLED(CONFIG_BT_PERIPHERAL) &&
|
||||
atomic_test_bit(bt_dev.flags, BT_DEV_ADVERTISING_CONNECTABLE)) {
|
||||
le_adv_stop_free_conn(adv);
|
||||
}
|
||||
|
||||
return set_le_adv_enable_ext(adv, false, NULL);
|
||||
|
|
|
@ -98,6 +98,9 @@ struct bt_le_ext_adv {
|
|||
/* Current local Random Address */
|
||||
bt_addr_le_t random_addr;
|
||||
|
||||
/* Current target address */
|
||||
bt_addr_le_t target_addr;
|
||||
|
||||
ATOMIC_DEFINE(flags, BT_ADV_NUM_FLAGS);
|
||||
|
||||
#if defined(CONFIG_BT_EXT_ADV)
|
||||
|
|
|
@ -800,10 +800,10 @@ static int cmd_directed_adv(const struct shell *shell,
|
|||
{
|
||||
int err;
|
||||
bt_addr_le_t addr;
|
||||
struct bt_conn *conn;
|
||||
struct bt_le_adv_param *param = BT_LE_ADV_CONN_DIR;
|
||||
struct bt_le_adv_param param;
|
||||
|
||||
err = bt_addr_le_from_str(argv[1], argv[2], &addr);
|
||||
param = *BT_LE_ADV_CONN_DIR(&addr);
|
||||
if (err) {
|
||||
shell_error(shell, "Invalid peer address (err %d)", err);
|
||||
return err;
|
||||
|
@ -811,23 +811,20 @@ static int cmd_directed_adv(const struct shell *shell,
|
|||
|
||||
if (argc > 3) {
|
||||
if (!strcmp(argv[3], "low")) {
|
||||
param = BT_LE_ADV_CONN_DIR_LOW_DUTY;
|
||||
param = *BT_LE_ADV_CONN_DIR_LOW_DUTY(&addr);
|
||||
} else {
|
||||
shell_help(shell);
|
||||
return -ENOEXEC;
|
||||
}
|
||||
}
|
||||
|
||||
err = bt_conn_le_create_slave(&addr, param, &conn);
|
||||
err = bt_le_adv_start(¶m, NULL, 0, NULL, 0);
|
||||
if (err) {
|
||||
shell_error(shell, "Failed to start directed advertising (%d)",
|
||||
err);
|
||||
return -ENOEXEC;
|
||||
} else {
|
||||
shell_print(shell, "Started directed advertising");
|
||||
|
||||
/* unref connection obj in advance as app user */
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -839,6 +836,7 @@ static bool adv_param_parse(size_t argc, char *argv[],
|
|||
struct bt_le_adv_param *param)
|
||||
{
|
||||
param->options = 0;
|
||||
param->peer = NULL;
|
||||
|
||||
if (!strcmp(argv[1], "conn-scan")) {
|
||||
param->options |= BT_LE_ADV_OPT_CONNECTABLE;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue