aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaty Moe2017-10-06 11:53:01 +0100
committerKaty Moe2017-10-06 11:55:36 +0100
commit5d22f042d01593612daf9bfaff07f602189db20c (patch)
treecfcea5ad0e8cf5bbcc39afaa41bb6ef582da1047
parentaed3a3c4a40a2eef4f9ebfa8493467b4ff8df2bf (diff)
downloadaur-5d22f042d01593612daf9bfaff07f602189db20c.tar.gz
v0.9: updates to skbuff
-rw-r--r--.SRCINFO12
-rw-r--r--PKGBUILD12
-rw-r--r--btusb.c204
3 files changed, 193 insertions, 35 deletions
diff --git a/.SRCINFO b/.SRCINFO
index d9fe8e1e087b..b61e54107b52 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,6 +1,6 @@
pkgbase = btusb-qca-0x3004
pkgdesc = patch btusb so it works on QCA devices with id 0x3004
- pkgver = 0.8
+ pkgver = 0.9
pkgrel = 1
install = btusb-qca-0x3004.install
arch = i686
@@ -10,14 +10,14 @@ pkgbase = btusb-qca-0x3004
source = Makefile
source = btusb.patch
source = btusb-qca-0x3004.install
- source = btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.10.4
- source = btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.10.4
- source = btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.10.4
- source = btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.10.4
+ source = btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.13.4
+ source = btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.13.4
+ source = btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.13.4
+ source = btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.13.4
md5sums = 369ff1a06ddfa06bc68bd776d3fbc97e
md5sums = bf67cf7e920e90f399fafadc2d26f9d7
md5sums = 3b63db7fbf7aab07322b0a1f71a7ffdb
- md5sums = 25e4e23aae21b04fa865c8e1b07a1d77
+ md5sums = 4e30ace94e0c3842da7d16c1d8dfded1
md5sums = 764863abf53cb70bc04a3af1c24d226e
md5sums = 4c5d3ed81979cc6af062b381731d25e3
md5sums = ed7b0912a2e3507068c0d173ed9338fa
diff --git a/PKGBUILD b/PKGBUILD
index 821a3b60de2a..30f2f8e93129 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -4,7 +4,7 @@ _kernver="$(uname -r)"
_kernver_base="$(echo $_kernver | cut -d- -f1)"
pkgname=btusb-qca-0x3004
_pkgname=btusb
-pkgver=0.8
+pkgver=0.9
pkgrel=1
pkgdesc="patch btusb so it works on QCA devices with id 0x3004"
arch=('i686' 'x86_64')
@@ -13,10 +13,10 @@ depends=('linux-headers')
source=("Makefile"
"btusb.patch"
"btusb-qca-0x3004.install"
- "btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.10.4"
- "btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.10.4"
- "btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.10.4"
- "btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.10.4")
+ "btusb.c::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btusb.c?id=refs/tags/v4.13.4"
+ "btintel.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btintel.h?id=refs/tags/v4.13.4"
+ "btbcm.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btbcm.h?id=refs/tags/v4.13.4"
+ "btrtl.h::https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/plain/drivers/bluetooth/btrtl.h?id=refs/tags/v4.13.4")
install="btusb-qca-0x3004.install"
@@ -37,7 +37,7 @@ package() {
md5sums=('369ff1a06ddfa06bc68bd776d3fbc97e'
'bf67cf7e920e90f399fafadc2d26f9d7'
'3b63db7fbf7aab07322b0a1f71a7ffdb'
- '25e4e23aae21b04fa865c8e1b07a1d77'
+ '4e30ace94e0c3842da7d16c1d8dfded1'
'764863abf53cb70bc04a3af1c24d226e'
'4c5d3ed81979cc6af062b381731d25e3'
'ed7b0912a2e3507068c0d173ed9338fa')
diff --git a/btusb.c b/btusb.c
index dd220fad366c..e331e212f5fc 100644
--- a/btusb.c
+++ b/btusb.c
@@ -24,6 +24,9 @@
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/firmware.h>
+#include <linux/of_device.h>
+#include <linux/of_irq.h>
+#include <linux/suspend.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
@@ -130,6 +133,10 @@ static const struct usb_device_id btusb_table[] = {
/* Broadcom BCM43142A0 (Foxconn/Lenovo) */
{ USB_DEVICE(0x105b, 0xe065), .driver_info = BTUSB_BCM_PATCHRAM },
+ /* Broadcom BCM920703 (HTC Vive) */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x0bb4, 0xff, 0x01, 0x01),
+ .driver_info = BTUSB_BCM_PATCHRAM },
+
/* Foxconn - Hon Hai */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0489, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
@@ -154,6 +161,10 @@ static const struct usb_device_id btusb_table[] = {
{ USB_VENDOR_AND_INTERFACE_INFO(0x13d3, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
+ /* Dell Computer - Broadcom based */
+ { USB_VENDOR_AND_INTERFACE_INFO(0x413c, 0xff, 0x01, 0x01),
+ .driver_info = BTUSB_BCM_PATCHRAM },
+
/* Toshiba Corp - Broadcom based */
{ USB_VENDOR_AND_INTERFACE_INFO(0x0930, 0xff, 0x01, 0x01),
.driver_info = BTUSB_BCM_PATCHRAM },
@@ -252,8 +263,10 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x0cf3, 0xe007), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe009), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe300), .driver_info = BTUSB_QCA_ROME },
+ { USB_DEVICE(0x0cf3, 0xe301), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0cf3, 0xe360), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x0489, 0xe092), .driver_info = BTUSB_QCA_ROME },
+ { USB_DEVICE(0x0489, 0xe0a2), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3011), .driver_info = BTUSB_QCA_ROME },
/* Broadcom BCM2035 */
@@ -318,11 +331,13 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x1286, 0x204e), .driver_info = BTUSB_MARVELL },
/* Intel Bluetooth devices */
+ { USB_DEVICE(0x8087, 0x0025), .driver_info = BTUSB_INTEL_NEW },
{ USB_DEVICE(0x8087, 0x07da), .driver_info = BTUSB_CSR },
{ USB_DEVICE(0x8087, 0x07dc), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2a), .driver_info = BTUSB_INTEL },
{ USB_DEVICE(0x8087, 0x0a2b), .driver_info = BTUSB_INTEL_NEW },
{ USB_DEVICE(0x8087, 0x0aa7), .driver_info = BTUSB_INTEL },
+ { USB_DEVICE(0x8087, 0x0aaa), .driver_info = BTUSB_INTEL_NEW },
/* Other Intel Bluetooth devices */
{ USB_VENDOR_AND_INTERFACE_INFO(0x8087, 0xe0, 0x01, 0x01),
@@ -342,6 +357,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x13d3, 0x3410), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3416), .driver_info = BTUSB_REALTEK },
{ USB_DEVICE(0x13d3, 0x3459), .driver_info = BTUSB_REALTEK },
+ { USB_DEVICE(0x13d3, 0x3494), .driver_info = BTUSB_REALTEK },
/* Additional Realtek 8821AE Bluetooth devices */
{ USB_DEVICE(0x0b05, 0x17dc), .driver_info = BTUSB_REALTEK },
@@ -370,6 +386,7 @@ static const struct usb_device_id blacklist_table[] = {
#define BTUSB_BOOTING 9
#define BTUSB_RESET_RESUME 10
#define BTUSB_DIAG_RUNNING 11
+#define BTUSB_OOB_WAKE_ENABLED 12
struct btusb_data {
struct hci_dev *hdev;
@@ -417,6 +434,8 @@ struct btusb_data {
int (*recv_bulk)(struct btusb_data *data, void *buffer, int count);
int (*setup_on_usb)(struct hci_dev *hdev);
+
+ int oob_wake_irq; /* irq for out-of-band wake-on-bt */
};
static inline void btusb_free_frags(struct btusb_data *data)
@@ -460,7 +479,7 @@ static int btusb_recv_intr(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, hci_skb_expect(skb), count);
- memcpy(skb_put(skb, len), buffer, len);
+ skb_put_data(skb, buffer, len);
count -= len;
buffer += len;
@@ -515,7 +534,7 @@ static int btusb_recv_bulk(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, hci_skb_expect(skb), count);
- memcpy(skb_put(skb, len), buffer, len);
+ skb_put_data(skb, buffer, len);
count -= len;
buffer += len;
@@ -572,7 +591,7 @@ static int btusb_recv_isoc(struct btusb_data *data, void *buffer, int count)
}
len = min_t(uint, hci_skb_expect(skb), count);
- memcpy(skb_put(skb, len), buffer, len);
+ skb_put_data(skb, buffer, len);
count -= len;
buffer += len;
@@ -916,8 +935,8 @@ static void btusb_diag_complete(struct urb *urb)
skb = bt_skb_alloc(urb->actual_length, GFP_ATOMIC);
if (skb) {
- memcpy(skb_put(skb, urb->actual_length),
- urb->transfer_buffer, urb->actual_length);
+ skb_put_data(skb, urb->transfer_buffer,
+ urb->actual_length);
hci_recv_diag(hdev, skb);
}
} else if (urb->status == -ENOENT) {
@@ -1818,15 +1837,15 @@ static int inject_cmd_complete(struct hci_dev *hdev, __u16 opcode)
if (!skb)
return -ENOMEM;
- hdr = (struct hci_event_hdr *)skb_put(skb, sizeof(*hdr));
+ hdr = skb_put(skb, sizeof(*hdr));
hdr->evt = HCI_EV_CMD_COMPLETE;
hdr->plen = sizeof(*evt) + 1;
- evt = (struct hci_ev_cmd_complete *)skb_put(skb, sizeof(*evt));
+ evt = skb_put(skb, sizeof(*evt));
evt->ncmd = 0x01;
evt->opcode = cpu_to_le16(opcode);
- *skb_put(skb, 1) = 0x00;
+ skb_put_u8(skb, 0x00);
hci_skb_pkt_type(skb) = HCI_EVENT_PKT;
@@ -2011,13 +2030,19 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
return -EINVAL;
}
- /* At the moment the iBT 3.0 hardware variants 0x0b (LnP/SfP)
- * and 0x0c (WsP) are supported by this firmware loading method.
+ /* Check for supported iBT hardware variants of this firmware
+ * loading method.
*
* This check has been put in place to ensure correct forward
* compatibility options when newer hardware variants come along.
*/
- if (ver.hw_variant != 0x0b && ver.hw_variant != 0x0c) {
+ switch (ver.hw_variant) {
+ case 0x0b: /* SfP */
+ case 0x0c: /* WsP */
+ case 0x11: /* JfP */
+ case 0x12: /* ThP */
+ break;
+ default:
BT_ERR("%s: Unsupported Intel hardware variant (%u)",
hdev->name, ver.hw_variant);
return -EINVAL;
@@ -2117,6 +2142,8 @@ static int btusb_setup_intel_new(struct hci_dev *hdev)
* Currently the supported hardware variants are:
* 11 (0x0b) for iBT3.0 (LnP/SfP)
* 12 (0x0c) for iBT3.5 (WsP)
+ * 17 (0x11) for iBT3.5 (JfP)
+ * 18 (0x12) for iBT3.5 (ThP)
*/
snprintf(fwname, sizeof(fwname), "intel/ibt-%u-%u.sfi",
le16_to_cpu(ver.hw_variant),
@@ -2339,6 +2366,50 @@ static int btusb_shutdown_intel(struct hci_dev *hdev)
return 0;
}
+#ifdef CONFIG_PM
+/* Configure an out-of-band gpio as wake-up pin, if specified in device tree */
+static int marvell_config_oob_wake(struct hci_dev *hdev)
+{
+ struct sk_buff *skb;
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct device *dev = &data->udev->dev;
+ u16 pin, gap, opcode;
+ int ret;
+ u8 cmd[5];
+
+ /* Move on if no wakeup pin specified */
+ if (of_property_read_u16(dev->of_node, "marvell,wakeup-pin", &pin) ||
+ of_property_read_u16(dev->of_node, "marvell,wakeup-gap-ms", &gap))
+ return 0;
+
+ /* Vendor specific command to configure a GPIO as wake-up pin */
+ opcode = hci_opcode_pack(0x3F, 0x59);
+ cmd[0] = opcode & 0xFF;
+ cmd[1] = opcode >> 8;
+ cmd[2] = 2; /* length of parameters that follow */
+ cmd[3] = pin;
+ cmd[4] = gap; /* time in ms, for which wakeup pin should be asserted */
+
+ skb = bt_skb_alloc(sizeof(cmd), GFP_KERNEL);
+ if (!skb) {
+ bt_dev_err(hdev, "%s: No memory\n", __func__);
+ return -ENOMEM;
+ }
+
+ skb_put_data(skb, cmd, sizeof(cmd));
+ hci_skb_pkt_type(skb) = HCI_COMMAND_PKT;
+
+ ret = btusb_send_frame(hdev, skb);
+ if (ret) {
+ bt_dev_err(hdev, "%s: configuration failed\n", __func__);
+ kfree_skb(skb);
+ return ret;
+ }
+
+ return 0;
+}
+#endif
+
static int btusb_set_bdaddr_marvell(struct hci_dev *hdev,
const bdaddr_t *bdaddr)
{
@@ -2697,8 +2768,8 @@ static struct urb *alloc_diag_urb(struct hci_dev *hdev, bool enable)
return ERR_PTR(-ENOMEM);
}
- *skb_put(skb, 1) = 0xf0;
- *skb_put(skb, 1) = enable;
+ skb_put_u8(skb, 0xf0);
+ skb_put_u8(skb, enable);
pipe = usb_sndbulkpipe(data->udev, data->diag_tx_ep->bEndpointAddress);
@@ -2729,6 +2800,67 @@ static int btusb_bcm_set_diag(struct hci_dev *hdev, bool enable)
}
#endif
+#ifdef CONFIG_PM
+static irqreturn_t btusb_oob_wake_handler(int irq, void *priv)
+{
+ struct btusb_data *data = priv;
+
+ pm_wakeup_event(&data->udev->dev, 0);
+ pm_system_wakeup();
+
+ /* Disable only if not already disabled (keep it balanced) */
+ if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
+ disable_irq_nosync(irq);
+ disable_irq_wake(irq);
+ }
+ return IRQ_HANDLED;
+}
+
+static const struct of_device_id btusb_match_table[] = {
+ { .compatible = "usb1286,204e" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, btusb_match_table);
+
+/* Use an oob wakeup pin? */
+static int btusb_config_oob_wake(struct hci_dev *hdev)
+{
+ struct btusb_data *data = hci_get_drvdata(hdev);
+ struct device *dev = &data->udev->dev;
+ int irq, ret;
+
+ clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
+
+ if (!of_match_device(btusb_match_table, dev))
+ return 0;
+
+ /* Move on if no IRQ specified */
+ irq = of_irq_get_byname(dev->of_node, "wakeup");
+ if (irq <= 0) {
+ bt_dev_dbg(hdev, "%s: no OOB Wakeup IRQ in DT", __func__);
+ return 0;
+ }
+
+ ret = devm_request_irq(&hdev->dev, irq, btusb_oob_wake_handler,
+ 0, "OOB Wake-on-BT", data);
+ if (ret) {
+ bt_dev_err(hdev, "%s: IRQ request failed", __func__);
+ return ret;
+ }
+
+ ret = device_init_wakeup(dev, true);
+ if (ret) {
+ bt_dev_err(hdev, "%s: failed to init_wakeup", __func__);
+ return ret;
+ }
+
+ data->oob_wake_irq = irq;
+ disable_irq(irq);
+ bt_dev_info(hdev, "OOB Wake-on-BT configured at IRQ %u", irq);
+ return 0;
+}
+#endif
+
static int btusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
@@ -2850,6 +2982,18 @@ static int btusb_probe(struct usb_interface *intf,
hdev->send = btusb_send_frame;
hdev->notify = btusb_notify;
+#ifdef CONFIG_PM
+ err = btusb_config_oob_wake(hdev);
+ if (err)
+ goto out_free_dev;
+
+ /* Marvell devices may need a specific chip configuration */
+ if (id->driver_info & BTUSB_MARVELL && data->oob_wake_irq) {
+ err = marvell_config_oob_wake(hdev);
+ if (err)
+ goto out_free_dev;
+ }
+#endif
if (id->driver_info & BTUSB_CW6622)
set_bit(HCI_QUIRK_BROKEN_STORED_LINK_KEY, &hdev->quirks);
@@ -2992,18 +3136,15 @@ static int btusb_probe(struct usb_interface *intf,
err = usb_set_interface(data->udev, 0, 0);
if (err < 0) {
BT_ERR("failed to set interface 0, alt 0 %d", err);
- hci_free_dev(hdev);
- return err;
+ goto out_free_dev;
}
}
if (data->isoc) {
err = usb_driver_claim_interface(&btusb_driver,
data->isoc, data);
- if (err < 0) {
- hci_free_dev(hdev);
- return err;
- }
+ if (err < 0)
+ goto out_free_dev;
}
#ifdef CONFIG_BT_HCIBTUSB_BCM
@@ -3017,14 +3158,16 @@ static int btusb_probe(struct usb_interface *intf,
#endif
err = hci_register_dev(hdev);
- if (err < 0) {
- hci_free_dev(hdev);
- return err;
- }
+ if (err < 0)
+ goto out_free_dev;
usb_set_intfdata(intf, data);
return 0;
+
+out_free_dev:
+ hci_free_dev(hdev);
+ return err;
}
static void btusb_disconnect(struct usb_interface *intf)
@@ -3063,6 +3206,9 @@ static void btusb_disconnect(struct usb_interface *intf)
usb_driver_release_interface(&btusb_driver, data->isoc);
}
+ if (data->oob_wake_irq)
+ device_init_wakeup(&data->udev->dev, false);
+
hci_free_dev(hdev);
}
@@ -3091,6 +3237,12 @@ static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
btusb_stop_traffic(data);
usb_kill_anchored_urbs(&data->tx_anchor);
+ if (data->oob_wake_irq && device_may_wakeup(&data->udev->dev)) {
+ set_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags);
+ enable_irq_wake(data->oob_wake_irq);
+ enable_irq(data->oob_wake_irq);
+ }
+
/* Optionally request a device reset on resume, but only when
* wakeups are disabled. If wakeups are enabled we assume the
* device will stay powered up throughout suspend.
@@ -3128,6 +3280,12 @@ static int btusb_resume(struct usb_interface *intf)
if (--data->suspend_count)
return 0;
+ /* Disable only if not already disabled (keep it balanced) */
+ if (test_and_clear_bit(BTUSB_OOB_WAKE_ENABLED, &data->flags)) {
+ disable_irq(data->oob_wake_irq);
+ disable_irq_wake(data->oob_wake_irq);
+ }
+
if (!test_bit(HCI_RUNNING, &hdev->flags))
goto done;