From patchwork Wed Dec 1 18:54:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519401 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6441CC433FE for ; Wed, 1 Dec 2021 18:55:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241454AbhLAS6j (ORCPT ); Wed, 1 Dec 2021 13:58:39 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51474 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244287AbhLAS6a (ORCPT ); Wed, 1 Dec 2021 13:58:30 -0500 Received: from mail-pj1-x1035.google.com (mail-pj1-x1035.google.com [IPv6:2607:f8b0:4864:20::1035]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4866AC061748 for ; Wed, 1 Dec 2021 10:55:09 -0800 (PST) Received: by mail-pj1-x1035.google.com with SMTP id x7so18744088pjn.0 for ; Wed, 01 Dec 2021 10:55:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=9G4nN6adFXZs7o7sbkseSehA9CiImKOItvL2sjo4178=; b=oarEs9uBgDkvv6egljVtCJvsYWMIllP4GsQgwrcOLBi7vhU78bQqYi9KOaJrfcrTCN 0xN2T8Kbi7k8I0B74XINJ1mq8KE+JR63PpVP1MQaiRkZ+qja04yQkzppvrxb61gXV7Qg ScwiloxJ5NIt/THNe7jwV/ZPfl/jpC+UAG5jgF6Y9DXjEh670H2VLnjJ9DpFiYUZRyVW /DnFkvvT/FpYXlcNLyyPfMEPy1jU5YbV+zf3sWZPVNaGKEieH5PMnenQYydn0z7GrCnH njpt7bvR4DNgW8Gv6Cz357QfoBqfg5zcUGjncFiSql5bVcewAqQwKijOY8ypiqhpI3iu y4Sg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=9G4nN6adFXZs7o7sbkseSehA9CiImKOItvL2sjo4178=; b=8N4gjcvVBYEIZatbl/bH2gU2ABmjsjEhVExuVx/PXPBMoh4L77B0B9npfsLFW09ZWV FDcFJ6S78x/XMyvGBhtotOL2MbC02gjN3MbWE0TLeWk4KIRf6n0+P8ILhMHSsfBRal/q qcwJB8QzMzcsVG3Vq3VzSNZtfhKh6itEZ7gOVUdVOxysT73uXigi5e9J2ZMWHtqUX0SQ MjdJg4qPbZeNoviQa9qjPlFo0mcrEGg0dak7+b2KTrpc0iB5/nB0uvgcUI805YmyDxYp RBiHaDNRU9uOzOVOZeOML+DPjy6n6WToRx0x8K5Vz3HSMOQ1/6DZd/ZbuewRn3kEfr8O nS6A== X-Gm-Message-State: AOAM5315cdI9Mabr9sg7LveL63F8ANTLTtnxJWAFHKjvjx6mdQdMNCyi FOreTY5tMkX/JAM6weR8+rumfgi0swA= X-Google-Smtp-Source: ABdhPJzZ7LNZD7jVZKlytk+taWta0zVW4NZHPOn++zzd8PLPRVaU3mtlp5y05fkE7TPHA2+lHlVI1w== X-Received: by 2002:a17:90b:33c2:: with SMTP id lk2mr36133pjb.19.1638384908543; Wed, 01 Dec 2021 10:55:08 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:08 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 01/15] skbuff: introduce skb_pull_data Date: Wed, 1 Dec 2021 10:54:52 -0800 Message-Id: <20211201185506.1421186-2-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz Like skb_pull but returns the original data pointer before pulling the data after performing a check against sbk->len. This allows to change code that does "struct foo *p = (void *)skb->data;" which is hard to audit and error prone, to: p = skb_pull_data(skb, sizeof(*p)); if (!p) return; Which is both safer and cleaner. Acked-by: Jakub Kicinski Signed-off-by: Luiz Augusto von Dentz Signed-off-by: Dan Carpenter --- include/linux/skbuff.h | 2 ++ net/core/skbuff.c | 23 +++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index eba256af64a5..877dda38684a 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -2373,6 +2373,8 @@ static inline void *skb_pull_inline(struct sk_buff *skb, unsigned int len) return unlikely(len > skb->len) ? NULL : __skb_pull(skb, len); } +void *skb_pull_data(struct sk_buff *skb, size_t len); + void *__pskb_pull_tail(struct sk_buff *skb, int delta); static inline void *__pskb_pull(struct sk_buff *skb, unsigned int len) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index a33247fdb8f5..0b19833ffbce 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -2023,6 +2023,29 @@ void *skb_pull(struct sk_buff *skb, unsigned int len) } EXPORT_SYMBOL(skb_pull); +/** + * skb_pull_data - remove data from the start of a buffer returning its + * original position. + * @skb: buffer to use + * @len: amount of data to remove + * + * This function removes data from the start of a buffer, returning + * the memory to the headroom. A pointer to the original data in the buffer + * is returned after checking if there is enough data to pull. Once the + * data has been pulled future pushes will overwrite the old data. + */ +void *skb_pull_data(struct sk_buff *skb, size_t len) +{ + void *data = skb->data; + + if (skb->len < len) + return NULL; + + skb_pull(skb, len); + + return data; +} + /** * skb_trim - remove end from a buffer * @skb: buffer to alter From patchwork Wed Dec 1 18:54:53 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520586 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id DC9EFC4332F for ; Wed, 1 Dec 2021 18:55:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244948AbhLAS6l (ORCPT ); Wed, 1 Dec 2021 13:58:41 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51478 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244351AbhLAS6b (ORCPT ); Wed, 1 Dec 2021 13:58:31 -0500 Received: from mail-pj1-x102b.google.com (mail-pj1-x102b.google.com [IPv6:2607:f8b0:4864:20::102b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6F8DFC06174A for ; Wed, 1 Dec 2021 10:55:10 -0800 (PST) Received: by mail-pj1-x102b.google.com with SMTP id h24so18714625pjq.2 for ; Wed, 01 Dec 2021 10:55:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=Bk82bxXbJxygZ2/esoOJbOmQoFQoDGqBukGE9+ZJoh8=; b=pBOERnkBDD09b+pmR5/YV8RhEc9uD7nhzsJK91BNFeS4VTN1PwcaeJgML/yVpMSFfG r8gjIMxkYB2nvjC9T6o/uUmOqF9B4nvxOYZ7LiWuzOuWSpJnWj6zyGk3nU5SxknYjvP0 81EPALT2e06ozzClEN7G/fSAk/809p3eobEj0+6aujcInguTXbkYxpVl7gxEBGp+MUHf EJeJYgl9nGSz3ZeJBKZGPXzvPcEstr8Xj+YrbdciU1Fl6kKXy8iMW3VT7y34VZJw1WJM w1OE+Biq2UMP4liIlnzqaXSo3JCg3LzJbMS+j4bf2J3X6TVZwygdemlh+Czw2/Vo1Y0J MnQw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Bk82bxXbJxygZ2/esoOJbOmQoFQoDGqBukGE9+ZJoh8=; b=1esJLpupDg4h8pwWISYVK4P432r9l4eSHI2Ml8YJr2jkHO3Q04gd8RMNfmWCIEC5+S Z1CmLem6IpRujZPK0f43SzrOrAi4CQIulrut8Gqa50+bElPLBmfvT8AXKT+G5QK+l0Wb /A5UYiAOzQR4nmEvH2mUKs6OvvIO62nGiLDKHPHrp6AbVfatl0R0j93J/3dWF0aTj+zv 3Im2UkqObHjYpCZ0uwmFZfYUs1PJRy5aX3xQVUlkVdosuW85pfqoEJlvW1iBRnGruqef /A8pXfUNnc6LcTckJWFW9n505oBZSaLdEJVtPZ4QJZ2pq5Uza9c+JgY0BET+JQx3x42l IG1w== X-Gm-Message-State: AOAM5308BECWPJmSIbXaumsDiaxEeTFkyJglrUZmPBTUPsx3katPdVpL 7biG3eGNK9UiD4yrcYLrYMCh+7pfw5c= X-Google-Smtp-Source: ABdhPJzsNjjZbv0v+jP5E4fPEr4vpLvAQUTUdDaY6SUIAh/sKdLMYgSCN9iYZYW1Z+Ho/7GMYtvBbg== X-Received: by 2002:a17:90b:2252:: with SMTP id hk18mr91260pjb.36.1638384909354; Wed, 01 Dec 2021 10:55:09 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.08 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:08 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 02/15] Bluetooth: HCI: Use skb_pull_data to parse BR/EDR events Date: Wed, 1 Dec 2021 10:54:53 -0800 Message-Id: <20211201185506.1421186-3-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the BR/EDR events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 4 + net/bluetooth/hci_event.c | 260 +++++++++++++++++++++++++++++------- 2 files changed, 217 insertions(+), 47 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 0d2a9216869b..ba89b078ceb5 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2012,6 +2012,10 @@ struct hci_cp_le_reject_cis { } __packed; /* ---- HCI Events ---- */ +struct hci_ev_status { + __u8 status; +} __packed; + #define HCI_EV_INQUIRY_COMPLETE 0x01 #define HCI_EV_INQUIRY_RESULT 0x02 diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 9d8d2d9e5d1f..0266eab8a18c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -45,6 +45,18 @@ /* Handle HCI Event packets */ +static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, + u8 ev, size_t len) +{ + void *data; + + data = skb_pull_data(skb, len); + if (!data) + bt_dev_err(hdev, "Malformed Event: 0x%2.2x", ev); + + return data; +} + static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, u8 *new_status) { @@ -2682,11 +2694,15 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status) static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *ev; struct discovery_state *discov = &hdev->discovery; struct inquiry_entry *e; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_COMPLETE, sizeof(*ev)); + if (!ev) + return; + + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_conn_check_pending(hdev); @@ -2780,9 +2796,13 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_conn_complete *ev = (void *) skb->data; + struct hci_ev_conn_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_COMPLETE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -2904,12 +2924,16 @@ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_conn_request *ev = (void *) skb->data; + struct hci_ev_conn_request *ev; int mask = hdev->link_mode; struct inquiry_entry *ie; struct hci_conn *conn; __u8 flags = 0; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_REQUEST, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, ev->link_type); @@ -3015,12 +3039,16 @@ static u8 hci_to_mgmt_reason(u8 err) static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_disconn_complete *ev = (void *) skb->data; + struct hci_ev_disconn_complete *ev; u8 reason; struct hci_conn_params *params; struct hci_conn *conn; bool mgmt_connected; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_COMPLETE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -3099,9 +3127,13 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_auth_complete *ev = (void *) skb->data; + struct hci_ev_auth_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_AUTH_COMPLETE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -3169,9 +3201,13 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_name *ev = (void *) skb->data; + struct hci_ev_remote_name *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_NAME, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_conn_check_pending(hdev); @@ -3252,9 +3288,13 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_encrypt_change *ev = (void *) skb->data; + struct hci_ev_encrypt_change *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ENCRYPT_CHANGE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -3367,9 +3407,14 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_change_link_key_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_change_link_key_complete *ev = (void *) skb->data; + struct hci_ev_change_link_key_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANGE_LINK_KEY_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -3390,9 +3435,13 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev, static void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_features *ev = (void *) skb->data; + struct hci_ev_remote_features *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_FEATURES, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -3841,9 +3890,11 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, hci_req_complete_t *req_complete, hci_req_complete_skb_t *req_complete_skb) { - struct hci_ev_cmd_status *ev = (void *) skb->data; + struct hci_ev_cmd_status *ev; - skb_pull(skb, sizeof(*ev)); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_STATUS, sizeof(*ev)); + if (!ev) + return; *opcode = __le16_to_cpu(ev->opcode); *status = ev->status; @@ -3951,7 +4002,11 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_hardware_error *ev = (void *) skb->data; + struct hci_ev_hardware_error *ev; + + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_HARDWARE_ERROR, sizeof(*ev)); + if (!ev) + return; hdev->hw_error_code = ev->code; @@ -3960,9 +4015,13 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_role_change *ev = (void *) skb->data; + struct hci_ev_role_change *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ROLE_CHANGE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -4070,17 +4129,19 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_num_comp_blocks *ev = (void *) skb->data; + struct hci_ev_num_comp_blocks *ev; int i; - if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { - bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, sizeof(*ev)); + if (!ev) return; - } - if (skb->len < sizeof(*ev) || - skb->len < struct_size(ev, handles, ev->num_hndl)) { - BT_DBG("%s bad parameters", hdev->name); + if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, + flex_array_size(ev, handles, ev->num_hndl))) + return; + + if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { + bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); return; } @@ -4121,9 +4182,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_mode_change *ev = (void *) skb->data; + struct hci_ev_mode_change *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_MODE_CHANGE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -4149,9 +4214,13 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_pin_code_req *ev = (void *) skb->data; + struct hci_ev_pin_code_req *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PIN_CODE_REQ, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4219,11 +4288,15 @@ static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len) static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_link_key_req *ev = (void *) skb->data; + struct hci_ev_link_key_req *ev; struct hci_cp_link_key_reply cp; struct hci_conn *conn; struct link_key *key; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_REQ, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); if (!hci_dev_test_flag(hdev, HCI_MGMT)) @@ -4279,12 +4352,16 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_link_key_notify *ev = (void *) skb->data; + struct hci_ev_link_key_notify *ev; struct hci_conn *conn; struct link_key *key; bool persistent; u8 pin_len = 0; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_NOTIFY, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4339,9 +4416,13 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_clock_offset *ev = (void *) skb->data; + struct hci_ev_clock_offset *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CLOCK_OFFSET, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -4362,9 +4443,13 @@ static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_pkt_type_change *ev = (void *) skb->data; + struct hci_ev_pkt_type_change *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PKT_TYPE_CHANGE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -4378,9 +4463,13 @@ static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_pscan_rep_mode *ev = (void *) skb->data; + struct hci_ev_pscan_rep_mode *ev; struct inquiry_entry *ie; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PSCAN_REP_MODE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4468,9 +4557,14 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, static void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_ext_features *ev = (void *) skb->data; + struct hci_ev_remote_ext_features *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_EXT_FEATURES, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4532,9 +4626,13 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, static void hci_sync_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_sync_conn_complete *ev = (void *) skb->data; + struct hci_ev_sync_conn_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SYNC_CONN_COMPLETE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -4697,9 +4795,14 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, static void hci_key_refresh_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_key_refresh_complete *ev = (void *) skb->data; + struct hci_ev_key_refresh_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEY_REFRESH_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, __le16_to_cpu(ev->handle)); @@ -4806,9 +4909,13 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_io_capa_request *ev = (void *) skb->data; + struct hci_ev_io_capa_request *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REQUEST, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4875,9 +4982,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_io_capa_reply *ev = (void *) skb->data; + struct hci_ev_io_capa_reply *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REPLY, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4896,10 +5007,15 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_user_confirm_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_user_confirm_req *ev = (void *) skb->data; + struct hci_ev_user_confirm_req *ev; int loc_mitm, rem_mitm, confirm_hint = 0; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_CONFIRM_REQUEST, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -4981,7 +5097,12 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, static void hci_user_passkey_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_user_passkey_req *ev = (void *) skb->data; + struct hci_ev_user_passkey_req *ev; + + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_REQUEST, + sizeof(*ev)); + if (!ev) + return; BT_DBG("%s", hdev->name); @@ -4992,9 +5113,14 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, static void hci_user_passkey_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_user_passkey_notify *ev = (void *) skb->data; + struct hci_ev_user_passkey_notify *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_NOTIFY, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); @@ -5012,9 +5138,13 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_keypress_notify *ev = (void *) skb->data; + struct hci_ev_keypress_notify *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEYPRESS_NOTIFY, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); @@ -5051,9 +5181,14 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_simple_pair_complete *ev = (void *) skb->data; + struct hci_ev_simple_pair_complete *ev; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SIMPLE_PAIR_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -5082,10 +5217,15 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, static void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_host_features *ev = (void *) skb->data; + struct hci_ev_remote_host_features *ev; struct inquiry_entry *ie; struct hci_conn *conn; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_HOST_FEATURES, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -5104,9 +5244,14 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev, static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_remote_oob_data_request *ev = (void *) skb->data; + struct hci_ev_remote_oob_data_request *ev; struct oob_data *data; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_OOB_DATA_REQUEST, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s", hdev->name); hci_dev_lock(hdev); @@ -5158,12 +5303,14 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, #if IS_ENABLED(CONFIG_BT_HS) static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_channel_selected *ev = (void *)skb->data; + struct hci_ev_channel_selected *ev; struct hci_conn *hcon; - BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANNEL_SELECTED, sizeof(*ev)); + if (!ev) + return; - skb_pull(skb, sizeof(*ev)); + BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); if (!hcon) @@ -5175,9 +5322,13 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_phy_link_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_phy_link_complete *ev = (void *) skb->data; + struct hci_ev_phy_link_complete *ev; struct hci_conn *hcon, *bredr_hcon; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PHY_LINK_COMPLETE, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, ev->status); @@ -5215,11 +5366,16 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev, static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_logical_link_complete *ev = (void *) skb->data; + struct hci_ev_logical_link_complete *ev; struct hci_conn *hcon; struct hci_chan *hchan; struct amp_mgr *mgr; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LOGICAL_LINK_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, ev->status); @@ -5255,9 +5411,14 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_disconn_logical_link_complete *ev = (void *) skb->data; + struct hci_ev_disconn_logical_link_complete *ev; struct hci_chan *hchan; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, le16_to_cpu(ev->handle), ev->status); @@ -5279,9 +5440,14 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_disconn_phy_link_complete *ev = (void *) skb->data; + struct hci_ev_disconn_phy_link_complete *ev; struct hci_conn *hcon; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_PHY_LINK_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); if (ev->status) From patchwork Wed Dec 1 18:54:54 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519396 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0C922C433FE for ; Wed, 1 Dec 2021 18:55:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244960AbhLAS6s (ORCPT ); Wed, 1 Dec 2021 13:58:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51488 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244918AbhLAS6d (ORCPT ); Wed, 1 Dec 2021 13:58:33 -0500 Received: from mail-pg1-x529.google.com (mail-pg1-x529.google.com [IPv6:2607:f8b0:4864:20::529]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B38DDC061758 for ; Wed, 1 Dec 2021 10:55:11 -0800 (PST) Received: by mail-pg1-x529.google.com with SMTP id 137so17505326pgg.3 for ; Wed, 01 Dec 2021 10:55:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=uPOJ6g8lTG95Y+Z46Oq6oJf/fMR/nONJgH+NY07iJEw=; b=IaqgkfMi18xdz9iJFQq/1Tw8c9Jt7f0bvFUvVNvloVM7JLwh7hWjhDhKaHbRCSErjS dlXvDCPJxeOI+f/R4GiIe79OMA/gYb7qLE3kuSVoDN8qR8ajdIUME4Swmz3nXSpLktEn ZXsjhD/5fF8B2g4XUR1s39F+ttWYpNgbNyLTa9FklLS0WMi14VtLVibp7X6qxJOrA9hl PdnW+TGopamTWEKCPwx6UBTxcUiroDnbJz4Vlql75n7hLBRkKlqRlDDZWKvXY+EMvBuw kC+Uptfp7qev+lBPZjZS6oPdduJKo2hnbeCBrIsfCsE6SNaHSyCp0UVNk9Ac5yAZpjVn v/Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=uPOJ6g8lTG95Y+Z46Oq6oJf/fMR/nONJgH+NY07iJEw=; b=xPDUg9XYIUDtJ2ls2Yp57hpiwOgS/YgIwmDFnSao6fPxLCtcrmV1jPu1oG40nADOiA cFRy9jQ1FJ57e22YAEChUak615fsobgohCCx4mLTT4CA6sfjeFuM4nBIA3PPAOhN7zkQ ws5vebB9gLRPCHgoglFPy+ow/ciQRGQXfykEaYxma4qUpiTRE0tHqAWUNcdGuOc6vdK1 gHFCFCc1XTWsWQufwAoyVdorAvfe/AwiHEtUKzUHpJVvnpCzY/IgbJeEk5r5TN9w6qo5 1UOnMImWJd+X4n+0c+39+0iWj3iZfv4qsaxm7kXyei0qSM20NLLEM48Bm29A9ESdzswE VNcQ== X-Gm-Message-State: AOAM532OS9sbPXmc1J7IG0265FzAAwJ26NRNUTISf9MhlGWFrXKxTgea +Jxn7SnLlMCW5u+9hnCTGjIvzS0J+10= X-Google-Smtp-Source: ABdhPJwOcZ9LCUn+CEabbHAUSEhGDuow0KnS0aIFKMm8wZzgMMqCV1FqOiP5P3ZXPy5lZ4ksRK2M2A== X-Received: by 2002:a05:6a00:1504:b0:4a0:28a7:ced8 with SMTP id q4-20020a056a00150400b004a028a7ced8mr7818929pfu.30.1638384910156; Wed, 01 Dec 2021 10:55:10 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.09 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:09 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 03/15] Bluetooth: HCI: Use skb_pull_data to parse Command Complete event Date: Wed, 1 Dec 2021 10:54:54 -0800 Message-Id: <20211201185506.1421186-4-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the Command Complete events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 904 ++++++++++++++++++++++++++++---------- 1 file changed, 663 insertions(+), 241 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0266eab8a18c..09d7d997c4b1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -57,12 +57,28 @@ static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, return data; } +static void *hci_cc_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, + u16 op, size_t len) +{ + void *data; + + data = skb_pull_data(skb, len); + if (!data) + bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x", op); + + return data; +} + static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, u8 *new_status) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_INQUIRY_CANCEL, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); /* It is possible that we receive Inquiry Complete event right * before we receive Inquiry Cancel Command Complete event, in @@ -71,14 +87,14 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, * we actually achieve what Inquiry Cancel wants to achieve, * which is to end the last Inquiry session. */ - if (status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) { + if (rp->status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) { bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command"); - status = 0x00; + rp->status = 0x00; } - *new_status = status; + *new_status = rp->status; - if (status) + if (rp->status) return; clear_bit(HCI_INQUIRY, &hdev->flags); @@ -99,11 +115,15 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PERIODIC_INQ, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; hci_dev_set_flag(hdev, HCI_PERIODIC_INQ); @@ -111,11 +131,15 @@ static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_EXIT_PERIODIC_INQ, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); @@ -126,15 +150,26 @@ static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, struct sk_buff *skb) { - BT_DBG("%s", hdev->name); + struct hci_ev_status *rp; + + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_REMOTE_NAME_REQ_CANCEL, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); } static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_role_discovery *rp = (void *) skb->data; + struct hci_rp_role_discovery *rp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_ROLE_DISCOVERY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -150,10 +185,14 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_link_policy *rp = (void *) skb->data; + struct hci_rp_read_link_policy *rp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LINK_POLICY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -169,11 +208,15 @@ static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_write_link_policy *rp = (void *) skb->data; + struct hci_rp_write_link_policy *rp; struct hci_conn *conn; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LINK_POLICY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -194,9 +237,14 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_def_link_policy *rp = (void *) skb->data; + struct hci_rp_read_def_link_policy *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_LINK_POLICY, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -207,12 +255,17 @@ static void hci_cc_read_def_link_policy(struct hci_dev *hdev, static void hci_cc_write_def_link_policy(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_LINK_POLICY, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); @@ -224,13 +277,17 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev, static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_RESET, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); clear_bit(HCI_RESET, &hdev->flags); - if (status) + if (rp->status) return; /* Reset all non-persistent flags */ @@ -258,10 +315,15 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_stored_link_key(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_stored_link_key *rp = (void *)skb->data; + struct hci_rp_read_stored_link_key *rp; struct hci_cp_read_stored_link_key *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_STORED_LINK_KEY, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY); if (!sent) @@ -276,9 +338,14 @@ static void hci_cc_read_stored_link_key(struct hci_dev *hdev, static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_delete_stored_link_key *rp = (void *)skb->data; + struct hci_rp_delete_stored_link_key *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_DELETE_STORED_LINK_KEY, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -291,10 +358,14 @@ static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LOCAL_NAME, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); if (!sent) @@ -303,8 +374,8 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); if (hci_dev_test_flag(hdev, HCI_MGMT)) - mgmt_set_local_name_complete(hdev, sent, status); - else if (!status) + mgmt_set_local_name_complete(hdev, sent, rp->status); + else if (!rp->status) memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); hci_dev_unlock(hdev); @@ -312,9 +383,13 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_name *rp = (void *) skb->data; + struct hci_rp_read_local_name *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_NAME, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -326,10 +401,14 @@ static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_ENABLE, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); if (!sent) @@ -337,7 +416,7 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (!status) { + if (!rp->status) { __u8 param = *((__u8 *) sent); if (param == AUTH_ENABLED) @@ -347,20 +426,24 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) } if (hci_dev_test_flag(hdev, HCI_MGMT)) - mgmt_auth_enable_complete(hdev, status); + mgmt_auth_enable_complete(hdev, rp->status); hci_dev_unlock(hdev); } static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; __u8 param; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_ENCRYPT_MODE, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); @@ -377,11 +460,15 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; __u8 param; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); if (!sent) @@ -391,7 +478,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (status) { + if (rp->status) { hdev->discov_timeout = 0; goto done; } @@ -412,13 +499,17 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *)skb->data); + struct hci_ev_status *rp; struct hci_cp_set_event_filter *cp; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT); @@ -435,25 +526,33 @@ static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_class_of_dev *rp = (void *) skb->data; + struct hci_rp_read_class_of_dev *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; memcpy(hdev->dev_class, rp->dev_class, 3); - BT_DBG("%s class 0x%.2x%.2x%.2x", hdev->name, - hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); + bt_dev_dbg(hdev, "class 0x%.2x%.2x%.2x", hdev->dev_class[2], + hdev->dev_class[1], hdev->dev_class[0]); } static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); if (!sent) @@ -461,21 +560,25 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (status == 0) + if (!rp->status) memcpy(hdev->dev_class, sent, 3); if (hci_dev_test_flag(hdev, HCI_MGMT)) - mgmt_set_class_of_dev_complete(hdev, sent, status); + mgmt_set_class_of_dev_complete(hdev, sent, rp->status); hci_dev_unlock(hdev); } static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_voice_setting *rp = (void *) skb->data; + struct hci_rp_read_voice_setting *rp; __u16 setting; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_VOICE_SETTING, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -487,7 +590,7 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) hdev->voice_setting = setting; - BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); + bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); @@ -496,13 +599,18 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; __u16 setting; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_VOICE_SETTING, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); @@ -516,7 +624,7 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, hdev->voice_setting = setting; - BT_DBG("%s voice setting 0x%4.4x", hdev->name, setting); + bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); @@ -525,24 +633,33 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; + struct hci_rp_read_num_supported_iac *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_NUM_SUPPORTED_IAC, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; hdev->num_iac = rp->num_iac; - BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); + bt_dev_dbg(hdev, "num iac %d", hdev->num_iac); } static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_write_ssp_mode *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_MODE, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); if (!sent) @@ -550,14 +667,14 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (!status) { + if (!rp->status) { if (sent->mode) hdev->features[1][0] |= LMP_HOST_SSP; else hdev->features[1][0] &= ~LMP_HOST_SSP; } - if (!status) { + if (!rp->status) { if (sent->mode) hci_dev_set_flag(hdev, HCI_SSP_ENABLED); else @@ -569,10 +686,14 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) { - u8 status = *((u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_write_sc_support *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SC_SUPPORT, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); if (!sent) @@ -580,14 +701,14 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (!status) { + if (!rp->status) { if (sent->support) hdev->features[1][0] |= LMP_HOST_SC; else hdev->features[1][0] &= ~LMP_HOST_SC; } - if (!hci_dev_test_flag(hdev, HCI_MGMT) && !status) { + if (!hci_dev_test_flag(hdev, HCI_MGMT) && !rp->status) { if (sent->support) hci_dev_set_flag(hdev, HCI_SC_ENABLED); else @@ -599,9 +720,13 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_version *rp = (void *) skb->data; + struct hci_rp_read_local_version *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_VERSION, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -619,9 +744,14 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_commands(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_commands *rp = (void *) skb->data; + struct hci_rp_read_local_commands *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_COMMANDS, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -634,10 +764,15 @@ static void hci_cc_read_local_commands(struct hci_dev *hdev, static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_auth_payload_to *rp = (void *)skb->data; + struct hci_rp_read_auth_payload_to *rp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_AUTH_PAYLOAD_TO, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -654,11 +789,15 @@ static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_write_auth_payload_to *rp = (void *)skb->data; + struct hci_rp_write_auth_payload_to *rp; struct hci_conn *conn; void *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_PAYLOAD_TO, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -679,9 +818,14 @@ static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, static void hci_cc_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_features *rp = (void *) skb->data; + struct hci_rp_read_local_features *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_FEATURES, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -729,9 +873,14 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, static void hci_cc_read_local_ext_features(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_ext_features *rp = (void *) skb->data; + struct hci_rp_read_local_ext_features *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_EXT_FEATURES, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -746,9 +895,14 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; + struct hci_rp_read_flow_control_mode *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_FLOW_CONTROL_MODE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -758,9 +912,13 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_buffer_size *rp = (void *) skb->data; + struct hci_rp_read_buffer_size *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BUFFER_SIZE, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -784,9 +942,13 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_bd_addr *rp = (void *) skb->data; + struct hci_rp_read_bd_addr *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BD_ADDR, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -801,9 +963,14 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_pairing_opts *rp = (void *) skb->data; + struct hci_rp_read_local_pairing_opts *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_PAIRING_OPTS, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -818,9 +985,14 @@ static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev, static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_page_scan_activity *rp = (void *) skb->data; + struct hci_rp_read_page_scan_activity *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -834,12 +1006,17 @@ static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, struct sk_buff *skb) { - u8 status = *((u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_write_page_scan_activity *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); @@ -853,9 +1030,14 @@ static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, static void hci_cc_read_page_scan_type(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_page_scan_type *rp = (void *) skb->data; + struct hci_rp_read_page_scan_type *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_TYPE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -867,12 +1049,17 @@ static void hci_cc_read_page_scan_type(struct hci_dev *hdev, static void hci_cc_write_page_scan_type(struct hci_dev *hdev, struct sk_buff *skb) { - u8 status = *((u8 *) skb->data); + struct hci_ev_status *rp; u8 *type; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_PAGE_SCAN_TYPE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); @@ -883,9 +1070,14 @@ static void hci_cc_write_page_scan_type(struct hci_dev *hdev, static void hci_cc_read_data_block_size(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_data_block_size *rp = (void *) skb->data; + struct hci_rp_read_data_block_size *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DATA_BLOCK_SIZE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -902,15 +1094,18 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_clock *rp = (void *) skb->data; + struct hci_rp_read_clock *rp; struct hci_cp_read_clock *cp; struct hci_conn *conn; BT_DBG("%s", hdev->name); - if (skb->len < sizeof(*rp)) + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLOCK, sizeof(*rp)); + if (!rp) return; + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + if (rp->status) return; @@ -938,9 +1133,14 @@ static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_local_amp_info(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_amp_info *rp = (void *) skb->data; + struct hci_rp_read_local_amp_info *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_AMP_INFO, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -960,9 +1160,14 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_inq_rsp_tx_power *rp = (void *) skb->data; + struct hci_rp_read_inq_rsp_tx_power *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_INQ_RSP_TX_POWER, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -973,9 +1178,14 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_def_err_data_reporting *rp = (void *)skb->data; + struct hci_rp_read_def_err_data_reporting *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_ERR_DATA_REPORTING, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -986,12 +1196,17 @@ static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *)skb->data); + struct hci_ev_status *rp; struct hci_cp_write_def_err_data_reporting *cp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING); @@ -1003,11 +1218,15 @@ static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_pin_code_reply *rp = (void *) skb->data; + struct hci_rp_pin_code_reply *rp; struct hci_cp_pin_code_reply *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_REPLY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1031,9 +1250,13 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_pin_code_neg_reply *rp = (void *) skb->data; + struct hci_rp_pin_code_neg_reply *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1047,9 +1270,14 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_buffer_size *rp = (void *) skb->data; + struct hci_rp_le_read_buffer_size *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_BUFFER_SIZE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1065,7 +1293,12 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, static void hci_cc_le_read_local_features(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_local_features *rp = (void *) skb->data; + struct hci_rp_le_read_local_features *rp; + + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_LOCAL_FEATURES, + sizeof(*rp)); + if (!rp) + return; BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); @@ -1078,9 +1311,14 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev, static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_adv_tx_power *rp = (void *) skb->data; + struct hci_rp_le_read_adv_tx_power *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ADV_TX_POWER, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1090,9 +1328,13 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; + struct hci_rp_user_confirm_reply *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_REPLY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1106,9 +1348,14 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; + struct hci_rp_user_confirm_reply *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_NEG_REPLY, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1121,9 +1368,13 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; + struct hci_rp_user_confirm_reply *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_REPLY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1137,9 +1388,13 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp = (void *) skb->data; + struct hci_rp_user_confirm_reply *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1153,27 +1408,39 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, static void hci_cc_read_local_oob_data(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_oob_data *rp = (void *) skb->data; + struct hci_rp_read_local_oob_data *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_DATA, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); } static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; + struct hci_rp_read_local_oob_ext_data *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_EXT_DATA, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); } static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; bdaddr_t *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_RANDOM_ADDR, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); @@ -1195,12 +1462,16 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_le_set_default_phy *cp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY); @@ -1218,11 +1489,18 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_le_set_adv_set_rand_addr *cp; struct adv_info *adv; - if (status) + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_SET_RAND_ADDR, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR); @@ -1251,11 +1529,17 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *)skb->data); + struct hci_ev_status *rp; u8 *instance; int err; - if (status) + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_REMOVE_ADV_SET, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; instance = hci_sent_cmd_data(hdev, HCI_OP_LE_REMOVE_ADV_SET); @@ -1274,11 +1558,17 @@ static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *)skb->data); + struct hci_ev_status *rp; struct adv_info *adv, *n; int err; - if (status) + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ADV_SETS, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; if (!hci_sent_cmd_data(hdev, HCI_OP_LE_CLEAR_ADV_SETS)) @@ -1301,9 +1591,14 @@ static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_le_read_transmit_power(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_transmit_power *rp = (void *)skb->data; + struct hci_rp_le_read_transmit_power *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_TRANSMIT_POWER, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1314,11 +1609,16 @@ static void hci_cc_le_read_transmit_power(struct hci_dev *hdev, static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 *sent, status = *((__u8 *) skb->data); + struct hci_ev_status *rp; + __u8 *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_ENABLE, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); @@ -1352,12 +1652,17 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, { struct hci_cp_le_set_ext_adv_enable *cp; struct hci_cp_ext_adv_set *set; - __u8 status = *((__u8 *) skb->data); struct adv_info *adv = NULL, *n; + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_ENABLE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE); @@ -1414,11 +1719,15 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_set_scan_param *cp; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_PARAM, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); @@ -1436,12 +1745,17 @@ static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_set_ext_scan_params *cp; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; struct hci_cp_le_scan_phy_params *phy_param; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_PARAMS, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS); @@ -1544,11 +1858,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_set_scan_enable *cp; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_ENABLE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); @@ -1562,11 +1881,16 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_set_ext_scan_enable *cp; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_ENABLE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE); @@ -1579,10 +1903,15 @@ static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_num_supported_adv_sets *rp = (void *) skb->data; + struct hci_rp_le_read_num_supported_adv_sets *rp; + + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS, + sizeof(*rp)); + if (!rp) + return; - BT_DBG("%s status 0x%2.2x No of Adv sets %u", hdev->name, rp->status, - rp->num_of_sets); + bt_dev_dbg(hdev, "status 0x%2.2x No of Adv sets %u", rp->status, + rp->num_of_sets); if (rp->status) return; @@ -1593,9 +1922,14 @@ static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_accept_list_size *rp = (void *)skb->data; + struct hci_rp_le_read_accept_list_size *rp; - BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ACCEPT_LIST_SIZE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size); if (rp->status) return; @@ -1606,11 +1940,16 @@ static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev, static void hci_cc_le_clear_accept_list(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ACCEPT_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; hci_bdaddr_list_clear(&hdev->le_accept_list); @@ -1620,11 +1959,16 @@ static void hci_cc_le_add_to_accept_list(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_add_to_accept_list *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_ACCEPT_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); @@ -1639,11 +1983,16 @@ static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_del_from_accept_list *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_ACCEPT_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST); @@ -1657,9 +2006,14 @@ static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev, static void hci_cc_le_read_supported_states(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_supported_states *rp = (void *) skb->data; + struct hci_rp_le_read_supported_states *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_SUPPORTED_STATES, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1670,9 +2024,14 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev, static void hci_cc_le_read_def_data_len(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_def_data_len *rp = (void *) skb->data; + struct hci_rp_le_read_def_data_len *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_DEF_DATA_LEN, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1685,11 +2044,16 @@ static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_write_def_data_len *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_WRITE_DEF_DATA_LEN, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN); @@ -1704,11 +2068,16 @@ static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_add_to_resolv_list *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_RESOLV_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST); @@ -1724,11 +2093,16 @@ static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_del_from_resolv_list *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_RESOLV_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST); @@ -1742,11 +2116,16 @@ static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_RESOLV_LIST, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; hci_bdaddr_list_clear(&hdev->le_resolv_list); @@ -1755,9 +2134,14 @@ static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_resolv_list_size *rp = (void *) skb->data; + struct hci_rp_le_read_resolv_list_size *rp; - BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_RESOLV_LIST_SIZE, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size); if (rp->status) return; @@ -1768,11 +2152,17 @@ static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, struct sk_buff *skb) { - __u8 *sent, status = *((__u8 *) skb->data); + struct hci_ev_status *rp; + __u8 *sent; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE); @@ -1792,9 +2182,14 @@ static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, static void hci_cc_le_read_max_data_len(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_read_max_data_len *rp = (void *) skb->data; + struct hci_rp_le_read_max_data_len *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_MAX_DATA_LEN, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1809,11 +2204,16 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_write_le_host_supported *sent; - __u8 status = *((__u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LE_HOST_SUPPORTED, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); @@ -1842,11 +2242,15 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_le_set_adv_param *cp; - u8 status = *((u8 *) skb->data); + struct hci_ev_status *rp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_PARAM, sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); @@ -1860,11 +2264,16 @@ static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_le_set_ext_adv_params *rp = (void *) skb->data; + struct hci_rp_le_set_ext_adv_params *rp; struct hci_cp_le_set_ext_adv_params *cp; struct adv_info *adv_instance; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_PARAMS, + sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1891,10 +2300,14 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_rp_read_rssi *rp = (void *) skb->data; + struct hci_rp_read_rssi *rp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_RSSI, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1911,10 +2324,14 @@ static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_cp_read_tx_power *sent; - struct hci_rp_read_tx_power *rp = (void *) skb->data; + struct hci_rp_read_tx_power *rp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_TX_POWER, sizeof(*rp)); + if (!rp) + return; + + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) return; @@ -1944,12 +2361,17 @@ static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb) { - u8 status = *((u8 *) skb->data); + struct hci_ev_status *rp; u8 *mode; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_DEBUG_MODE, + sizeof(*rp)); + if (!rp) + return; - if (status) + bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + if (rp->status) return; mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE); @@ -3505,12 +3927,14 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, hci_req_complete_t *req_complete, hci_req_complete_skb_t *req_complete_skb) { - struct hci_ev_cmd_complete *ev = (void *) skb->data; + struct hci_ev_cmd_complete *ev; - *opcode = __le16_to_cpu(ev->opcode); - *status = skb->data[sizeof(*ev)]; + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_COMPLETE, sizeof(*ev)); + if (!ev) + return; - skb_pull(skb, sizeof(*ev)); + *opcode = __le16_to_cpu(ev->opcode); + *status = skb->data[0]; switch (*opcode) { case HCI_OP_INQUIRY_CANCEL: @@ -6466,13 +6890,9 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, if (!skb) return false; - if (skb->len < sizeof(*hdr)) { - bt_dev_err(hdev, "too short HCI event"); + hdr = hci_ev_skb_pull(hdev, skb, event, sizeof(*hdr)); + if (!hdr) return false; - } - - hdr = (void *) skb->data; - skb_pull(skb, HCI_EVENT_HDR_SIZE); if (event) { if (hdr->evt != event) @@ -6492,13 +6912,9 @@ static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, return false; } - if (skb->len < sizeof(*ev)) { - bt_dev_err(hdev, "too short cmd_complete event"); + ev = hci_cc_skb_pull(hdev, skb, opcode, sizeof(*ev)); + if (!ev) return false; - } - - ev = (void *) skb->data; - skb_pull(skb, sizeof(*ev)); if (opcode != __le16_to_cpu(ev->opcode)) { BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode, @@ -6584,9 +7000,15 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_req_complete_t req_complete = NULL; hci_req_complete_skb_t req_complete_skb = NULL; struct sk_buff *orig_skb = NULL; - u8 status = 0, event = hdr->evt, req_evt = 0; + u8 status = 0, event, req_evt = 0; u16 opcode = HCI_OP_NOP; + if (skb->len < sizeof(*hdr)) { + bt_dev_err(hdev, "Malformed HCI Event"); + goto done; + } + + event = hdr->evt; if (!event) { bt_dev_warn(hdev, "Received unexpected HCI Event 00000000"); goto done; From patchwork Wed Dec 1 18:54:55 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519399 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 29504C433F5 for ; Wed, 1 Dec 2021 18:55:24 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351455AbhLAS6o (ORCPT ); Wed, 1 Dec 2021 13:58:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51486 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244895AbhLAS6d (ORCPT ); Wed, 1 Dec 2021 13:58:33 -0500 Received: from mail-pl1-x636.google.com (mail-pl1-x636.google.com [IPv6:2607:f8b0:4864:20::636]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8507DC061757 for ; Wed, 1 Dec 2021 10:55:11 -0800 (PST) Received: by mail-pl1-x636.google.com with SMTP id b11so18406393pld.12 for ; Wed, 01 Dec 2021 10:55:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=j5ekZ4KztehWagyD6KmPICwo6+51UABy5q3ntCm5U44=; b=WXtvRgS+r8eXu9DPhGsVhIyG0lO8Pgj8Gwt1GtqciLTbzLpnx3uWHXI0zKfyNZo7/z UmUdKOPdqg0EwjK0Sg/i9TG2dj3Ib5z34fKfHeYHOj1NZ/b2hYhhMGdxm2xfBkpKWIwN 57oeb25nqCtLa3woPHikBIl9EpfaizYVrwoxuULQAkClNPW1s7Av8frpOB1CL+uroyqz RuwDTl7DUZMSSsg1xXGRX/GXuwVQdSI4QoLb1QhkquYjDnIgiwzZi39tK3zs4XF4L+LL vG+nG3q0bZcT/OMUwsw0C4hyLvnE8rV/JXZKQXamkfzF0/RzH3qmUV1wamOtKK0gkazy vAVA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=j5ekZ4KztehWagyD6KmPICwo6+51UABy5q3ntCm5U44=; b=CVUd8P+sTAaxwtbOT0coHdM0DAHGjw5lKISHI29Khd7hbJDutirztphotvrFU8hoBR +T8OjrqpFSk/Olq6UA8vZP5WefzLOjvtzqdJqdNJTYod5gD3BrRu651I5YsSmi4Y9WFD 4cJNPLoZO4J7WJfoCdeVCIAHfA7UGULl+N3RJIc88lI5Si+lPYgOX6OmEE0g5FqdzoUd Tu8ahHeIsvxBsf6LNCknWe/iZxmPFmNnwIDcj98zIJnEOA9gioeqqaS2m4LjYYgHiEoW w81LAdHwXA7xZxrdoHuZcSxkRzArM582X5PP5gQmkytfe2s3syzen10yoIUVxhZokg90 G2bQ== X-Gm-Message-State: AOAM532Jj9V5GkQNNkZtk1HYyonaY9VvS/MZPAfgfRoa0na8x7dLe8IJ d6GfyGvxazxvziub8nnKcajyvVZXlMc= X-Google-Smtp-Source: ABdhPJzAEdBcWJC4hBbYeLVrgTiSQMELRGEMvMPs5jLAXJ+b1dkzbXdyMVepGV9bINGNEdU0GP/xNQ== X-Received: by 2002:a17:90a:4414:: with SMTP id s20mr66184pjg.132.1638384910786; Wed, 01 Dec 2021 10:55:10 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:10 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 04/15] Bluetooth: HCI: Use skb_pull_data to parse Number of Complete Packets event Date: Wed, 1 Dec 2021 10:54:55 -0800 Message-Id: <20211201185506.1421186-5-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the Number of Complete Packets events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 2 +- net/bluetooth/hci_event.c | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ba89b078ceb5..3f57fd677b67 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2139,7 +2139,7 @@ struct hci_comp_pkts_info { } __packed; struct hci_ev_num_comp_pkts { - __u8 num_hndl; + __u8 num; struct hci_comp_pkts_info handles[]; } __packed; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 09d7d997c4b1..b27a4ad647ca 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4465,23 +4465,25 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_num_comp_pkts *ev = (void *) skb->data; + struct hci_ev_num_comp_pkts *ev; int i; - if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { - bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, sizeof(*ev)); + if (!ev) return; - } - if (skb->len < sizeof(*ev) || - skb->len < struct_size(ev, handles, ev->num_hndl)) { - BT_DBG("%s bad parameters", hdev->name); + if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, + flex_array_size(ev, handles, ev->num))) + return; + + if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) { + bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); return; } - BT_DBG("%s num_hndl %d", hdev->name, ev->num_hndl); + BT_DBG("%s num %d", hdev->name, ev->num); - for (i = 0; i < ev->num_hndl; i++) { + for (i = 0; i < ev->num; i++) { struct hci_comp_pkts_info *info = &ev->handles[i]; struct hci_conn *conn; __u16 handle, count; From patchwork Wed Dec 1 18:54:56 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519400 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EB537C433F5 for ; Wed, 1 Dec 2021 18:55:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352437AbhLAS6m (ORCPT ); Wed, 1 Dec 2021 13:58:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351455AbhLAS6e (ORCPT ); Wed, 1 Dec 2021 13:58:34 -0500 Received: from mail-pl1-x62a.google.com (mail-pl1-x62a.google.com [IPv6:2607:f8b0:4864:20::62a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 75634C061574 for ; Wed, 1 Dec 2021 10:55:12 -0800 (PST) Received: by mail-pl1-x62a.google.com with SMTP id u11so18436889plf.3 for ; Wed, 01 Dec 2021 10:55:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=5vQn+Qe0kMnjkKX/1BwjLPY1a1irRV2Zdg3iTMrOkRw=; b=Uw0do0AEK3vwIK8hy/S7z6/I7RZaCfMut7GlLpZQlCuPRVy90PAxDf4XSYxvW84uXg BPwpJO6ccUyuDpE7/sed+EOVO/3PN8mVeSdUDAzJpN7siW/FmhShJ4ULPSsK+ETIOjYM KPmcHQpLJCWV0mbABWxV+E42xQcfaI81oKHW0NzKWyGP+B23toHNM0HKEfobe4dzKliv 8Dp3n+Mcfd/wlONshldpiLPCddEp+XeUUlYB7pqZldg0iSESoY2WgDEuASb3so0OXS4C KNrSE9qMUSGdUSIKaUP7PjZdQX4mbH8ORG6aQJHaCO+Vd8Z1DLBD1v6hd8nz0kkwTLng yi7w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=5vQn+Qe0kMnjkKX/1BwjLPY1a1irRV2Zdg3iTMrOkRw=; b=whn3cTvt1F1GyUjcHaN2JKFtCOS6l4+pWmegWPTbpr00go2g8nDHulBgbWWorzg03+ 1LlDJ2gLzPBPYlO1w/0DCHxGfd7muRX3X5Xu1if6ZKJHbgEeoQxnnq8ENGjPe3ozDZF5 hfV0FITqybm8vDQ5EqcXT3WhCVKJzl7Kr0aqE7nxwnOi3XItZRRiGpqHemQA+Bx+W0kW VkZqecpolZQSM/AClWU8oxZT5YHgycEZJ+3RG8bcXr7Q7FTcskXoUJ7qEVOzFzUWpzVE mZy0dD/PEF9MwiutwGAhAQapgDVTvfUn1dsSoPhfHGd/09PtLuy8lF4M0zL+85x+9z+V 6N/Q== X-Gm-Message-State: AOAM532kv2VL4qCl/12S5pV2s0q4Buqf1UqpxMVIin5iaOjEBGhIBCNe PI77xpmbznAJiyttae9MQDfm7Tgq8YY= X-Google-Smtp-Source: ABdhPJyxOMguDL+6r4jwTDwxTdzTNNvgDsT0pbi+ZLgFWXsQu08EerkaRu1q1Osc/EY57wylZ+h0Tw== X-Received: by 2002:a17:90b:1e0c:: with SMTP id pg12mr11304pjb.135.1638384911820; Wed, 01 Dec 2021 10:55:11 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.10 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:11 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 05/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result event Date: Wed, 1 Dec 2021 10:54:56 -0800 Message-Id: <20211201185506.1421186-6-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the Inquiry Result events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 5 +++++ net/bluetooth/hci_event.c | 19 ++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3f57fd677b67..55466bfb972a 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2028,6 +2028,11 @@ struct inquiry_info { __le16 clock_offset; } __packed; +struct hci_ev_inquiry_result { + __u8 num; + struct inquiry_info info[]; +}; + #define HCI_EV_CONN_COMPLETE 0x03 struct hci_ev_conn_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b27a4ad647ca..0bf062f6f262 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3180,13 +3180,21 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) { + struct hci_ev_inquiry_result *ev; struct inquiry_data data; - struct inquiry_info *info = (void *) (skb->data + 1); - int num_rsp = *((__u8 *) skb->data); + int i; - BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, sizeof(*ev)); + if (!ev) + return; - if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) + if (!hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, + flex_array_size(ev, info, ev->num))) + return; + + BT_DBG("%s num %d", hdev->name, ev->num); + + if (!ev->num) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) @@ -3194,7 +3202,8 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - for (; num_rsp; num_rsp--, info++) { + for (i = 0; i < ev->num; i++) { + struct inquiry_info *info = &ev->info[i]; u32 flags; bacpy(&data.bdaddr, &info->bdaddr); From patchwork Wed Dec 1 18:54:57 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519397 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9B9BFC4332F for ; Wed, 1 Dec 2021 18:55:28 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352045AbhLAS6s (ORCPT ); Wed, 1 Dec 2021 13:58:48 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51502 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351880AbhLAS6g (ORCPT ); Wed, 1 Dec 2021 13:58:36 -0500 Received: from mail-pg1-x52a.google.com (mail-pg1-x52a.google.com [IPv6:2607:f8b0:4864:20::52a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 56E13C061759 for ; Wed, 1 Dec 2021 10:55:13 -0800 (PST) Received: by mail-pg1-x52a.google.com with SMTP id s37so14889089pga.9 for ; Wed, 01 Dec 2021 10:55:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=ab89kELLOw7PFgiC45BjFwbpcUH6t8PHkBmKKzmYafY=; b=Zi7VU5T5oNR2v4+MXhUUm3JuD3PhpdmY/uG3ZIDDPpTItjI5pGCxy6dn3ldWPWiYys 5nbK485lov+S7ffknTqAKlgAc7apIbOmSrbORXIA23IR2eAihSBfkatVncpH1qlUOtct vp0zZCzDVSLEajr4AKc7/T4gMw4wuDdcyaQsviutvaNJdWxB0hqHdFgfTUohPNbIk08N w8Lv0+OlUHj2Dorlvuo2b9r3rT2tgPMhLL5MqUbo8WXoZcaIGWsgLO0URlEoQxa5Ood5 cnLM3G23r7MIOoJX7MU17oKkmqFDczwBoKRcPr4Bottr4iFd/8hi6oPrDIeF/YGpKrPD 41BA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ab89kELLOw7PFgiC45BjFwbpcUH6t8PHkBmKKzmYafY=; b=rUEWB2wnrV57cLCvK6s9oyLUlnKg+jwGCOk7lZKZ//oNNTN7QM6SXvs0gGjqp/rUES xUxIiC8FkOO0+ZOILJ+IgEBE58HdRuiimiK06bYIAHQrbFTusCb+ENn8uvPs+XObk40L WbDxc6H8UQ7uu7nD190U/7zimtpzSVbU+Bhq1HQCnx6RwybacG4FVLoUZ2gvTLHifQBc 6CWSA+aYXvO2iGMchSwCIQBIuEBnUQ0DEQTebYCVXTEFAiSTbsufdViZ0nX3FJYMbH0/ WH4kXPPleTmYSDvEqbQOw9aKU7GZbrw9a9Dlhgebvjkk8fEgNZo0V+DrcqlYKS2J2Y14 Z0aQ== X-Gm-Message-State: AOAM5326Ujssow3kq3z0LAaT7vmWi6FHrU4Hctcd4MB35HZYksxvWnKW DW1lglltHRXnbtjxXAmE1ZiSba/Gq8U= X-Google-Smtp-Source: ABdhPJxEIL8VXgpV85R4T6xdY8yGP5ZCQp7UIcb5VtQlNXFm+ekzBZF7FheAZCbuiY0dx3tXNwRYYA== X-Received: by 2002:a63:80c8:: with SMTP id j191mr6181562pgd.143.1638384912467; Wed, 01 Dec 2021 10:55:12 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.11 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:12 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 06/15] Bluetooth: HCI: Use skb_pull_data to parse Inquiry Result with RSSI event Date: Wed, 1 Dec 2021 10:54:57 -0800 Message-Id: <20211201185506.1421186-7-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the Inquiry Result with RSSI events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 12 +++++++++-- net/bluetooth/hci_event.c | 40 +++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 55466bfb972a..d25afd92a46e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2194,7 +2194,7 @@ struct hci_ev_pscan_rep_mode { } __packed; #define HCI_EV_INQUIRY_RESULT_WITH_RSSI 0x22 -struct inquiry_info_with_rssi { +struct inquiry_info_rssi { bdaddr_t bdaddr; __u8 pscan_rep_mode; __u8 pscan_period_mode; @@ -2202,7 +2202,7 @@ struct inquiry_info_with_rssi { __le16 clock_offset; __s8 rssi; } __packed; -struct inquiry_info_with_rssi_and_pscan_mode { +struct inquiry_info_rssi_pscan { bdaddr_t bdaddr; __u8 pscan_rep_mode; __u8 pscan_period_mode; @@ -2211,6 +2211,14 @@ struct inquiry_info_with_rssi_and_pscan_mode { __le16 clock_offset; __s8 rssi; } __packed; +struct hci_ev_inquiry_result_rssi { + __u8 num; + struct inquiry_info_rssi info[]; +} __packed; +struct hci_ev_inquiry_result_rssi_pscan { + __u8 num; + struct inquiry_info_rssi_pscan info[]; +} __packed; #define HCI_EV_REMOTE_EXT_FEATURES 0x23 struct hci_ev_remote_ext_features { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0bf062f6f262..6560dca8c5ce 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4921,12 +4921,21 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, struct sk_buff *skb) { + union { + struct hci_ev_inquiry_result_rssi *res1; + struct hci_ev_inquiry_result_rssi_pscan *res2; + } *ev; struct inquiry_data data; - int num_rsp = *((__u8 *) skb->data); + int i; - BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT_WITH_RSSI, + sizeof(*ev)); + if (!ev) + return; + + BT_DBG("%s num_rsp %d", hdev->name, ev->res1->num); - if (!num_rsp) + if (!ev->res1->num) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) @@ -4934,16 +4943,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, hci_dev_lock(hdev); - if ((skb->len - 1) / num_rsp != sizeof(struct inquiry_info_with_rssi)) { - struct inquiry_info_with_rssi_and_pscan_mode *info; - info = (void *) (skb->data + 1); + if (skb->len == flex_array_size(ev, res2->info, ev->res2->num)) { + struct inquiry_info_rssi_pscan *info; - if (skb->len < num_rsp * sizeof(*info) + 1) - goto unlock; - - for (; num_rsp; num_rsp--, info++) { + for (i = 0; i < ev->res2->num; i++) { u32 flags; + info = &ev->res2->info[i]; bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -4959,15 +4965,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, info->dev_class, info->rssi, flags, NULL, 0, NULL, 0); } - } else { - struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); + } else if (skb->len == flex_array_size(ev, res1->info, ev->res1->num)) { + struct inquiry_info_rssi *info; - if (skb->len < num_rsp * sizeof(*info) + 1) - goto unlock; - - for (; num_rsp; num_rsp--, info++) { + for (i = 0; i < ev->res1->num; i++) { u32 flags; + info = &ev->res1->info[i]; bacpy(&data.bdaddr, &info->bdaddr); data.pscan_rep_mode = info->pscan_rep_mode; data.pscan_period_mode = info->pscan_period_mode; @@ -4983,9 +4987,11 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, info->dev_class, info->rssi, flags, NULL, 0, NULL, 0); } + } else { + bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x", + HCI_EV_INQUIRY_RESULT_WITH_RSSI); } -unlock: hci_dev_unlock(hdev); } From patchwork Wed Dec 1 18:54:58 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520582 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AEF7BC433EF for ; Wed, 1 Dec 2021 18:55:29 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352569AbhLAS6t (ORCPT ); Wed, 1 Dec 2021 13:58:49 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51504 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1351888AbhLAS6g (ORCPT ); Wed, 1 Dec 2021 13:58:36 -0500 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C3A5BC06175A for ; Wed, 1 Dec 2021 10:55:13 -0800 (PST) Received: by mail-pl1-x62d.google.com with SMTP id b13so18449549plg.2 for ; Wed, 01 Dec 2021 10:55:13 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=TR5msw3HgDvkV0NY0xMd3R5/Y+9WHFDKSZCOK0wsevM=; b=JerLeTZXuxv/7+E80P3VR46eq+LvwHUM9C+Q47tofHRe/Efp800v0j4qdoLIkP6M0p MvGilz+0MSreGpEIZdMe49i7lsOv5pOzI8kKkZzSNyPfQVURIBDNyARjlrPT4/jWdBMR /kwpXOUpzx2R7TCRKbYJmcCunHUWkbsZpwT7uClRsDzKcKpC011C5EJDnCm6Q1sY1gYA Lmz9izTJUDYwTl6jqklSpN8sl+9zTubAenqrIafM9Fr79b/FnVgKdZP7nZCQXqyujAWw 5n1vfvJBg4lwN/RbeDAZ0sV5/bH0wGihvkudZ7J7zXkZaLsaVmrhk7K/1SzlLhGrZ4Br Tw2g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=TR5msw3HgDvkV0NY0xMd3R5/Y+9WHFDKSZCOK0wsevM=; b=LOZqMcklm8rmhyO0JunOumk+8ZXOhM0gRZjxSjbFedQeQpV7hpYtuCxXHJp6yzIvCo aTwhcQV+LgzzFDkiadz4Qvb25yfPoS+zz8s6hYZph8m/zclzDboSNhJ3DqKGAjC9eQGN vj7eupLJeE6K02IiN0EMetGaf1Tc6vKHu1Ts57tW8APUJiHUI/JUifeuk78p/B4MGBSQ ZnDs3UZTNtS1LMwoEFPtu0idk7rAJt1gjtgpXxHnjeyONTn5EwAmw2cDSkhabqCwpaUu /ttZtBSi9rFfqBOkuhNSPPHlC7avm/j8on/R/owuM6mjZOfmABn+42wv92+k1+h3ThbV LbfA== X-Gm-Message-State: AOAM533btTwu4XQbzxgTIkIsNXyWuxFf4ufPEceYGJWMG6NWNLbXbJIc mU5K5g3V7zSyJ1g2OoVWQnK1co2mJq8= X-Google-Smtp-Source: ABdhPJwRNXvmwGF7PoA2qzLOvcDZPbWsgoi17+8Oy2NvoY+/w1nq3FC5XNem3pBl/FGjIYiCZ5vWCw== X-Received: by 2002:a17:90b:4f86:: with SMTP id qe6mr43900pjb.224.1638384913064; Wed, 01 Dec 2021 10:55:13 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.12 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:12 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 07/15] Bluetooth: HCI: Use skb_pull_data to parse Extended Inquiry Result event Date: Wed, 1 Dec 2021 10:54:58 -0800 Message-Id: <20211201185506.1421186-8-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the Extended Inquiry Result events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 5 +++++ net/bluetooth/hci_event.c | 20 +++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index d25afd92a46e..9e721e6efef3 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2273,6 +2273,11 @@ struct extended_inquiry_info { __u8 data[240]; } __packed; +struct hci_ev_ext_inquiry_result { + __u8 num; + struct extended_inquiry_info info[]; +} __packed; + #define HCI_EV_KEY_REFRESH_COMPLETE 0x30 struct hci_ev_key_refresh_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 6560dca8c5ce..89c263c1883f 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -5186,14 +5186,23 @@ static inline size_t eir_get_length(u8 *eir, size_t eir_len) static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) { + struct hci_ev_ext_inquiry_result *ev; struct inquiry_data data; - struct extended_inquiry_info *info = (void *) (skb->data + 1); - int num_rsp = *((__u8 *) skb->data); size_t eir_len; + int i; - BT_DBG("%s num_rsp %d", hdev->name, num_rsp); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT, + sizeof(*ev)); + if (!ev) + return; - if (!num_rsp || skb->len < num_rsp * sizeof(*info) + 1) + if (!hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT, + flex_array_size(ev, info, ev->num))) + return; + + BT_DBG("%s num %d", hdev->name, ev->num); + + if (!ev->num) return; if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) @@ -5201,7 +5210,8 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, hci_dev_lock(hdev); - for (; num_rsp; num_rsp--, info++) { + for (i = 0; i < ev->num; i++) { + struct extended_inquiry_info *info = &ev->info[i]; u32 flags; bool name_known; From patchwork Wed Dec 1 18:54:59 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520585 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4B767C433FE for ; Wed, 1 Dec 2021 18:55:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352466AbhLAS6m (ORCPT ); Wed, 1 Dec 2021 13:58:42 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51510 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352034AbhLAS6g (ORCPT ); Wed, 1 Dec 2021 13:58:36 -0500 Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9A0EBC06175B for ; Wed, 1 Dec 2021 10:55:14 -0800 (PST) Received: by mail-pf1-x432.google.com with SMTP id n85so25446045pfd.10 for ; Wed, 01 Dec 2021 10:55:14 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=8WbgfQy9Pg3s7B9vf/AWyt49WCqLJiGtD+eFrFA9TAc=; b=fdyGH01OdCfEk2JxmTMViVx+H6Xnnw4hOaBkyWq+MZ5DYMKTRDF2sf0cKCzU8YqGeq KFLCH2AT/9i7SPN6WOsCJmddYkjJzogwa94KkgIO0SNLB035v81MqZrHRUM1uYvuv2Uv d5x3DpjxS9U97Z404cvr2s6BOx0fIk0bdZ902cearl/306DxhRsvRmY3i4MOVVSGvkvt r1qSOTsWmVaJjT5WYCndd7zlDarL2HafhQRglyptBj9qKy89RgamjebBYFbjDSXB16Vl abSdqvwKVpwZvvWCJv78tgWBzD2OmCkmaLetrfAMMZHM02xEG4+KENgyiy7SWdvumkny syUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=8WbgfQy9Pg3s7B9vf/AWyt49WCqLJiGtD+eFrFA9TAc=; b=IjoMsqfruGjUelrvTzDMEQVLbBUIoBmR7NRbpQO3Zzl+2nVGczEfcHIQHV4nxxU/mQ 6iHjxxhnQBa+TWjBiUpxct+zbkLaSCd0VPGCzNKYjRdIUcQAhTFTMpw9t455BNebzpMR VzelPz0SQ1ChP1D7sO9qAbkpn7Rj39B3aSCxgdl5nB2AVPZ/xWFAv6zwPVyEFAeIIq/E 5P08ztyzcYB1g/bSIoca9WUAKGsjvm8aJ+/OmsXhlxN9zi/2QCZdkXxy42RWMsSMMcZr +BJE7cQ+4GVClKYuwzFU2AkfUXvvtc9wpva2CgQGiMjN9eEfxIACeg7cqB7ydAFORfXk wIQg== X-Gm-Message-State: AOAM5320vAljfkLiKYLABdSi1T+lSEnjGItlIJHETdSKjgQn4YRWkrDm TiwYOUtLQ5QlCgifaXD27uM8RN+dJNM= X-Google-Smtp-Source: ABdhPJweYFze1EOBKepvEby/CuhtuGEaJMa2dS80kO+0ydhFeAeyRz5B/evl3dtZ4Ff2A86ZKemRjQ== X-Received: by 2002:a05:6a00:23cc:b0:49f:bfaa:e2f6 with SMTP id g12-20020a056a0023cc00b0049fbfaae2f6mr7915102pfc.35.1638384913811; Wed, 01 Dec 2021 10:55:13 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.13 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:13 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 08/15] Bluetooth: HCI: Use skb_pull_data to parse LE Metaevents Date: Wed, 1 Dec 2021 10:54:59 -0800 Message-Id: <20211201185506.1421186-9-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the LE Metaevents received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 75 +++++++++++++++++++++++++++++++++------ 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 89c263c1883f..d30e77f66376 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -69,6 +69,18 @@ static void *hci_cc_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, return data; } +static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, + u8 ev, size_t len) +{ + void *data; + + data = skb_pull_data(skb, len); + if (!data) + bt_dev_err(hdev, "Malformed LE Event: 0x%2.2x", ev); + + return data; +} + static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, u8 *new_status) { @@ -6119,7 +6131,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_conn_complete *ev = (void *) skb->data; + struct hci_ev_le_conn_complete *ev; + + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_COMPLETE, + sizeof(*ev)); + if (!ev) + return; BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); @@ -6133,7 +6150,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_enh_conn_complete *ev = (void *) skb->data; + struct hci_ev_le_enh_conn_complete *ev; + + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ENHANCED_CONN_COMPLETE, + sizeof(*ev)); + if (!ev) + return; BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); @@ -6146,10 +6168,15 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_evt_le_ext_adv_set_term *ev = (void *) skb->data; + struct hci_evt_le_ext_adv_set_term *ev; struct hci_conn *conn; struct adv_info *adv, *n; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_SET_TERM, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); adv = hci_find_adv_instance(hdev, ev->handle); @@ -6211,9 +6238,14 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; + struct hci_ev_le_conn_update_complete *ev; struct hci_conn *conn; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_UPDATE_COMPLETE, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); if (ev->status) @@ -6636,9 +6668,14 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_remote_feat_complete *ev = (void *)skb->data; + struct hci_ev_le_remote_feat_complete *ev; struct hci_conn *conn; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, + sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); hci_dev_lock(hdev); @@ -6677,12 +6714,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_ltk_req *ev = (void *) skb->data; + struct hci_ev_le_ltk_req *ev; struct hci_cp_le_ltk_reply cp; struct hci_cp_le_ltk_neg_reply neg; struct hci_conn *conn; struct smp_ltk *ltk; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_LTK_REQ, sizeof(*ev)); + if (!ev) + return; + BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); hci_dev_lock(hdev); @@ -6754,11 +6795,16 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; + struct hci_ev_le_remote_conn_param_req *ev; struct hci_cp_le_conn_param_req_reply cp; struct hci_conn *hcon; u16 handle, min, max, latency, timeout; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_REMOTE_CONN_PARAM_REQ, + sizeof(*ev)); + if (!ev) + return; + handle = le16_to_cpu(ev->handle); min = le16_to_cpu(ev->interval_min); max = le16_to_cpu(ev->interval_max); @@ -6831,9 +6877,14 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_phy_update_complete *ev = (void *) skb->data; + struct hci_ev_le_phy_update_complete *ev; struct hci_conn *conn; + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PHY_UPDATE_COMPLETE, + sizeof(*ev)); + if (ev) + return; + BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); if (ev->status) @@ -6854,11 +6905,13 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_ev_le_meta *le_ev = (void *) skb->data; + struct hci_ev_le_meta *ev; - skb_pull(skb, sizeof(*le_ev)); + ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LE_META, sizeof(*ev)); + if (!ev) + return; - switch (le_ev->subevent) { + switch (ev->subevent) { case HCI_EV_LE_CONN_COMPLETE: hci_le_conn_complete_evt(hdev, skb); break; From patchwork Wed Dec 1 18:55:00 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520583 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6E70BC433EF for ; Wed, 1 Dec 2021 18:55:27 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352608AbhLAS6q (ORCPT ); Wed, 1 Dec 2021 13:58:46 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352045AbhLAS6g (ORCPT ); Wed, 1 Dec 2021 13:58:36 -0500 Received: from mail-pg1-x52b.google.com (mail-pg1-x52b.google.com [IPv6:2607:f8b0:4864:20::52b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 80A5CC061748 for ; Wed, 1 Dec 2021 10:55:15 -0800 (PST) Received: by mail-pg1-x52b.google.com with SMTP id l190so24576353pge.7 for ; Wed, 01 Dec 2021 10:55:15 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=rGmuzjNWCJwSMo2crUTDHRKMD3or9KnZlwBZfVFowyQ=; b=qxQg1mqEWqACKJ1P8uWqlJtOP5hLJnOxf4njPWxJiRKwiY2L9jgUFtcucJ6F8f1G5P RqIA6TEFOxknLL5GGuLU3NQFz95DCWLDC/1AbPz6C6PvSTblRySBhmcfyDENudA/ll6M GpWEH9HSJnIeZFlSzUwzpmr3/aL6CukbL459K+1SED0igdaH3XaHuqTcpvltnwfu7qS2 6qHkOTYFo2ECWGPpthn0grKXyUhcJyfdA+Q4/32cyRQsoKXWHOXPm/tfJsthPhvpHG3x FYndGOvvfzqMVudyuNCsJdLlrVgkx9to5Fy7jARz0waQC4nNP8T2bSYSrP+bRbZTzerY dv7g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rGmuzjNWCJwSMo2crUTDHRKMD3or9KnZlwBZfVFowyQ=; b=3ZBsJ0bQ4XUWpcQRRw7M1NaBep28x8nMsqvSl5ErIJCyCLo0GSoDMdi+/wQLnLLI0v Op0YiKWUpBDU8pu2B2kNzh8dpzGw1RL+JTxqw+gudQBy/8UJPF10m+OQVZTVSRM58EnW FFpri3D2WkmkIZAeHHMV27ZrvX0YPQaVHXrkRZBMOgBFmSPP5/vmjL4de419o3lzBRZK FWow7Emh4UeAkAPEnJmHGMRrDW/Rw4dr4e1DhVx1DwaY6C59ueZEufZmAkNlBGVb9ALL fZisoK+Oyrx45LHFoBO4QkP8PNTyv0jndU8tPtGDyDjKOYBuY4aldML2KRIGd4UMjkxe dLhQ== X-Gm-Message-State: AOAM533e3KotQKLxmL8bphn92F3GfxCeok0TrG6yzIlR+XQw7KWf5a+y DnFvMyVOouHUU6k17ddDAlTyowXURa8= X-Google-Smtp-Source: ABdhPJwETjkUVaoWU9JIUdOZHVXeCqzrfLGU2dS4AicC1FrtNR0h1d2Gh6UGxfrgGIIpG2az2ChPtQ== X-Received: by 2002:a05:6a00:807:b0:49f:9a8d:23b4 with SMTP id m7-20020a056a00080700b0049f9a8d23b4mr7758128pfk.71.1638384914620; Wed, 01 Dec 2021 10:55:14 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:14 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 09/15] Bluetooth: HCI: Use skb_pull_data to parse LE Advertising Report event Date: Wed, 1 Dec 2021 10:55:00 -0800 Message-Id: <20211201185506.1421186-10-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the LE Advertising Report events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 7 ++++++- net/bluetooth/hci_event.c | 39 +++++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 9e721e6efef3..c005b1ccdbc5 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2445,13 +2445,18 @@ struct hci_ev_le_conn_complete { #define HCI_EV_LE_ADVERTISING_REPORT 0x02 struct hci_ev_le_advertising_info { - __u8 evt_type; + __u8 type; __u8 bdaddr_type; bdaddr_t bdaddr; __u8 length; __u8 data[]; } __packed; +struct hci_ev_le_advertising_report { + __u8 num; + struct hci_ev_le_advertising_info info[]; +} __packed; + #define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03 struct hci_ev_le_conn_update_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index d30e77f66376..42ffd5df6d4b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6564,31 +6564,40 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) { - u8 num_reports = skb->data[0]; - void *ptr = &skb->data[1]; + struct hci_ev_le_advertising_report *ev; + + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT, + sizeof(*ev)); + if (!ev) + return; + + if (!ev->num) + return; hci_dev_lock(hdev); - while (num_reports--) { - struct hci_ev_le_advertising_info *ev = ptr; + while (ev->num--) { + struct hci_ev_le_advertising_info *info; s8 rssi; - if (ptr > (void *)skb_tail_pointer(skb) - sizeof(*ev)) { - bt_dev_err(hdev, "Malicious advertising data."); + info = hci_le_ev_skb_pull(hdev, skb, + HCI_EV_LE_ADVERTISING_REPORT, + sizeof(*info)); + if (!info) break; - } - if (ev->length <= HCI_MAX_AD_LENGTH && - ev->data + ev->length <= skb_tail_pointer(skb)) { - rssi = ev->data[ev->length]; - process_adv_report(hdev, ev->evt_type, &ev->bdaddr, - ev->bdaddr_type, NULL, 0, rssi, - ev->data, ev->length, false); + if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT, + info->length + 1)) + break; + + if (info->length <= HCI_MAX_AD_LENGTH) { + rssi = info->data[info->length]; + process_adv_report(hdev, info->type, &info->bdaddr, + info->bdaddr_type, NULL, 0, rssi, + info->data, info->length, false); } else { bt_dev_err(hdev, "Dropping invalid advertising data"); } - - ptr += sizeof(*ev) + ev->length + 1; } hci_dev_unlock(hdev); From patchwork Wed Dec 1 18:55:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520584 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 05F56C433EF for ; Wed, 1 Dec 2021 18:55:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352322AbhLAS6o (ORCPT ); Wed, 1 Dec 2021 13:58:44 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51484 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352051AbhLAS6i (ORCPT ); Wed, 1 Dec 2021 13:58:38 -0500 Received: from mail-pf1-x432.google.com (mail-pf1-x432.google.com [IPv6:2607:f8b0:4864:20::432]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 335FDC06174A for ; Wed, 1 Dec 2021 10:55:16 -0800 (PST) Received: by mail-pf1-x432.google.com with SMTP id g18so25488751pfk.5 for ; Wed, 01 Dec 2021 10:55:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=rAgw96mWSTxvK0gyqEQQZc+al2NNhHRrOI3U1Yiwed8=; b=ce8pkQgzsdEO9/vWEXlhv9eHi5h660Z8rE6zK3sW75qYO67naSNLC+xlyW5bQVmBwS 2W/8qFUjI8MAQcUzwDtio2IkQOljOf0Q97cmcNFzowCx8QZ75dWXghJY5G0U9YgE40JH bfKagm+K9HoLNOArnKwgU9bP48k1x4lfVO1QqCD9wO+8CuIzmEcFkdOw+uOZRsBmndwW 5Vh+HJU4dgxdtlz9ZZDRo/BClanzh/RLlTZegqzqgReh2e9tTmTtYxkk95xmcktpPbTI L9UB/9UmwwC3xIPGQfZgYFyNwc8VkwCXne7ukbfL8ItIA7oqNcHsaXI+QHbmgcTCRkRy +D4A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=rAgw96mWSTxvK0gyqEQQZc+al2NNhHRrOI3U1Yiwed8=; b=xp4TSxs2aQNpSQf39v378lmwno8tD3tAIkIkV02ZxlUweXJgfgWmAkd29uGO3HCfEB ZfVSBVcHSIuh50lvswE0uHvlV72xe250CYUUHMcIyMOEVk9vsp9QSlf4cud7nZ7xEZ3t SSKJBgQF2mjryqzqpZ4vzkhN1yZgTMzo5tyEN9Yjv8eqU5R71t0B97a4YciSg+MxwQko S4++wqYmTBCaGGOeTmS/Q0TeAE2Ug271Uawzr0PP/c7cFPEd13l9krCUWgPgG9pzvhL1 3ceQnR2e5L4rkiZf5i2yA7VnXAto0l9pV2aXVVbjoCyPTmRe4VOE1FocaRiF1Gtk36Ba hPDw== X-Gm-Message-State: AOAM531/on8rgpCUVSxLGFrKwofaj1g0ezRTziAXbiybEqRkRieiHMsu mI3E+0D+LOtTJ/Edzetq4AgLLpke4kg= X-Google-Smtp-Source: ABdhPJwgaJH68cBJLg/SUfPZXv1mQ2ajsQzyATk94Ztr/ajQRf4OgstEMfKYUogoA3evaxldECKMAA== X-Received: by 2002:a05:6a00:986:b0:4a2:c1fa:8899 with SMTP id u6-20020a056a00098600b004a2c1fa8899mr8127115pfg.61.1638384915506; Wed, 01 Dec 2021 10:55:15 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.14 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:15 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 10/15] Bluetooth: HCI: Use skb_pull_data to parse LE Ext Advertising Report event Date: Wed, 1 Dec 2021 10:55:01 -0800 Message-Id: <20211201185506.1421186-11-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the LE Extended Advertising Report events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 17 +++++++++++------ net/bluetooth/hci_event.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c005b1ccdbc5..d3f2da9b2ac2 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2517,8 +2517,8 @@ struct hci_ev_le_phy_update_complete { } __packed; #define HCI_EV_LE_EXT_ADV_REPORT 0x0d -struct hci_ev_le_ext_adv_report { - __le16 evt_type; +struct hci_ev_le_ext_adv_info { + __le16 type; __u8 bdaddr_type; bdaddr_t bdaddr; __u8 primary_phy; @@ -2526,11 +2526,16 @@ struct hci_ev_le_ext_adv_report { __u8 sid; __u8 tx_power; __s8 rssi; - __le16 interval; - __u8 direct_addr_type; + __le16 interval; + __u8 direct_addr_type; bdaddr_t direct_addr; - __u8 length; - __u8 data[]; + __u8 length; + __u8 data[]; +} __packed; + +struct hci_ev_le_ext_adv_report { + __u8 num; + struct hci_ev_le_ext_adv_info info[]; } __packed; #define HCI_EV_LE_ENHANCED_CONN_COMPLETE 0x0a diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 42ffd5df6d4b..23cfcb1c0ca3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6649,26 +6649,40 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type) static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) { - u8 num_reports = skb->data[0]; - void *ptr = &skb->data[1]; + struct hci_ev_le_ext_adv_report *ev; + + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, + sizeof(*ev)); + if (!ev) + return; + + if (!ev->num) + return; hci_dev_lock(hdev); - while (num_reports--) { - struct hci_ev_le_ext_adv_report *ev = ptr; + while (ev->num--) { + struct hci_ev_le_ext_adv_info *info; u8 legacy_evt_type; u16 evt_type; - evt_type = __le16_to_cpu(ev->evt_type); + info = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, + sizeof(*info)); + if (!info) + break; + + if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, + info->length)) + break; + + evt_type = __le16_to_cpu(info->type); legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type); if (legacy_evt_type != LE_ADV_INVALID) { - process_adv_report(hdev, legacy_evt_type, &ev->bdaddr, - ev->bdaddr_type, NULL, 0, ev->rssi, - ev->data, ev->length, + process_adv_report(hdev, legacy_evt_type, &info->bdaddr, + info->bdaddr_type, NULL, 0, + info->rssi, info->data, info->length, !(evt_type & LE_EXT_ADV_LEGACY_PDU)); } - - ptr += sizeof(*ev) + ev->length; } hci_dev_unlock(hdev); @@ -7019,7 +7033,7 @@ static void hci_store_wake_reason(struct hci_dev *hdev, u8 event, { struct hci_ev_le_advertising_info *adv; struct hci_ev_le_direct_adv_info *direct_adv; - struct hci_ev_le_ext_adv_report *ext_adv; + struct hci_ev_le_ext_adv_info *ext_adv; const struct hci_ev_conn_complete *conn_complete = (void *)skb->data; const struct hci_ev_conn_request *conn_request = (void *)skb->data; From patchwork Wed Dec 1 18:55:02 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519398 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1EB95C433F5 for ; Wed, 1 Dec 2021 18:55:26 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352034AbhLAS6p (ORCPT ); Wed, 1 Dec 2021 13:58:45 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51522 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352096AbhLAS6i (ORCPT ); Wed, 1 Dec 2021 13:58:38 -0500 Received: from mail-pg1-x533.google.com (mail-pg1-x533.google.com [IPv6:2607:f8b0:4864:20::533]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 00E54C06175D for ; Wed, 1 Dec 2021 10:55:17 -0800 (PST) Received: by mail-pg1-x533.google.com with SMTP id s37so14889240pga.9 for ; Wed, 01 Dec 2021 10:55:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=K0Q/AjPg4LwkcVHvTd078tsJRcQ1xeg7l6PZYQuqunw=; b=GulY9miN5zHaBuPhapbniYVH/rgRq4G6ZUHRB70Z+M/tlMcX1cj9VH6NPRZQFjrIB2 lxMkMtmjUiwMRQYaz+9yeep5ZFZcF15W9p7o0mbUeGtdiTH/oRHDZiVN9OexchIUu6Cp Qu0wSvpJhVBS2nc6+5NMbzO6XVj/WsSAtm7BLxWn1IrZJ39uPSMQZg5hu7n9sR8cMh0r d09k7KXuB+ZwcS4Oi2IKJqwAeHkXz6z8pYYmYS2TPL6RYKAzBKvwe8gh74uuwtokpgLB CSjH9szwt1HTgMxsAaK/lsFPvCT9LlKgHvFoobC7MNDoWzb7So3DTcKSvXfAdwmrcHqW Paag== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=K0Q/AjPg4LwkcVHvTd078tsJRcQ1xeg7l6PZYQuqunw=; b=JjRvgL+iyxtKcsASSfSXo3HkGtIT5aHff34sUW82KreeX8+zS03XFyflNQPMsCTlGG b1tjtr0bhvl6Q5pA0UXdmrMmB4z1mhPORQKGRSWu09kZR/7PfBo4iWv2dSOaCjYI9hG0 Fyw2p/LPHYFjrMcrpK5r6gN+qV0bCeZ/nB3NJV/uVtjAoQxIwFIsdBP5U94L989fJR6d k5HcAdvrt0CR+5rbjijUWyfMVdancbjap04ir/H/UTuH7Byk115Pu9omLbAY+5zygPb+ mOnTsB2AJiHTULhJGtjfK3nd7iZEZcNAEv+4mDs8LLAp/+I7VKGYKpLpA6DwXJ2pS3B4 5/Qg== X-Gm-Message-State: AOAM532L2L9wzq5KWUISJvxP39TpaCy+67ULC++5b5EQm/1Y1AaPbUbk NQuSbbVdwWWyW0bcGUB8cDiPISGw9zI= X-Google-Smtp-Source: ABdhPJwro6PPZ9aE51ZE/cf3RSU66p18Pxzi3RyinpQtlYVz2Hul65JS/oQLBbiuWDoiqo32oPy9ZA== X-Received: by 2002:a63:b703:: with SMTP id t3mr5988428pgf.393.1638384916196; Wed, 01 Dec 2021 10:55:16 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.15 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:15 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 11/15] Bluetooth: HCI: Use skb_pull_data to parse LE Direct Advertising Report event Date: Wed, 1 Dec 2021 10:55:02 -0800 Message-Id: <20211201185506.1421186-12-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This uses skb_pull_data to check the LE Direct Advertising Report events received have the minimum required length. Signed-off-by: Luiz Augusto von Dentz --- include/net/bluetooth/hci.h | 7 ++++++- net/bluetooth/hci_event.c | 26 +++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index d3f2da9b2ac2..4343f79bd02c 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -2500,7 +2500,7 @@ struct hci_ev_le_data_len_change { #define HCI_EV_LE_DIRECT_ADV_REPORT 0x0B struct hci_ev_le_direct_adv_info { - __u8 evt_type; + __u8 type; __u8 bdaddr_type; bdaddr_t bdaddr; __u8 direct_addr_type; @@ -2508,6 +2508,11 @@ struct hci_ev_le_direct_adv_info { __s8 rssi; } __packed; +struct hci_ev_le_direct_adv_report { + __u8 num; + struct hci_ev_le_direct_adv_info info[]; +} __packed; + #define HCI_EV_LE_PHY_UPDATE_COMPLETE 0x0c struct hci_ev_le_phy_update_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 23cfcb1c0ca3..8f21405997d1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -6881,19 +6881,31 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) { - u8 num_reports = skb->data[0]; - struct hci_ev_le_direct_adv_info *ev = (void *)&skb->data[1]; + struct hci_ev_le_direct_adv_report *ev; + int i; + + ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT, + sizeof(*ev)); + if (!ev) + return; - if (!num_reports || skb->len < num_reports * sizeof(*ev) + 1) + if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT, + flex_array_size(ev, info, ev->num))) + return; + + if (!ev->num) return; hci_dev_lock(hdev); - for (; num_reports; num_reports--, ev++) - process_adv_report(hdev, ev->evt_type, &ev->bdaddr, - ev->bdaddr_type, &ev->direct_addr, - ev->direct_addr_type, ev->rssi, NULL, 0, + for (i = 0; i < ev->num; i++) { + struct hci_ev_le_direct_adv_info *info = &ev->info[i]; + + process_adv_report(hdev, info->type, &info->bdaddr, + info->bdaddr_type, &info->direct_addr, + info->direct_addr_type, info->rssi, NULL, 0, false); + } hci_dev_unlock(hdev); } From patchwork Wed Dec 1 18:55:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519395 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0A63C433F5 for ; Wed, 1 Dec 2021 18:55:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1351880AbhLAS6u (ORCPT ); Wed, 1 Dec 2021 13:58:50 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51526 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244557AbhLAS6k (ORCPT ); Wed, 1 Dec 2021 13:58:40 -0500 Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id DDF78C061574 for ; Wed, 1 Dec 2021 10:55:18 -0800 (PST) Received: by mail-pl1-x62d.google.com with SMTP id u17so18410306plg.9 for ; Wed, 01 Dec 2021 10:55:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=26LcvWDxzgcVIam0GOCmEqBo/708ue2MR9y09iGWu6M=; b=Sj0PcyrUWKt3Dxdq4ZeT96m3Kejh8kgpy6kvpBezaoFQzc6Ur48nPyTd0gYsA58eKm QuVYvlZNkHOdVWp9AgO7wvf+GiRLfwqHkO6xCOlz5CJG2Lo44LgcUBcXUp7Z3vPkLTbM yKwIy7gsyuXfyMU6yYUvzgWKzjcDbzyetsWLrVmZBphF+z5Twu8mIvT8prx46+3rHWw+ m92zXDe6sQQS0p5Asg07hj/+xxRv+uv6B3LIFqC7kAPioZEYesTF1RBsWO3YrccEfgq6 gzs3mq1VRdqTUxoED+ZOahugsyln6bH+56wBq0qS+viFG8k8tlOI+9p59oLHy6VhjIxt paEA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=26LcvWDxzgcVIam0GOCmEqBo/708ue2MR9y09iGWu6M=; b=NzZnvaM7ow257mts0LmedJCPLRTIkc4WSj1XL3VXgstkbJ2nQxZXp+nUO2ISP3gz+x zLLgJxN9DkGyq2TVVQ3WRGd+JTqsF8WZBMrnO7dx8OB+t1Y9RpJw85axfh1OOiq5vLjx /5LJ67L9xaGtkX9FXsJkRg88Mvpikj/FLX+pmK9LdDz0T0F7P6MxLuAdMAFz6OJL3aE0 nnkx1Vyhh0Nm3rLWRySLysBdF15MTZrG59KsF2nJu9xDgrAXZ04PiBhCpUzYcM5XL8QI HElHa5vatgr2gYeqzNDX1dMK+tEksuI3R9bFuo0Q19pa+AeYs1uYsubNwnkt/Ei7r36e BN3w== X-Gm-Message-State: AOAM530FkemEa7VdttSpCvPFKs05RlIhJ3SUj9BAWEpS20tN+qDNq1Cr fAVE9zn0fFcskmvt5rnbYC23sJX7wbE= X-Google-Smtp-Source: ABdhPJwlnjRGSMxDQKkaK0Hk+VP9tV3sI1IV1ETjHQyg70HQrvAkkBWRbGRdxKp8H7fXr4pqrdYuwA== X-Received: by 2002:a17:90b:4f84:: with SMTP id qe4mr71890pjb.102.1638384917426; Wed, 01 Dec 2021 10:55:17 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.16 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:16 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 12/15] Bluetooth: hci_event: Use of a function table to handle HCI events Date: Wed, 1 Dec 2021 10:55:03 -0800 Message-Id: <20211201185506.1421186-13-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This change the use of switch statement to a function table which is easier to extend and can include min/max length of each HCI event. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 904 ++++++++++++++++---------------------- net/bluetooth/msft.c | 2 +- net/bluetooth/msft.h | 2 +- 3 files changed, 392 insertions(+), 516 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8f21405997d1..3953ec188ff6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3126,17 +3126,14 @@ static void hci_cs_switch_role(struct hci_dev *hdev, u8 status) hci_dev_unlock(hdev); } -static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_inquiry_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *ev; + struct hci_ev_status *ev = data; struct discovery_state *discov = &hdev->discovery; struct inquiry_entry *e; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_conn_check_pending(hdev); @@ -3190,21 +3187,18 @@ static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_inquiry_result_evt(struct hci_dev *hdev, void *edata, + struct sk_buff *skb) { - struct hci_ev_inquiry_result *ev; + struct hci_ev_inquiry_result *ev = edata; struct inquiry_data data; int i; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, sizeof(*ev)); - if (!ev) - return; - if (!hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT, flex_array_size(ev, info, ev->num))) return; - BT_DBG("%s num %d", hdev->name, ev->num); + bt_dev_dbg(hdev, "num %d", ev->num); if (!ev->num) return; @@ -3237,16 +3231,13 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_conn_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_conn_complete *ev; + struct hci_ev_conn_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3365,20 +3356,16 @@ static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); } -static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_conn_request_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_conn_request *ev; + struct hci_ev_conn_request *ev = data; int mask = hdev->link_mode; struct inquiry_entry *ie; struct hci_conn *conn; __u8 flags = 0; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CONN_REQUEST, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, - ev->link_type); + bt_dev_dbg(hdev, "bdaddr %pMR type 0x%x", &ev->bdaddr, ev->link_type); mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, &flags); @@ -3480,19 +3467,16 @@ static u8 hci_to_mgmt_reason(u8 err) } } -static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_disconn_complete *ev; + struct hci_ev_disconn_complete *ev = data; u8 reason; struct hci_conn_params *params; struct hci_conn *conn; bool mgmt_connected; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3568,16 +3552,13 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_auth_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_auth_complete *ev; + struct hci_ev_auth_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_AUTH_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3642,16 +3623,13 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_remote_name_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_remote_name *ev; + struct hci_ev_remote_name *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_NAME, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_conn_check_pending(hdev); @@ -3729,16 +3707,13 @@ static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status, hci_dev_unlock(hdev); } -static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_encrypt_change *ev; + struct hci_ev_encrypt_change *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ENCRYPT_CHANGE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3847,18 +3822,13 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_change_link_key_complete_evt(struct hci_dev *hdev, +static void hci_change_link_key_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_change_link_key_complete *ev; + struct hci_ev_change_link_key_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANGE_LINK_KEY_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3875,17 +3845,13 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_remote_features_evt(struct hci_dev *hdev, +static void hci_remote_features_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_remote_features *ev; + struct hci_ev_remote_features *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_FEATURES, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -3943,16 +3909,12 @@ static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd) } } -static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, - u16 *opcode, u8 *status, +static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb, u16 *opcode, u8 *status, hci_req_complete_t *req_complete, hci_req_complete_skb_t *req_complete_skb) { - struct hci_ev_cmd_complete *ev; - - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_COMPLETE, sizeof(*ev)); - if (!ev) - return; + struct hci_ev_cmd_complete *ev = data; *opcode = __le16_to_cpu(ev->opcode); *status = skb->data[0]; @@ -4330,16 +4292,12 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, queue_work(hdev->workqueue, &hdev->cmd_work); } -static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, - u16 *opcode, u8 *status, +static void hci_cmd_status_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb, u16 *opcode, u8 *status, hci_req_complete_t *req_complete, hci_req_complete_skb_t *req_complete_skb) { - struct hci_ev_cmd_status *ev; - - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CMD_STATUS, sizeof(*ev)); - if (!ev) - return; + struct hci_ev_cmd_status *ev = data; *opcode = __le16_to_cpu(ev->opcode); *status = ev->status; @@ -4445,29 +4403,25 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb, queue_work(hdev->workqueue, &hdev->cmd_work); } -static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_hardware_error_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_hardware_error *ev; + struct hci_ev_hardware_error *ev = data; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_HARDWARE_ERROR, sizeof(*ev)); - if (!ev) - return; + bt_dev_dbg(hdev, "code 0x%2.2x", ev->code); hdev->hw_error_code = ev->code; queue_work(hdev->req_workqueue, &hdev->error_reset); } -static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_role_change_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_role_change *ev; + struct hci_ev_role_change *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_ROLE_CHANGE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -4484,15 +4438,12 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_num_comp_pkts *ev; + struct hci_ev_num_comp_pkts *ev = data; int i; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, sizeof(*ev)); - if (!ev) - return; - if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS, flex_array_size(ev, handles, ev->num))) return; @@ -4502,7 +4453,7 @@ static void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) return; } - BT_DBG("%s num %d", hdev->name, ev->num); + bt_dev_dbg(hdev, "num %d", ev->num); for (i = 0; i < ev->num; i++) { struct hci_comp_pkts_info *info = &ev->handles[i]; @@ -4574,26 +4525,24 @@ static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev, return NULL; } -static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_num_comp_blocks *ev; + struct hci_ev_num_comp_blocks *ev = data; int i; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, sizeof(*ev)); - if (!ev) - return; - if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS, flex_array_size(ev, handles, ev->num_hndl))) return; if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) { - bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode); + bt_dev_err(hdev, "wrong event for mode %d", + hdev->flow_ctl_mode); return; } - BT_DBG("%s num_blocks %d num_hndl %d", hdev->name, ev->num_blocks, - ev->num_hndl); + bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks, + ev->num_hndl); for (i = 0; i < ev->num_hndl; i++) { struct hci_comp_blocks_info *info = &ev->handles[i]; @@ -4627,16 +4576,13 @@ static void hci_num_comp_blocks_evt(struct hci_dev *hdev, struct sk_buff *skb) queue_work(hdev->workqueue, &hdev->tx_work); } -static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_mode_change_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_mode_change *ev; + struct hci_ev_mode_change *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_MODE_CHANGE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -4659,16 +4605,13 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_pin_code_request_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_pin_code_req *ev; + struct hci_ev_pin_code_req *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PIN_CODE_REQ, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -4733,18 +4676,15 @@ static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len) } } -static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_link_key_request_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_link_key_req *ev; + struct hci_ev_link_key_req *ev = data; struct hci_cp_link_key_reply cp; struct hci_conn *conn; struct link_key *key; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_REQ, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); if (!hci_dev_test_flag(hdev, HCI_MGMT)) return; @@ -4753,13 +4693,11 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) key = hci_find_link_key(hdev, &ev->bdaddr); if (!key) { - BT_DBG("%s link key not found for %pMR", hdev->name, - &ev->bdaddr); + bt_dev_dbg(hdev, "link key not found for %pMR", &ev->bdaddr); goto not_found; } - BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, - &ev->bdaddr); + bt_dev_dbg(hdev, "found key type %u for %pMR", key->type, &ev->bdaddr); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (conn) { @@ -4768,15 +4706,14 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || key->type == HCI_LK_UNAUTH_COMBINATION_P256) && conn->auth_type != 0xff && (conn->auth_type & 0x01)) { - BT_DBG("%s ignoring unauthenticated key", hdev->name); + bt_dev_dbg(hdev, "ignoring unauthenticated key"); goto not_found; } if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 && (conn->pending_sec_level == BT_SECURITY_HIGH || conn->pending_sec_level == BT_SECURITY_FIPS)) { - BT_DBG("%s ignoring key unauthenticated for high security", - hdev->name); + bt_dev_dbg(hdev, "ignoring key unauthenticated for high security"); goto not_found; } @@ -4797,19 +4734,16 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_link_key_notify *ev; + struct hci_ev_link_key_notify *ev = data; struct hci_conn *conn; struct link_key *key; bool persistent; u8 pin_len = 0; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LINK_KEY_NOTIFY, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -4861,16 +4795,13 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_clock_offset_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_clock_offset *ev; + struct hci_ev_clock_offset *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CLOCK_OFFSET, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -4888,16 +4819,13 @@ static void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_pkt_type_change_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_pkt_type_change *ev; + struct hci_ev_pkt_type_change *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PKT_TYPE_CHANGE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -4908,16 +4836,13 @@ static void hci_pkt_type_change_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_pscan_rep_mode *ev; + struct hci_ev_pscan_rep_mode *ev = data; struct inquiry_entry *ie; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PSCAN_REP_MODE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -4930,22 +4855,17 @@ static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, +static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata, struct sk_buff *skb) { union { struct hci_ev_inquiry_result_rssi *res1; struct hci_ev_inquiry_result_rssi_pscan *res2; - } *ev; + } *ev = edata; struct inquiry_data data; int i; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT_WITH_RSSI, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s num_rsp %d", hdev->name, ev->res1->num); + bt_dev_dbg(hdev, "num_rsp %d", ev->res1->num); if (!ev->res1->num) return; @@ -5007,18 +4927,13 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_remote_ext_features_evt(struct hci_dev *hdev, +static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_remote_ext_features *ev; + struct hci_ev_remote_ext_features *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_EXT_FEATURES, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -5076,17 +4991,13 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_sync_conn_complete_evt(struct hci_dev *hdev, +static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_sync_conn_complete *ev; + struct hci_ev_sync_conn_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SYNC_CONN_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -5195,24 +5106,19 @@ static inline size_t eir_get_length(u8 *eir, size_t eir_len) return eir_len; } -static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, +static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, void *edata, struct sk_buff *skb) { - struct hci_ev_ext_inquiry_result *ev; + struct hci_ev_ext_inquiry_result *ev = edata; struct inquiry_data data; size_t eir_len; int i; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT, - sizeof(*ev)); - if (!ev) - return; - if (!hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT, flex_array_size(ev, info, ev->num))) return; - BT_DBG("%s num %d", hdev->name, ev->num); + bt_dev_dbg(hdev, "num %d", ev->num); if (!ev->num) return; @@ -5255,19 +5161,14 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_key_refresh_complete_evt(struct hci_dev *hdev, +static void hci_key_refresh_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_key_refresh_complete *ev; + struct hci_ev_key_refresh_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEY_REFRESH_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x handle 0x%4.4x", hdev->name, ev->status, - __le16_to_cpu(ev->handle)); + bt_dev_dbg(hdev, "status 0x%2.2x handle 0x%4.4x", ev->status, + __le16_to_cpu(ev->handle)); hci_dev_lock(hdev); @@ -5370,16 +5271,13 @@ static u8 bredr_oob_data_present(struct hci_conn *conn) return 0x01; } -static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_io_capa_request *ev; + struct hci_ev_io_capa_request *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REQUEST, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5443,16 +5341,13 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_io_capa_reply_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_io_capa_reply *ev; + struct hci_ev_io_capa_reply *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_IO_CAPA_REPLY, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5467,19 +5362,14 @@ static void hci_io_capa_reply_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_user_confirm_request_evt(struct hci_dev *hdev, +static void hci_user_confirm_request_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_user_confirm_req *ev; + struct hci_ev_user_confirm_req *ev = data; int loc_mitm, rem_mitm, confirm_hint = 0; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_CONFIRM_REQUEST, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5500,7 +5390,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, */ if (conn->pending_sec_level > BT_SECURITY_MEDIUM && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { - BT_DBG("Rejecting request: remote device can't provide MITM"); + bt_dev_dbg(hdev, "Rejecting request: remote device can't provide MITM"); hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, sizeof(ev->bdaddr), &ev->bdaddr); goto unlock; @@ -5519,7 +5409,7 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && (loc_mitm || rem_mitm)) { - BT_DBG("Confirming auto-accept as acceptor"); + bt_dev_dbg(hdev, "Confirming auto-accept as acceptor"); confirm_hint = 1; goto confirm; } @@ -5557,34 +5447,24 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_user_passkey_request_evt(struct hci_dev *hdev, +static void hci_user_passkey_request_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_user_passkey_req *ev; - - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_REQUEST, - sizeof(*ev)); - if (!ev) - return; + struct hci_ev_user_passkey_req *ev = data; - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); if (hci_dev_test_flag(hdev, HCI_MGMT)) mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); } -static void hci_user_passkey_notify_evt(struct hci_dev *hdev, +static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_user_passkey_notify *ev; + struct hci_ev_user_passkey_notify *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_USER_PASSKEY_NOTIFY, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (!conn) @@ -5599,16 +5479,13 @@ static void hci_user_passkey_notify_evt(struct hci_dev *hdev, conn->passkey_entered); } -static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_keypress_notify_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_keypress_notify *ev; + struct hci_ev_keypress_notify *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_KEYPRESS_NOTIFY, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); if (!conn) @@ -5641,18 +5518,13 @@ static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) conn->passkey_entered); } -static void hci_simple_pair_complete_evt(struct hci_dev *hdev, +static void hci_simple_pair_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_simple_pair_complete *ev; + struct hci_ev_simple_pair_complete *ev = data; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_SIMPLE_PAIR_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5677,19 +5549,14 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_remote_host_features_evt(struct hci_dev *hdev, +static void hci_remote_host_features_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_remote_host_features *ev; + struct hci_ev_remote_host_features *ev = data; struct inquiry_entry *ie; struct hci_conn *conn; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_HOST_FEATURES, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5704,18 +5571,13 @@ static void hci_remote_host_features_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, +static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, void *edata, struct sk_buff *skb) { - struct hci_ev_remote_oob_data_request *ev; + struct hci_ev_remote_oob_data_request *ev = edata; struct oob_data *data; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_REMOTE_OOB_DATA_REQUEST, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s", hdev->name); + bt_dev_dbg(hdev, ""); hci_dev_lock(hdev); @@ -5764,16 +5626,13 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, } #if IS_ENABLED(CONFIG_BT_HS) -static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_chan_selected_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_channel_selected *ev; + struct hci_ev_channel_selected *ev = data; struct hci_conn *hcon; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_CHANNEL_SELECTED, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s handle 0x%2.2x", hdev->name, ev->phy_handle); + bt_dev_dbg(hdev, "handle 0x%2.2x", ev->phy_handle); hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); if (!hcon) @@ -5782,18 +5641,14 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb) amp_read_loc_assoc_final_data(hdev, hcon); } -static void hci_phy_link_complete_evt(struct hci_dev *hdev, +static void hci_phy_link_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_phy_link_complete *ev; + struct hci_ev_phy_link_complete *ev = data; struct hci_conn *hcon, *bredr_hcon; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_PHY_LINK_COMPLETE, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s handle 0x%2.2x status 0x%2.2x", hdev->name, ev->phy_handle, - ev->status); + bt_dev_dbg(hdev, "handle 0x%2.2x status 0x%2.2x", ev->phy_handle, + ev->status); hci_dev_lock(hdev); @@ -5827,21 +5682,16 @@ static void hci_phy_link_complete_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_loglink_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_logical_link_complete *ev; + struct hci_ev_logical_link_complete *ev = data; struct hci_conn *hcon; struct hci_chan *hchan; struct amp_mgr *mgr; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LOGICAL_LINK_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", - hdev->name, le16_to_cpu(ev->handle), ev->phy_handle, - ev->status); + bt_dev_dbg(hdev, "log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x", + le16_to_cpu(ev->handle), ev->phy_handle, ev->status); hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle); if (!hcon) @@ -5871,19 +5721,14 @@ static void hci_loglink_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } } -static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, +static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_disconn_logical_link_complete *ev; + struct hci_ev_disconn_logical_link_complete *ev = data; struct hci_chan *hchan; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s log handle 0x%4.4x status 0x%2.2x", hdev->name, - le16_to_cpu(ev->handle), ev->status); + bt_dev_dbg(hdev, "handle 0x%4.4x status 0x%2.2x", + le16_to_cpu(ev->handle), ev->status); if (ev->status) return; @@ -5900,18 +5745,13 @@ static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, +static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_disconn_phy_link_complete *ev; + struct hci_ev_disconn_phy_link_complete *ev = data; struct hci_conn *hcon; - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_DISCONN_PHY_LINK_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); if (ev->status) return; @@ -6938,13 +6778,10 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_meta_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_meta *ev; - - ev = hci_ev_skb_pull(hdev, skb, HCI_EV_LE_META, sizeof(*ev)); - if (!ev) - return; + struct hci_ev_le_meta *ev = data; switch (ev->subevent) { case HCI_EV_LE_CONN_COMPLETE: @@ -7109,6 +6946,225 @@ static void hci_store_wake_reason(struct hci_dev *hdev, u8 event, hci_dev_unlock(hdev); } +#define HCI_EV_VL(_op, _func, _min_len, _max_len) \ +[_op] = { \ + .req = false, \ + .func = _func, \ + .min_len = _min_len, \ + .max_len = _max_len, \ +} + +#define HCI_EV(_op, _func, _len) \ + HCI_EV_VL(_op, _func, _len, _len) + +#define HCI_EV_STATUS(_op, _func) \ + HCI_EV(_op, _func, sizeof(struct hci_ev_status)) + +#define HCI_EV_REQ_VL(_op, _func, _min_len, _max_len) \ +[_op] = { \ + .req = true, \ + .func_req = _func, \ + .min_len = _min_len, \ + .max_len = _max_len, \ +} + +#define HCI_EV_REQ(_op, _func, _len) \ + HCI_EV_REQ_VL(_op, _func, _len, _len) + +/* Entries in this table shall have their position according to the event opcode + * they handle so the use of the macros above is recommend since it does attempt + * to initialize at its proper index using Designated Initializers that way + * events without a callback function don't have entered. + */ +static const struct hci_ev { + bool req; + union { + void (*func)(struct hci_dev *hdev, void *data, + struct sk_buff *skb); + void (*func_req)(struct hci_dev *hdev, void *data, + struct sk_buff *skb, u16 *opcode, u8 *status, + hci_req_complete_t *req_complete, + hci_req_complete_skb_t *req_complete_skb); + }; + u16 min_len; + u16 max_len; +} hci_ev_table[U8_MAX + 1] = { + /* [0x01 = HCI_EV_INQUIRY_COMPLETE] */ + HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt), + /* [0x02 = HCI_EV_INQUIRY_RESULT] */ + HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt, + sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE), + /* [0x03 = HCI_EV_CONN_COMPLETE] */ + HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt, + sizeof(struct hci_ev_conn_complete)), + /* [0x04 = HCI_EV_CONN_REQUEST] */ + HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt, + sizeof(struct hci_ev_conn_request)), + /* [0x05 = HCI_EV_DISCONN_COMPLETE] */ + HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt, + sizeof(struct hci_ev_disconn_complete)), + /* [0x06 = HCI_EV_AUTH_COMPLETE] */ + HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt, + sizeof(struct hci_ev_auth_complete)), + /* [0x07 = HCI_EV_REMOTE_NAME] */ + HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt, + sizeof(struct hci_ev_remote_name)), + /* [0x08 = HCI_EV_ENCRYPT_CHANGE] */ + HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt, + sizeof(struct hci_ev_encrypt_change)), + /* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */ + HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE, + hci_change_link_key_complete_evt, + sizeof(struct hci_ev_change_link_key_complete)), + /* [0x0b = HCI_EV_REMOTE_FEATURES] */ + HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt, + sizeof(struct hci_ev_remote_features)), + /* [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), + /* [0x0f = HCI_EV_CMD_STATUS] */ + HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt, + sizeof(struct hci_ev_cmd_status)), + /* [0x10 = HCI_EV_CMD_STATUS] */ + HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt, + sizeof(struct hci_ev_hardware_error)), + /* [0x12 = HCI_EV_ROLE_CHANGE] */ + HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt, + sizeof(struct hci_ev_role_change)), + /* [0x13 = HCI_EV_NUM_COMP_PKTS] */ + HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt, + sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE), + /* [0x14 = HCI_EV_MODE_CHANGE] */ + HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt, + sizeof(struct hci_ev_mode_change)), + /* [0x16 = HCI_EV_PIN_CODE_REQ] */ + HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt, + sizeof(struct hci_ev_pin_code_req)), + /* [0x17 = HCI_EV_LINK_KEY_REQ] */ + HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt, + sizeof(struct hci_ev_link_key_req)), + /* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */ + HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt, + sizeof(struct hci_ev_link_key_notify)), + /* [0x1c = HCI_EV_CLOCK_OFFSET] */ + HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt, + sizeof(struct hci_ev_clock_offset)), + /* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */ + HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt, + sizeof(struct hci_ev_pkt_type_change)), + /* [0x20 = HCI_EV_PSCAN_REP_MODE] */ + HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt, + sizeof(struct hci_ev_pscan_rep_mode)), + /* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */ + HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI, + hci_inquiry_result_with_rssi_evt, + sizeof(struct hci_ev_inquiry_result_rssi), + HCI_MAX_EVENT_SIZE), + /* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */ + HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt, + sizeof(struct hci_ev_remote_ext_features)), + /* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */ + HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt, + sizeof(struct hci_ev_sync_conn_complete)), + /* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */ + HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT, + hci_extended_inquiry_result_evt, + sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE), + /* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */ + HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt, + sizeof(struct hci_ev_key_refresh_complete)), + /* [0x31 = HCI_EV_IO_CAPA_REQUEST] */ + HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt, + sizeof(struct hci_ev_io_capa_request)), + /* [0x32 = HCI_EV_IO_CAPA_REPLY] */ + HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt, + sizeof(struct hci_ev_io_capa_reply)), + /* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */ + HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt, + sizeof(struct hci_ev_user_confirm_req)), + /* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */ + HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt, + sizeof(struct hci_ev_user_passkey_req)), + /* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */ + HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt, + sizeof(struct hci_ev_remote_oob_data_request)), + /* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */ + HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt, + sizeof(struct hci_ev_simple_pair_complete)), + /* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */ + HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt, + sizeof(struct hci_ev_user_passkey_notify)), + /* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */ + HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt, + sizeof(struct hci_ev_keypress_notify)), + /* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */ + HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt, + sizeof(struct hci_ev_remote_host_features)), + /* [0x3e = HCI_EV_LE_META] */ + HCI_EV_VL(HCI_EV_LE_META, hci_le_meta_evt, + sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE), +#if IS_ENABLED(CONFIG_BT_HS) + /* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */ + HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt, + sizeof(struct hci_ev_phy_link_complete)), + /* [0x41 = HCI_EV_CHANNEL_SELECTED] */ + HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt, + sizeof(struct hci_ev_channel_selected)), + /* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */ + HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE, + hci_disconn_loglink_complete_evt, + sizeof(struct hci_ev_disconn_logical_link_complete)), + /* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */ + HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt, + sizeof(struct hci_ev_logical_link_complete)), + /* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */ + HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE, + hci_disconn_phylink_complete_evt, + sizeof(struct hci_ev_disconn_phy_link_complete)), +#endif + /* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */ + HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt, + sizeof(struct hci_ev_num_comp_blocks)), + /* [0xff = HCI_EV_VENDOR] */ + HCI_EV(HCI_EV_VENDOR, msft_vendor_evt, 0), +}; + +static void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb, + u16 *opcode, u8 *status, + hci_req_complete_t *req_complete, + hci_req_complete_skb_t *req_complete_skb) +{ + const struct hci_ev *ev = &hci_ev_table[event]; + void *data; + + if (!ev->func) + return; + + if (skb->len < ev->min_len) { + bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u", + event, skb->len, ev->min_len); + return; + } + + /* Just warn if the length is over max_len size it still be + * possible to partially parse the event so leave to callback to + * decide if that is acceptable. + */ + if (skb->len > ev->max_len) + bt_dev_warn(hdev, "unexpected event 0x%2.2x length: %u > %u", + event, skb->len, ev->max_len); + + data = hci_ev_skb_pull(hdev, skb, event, ev->min_len); + if (!data) + return; + + if (ev->req) + ev->func_req(hdev, data, skb, opcode, status, req_complete, + req_complete_skb); + else + ev->func(hdev, data, skb); +} + void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_event_hdr *hdr = (void *) skb->data; @@ -7125,7 +7181,8 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) event = hdr->evt; if (!event) { - bt_dev_warn(hdev, "Received unexpected HCI Event 00000000"); + bt_dev_warn(hdev, "Received unexpected HCI Event 0x%2.2x", + event); goto done; } @@ -7151,191 +7208,10 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) /* Store wake reason if we're suspended */ hci_store_wake_reason(hdev, event, skb); - switch (event) { - case HCI_EV_INQUIRY_COMPLETE: - hci_inquiry_complete_evt(hdev, skb); - break; - - case HCI_EV_INQUIRY_RESULT: - hci_inquiry_result_evt(hdev, skb); - break; - - case HCI_EV_CONN_COMPLETE: - hci_conn_complete_evt(hdev, skb); - break; - - case HCI_EV_CONN_REQUEST: - hci_conn_request_evt(hdev, skb); - break; - - case HCI_EV_DISCONN_COMPLETE: - hci_disconn_complete_evt(hdev, skb); - break; - - case HCI_EV_AUTH_COMPLETE: - hci_auth_complete_evt(hdev, skb); - break; - - case HCI_EV_REMOTE_NAME: - hci_remote_name_evt(hdev, skb); - break; - - case HCI_EV_ENCRYPT_CHANGE: - hci_encrypt_change_evt(hdev, skb); - break; - - case HCI_EV_CHANGE_LINK_KEY_COMPLETE: - hci_change_link_key_complete_evt(hdev, skb); - break; - - case HCI_EV_REMOTE_FEATURES: - hci_remote_features_evt(hdev, skb); - break; - - case HCI_EV_CMD_COMPLETE: - hci_cmd_complete_evt(hdev, skb, &opcode, &status, - &req_complete, &req_complete_skb); - break; + bt_dev_dbg(hdev, "event 0x%2.2x", event); - case HCI_EV_CMD_STATUS: - hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete, - &req_complete_skb); - break; - - case HCI_EV_HARDWARE_ERROR: - hci_hardware_error_evt(hdev, skb); - break; - - case HCI_EV_ROLE_CHANGE: - hci_role_change_evt(hdev, skb); - break; - - case HCI_EV_NUM_COMP_PKTS: - hci_num_comp_pkts_evt(hdev, skb); - break; - - case HCI_EV_MODE_CHANGE: - hci_mode_change_evt(hdev, skb); - break; - - case HCI_EV_PIN_CODE_REQ: - hci_pin_code_request_evt(hdev, skb); - break; - - case HCI_EV_LINK_KEY_REQ: - hci_link_key_request_evt(hdev, skb); - break; - - case HCI_EV_LINK_KEY_NOTIFY: - hci_link_key_notify_evt(hdev, skb); - break; - - case HCI_EV_CLOCK_OFFSET: - hci_clock_offset_evt(hdev, skb); - break; - - case HCI_EV_PKT_TYPE_CHANGE: - hci_pkt_type_change_evt(hdev, skb); - break; - - case HCI_EV_PSCAN_REP_MODE: - hci_pscan_rep_mode_evt(hdev, skb); - break; - - case HCI_EV_INQUIRY_RESULT_WITH_RSSI: - hci_inquiry_result_with_rssi_evt(hdev, skb); - break; - - case HCI_EV_REMOTE_EXT_FEATURES: - hci_remote_ext_features_evt(hdev, skb); - break; - - case HCI_EV_SYNC_CONN_COMPLETE: - hci_sync_conn_complete_evt(hdev, skb); - break; - - case HCI_EV_EXTENDED_INQUIRY_RESULT: - hci_extended_inquiry_result_evt(hdev, skb); - break; - - case HCI_EV_KEY_REFRESH_COMPLETE: - hci_key_refresh_complete_evt(hdev, skb); - break; - - case HCI_EV_IO_CAPA_REQUEST: - hci_io_capa_request_evt(hdev, skb); - break; - - case HCI_EV_IO_CAPA_REPLY: - hci_io_capa_reply_evt(hdev, skb); - break; - - case HCI_EV_USER_CONFIRM_REQUEST: - hci_user_confirm_request_evt(hdev, skb); - break; - - case HCI_EV_USER_PASSKEY_REQUEST: - hci_user_passkey_request_evt(hdev, skb); - break; - - case HCI_EV_USER_PASSKEY_NOTIFY: - hci_user_passkey_notify_evt(hdev, skb); - break; - - case HCI_EV_KEYPRESS_NOTIFY: - hci_keypress_notify_evt(hdev, skb); - break; - - case HCI_EV_SIMPLE_PAIR_COMPLETE: - hci_simple_pair_complete_evt(hdev, skb); - break; - - case HCI_EV_REMOTE_HOST_FEATURES: - hci_remote_host_features_evt(hdev, skb); - break; - - case HCI_EV_LE_META: - hci_le_meta_evt(hdev, skb); - break; - - case HCI_EV_REMOTE_OOB_DATA_REQUEST: - hci_remote_oob_data_request_evt(hdev, skb); - break; - -#if IS_ENABLED(CONFIG_BT_HS) - case HCI_EV_CHANNEL_SELECTED: - hci_chan_selected_evt(hdev, skb); - break; - - case HCI_EV_PHY_LINK_COMPLETE: - hci_phy_link_complete_evt(hdev, skb); - break; - - case HCI_EV_LOGICAL_LINK_COMPLETE: - hci_loglink_complete_evt(hdev, skb); - break; - - case HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE: - hci_disconn_loglink_complete_evt(hdev, skb); - break; - - case HCI_EV_DISCONN_PHY_LINK_COMPLETE: - hci_disconn_phylink_complete_evt(hdev, skb); - break; -#endif - - case HCI_EV_NUM_COMP_BLOCKS: - hci_num_comp_blocks_evt(hdev, skb); - break; - - case HCI_EV_VENDOR: - msft_vendor_evt(hdev, skb); - break; - - default: - BT_DBG("%s event 0x%2.2x", hdev->name, event); - break; - } + hci_event_func(hdev, event, skb, &opcode, &status, &req_complete, + &req_complete_skb); if (req_complete) { req_complete(hdev, status, opcode); diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c index 1122097e1e49..6a943634b31a 100644 --- a/net/bluetooth/msft.c +++ b/net/bluetooth/msft.c @@ -590,7 +590,7 @@ void msft_unregister(struct hci_dev *hdev) kfree(msft); } -void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb) +void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { struct msft_data *msft = hdev->msft_data; u8 event; diff --git a/net/bluetooth/msft.h b/net/bluetooth/msft.h index b59b63dc0ea8..7fefc0655b6f 100644 --- a/net/bluetooth/msft.h +++ b/net/bluetooth/msft.h @@ -17,7 +17,7 @@ void msft_register(struct hci_dev *hdev); void msft_unregister(struct hci_dev *hdev); void msft_do_open(struct hci_dev *hdev); void msft_do_close(struct hci_dev *hdev); -void msft_vendor_evt(struct hci_dev *hdev, struct sk_buff *skb); +void msft_vendor_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb); __u64 msft_get_features(struct hci_dev *hdev); int msft_add_monitor_pattern(struct hci_dev *hdev, struct adv_monitor *monitor); int msft_remove_monitor(struct hci_dev *hdev, struct adv_monitor *monitor, From patchwork Wed Dec 1 18:55:04 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520581 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8A0F5C43219 for ; Wed, 1 Dec 2021 18:55:31 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352606AbhLAS6v (ORCPT ); Wed, 1 Dec 2021 13:58:51 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51528 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352021AbhLAS6k (ORCPT ); Wed, 1 Dec 2021 13:58:40 -0500 Received: from mail-pj1-x1036.google.com (mail-pj1-x1036.google.com [IPv6:2607:f8b0:4864:20::1036]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 047B4C061748 for ; Wed, 1 Dec 2021 10:55:19 -0800 (PST) Received: by mail-pj1-x1036.google.com with SMTP id nh10-20020a17090b364a00b001a69adad5ebso2452443pjb.2 for ; Wed, 01 Dec 2021 10:55:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=6Qm9uxlPq0TJwSg0jQX4vsgvqJsp5f/3ttbAXcPUU0w=; b=Su+4WNDLpxlH2oP8ve12jsRsUXHrX8Vu9cNPNkxcIsEIgXd3HYCZyDh1i3j5RY4CXh JktFCoA6YQ3rLt6iIwFhh17iQDoFOX1BwgcGzL+TMHekovgrYFHR5Xb2cYYE61avkmxp IajCyeG7OgBKAnETN/QYISKYHA0vBdHwRTP32rL2f+/IJ4UyqjL7WksCCU9pVlfkp1gU 04qF1CnydZg7kJ6dqbmMWsgIPeDktKUNJxxHGHTyUQwgjZaYzZPMALL3YSXj/xavqYIJ 8x5L5KtBNYjUldcPUWgJMX2/Rf2nVuJlOv8Xs8sxFjOqk/VCM3dQQ76lwed8+3THYfPH 2XWA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=6Qm9uxlPq0TJwSg0jQX4vsgvqJsp5f/3ttbAXcPUU0w=; b=VuOw+pflDSnhekvRmyE4cNU6pCw3G+dxcc0GrvG0nIF//0LbvSsVeNNtx8IIfSp2w1 hb3MkNklDtsiRncu/ZQl6olRqd0E+rqKjTiNDoC5+lFjLs7yY0SPyKjkkVst+8beRTFY W3DcIL7qHsNZD1ln0Gs0bRbv3NeKSonW0VR46kMsbVXfODvPAdFFdcfLtex1HKbROu0u khNH/ohqTMUOOOEZeEdHlzDPLgJL9MVDqOUp19DU27H4bdUbns57wV8kFb2nSB822azu 9RnBKSOq2WPjiKPOC3CQACFy4Lbhvdd3XrWLEJnXMrctpE/i4brv7K4wGrNbDyB8EQLU jWYw== X-Gm-Message-State: AOAM530sd+ovj2GS5gtdNFQgnO18QjGMAn5UYUHzvsXqFpa/IreAW2nT RkAKQjXNfWZiZVmSMMhfAdQZU0+hHLg= X-Google-Smtp-Source: ABdhPJwDKe1jfCqykgkFVCZilYNReZju7+MyY2u8DsD8RUG4kN64XTEzI75pl2RJsXmkfFuCe+wOgQ== X-Received: by 2002:a17:902:c105:b0:142:2441:aa24 with SMTP id 5-20020a170902c10500b001422441aa24mr9508267pli.44.1638384918158; Wed, 01 Dec 2021 10:55:18 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:17 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 13/15] Bluetooth: hci_event: Use of a function table to handle LE subevents Date: Wed, 1 Dec 2021 10:55:04 -0800 Message-Id: <20211201185506.1421186-14-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This change the use of switch statement to a function table which is easier to extend and can include min/max length of each subevent. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 247 +++++++++++++++++++------------------- 1 file changed, 122 insertions(+), 125 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 3953ec188ff6..cecd81e0504c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -5969,16 +5969,12 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, hci_dev_unlock(hdev); } -static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_conn_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_conn_complete *ev; - - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_COMPLETE, - sizeof(*ev)); - if (!ev) - return; + struct hci_ev_le_conn_complete *ev = data; - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, NULL, ev->role, le16_to_cpu(ev->handle), @@ -5987,17 +5983,12 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) le16_to_cpu(ev->supervision_timeout)); } -static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, +static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_le_enh_conn_complete *ev; + struct hci_ev_le_enh_conn_complete *ev = data; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ENHANCED_CONN_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type, &ev->local_rpa, ev->role, le16_to_cpu(ev->handle), @@ -6006,18 +5997,14 @@ static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, le16_to_cpu(ev->supervision_timeout)); } -static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_evt_le_ext_adv_set_term *ev; + struct hci_evt_le_ext_adv_set_term *ev = data; struct hci_conn *conn; struct adv_info *adv, *n; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_SET_TERM, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); adv = hci_find_adv_instance(hdev, ev->handle); @@ -6075,18 +6062,13 @@ static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, struct sk_buff *skb) } } -static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, +static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_le_conn_update_complete *ev; + struct hci_ev_le_conn_update_complete *ev = data; struct hci_conn *conn; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_CONN_UPDATE_COMPLETE, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); if (ev->status) return; @@ -6402,14 +6384,10 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, clear_pending_adv_report(hdev); } -static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_advertising_report *ev; - - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT, - sizeof(*ev)); - if (!ev) - return; + struct hci_ev_le_advertising_report *ev = data; if (!ev->num) return; @@ -6487,14 +6465,10 @@ static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type) return LE_ADV_INVALID; } -static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_ext_adv_report *ev; - - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, - sizeof(*ev)); - if (!ev) - return; + struct hci_ev_le_ext_adv_report *ev = data; if (!ev->num) return; @@ -6528,18 +6502,13 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, +static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_le_remote_feat_complete *ev; + struct hci_ev_le_remote_feat_complete *ev = data; struct hci_conn *conn; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT, - sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); hci_dev_lock(hdev); @@ -6575,19 +6544,16 @@ static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_ltk_request_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_ltk_req *ev; + struct hci_ev_le_ltk_req *ev = data; struct hci_cp_le_ltk_reply cp; struct hci_cp_le_ltk_neg_reply neg; struct hci_conn *conn; struct smp_ltk *ltk; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_LTK_REQ, sizeof(*ev)); - if (!ev) - return; - - BT_DBG("%s handle 0x%4.4x", hdev->name, __le16_to_cpu(ev->handle)); + bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle)); hci_dev_lock(hdev); @@ -6655,18 +6621,15 @@ static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, &cp); } -static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, +static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_le_remote_conn_param_req *ev; + struct hci_ev_le_remote_conn_param_req *ev = data; struct hci_cp_le_conn_param_req_reply cp; struct hci_conn *hcon; u16 handle, min, max, latency, timeout; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_REMOTE_CONN_PARAM_REQ, - sizeof(*ev)); - if (!ev) - return; + bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle)); handle = le16_to_cpu(ev->handle); min = le16_to_cpu(ev->interval_min); @@ -6718,17 +6681,12 @@ static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); } -static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, +static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_le_direct_adv_report *ev; + struct hci_ev_le_direct_adv_report *ev = data; int i; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT, - sizeof(*ev)); - if (!ev) - return; - if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT, flex_array_size(ev, info, ev->num))) return; @@ -6750,17 +6708,13 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, hci_dev_unlock(hdev); } -static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_le_phy_update_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_le_phy_update_complete *ev; + struct hci_ev_le_phy_update_complete *ev = data; struct hci_conn *conn; - ev = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_PHY_UPDATE_COMPLETE, - sizeof(*ev)); - if (ev) - return; - - BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); + bt_dev_dbg(hdev, "status 0x%2.2x", ev->status); if (ev->status) return; @@ -6778,59 +6732,102 @@ static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_unlock(hdev); } -static void hci_le_meta_evt(struct hci_dev *hdev, void *data, - struct sk_buff *skb) -{ - struct hci_ev_le_meta *ev = data; - - switch (ev->subevent) { - case HCI_EV_LE_CONN_COMPLETE: - hci_le_conn_complete_evt(hdev, skb); - break; - - case HCI_EV_LE_CONN_UPDATE_COMPLETE: - hci_le_conn_update_complete_evt(hdev, skb); - break; +#define HCI_LE_EV_VL(_op, _func, _min_len, _max_len) \ +[_op] = { \ + .func = _func, \ + .min_len = _min_len, \ + .max_len = _max_len, \ +} - case HCI_EV_LE_ADVERTISING_REPORT: - hci_le_adv_report_evt(hdev, skb); - break; +#define HCI_LE_EV(_op, _func, _len) \ + HCI_LE_EV_VL(_op, _func, _len, _len) - case HCI_EV_LE_REMOTE_FEAT_COMPLETE: - hci_le_remote_feat_complete_evt(hdev, skb); - break; +#define HCI_LE_EV_STATUS(_op, _func) \ + HCI_LE_EV(_op, _func, sizeof(struct hci_ev_status)) - case HCI_EV_LE_LTK_REQ: - hci_le_ltk_request_evt(hdev, skb); - break; +/* Entries in this table shall have their position according to the subevent + * opcode they handle so the use of the macros above is recommend since it does + * attempt to initialize at its proper index using Designated Initializers that + * way events without a callback function can be ommited. + */ +static const struct hci_le_ev { + void (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb); + u16 min_len; + u16 max_len; +} hci_le_ev_table[U8_MAX + 1] = { + /* [0x01 = HCI_EV_LE_CONN_COMPLETE] */ + HCI_LE_EV(HCI_EV_LE_CONN_COMPLETE, hci_le_conn_complete_evt, + sizeof(struct hci_ev_le_conn_complete)), + /* [0x02 = HCI_EV_LE_ADVERTISING_REPORT] */ + HCI_LE_EV_VL(HCI_EV_LE_ADVERTISING_REPORT, hci_le_adv_report_evt, + sizeof(struct hci_ev_le_advertising_report), + HCI_MAX_EVENT_SIZE), + /* [0x03 = HCI_EV_LE_CONN_UPDATE_COMPLETE] */ + HCI_LE_EV(HCI_EV_LE_CONN_UPDATE_COMPLETE, + hci_le_conn_update_complete_evt, + sizeof(struct hci_ev_le_conn_update_complete)), + /* [0x04 = HCI_EV_LE_REMOTE_FEAT_COMPLETE] */ + HCI_LE_EV(HCI_EV_LE_REMOTE_FEAT_COMPLETE, + hci_le_remote_feat_complete_evt, + sizeof(struct hci_ev_le_remote_feat_complete)), + /* [0x05 = HCI_EV_LE_LTK_REQ] */ + HCI_LE_EV(HCI_EV_LE_LTK_REQ, hci_le_ltk_request_evt, + sizeof(struct hci_ev_le_ltk_req)), + /* [0x06 = HCI_EV_LE_REMOTE_CONN_PARAM_REQ] */ + HCI_LE_EV(HCI_EV_LE_REMOTE_CONN_PARAM_REQ, + hci_le_remote_conn_param_req_evt, + sizeof(struct hci_ev_le_remote_conn_param_req)), + /* [0x0a = HCI_EV_LE_ENHANCED_CONN_COMPLETE] */ + HCI_LE_EV(HCI_EV_LE_ENHANCED_CONN_COMPLETE, + hci_le_enh_conn_complete_evt, + sizeof(struct hci_ev_le_enh_conn_complete)), + /* [0x0b = HCI_EV_LE_DIRECT_ADV_REPORT] */ + HCI_LE_EV_VL(HCI_EV_LE_DIRECT_ADV_REPORT, hci_le_direct_adv_report_evt, + sizeof(struct hci_ev_le_direct_adv_report), + HCI_MAX_EVENT_SIZE), + /* [0x0c = HCI_EV_LE_PHY_UPDATE_COMPLETE] */ + HCI_LE_EV(HCI_EV_LE_PHY_UPDATE_COMPLETE, hci_le_phy_update_evt, + sizeof(struct hci_ev_le_phy_update_complete)), + /* [0x0d = HCI_EV_LE_EXT_ADV_REPORT] */ + HCI_LE_EV_VL(HCI_EV_LE_EXT_ADV_REPORT, hci_le_ext_adv_report_evt, + sizeof(struct hci_ev_le_ext_adv_report), + HCI_MAX_EVENT_SIZE), + /* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */ + HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt, + sizeof(struct hci_evt_le_ext_adv_set_term)), +}; - case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: - hci_le_remote_conn_param_req_evt(hdev, skb); - break; +static void hci_le_meta_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb) +{ + struct hci_ev_le_meta *ev = data; + const struct hci_le_ev *subev; - case HCI_EV_LE_DIRECT_ADV_REPORT: - hci_le_direct_adv_report_evt(hdev, skb); - break; + bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent); - case HCI_EV_LE_PHY_UPDATE_COMPLETE: - hci_le_phy_update_evt(hdev, skb); - break; + subev = &hci_le_ev_table[ev->subevent]; + if (!subev->func) + return; - case HCI_EV_LE_EXT_ADV_REPORT: - hci_le_ext_adv_report_evt(hdev, skb); - break; + if (skb->len < subev->min_len) { + bt_dev_err(hdev, "unexpected subevent 0x%2.2x length: %u < %u", + ev->subevent, skb->len, subev->min_len); + return; + } - case HCI_EV_LE_ENHANCED_CONN_COMPLETE: - hci_le_enh_conn_complete_evt(hdev, skb); - break; + /* Just warn if the length is over max_len size it still be + * possible to partially parse the event so leave to callback to + * decide if that is acceptable. + */ + if (skb->len > subev->max_len) + bt_dev_warn(hdev, "unexpected subevent 0x%2.2x length: %u > %u", + ev->subevent, skb->len, subev->max_len); - case HCI_EV_LE_EXT_ADV_SET_TERM: - hci_le_ext_adv_term_evt(hdev, skb); - break; + data = hci_le_ev_skb_pull(hdev, skb, ev->subevent, subev->min_len); + if (!data) + return; - default: - break; - } + subev->func(hdev, data, skb); } static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, From patchwork Wed Dec 1 18:55:05 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 520580 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 146E2C433FE for ; Wed, 1 Dec 2021 18:55:34 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352245AbhLAS6w (ORCPT ); Wed, 1 Dec 2021 13:58:52 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51542 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1352412AbhLAS6l (ORCPT ); Wed, 1 Dec 2021 13:58:41 -0500 Received: from mail-pj1-x102a.google.com (mail-pj1-x102a.google.com [IPv6:2607:f8b0:4864:20::102a]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id CB11AC06174A for ; Wed, 1 Dec 2021 10:55:20 -0800 (PST) Received: by mail-pj1-x102a.google.com with SMTP id np6-20020a17090b4c4600b001a90b011e06so2441440pjb.5 for ; Wed, 01 Dec 2021 10:55:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=QFJJ4xjjtlB+rtwOOH7ULxkED2/GpQPgb/RIRKJIEIE=; b=DAdm5xuWJ/3KmCA3V6kioBAgX2zN9WQZMGgHmkIhYNRhe5iFTuI3B0dS20Z6tC+Klj afT3g04U2lzjoE+24Q+cRCvJVHAl9T/WQpwDNri5P1/EjaX3/bs1Rg/dMJAm2Z7l0HDR R4m3eIivE1tlxVX3wq4L5irAtpUKxFH59Gxz32OBK9xPoOaO2n7ve2qzDEGKPqUi9jQP iQ5uN1GCiySUQR8023YUfW8lg73S0uRvQhwmndalJIal5UMomYdVd8T8Y/0PPSrZOiVJ pMjeiEXlkL1KgOUWcMvdbZwFz+UuNTjbOSrpHU99AYK1wtOWOpOQqdVELFW2mge5SAhK p0tA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=QFJJ4xjjtlB+rtwOOH7ULxkED2/GpQPgb/RIRKJIEIE=; b=tgu/eA5AMHD8GeurPkhpjyoXECAjttSlEx/kcJ/nPgbAH/JwCGtCEfeMODMQDtbLJt mlqOdGPhQO5j/qiu6f8m3NTpa5+TjQfSghLBUP2uUjJhKz5CheZxjsgaTD9VYMMi5uxP OcDCpcGz+jjZhvMr2Fwwq9+PjX+9iuIAH4UVURrA+cyjjuqxHh4BMzhyAbj4mJaaE2JJ SoXdk5bc3HcoBDDQtA07hMS8mOshLaVsFIF5Np1/tIIhY0DKIc1VfomcO4jirgrotJZu x2r+qhJgqjg80ar3paYZIHspL2hwhXHd1giSi8bgOo2EEU21gztJUUfFqoJfsIlLC+FV 1QZA== X-Gm-Message-State: AOAM532UD7ER62S/PDGUKLrAE0357gGdjARMCE8IaMAcMSsiV7nmxSWp LaHRA1E0AaVXVX1R6N2bbP2d69Y8rDA= X-Google-Smtp-Source: ABdhPJzusnltMy/qldx5xbOXEayCn8fEN3Xk3xARLi42/0BcxaRK2XaThFbQgGkty/JJ3xqtvS/5rQ== X-Received: by 2002:a17:90b:4c4f:: with SMTP id np15mr26301pjb.65.1638384918992; Wed, 01 Dec 2021 10:55:18 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.18 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:18 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 14/15] Bluetooth: hci_event: Use of a function table to handle Command Complete Date: Wed, 1 Dec 2021 10:55:05 -0800 Message-Id: <20211201185506.1421186-15-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This change the use of switch statement to a function table which is easier to extend and can include min/max length of each command. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 1848 +++++++++++++++---------------------- 1 file changed, 752 insertions(+), 1096 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index cecd81e0504c..313b7b79d5b5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -81,14 +81,10 @@ static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb, return data; } -static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, - u8 *new_status) +static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_INQUIRY_CANCEL, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -104,10 +100,8 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, rp->status = 0x00; } - *new_status = rp->status; - if (rp->status) - return; + return rp->status; clear_bit(HCI_INQUIRY, &hdev->flags); smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */ @@ -123,68 +117,62 @@ static void hci_cc_inquiry_cancel(struct hci_dev *hdev, struct sk_buff *skb, hci_dev_unlock(hdev); hci_conn_check_pending(hdev); + + return rp->status; } -static void hci_cc_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_periodic_inq(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PERIODIC_INQ, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_set_flag(hdev, HCI_PERIODIC_INQ); + + return rp->status; } -static void hci_cc_exit_periodic_inq(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_exit_periodic_inq(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_EXIT_PERIODIC_INQ, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); hci_conn_check_pending(hdev); + + return rp->status; } -static void hci_cc_remote_name_req_cancel(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_remote_name_req_cancel(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_REMOTE_NAME_REQ_CANCEL, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + return rp->status; } -static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_role_discovery(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_role_discovery *rp; + struct hci_rp_role_discovery *rp = data; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_ROLE_DISCOVERY, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_lock(hdev); @@ -193,21 +181,20 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) conn->role = rp->role; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_link_policy(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_link_policy *rp; + struct hci_rp_read_link_policy *rp = data; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LINK_POLICY, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_lock(hdev); @@ -216,26 +203,25 @@ static void hci_cc_read_link_policy(struct hci_dev *hdev, struct sk_buff *skb) conn->link_policy = __le16_to_cpu(rp->policy); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_link_policy(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_write_link_policy *rp; + struct hci_rp_write_link_policy *rp = data; struct hci_conn *conn; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LINK_POLICY, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -244,63 +230,55 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) conn->link_policy = get_unaligned_le16(sent + 2); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_def_link_policy(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_def_link_policy(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_def_link_policy *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_LINK_POLICY, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_def_link_policy *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->link_policy = __le16_to_cpu(rp->policy); + + return rp->status; } -static void hci_cc_write_def_link_policy(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_def_link_policy(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_LINK_POLICY, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); if (!sent) - return; + return rp->status; hdev->link_policy = get_unaligned_le16(sent); + + return rp->status; } -static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_reset(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_RESET, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); clear_bit(HCI_RESET, &hdev->flags); if (rp->status) - return; + return rp->status; /* Reset all non-persistent flags */ hci_dev_clear_volatile_flags(hdev); @@ -322,66 +300,59 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) hci_bdaddr_list_clear(&hdev->le_accept_list); hci_bdaddr_list_clear(&hdev->le_resolv_list); + + return rp->status; } -static void hci_cc_read_stored_link_key(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_stored_link_key(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_stored_link_key *rp; + struct hci_rp_read_stored_link_key *rp = data; struct hci_cp_read_stored_link_key *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_STORED_LINK_KEY, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY); if (!sent) - return; + return rp->status; if (!rp->status && sent->read_all == 0x01) { hdev->stored_max_keys = le16_to_cpu(rp->max_keys); hdev->stored_num_keys = le16_to_cpu(rp->num_keys); } + + return rp->status; } -static void hci_cc_delete_stored_link_key(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_delete_stored_link_key *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_DELETE_STORED_LINK_KEY, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_delete_stored_link_key *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (rp->num_keys <= hdev->stored_num_keys) hdev->stored_num_keys -= le16_to_cpu(rp->num_keys); else hdev->stored_num_keys = 0; + + return rp->status; } -static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_local_name(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LOCAL_NAME, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -391,40 +362,38 @@ static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_local_name(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_local_name(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_name *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_NAME, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_name *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (hci_dev_test_flag(hdev, HCI_SETUP) || hci_dev_test_flag(hdev, HCI_CONFIG)) memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH); + + return rp->status; } -static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_auth_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_ENABLE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -441,26 +410,25 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) mgmt_auth_enable_complete(hdev, rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_encrypt_mode(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; __u8 param; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_ENCRYPT_MODE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); if (!sent) - return; + return rp->status; param = *((__u8 *) sent); @@ -468,23 +436,22 @@ static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) set_bit(HCI_ENCRYPT, &hdev->flags); else clear_bit(HCI_ENCRYPT, &hdev->flags); + + return rp->status; } -static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_scan_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; __u8 param; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE); if (!sent) - return; + return rp->status; param = *((__u8 *) sent); @@ -507,26 +474,25 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) done: hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_set_event_filter(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_set_event_filter *cp; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SCAN_ENABLE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT); if (!sent) - return; + return rp->status; cp = (struct hci_cp_set_event_filter *)sent; @@ -534,41 +500,39 @@ static void hci_cc_set_event_filter(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED); else hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED); + + return rp->status; } -static void hci_cc_read_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_class_of_dev(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_class_of_dev *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_class_of_dev *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; memcpy(hdev->dev_class, rp->dev_class, 3); bt_dev_dbg(hdev, "class 0x%.2x%.2x%.2x", hdev->dev_class[2], hdev->dev_class[1], hdev->dev_class[0]); + + return rp->status; } -static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_class_of_dev(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLASS_OF_DEV, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -579,26 +543,25 @@ static void hci_cc_write_class_of_dev(struct hci_dev *hdev, struct sk_buff *skb) mgmt_set_class_of_dev_complete(hdev, sent, rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_voice_setting(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_voice_setting *rp; + struct hci_rp_read_voice_setting *rp = data; __u16 setting; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_VOICE_SETTING, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; setting = __le16_to_cpu(rp->voice_setting); if (hdev->voice_setting == setting) - return; + return rp->status; hdev->voice_setting = setting; @@ -606,33 +569,30 @@ static void hci_cc_read_voice_setting(struct hci_dev *hdev, struct sk_buff *skb) if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); + + return rp->status; } -static void hci_cc_write_voice_setting(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_voice_setting(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; __u16 setting; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_VOICE_SETTING, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING); if (!sent) - return; + return rp->status; setting = get_unaligned_le16(sent); if (hdev->voice_setting == setting) - return; + return rp->status; hdev->voice_setting = setting; @@ -640,42 +600,38 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); + + return rp->status; } -static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_num_supported_iac(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_num_supported_iac *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_NUM_SUPPORTED_IAC, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_num_supported_iac *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->num_iac = rp->num_iac; bt_dev_dbg(hdev, "num iac %d", hdev->num_iac); + + return rp->status; } -static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_ssp_mode(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_write_ssp_mode *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_MODE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -694,22 +650,21 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_sc_support(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_write_sc_support *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SC_SUPPORT, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -728,20 +683,19 @@ static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_local_version(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_version *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_VERSION, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_version *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (hci_dev_test_flag(hdev, HCI_SETUP) || hci_dev_test_flag(hdev, HCI_CONFIG)) { @@ -751,43 +705,37 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) hdev->manufacturer = __le16_to_cpu(rp->manufacturer); hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); } + + return rp->status; } -static void hci_cc_read_local_commands(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_commands(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_commands *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_COMMANDS, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_commands *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (hci_dev_test_flag(hdev, HCI_SETUP) || hci_dev_test_flag(hdev, HCI_CONFIG)) memcpy(hdev->commands, rp->commands, sizeof(hdev->commands)); + + return rp->status; } -static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_auth_payload_to *rp; + struct hci_rp_read_auth_payload_to *rp = data; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_AUTH_PAYLOAD_TO, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_lock(hdev); @@ -796,27 +744,25 @@ static void hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, conn->auth_payload_timeout = __le16_to_cpu(rp->timeout); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_write_auth_payload_to *rp; + struct hci_rp_write_auth_payload_to *rp = data; struct hci_conn *conn; void *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_AUTH_PAYLOAD_TO, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -825,22 +771,19 @@ static void hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, conn->auth_payload_timeout = get_unaligned_le16(sent + 2); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_local_features(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_features(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_features *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_FEATURES, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_features *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; memcpy(hdev->features, rp->features, 8); @@ -880,60 +823,53 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, if (hdev->features[0][5] & LMP_EDR_3S_ESCO) hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5); + + return rp->status; } -static void hci_cc_read_local_ext_features(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_ext_features *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_EXT_FEATURES, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_ext_features *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (hdev->max_page < rp->max_page) hdev->max_page = rp->max_page; if (rp->page < HCI_MAX_PAGES) memcpy(hdev->features[rp->page], rp->features, 8); + + return rp->status; } -static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_flow_control_mode *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_FLOW_CONTROL_MODE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_flow_control_mode *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->flow_ctl_mode = rp->mode; + + return rp->status; } -static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_buffer_size *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BUFFER_SIZE, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_buffer_size *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu); hdev->sco_mtu = rp->sco_mtu; @@ -950,149 +886,130 @@ static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu, hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts); + + return rp->status; } -static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_bd_addr(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_bd_addr *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_BD_ADDR, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_bd_addr *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (test_bit(HCI_INIT, &hdev->flags)) bacpy(&hdev->bdaddr, &rp->bdaddr); if (hci_dev_test_flag(hdev, HCI_SETUP)) bacpy(&hdev->setup_addr, &rp->bdaddr); + + return rp->status; } -static void hci_cc_read_local_pairing_opts(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_pairing_opts(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_pairing_opts *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_PAIRING_OPTS, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_pairing_opts *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (hci_dev_test_flag(hdev, HCI_SETUP) || hci_dev_test_flag(hdev, HCI_CONFIG)) { hdev->pairing_opts = rp->pairing_opts; hdev->max_enc_key_size = rp->max_key_size; } + + return rp->status; } -static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_page_scan_activity(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_page_scan_activity *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_page_scan_activity *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (test_bit(HCI_INIT, &hdev->flags)) { hdev->page_scan_interval = __le16_to_cpu(rp->interval); hdev->page_scan_window = __le16_to_cpu(rp->window); } + + return rp->status; } -static void hci_cc_write_page_scan_activity(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_page_scan_activity(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_write_page_scan_activity *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_ACTIVITY, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY); if (!sent) - return; + return rp->status; hdev->page_scan_interval = __le16_to_cpu(sent->interval); hdev->page_scan_window = __le16_to_cpu(sent->window); + + return rp->status; } -static void hci_cc_read_page_scan_type(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_page_scan_type(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_page_scan_type *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_PAGE_SCAN_TYPE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_page_scan_type *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (test_bit(HCI_INIT, &hdev->flags)) hdev->page_scan_type = rp->type; + + return rp->status; } -static void hci_cc_write_page_scan_type(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; u8 *type; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_PAGE_SCAN_TYPE, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE); if (type) hdev->page_scan_type = *type; + + return rp->status; } -static void hci_cc_read_data_block_size(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_data_block_size *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DATA_BLOCK_SIZE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_data_block_size *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); hdev->block_len = __le16_to_cpu(rp->block_len); @@ -1102,24 +1019,21 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, hdev->block_cnt, hdev->block_len); + + return rp->status; } -static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_clock *rp; + struct hci_rp_read_clock *rp = data; struct hci_cp_read_clock *cp; struct hci_conn *conn; - BT_DBG("%s", hdev->name); - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_CLOCK, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_lock(hdev); @@ -1140,22 +1054,18 @@ static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) unlock: hci_dev_unlock(hdev); + return rp->status; } -static void hci_cc_read_local_amp_info(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_amp_info *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_AMP_INFO, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_amp_info *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->amp_status = rp->amp_status; hdev->amp_total_bw = __le32_to_cpu(rp->total_bw); @@ -1167,77 +1077,67 @@ static void hci_cc_read_local_amp_info(struct hci_dev *hdev, hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size); hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to); hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to); + + return rp->status; } -static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_inq_rsp_tx_power *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_INQ_RSP_TX_POWER, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_inq_rsp_tx_power *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->inq_tx_power = rp->tx_power; + + return rp->status; } -static void hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_def_err_data_reporting *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_DEF_ERR_DATA_REPORTING, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_def_err_data_reporting *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->err_data_reporting = rp->err_data_reporting; + + return rp->status; } -static void hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_write_def_err_data_reporting *cp; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING); if (!cp) - return; + return rp->status; hdev->err_data_reporting = cp->err_data_reporting; + + return rp->status; } -static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_pin_code_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_pin_code_reply *rp; + struct hci_rp_pin_code_reply *rp = data; struct hci_cp_pin_code_reply *cp; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_REPLY, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); hci_dev_lock(hdev); @@ -1258,15 +1158,13 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) unlock: hci_dev_unlock(hdev); + return rp->status; } -static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_pin_code_neg_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_pin_code_neg_reply *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_PIN_CODE_NEG_REPLY, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_pin_code_neg_reply *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1277,22 +1175,19 @@ static void hci_cc_pin_code_neg_reply(struct hci_dev *hdev, struct sk_buff *skb) rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_buffer_size *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_BUFFER_SIZE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_buffer_size *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->le_mtu = __le16_to_cpu(rp->le_mtu); hdev->le_pkts = rp->le_max_pkt; @@ -1300,51 +1195,44 @@ static void hci_cc_le_read_buffer_size(struct hci_dev *hdev, hdev->le_cnt = hdev->le_pkts; BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts); + + return rp->status; } -static void hci_cc_le_read_local_features(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_local_features(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_local_features *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_LOCAL_FEATURES, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_local_features *rp = data; BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); if (rp->status) - return; + return rp->status; memcpy(hdev->le_features, rp->features, 8); + + return rp->status; } -static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_adv_tx_power *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ADV_TX_POWER, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_adv_tx_power *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->adv_tx_power = rp->tx_power; + + return rp->status; } -static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_user_confirm_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_REPLY, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_user_confirm_reply *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1355,17 +1243,14 @@ static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_CONFIRM_NEG_REPLY, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_user_confirm_reply *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1376,15 +1261,14 @@ static void hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, ACL_LINK, 0, rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_user_passkey_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_REPLY, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_user_confirm_reply *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1395,16 +1279,14 @@ static void hci_cc_user_passkey_reply(struct hci_dev *hdev, struct sk_buff *skb) 0, rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_user_confirm_reply *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_USER_PASSKEY_NEG_REPLY, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_user_confirm_reply *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1415,49 +1297,44 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, ACL_LINK, 0, rp->status); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_local_oob_data(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_oob_data(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_oob_data *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_DATA, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_oob_data *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + return rp->status; } -static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_local_oob_ext_data *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_LOCAL_OOB_EXT_DATA, sizeof(*rp)); - if (!rp) - return; + struct hci_rp_read_local_oob_ext_data *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); + + return rp->status; } -static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_set_random_addr(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; bdaddr_t *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_RANDOM_ADDR, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -1470,25 +1347,24 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_set_default_phy(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_le_set_default_phy *cp; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_DEFAULT_PHY, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY); if (!cp) - return; + return rp->status; hci_dev_lock(hdev); @@ -1496,24 +1372,21 @@ static void hci_cc_le_set_default_phy(struct hci_dev *hdev, struct sk_buff *skb) hdev->le_rx_def_phys = cp->rx_phys; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_le_set_adv_set_rand_addr *cp; struct adv_info *adv; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_SET_RAND_ADDR, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR); /* Update only in case the adv instance since handle 0x00 shall be using @@ -1521,7 +1394,7 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, * non-extended adverting. */ if (!cp || !cp->handle) - return; + return rp->status; hci_dev_lock(hdev); @@ -1537,26 +1410,25 @@ static void hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_remove_adv_set(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; u8 *instance; int err; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_REMOVE_ADV_SET, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; instance = hci_sent_cmd_data(hdev, HCI_OP_LE_REMOVE_ADV_SET); if (!instance) - return; + return rp->status; hci_dev_lock(hdev); @@ -1566,25 +1438,24 @@ static void hci_cc_le_remove_adv_set(struct hci_dev *hdev, struct sk_buff *skb) *instance); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_clear_adv_sets(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct adv_info *adv, *n; int err; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ADV_SETS, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; if (!hci_sent_cmd_data(hdev, HCI_OP_LE_CLEAR_ADV_SETS)) - return; + return rp->status; hci_dev_lock(hdev); @@ -1598,44 +1469,40 @@ static void hci_cc_le_clear_adv_sets(struct hci_dev *hdev, struct sk_buff *skb) } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_read_transmit_power(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_transmit_power(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_transmit_power *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_TRANSMIT_POWER, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_transmit_power *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->min_le_tx_power = rp->min_le_tx_power; hdev->max_le_tx_power = rp->max_le_tx_power; + + return rp->status; } -static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_set_adv_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; __u8 *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_ENABLE, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -1657,29 +1524,26 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) } hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_ext_adv_enable *cp; struct hci_cp_ext_adv_set *set; struct adv_info *adv = NULL, *n; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_ENABLE, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE); if (!cp) - return; + return rp->status; set = (void *)cp->data; @@ -1726,53 +1590,48 @@ static void hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, unlock: hci_dev_unlock(hdev); + return rp->status; } -static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_le_set_scan_param(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_scan_param *cp; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_PARAM, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); if (!cp) - return; + return rp->status; hci_dev_lock(hdev); hdev->le_scan_type = cp->type; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_ext_scan_params *cp; - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; struct hci_cp_le_scan_phy_params *phy_param; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_PARAMS, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS); if (!cp) - return; + return rp->status; phy_param = (void *)cp->data; @@ -1781,6 +1640,8 @@ static void hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, hdev->le_scan_type = phy_param->type; hci_dev_unlock(hdev); + + return rp->status; } static bool has_pending_adv_report(struct hci_dev *hdev) @@ -1866,320 +1727,273 @@ static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable) hci_dev_unlock(hdev); } -static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_scan_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_scan_enable *cp; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_SCAN_ENABLE, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); if (!cp) - return; + return rp->status; le_set_scan_enable_complete(hdev, cp->enable); + + return rp->status; } -static void hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_ext_scan_enable *cp; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_SCAN_ENABLE, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE); if (!cp) - return; + return rp->status; le_set_scan_enable_complete(hdev, cp->enable); + + return rp->status; } -static void hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, +static u8 hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, void *data, struct sk_buff *skb) { - struct hci_rp_le_read_num_supported_adv_sets *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_num_supported_adv_sets *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x No of Adv sets %u", rp->status, rp->num_of_sets); if (rp->status) - return; + return rp->status; hdev->le_num_of_adv_sets = rp->num_of_sets; + + return rp->status; } -static void hci_cc_le_read_accept_list_size(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_accept_list_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_accept_list_size *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_ACCEPT_LIST_SIZE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_accept_list_size *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size); if (rp->status) - return; + return rp->status; hdev->le_accept_list_size = rp->size; + + return rp->status; } -static void hci_cc_le_clear_accept_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_clear_accept_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_ACCEPT_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_bdaddr_list_clear(&hdev->le_accept_list); + + return rp->status; } -static void hci_cc_le_add_to_accept_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_add_to_accept_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_add_to_accept_list *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_ACCEPT_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST); if (!sent) - return; + return rp->status; hci_bdaddr_list_add(&hdev->le_accept_list, &sent->bdaddr, sent->bdaddr_type); + + return rp->status; } -static void hci_cc_le_del_from_accept_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_del_from_accept_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_del_from_accept_list *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_ACCEPT_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST); if (!sent) - return; + return rp->status; hci_bdaddr_list_del(&hdev->le_accept_list, &sent->bdaddr, sent->bdaddr_type); + + return rp->status; } -static void hci_cc_le_read_supported_states(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_supported_states(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_supported_states *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_SUPPORTED_STATES, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_supported_states *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; memcpy(hdev->le_states, rp->le_states, 8); + + return rp->status; } -static void hci_cc_le_read_def_data_len(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_def_data_len(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_def_data_len *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_DEF_DATA_LEN, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_def_data_len *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->le_def_tx_len = le16_to_cpu(rp->tx_len); hdev->le_def_tx_time = le16_to_cpu(rp->tx_time); + + return rp->status; } -static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_write_def_data_len(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_write_def_data_len *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_WRITE_DEF_DATA_LEN, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN); if (!sent) - return; + return rp->status; hdev->le_def_tx_len = le16_to_cpu(sent->tx_len); hdev->le_def_tx_time = le16_to_cpu(sent->tx_time); + + return rp->status; } -static void hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_add_to_resolv_list *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_ADD_TO_RESOLV_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST); if (!sent) - return; + return rp->status; hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr, sent->bdaddr_type, sent->peer_irk, sent->local_irk); + + return rp->status; } -static void hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_del_from_resolv_list *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_DEL_FROM_RESOLV_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST); if (!sent) - return; + return rp->status; hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr, sent->bdaddr_type); + + return rp->status; } -static void hci_cc_le_clear_resolv_list(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_clear_resolv_list(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_CLEAR_RESOLV_LIST, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_bdaddr_list_clear(&hdev->le_resolv_list); + + return rp->status; } -static void hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_resolv_list_size *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_RESOLV_LIST_SIZE, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_resolv_list_size *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size); if (rp->status) - return; + return rp->status; hdev->le_resolv_list_size = rp->size; + + return rp->status; } -static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; __u8 *sent; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -2189,48 +2003,42 @@ static void hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_le_read_max_data_len(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_le_read_max_data_len(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_read_max_data_len *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_READ_MAX_DATA_LEN, - sizeof(*rp)); - if (!rp) - return; + struct hci_rp_le_read_max_data_len *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hdev->le_max_tx_len = le16_to_cpu(rp->tx_len); hdev->le_max_tx_time = le16_to_cpu(rp->tx_time); hdev->le_max_rx_len = le16_to_cpu(rp->rx_len); hdev->le_max_rx_time = le16_to_cpu(rp->rx_time); + + return rp->status; } -static void hci_cc_write_le_host_supported(struct hci_dev *hdev, - struct sk_buff *skb) +static u8 hci_cc_write_le_host_supported(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_write_le_host_supported *sent; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_LE_HOST_SUPPORTED, - sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -2249,50 +2057,47 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_set_adv_param(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_le_set_adv_param *cp; - struct hci_ev_status *rp; - - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_ADV_PARAM, sizeof(*rp)); - if (!rp) - return; + struct hci_ev_status *rp = data; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); if (!cp) - return; + return rp->status; hci_dev_lock(hdev); hdev->adv_addr_type = cp->own_address_type; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_set_ext_adv_param(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_le_set_ext_adv_params *rp; + struct hci_rp_le_set_ext_adv_params *rp = data; struct hci_cp_le_set_ext_adv_params *cp; struct adv_info *adv_instance; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_LE_SET_EXT_ADV_PARAMS, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS); if (!cp) - return; + return rp->status; hci_dev_lock(hdev); hdev->adv_addr_type = cp->own_addr_type; @@ -2308,21 +2113,20 @@ static void hci_cc_set_ext_adv_param(struct hci_dev *hdev, struct sk_buff *skb) hci_req_update_adv_data(hdev, cp->handle); hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_rssi(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_rp_read_rssi *rp; + struct hci_rp_read_rssi *rp = data; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_RSSI, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; hci_dev_lock(hdev); @@ -2331,26 +2135,25 @@ static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) conn->rssi = rp->rssi; hci_dev_unlock(hdev); + + return rp->status; } -static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_read_tx_power(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { struct hci_cp_read_tx_power *sent; - struct hci_rp_read_tx_power *rp; + struct hci_rp_read_tx_power *rp = data; struct hci_conn *conn; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_READ_TX_POWER, sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); if (!sent) - return; + return rp->status; hci_dev_lock(hdev); @@ -2369,26 +2172,25 @@ static void hci_cc_read_tx_power(struct hci_dev *hdev, struct sk_buff *skb) unlock: hci_dev_unlock(hdev); + return rp->status; } -static void hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, struct sk_buff *skb) +static u8 hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, void *data, + struct sk_buff *skb) { - struct hci_ev_status *rp; + struct hci_ev_status *rp = data; u8 *mode; - rp = hci_cc_skb_pull(hdev, skb, HCI_OP_WRITE_SSP_DEBUG_MODE, - sizeof(*rp)); - if (!rp) - return; - bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); if (rp->status) - return; + return rp->status; mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE); if (mode) hdev->ssp_debug_mode = *mode; + + return rp->status; } static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) @@ -3909,372 +3711,226 @@ static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd) } } -static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data, - struct sk_buff *skb, u16 *opcode, u8 *status, - hci_req_complete_t *req_complete, - hci_req_complete_skb_t *req_complete_skb) -{ - struct hci_ev_cmd_complete *ev = data; - - *opcode = __le16_to_cpu(ev->opcode); - *status = skb->data[0]; - - switch (*opcode) { - case HCI_OP_INQUIRY_CANCEL: - hci_cc_inquiry_cancel(hdev, skb, status); - break; - - case HCI_OP_PERIODIC_INQ: - hci_cc_periodic_inq(hdev, skb); - break; - - case HCI_OP_EXIT_PERIODIC_INQ: - hci_cc_exit_periodic_inq(hdev, skb); - break; - - case HCI_OP_REMOTE_NAME_REQ_CANCEL: - hci_cc_remote_name_req_cancel(hdev, skb); - break; - - case HCI_OP_ROLE_DISCOVERY: - hci_cc_role_discovery(hdev, skb); - break; - - case HCI_OP_READ_LINK_POLICY: - hci_cc_read_link_policy(hdev, skb); - break; - - case HCI_OP_WRITE_LINK_POLICY: - hci_cc_write_link_policy(hdev, skb); - break; - - case HCI_OP_READ_DEF_LINK_POLICY: - hci_cc_read_def_link_policy(hdev, skb); - break; - - case HCI_OP_WRITE_DEF_LINK_POLICY: - hci_cc_write_def_link_policy(hdev, skb); - break; - - case HCI_OP_RESET: - hci_cc_reset(hdev, skb); - break; - - case HCI_OP_READ_STORED_LINK_KEY: - hci_cc_read_stored_link_key(hdev, skb); - break; - - case HCI_OP_DELETE_STORED_LINK_KEY: - hci_cc_delete_stored_link_key(hdev, skb); - break; - - case HCI_OP_WRITE_LOCAL_NAME: - hci_cc_write_local_name(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_NAME: - hci_cc_read_local_name(hdev, skb); - break; - - case HCI_OP_WRITE_AUTH_ENABLE: - hci_cc_write_auth_enable(hdev, skb); - break; - - case HCI_OP_WRITE_ENCRYPT_MODE: - hci_cc_write_encrypt_mode(hdev, skb); - break; - - case HCI_OP_WRITE_SCAN_ENABLE: - hci_cc_write_scan_enable(hdev, skb); - break; - - case HCI_OP_SET_EVENT_FLT: - hci_cc_set_event_filter(hdev, skb); - break; - - case HCI_OP_READ_CLASS_OF_DEV: - hci_cc_read_class_of_dev(hdev, skb); - break; - - case HCI_OP_WRITE_CLASS_OF_DEV: - hci_cc_write_class_of_dev(hdev, skb); - break; - - case HCI_OP_READ_VOICE_SETTING: - hci_cc_read_voice_setting(hdev, skb); - break; - - case HCI_OP_WRITE_VOICE_SETTING: - hci_cc_write_voice_setting(hdev, skb); - break; - - case HCI_OP_READ_NUM_SUPPORTED_IAC: - hci_cc_read_num_supported_iac(hdev, skb); - break; - - case HCI_OP_WRITE_SSP_MODE: - hci_cc_write_ssp_mode(hdev, skb); - break; - - case HCI_OP_WRITE_SC_SUPPORT: - hci_cc_write_sc_support(hdev, skb); - break; - - case HCI_OP_READ_AUTH_PAYLOAD_TO: - hci_cc_read_auth_payload_timeout(hdev, skb); - break; - - case HCI_OP_WRITE_AUTH_PAYLOAD_TO: - hci_cc_write_auth_payload_timeout(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_VERSION: - hci_cc_read_local_version(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_COMMANDS: - hci_cc_read_local_commands(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_FEATURES: - hci_cc_read_local_features(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_EXT_FEATURES: - hci_cc_read_local_ext_features(hdev, skb); - break; - - case HCI_OP_READ_BUFFER_SIZE: - hci_cc_read_buffer_size(hdev, skb); - break; - - case HCI_OP_READ_BD_ADDR: - hci_cc_read_bd_addr(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_PAIRING_OPTS: - hci_cc_read_local_pairing_opts(hdev, skb); - break; - - case HCI_OP_READ_PAGE_SCAN_ACTIVITY: - hci_cc_read_page_scan_activity(hdev, skb); - break; - - case HCI_OP_WRITE_PAGE_SCAN_ACTIVITY: - hci_cc_write_page_scan_activity(hdev, skb); - break; - - case HCI_OP_READ_PAGE_SCAN_TYPE: - hci_cc_read_page_scan_type(hdev, skb); - break; - - case HCI_OP_WRITE_PAGE_SCAN_TYPE: - hci_cc_write_page_scan_type(hdev, skb); - break; - - case HCI_OP_READ_DATA_BLOCK_SIZE: - hci_cc_read_data_block_size(hdev, skb); - break; - - case HCI_OP_READ_FLOW_CONTROL_MODE: - hci_cc_read_flow_control_mode(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_AMP_INFO: - hci_cc_read_local_amp_info(hdev, skb); - break; - - case HCI_OP_READ_CLOCK: - hci_cc_read_clock(hdev, skb); - break; - - case HCI_OP_READ_INQ_RSP_TX_POWER: - hci_cc_read_inq_rsp_tx_power(hdev, skb); - break; - - case HCI_OP_READ_DEF_ERR_DATA_REPORTING: - hci_cc_read_def_err_data_reporting(hdev, skb); - break; - - case HCI_OP_WRITE_DEF_ERR_DATA_REPORTING: - hci_cc_write_def_err_data_reporting(hdev, skb); - break; - - case HCI_OP_PIN_CODE_REPLY: - hci_cc_pin_code_reply(hdev, skb); - break; - - case HCI_OP_PIN_CODE_NEG_REPLY: - hci_cc_pin_code_neg_reply(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_OOB_DATA: - hci_cc_read_local_oob_data(hdev, skb); - break; - - case HCI_OP_READ_LOCAL_OOB_EXT_DATA: - hci_cc_read_local_oob_ext_data(hdev, skb); - break; - - case HCI_OP_LE_READ_BUFFER_SIZE: - hci_cc_le_read_buffer_size(hdev, skb); - break; - - case HCI_OP_LE_READ_LOCAL_FEATURES: - hci_cc_le_read_local_features(hdev, skb); - break; - - case HCI_OP_LE_READ_ADV_TX_POWER: - hci_cc_le_read_adv_tx_power(hdev, skb); - break; - - case HCI_OP_USER_CONFIRM_REPLY: - hci_cc_user_confirm_reply(hdev, skb); - break; - - case HCI_OP_USER_CONFIRM_NEG_REPLY: - hci_cc_user_confirm_neg_reply(hdev, skb); - break; - - case HCI_OP_USER_PASSKEY_REPLY: - hci_cc_user_passkey_reply(hdev, skb); - break; - - case HCI_OP_USER_PASSKEY_NEG_REPLY: - hci_cc_user_passkey_neg_reply(hdev, skb); - break; - - case HCI_OP_LE_SET_RANDOM_ADDR: - hci_cc_le_set_random_addr(hdev, skb); - break; - - case HCI_OP_LE_SET_ADV_ENABLE: - hci_cc_le_set_adv_enable(hdev, skb); - break; - - case HCI_OP_LE_SET_SCAN_PARAM: - hci_cc_le_set_scan_param(hdev, skb); - break; - - case HCI_OP_LE_SET_SCAN_ENABLE: - hci_cc_le_set_scan_enable(hdev, skb); - break; - - case HCI_OP_LE_READ_ACCEPT_LIST_SIZE: - hci_cc_le_read_accept_list_size(hdev, skb); - break; - - case HCI_OP_LE_CLEAR_ACCEPT_LIST: - hci_cc_le_clear_accept_list(hdev, skb); - break; - - case HCI_OP_LE_ADD_TO_ACCEPT_LIST: - hci_cc_le_add_to_accept_list(hdev, skb); - break; - - case HCI_OP_LE_DEL_FROM_ACCEPT_LIST: - hci_cc_le_del_from_accept_list(hdev, skb); - break; - - case HCI_OP_LE_READ_SUPPORTED_STATES: - hci_cc_le_read_supported_states(hdev, skb); - break; - - case HCI_OP_LE_READ_DEF_DATA_LEN: - hci_cc_le_read_def_data_len(hdev, skb); - break; - - case HCI_OP_LE_WRITE_DEF_DATA_LEN: - hci_cc_le_write_def_data_len(hdev, skb); - break; - - case HCI_OP_LE_ADD_TO_RESOLV_LIST: - hci_cc_le_add_to_resolv_list(hdev, skb); - break; - - case HCI_OP_LE_DEL_FROM_RESOLV_LIST: - hci_cc_le_del_from_resolv_list(hdev, skb); - break; - - case HCI_OP_LE_CLEAR_RESOLV_LIST: - hci_cc_le_clear_resolv_list(hdev, skb); - break; - - case HCI_OP_LE_READ_RESOLV_LIST_SIZE: - hci_cc_le_read_resolv_list_size(hdev, skb); - break; - - case HCI_OP_LE_SET_ADDR_RESOLV_ENABLE: - hci_cc_le_set_addr_resolution_enable(hdev, skb); - break; - - case HCI_OP_LE_READ_MAX_DATA_LEN: - hci_cc_le_read_max_data_len(hdev, skb); - break; - - case HCI_OP_WRITE_LE_HOST_SUPPORTED: - hci_cc_write_le_host_supported(hdev, skb); - break; - - case HCI_OP_LE_SET_ADV_PARAM: - hci_cc_set_adv_param(hdev, skb); - break; - - case HCI_OP_READ_RSSI: - hci_cc_read_rssi(hdev, skb); - break; - - case HCI_OP_READ_TX_POWER: - hci_cc_read_tx_power(hdev, skb); - break; +#define HCI_CC_VL(_op, _func, _min, _max) \ +{ \ + .op = _op, \ + .func = _func, \ + .min_len = _min, \ + .max_len = _max, \ +} - case HCI_OP_WRITE_SSP_DEBUG_MODE: - hci_cc_write_ssp_debug_mode(hdev, skb); - break; +#define HCI_CC(_op, _func, _len) \ + HCI_CC_VL(_op, _func, _len, _len) - case HCI_OP_LE_SET_EXT_SCAN_PARAMS: - hci_cc_le_set_ext_scan_param(hdev, skb); - break; +#define HCI_CC_STATUS(_op, _func) \ + HCI_CC(_op, _func, sizeof(struct hci_ev_status)) - case HCI_OP_LE_SET_EXT_SCAN_ENABLE: - hci_cc_le_set_ext_scan_enable(hdev, skb); - break; +static const struct hci_cc { + u16 op; + u8 (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb); + u16 min_len; + u16 max_len; +} hci_cc_table[] = { + HCI_CC_STATUS(HCI_OP_INQUIRY_CANCEL, hci_cc_inquiry_cancel), + HCI_CC_STATUS(HCI_OP_PERIODIC_INQ, hci_cc_periodic_inq), + HCI_CC_STATUS(HCI_OP_EXIT_PERIODIC_INQ, hci_cc_exit_periodic_inq), + HCI_CC_STATUS(HCI_OP_REMOTE_NAME_REQ_CANCEL, + hci_cc_remote_name_req_cancel), + HCI_CC(HCI_OP_ROLE_DISCOVERY, hci_cc_role_discovery, + sizeof(struct hci_rp_role_discovery)), + HCI_CC(HCI_OP_READ_LINK_POLICY, hci_cc_read_link_policy, + sizeof(struct hci_rp_read_link_policy)), + HCI_CC(HCI_OP_WRITE_LINK_POLICY, hci_cc_write_link_policy, + sizeof(struct hci_rp_write_link_policy)), + HCI_CC(HCI_OP_READ_DEF_LINK_POLICY, hci_cc_read_def_link_policy, + sizeof(struct hci_rp_read_def_link_policy)), + HCI_CC_STATUS(HCI_OP_WRITE_DEF_LINK_POLICY, + hci_cc_write_def_link_policy), + HCI_CC_STATUS(HCI_OP_RESET, hci_cc_reset), + HCI_CC(HCI_OP_READ_STORED_LINK_KEY, hci_cc_read_stored_link_key, + sizeof(struct hci_rp_read_stored_link_key)), + HCI_CC(HCI_OP_DELETE_STORED_LINK_KEY, hci_cc_delete_stored_link_key, + sizeof(struct hci_rp_delete_stored_link_key)), + HCI_CC_STATUS(HCI_OP_WRITE_LOCAL_NAME, hci_cc_write_local_name), + HCI_CC(HCI_OP_READ_LOCAL_NAME, hci_cc_read_local_name, + sizeof(struct hci_rp_read_local_name)), + HCI_CC_STATUS(HCI_OP_WRITE_AUTH_ENABLE, hci_cc_write_auth_enable), + HCI_CC_STATUS(HCI_OP_WRITE_ENCRYPT_MODE, hci_cc_write_encrypt_mode), + HCI_CC_STATUS(HCI_OP_WRITE_SCAN_ENABLE, hci_cc_write_scan_enable), + HCI_CC_STATUS(HCI_OP_SET_EVENT_FLT, hci_cc_set_event_filter), + HCI_CC(HCI_OP_READ_CLASS_OF_DEV, hci_cc_read_class_of_dev, + sizeof(struct hci_rp_read_class_of_dev)), + HCI_CC_STATUS(HCI_OP_WRITE_CLASS_OF_DEV, hci_cc_write_class_of_dev), + HCI_CC(HCI_OP_READ_VOICE_SETTING, hci_cc_read_voice_setting, + sizeof(struct hci_rp_read_voice_setting)), + HCI_CC_STATUS(HCI_OP_WRITE_VOICE_SETTING, hci_cc_write_voice_setting), + HCI_CC(HCI_OP_READ_NUM_SUPPORTED_IAC, hci_cc_read_num_supported_iac, + sizeof(struct hci_rp_read_num_supported_iac)), + HCI_CC_STATUS(HCI_OP_WRITE_SSP_MODE, hci_cc_write_ssp_mode), + HCI_CC_STATUS(HCI_OP_WRITE_SC_SUPPORT, hci_cc_write_sc_support), + HCI_CC(HCI_OP_READ_AUTH_PAYLOAD_TO, hci_cc_read_auth_payload_timeout, + sizeof(struct hci_rp_read_auth_payload_to)), + HCI_CC(HCI_OP_WRITE_AUTH_PAYLOAD_TO, hci_cc_write_auth_payload_timeout, + sizeof(struct hci_rp_write_auth_payload_to)), + HCI_CC(HCI_OP_READ_LOCAL_VERSION, hci_cc_read_local_version, + sizeof(struct hci_rp_read_local_version)), + HCI_CC(HCI_OP_READ_LOCAL_COMMANDS, hci_cc_read_local_commands, + sizeof(struct hci_rp_read_local_commands)), + HCI_CC(HCI_OP_READ_LOCAL_FEATURES, hci_cc_read_local_features, + sizeof(struct hci_rp_read_local_features)), + HCI_CC(HCI_OP_READ_LOCAL_EXT_FEATURES, hci_cc_read_local_ext_features, + sizeof(struct hci_rp_read_local_ext_features)), + HCI_CC(HCI_OP_READ_BUFFER_SIZE, hci_cc_read_buffer_size, + sizeof(struct hci_rp_read_buffer_size)), + HCI_CC(HCI_OP_READ_BD_ADDR, hci_cc_read_bd_addr, + sizeof(struct hci_rp_read_bd_addr)), + HCI_CC(HCI_OP_READ_LOCAL_PAIRING_OPTS, hci_cc_read_local_pairing_opts, + sizeof(struct hci_rp_read_local_pairing_opts)), + HCI_CC(HCI_OP_READ_PAGE_SCAN_ACTIVITY, hci_cc_read_page_scan_activity, + sizeof(struct hci_rp_read_page_scan_activity)), + HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, + hci_cc_write_page_scan_activity), + HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type, + sizeof(struct hci_rp_read_page_scan_type)), + HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type), + HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size, + sizeof(struct hci_rp_read_data_block_size)), + HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode, + sizeof(struct hci_rp_read_flow_control_mode)), + HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info, + sizeof(struct hci_rp_read_local_amp_info)), + HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock, + sizeof(struct hci_rp_read_clock)), + HCI_CC(HCI_OP_READ_INQ_RSP_TX_POWER, hci_cc_read_inq_rsp_tx_power, + sizeof(struct hci_rp_read_inq_rsp_tx_power)), + HCI_CC(HCI_OP_READ_DEF_ERR_DATA_REPORTING, + hci_cc_read_def_err_data_reporting, + sizeof(struct hci_rp_read_def_err_data_reporting)), + HCI_CC_STATUS(HCI_OP_WRITE_DEF_ERR_DATA_REPORTING, + hci_cc_write_def_err_data_reporting), + HCI_CC(HCI_OP_PIN_CODE_REPLY, hci_cc_pin_code_reply, + sizeof(struct hci_rp_pin_code_reply)), + HCI_CC(HCI_OP_PIN_CODE_NEG_REPLY, hci_cc_pin_code_neg_reply, + sizeof(struct hci_rp_pin_code_neg_reply)), + HCI_CC(HCI_OP_READ_LOCAL_OOB_DATA, hci_cc_read_local_oob_data, + sizeof(struct hci_rp_read_local_oob_data)), + HCI_CC(HCI_OP_READ_LOCAL_OOB_EXT_DATA, hci_cc_read_local_oob_ext_data, + sizeof(struct hci_rp_read_local_oob_ext_data)), + HCI_CC(HCI_OP_LE_READ_BUFFER_SIZE, hci_cc_le_read_buffer_size, + sizeof(struct hci_rp_le_read_buffer_size)), + HCI_CC(HCI_OP_LE_READ_LOCAL_FEATURES, hci_cc_le_read_local_features, + sizeof(struct hci_rp_le_read_local_features)), + HCI_CC(HCI_OP_LE_READ_ADV_TX_POWER, hci_cc_le_read_adv_tx_power, + sizeof(struct hci_rp_le_read_adv_tx_power)), + HCI_CC(HCI_OP_USER_CONFIRM_REPLY, hci_cc_user_confirm_reply, + sizeof(struct hci_rp_user_confirm_reply)), + HCI_CC(HCI_OP_USER_CONFIRM_NEG_REPLY, hci_cc_user_confirm_neg_reply, + sizeof(struct hci_rp_user_confirm_reply)), + HCI_CC(HCI_OP_USER_PASSKEY_REPLY, hci_cc_user_passkey_reply, + sizeof(struct hci_rp_user_confirm_reply)), + HCI_CC(HCI_OP_USER_PASSKEY_NEG_REPLY, hci_cc_user_passkey_neg_reply, + sizeof(struct hci_rp_user_confirm_reply)), + HCI_CC_STATUS(HCI_OP_LE_SET_RANDOM_ADDR, hci_cc_le_set_random_addr), + HCI_CC_STATUS(HCI_OP_LE_SET_ADV_ENABLE, hci_cc_le_set_adv_enable), + HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_PARAM, hci_cc_le_set_scan_param), + HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_ENABLE, hci_cc_le_set_scan_enable), + HCI_CC(HCI_OP_LE_READ_ACCEPT_LIST_SIZE, + hci_cc_le_read_accept_list_size, + sizeof(struct hci_rp_le_read_accept_list_size)), + HCI_CC_STATUS(HCI_OP_LE_CLEAR_ACCEPT_LIST, hci_cc_le_clear_accept_list), + HCI_CC_STATUS(HCI_OP_LE_ADD_TO_ACCEPT_LIST, + hci_cc_le_add_to_accept_list), + HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_ACCEPT_LIST, + hci_cc_le_del_from_accept_list), + HCI_CC(HCI_OP_LE_READ_SUPPORTED_STATES, hci_cc_le_read_supported_states, + sizeof(struct hci_rp_le_read_supported_states)), + HCI_CC(HCI_OP_LE_READ_DEF_DATA_LEN, hci_cc_le_read_def_data_len, + sizeof(struct hci_rp_le_read_def_data_len)), + HCI_CC_STATUS(HCI_OP_LE_WRITE_DEF_DATA_LEN, + hci_cc_le_write_def_data_len), + HCI_CC_STATUS(HCI_OP_LE_ADD_TO_RESOLV_LIST, + hci_cc_le_add_to_resolv_list), + HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_RESOLV_LIST, + hci_cc_le_del_from_resolv_list), + HCI_CC_STATUS(HCI_OP_LE_CLEAR_RESOLV_LIST, + hci_cc_le_clear_resolv_list), + HCI_CC(HCI_OP_LE_READ_RESOLV_LIST_SIZE, hci_cc_le_read_resolv_list_size, + sizeof(struct hci_rp_le_read_resolv_list_size)), + HCI_CC_STATUS(HCI_OP_LE_SET_ADDR_RESOLV_ENABLE, + hci_cc_le_set_addr_resolution_enable), + HCI_CC(HCI_OP_LE_READ_MAX_DATA_LEN, hci_cc_le_read_max_data_len, + sizeof(struct hci_rp_le_read_max_data_len)), + HCI_CC_STATUS(HCI_OP_WRITE_LE_HOST_SUPPORTED, + hci_cc_write_le_host_supported), + HCI_CC_STATUS(HCI_OP_LE_SET_ADV_PARAM, hci_cc_set_adv_param), + HCI_CC(HCI_OP_READ_RSSI, hci_cc_read_rssi, + sizeof(struct hci_rp_read_rssi)), + HCI_CC(HCI_OP_READ_TX_POWER, hci_cc_read_tx_power, + sizeof(struct hci_rp_read_tx_power)), + HCI_CC_STATUS(HCI_OP_WRITE_SSP_DEBUG_MODE, hci_cc_write_ssp_debug_mode), + HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_PARAMS, + hci_cc_le_set_ext_scan_param), + HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_ENABLE, + hci_cc_le_set_ext_scan_enable), + HCI_CC_STATUS(HCI_OP_LE_SET_DEFAULT_PHY, hci_cc_le_set_default_phy), + HCI_CC(HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS, + hci_cc_le_read_num_adv_sets, + sizeof(struct hci_rp_le_read_num_supported_adv_sets)), + HCI_CC(HCI_OP_LE_SET_EXT_ADV_PARAMS, hci_cc_set_ext_adv_param, + sizeof(struct hci_rp_le_set_ext_adv_params)), + HCI_CC_STATUS(HCI_OP_LE_SET_EXT_ADV_ENABLE, + hci_cc_le_set_ext_adv_enable), + HCI_CC_STATUS(HCI_OP_LE_SET_ADV_SET_RAND_ADDR, + hci_cc_le_set_adv_set_random_addr), + HCI_CC_STATUS(HCI_OP_LE_REMOVE_ADV_SET, hci_cc_le_remove_adv_set), + HCI_CC_STATUS(HCI_OP_LE_CLEAR_ADV_SETS, hci_cc_le_clear_adv_sets), + HCI_CC(HCI_OP_LE_READ_TRANSMIT_POWER, hci_cc_le_read_transmit_power, + sizeof(struct hci_rp_le_read_transmit_power)) +}; - case HCI_OP_LE_SET_DEFAULT_PHY: - hci_cc_le_set_default_phy(hdev, skb); - break; +static u8 hci_cc_func(struct hci_dev *hdev, const struct hci_cc *cc, + struct sk_buff *skb) +{ + void *data; - case HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS: - hci_cc_le_read_num_adv_sets(hdev, skb); - break; + if (skb->len < cc->min_len) { + bt_dev_err(hdev, "unexpected cc 0x%4.4x length: %u < %u", + cc->op, skb->len, cc->min_len); + return HCI_ERROR_UNSPECIFIED; + } - case HCI_OP_LE_SET_EXT_ADV_PARAMS: - hci_cc_set_ext_adv_param(hdev, skb); - break; + /* Just warn if the length is over max_len size it still be possible to + * partially parse the cc so leave to callback to decide if that is + * acceptable. + */ + if (skb->len > cc->max_len) + bt_dev_warn(hdev, "unexpected cc 0x%4.4x length: %u > %u", + cc->op, skb->len, cc->max_len); - case HCI_OP_LE_SET_EXT_ADV_ENABLE: - hci_cc_le_set_ext_adv_enable(hdev, skb); - break; + data = hci_cc_skb_pull(hdev, skb, cc->op, cc->min_len); + if (!data) + return HCI_ERROR_UNSPECIFIED; - case HCI_OP_LE_SET_ADV_SET_RAND_ADDR: - hci_cc_le_set_adv_set_random_addr(hdev, skb); - break; + return cc->func(hdev, data, skb); +} - case HCI_OP_LE_REMOVE_ADV_SET: - hci_cc_le_remove_adv_set(hdev, skb); - break; +static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data, + struct sk_buff *skb, u16 *opcode, u8 *status, + hci_req_complete_t *req_complete, + hci_req_complete_skb_t *req_complete_skb) +{ + struct hci_ev_cmd_complete *ev = data; + int i; - case HCI_OP_LE_CLEAR_ADV_SETS: - hci_cc_le_clear_adv_sets(hdev, skb); - break; + *opcode = __le16_to_cpu(ev->opcode); - case HCI_OP_LE_READ_TRANSMIT_POWER: - hci_cc_le_read_transmit_power(hdev, skb); - break; + bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode); - default: - BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); - break; + for (i = 0; i < ARRAY_SIZE(hci_cc_table); i++) { + if (hci_cc_table[i].op == *opcode) { + *status = hci_cc_func(hdev, &hci_cc_table[i], skb); + break; + } } handle_cmd_cnt_and_timer(hdev, ev->ncmd); From patchwork Wed Dec 1 18:55:06 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Augusto von Dentz X-Patchwork-Id: 519394 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 58D74C433EF for ; Wed, 1 Dec 2021 18:55:39 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1352620AbhLAS6y (ORCPT ); Wed, 1 Dec 2021 13:58:54 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:51540 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244351AbhLAS6l (ORCPT ); Wed, 1 Dec 2021 13:58:41 -0500 Received: from mail-pg1-x52f.google.com (mail-pg1-x52f.google.com [IPv6:2607:f8b0:4864:20::52f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 7EAF3C061574 for ; Wed, 1 Dec 2021 10:55:20 -0800 (PST) Received: by mail-pg1-x52f.google.com with SMTP id l190so24576549pge.7 for ; Wed, 01 Dec 2021 10:55:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=fPIfCP+f2YQy1I1YODv32kv9aALly5W7RjMOlxfRVJk=; b=TnUGGaPyflDB8FFNh5nCQ0JKnWACD1WpRVKmvCtze6GWCO0cECHMuzJryn8zakED6Z 8UtQZ1U0fMiJlZw6YNu06GSdcJshAApetjaP8BfgePppQ7W6N8B+JjaaQrq0ommmuWU8 djMDgYvUBV7dO0OWiHLEwQh0/MPGBnU5PUDNTvsQANQ2JgXEekOMY/Z55B1+eCqNB83I jy+ZL0YAASbWpJk/hWbzJU4ocdCUr/rkdEWH7D1bmr93CProOb+tqHQW3gyDJniG5/Dk a86b2snwWNOaIEAC8gCzuWsFz5yAxdUBtdCaGKAyVrB4e8cMOXtiLs95L54DQ78YtfNk U18A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=fPIfCP+f2YQy1I1YODv32kv9aALly5W7RjMOlxfRVJk=; b=nyzCSfgBSuYv/fF92LaHe8NsEkIIa82Z/Bauzqpi9ATsCZBg8q6xCP9sdsIvuQhdkX IasDgCEh+oW+alSWRBlI8jzBIC88ngUgnBXc6a9kyyW9fGQYEFc66sQoI/aFjrObYjhu SAqb6zoIR/Iy5E6RnBmBDXHfjdhHly37hNZwhDCYLldm4tyj/IYz1mK2M/bDioRA4fgX 964qK0NIA6cnGkY91IAwZmnqW+QGhFAVsof2jpTN2rpx++lTnSSFEBp9ztNqPi14dhkz EifOnwjD4/8WF0WFpO5494dezQzFG5ApIXt+ZgDoG3e1Sf8y3Hx3yYkwFL0LhsqxCvvA LLuw== X-Gm-Message-State: AOAM531Ii/wNQBBW8jaIrqJxtpC+F2V2xzY+hQVk+sZFEIIIG+XmRQAV yozm6noBF3pPgqX6nXufBdA3jmKdHrY= X-Google-Smtp-Source: ABdhPJx0i2xhobqpx2C8maHH6E+mTae3a/wE8u0QyJWcVp2qn5H3ejgFkZ3E0UXUjhWxH+cLtVNBww== X-Received: by 2002:a63:90c8:: with SMTP id a191mr6173779pge.400.1638384919598; Wed, 01 Dec 2021 10:55:19 -0800 (PST) Received: from lvondent-mobl4.intel.com (c-71-56-157-77.hsd1.or.comcast.net. [71.56.157.77]) by smtp.gmail.com with ESMTPSA id e19sm359391pgt.49.2021.12.01.10.55.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 01 Dec 2021 10:55:19 -0800 (PST) From: Luiz Augusto von Dentz To: linux-bluetooth@vger.kernel.org Subject: [PATCH v2 15/15] Bluetooth: hci_event: Use of a function table to handle Command Status Date: Wed, 1 Dec 2021 10:55:06 -0800 Message-Id: <20211201185506.1421186-16-luiz.dentz@gmail.com> X-Mailer: git-send-email 2.33.1 In-Reply-To: <20211201185506.1421186-1-luiz.dentz@gmail.com> References: <20211201185506.1421186-1-luiz.dentz@gmail.com> MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-bluetooth@vger.kernel.org From: Luiz Augusto von Dentz This change the use of switch statement to a function table which is easier to extend. Signed-off-by: Luiz Augusto von Dentz --- net/bluetooth/hci_event.c | 152 +++++++++++++++----------------------- 1 file changed, 59 insertions(+), 93 deletions(-) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 313b7b79d5b5..df1aca5f28da 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2195,7 +2195,7 @@ static u8 hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, void *data, static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status) { - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (status) { hci_conn_check_pending(hdev); @@ -2210,7 +2210,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) struct hci_cp_create_conn *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN); if (!cp) @@ -2220,7 +2220,7 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); - BT_DBG("%s bdaddr %pMR hcon %p", hdev->name, &cp->bdaddr, conn); + bt_dev_dbg(hdev, "bdaddr %pMR hcon %p", &cp->bdaddr, conn); if (status) { if (conn && conn->state == BT_CONNECT) { @@ -2249,7 +2249,7 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) struct hci_conn *acl, *sco; __u16 handle; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2260,7 +2260,7 @@ static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status) handle = __le16_to_cpu(cp->handle); - BT_DBG("%s handle 0x%4.4x", hdev->name, handle); + bt_dev_dbg(hdev, "handle 0x%4.4x", handle); hci_dev_lock(hdev); @@ -2283,7 +2283,7 @@ static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status) struct hci_cp_auth_requested *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2310,7 +2310,7 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) struct hci_cp_set_conn_encrypt *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2446,7 +2446,7 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) struct hci_cp_remote_name_req *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); /* If successful wait for the name req complete event before * checking for the need to do authentication */ @@ -2489,7 +2489,7 @@ static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) struct hci_cp_read_remote_features *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2516,7 +2516,7 @@ static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status) struct hci_cp_read_remote_ext_features *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2544,7 +2544,7 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) struct hci_conn *acl, *sco; __u16 handle; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2555,7 +2555,7 @@ static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status) handle = __le16_to_cpu(cp->handle); - BT_DBG("%s handle 0x%4.4x", hdev->name, handle); + bt_dev_dbg(hdev, "handle 0x%4.4x", handle); hci_dev_lock(hdev); @@ -2613,7 +2613,7 @@ static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status) struct hci_cp_sniff_mode *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2640,7 +2640,7 @@ static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status) struct hci_cp_exit_sniff_mode *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2669,6 +2669,8 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) struct hci_conn *conn; bool mgmt_conn; + bt_dev_dbg(hdev, "status 0x%2.2x", status); + /* Wait for HCI_EV_DISCONN_COMPLETE if status 0x00 and not suspended * otherwise cleanup the connection immediately. */ @@ -2802,7 +2804,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) { struct hci_cp_le_create_conn *cp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); /* All connection failure handling is taken care of by the * hci_le_conn_failed function which is triggered by the HCI @@ -2827,7 +2829,7 @@ static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status) { struct hci_cp_le_ext_create_conn *cp; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); /* All connection failure handling is taken care of by the * hci_le_conn_failed function which is triggered by the HCI @@ -2853,7 +2855,7 @@ static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status) struct hci_cp_le_read_remote_features *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -2880,7 +2882,7 @@ static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) struct hci_cp_le_start_enc *cp; struct hci_conn *conn; - BT_DBG("%s status 0x%2.2x", hdev->name, status); + bt_dev_dbg(hdev, "status 0x%2.2x", status); if (!status) return; @@ -3948,92 +3950,56 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data, queue_work(hdev->workqueue, &hdev->cmd_work); } +#define HCI_CS(_op, _func) \ +{ \ + .op = _op, \ + .func = _func, \ +} + +static const struct hci_cs { + u16 op; + void (*func)(struct hci_dev *hdev, __u8 status); +} hci_cs_table[] = { + HCI_CS(HCI_OP_INQUIRY, hci_cs_inquiry), + HCI_CS(HCI_OP_CREATE_CONN, hci_cs_create_conn), + HCI_CS(HCI_OP_DISCONNECT, hci_cs_disconnect), + HCI_CS(HCI_OP_ADD_SCO, hci_cs_add_sco), + HCI_CS(HCI_OP_AUTH_REQUESTED, hci_cs_auth_requested), + HCI_CS(HCI_OP_SET_CONN_ENCRYPT, hci_cs_set_conn_encrypt), + HCI_CS(HCI_OP_REMOTE_NAME_REQ, hci_cs_remote_name_req), + HCI_CS(HCI_OP_READ_REMOTE_FEATURES, hci_cs_read_remote_features), + HCI_CS(HCI_OP_READ_REMOTE_EXT_FEATURES, + hci_cs_read_remote_ext_features), + HCI_CS(HCI_OP_SETUP_SYNC_CONN, hci_cs_setup_sync_conn), + HCI_CS(HCI_OP_ENHANCED_SETUP_SYNC_CONN, + hci_cs_enhanced_setup_sync_conn), + HCI_CS(HCI_OP_SNIFF_MODE, hci_cs_sniff_mode), + HCI_CS(HCI_OP_EXIT_SNIFF_MODE, hci_cs_exit_sniff_mode), + HCI_CS(HCI_OP_SWITCH_ROLE, hci_cs_switch_role), + HCI_CS(HCI_OP_LE_CREATE_CONN, hci_cs_le_create_conn), + HCI_CS(HCI_OP_LE_READ_REMOTE_FEATURES, hci_cs_le_read_remote_features), + HCI_CS(HCI_OP_LE_START_ENC, hci_cs_le_start_enc), + HCI_CS(HCI_OP_LE_EXT_CREATE_CONN, hci_cs_le_ext_create_conn) +}; + static void hci_cmd_status_evt(struct hci_dev *hdev, void *data, struct sk_buff *skb, u16 *opcode, u8 *status, hci_req_complete_t *req_complete, hci_req_complete_skb_t *req_complete_skb) { struct hci_ev_cmd_status *ev = data; + int i; *opcode = __le16_to_cpu(ev->opcode); *status = ev->status; - switch (*opcode) { - case HCI_OP_INQUIRY: - hci_cs_inquiry(hdev, ev->status); - break; - - case HCI_OP_CREATE_CONN: - hci_cs_create_conn(hdev, ev->status); - break; - - case HCI_OP_DISCONNECT: - hci_cs_disconnect(hdev, ev->status); - break; - - case HCI_OP_ADD_SCO: - hci_cs_add_sco(hdev, ev->status); - break; - - case HCI_OP_AUTH_REQUESTED: - hci_cs_auth_requested(hdev, ev->status); - break; - - case HCI_OP_SET_CONN_ENCRYPT: - hci_cs_set_conn_encrypt(hdev, ev->status); - break; - - case HCI_OP_REMOTE_NAME_REQ: - hci_cs_remote_name_req(hdev, ev->status); - break; - - case HCI_OP_READ_REMOTE_FEATURES: - hci_cs_read_remote_features(hdev, ev->status); - break; - - case HCI_OP_READ_REMOTE_EXT_FEATURES: - hci_cs_read_remote_ext_features(hdev, ev->status); - break; - - case HCI_OP_SETUP_SYNC_CONN: - hci_cs_setup_sync_conn(hdev, ev->status); - break; - - case HCI_OP_ENHANCED_SETUP_SYNC_CONN: - hci_cs_enhanced_setup_sync_conn(hdev, ev->status); - break; - - case HCI_OP_SNIFF_MODE: - hci_cs_sniff_mode(hdev, ev->status); - break; - - case HCI_OP_EXIT_SNIFF_MODE: - hci_cs_exit_sniff_mode(hdev, ev->status); - break; - - case HCI_OP_SWITCH_ROLE: - hci_cs_switch_role(hdev, ev->status); - break; - - case HCI_OP_LE_CREATE_CONN: - hci_cs_le_create_conn(hdev, ev->status); - break; - - case HCI_OP_LE_READ_REMOTE_FEATURES: - hci_cs_le_read_remote_features(hdev, ev->status); - break; - - case HCI_OP_LE_START_ENC: - hci_cs_le_start_enc(hdev, ev->status); - break; - - case HCI_OP_LE_EXT_CREATE_CONN: - hci_cs_le_ext_create_conn(hdev, ev->status); - break; + bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode); - default: - BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); - break; + for (i = 0; i < ARRAY_SIZE(hci_cs_table); i++) { + if (hci_cs_table[i].op == *opcode) { + hci_cs_table[i].func(hdev, ev->status); + break; + } } handle_cmd_cnt_and_timer(hdev, ev->ncmd);