summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcel Holtmann <marcel@holtmann.org>2015-10-07 21:06:53 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2015-10-08 03:04:27 -0400
commit943cc592195ea458058c121d9c4d7481d0f28be1 (patch)
tree314fc8f985ade8eb5542b54bcb264f6030007efb
parent881f7e86a1e0322fbda42c92a36b13c44120bca2 (diff)
Bluetooth: bpa10x: Use h4_recv_buf helper for frame reassembly
The manually coded frame reassembly is actually broken. The h4_recv_buf helper from the UART driver is a perfect fit for frame reassembly for this driver. So just export that function and use it here as well. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
-rw-r--r--drivers/bluetooth/Kconfig1
-rw-r--r--drivers/bluetooth/bpa10x.c136
-rw-r--r--drivers/bluetooth/hci_h4.c1
3 files changed, 29 insertions, 109 deletions
diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig
index 62999546a301..c9c5dd0bad36 100644
--- a/drivers/bluetooth/Kconfig
+++ b/drivers/bluetooth/Kconfig
@@ -184,6 +184,7 @@ config BT_HCIBCM203X
184config BT_HCIBPA10X 184config BT_HCIBPA10X
185 tristate "HCI BPA10x USB driver" 185 tristate "HCI BPA10x USB driver"
186 depends on USB 186 depends on USB
187 select BT_HCIUART_H4
187 help 188 help
188 Bluetooth HCI BPA10x USB driver. 189 Bluetooth HCI BPA10x USB driver.
189 This driver provides support for the Digianswer BPA 100/105 Bluetooth 190 This driver provides support for the Digianswer BPA 100/105 Bluetooth
diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c
index a1a0f80212b3..49c397e21b39 100644
--- a/drivers/bluetooth/bpa10x.c
+++ b/drivers/bluetooth/bpa10x.c
@@ -35,7 +35,9 @@
35#include <net/bluetooth/bluetooth.h> 35#include <net/bluetooth/bluetooth.h>
36#include <net/bluetooth/hci_core.h> 36#include <net/bluetooth/hci_core.h>
37 37
38#define VERSION "0.10" 38#include "hci_uart.h"
39
40#define VERSION "0.11"
39 41
40static const struct usb_device_id bpa10x_table[] = { 42static const struct usb_device_id bpa10x_table[] = {
41 /* Tektronix BPA 100/105 (Digianswer) */ 43 /* Tektronix BPA 100/105 (Digianswer) */
@@ -56,112 +58,6 @@ struct bpa10x_data {
56 struct sk_buff *rx_skb[2]; 58 struct sk_buff *rx_skb[2];
57}; 59};
58 60
59#define HCI_VENDOR_HDR_SIZE 5
60
61struct hci_vendor_hdr {
62 __u8 type;
63 __le16 snum;
64 __le16 dlen;
65} __packed;
66
67static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count)
68{
69 struct bpa10x_data *data = hci_get_drvdata(hdev);
70
71 BT_DBG("%s queue %d buffer %p count %d", hdev->name,
72 queue, buf, count);
73
74 if (queue < 0 || queue > 1)
75 return -EILSEQ;
76
77 hdev->stat.byte_rx += count;
78
79 while (count) {
80 struct sk_buff *skb = data->rx_skb[queue];
81 struct { __u8 type; int expect; } *scb;
82 int type, len = 0;
83
84 if (!skb) {
85 /* Start of the frame */
86
87 type = *((__u8 *) buf);
88 count--; buf++;
89
90 switch (type) {
91 case HCI_EVENT_PKT:
92 if (count >= HCI_EVENT_HDR_SIZE) {
93 struct hci_event_hdr *h = buf;
94 len = HCI_EVENT_HDR_SIZE + h->plen;
95 } else
96 return -EILSEQ;
97 break;
98
99 case HCI_ACLDATA_PKT:
100 if (count >= HCI_ACL_HDR_SIZE) {
101 struct hci_acl_hdr *h = buf;
102 len = HCI_ACL_HDR_SIZE +
103 __le16_to_cpu(h->dlen);
104 } else
105 return -EILSEQ;
106 break;
107
108 case HCI_SCODATA_PKT:
109 if (count >= HCI_SCO_HDR_SIZE) {
110 struct hci_sco_hdr *h = buf;
111 len = HCI_SCO_HDR_SIZE + h->dlen;
112 } else
113 return -EILSEQ;
114 break;
115
116 case HCI_VENDOR_PKT:
117 if (count >= HCI_VENDOR_HDR_SIZE) {
118 struct hci_vendor_hdr *h = buf;
119 len = HCI_VENDOR_HDR_SIZE +
120 __le16_to_cpu(h->dlen);
121 } else
122 return -EILSEQ;
123 break;
124 }
125
126 skb = bt_skb_alloc(len, GFP_ATOMIC);
127 if (!skb) {
128 BT_ERR("%s no memory for packet", hdev->name);
129 return -ENOMEM;
130 }
131
132 data->rx_skb[queue] = skb;
133
134 scb = (void *) skb->cb;
135 scb->type = type;
136 scb->expect = len;
137 } else {
138 /* Continuation */
139
140 scb = (void *) skb->cb;
141 len = scb->expect;
142 }
143
144 len = min(len, count);
145
146 memcpy(skb_put(skb, len), buf, len);
147
148 scb->expect -= len;
149
150 if (scb->expect == 0) {
151 /* Complete frame */
152
153 data->rx_skb[queue] = NULL;
154
155 bt_cb(skb)->pkt_type = scb->type;
156 hci_recv_frame(hdev, skb);
157 }
158
159 count -= len; buf += len;
160 }
161
162 return 0;
163}
164
165static void bpa10x_tx_complete(struct urb *urb) 61static void bpa10x_tx_complete(struct urb *urb)
166{ 62{
167 struct sk_buff *skb = urb->context; 63 struct sk_buff *skb = urb->context;
@@ -184,6 +80,22 @@ done:
184 kfree_skb(skb); 80 kfree_skb(skb);
185} 81}
186 82
83#define HCI_VENDOR_HDR_SIZE 5
84
85#define HCI_RECV_VENDOR \
86 .type = HCI_VENDOR_PKT, \
87 .hlen = HCI_VENDOR_HDR_SIZE, \
88 .loff = 3, \
89 .lsize = 2, \
90 .maxlen = HCI_MAX_FRAME_SIZE
91
92static const struct h4_recv_pkt bpa10x_recv_pkts[] = {
93 { H4_RECV_ACL, .recv = hci_recv_frame },
94 { H4_RECV_SCO, .recv = hci_recv_frame },
95 { H4_RECV_EVENT, .recv = hci_recv_frame },
96 { HCI_RECV_VENDOR, .recv = hci_recv_diag },
97};
98
187static void bpa10x_rx_complete(struct urb *urb) 99static void bpa10x_rx_complete(struct urb *urb)
188{ 100{
189 struct hci_dev *hdev = urb->context; 101 struct hci_dev *hdev = urb->context;
@@ -197,11 +109,17 @@ static void bpa10x_rx_complete(struct urb *urb)
197 return; 109 return;
198 110
199 if (urb->status == 0) { 111 if (urb->status == 0) {
200 if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe), 112 bool idx = usb_pipebulk(urb->pipe);
113
114 data->rx_skb[idx] = h4_recv_buf(hdev, data->rx_skb[idx],
201 urb->transfer_buffer, 115 urb->transfer_buffer,
202 urb->actual_length) < 0) { 116 urb->actual_length,
117 bpa10x_recv_pkts,
118 ARRAY_SIZE(bpa10x_recv_pkts));
119 if (IS_ERR(data->rx_skb[idx])) {
203 BT_ERR("%s corrupted event packet", hdev->name); 120 BT_ERR("%s corrupted event packet", hdev->name);
204 hdev->stat.err_rx++; 121 hdev->stat.err_rx++;
122 data->rx_skb[idx] = NULL;
205 } 123 }
206 } 124 }
207 125
diff --git a/drivers/bluetooth/hci_h4.c b/drivers/bluetooth/hci_h4.c
index eec3f28e4bb9..a6fce48da0fb 100644
--- a/drivers/bluetooth/hci_h4.c
+++ b/drivers/bluetooth/hci_h4.c
@@ -266,3 +266,4 @@ struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
266 266
267 return skb; 267 return skb;
268} 268}
269EXPORT_SYMBOL_GPL(h4_recv_buf);