Bluetooth: Add support to read LMP remote features
Introduces HCI protocol defines to be able request and read remote LMP features and if available extended data from peer when connected. Change-Id: Ic274737d8b6c896eb9e83e2179829bcbadf6f635 Signed-off-by: Arkadiusz Lichwa <arkadiusz.lichwa@tieto.com>
This commit is contained in:
parent
2bf391797b
commit
16fda5f3d9
3 changed files with 123 additions and 1 deletions
|
@ -124,6 +124,7 @@ struct bt_hci_cmd_hdr {
|
|||
/* LMP features */
|
||||
#define BT_LMP_NO_BREDR 0x20
|
||||
#define BT_LMP_LE 0x40
|
||||
#define BT_LMP_REMOTE_EXT_FEATURES 0x80
|
||||
|
||||
/* LE features */
|
||||
#define BT_HCI_LE_ENCRYPTION 0x01
|
||||
|
@ -285,6 +286,17 @@ struct bt_hci_rp_remote_name_cancel {
|
|||
bt_addr_t bdaddr;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_READ_REMOTE_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001b)
|
||||
struct bt_hci_cp_read_remote_features {
|
||||
uint16_t handle;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_READ_REMOTE_EXT_FEATURES BT_OP(BT_OGF_LINK_CTRL, 0x001c)
|
||||
struct bt_hci_cp_read_remote_ext_features {
|
||||
uint16_t handle;
|
||||
uint8_t page;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_OP_IO_CAPABILITY_REPLY BT_OP(BT_OGF_LINK_CTRL, 0x002b)
|
||||
struct bt_hci_cp_io_capability_reply {
|
||||
bt_addr_t bdaddr;
|
||||
|
@ -640,6 +652,13 @@ struct bt_hci_evt_encrypt_change {
|
|||
uint8_t encrypt;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_REMOTE_FEATURES 0x0b
|
||||
struct bt_hci_evt_remote_features {
|
||||
uint8_t status;
|
||||
uint16_t handle;
|
||||
uint8_t features[8];
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_CMD_COMPLETE 0x0e
|
||||
struct hci_evt_cmd_complete {
|
||||
uint8_t ncmd;
|
||||
|
@ -697,6 +716,15 @@ struct bt_hci_evt_inquiry_result_with_rssi {
|
|||
int8_t rssi;
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_REMOTE_EXT_FEATURES 0x23
|
||||
struct bt_hci_evt_remote_ext_features {
|
||||
uint8_t status;
|
||||
uint16_t handle;
|
||||
uint8_t page;
|
||||
uint8_t max_page;
|
||||
uint8_t features[8];
|
||||
} __packed;
|
||||
|
||||
#define BT_HCI_EVT_EXTENDED_INQUIRY_RESULT 0x2f
|
||||
struct bt_hci_evt_extended_inquiry_result {
|
||||
uint8_t num_reports;
|
||||
|
|
|
@ -57,11 +57,20 @@ struct bt_conn_le {
|
|||
};
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_BREDR)
|
||||
/* For now reserve space for 2 pages of LMP remote features */
|
||||
#define LMP_MAX_PAGES 2
|
||||
|
||||
/* Helper to get remote extended features bit available at page 0 */
|
||||
#define lmp_ext_feat_capable(conn) \
|
||||
((conn)->br.features[0][7] & BT_LMP_REMOTE_EXT_FEATURES)
|
||||
|
||||
struct bt_conn_br {
|
||||
bt_addr_t dst;
|
||||
uint8_t remote_io_capa;
|
||||
uint8_t remote_auth;
|
||||
uint8_t pairing_method;
|
||||
/* remote LMP features pages per 8 bytes each */
|
||||
uint8_t features[LMP_MAX_PAGES][8];
|
||||
};
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1058,6 +1058,7 @@ static void conn_complete(struct net_buf *buf)
|
|||
{
|
||||
struct bt_hci_evt_conn_complete *evt = (void *)buf->data;
|
||||
struct bt_conn *conn;
|
||||
struct bt_hci_cp_read_remote_features *cp;
|
||||
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
||||
|
||||
BT_DBG("status 0x%02x, handle %u, type 0x%02x", evt->status, handle,
|
||||
|
@ -1081,6 +1082,16 @@ static void conn_complete(struct net_buf *buf)
|
|||
update_sec_level_br(conn);
|
||||
bt_conn_set_state(conn, BT_CONN_CONNECTED);
|
||||
bt_conn_unref(conn);
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_FEATURES, sizeof(*cp));
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
cp->handle = evt->handle;
|
||||
|
||||
bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_FEATURES, buf, NULL);
|
||||
}
|
||||
|
||||
static void pin_code_req(struct net_buf *buf)
|
||||
|
@ -1741,6 +1752,71 @@ static void auth_complete(struct net_buf *buf)
|
|||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
static void read_remote_features_complete(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_remote_features *evt = (void *)buf->data;
|
||||
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
||||
struct bt_hci_cp_read_remote_ext_features *cp;
|
||||
struct bt_conn *conn;
|
||||
|
||||
BT_DBG("status %u handle %u", evt->status, handle);
|
||||
|
||||
conn = bt_conn_lookup_handle(handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Can't find conn for handle %u", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!evt->status) {
|
||||
memcpy(conn->br.features[0], evt->features,
|
||||
sizeof(conn->br.features[0]));
|
||||
|
||||
if (!lmp_ext_feat_capable(conn)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
buf = bt_hci_cmd_create(BT_HCI_OP_READ_REMOTE_EXT_FEATURES,
|
||||
sizeof(*cp));
|
||||
if (!buf) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* read LMP remote features page 1 */
|
||||
cp = net_buf_add(buf, sizeof(*cp));
|
||||
cp->handle = evt->handle;
|
||||
/* get page at index 1 */
|
||||
cp->page = 0x01;
|
||||
|
||||
bt_hci_cmd_send_sync(BT_HCI_OP_READ_REMOTE_EXT_FEATURES, buf,
|
||||
NULL);
|
||||
}
|
||||
done:
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
static void read_remote_ext_features_complete(struct net_buf *buf)
|
||||
{
|
||||
struct bt_hci_evt_remote_ext_features *evt = (void *)buf->data;
|
||||
uint16_t handle = sys_le16_to_cpu(evt->handle);
|
||||
struct bt_conn *conn;
|
||||
|
||||
BT_DBG("status %u handle %u", evt->status, handle);
|
||||
|
||||
conn = bt_conn_lookup_handle(handle);
|
||||
if (!conn) {
|
||||
BT_ERR("Can't find conn for handle %u", handle);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!evt->status && evt->page == 0x01) {
|
||||
memcpy(conn->br.features[1], evt->features,
|
||||
sizeof(conn->br.features[1]));
|
||||
}
|
||||
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
|
||||
#if defined(CONFIG_BLUETOOTH_SMP) || defined(CONFIG_BLUETOOTH_BREDR)
|
||||
|
@ -2471,6 +2547,12 @@ static void hci_event(struct net_buf *buf)
|
|||
case BT_HCI_EVT_AUTH_COMPLETE:
|
||||
auth_complete(buf);
|
||||
break;
|
||||
case BT_HCI_EVT_REMOTE_FEATURES:
|
||||
read_remote_features_complete(buf);
|
||||
break;
|
||||
case BT_HCI_EVT_REMOTE_EXT_FEATURES:
|
||||
read_remote_ext_features_complete(buf);
|
||||
break;
|
||||
#endif
|
||||
#if defined(CONFIG_BLUETOOTH_CONN)
|
||||
case BT_HCI_EVT_DISCONN_COMPLETE:
|
||||
|
@ -2918,10 +3000,12 @@ static int set_event_mask(void)
|
|||
ev->events[0] |= 0x08; /* Connection Request */
|
||||
ev->events[0] |= 0x20; /* Authentication Complete */
|
||||
ev->events[0] |= 0x40; /* Remote Name Request Complete */
|
||||
ev->events[1] |= 0x04; /* Read Remote Feature Complete */
|
||||
ev->events[2] |= 0x20; /* Pin Code Request */
|
||||
ev->events[2] |= 0x40; /* Link Key Request */
|
||||
ev->events[2] |= 0x80; /* Link Key Notif */
|
||||
ev->events[4] |= 0x02; /* Inquiry Result With RSSI */
|
||||
ev->events[4] |= 0x04; /* Remote Extended Features Complete */
|
||||
ev->events[5] |= 0x40; /* Extended Inquiry Result */
|
||||
ev->events[6] |= 0x01; /* IO Capability Request */
|
||||
ev->events[6] |= 0x02; /* IO Capability Response */
|
||||
|
@ -2929,7 +3013,8 @@ static int set_event_mask(void)
|
|||
ev->events[6] |= 0x08; /* User Passkey Request */
|
||||
ev->events[6] |= 0x20; /* Simple Pairing Complete */
|
||||
ev->events[7] |= 0x04; /* User Passkey Notification */
|
||||
#endif
|
||||
#endif /* CONFIG_BLUETOOTH_BREDR */
|
||||
|
||||
ev->events[1] |= 0x20; /* Command Complete */
|
||||
ev->events[1] |= 0x40; /* Command Status */
|
||||
ev->events[1] |= 0x80; /* Hardware Error */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue