Bluetooth: Reading remote device lmp_version from controller.

On ACL connection complete with a remote device, the remote
device lmp version should be available with Controller. The
current change is to read this information from controller to
host and update to bluez userspace through management APIs.

Change-Id: Ie152ed98fa0a6cf9ab170a6bb8c6a05b5b9dfcb0
Signed-off-by: Srinivas Krovvidi <skrovvid@codeaurora.org>
This commit is contained in:
Srinivas Krovvidi
2012-01-12 19:46:26 +05:30
parent 7b754271f1
commit d352b26f74
4 changed files with 47 additions and 5 deletions

View File

@@ -1047,6 +1047,8 @@ int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status);
/* LE SMP Management interface */ /* LE SMP Management interface */
int le_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, void *cp); int le_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, void *cp);
int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3]); int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3]);
int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
u16 sub_ver);
/* HCI info for socket */ /* HCI info for socket */
#define hci_pi(sk) ((struct hci_pinfo *) sk) #define hci_pi(sk) ((struct hci_pinfo *) sk)

View File

@@ -347,3 +347,11 @@ struct mgmt_ev_remote_class {
bdaddr_t bdaddr; bdaddr_t bdaddr;
__u8 dev_class[3]; __u8 dev_class[3];
} __packed; } __packed;
#define MGMT_EV_REMOTE_VERSION 0x0018
struct mgmt_ev_remote_version {
bdaddr_t bdaddr;
__u8 lmp_ver;
__u16 manufacturer;
__u16 lmp_subver;
} __packed;

View File

@@ -1606,12 +1606,12 @@ static inline void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *s
if (test_bit(HCI_ENCRYPT, &hdev->flags)) if (test_bit(HCI_ENCRYPT, &hdev->flags))
conn->link_mode |= HCI_LM_ENCRYPT; conn->link_mode |= HCI_LM_ENCRYPT;
/* Get remote features */ /* Get remote version */
if (conn->type == ACL_LINK) { if (conn->type == ACL_LINK) {
struct hci_cp_read_remote_features cp; struct hci_cp_read_remote_version cp;
cp.handle = ev->handle; cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION,
sizeof(cp), &cp); sizeof(cp), &cp);
} }
/* Set packet type for incoming connection */ /* Set packet type for incoming connection */
@@ -1959,7 +1959,24 @@ unlock:
static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb) static inline void hci_remote_version_evt(struct hci_dev *hdev, struct sk_buff *skb)
{ {
BT_DBG("%s", hdev->name); struct hci_ev_remote_version *ev = (void *) skb->data;
struct hci_cp_read_remote_features cp;
struct hci_conn *conn;
BT_DBG("%s status %d", hdev->name, ev->status);
hci_dev_lock(hdev);
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
sizeof(cp), &cp);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (!ev->status)
mgmt_remote_version(hdev->id, &conn->dst, ev->lmp_ver,
ev->manufacturer, ev->lmp_subver);
unlock:
hci_dev_unlock(hdev);
} }
static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static inline void hci_qos_setup_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)

View File

@@ -2893,3 +2893,18 @@ int mgmt_remote_class(u16 index, bdaddr_t *bdaddr, u8 dev_class[3])
return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL); return mgmt_event(MGMT_EV_REMOTE_CLASS, index, &ev, sizeof(ev), NULL);
} }
int mgmt_remote_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf,
u16 sub_ver)
{
struct mgmt_ev_remote_version ev;
memset(&ev, 0, sizeof(ev));
bacpy(&ev.bdaddr, bdaddr);
ev.lmp_ver = ver;
ev.manufacturer = mnf;
ev.lmp_subver = sub_ver;
return mgmt_event(MGMT_EV_REMOTE_VERSION, index, &ev, sizeof(ev), NULL);
}