rtk_btusb: Update driver version to 3.1.65ab490.20240531-141726

- Update driver to 3.1.65ab490.20240531-141726
- Add support for 8852CE

Bug 4915378

Change-Id: Ib3f695047ee306fd07db424239c985195619aad1
Signed-off-by: Shobek Attupurath <sattupurath@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3237077
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
Reviewed-by: Ashutosh Jha <ajha@nvidia.com>
Reviewed-by: Revanth Kumar Uppala <ruppala@nvidia.com>
This commit is contained in:
Shobek Attupurath
2024-10-18 17:54:13 +00:00
committed by mobile promotions
parent 7ea5704ca3
commit 3d15bb40b5
7 changed files with 1930 additions and 605 deletions

View File

@@ -1,8 +1,22 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
*
* Realtek Bluetooth USB driver
*
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <linux/kernel.h>
@@ -22,7 +36,7 @@
#include "rtk_bt.h"
#include "rtk_misc.h"
#define VERSION "3.1.6fd4e69.20220818-105856"
#define VERSION "3.1.65ab490.20240531-141726"
#ifdef BTCOEX
#include "rtk_coex.h"
@@ -35,95 +49,64 @@ static DEFINE_SEMAPHORE(switch_sem);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 7, 1)
static bool reset = 0;
static bool reset = true;
#endif
static struct usb_driver btusb_driver;
static struct usb_device_id btusb_table[] = {
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static u16 iso_min_conn_handle = 0x1b;
#endif
static const struct usb_device_id btusb_table[] = {
/* Generic Bluetooth USB device */
{ USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
/* Generic Bluetooth USB interface */
{ USB_INTERFACE_INFO(0xe0, 0x01, 0x01) },
{}
};
static const struct usb_device_id blacklist_table[] = {
{
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0bda,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x13d3,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0489,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x1358,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04ca,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x2ff8,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0b05,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0930,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x10ec,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04c5,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0cb5,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR |
USB_DEVICE_ID_MATCH_INT_INFO,
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x0cb8,
.bInterfaceClass = 0xe0,
.bInterfaceSubClass = 0x01,
.bInterfaceProtocol = 0x01
}, {
.match_flags = USB_DEVICE_ID_MATCH_VENDOR,
.idVendor = 0x04b8,
}, { }
};
@@ -148,20 +131,6 @@ static struct btusb_data *rtk_alloc(struct usb_interface *intf)
MODULE_DEVICE_TABLE(usb, btusb_table);
static int inc_tx(struct btusb_data *data)
{
unsigned long flags;
int rv;
spin_lock_irqsave(&data->txlock, flags);
rv = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!rv)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
return rv;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
static inline void btusb_free_frags(struct btusb_data *data)
{
@@ -204,7 +173,11 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
@@ -259,15 +232,26 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
bt_cb(skb)->expect -= len;
if (skb->len == HCI_ACL_HDR_SIZE) {
__le16 dlen = hci_acl_hdr(skb)->dlen;
struct hci_acl_hdr *h = hci_acl_hdr(skb);
__le16 dlen = h->dlen;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
__u16 handle = __le16_to_cpu(h->handle) & 0xfff;
if(handle >= iso_min_conn_handle) {
bt_cb(skb)->pkt_type = HCI_ISODATA_PKT;
}
#endif
/* Complete ACL header */
bt_cb(skb)->expect = __le16_to_cpu(dlen);
@@ -293,10 +277,42 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
return err;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
static int btrtl_usb_recv_isoc(u16 pos, u8 *data, u8 *p, int len,
u16 wMaxPacketSize)
{
u8 *prev;
if (pos >= HCI_SCO_HDR_SIZE && pos >= wMaxPacketSize &&
len == wMaxPacketSize && !(pos % wMaxPacketSize) &&
wMaxPacketSize >= 10 && p[0] == data[0] && p[1] == data[1]) {
prev = data + (pos - wMaxPacketSize);
/* Detect the sco data of usb isoc pkt duplication. */
if (!memcmp(p + 2, prev + 2, 8))
return -EILSEQ;
if (wMaxPacketSize >= 12 &&
p[2] == prev[6] && p[3] == prev[7] &&
p[4] == prev[4] && p[5] == prev[5] &&
p[6] == prev[10] && p[7] == prev[11] &&
p[8] == prev[8] && p[9] == prev[9]) {
return -EILSEQ;
}
}
return 0;
}
#endif
static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
{
struct sk_buff *skb;
int err = 0;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
u16 wMaxPacketSize = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize);
#endif
spin_lock(&data->rxlock);
skb = data->sco_skb;
@@ -316,7 +332,24 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, bt_cb(skb)->expect, count);
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
/* Gaps in audio could be heard while streaming WBS using USB
* alt settings 3 on some platforms.
* Add the function to detect it.
*/
if (test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags)) {
err = btrtl_usb_recv_isoc(skb->len, skb->data, buffer,
len, wMaxPacketSize);
if (err)
break;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
skb_put_data(skb, buffer, len);
#else
memcpy(skb_put(skb, len), buffer, len);
#endif
count -= len;
buffer += len;
@@ -347,6 +380,21 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
return err;
}
#else
static int inc_tx(struct btusb_data *data)
{
unsigned long flags;
int rv;
spin_lock_irqsave(&data->txlock, flags);
rv = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!rv)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
return rv;
}
#endif
static void btusb_intr_complete(struct urb *urb)
@@ -626,6 +674,51 @@ retry:
}
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
static inline void __fill_isoc_descriptor_msbc(struct urb *urb, int len,
int mtu, struct btusb_data *data)
{
int i = 0, offset = 0;
unsigned int interval;
BT_DBG("len %d mtu %d", len, mtu);
/* For mSBC ALT 6 settings some Realtek chips need to transmit the data
* continuously without the zero length of USB packets.
*/
if (btrealtek_test_flag(data->hdev, REALTEK_ALT6_CONTINUOUS_TX_CHIP))
goto ignore_usb_alt6_packet_flow;
/* For mSBC ALT 6 setting the host will send the packet at continuous
* flow. As per core spec 5, vol 4, part B, table 2.1. For ALT setting
* 6 the HCI PACKET INTERVAL should be 7.5ms for every usb packets.
* To maintain the rate we send 63bytes of usb packets alternatively for
* 7ms and 8ms to maintain the rate as 7.5ms.
*/
if (data->usb_alt6_packet_flow) {
interval = 7;
data->usb_alt6_packet_flow = false;
} else {
interval = 6;
data->usb_alt6_packet_flow = true;
}
for (i = 0; i < interval; i++) {
urb->iso_frame_desc[i].offset = offset;
urb->iso_frame_desc[i].length = offset;
}
ignore_usb_alt6_packet_flow:
if (len && i < BTUSB_MAX_ISOC_FRAMES) {
urb->iso_frame_desc[i].offset = offset;
urb->iso_frame_desc[i].length = len;
i++;
}
urb->number_of_packets = i;
}
#endif
static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
{
int i, offset = 0;
@@ -675,6 +768,12 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress);
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 2, 14)
usb_fill_int_urb(urb, data->udev, pipe, buf, size, btusb_isoc_complete,
hdev, data->isoc_rx_ep->bInterval);
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
#else
urb->dev = data->udev;
urb->pipe = pipe;
urb->context = hdev;
@@ -684,6 +783,7 @@ static int btusb_submit_isoc_urb(struct hci_dev *hdev, gfp_t mem_flags)
urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP;
urb->transfer_buffer = buf;
urb->transfer_buffer_length = size;
#endif
__fill_isoc_descriptor(urb, size,
le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize));
@@ -734,8 +834,8 @@ static void btusb_isoc_tx_complete(struct urb *urb)
struct sk_buff *skb = urb->context;
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
RTKBT_DBG("%s: urb %p status %d count %d",__func__,
urb, urb->status, urb->actual_length);
RTKBT_DBG("%s: urb %p status %d count %d", __func__,
urb, urb->status, urb->actual_length);
if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done;
@@ -751,6 +851,49 @@ done:
kfree_skb(skb);
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static int rtl_read_iso_handle_range(struct hci_dev *hdev)
{
struct sk_buff *skb;
struct __rp {
u8 status;
u8 min_handle[2];
} *rp;
int ret = -EIO;
skb = __hci_cmd_sync(hdev, 0xfdab, 0, NULL, HCI_CMD_TIMEOUT);
if (IS_ERR(skb)) {
return PTR_ERR(skb);
}
/* FIXME: if the return status is not zero, __hci_cmd_sync() would
* return an error and we would not reach here.
*/
if (skb->data[0]) {
RTKBT_ERR("%s: Read failed, status %0x", hdev->name,
skb->data[0]);
goto err;
}
if (skb->len < sizeof(*rp)) {
RTKBT_WARN("%s: The len %u of rp is too short", __func__,
skb->len);
goto err;
}
rp = (void *)skb->data;
iso_min_conn_handle = (u16)rp->min_handle[1] << 8 | rp->min_handle[0];
RTKBT_DBG("ISO handle range (handle >= %04x)", iso_min_conn_handle);
kfree_skb(skb);
return 0;
err:
kfree_skb(skb);
return ret;
}
#endif
static int btusb_open(struct hci_dev *hdev)
{
struct btusb_data *data = GET_DRV_DATA(hdev);
@@ -775,6 +918,10 @@ static int btusb_open(struct hci_dev *hdev)
goto failed;
/*******************************/
err = setup_btrealtek_flag(data->intf, hdev);
if (err < 0)
RTKBT_WARN("setup_btrealtek_flag incorrect!");
RTKBT_INFO("%s set HCI UP RUNNING", __func__);
if (test_and_set_bit(HCI_UP, &hdev->flags))
goto done;
@@ -817,6 +964,32 @@ failed:
return err;
}
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
static int btusb_setup(struct hci_dev *hdev)
{
rtl_read_iso_handle_range(hdev);
return 0;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
static int btusb_shutdown(struct hci_dev *hdev)
{
struct sk_buff *skb;
int ret;
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
ret = PTR_ERR(skb);
bt_dev_err(hdev, "HCI reset during shutdown failed");
return ret;
}
kfree_skb(skb);
return 0;
}
#endif
static void btusb_stop_traffic(struct btusb_data *data)
{
mdelay(URB_CANCELING_DELAY_MS); // Added by Realtek
@@ -920,8 +1093,152 @@ static const char pkt_ind[][8] = {
[HCI_COMMAND_PKT] = "cmd",
[HCI_ACLDATA_PKT] = "acl",
[HCI_SCODATA_PKT] = "sco",
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
[HCI_ISODATA_PKT] = "iso",
#endif
};
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
static struct urb *alloc_ctrl_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct usb_ctrlrequest *dr;
struct urb *urb;
unsigned int pipe;
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
dr = kmalloc(sizeof(*dr), GFP_KERNEL);
if (!dr) {
usb_free_urb(urb);
return ERR_PTR(-ENOMEM);
}
dr->bRequestType = data->cmdreq_type;
dr->bRequest = 0;
dr->wIndex = 0;
dr->wValue = 0;
dr->wLength = __cpu_to_le16(skb->len);
pipe = usb_sndctrlpipe(data->udev, 0x00);
usb_fill_control_urb(urb, data->udev, pipe, (void *)dr,
skb->data, skb->len, btusb_tx_complete, skb);
skb->dev = (void *)hdev;
return urb;
}
static struct urb *alloc_bulk_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
unsigned int pipe;
if (!data->bulk_tx_ep)
return ERR_PTR(-ENODEV);
urb = usb_alloc_urb(0, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
pipe = usb_sndbulkpipe(data->udev, data->bulk_tx_ep->bEndpointAddress);
usb_fill_bulk_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_tx_complete, skb);
skb->dev = (void *)hdev;
return urb;
}
static struct urb *alloc_isoc_urb(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
struct urb *urb;
unsigned int pipe;
if (!data->isoc_tx_ep)
return ERR_PTR(-ENODEV);
urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL);
if (!urb)
return ERR_PTR(-ENOMEM);
pipe = usb_sndisocpipe(data->udev, data->isoc_tx_ep->bEndpointAddress);
usb_fill_int_urb(urb, data->udev, pipe,
skb->data, skb->len, btusb_isoc_tx_complete,
skb, data->isoc_tx_ep->bInterval);
urb->transfer_flags = URB_ISO_ASAP;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
if (data->isoc_altsetting == 6)
__fill_isoc_descriptor_msbc(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize),
data);
else
__fill_isoc_descriptor(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
#else
__fill_isoc_descriptor(urb, skb->len,
le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
#endif
skb->dev = (void *)hdev;
return urb;
}
static int submit_tx_urb(struct hci_dev *hdev, struct urb *urb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
int err;
usb_anchor_urb(urb, &data->tx_anchor);
err = usb_submit_urb(urb, GFP_KERNEL);
if (err < 0) {
if (err != -EPERM && err != -ENODEV)
RTKBT_ERR("%s urb %p submission failed (%d)",
hdev->name, urb, -err);
kfree(urb->setup_packet);
usb_unanchor_urb(urb);
} else {
usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
return err;
}
static int submit_or_queue_tx_urb(struct hci_dev *hdev, struct urb *urb)
{
struct btusb_data *data = hci_get_drvdata(hdev);
unsigned long flags;
bool suspending;
spin_lock_irqsave(&data->txlock, flags);
suspending = test_bit(BTUSB_SUSPENDING, &data->flags);
if (!suspending)
data->tx_in_flight++;
spin_unlock_irqrestore(&data->txlock, flags);
if (!suspending)
return submit_tx_urb(hdev, urb);
usb_anchor_urb(urb, &data->deferred);
schedule_work(&data->waker);
usb_free_urb(urb);
return 0;
}
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
{
@@ -931,14 +1248,20 @@ int btusb_send_frame(struct sk_buff *skb)
struct hci_dev *hdev = (struct hci_dev *)skb->dev;
#endif
struct urb *urb;
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
struct btusb_data *data = GET_DRV_DATA(hdev);
struct usb_ctrlrequest *dr;
struct urb *urb;
unsigned int pipe;
int err;
#endif
//RTKBT_DBG("%s", hdev->name);
// RTKBT_DBG("%s", hdev->name);
/* After Kernel version 4.4.0, move the check into the
* hci_send_frame function before calling hdev->send
*/
#if HCI_VERSION_CODE < KERNEL_VERSION(4, 4, 0)
if (!test_bit(HCI_RUNNING, &hdev->flags)) {
/* If the parameter is wrong, the hdev isn't the correct
* one. Then no HCI commands can be sent.
@@ -946,13 +1269,15 @@ int btusb_send_frame(struct sk_buff *skb)
RTKBT_ERR("HCI is not running");
return -EBUSY;
}
#endif
/* Before kernel/hci version 3.13.0, the skb->dev is set before
* entering btusb_send_frame(). So there is no need to set it here.
*
* The skb->dev will be used in the callbacks when urb transfer
* completes. See btusb_tx_complete() and btusb_isoc_tx_complete() */
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 13, 0) && \
HCI_VERSION_CODE < KERNEL_VERSION(3, 18, 0)
skb->dev = (void *)hdev;
#endif
@@ -963,6 +1288,14 @@ int btusb_send_frame(struct sk_buff *skb)
#ifdef BTCOEX
rtk_btcoex_parse_cmd(skb->data, skb->len);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
urb = alloc_ctrl_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.cmd_tx++;
return submit_or_queue_tx_urb(hdev, urb);
#else
urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!urb)
return -ENOMEM;
@@ -988,11 +1321,24 @@ int btusb_send_frame(struct sk_buff *skb)
hdev->stat.cmd_tx++;
break;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
case HCI_ISODATA_PKT:
#endif
case HCI_ACLDATA_PKT:
print_acl(skb, 1);
#ifdef BTCOEX
rtk_btcoex_parse_l2cap_data_tx(skb->data, skb->len);
if(bt_cb(skb)->pkt_type == HCI_ACLDATA_PKT)
rtk_btcoex_parse_l2cap_data_tx(skb->data, skb->len);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
urb = alloc_bulk_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.acl_tx++;
return submit_or_queue_tx_urb(hdev, urb);
#else
if (!data->bulk_tx_ep)
return -ENODEV;
@@ -1009,7 +1355,22 @@ int btusb_send_frame(struct sk_buff *skb)
hdev->stat.acl_tx++;
break;
#endif
case HCI_SCODATA_PKT:
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 18, 0)
if (hci_conn_num(hdev, SCO_LINK) < 1)
return -ENODEV;
urb = alloc_isoc_urb(hdev, skb);
if (IS_ERR(urb))
return PTR_ERR(urb);
hdev->stat.sco_tx++;
return submit_tx_urb(hdev, urb);
}
return -EILSEQ;
#else
if (!data->isoc_tx_ep || SCO_NUM < 1)
return -ENODEV;
@@ -1035,6 +1396,7 @@ int btusb_send_frame(struct sk_buff *skb)
default:
return -EILSEQ;
}
err = inc_tx(data);
@@ -1057,12 +1419,14 @@ skip_waking:
} else {
usb_mark_last_busy(data->udev);
}
usb_free_urb(urb);
done:
usb_free_urb(urb);
return err;
#endif
}
#if HCI_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
static void btusb_destruct(struct hci_dev *hdev)
{
@@ -1181,6 +1545,9 @@ static struct usb_host_interface *btusb_find_altsetting(struct btusb_data *data,
BT_DBG("Looking for Alt no :%d", alt);
if (!intf)
return NULL;
for (i = 0; i < intf->num_altsetting; i++) {
if (intf->altsetting[i].desc.bAlternateSetting == alt)
return &intf->altsetting[i];
@@ -1221,7 +1588,14 @@ static void btusb_work(struct work_struct *work)
new_alts = data->sco_num;
}
} else if (data->air_mode == HCI_NOTIFY_ENABLE_SCO_TRANSP) {
new_alts = btusb_find_altsetting(data, 6) ? 6 : 1;
if (btusb_find_altsetting(data, 6))
new_alts = 6;
else if (btusb_find_altsetting(data, 3) &&
hdev->sco_mtu >= 72 &&
test_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags))
new_alts = 3;
else
new_alts = 1;
}
if (btusb_switch_alt_setting(hdev, new_alts) < 0)
@@ -1421,7 +1795,7 @@ static int rtkbt_pm_notify(struct notifier_block *notifier,
result = __rtk_send_hci_cmd(udev, cmd, 3);
kfree(cmd);
msleep(100); /* From FW colleague's recommendation */
result = download_lps_patch(intf);
result = download_special_patch(intf, "lps_");
#endif
#ifdef RTKBT_TV_POWERON_WHITELIST
@@ -1540,13 +1914,23 @@ static int btusb_probe(struct usb_interface *intf,
struct usb_device *udev;
udev = interface_to_usbdev(intf);
RTKBT_DBG("btusb_probe intf->cur_altsetting->desc.bInterfaceNumber %d",
RTKBT_INFO("btusb_probe intf->cur_altsetting->desc.bInterfaceNumber %d",
intf->cur_altsetting->desc.bInterfaceNumber);
/* interface numbers are hardcoded in the spec */
if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
return -ENODEV;
if (!id->driver_info) {
const struct usb_device_id *match;
match = usb_match_id(intf, blacklist_table);
if (match)
id = match;
else
return -ENODEV;
}
/*******************************/
flag1 = device_can_wakeup(&udev->dev);
flag2 = device_may_wakeup(&udev->dev);
@@ -1636,6 +2020,13 @@ static int btusb_probe(struct usb_interface *intf,
hdev->flush = btusb_flush;
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
hdev->setup = btusb_setup;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(4, 1, 0)
hdev->shutdown = btusb_shutdown;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)
hci_set_drvdata(hdev, data);
@@ -1645,10 +2036,14 @@ static int btusb_probe(struct usb_interface *intf,
hdev->owner = THIS_MODULE;
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(5, 8, 0)
set_bit(BTUSB_USE_ALT3_FOR_WBS, &data->flags);
set_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks);
#endif
#if HCI_VERSION_CODE >= KERNEL_VERSION(3, 7, 1)
if (!reset)
set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);
RTKBT_DBG("set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);");
#endif
/* Interface numbers are hardcoded in the specification */