Blame view
drivers/bluetooth/bpa10x.c
10.7 KB
1da177e4c
|
1 2 3 4 |
/* * * Digianswer Bluetooth USB driver * |
e24b21ec8
|
5 |
* Copyright (C) 2004-2007 Marcel Holtmann <marcel@holtmann.org> |
1da177e4c
|
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
* * * 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 * */ |
1da177e4c
|
23 |
#include <linux/kernel.h> |
e24b21ec8
|
24 |
#include <linux/module.h> |
1da177e4c
|
25 26 27 |
#include <linux/init.h> #include <linux/slab.h> #include <linux/types.h> |
e24b21ec8
|
28 |
#include <linux/sched.h> |
1da177e4c
|
29 |
#include <linux/errno.h> |
e24b21ec8
|
30 |
#include <linux/skbuff.h> |
1da177e4c
|
31 32 33 34 35 |
#include <linux/usb.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> |
943d56b0a
|
36 |
#define VERSION "0.10" |
1da177e4c
|
37 38 39 40 41 42 43 44 45 |
static struct usb_device_id bpa10x_table[] = { /* Tektronix BPA 100/105 (Digianswer) */ { USB_DEVICE(0x08fd, 0x0002) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, bpa10x_table); |
1da177e4c
|
46 |
struct bpa10x_data { |
e24b21ec8
|
47 48 |
struct hci_dev *hdev; struct usb_device *udev; |
1da177e4c
|
49 |
|
e24b21ec8
|
50 51 |
struct usb_anchor tx_anchor; struct usb_anchor rx_anchor; |
1da177e4c
|
52 |
|
e24b21ec8
|
53 |
struct sk_buff *rx_skb[2]; |
1da177e4c
|
54 |
}; |
e24b21ec8
|
55 |
#define HCI_VENDOR_HDR_SIZE 5 |
1da177e4c
|
56 57 |
struct hci_vendor_hdr { |
e24b21ec8
|
58 59 60 |
__u8 type; __le16 snum; __le16 dlen; |
81ca405ae
|
61 |
} __packed; |
1da177e4c
|
62 |
|
e24b21ec8
|
63 |
static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) |
1da177e4c
|
64 |
{ |
e24b21ec8
|
65 66 67 68 69 70 71 72 73 |
struct bpa10x_data *data = hdev->driver_data; 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; |
1da177e4c
|
74 75 |
while (count) { |
e24b21ec8
|
76 77 78 |
struct sk_buff *skb = data->rx_skb[queue]; struct { __u8 type; int expect; } *scb; int type, len = 0; |
1da177e4c
|
79 |
|
e24b21ec8
|
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
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; |
1da177e4c
|
120 |
} |
1da177e4c
|
121 |
|
1da177e4c
|
122 |
skb = bt_skb_alloc(len, GFP_ATOMIC); |
e24b21ec8
|
123 124 125 |
if (!skb) { BT_ERR("%s no memory for packet", hdev->name); return -ENOMEM; |
1da177e4c
|
126 |
} |
1da177e4c
|
127 |
|
e24b21ec8
|
128 |
skb->dev = (void *) hdev; |
1da177e4c
|
129 |
|
e24b21ec8
|
130 |
data->rx_skb[queue] = skb; |
1da177e4c
|
131 |
|
e24b21ec8
|
132 133 134 135 136 |
scb = (void *) skb->cb; scb->type = type; scb->expect = len; } else { /* Continuation */ |
1da177e4c
|
137 |
|
e24b21ec8
|
138 139 |
scb = (void *) skb->cb; len = scb->expect; |
1da177e4c
|
140 |
} |
e24b21ec8
|
141 |
len = min(len, count); |
1da177e4c
|
142 |
|
e24b21ec8
|
143 |
memcpy(skb_put(skb, len), buf, len); |
1da177e4c
|
144 |
|
e24b21ec8
|
145 |
scb->expect -= len; |
1da177e4c
|
146 |
|
e24b21ec8
|
147 148 |
if (scb->expect == 0) { /* Complete frame */ |
1da177e4c
|
149 |
|
e24b21ec8
|
150 |
data->rx_skb[queue] = NULL; |
1da177e4c
|
151 |
|
e24b21ec8
|
152 |
bt_cb(skb)->pkt_type = scb->type; |
1da177e4c
|
153 |
hci_recv_frame(skb); |
1da177e4c
|
154 |
} |
e24b21ec8
|
155 156 |
count -= len; buf += len; |
1da177e4c
|
157 158 159 160 |
} return 0; } |
e24b21ec8
|
161 |
static void bpa10x_tx_complete(struct urb *urb) |
1da177e4c
|
162 |
{ |
e24b21ec8
|
163 164 |
struct sk_buff *skb = urb->context; struct hci_dev *hdev = (struct hci_dev *) skb->dev; |
1da177e4c
|
165 |
|
e24b21ec8
|
166 167 |
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, urb->actual_length); |
1da177e4c
|
168 |
|
e24b21ec8
|
169 170 171 172 173 |
if (!test_bit(HCI_RUNNING, &hdev->flags)) goto done; if (!urb->status) hdev->stat.byte_tx += urb->transfer_buffer_length; |
1da177e4c
|
174 |
else |
e24b21ec8
|
175 |
hdev->stat.err_tx++; |
1da177e4c
|
176 |
|
e24b21ec8
|
177 178 |
done: kfree(urb->setup_packet); |
1da177e4c
|
179 |
|
e24b21ec8
|
180 181 182 183 184 185 186 187 |
kfree_skb(skb); } static void bpa10x_rx_complete(struct urb *urb) { struct hci_dev *hdev = urb->context; struct bpa10x_data *data = hdev->driver_data; int err; |
1da177e4c
|
188 |
|
e24b21ec8
|
189 190 |
BT_DBG("%s urb %p status %d count %d", hdev->name, urb, urb->status, urb->actual_length); |
1da177e4c
|
191 |
|
e24b21ec8
|
192 193 |
if (!test_bit(HCI_RUNNING, &hdev->flags)) return; |
1da177e4c
|
194 |
|
e24b21ec8
|
195 196 197 198 199 200 201 |
if (urb->status == 0) { if (bpa10x_recv(hdev, usb_pipebulk(urb->pipe), urb->transfer_buffer, urb->actual_length) < 0) { BT_ERR("%s corrupted event packet", hdev->name); hdev->stat.err_rx++; } |
1da177e4c
|
202 |
} |
e24b21ec8
|
203 204 205 206 207 208 209 |
usb_anchor_urb(urb, &data->rx_anchor); err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { BT_ERR("%s urb %p failed to resubmit (%d)", hdev->name, urb, -err); usb_unanchor_urb(urb); |
1da177e4c
|
210 211 |
} } |
e24b21ec8
|
212 |
static inline int bpa10x_submit_intr_urb(struct hci_dev *hdev) |
1da177e4c
|
213 |
{ |
e24b21ec8
|
214 215 216 217 218 |
struct bpa10x_data *data = hdev->driver_data; struct urb *urb; unsigned char *buf; unsigned int pipe; int err, size = 16; |
1da177e4c
|
219 |
|
e24b21ec8
|
220 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
221 |
|
e24b21ec8
|
222 223 224 |
urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; |
1da177e4c
|
225 |
|
e24b21ec8
|
226 227 228 229 230 |
buf = kmalloc(size, GFP_KERNEL); if (!buf) { usb_free_urb(urb); return -ENOMEM; } |
1da177e4c
|
231 |
|
e24b21ec8
|
232 |
pipe = usb_rcvintpipe(data->udev, 0x81); |
1da177e4c
|
233 |
|
e24b21ec8
|
234 235 |
usb_fill_int_urb(urb, data->udev, pipe, buf, size, bpa10x_rx_complete, hdev, 1); |
1da177e4c
|
236 |
|
e24b21ec8
|
237 |
urb->transfer_flags |= URB_FREE_BUFFER; |
1da177e4c
|
238 |
|
e24b21ec8
|
239 |
usb_anchor_urb(urb, &data->rx_anchor); |
1da177e4c
|
240 |
|
e24b21ec8
|
241 242 243 244 245 |
err = usb_submit_urb(urb, GFP_KERNEL); if (err < 0) { BT_ERR("%s urb %p submission failed (%d)", hdev->name, urb, -err); usb_unanchor_urb(urb); |
1da177e4c
|
246 |
} |
e24b21ec8
|
247 |
usb_free_urb(urb); |
1da177e4c
|
248 |
|
e24b21ec8
|
249 |
return err; |
1da177e4c
|
250 |
} |
e24b21ec8
|
251 |
static inline int bpa10x_submit_bulk_urb(struct hci_dev *hdev) |
1da177e4c
|
252 |
{ |
e24b21ec8
|
253 |
struct bpa10x_data *data = hdev->driver_data; |
1da177e4c
|
254 |
struct urb *urb; |
1da177e4c
|
255 |
unsigned char *buf; |
e24b21ec8
|
256 257 |
unsigned int pipe; int err, size = 64; |
1da177e4c
|
258 |
|
e24b21ec8
|
259 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
260 |
|
e24b21ec8
|
261 |
urb = usb_alloc_urb(0, GFP_KERNEL); |
1da177e4c
|
262 |
if (!urb) |
e24b21ec8
|
263 |
return -ENOMEM; |
1da177e4c
|
264 |
|
e24b21ec8
|
265 |
buf = kmalloc(size, GFP_KERNEL); |
1da177e4c
|
266 267 |
if (!buf) { usb_free_urb(urb); |
e24b21ec8
|
268 |
return -ENOMEM; |
1da177e4c
|
269 |
} |
e24b21ec8
|
270 |
pipe = usb_rcvbulkpipe(data->udev, 0x82); |
1da177e4c
|
271 |
|
e24b21ec8
|
272 273 |
usb_fill_bulk_urb(urb, data->udev, pipe, buf, size, bpa10x_rx_complete, hdev); |
1da177e4c
|
274 |
|
e24b21ec8
|
275 |
urb->transfer_flags |= URB_FREE_BUFFER; |
1da177e4c
|
276 |
|
e24b21ec8
|
277 |
usb_anchor_urb(urb, &data->rx_anchor); |
1da177e4c
|
278 |
|
e24b21ec8
|
279 280 281 282 283 |
err = usb_submit_urb(urb, GFP_KERNEL); if (err < 0) { BT_ERR("%s urb %p submission failed (%d)", hdev->name, urb, -err); usb_unanchor_urb(urb); |
1da177e4c
|
284 |
} |
1da177e4c
|
285 |
usb_free_urb(urb); |
e24b21ec8
|
286 287 |
return err; |
1da177e4c
|
288 289 290 291 292 |
} static int bpa10x_open(struct hci_dev *hdev) { struct bpa10x_data *data = hdev->driver_data; |
1da177e4c
|
293 |
int err; |
e24b21ec8
|
294 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
295 296 297 |
if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) return 0; |
e24b21ec8
|
298 299 300 |
err = bpa10x_submit_intr_urb(hdev); if (err < 0) goto error; |
1da177e4c
|
301 |
|
e24b21ec8
|
302 303 304 |
err = bpa10x_submit_bulk_urb(hdev); if (err < 0) goto error; |
1da177e4c
|
305 |
|
e24b21ec8
|
306 |
return 0; |
1da177e4c
|
307 |
|
e24b21ec8
|
308 309 |
error: usb_kill_anchored_urbs(&data->rx_anchor); |
1da177e4c
|
310 |
|
e24b21ec8
|
311 |
clear_bit(HCI_RUNNING, &hdev->flags); |
1da177e4c
|
312 313 314 315 316 317 318 |
return err; } static int bpa10x_close(struct hci_dev *hdev) { struct bpa10x_data *data = hdev->driver_data; |
1da177e4c
|
319 |
|
e24b21ec8
|
320 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
321 322 323 |
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; |
e24b21ec8
|
324 |
usb_kill_anchored_urbs(&data->rx_anchor); |
1da177e4c
|
325 326 327 328 329 330 331 |
return 0; } static int bpa10x_flush(struct hci_dev *hdev) { struct bpa10x_data *data = hdev->driver_data; |
e24b21ec8
|
332 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
333 |
|
e24b21ec8
|
334 |
usb_kill_anchored_urbs(&data->tx_anchor); |
1da177e4c
|
335 336 337 338 339 340 341 |
return 0; } static int bpa10x_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; |
e24b21ec8
|
342 343 344 345 346 |
struct bpa10x_data *data = hdev->driver_data; struct usb_ctrlrequest *dr; struct urb *urb; unsigned int pipe; int err; |
1da177e4c
|
347 |
|
e24b21ec8
|
348 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
349 350 351 |
if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; |
e24b21ec8
|
352 353 354 |
urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; |
1da177e4c
|
355 356 |
/* Prepend skb with frame type */ |
e24b21ec8
|
357 |
*skb_push(skb, 1) = bt_cb(skb)->pkt_type; |
1da177e4c
|
358 |
|
0d48d9394
|
359 |
switch (bt_cb(skb)->pkt_type) { |
1da177e4c
|
360 |
case HCI_COMMAND_PKT: |
e24b21ec8
|
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 |
dr = kmalloc(sizeof(*dr), GFP_ATOMIC); if (!dr) { usb_free_urb(urb); return -ENOMEM; } dr->bRequestType = USB_TYPE_VENDOR; 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, bpa10x_tx_complete, skb); |
1da177e4c
|
377 |
hdev->stat.cmd_tx++; |
1da177e4c
|
378 379 380 |
break; case HCI_ACLDATA_PKT: |
e24b21ec8
|
381 382 383 384 |
pipe = usb_sndbulkpipe(data->udev, 0x02); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, bpa10x_tx_complete, skb); |
1da177e4c
|
385 |
hdev->stat.acl_tx++; |
1da177e4c
|
386 387 388 |
break; case HCI_SCODATA_PKT: |
e24b21ec8
|
389 390 391 392 |
pipe = usb_sndbulkpipe(data->udev, 0x02); usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, bpa10x_tx_complete, skb); |
1da177e4c
|
393 |
hdev->stat.sco_tx++; |
1da177e4c
|
394 |
break; |
1da177e4c
|
395 |
|
e24b21ec8
|
396 |
default: |
cb7cd4293
|
397 |
usb_free_urb(urb); |
e24b21ec8
|
398 399 400 401 |
return -EILSEQ; } usb_anchor_urb(urb, &data->tx_anchor); |
1da177e4c
|
402 |
|
e24b21ec8
|
403 404 405 406 407 408 |
err = usb_submit_urb(urb, GFP_ATOMIC); if (err < 0) { BT_ERR("%s urb %p submission failed", hdev->name, urb); kfree(urb->setup_packet); usb_unanchor_urb(urb); } |
1da177e4c
|
409 |
|
e24b21ec8
|
410 |
usb_free_urb(urb); |
1da177e4c
|
411 412 413 414 415 416 417 |
return 0; } static void bpa10x_destruct(struct hci_dev *hdev) { struct bpa10x_data *data = hdev->driver_data; |
e24b21ec8
|
418 |
BT_DBG("%s", hdev->name); |
1da177e4c
|
419 |
|
cbafe312e
|
420 421 |
kfree_skb(data->rx_skb[0]); kfree_skb(data->rx_skb[1]); |
1da177e4c
|
422 423 424 425 426 |
kfree(data); } static int bpa10x_probe(struct usb_interface *intf, const struct usb_device_id *id) { |
1da177e4c
|
427 |
struct bpa10x_data *data; |
e24b21ec8
|
428 |
struct hci_dev *hdev; |
1da177e4c
|
429 430 431 |
int err; BT_DBG("intf %p id %p", intf, id); |
e24b21ec8
|
432 |
if (intf->cur_altsetting->desc.bInterfaceNumber != 0) |
1da177e4c
|
433 |
return -ENODEV; |
089b1dbbd
|
434 |
data = kzalloc(sizeof(*data), GFP_KERNEL); |
e24b21ec8
|
435 |
if (!data) |
1da177e4c
|
436 |
return -ENOMEM; |
1da177e4c
|
437 |
|
e24b21ec8
|
438 |
data->udev = interface_to_usbdev(intf); |
1da177e4c
|
439 |
|
e24b21ec8
|
440 441 |
init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->rx_anchor); |
1da177e4c
|
442 443 444 |
hdev = hci_alloc_dev(); if (!hdev) { |
1da177e4c
|
445 446 447 |
kfree(data); return -ENOMEM; } |
c13854cef
|
448 |
hdev->bus = HCI_USB; |
1da177e4c
|
449 |
hdev->driver_data = data; |
e24b21ec8
|
450 451 |
data->hdev = hdev; |
1da177e4c
|
452 |
SET_HCIDEV_DEV(hdev, &intf->dev); |
e24b21ec8
|
453 454 455 456 457 |
hdev->open = bpa10x_open; hdev->close = bpa10x_close; hdev->flush = bpa10x_flush; hdev->send = bpa10x_send_frame; hdev->destruct = bpa10x_destruct; |
1da177e4c
|
458 459 |
hdev->owner = THIS_MODULE; |
7a9d40205
|
460 |
set_bit(HCI_QUIRK_NO_RESET, &hdev->quirks); |
1da177e4c
|
461 462 |
err = hci_register_dev(hdev); if (err < 0) { |
1da177e4c
|
463 |
hci_free_dev(hdev); |
e24b21ec8
|
464 |
kfree(data); |
1da177e4c
|
465 466 467 468 469 470 471 472 473 474 475 |
return err; } usb_set_intfdata(intf, data); return 0; } static void bpa10x_disconnect(struct usb_interface *intf) { struct bpa10x_data *data = usb_get_intfdata(intf); |
1da177e4c
|
476 477 |
BT_DBG("intf %p", intf); |
e24b21ec8
|
478 |
if (!data) |
1da177e4c
|
479 480 481 |
return; usb_set_intfdata(intf, NULL); |
e24b21ec8
|
482 |
hci_unregister_dev(data->hdev); |
1da177e4c
|
483 |
|
e24b21ec8
|
484 |
hci_free_dev(data->hdev); |
1da177e4c
|
485 486 487 |
} static struct usb_driver bpa10x_driver = { |
1da177e4c
|
488 489 490 491 492 493 494 495 |
.name = "bpa10x", .probe = bpa10x_probe, .disconnect = bpa10x_disconnect, .id_table = bpa10x_table, }; static int __init bpa10x_init(void) { |
1da177e4c
|
496 |
BT_INFO("Digianswer Bluetooth USB driver ver %s", VERSION); |
e24b21ec8
|
497 |
return usb_register(&bpa10x_driver); |
1da177e4c
|
498 499 500 501 502 503 504 505 506 |
} static void __exit bpa10x_exit(void) { usb_deregister(&bpa10x_driver); } module_init(bpa10x_init); module_exit(bpa10x_exit); |
1da177e4c
|
507 508 509 510 |
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("Digianswer Bluetooth USB driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); |