From d352b26f74591cac89bf4d501d78efcdc88a5ca3 Mon Sep 17 00:00:00 2001 From: Srinivas Krovvidi Date: Thu, 12 Jan 2012 19:46:26 +0530 Subject: [PATCH] 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 --- include/net/bluetooth/hci_core.h | 2 ++ include/net/bluetooth/mgmt.h | 8 ++++++++ net/bluetooth/hci_event.c | 27 ++++++++++++++++++++++----- net/bluetooth/mgmt.c | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 857f65406f7..8e66a251330 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1047,6 +1047,8 @@ int mgmt_encrypt_change(u16 index, bdaddr_t *bdaddr, u8 status); /* LE SMP Management interface */ 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_version(u16 index, bdaddr_t *bdaddr, u8 ver, u16 mnf, + u16 sub_ver); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index de61c32fd27..9e79fb33921 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -347,3 +347,11 @@ struct mgmt_ev_remote_class { bdaddr_t bdaddr; __u8 dev_class[3]; } __packed; + +#define MGMT_EV_REMOTE_VERSION 0x0018 +struct mgmt_ev_remote_version { + bdaddr_t bdaddr; + __u8 lmp_ver; + __u16 manufacturer; + __u16 lmp_subver; +} __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f98a90e4130..675b34f52a4 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -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)) conn->link_mode |= HCI_LM_ENCRYPT; - /* Get remote features */ + /* Get remote version */ if (conn->type == ACL_LINK) { - struct hci_cp_read_remote_features cp; + struct hci_cp_read_remote_version cp; cp.handle = ev->handle; - hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES, - sizeof(cp), &cp); + hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION, + sizeof(cp), &cp); } /* 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) { - 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) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 67a2900e922..74b1d2d930d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -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); } + +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); +}