These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / bluetooth / bpa10x.c
index 8a31991..49c397e 100644 (file)
@@ -35,7 +35,9 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 
-#define VERSION "0.10"
+#include "hci_uart.h"
+
+#define VERSION "0.11"
 
 static const struct usb_device_id bpa10x_table[] = {
        /* Tektronix BPA 100/105 (Digianswer) */
@@ -56,112 +58,6 @@ struct bpa10x_data {
        struct sk_buff *rx_skb[2];
 };
 
-#define HCI_VENDOR_HDR_SIZE 5
-
-struct hci_vendor_hdr {
-       __u8    type;
-       __le16  snum;
-       __le16  dlen;
-} __packed;
-
-static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
-{
-       struct bpa10x_data *data = hci_get_drvdata(hdev);
-
-       BT_DBG("%s queue %d buffer %p count %d", hdev->name,
-                                                       queue, buf, count);
-
-       if (queue < 0 || queue > 1)
-               return -EILSEQ;
-
-       hdev->stat.byte_rx += count;
-
-       while (count) {
-               struct sk_buff *skb = data->rx_skb[queue];
-               struct { __u8 type; int expect; } *scb;
-               int type, len = 0;
-
-               if (!skb) {
-                       /* Start of the frame */
-
-                       type = *((__u8 *) buf);
-                       count--; buf++;
-
-                       switch (type) {
-                       case HCI_EVENT_PKT:
-                               if (count >= HCI_EVENT_HDR_SIZE) {
-                                       struct hci_event_hdr *h = buf;
-                                       len = HCI_EVENT_HDR_SIZE + h->plen;
-                               } else
-                                       return -EILSEQ;
-                               break;
-
-                       case HCI_ACLDATA_PKT:
-                               if (count >= HCI_ACL_HDR_SIZE) {
-                                       struct hci_acl_hdr *h = buf;
-                                       len = HCI_ACL_HDR_SIZE +
-                                                       __le16_to_cpu(h->dlen);
-                               } else
-                                       return -EILSEQ;
-                               break;
-
-                       case HCI_SCODATA_PKT:
-                               if (count >= HCI_SCO_HDR_SIZE) {
-                                       struct hci_sco_hdr *h = buf;
-                                       len = HCI_SCO_HDR_SIZE + h->dlen;
-                               } else
-                                       return -EILSEQ;
-                               break;
-
-                       case HCI_VENDOR_PKT:
-                               if (count >= HCI_VENDOR_HDR_SIZE) {
-                                       struct hci_vendor_hdr *h = buf;
-                                       len = HCI_VENDOR_HDR_SIZE +
-                                                       __le16_to_cpu(h->dlen);
-                               } else
-                                       return -EILSEQ;
-                               break;
-                       }
-
-                       skb = bt_skb_alloc(len, GFP_ATOMIC);
-                       if (!skb) {
-                               BT_ERR("%s no memory for packet", hdev->name);
-                               return -ENOMEM;
-                       }
-
-                       data->rx_skb[queue] = skb;
-
-                       scb = (void *) skb->cb;
-                       scb->type = type;
-                       scb->expect = len;
-               } else {
-                       /* Continuation */
-
-                       scb = (void *) skb->cb;
-                       len = scb->expect;
-               }
-
-               len = min(len, count);
-
-               memcpy(skb_put(skb, len), buf, len);
-
-               scb->expect -= len;
-
-               if (scb->expect == 0) {
-                       /* Complete frame */
-
-                       data->rx_skb[queue] = NULL;
-
-                       bt_cb(skb)->pkt_type = scb->type;
-                       hci_recv_frame(hdev, skb);
-               }
-
-               count -= len; buf += len;
-       }
-
-       return 0;
-}
-
 static void bpa10x_tx_complete(struct urb *urb)
 {
        struct sk_buff *skb = urb->context;
@@ -184,6 +80,22 @@ done:
        kfree_skb(skb);
 }
 
+#define HCI_VENDOR_HDR_SIZE 5
+
+#define HCI_RECV_VENDOR \
+       .type = HCI_VENDOR_PKT, \
+       .hlen = HCI_VENDOR_HDR_SIZE, \
+       .loff = 3, \
+       .lsize = 2, \
+       .maxlen = HCI_MAX_FRAME_SIZE
+
+static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
+       { H4_RECV_ACL,     .recv = hci_recv_frame },
+       { H4_RECV_SCO,     .recv = hci_recv_frame },
+       { H4_RECV_EVENT,   .recv = hci_recv_frame },
+       { HCI_RECV_VENDOR, .recv = hci_recv_diag  },
+};
+
 static void bpa10x_rx_complete(struct urb *urb)
 {
        struct hci_dev *hdev = urb->context;
@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
                return;
 
        if (urb->status == 0) {
-               if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe),
+               bool idx = usb_pipebulk(urb->pipe);
+
+               data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
                                                urb->transfer_buffer,
-                                               urb->actual_length) < 0) {
+                                               urb->actual_length,
+                                               bpa10x_recv_pkts,
+                                               ARRAY_SIZE(bpa10x_recv_pkts));
+               if (IS_ERR(data->rx_skb[idx])) {
                        BT_ERR("%s corrupted event packet", hdev->name);
                        hdev->stat.err_rx++;
+                       data->rx_skb[idx] = NULL;
                }
        }
 
@@ -304,9 +222,6 @@ static int bpa10x_open(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
-       if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
-               return 0;
-
        err = bpa10x_submit_intr_urb(hdev);
        if (err < 0)
                goto error;
@@ -320,8 +235,6 @@ static int bpa10x_open(struct hci_dev *hdev)
 error:
        usb_kill_anchored_urbs(&data->rx_anchor);
 
-       clear_bit(HCI_RUNNING, &hdev->flags);
-
        return err;
 }
 
@@ -331,9 +244,6 @@ static int bpa10x_close(struct hci_dev *hdev)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
-               return 0;
-
        usb_kill_anchored_urbs(&data->rx_anchor);
 
        return 0;
@@ -350,6 +260,24 @@ static int bpa10x_flush(struct hci_dev *hdev)
        return 0;
 }
 
+static int bpa10x_setup(struct hci_dev *hdev)
+{
+       const u8 req[] = { 0x07 };
+       struct sk_buff *skb;
+
+       BT_DBG("%s", hdev->name);
+
+       /* Read revision string */
+       skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       BT_INFO("%s: %s", hdev->name, (char *)(skb->data + 1));
+
+       kfree_skb(skb);
+       return 0;
+}
+
 static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 {
        struct bpa10x_data *data = hci_get_drvdata(hdev);
@@ -360,9 +288,6 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
 
        BT_DBG("%s", hdev->name);
 
-       if (!test_bit(HCI_RUNNING, &hdev->flags))
-               return -EBUSY;
-
        skb->dev = (void *) hdev;
 
        urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -431,6 +356,25 @@ static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb)
        return 0;
 }
 
+static int bpa10x_set_diag(struct hci_dev *hdev, bool enable)
+{
+       const u8 req[] = { 0x00, enable };
+       struct sk_buff *skb;
+
+       BT_DBG("%s", hdev->name);
+
+       if (!test_bit(HCI_RUNNING, &hdev->flags))
+               return -ENETDOWN;
+
+       /* Enable sniffer operation */
+       skb = __hci_cmd_sync(hdev, 0xfc0e, sizeof(req), req, HCI_INIT_TIMEOUT);
+       if (IS_ERR(skb))
+               return PTR_ERR(skb);
+
+       kfree_skb(skb);
+       return 0;
+}
+
 static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
        struct bpa10x_data *data;
@@ -465,7 +409,9 @@ static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *
        hdev->open     = bpa10x_open;
        hdev->close    = bpa10x_close;
        hdev->flush    = bpa10x_flush;
+       hdev->setup    = bpa10x_setup;
        hdev->send     = bpa10x_send_frame;
+       hdev->set_diag = bpa10x_set_diag;
 
        set_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks);