From: Gongwei Li Add processing for HCI Process Read Remote Version event. Used to query the lmp version of remote devices. Signed-off-by: Gongwei Li Reviewed-by: Paul Menzel --- v1->v2: Add bt_dev_dbg to print remote_ver v2->v3: Read ver in get_conn_info_Sync() instead of during the connection process include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/hci_sync.h | 2 ++ net/bluetooth/hci_event.c | 25 +++++++++++++++++++++++++ net/bluetooth/hci_sync.c | 11 +++++++++++ net/bluetooth/mgmt.c | 2 ++ 5 files changed, 41 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 9efdefed3..424349b74 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -750,6 +750,7 @@ struct hci_conn { __u8 remote_cap; __u8 remote_auth; + __u8 remote_ver; unsigned int sent; diff --git a/include/net/bluetooth/hci_sync.h b/include/net/bluetooth/hci_sync.h index 3133f40fa..52078c58a 100644 --- a/include/net/bluetooth/hci_sync.h +++ b/include/net/bluetooth/hci_sync.h @@ -189,3 +189,5 @@ int hci_le_conn_update_sync(struct hci_dev *hdev, struct hci_conn *conn, int hci_connect_pa_sync(struct hci_dev *hdev, struct hci_conn *conn); int hci_connect_big_sync(struct hci_dev *hdev, struct hci_conn *conn); int hci_past_sync(struct hci_conn *conn, struct hci_conn *le); + +int hci_get_remote_ver_sync(struct hci_dev *hdev, __le16 handle); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7c4ca14f1..12ed1fd36 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3738,6 +3738,28 @@ static void hci_remote_features_evt(struct hci_dev *hdev, void *data, hci_dev_unlock(hdev); } +static void hci_remote_version_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) +{ + struct hci_ev_remote_version *ev = (void *)skb->data; + struct hci_conn *conn; + + bt_dev_dbg(hdev, ""); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); + if (!conn) + goto unlock; + + conn->remote_ver = ev->lmp_ver; + + bt_dev_dbg(hdev, "remote_ver 0x%2x2", conn->remote_ver); + +unlock: + hci_dev_unlock(hdev); +} + static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd) { cancel_delayed_work(&hdev->cmd_timer); @@ -7523,6 +7545,9 @@ static const struct hci_ev { /* [0x0b = HCI_EV_REMOTE_FEATURES] */ HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt, sizeof(struct hci_ev_remote_features)), + /* [0x0c = HCI_EV_REMOTE_VERSION] */ + HCI_EV(HCI_EV_REMOTE_VERSION, hci_remote_version_evt, + sizeof(struct hci_ev_remote_version)), /* [0x0e = HCI_EV_CMD_COMPLETE] */ HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt, sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE), diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index a36d2414a..1bca97564 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -419,6 +419,17 @@ static void le_scan_disable(struct work_struct *work) static int hci_le_set_scan_enable_sync(struct hci_dev *hdev, u8 val, u8 filter_dup); +int hci_get_remote_ver_sync(struct hci_dev *hdev, __le16 handle) +{ + struct hci_cp_read_remote_version cp; + + memset(&cp, 0, sizeof(cp)); + cp.handle = handle; + + return __hci_cmd_sync_status(hdev, HCI_OP_READ_REMOTE_VERSION, + sizeof(cp), &cp, HCI_NCMD_TIMEOUT); +} + static int reenable_adv_sync(struct hci_dev *hdev, void *data) { bt_dev_dbg(hdev, ""); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c11cdef42..36f713d9e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7402,6 +7402,8 @@ static int get_conn_info_sync(struct hci_dev *hdev, void *data) /* Refresh RSSI each time */ err = hci_read_rssi_sync(hdev, handle); + err = hci_get_remote_ver_sync(hdev, handle); + /* For LE links TX power does not change thus we don't need to * query for it once value is known. */ -- 2.25.1