[7885] wlbt: Add packet inspection bypass for ACL data dump
authorJes Andersen <jes.andersen@samsung.com>
Fri, 4 May 2018 10:51:51 +0000 (12:51 +0200)
committerIvan Priest <i.priest@samsung.com>
Wed, 11 Jul 2018 17:43:17 +0000 (18:43 +0100)
To implement a vendor specific command raw acl data must be passed to
the host without a connection.

The upper byte in the connection_handle is unused by the firmware
currently, as it previously would just have increased the error count.

Change-Id: I8667f8249323449418a3c9c7ef28f8ad8a6122f1
SCSC-Bug-Id: SSB-39242
Signed-off-by: Jes Andersen <jes.andersen@samsung.com>
drivers/misc/samsung/scsc_bt/scsc_bt_priv.h
drivers/misc/samsung/scsc_bt/scsc_shm.c

index 2690a0f6760dbd9f6088543f432a394df219f8f5..4a18797c91a7351282b758aa93ccb7ed3c16473b 100755 (executable)
@@ -65,6 +65,8 @@
 #define ANT_HEADER_LENGTH 1
 
 #define SCSC_BT_CONNECTION_INFO_MAX     (0x1000)
+#define SCSC_BT_ACL_RAW_MASK            (0xF000)
+#define SCSC_BT_ACL_RAW                 (0x2000)
 
 #define SCSC_TTY_MINORS (8)
 
index 093c884cedcb956a20f4df07f6d0ac36d43167fd..42f15d95262927f8458de7202b93cb0d5a0d3290 100755 (executable)
@@ -942,14 +942,62 @@ static ssize_t scsc_bt_shm_h4_read_hci_evt(char __user *buf, size_t len)
        return 0 == ret ? consumed : ret;
 }
 
+/**
+ * Start the acl data to userspace copy
+ *
+ * Acl processing should be stopped if either unable to read a complete packet
+ * or a complete packet is read and BlueZ is enabled
+ *
+ * @param[out]    ret      result of read operations written to here
+ * @param[in,out] consumed read bytes added to this
+ *
+ * @return true if ACL data processing should stop
+ */
+static bool scsc_bt_shm_h4_acl_start_copy(char __user *buf,
+       size_t len,
+       ssize_t *ret,
+       ssize_t *consumed)
+{
+       bt_service.read_operation = BT_READ_OP_ACL_DATA;
+       bt_service.read_index = bt_service.mailbox_acl_rx_read;
+       *ret = scsc_acl_read(&buf[*consumed], len - *consumed);
+       if (*ret <= 0)
+               return *ret < 0; /* Break the loop for errors */
+
+       /* Update our consumed information */
+       *consumed += *ret;
+       *ret = 0;
+
+       /* Stop processing if all the data could not be copied to userspace */
+       if (bt_service.read_operation != BT_READ_OP_NONE)
+               return true;
+
+       BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE);
+
+#ifdef CONFIG_SCSC_BT_BLUEZ
+       /* If BlueZ is enabled stop processing even after one complete packet */
+       return true;
+#else
+       return false;
+#endif
+}
+
 static ssize_t scsc_bt_shm_h4_read_acl_data(char __user *buf, size_t len)
 {
        ssize_t ret = 0;
        ssize_t consumed = 0;
 
-       while (BT_READ_OP_NONE == bt_service.read_operation && 0 == ret && !bt_service.acldata_paused && bt_service.mailbox_acl_rx_read != bt_service.mailbox_acl_rx_write) {
+       while (bt_service.read_operation == BT_READ_OP_NONE &&
+              !bt_service.acldata_paused &&
+              bt_service.mailbox_acl_rx_read != bt_service.mailbox_acl_rx_write) {
                struct BSMHCP_TD_ACL_RX *td = &bt_service.bsmhcp_protocol->acl_rx_transfer_ring[bt_service.mailbox_acl_rx_read];
 
+               /* Bypass packet inspection and connection handling for data dump */
+               if (SCSC_BT_ACL_RAW == (td->hci_connection_handle & SCSC_BT_ACL_RAW_MASK)) {
+                       if (scsc_bt_shm_h4_acl_start_copy(buf, len, &ret, &consumed))
+                               break;
+               }
+
                /* Sanity check of the HCI connection handle */
                if (td->hci_connection_handle >= SCSC_BT_CONNECTION_INFO_MAX) {
                        SCSC_TAG_ERR(BT_H4, "connection handle is beyond max (hci_connection_handle=0x%03x)\n",
@@ -974,23 +1022,8 @@ static ssize_t scsc_bt_shm_h4_read_acl_data(char __user *buf, size_t len)
                                /* Update the read pointer */
                                BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE);
                        } else {
-                               /* Start a ACL data copy to userspace */
-                               bt_service.read_operation = BT_READ_OP_ACL_DATA;
-                               bt_service.read_index = bt_service.mailbox_acl_rx_read;
-                               ret = scsc_acl_read(&buf[consumed], len - consumed);
-                               if (ret > 0) {
-                                       /* Update our consumed information */
-                                       consumed += ret;
-                                       ret = 0;
-
-                                       /* Update the index if all the data could be copied to the userspace buffer otherwise stop processing the ACL data */
-                                       if (BT_READ_OP_NONE == bt_service.read_operation)
-                                               BSMHCP_INCREASE_INDEX(bt_service.mailbox_acl_rx_read, BSMHCP_TRANSFER_RING_ACL_SIZE);
-#ifndef CONFIG_SCSC_BT_BLUEZ
-                                       else
-#endif
-                                               break;
-                               }
+                               if (scsc_bt_shm_h4_acl_start_copy(buf, len, &ret, &consumed))
+                                       break;
                        }
                        /* If the connection state is inactive the HCI connection complete information hasn't yet arrived. Stop processing ACL data */
                } else if (CONNECTION_NONE == bt_service.connection_handle_list[td->hci_connection_handle].state) {