From 7af98f82103a3e30333440caed06dcb3f4adc05e Mon Sep 17 00:00:00 2001 From: Jes Andersen Date: Fri, 4 May 2018 12:51:51 +0200 Subject: [PATCH] [7885] wlbt: Add packet inspection bypass for ACL data dump 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 --- drivers/misc/samsung/scsc_bt/scsc_bt_priv.h | 2 + drivers/misc/samsung/scsc_bt/scsc_shm.c | 69 +++++++++++++++------ 2 files changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/misc/samsung/scsc_bt/scsc_bt_priv.h b/drivers/misc/samsung/scsc_bt/scsc_bt_priv.h index 2690a0f6760d..4a18797c91a7 100755 --- a/drivers/misc/samsung/scsc_bt/scsc_bt_priv.h +++ b/drivers/misc/samsung/scsc_bt/scsc_bt_priv.h @@ -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) diff --git a/drivers/misc/samsung/scsc_bt/scsc_shm.c b/drivers/misc/samsung/scsc_bt/scsc_shm.c index 093c884cedcb..42f15d952629 100755 --- a/drivers/misc/samsung/scsc_bt/scsc_shm.c +++ b/drivers/misc/samsung/scsc_bt/scsc_shm.c @@ -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) { -- 2.20.1