Skip to content

Commit 649a813

Browse files
Blackladderjhedberg
authored andcommitted
Bluetooth: host: Add calling of read_remote_version
Make remote features and remote version accesible to the application through the bt_conn_get_remote_info object. The host will auto initiate the procedures. If the procedures have not finished with the application calls bt_conn_get_remote_info then EBUSY will be returned. The procedures should finish during the first 10 connection intervals. Signed-off-by: Sverre Storvold <Sverre.Storvold@nordicsemi.no> Signed-off-by: Joakim Andersson <joakim.andersson@nordicsemi.no>
1 parent 32bde4f commit 649a813

File tree

6 files changed

+238
-1
lines changed

6 files changed

+238
-1
lines changed

doc/zephyr.doxyfile.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ PREDEFINED = "CONFIG_SYS_CLOCK_EXISTS=y" \
19771977
"CONFIG_SYS_POWER_MANAGEMENT=y" \
19781978
"CONFIG_DEVICE_POWER_MANAGEMENT=y" \
19791979
"CONFIG_BT_SMP=y" \
1980+
"CONFIG_BT_REMOTE_INFO=y" \
19801981
"CONFIG_USERSPACE=y" \
19811982
"CONFIG_BT_BREDR=y" \
19821983
"CONFIG_FLASH_PAGE_LAYOUT=y" \

include/bluetooth/conn.h

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ enum {
163163
};
164164

165165
/** @brief Connection Info Structure
166-
*
167166
*
168167
* @param type Connection Type
169168
* @param role Connection Role
@@ -185,6 +184,50 @@ struct bt_conn_info {
185184
};
186185
};
187186

187+
/** LE Connection Remote Info Structure */
188+
struct bt_conn_le_remote_info {
189+
190+
/** Remote LE feature set (bitmask). */
191+
const u8_t *features;
192+
};
193+
194+
/** BR/EDR Connection Remote Info structure */
195+
struct bt_conn_br_remote_info {
196+
197+
/** Remote feature set (pages of bitmasks). */
198+
const u8_t *features;
199+
200+
/** Number of pages in the remote feature set. */
201+
u8_t num_pages;
202+
};
203+
204+
/** @brief Connection Remote Info Structure
205+
*
206+
* @note The version, manufacturer and subversion fields will only contain
207+
* valid data if :option:`CONFIG_BT_REMOTE_VERSION` is enabled.
208+
*/
209+
struct bt_conn_remote_info {
210+
/* Connection Type */
211+
u8_t type;
212+
213+
/* Remote Link Layer version */
214+
u8_t version;
215+
216+
/* Remote manufacturer identifier */
217+
u16_t manufacturer;
218+
219+
/* Per-manufacturer unique revision */
220+
u16_t subversion;
221+
222+
union {
223+
/* LE connection remote info */
224+
struct bt_conn_le_remote_info le;
225+
226+
/* BR/EDR connection remote info */
227+
struct bt_conn_br_remote_info br;
228+
};
229+
};
230+
188231
/** @brief Get connection info
189232
*
190233
* @param conn Connection object.
@@ -194,6 +237,24 @@ struct bt_conn_info {
194237
*/
195238
int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info);
196239

240+
/** @brief Get connection info for the remote device.
241+
*
242+
* @param conn Connection object.
243+
* @param remote_info Connection remote info object.
244+
*
245+
* @note In order to retrieve the remote version (version, manufacturer
246+
* and subversion) :option:`CONFIG_BT_REMOTE_VERSION` must be enabled
247+
*
248+
* @note The remote information is exchanged directly after the connection has
249+
* been established. The application can be notified about when the remote
250+
* information is available through the remote_info_available callback.
251+
*
252+
* @return Zero on success or (negative) error code on failure.
253+
* @return -EBUSY The remote information is not yet available.
254+
*/
255+
int bt_conn_get_remote_info(struct bt_conn *conn,
256+
struct bt_conn_remote_info *remote_info);
257+
197258
/** @brief Update the connection parameters.
198259
*
199260
* @param conn Connection object.
@@ -494,6 +555,17 @@ struct bt_conn_cb {
494555
void (*security_changed)(struct bt_conn *conn, bt_security_t level,
495556
enum bt_security_err err);
496557
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */
558+
559+
#if defined(CONFIG_BT_REMOTE_INFO)
560+
/** @brief Remote information procedures has completed.
561+
*
562+
* This callback notifies the application that the remote information
563+
* has been retrieved from the remote peer.
564+
*/
565+
void (*remote_info_available)(struct bt_conn *conn,
566+
struct bt_conn_remote_info *remote_info);
567+
#endif /* defined(CONFIG_BT_REMOTE_INFO) */
568+
497569
struct bt_conn_cb *_next;
498570
};
499571

subsys/bluetooth/host/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,22 @@ config BT_AUTO_PHY_UPDATE
261261
want to rely on remote device to initiate the procedure at its
262262
discretion.
263263

264+
config BT_REMOTE_INFO
265+
bool "Enable application access to remote information"
266+
help
267+
Enable application access to the remote information available in the
268+
stack. The remote information is retrieved once a connection has been
269+
established and the application will be notified when this information
270+
is available through the remote_version_available connection callback.
271+
272+
config BT_REMOTE_VERSION
273+
bool "Enable remote version information"
274+
depends on BT_REMOTE_INFO
275+
help
276+
Enable this to get access to the remote version through
277+
the remote_version_available callback. The host will automatically ask
278+
the remote device after the connection has been established.
279+
264280
config BT_SMP
265281
bool "Security Manager Protocol support"
266282
select TINYCRYPT

subsys/bluetooth/host/conn.c

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,27 @@ static void notify_disconnected(struct bt_conn *conn)
154154
}
155155
}
156156

157+
#if defined(CONFIG_BT_REMOTE_INFO)
158+
void notify_remote_info(struct bt_conn *conn)
159+
{
160+
struct bt_conn_remote_info remote_info;
161+
struct bt_conn_cb *cb;
162+
int err;
163+
164+
err = bt_conn_get_remote_info(conn, &remote_info);
165+
if (err) {
166+
BT_DBG("Notify remote info failed %d", err);
167+
return;
168+
}
169+
170+
for (cb = callback_list; cb; cb = cb->_next) {
171+
if (cb->remote_info_available) {
172+
cb->remote_info_available(conn, &remote_info);
173+
}
174+
}
175+
}
176+
#endif /* defined(CONFIG_BT_REMOTE_INFO) */
177+
157178
void notify_le_param_updated(struct bt_conn *conn)
158179
{
159180
struct bt_conn_cb *cb;
@@ -1638,6 +1659,7 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
16381659
bt_conn_unref(conn);
16391660
break;
16401661
}
1662+
16411663
/* Notify disconnection and queue a dummy buffer to wake
16421664
* up and stop the tx thread for states where it was
16431665
* running.
@@ -1902,6 +1924,42 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
19021924
return -EINVAL;
19031925
}
19041926

1927+
int bt_conn_get_remote_info(struct bt_conn *conn,
1928+
struct bt_conn_remote_info *remote_info)
1929+
{
1930+
if (!atomic_test_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH) ||
1931+
(IS_ENABLED(CONFIG_BT_REMOTE_VERSION) &&
1932+
!atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO))) {
1933+
return -EBUSY;
1934+
}
1935+
1936+
remote_info->type = conn->type;
1937+
#if defined(CONFIG_BT_REMOTE_VERSION)
1938+
/* The conn->rv values will be just zeroes if the operation failed */
1939+
remote_info->version = conn->rv.version;
1940+
remote_info->manufacturer = conn->rv.manufacturer;
1941+
remote_info->subversion = conn->rv.subversion;
1942+
#else
1943+
remote_info->version = 0;
1944+
remote_info->manufacturer = 0;
1945+
remote_info->subversion = 0;
1946+
#endif
1947+
1948+
switch (conn->type) {
1949+
case BT_CONN_TYPE_LE:
1950+
remote_info->le.features = conn->le.features;
1951+
return 0;
1952+
#if defined(CONFIG_BT_BREDR)
1953+
case BT_CONN_TYPE_BR:
1954+
/* TODO: Make sure the HCI commands to read br features and
1955+
* extended features has finished. */
1956+
return -ENOTSUP;
1957+
#endif
1958+
default:
1959+
return -EINVAL;
1960+
}
1961+
}
1962+
19051963
static int bt_hci_disconnect(struct bt_conn *conn, u8_t reason)
19061964
{
19071965
struct net_buf *buf;

subsys/bluetooth/host/conn_internal.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ enum {
3333

3434
BT_CONN_AUTO_PHY_COMPLETE, /* Auto-initiated PHY procedure done */
3535
BT_CONN_AUTO_FEATURE_EXCH, /* Auto-initiated LE Feat done */
36+
BT_CONN_AUTO_VERSION_INFO, /* Auto-initiated LE version done */
3637

3738
/* Total number of flags - must be at the end of the enum */
3839
BT_CONN_NUM_FLAGS,
@@ -146,6 +147,14 @@ struct bt_conn {
146147
struct bt_conn_sco sco;
147148
#endif
148149
};
150+
151+
#if defined(CONFIG_BT_REMOTE_VERSION)
152+
struct bt_conn_rv {
153+
u8_t version;
154+
u16_t manufacturer;
155+
u16_t subversion;
156+
} rv;
157+
#endif
149158
};
150159

151160
/* Process incoming data for a connection */
@@ -212,6 +221,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state);
212221
int bt_conn_le_conn_update(struct bt_conn *conn,
213222
const struct bt_le_conn_param *param);
214223

224+
void notify_remote_info(struct bt_conn *conn);
225+
215226
void notify_le_param_updated(struct bt_conn *conn);
216227

217228
bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);

subsys/bluetooth/host/hci_core.c

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -967,6 +967,33 @@ static int hci_le_read_remote_features(struct bt_conn *conn)
967967
return 0;
968968
}
969969

970+
static int hci_read_remote_version(struct bt_conn *conn)
971+
{
972+
struct bt_hci_cp_read_remote_version_info *cp;
973+
struct net_buf *buf;
974+
975+
if (conn->state != BT_CONN_CONNECTED) {
976+
return -ENOTCONN;
977+
}
978+
979+
/* Remote version cannot change. */
980+
if (atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) {
981+
return 0;
982+
}
983+
984+
buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_VERSION_INFO,
985+
sizeof(*cp));
986+
if (!buf) {
987+
return -ENOBUFS;
988+
}
989+
990+
cp = net_buf_add(buf, sizeof(*cp));
991+
cp->handle = sys_cpu_to_le16(conn->handle);
992+
993+
return bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_VERSION_INFO, buf,
994+
NULL);
995+
}
996+
970997
/* LE Data Length Change Event is optional so this function just ignore
971998
* error and stack will continue to use default values.
972999
*/
@@ -1099,6 +1126,14 @@ static void conn_auto_initiate(struct bt_conn *conn)
10991126
}
11001127
}
11011128

1129+
if (IS_ENABLED(CONFIG_BT_REMOTE_VERSION) &&
1130+
!atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO)) {
1131+
err = hci_read_remote_version(conn);
1132+
if (!err) {
1133+
return;
1134+
}
1135+
}
1136+
11021137
if (IS_ENABLED(CONFIG_BT_AUTO_PHY_UPDATE) &&
11031138
!atomic_test_bit(conn->flags, BT_CONN_AUTO_PHY_COMPLETE) &&
11041139
BT_FEAT_LE_PHY_2M(bt_dev.le.features)) {
@@ -1372,6 +1407,12 @@ static void le_remote_feat_complete(struct net_buf *buf)
13721407
}
13731408

13741409
atomic_set_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH);
1410+
1411+
if (IS_ENABLED(CONFIG_BT_REMOTE_INFO) &&
1412+
!IS_ENABLED(CONFIG_BT_REMOTE_VERSION)) {
1413+
notify_remote_info(conn);
1414+
}
1415+
13751416
/* Continue with auto-initiated procedures */
13761417
conn_auto_initiate(conn);
13771418

@@ -3231,6 +3272,39 @@ static void hci_encrypt_key_refresh_complete(struct net_buf *buf)
32313272
}
32323273
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
32333274

3275+
#if defined(CONFIG_BT_REMOTE_VERSION)
3276+
static void bt_hci_evt_read_remote_version_complete(struct net_buf *buf)
3277+
{
3278+
struct bt_hci_evt_remote_version_info *evt;
3279+
struct bt_conn *conn;
3280+
3281+
evt = net_buf_pull_mem(buf, sizeof(*evt));
3282+
conn = bt_conn_lookup_handle(evt->handle);
3283+
if (!conn) {
3284+
BT_ERR("No connection for handle %u", evt->handle);
3285+
return;
3286+
}
3287+
3288+
if (!evt->status) {
3289+
conn->rv.version = evt->version;
3290+
conn->rv.manufacturer = sys_le16_to_cpu(evt->manufacturer);
3291+
conn->rv.subversion = sys_le16_to_cpu(evt->subversion);
3292+
}
3293+
3294+
atomic_set_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO);
3295+
3296+
if (IS_ENABLED(CONFIG_BT_REMOTE_INFO)) {
3297+
/* Remote features is already present */
3298+
notify_remote_info(conn);
3299+
}
3300+
3301+
/* Continue with auto-initiated procedures */
3302+
conn_auto_initiate(conn);
3303+
3304+
bt_conn_unref(conn);
3305+
}
3306+
#endif /* CONFIG_BT_REMOTE_VERSION */
3307+
32343308
#if defined(CONFIG_BT_SMP)
32353309
static void le_ltk_neg_reply(u16_t handle)
32363310
{
@@ -3795,6 +3869,11 @@ static const struct event_handler normal_events[] = {
37953869
hci_encrypt_key_refresh_complete,
37963870
sizeof(struct bt_hci_evt_encrypt_key_refresh_complete)),
37973871
#endif /* CONFIG_BT_SMP || CONFIG_BT_BREDR */
3872+
#if defined(CONFIG_BT_REMOTE_VERSION)
3873+
EVENT_HANDLER(BT_HCI_EVT_REMOTE_VERSION_INFO,
3874+
bt_hci_evt_read_remote_version_complete,
3875+
sizeof(struct bt_hci_evt_remote_version_info)),
3876+
#endif /* CONFIG_BT_REMOTE_VERSION */
37983877
};
37993878

38003879
static void hci_event(struct net_buf *buf)

0 commit comments

Comments
 (0)