Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/zephyr.doxyfile.in
Original file line number Diff line number Diff line change
Expand Up @@ -1977,6 +1977,7 @@ PREDEFINED = "CONFIG_SYS_CLOCK_EXISTS=y" \
"CONFIG_SYS_POWER_MANAGEMENT=y" \
"CONFIG_DEVICE_POWER_MANAGEMENT=y" \
"CONFIG_BT_SMP=y" \
"CONFIG_BT_REMOTE_INFO=y" \
"CONFIG_USERSPACE=y" \
"CONFIG_BT_BREDR=y" \
"CONFIG_FLASH_PAGE_LAYOUT=y" \
Expand Down
74 changes: 73 additions & 1 deletion include/bluetooth/conn.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ enum {
};

/** @brief Connection Info Structure
*
*
* @param type Connection Type
* @param role Connection Role
Expand All @@ -185,6 +184,50 @@ struct bt_conn_info {
};
};

/** LE Connection Remote Info Structure */
struct bt_conn_le_remote_info {

/** Remote LE feature set (bitmask). */
const u8_t *features;
};

/** BR/EDR Connection Remote Info structure */
struct bt_conn_br_remote_info {

/** Remote feature set (pages of bitmasks). */
const u8_t *features;

/** Number of pages in the remote feature set. */
u8_t num_pages;
};

/** @brief Connection Remote Info Structure
*
* @note The version, manufacturer and subversion fields will only contain
* valid data if :option:`CONFIG_BT_REMOTE_VERSION` is enabled.
*/
struct bt_conn_remote_info {
/* Connection Type */
u8_t type;

/* Remote Link Layer version */
u8_t version;

/* Remote manufacturer identifier */
u16_t manufacturer;

/* Per-manufacturer unique revision */
u16_t subversion;

union {
/* LE connection remote info */
struct bt_conn_le_remote_info le;

/* BR/EDR connection remote info */
struct bt_conn_br_remote_info br;
};
};

/** @brief Get connection info
*
* @param conn Connection object.
Expand All @@ -194,6 +237,24 @@ struct bt_conn_info {
*/
int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info);

/** @brief Get connection info for the remote device.
*
* @param conn Connection object.
* @param remote_info Connection remote info object.
*
* @note In order to retrieve the remote version (version, manufacturer
* and subversion) :option:`CONFIG_BT_REMOTE_VERSION` must be enabled
*
* @note The remote information is exchanged directly after the connection has
* been established. The application can be notified about when the remote
* information is available through the remote_info_available callback.
*
* @return Zero on success or (negative) error code on failure.
* @return -EBUSY The remote information is not yet available.
*/
int bt_conn_get_remote_info(struct bt_conn *conn,
struct bt_conn_remote_info *remote_info);

/** @brief Update the connection parameters.
*
* @param conn Connection object.
Expand Down Expand Up @@ -494,6 +555,17 @@ struct bt_conn_cb {
void (*security_changed)(struct bt_conn *conn, bt_security_t level,
enum bt_security_err err);
#endif /* defined(CONFIG_BT_SMP) || defined(CONFIG_BT_BREDR) */

#if defined(CONFIG_BT_REMOTE_INFO)
/** @brief Remote information procedures has completed.
*
* This callback notifies the application that the remote information
* has been retrieved from the remote peer.
*/
void (*remote_info_available)(struct bt_conn *conn,
struct bt_conn_remote_info *remote_info);
#endif /* defined(CONFIG_BT_REMOTE_INFO) */

struct bt_conn_cb *_next;
};

Expand Down
52 changes: 29 additions & 23 deletions subsys/bluetooth/controller/hci/hci.c
Original file line number Diff line number Diff line change
Expand Up @@ -3330,6 +3330,29 @@ static void le_data_len_change(struct pdu_data *pdu_data, u16_t handle,
}
#endif /* CONFIG_BT_CTLR_DATA_LENGTH */

#if defined(CONFIG_BT_REMOTE_VERSION)
void hci_remote_version_info_encode(struct pdu_data *pdu_data, u16_t handle,
struct net_buf *buf)
{
struct pdu_data_llctrl_version_ind *ver_ind;
struct bt_hci_evt_remote_version_info *ep;

if (!(event_mask & BT_EVT_MASK_REMOTE_VERSION_INFO)) {
return;
}

hci_evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep));
ep = net_buf_add(buf, sizeof(*ep));

ver_ind = &pdu_data->llctrl.version_ind;
ep->status = 0x00;
ep->handle = sys_cpu_to_le16(handle);
ep->version = ver_ind->version_number;
ep->manufacturer = ver_ind->company_id;
ep->subversion = ver_ind->sub_version_number;
}
#endif /* CONFIG_BT_REMOTE_VERSION */

static void encode_data_ctrl(struct node_rx_pdu *node_rx,
struct pdu_data *pdu_data, struct net_buf *buf)
{
Expand All @@ -3347,6 +3370,12 @@ static void encode_data_ctrl(struct node_rx_pdu *node_rx,
break;
#endif /* CONFIG_BT_CTLR_LE_ENC */

#if defined(CONFIG_BT_REMOTE_VERSION)
case PDU_DATA_LLCTRL_TYPE_VERSION_IND:
hci_remote_version_info_encode(pdu_data, handle, buf);
break;
#endif /* defined(CONFIG_BT_REMOTE_VERSION) */

case PDU_DATA_LLCTRL_TYPE_FEATURE_RSP:
le_remote_feat_complete(0x00, pdu_data, handle, buf);
break;
Expand Down Expand Up @@ -3456,29 +3485,6 @@ void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num)
hc->handle = sys_cpu_to_le16(handle);
hc->count = sys_cpu_to_le16(num);
}

#if defined(CONFIG_BT_REMOTE_VERSION)
void hci_remote_version_info_encode(struct net_buf *buf,
struct pdu_data *pdu_data, u16_t handle)
{
struct pdu_data_llctrl_version_ind *ver_ind;
struct bt_hci_evt_remote_version_info *ep;

if (!(event_mask & BT_EVT_MASK_REMOTE_VERSION_INFO)) {
return;
}

hci_evt_create(buf, BT_HCI_EVT_REMOTE_VERSION_INFO, sizeof(*ep));
ep = net_buf_add(buf, sizeof(*ep));

ver_ind = &pdu_data->llctrl.version_ind;
ep->status = 0x00;
ep->handle = sys_cpu_to_le16(handle);
ep->version = ver_ind->version_number;
ep->manufacturer = ver_ind->company_id;
ep->subversion = ver_ind->sub_version_number;
}
#endif /* CONFIG_BT_REMOTE_VERSION */
#endif /* CONFIG_BT_CONN */

u8_t hci_get_class(struct node_rx_pdu *node_rx)
Expand Down
22 changes: 1 addition & 21 deletions subsys/bluetooth/controller/hci/hci_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,27 +76,7 @@ static s32_t hbuf_count;

static struct net_buf *process_prio_evt(struct node_rx_pdu *node_rx)
{
/* Currently the only event processed */
#if defined(CONFIG_BT_REMOTE_VERSION)
struct pdu_data *pdu_data = PDU_DATA(node_rx);
struct net_buf *buf;
u16_t handle;

/* Avoid using hci_get_class() to speed things up */
if (node_rx->hdr.user_meta == HCI_CLASS_EVT_LLCP) {

handle = node_rx->hdr.handle;
if (pdu_data->llctrl.opcode ==
PDU_DATA_LLCTRL_TYPE_VERSION_IND) {

buf = bt_buf_get_evt(BT_HCI_EVT_REMOTE_VERSION_INFO,
false, K_FOREVER);
hci_remote_version_info_encode(buf, pdu_data, handle);
return buf;
}
}

#endif /* CONFIG_BT_CONN */
/* Currently there are no events processed */
return NULL;
}

Expand Down
2 changes: 0 additions & 2 deletions subsys/bluetooth/controller/hci/hci_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ u8_t hci_get_class(struct node_rx_pdu *node_rx);
int hci_acl_handle(struct net_buf *acl, struct net_buf **evt);
void hci_acl_encode(struct node_rx_pdu *node_rx, struct net_buf *buf);
void hci_num_cmplt_encode(struct net_buf *buf, u16_t handle, u8_t num);
void hci_remote_version_info_encode(struct net_buf *buf,
struct pdu_data *pdu_data, u16_t handle);
#endif
int hci_vendor_cmd_handle(u16_t ocf, struct net_buf *cmd,
struct net_buf **evt);
Expand Down
16 changes: 16 additions & 0 deletions subsys/bluetooth/host/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,22 @@ config BT_AUTO_PHY_UPDATE
want to rely on remote device to initiate the procedure at its
discretion.

config BT_REMOTE_INFO
bool "Enable application access to remote information"
help
Enable application access to the remote information available in the
stack. The remote information is retrieved once a connection has been
established and the application will be notified when this information
is available through the remote_version_available connection callback.

config BT_REMOTE_VERSION
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jhedberg we should move this to the common Kconfig settings so that I can refer to it in #19657

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlescufi What exactly do you want to do on the controller side? Don't we want this always enabled for split (controller only) builds? AFAIK it's a mandatory command for the controller whenever connections are supported.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant enabling the processing in the priority thread. But in fact what I'll do is to conditionally compile it based on whether it's a combined build or not, so let's not move it. Sorry for the noise.

bool "Enable remote version information"
depends on BT_REMOTE_INFO
help
Enable this to get access to the remote version through
the remote_version_available callback. The host will automatically ask
the remote device after the connection has been established.

config BT_SMP
bool "Security Manager Protocol support"
select TINYCRYPT
Expand Down
58 changes: 58 additions & 0 deletions subsys/bluetooth/host/conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,27 @@ static void notify_disconnected(struct bt_conn *conn)
}
}

#if defined(CONFIG_BT_REMOTE_INFO)
void notify_remote_info(struct bt_conn *conn)
{
struct bt_conn_remote_info remote_info;
struct bt_conn_cb *cb;
int err;

err = bt_conn_get_remote_info(conn, &remote_info);
if (err) {
BT_DBG("Notify remote info failed %d", err);
return;
}

for (cb = callback_list; cb; cb = cb->_next) {
if (cb->remote_info_available) {
cb->remote_info_available(conn, &remote_info);
}
}
}
#endif /* defined(CONFIG_BT_REMOTE_INFO) */

void notify_le_param_updated(struct bt_conn *conn)
{
struct bt_conn_cb *cb;
Expand Down Expand Up @@ -1638,6 +1659,7 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state)
bt_conn_unref(conn);
break;
}

/* Notify disconnection and queue a dummy buffer to wake
* up and stop the tx thread for states where it was
* running.
Expand Down Expand Up @@ -1902,6 +1924,42 @@ int bt_conn_get_info(const struct bt_conn *conn, struct bt_conn_info *info)
return -EINVAL;
}

int bt_conn_get_remote_info(struct bt_conn *conn,
struct bt_conn_remote_info *remote_info)
{
if (!atomic_test_bit(conn->flags, BT_CONN_AUTO_FEATURE_EXCH) ||
(IS_ENABLED(CONFIG_BT_REMOTE_VERSION) &&
!atomic_test_bit(conn->flags, BT_CONN_AUTO_VERSION_INFO))) {
return -EBUSY;
}

remote_info->type = conn->type;
#if defined(CONFIG_BT_REMOTE_VERSION)
/* The conn->rv values will be just zeroes if the operation failed */
remote_info->version = conn->rv.version;
remote_info->manufacturer = conn->rv.manufacturer;
remote_info->subversion = conn->rv.subversion;
#else
remote_info->version = 0;
remote_info->manufacturer = 0;
remote_info->subversion = 0;
#endif

switch (conn->type) {
case BT_CONN_TYPE_LE:
remote_info->le.features = conn->le.features;
return 0;
#if defined(CONFIG_BT_BREDR)
case BT_CONN_TYPE_BR:
/* TODO: Make sure the HCI commands to read br features and
* extended features has finished. */
return -ENOTSUP;
#endif
default:
return -EINVAL;
}
}

static int bt_hci_disconnect(struct bt_conn *conn, u8_t reason)
{
struct net_buf *buf;
Expand Down
14 changes: 14 additions & 0 deletions subsys/bluetooth/host/conn_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ enum {
BT_CONN_SLAVE_PARAM_L2CAP, /* If should force L2CAP for CPUP */
BT_CONN_FORCE_PAIR, /* Pairing even with existing keys. */

BT_CONN_AUTO_PHY_COMPLETE, /* Auto-initiated PHY procedure done */
BT_CONN_AUTO_FEATURE_EXCH, /* Auto-initiated LE Feat done */
BT_CONN_AUTO_VERSION_INFO, /* Auto-initiated LE version done */

/* Total number of flags - must be at the end of the enum */
BT_CONN_NUM_FLAGS,
};
Expand Down Expand Up @@ -143,6 +147,14 @@ struct bt_conn {
struct bt_conn_sco sco;
#endif
};

#if defined(CONFIG_BT_REMOTE_VERSION)
struct bt_conn_rv {
u8_t version;
u16_t manufacturer;
u16_t subversion;
} rv;
#endif
};

/* Process incoming data for a connection */
Expand Down Expand Up @@ -209,6 +221,8 @@ void bt_conn_set_state(struct bt_conn *conn, bt_conn_state_t state);
int bt_conn_le_conn_update(struct bt_conn *conn,
const struct bt_le_conn_param *param);

void notify_remote_info(struct bt_conn *conn);

void notify_le_param_updated(struct bt_conn *conn);

bool le_param_req(struct bt_conn *conn, struct bt_le_conn_param *param);
Expand Down
Loading