Lee, Chun-Yi 1f7ef9
From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Lee, Chun-Yi 1f7ef9
Date: Fri, 4 Feb 2022 13:04:38 -0800
Lee, Chun-Yi 1f7ef9
Subject: Bluetooth: hci_core: Introduce hci_recv_event_data
Lee, Chun-Yi 1f7ef9
Patch-mainline: v6.0-rc1
Lee, Chun-Yi 1f7ef9
Git-commit: dfe6d5c3ec23c5b999261d989059aa35403d791d
Lee, Chun-Yi 1f7ef9
References: jsc#PED-1407
Lee, Chun-Yi 1f7ef9
Lee, Chun-Yi 1f7ef9
This introduces hci_recv_event_data to make it simpler to access the
Lee, Chun-Yi 1f7ef9
contents of last received event rather than having to pass its contents
Lee, Chun-Yi 1f7ef9
to the likes of *_ind/*_cfm callbacks.
Lee, Chun-Yi 1f7ef9
Lee, Chun-Yi 1f7ef9
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Lee, Chun-Yi 1f7ef9
Acked-by: Lee, Chun-Yi <jlee@suse.com>
Lee, Chun-Yi 1f7ef9
---
Lee, Chun-Yi 1f7ef9
 include/net/bluetooth/hci_core.h |    2 ++
Lee, Chun-Yi 1f7ef9
 net/bluetooth/hci_core.c         |   32 ++++++++++++++++++++++++++++++++
Lee, Chun-Yi 1f7ef9
 net/bluetooth/hci_event.c        |    3 +++
Lee, Chun-Yi 1f7ef9
 3 files changed, 37 insertions(+)
Lee, Chun-Yi 1f7ef9
Lee, Chun-Yi 1f7ef9
--- a/include/net/bluetooth/hci_core.h
Lee, Chun-Yi 1f7ef9
+++ b/include/net/bluetooth/hci_core.h
Lee, Chun-Yi 1f7ef9
@@ -525,6 +525,7 @@ struct hci_dev {
Lee, Chun-Yi 1f7ef9
 	struct sk_buff_head	cmd_q;
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
 	struct sk_buff		*sent_cmd;
Lee, Chun-Yi 1f7ef9
+	struct sk_buff		*recv_event;
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
 	struct mutex		req_lock;
Lee, Chun-Yi 1f7ef9
 	wait_queue_head_t	req_wait_q;
Lee, Chun-Yi 1f7ef9
@@ -1747,6 +1748,7 @@ void hci_send_acl(struct hci_chan *chan,
Lee, Chun-Yi 1f7ef9
 void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
 void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
Lee, Chun-Yi 1f7ef9
+void *hci_recv_event_data(struct hci_dev *hdev, __u8 event);
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
 u32 hci_conn_get_phy(struct hci_conn *conn);
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
--- a/net/bluetooth/hci_core.c
Lee, Chun-Yi 1f7ef9
+++ b/net/bluetooth/hci_core.c
Lee, Chun-Yi 1f7ef9
@@ -2712,6 +2712,7 @@ void hci_release_dev(struct hci_dev *hde
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
 	ida_simple_remove(&hci_index_ida, hdev->id);
Lee, Chun-Yi 1f7ef9
 	kfree_skb(hdev->sent_cmd);
Lee, Chun-Yi 1f7ef9
+	kfree_skb(hdev->recv_event);
Lee, Chun-Yi 1f7ef9
 	kfree(hdev);
Lee, Chun-Yi 1f7ef9
 }
Lee, Chun-Yi 1f7ef9
 EXPORT_SYMBOL(hci_release_dev);
Lee, Chun-Yi 1f7ef9
@@ -3018,6 +3019,37 @@ void *hci_sent_cmd_data(struct hci_dev *
Lee, Chun-Yi 1f7ef9
 	return hdev->sent_cmd->data + HCI_COMMAND_HDR_SIZE;
Lee, Chun-Yi 1f7ef9
 }
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
+/* Get data from last received event */
Lee, Chun-Yi 1f7ef9
+void *hci_recv_event_data(struct hci_dev *hdev, __u8 event)
Lee, Chun-Yi 1f7ef9
+{
Lee, Chun-Yi 1f7ef9
+	struct hci_event_hdr *hdr;
Lee, Chun-Yi 1f7ef9
+	int offset;
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+	if (!hdev->recv_event)
Lee, Chun-Yi 1f7ef9
+		return NULL;
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+	hdr = (void *)hdev->recv_event->data;
Lee, Chun-Yi 1f7ef9
+	offset = sizeof(*hdr);
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+	if (hdr->evt != event) {
Lee, Chun-Yi 1f7ef9
+		/* In case of LE metaevent check the subevent match */
Lee, Chun-Yi 1f7ef9
+		if (hdr->evt == HCI_EV_LE_META) {
Lee, Chun-Yi 1f7ef9
+			struct hci_ev_le_meta *ev;
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+			ev = (void *)hdev->recv_event->data + offset;
Lee, Chun-Yi 1f7ef9
+			offset += sizeof(*ev);
Lee, Chun-Yi 1f7ef9
+			if (ev->subevent == event)
Lee, Chun-Yi 1f7ef9
+				goto found;
Lee, Chun-Yi 1f7ef9
+		}
Lee, Chun-Yi 1f7ef9
+		return NULL;
Lee, Chun-Yi 1f7ef9
+	}
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+found:
Lee, Chun-Yi 1f7ef9
+	bt_dev_dbg(hdev, "event 0x%2.2x", event);
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
+	return hdev->recv_event->data + offset;
Lee, Chun-Yi 1f7ef9
+}
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
 /* Send ACL data */
Lee, Chun-Yi 1f7ef9
 static void hci_add_acl_hdr(struct sk_buff *skb, __u16 handle, __u16 flags)
Lee, Chun-Yi 1f7ef9
 {
Lee, Chun-Yi 1f7ef9
--- a/net/bluetooth/hci_event.c
Lee, Chun-Yi 1f7ef9
+++ b/net/bluetooth/hci_event.c
Lee, Chun-Yi 1f7ef9
@@ -6936,6 +6936,9 @@ void hci_event_packet(struct hci_dev *hd
Lee, Chun-Yi 1f7ef9
 		goto done;
Lee, Chun-Yi 1f7ef9
 	}
Lee, Chun-Yi 1f7ef9
 
Lee, Chun-Yi 1f7ef9
+	kfree_skb(hdev->recv_event);
Lee, Chun-Yi 1f7ef9
+	hdev->recv_event = skb_clone(skb, GFP_KERNEL);
Lee, Chun-Yi 1f7ef9
+
Lee, Chun-Yi 1f7ef9
 	event = hdr->evt;
Lee, Chun-Yi 1f7ef9
 	if (!event) {
Lee, Chun-Yi 1f7ef9
 		bt_dev_warn(hdev, "Received unexpected HCI Event 0x%2.2x",