Blame view
drivers/bluetooth/bfusb.c
16.6 KB
1da177e4c
|
1 2 3 4 |
/* * * AVM BlueFRITZ! USB driver * |
9c724357f
|
5 |
* Copyright (C) 2003-2006 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 24 25 26 27 28 |
#include <linux/module.h> #include <linux/kernel.h> #include <linux/init.h> #include <linux/slab.h> #include <linux/types.h> |
1da177e4c
|
29 30 31 32 33 34 35 36 37 38 |
#include <linux/errno.h> #include <linux/skbuff.h> #include <linux/device.h> #include <linux/firmware.h> #include <linux/usb.h> #include <net/bluetooth/bluetooth.h> #include <net/bluetooth/hci_core.h> |
943d56b0a
|
39 |
#define VERSION "1.2" |
1da177e4c
|
40 41 42 43 44 45 46 47 48 49 50 |
static struct usb_driver bfusb_driver; static struct usb_device_id bfusb_table[] = { /* AVM BlueFRITZ! USB */ { USB_DEVICE(0x057c, 0x2200) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, bfusb_table); |
1da177e4c
|
51 52 53 54 55 56 57 58 59 |
#define BFUSB_MAX_BLOCK_SIZE 256 #define BFUSB_BLOCK_TIMEOUT 3000 #define BFUSB_TX_PROCESS 1 #define BFUSB_TX_WAKEUP 2 #define BFUSB_MAX_BULK_TX 2 #define BFUSB_MAX_BULK_RX 2 |
9c724357f
|
60 |
struct bfusb_data { |
1da177e4c
|
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
struct hci_dev *hdev; unsigned long state; struct usb_device *udev; unsigned int bulk_in_ep; unsigned int bulk_out_ep; unsigned int bulk_pkt_size; rwlock_t lock; struct sk_buff_head transmit_q; struct sk_buff *reassembly; atomic_t pending_tx; struct sk_buff_head pending_q; struct sk_buff_head completed_q; }; |
9c724357f
|
81 |
struct bfusb_data_scb { |
1da177e4c
|
82 83 |
struct urb *urb; }; |
7d12e780e
|
84 85 |
static void bfusb_tx_complete(struct urb *urb); static void bfusb_rx_complete(struct urb *urb); |
1da177e4c
|
86 |
|
9c724357f
|
87 |
static struct urb *bfusb_get_completed(struct bfusb_data *data) |
1da177e4c
|
88 89 90 |
{ struct sk_buff *skb; struct urb *urb = NULL; |
9c724357f
|
91 |
BT_DBG("bfusb %p", data); |
1da177e4c
|
92 |
|
9c724357f
|
93 |
skb = skb_dequeue(&data->completed_q); |
1da177e4c
|
94 |
if (skb) { |
9c724357f
|
95 |
urb = ((struct bfusb_data_scb *) skb->cb)->urb; |
1da177e4c
|
96 97 98 99 100 |
kfree_skb(skb); } return urb; } |
9c724357f
|
101 |
static void bfusb_unlink_urbs(struct bfusb_data *data) |
1da177e4c
|
102 103 104 |
{ struct sk_buff *skb; struct urb *urb; |
9c724357f
|
105 |
BT_DBG("bfusb %p", data); |
1da177e4c
|
106 |
|
9c724357f
|
107 108 |
while ((skb = skb_dequeue(&data->pending_q))) { urb = ((struct bfusb_data_scb *) skb->cb)->urb; |
1da177e4c
|
109 |
usb_kill_urb(urb); |
9c724357f
|
110 |
skb_queue_tail(&data->completed_q, skb); |
1da177e4c
|
111 |
} |
9c724357f
|
112 |
while ((urb = bfusb_get_completed(data))) |
1da177e4c
|
113 114 |
usb_free_urb(urb); } |
9c724357f
|
115 |
static int bfusb_send_bulk(struct bfusb_data *data, struct sk_buff *skb) |
1da177e4c
|
116 |
{ |
9c724357f
|
117 118 |
struct bfusb_data_scb *scb = (void *) skb->cb; struct urb *urb = bfusb_get_completed(data); |
1da177e4c
|
119 |
int err, pipe; |
9c724357f
|
120 |
BT_DBG("bfusb %p skb %p len %d", data, skb, skb->len); |
1da177e4c
|
121 122 123 |
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) return -ENOMEM; |
9c724357f
|
124 |
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); |
1da177e4c
|
125 |
|
9c724357f
|
126 |
usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, skb->len, |
1da177e4c
|
127 128 129 |
bfusb_tx_complete, skb); scb->urb = urb; |
9c724357f
|
130 |
skb_queue_tail(&data->pending_q, skb); |
1da177e4c
|
131 132 133 134 |
err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk tx submit failed urb %p err %d", |
9c724357f
|
135 136 |
data->hdev->name, urb, err); skb_unlink(skb, &data->pending_q); |
1da177e4c
|
137 138 |
usb_free_urb(urb); } else |
9c724357f
|
139 |
atomic_inc(&data->pending_tx); |
1da177e4c
|
140 141 142 |
return err; } |
9c724357f
|
143 |
static void bfusb_tx_wakeup(struct bfusb_data *data) |
1da177e4c
|
144 145 |
{ struct sk_buff *skb; |
9c724357f
|
146 |
BT_DBG("bfusb %p", data); |
1da177e4c
|
147 |
|
9c724357f
|
148 149 |
if (test_and_set_bit(BFUSB_TX_PROCESS, &data->state)) { set_bit(BFUSB_TX_WAKEUP, &data->state); |
1da177e4c
|
150 151 152 153 |
return; } do { |
9c724357f
|
154 |
clear_bit(BFUSB_TX_WAKEUP, &data->state); |
1da177e4c
|
155 |
|
9c724357f
|
156 157 158 159 |
while ((atomic_read(&data->pending_tx) < BFUSB_MAX_BULK_TX) && (skb = skb_dequeue(&data->transmit_q))) { if (bfusb_send_bulk(data, skb) < 0) { skb_queue_head(&data->transmit_q, skb); |
1da177e4c
|
160 161 162 |
break; } } |
9c724357f
|
163 |
} while (test_bit(BFUSB_TX_WAKEUP, &data->state)); |
1da177e4c
|
164 |
|
9c724357f
|
165 |
clear_bit(BFUSB_TX_PROCESS, &data->state); |
1da177e4c
|
166 |
} |
7d12e780e
|
167 |
static void bfusb_tx_complete(struct urb *urb) |
1da177e4c
|
168 169 |
{ struct sk_buff *skb = (struct sk_buff *) urb->context; |
9c724357f
|
170 |
struct bfusb_data *data = (struct bfusb_data *) skb->dev; |
1da177e4c
|
171 |
|
9c724357f
|
172 |
BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len); |
1da177e4c
|
173 |
|
9c724357f
|
174 |
atomic_dec(&data->pending_tx); |
1da177e4c
|
175 |
|
9c724357f
|
176 |
if (!test_bit(HCI_RUNNING, &data->hdev->flags)) |
1da177e4c
|
177 178 179 |
return; if (!urb->status) |
9c724357f
|
180 |
data->hdev->stat.byte_tx += skb->len; |
1da177e4c
|
181 |
else |
9c724357f
|
182 |
data->hdev->stat.err_tx++; |
1da177e4c
|
183 |
|
9c724357f
|
184 |
read_lock(&data->lock); |
1da177e4c
|
185 |
|
9c724357f
|
186 187 |
skb_unlink(skb, &data->pending_q); skb_queue_tail(&data->completed_q, skb); |
1da177e4c
|
188 |
|
9c724357f
|
189 |
bfusb_tx_wakeup(data); |
1da177e4c
|
190 |
|
9c724357f
|
191 |
read_unlock(&data->lock); |
1da177e4c
|
192 |
} |
9c724357f
|
193 |
static int bfusb_rx_submit(struct bfusb_data *data, struct urb *urb) |
1da177e4c
|
194 |
{ |
9c724357f
|
195 |
struct bfusb_data_scb *scb; |
1da177e4c
|
196 197 |
struct sk_buff *skb; int err, pipe, size = HCI_MAX_FRAME_SIZE + 32; |
a418b893a
|
198 |
BT_DBG("bfusb %p urb %p", data, urb); |
1da177e4c
|
199 200 201 |
if (!urb && !(urb = usb_alloc_urb(0, GFP_ATOMIC))) return -ENOMEM; |
9c724357f
|
202 203 |
skb = bt_skb_alloc(size, GFP_ATOMIC); if (!skb) { |
1da177e4c
|
204 205 206 |
usb_free_urb(urb); return -ENOMEM; } |
9c724357f
|
207 |
skb->dev = (void *) data; |
1da177e4c
|
208 |
|
9c724357f
|
209 |
scb = (struct bfusb_data_scb *) skb->cb; |
1da177e4c
|
210 |
scb->urb = urb; |
9c724357f
|
211 |
pipe = usb_rcvbulkpipe(data->udev, data->bulk_in_ep); |
1da177e4c
|
212 |
|
9c724357f
|
213 |
usb_fill_bulk_urb(urb, data->udev, pipe, skb->data, size, |
1da177e4c
|
214 |
bfusb_rx_complete, skb); |
9c724357f
|
215 |
skb_queue_tail(&data->pending_q, skb); |
1da177e4c
|
216 217 218 219 |
err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk rx submit failed urb %p err %d", |
9c724357f
|
220 221 |
data->hdev->name, urb, err); skb_unlink(skb, &data->pending_q); |
1da177e4c
|
222 223 224 225 226 227 |
kfree_skb(skb); usb_free_urb(urb); } return err; } |
9c724357f
|
228 |
static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned char *buf, int len) |
1da177e4c
|
229 |
{ |
9c724357f
|
230 |
BT_DBG("bfusb %p hdr 0x%02x data %p len %d", data, hdr, buf, len); |
1da177e4c
|
231 232 |
if (hdr & 0x10) { |
9c724357f
|
233 |
BT_ERR("%s error in block", data->hdev->name); |
b1fb06830
|
234 |
kfree_skb(data->reassembly); |
9c724357f
|
235 |
data->reassembly = NULL; |
1da177e4c
|
236 237 238 239 240 241 242 |
return -EIO; } if (hdr & 0x04) { struct sk_buff *skb; unsigned char pkt_type; int pkt_len = 0; |
9c724357f
|
243 244 245 246 |
if (data->reassembly) { BT_ERR("%s unexpected start block", data->hdev->name); kfree_skb(data->reassembly); data->reassembly = NULL; |
1da177e4c
|
247 248 249 |
} if (len < 1) { |
9c724357f
|
250 |
BT_ERR("%s no packet type found", data->hdev->name); |
1da177e4c
|
251 252 |
return -EPROTO; } |
9c724357f
|
253 |
pkt_type = *buf++; len--; |
1da177e4c
|
254 255 256 257 |
switch (pkt_type) { case HCI_EVENT_PKT: if (len >= HCI_EVENT_HDR_SIZE) { |
9c724357f
|
258 |
struct hci_event_hdr *hdr = (struct hci_event_hdr *) buf; |
1da177e4c
|
259 260 |
pkt_len = HCI_EVENT_HDR_SIZE + hdr->plen; } else { |
9c724357f
|
261 |
BT_ERR("%s event block is too short", data->hdev->name); |
1da177e4c
|
262 263 264 265 266 267 |
return -EILSEQ; } break; case HCI_ACLDATA_PKT: if (len >= HCI_ACL_HDR_SIZE) { |
9c724357f
|
268 |
struct hci_acl_hdr *hdr = (struct hci_acl_hdr *) buf; |
1da177e4c
|
269 270 |
pkt_len = HCI_ACL_HDR_SIZE + __le16_to_cpu(hdr->dlen); } else { |
9c724357f
|
271 |
BT_ERR("%s data block is too short", data->hdev->name); |
1da177e4c
|
272 273 274 275 276 277 |
return -EILSEQ; } break; case HCI_SCODATA_PKT: if (len >= HCI_SCO_HDR_SIZE) { |
9c724357f
|
278 |
struct hci_sco_hdr *hdr = (struct hci_sco_hdr *) buf; |
1da177e4c
|
279 280 |
pkt_len = HCI_SCO_HDR_SIZE + hdr->dlen; } else { |
9c724357f
|
281 |
BT_ERR("%s audio block is too short", data->hdev->name); |
1da177e4c
|
282 283 284 285 286 287 288 |
return -EILSEQ; } break; } skb = bt_skb_alloc(pkt_len, GFP_ATOMIC); if (!skb) { |
9c724357f
|
289 |
BT_ERR("%s no memory for the packet", data->hdev->name); |
1da177e4c
|
290 291 |
return -ENOMEM; } |
9c724357f
|
292 |
skb->dev = (void *) data->hdev; |
0d48d9394
|
293 |
bt_cb(skb)->pkt_type = pkt_type; |
1da177e4c
|
294 |
|
9c724357f
|
295 |
data->reassembly = skb; |
1da177e4c
|
296 |
} else { |
9c724357f
|
297 298 |
if (!data->reassembly) { BT_ERR("%s unexpected continuation block", data->hdev->name); |
1da177e4c
|
299 300 301 302 303 |
return -EIO; } } if (len > 0) |
9c724357f
|
304 |
memcpy(skb_put(data->reassembly, len), buf, len); |
1da177e4c
|
305 306 |
if (hdr & 0x08) { |
9c724357f
|
307 308 |
hci_recv_frame(data->reassembly); data->reassembly = NULL; |
1da177e4c
|
309 310 311 312 |
} return 0; } |
7d12e780e
|
313 |
static void bfusb_rx_complete(struct urb *urb) |
1da177e4c
|
314 315 |
{ struct sk_buff *skb = (struct sk_buff *) urb->context; |
9c724357f
|
316 |
struct bfusb_data *data = (struct bfusb_data *) skb->dev; |
1da177e4c
|
317 318 319 |
unsigned char *buf = urb->transfer_buffer; int count = urb->actual_length; int err, hdr, len; |
a418b893a
|
320 |
BT_DBG("bfusb %p urb %p skb %p len %d", data, urb, skb, skb->len); |
1da177e4c
|
321 |
|
9c724357f
|
322 |
read_lock(&data->lock); |
1da177e4c
|
323 |
|
9c724357f
|
324 |
if (!test_bit(HCI_RUNNING, &data->hdev->flags)) |
1da177e4c
|
325 326 327 328 |
goto unlock; if (urb->status || !count) goto resubmit; |
9c724357f
|
329 |
data->hdev->stat.byte_rx += count; |
1da177e4c
|
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
skb_put(skb, count); while (count) { hdr = buf[0] | (buf[1] << 8); if (hdr & 0x4000) { len = 0; count -= 2; buf += 2; } else { len = (buf[2] == 0) ? 256 : buf[2]; count -= 3; buf += 3; } if (count < len) { BT_ERR("%s block extends over URB buffer ranges", |
9c724357f
|
348 |
data->hdev->name); |
1da177e4c
|
349 350 351 |
} if ((hdr & 0xe1) == 0xc1) |
9c724357f
|
352 |
bfusb_recv_block(data, hdr, buf, len); |
1da177e4c
|
353 354 355 356 |
count -= len; buf += len; } |
9c724357f
|
357 |
skb_unlink(skb, &data->pending_q); |
1da177e4c
|
358 |
kfree_skb(skb); |
9c724357f
|
359 |
bfusb_rx_submit(data, urb); |
1da177e4c
|
360 |
|
9c724357f
|
361 |
read_unlock(&data->lock); |
1da177e4c
|
362 363 364 365 |
return; resubmit: |
9c724357f
|
366 |
urb->dev = data->udev; |
1da177e4c
|
367 368 369 370 |
err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { BT_ERR("%s bulk resubmit failed urb %p err %d", |
9c724357f
|
371 |
data->hdev->name, urb, err); |
1da177e4c
|
372 373 374 |
} unlock: |
9c724357f
|
375 |
read_unlock(&data->lock); |
1da177e4c
|
376 |
} |
1da177e4c
|
377 378 |
static int bfusb_open(struct hci_dev *hdev) { |
9c724357f
|
379 |
struct bfusb_data *data = hdev->driver_data; |
1da177e4c
|
380 381 |
unsigned long flags; int i, err; |
9c724357f
|
382 |
BT_DBG("hdev %p bfusb %p", hdev, data); |
1da177e4c
|
383 384 385 |
if (test_and_set_bit(HCI_RUNNING, &hdev->flags)) return 0; |
9c724357f
|
386 |
write_lock_irqsave(&data->lock, flags); |
1da177e4c
|
387 |
|
9c724357f
|
388 |
err = bfusb_rx_submit(data, NULL); |
1da177e4c
|
389 390 |
if (!err) { for (i = 1; i < BFUSB_MAX_BULK_RX; i++) |
9c724357f
|
391 |
bfusb_rx_submit(data, NULL); |
1da177e4c
|
392 393 394 |
} else { clear_bit(HCI_RUNNING, &hdev->flags); } |
9c724357f
|
395 |
write_unlock_irqrestore(&data->lock, flags); |
1da177e4c
|
396 397 398 399 400 401 |
return err; } static int bfusb_flush(struct hci_dev *hdev) { |
9c724357f
|
402 |
struct bfusb_data *data = hdev->driver_data; |
1da177e4c
|
403 |
|
9c724357f
|
404 |
BT_DBG("hdev %p bfusb %p", hdev, data); |
1da177e4c
|
405 |
|
9c724357f
|
406 |
skb_queue_purge(&data->transmit_q); |
1da177e4c
|
407 408 409 410 411 412 |
return 0; } static int bfusb_close(struct hci_dev *hdev) { |
9c724357f
|
413 |
struct bfusb_data *data = hdev->driver_data; |
1da177e4c
|
414 |
unsigned long flags; |
9c724357f
|
415 |
BT_DBG("hdev %p bfusb %p", hdev, data); |
1da177e4c
|
416 417 418 |
if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; |
9c724357f
|
419 420 |
write_lock_irqsave(&data->lock, flags); write_unlock_irqrestore(&data->lock, flags); |
1da177e4c
|
421 |
|
9c724357f
|
422 |
bfusb_unlink_urbs(data); |
1da177e4c
|
423 424 425 426 427 428 429 430 |
bfusb_flush(hdev); return 0; } static int bfusb_send_frame(struct sk_buff *skb) { struct hci_dev *hdev = (struct hci_dev *) skb->dev; |
9c724357f
|
431 |
struct bfusb_data *data; |
1da177e4c
|
432 433 434 |
struct sk_buff *nskb; unsigned char buf[3]; int sent = 0, size, count; |
0d48d9394
|
435 |
BT_DBG("hdev %p skb %p type %d len %d", hdev, skb, bt_cb(skb)->pkt_type, skb->len); |
1da177e4c
|
436 437 438 439 440 441 442 443 |
if (!hdev) { BT_ERR("Frame for unknown HCI device (hdev=NULL)"); return -ENODEV; } if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; |
9c724357f
|
444 |
data = hdev->driver_data; |
1da177e4c
|
445 |
|
0d48d9394
|
446 |
switch (bt_cb(skb)->pkt_type) { |
1da177e4c
|
447 448 449 450 451 452 453 454 455 456 457 458 |
case HCI_COMMAND_PKT: hdev->stat.cmd_tx++; break; case HCI_ACLDATA_PKT: hdev->stat.acl_tx++; break; case HCI_SCODATA_PKT: hdev->stat.sco_tx++; break; }; /* Prepend skb with frame type */ |
0d48d9394
|
459 |
memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1); |
1da177e4c
|
460 461 462 463 |
count = skb->len; /* Max HCI frame size seems to be 1511 + 1 */ |
9c724357f
|
464 465 |
nskb = bt_skb_alloc(count + 32, GFP_ATOMIC); if (!nskb) { |
1da177e4c
|
466 467 468 |
BT_ERR("Can't allocate memory for new packet"); return -ENOMEM; } |
9c724357f
|
469 |
nskb->dev = (void *) data; |
1da177e4c
|
470 471 472 473 474 475 476 477 478 |
while (count) { size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE); buf[0] = 0xc1 | ((sent == 0) ? 0x04 : 0) | ((count == size) ? 0x08 : 0); buf[1] = 0x00; buf[2] = (size == BFUSB_MAX_BLOCK_SIZE) ? 0 : size; memcpy(skb_put(nskb, 3), buf, 3); |
d626f62b1
|
479 |
skb_copy_from_linear_data_offset(skb, sent, skb_put(nskb, size), size); |
1da177e4c
|
480 481 482 483 484 485 |
sent += size; count -= size; } /* Don't send frame with multiple size of bulk max packet */ |
9c724357f
|
486 |
if ((nskb->len % data->bulk_pkt_size) == 0) { |
1da177e4c
|
487 488 489 490 |
buf[0] = 0xdd; buf[1] = 0x00; memcpy(skb_put(nskb, 2), buf, 2); } |
9c724357f
|
491 |
read_lock(&data->lock); |
1da177e4c
|
492 |
|
9c724357f
|
493 494 |
skb_queue_tail(&data->transmit_q, nskb); bfusb_tx_wakeup(data); |
1da177e4c
|
495 |
|
9c724357f
|
496 |
read_unlock(&data->lock); |
1da177e4c
|
497 498 499 500 501 502 503 504 |
kfree_skb(skb); return 0; } static void bfusb_destruct(struct hci_dev *hdev) { |
9c724357f
|
505 |
struct bfusb_data *data = hdev->driver_data; |
1da177e4c
|
506 |
|
9c724357f
|
507 |
BT_DBG("hdev %p bfusb %p", hdev, data); |
1da177e4c
|
508 |
|
9c724357f
|
509 |
kfree(data); |
1da177e4c
|
510 511 512 513 514 515 |
} static int bfusb_ioctl(struct hci_dev *hdev, unsigned int cmd, unsigned long arg) { return -ENOIOCTLCMD; } |
8187b4fb9
|
516 517 |
static int bfusb_load_firmware(struct bfusb_data *data, const unsigned char *firmware, int count) |
1da177e4c
|
518 519 520 |
{ unsigned char *buf; int err, pipe, len, size, sent = 0; |
9c724357f
|
521 |
BT_DBG("bfusb %p udev %p", data, data->udev); |
1da177e4c
|
522 523 |
BT_INFO("BlueFRITZ! USB loading firmware"); |
6b441fab2
|
524 525 526 527 528 |
buf = kmalloc(BFUSB_MAX_BLOCK_SIZE + 3, GFP_KERNEL); if (!buf) { BT_ERR("Can't allocate memory chunk for firmware"); return -ENOMEM; } |
9c724357f
|
529 |
pipe = usb_sndctrlpipe(data->udev, 0); |
1da177e4c
|
530 |
|
9c724357f
|
531 |
if (usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION, |
1da177e4c
|
532 533 |
0, 1, 0, NULL, 0, USB_CTRL_SET_TIMEOUT) < 0) { BT_ERR("Can't change to loading configuration"); |
6b441fab2
|
534 |
kfree(buf); |
1da177e4c
|
535 536 |
return -EBUSY; } |
9c724357f
|
537 |
data->udev->toggle[0] = data->udev->toggle[1] = 0; |
1da177e4c
|
538 |
|
9c724357f
|
539 |
pipe = usb_sndbulkpipe(data->udev, data->bulk_out_ep); |
1da177e4c
|
540 541 542 543 544 |
while (count) { size = min_t(uint, count, BFUSB_MAX_BLOCK_SIZE + 3); memcpy(buf, firmware + sent, size); |
9c724357f
|
545 |
err = usb_bulk_msg(data->udev, pipe, buf, size, |
1da177e4c
|
546 547 548 549 550 551 552 553 554 555 |
&len, BFUSB_BLOCK_TIMEOUT); if (err || (len != size)) { BT_ERR("Error in firmware loading"); goto error; } sent += size; count -= size; } |
9c724357f
|
556 557 558 |
err = usb_bulk_msg(data->udev, pipe, NULL, 0, &len, BFUSB_BLOCK_TIMEOUT); if (err < 0) { |
1da177e4c
|
559 560 561 |
BT_ERR("Error in null packet request"); goto error; } |
9c724357f
|
562 |
pipe = usb_sndctrlpipe(data->udev, 0); |
1da177e4c
|
563 |
|
9c724357f
|
564 565 566 |
err = usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION, 0, 2, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); if (err < 0) { |
1da177e4c
|
567 568 569 |
BT_ERR("Can't change to running configuration"); goto error; } |
9c724357f
|
570 |
data->udev->toggle[0] = data->udev->toggle[1] = 0; |
1da177e4c
|
571 572 573 574 575 576 577 578 |
BT_INFO("BlueFRITZ! USB device ready"); kfree(buf); return 0; error: kfree(buf); |
9c724357f
|
579 |
pipe = usb_sndctrlpipe(data->udev, 0); |
1da177e4c
|
580 |
|
9c724357f
|
581 |
usb_control_msg(data->udev, pipe, USB_REQ_SET_CONFIGURATION, |
1da177e4c
|
582 583 584 585 586 587 588 589 590 591 592 593 |
0, 0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT); return err; } static int bfusb_probe(struct usb_interface *intf, const struct usb_device_id *id) { const struct firmware *firmware; struct usb_device *udev = interface_to_usbdev(intf); struct usb_host_endpoint *bulk_out_ep; struct usb_host_endpoint *bulk_in_ep; struct hci_dev *hdev; |
9c724357f
|
594 |
struct bfusb_data *data; |
1da177e4c
|
595 596 |
BT_DBG("intf %p id %p", intf, id); |
1da177e4c
|
597 598 599 600 601 602 603 604 605 606 607 608 609 |
/* Check number of endpoints */ if (intf->cur_altsetting->desc.bNumEndpoints < 2) return -EIO; bulk_out_ep = &intf->cur_altsetting->endpoint[0]; bulk_in_ep = &intf->cur_altsetting->endpoint[1]; if (!bulk_out_ep || !bulk_in_ep) { BT_ERR("Bulk endpoints not found"); goto done; } /* Initialize control structure and load firmware */ |
9c724357f
|
610 611 |
data = kzalloc(sizeof(struct bfusb_data), GFP_KERNEL); if (!data) { |
1da177e4c
|
612 613 614 |
BT_ERR("Can't allocate memory for control structure"); goto done; } |
9c724357f
|
615 616 617 618 |
data->udev = udev; data->bulk_in_ep = bulk_in_ep->desc.bEndpointAddress; data->bulk_out_ep = bulk_out_ep->desc.bEndpointAddress; data->bulk_pkt_size = le16_to_cpu(bulk_out_ep->desc.wMaxPacketSize); |
1da177e4c
|
619 |
|
9c724357f
|
620 |
rwlock_init(&data->lock); |
1da177e4c
|
621 |
|
9c724357f
|
622 |
data->reassembly = NULL; |
1da177e4c
|
623 |
|
9c724357f
|
624 625 626 |
skb_queue_head_init(&data->transmit_q); skb_queue_head_init(&data->pending_q); skb_queue_head_init(&data->completed_q); |
1da177e4c
|
627 628 629 630 631 |
if (request_firmware(&firmware, "bfubase.frm", &udev->dev) < 0) { BT_ERR("Firmware request failed"); goto error; } |
a418b893a
|
632 |
BT_DBG("firmware data %p size %zu", firmware->data, firmware->size); |
1da177e4c
|
633 |
|
9c724357f
|
634 |
if (bfusb_load_firmware(data, firmware->data, firmware->size) < 0) { |
1da177e4c
|
635 636 637 638 639 640 641 642 643 644 645 646 |
BT_ERR("Firmware loading failed"); goto release; } release_firmware(firmware); /* Initialize and register HCI device */ hdev = hci_alloc_dev(); if (!hdev) { BT_ERR("Can't allocate HCI device"); goto error; } |
9c724357f
|
647 |
data->hdev = hdev; |
1da177e4c
|
648 |
|
c13854cef
|
649 |
hdev->bus = HCI_USB; |
9c724357f
|
650 |
hdev->driver_data = data; |
1da177e4c
|
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 |
SET_HCIDEV_DEV(hdev, &intf->dev); hdev->open = bfusb_open; hdev->close = bfusb_close; hdev->flush = bfusb_flush; hdev->send = bfusb_send_frame; hdev->destruct = bfusb_destruct; hdev->ioctl = bfusb_ioctl; hdev->owner = THIS_MODULE; if (hci_register_dev(hdev) < 0) { BT_ERR("Can't register HCI device"); hci_free_dev(hdev); goto error; } |
9c724357f
|
667 |
usb_set_intfdata(intf, data); |
1da177e4c
|
668 669 670 671 672 673 674 |
return 0; release: release_firmware(firmware); error: |
9c724357f
|
675 |
kfree(data); |
1da177e4c
|
676 677 678 679 680 681 682 |
done: return -EIO; } static void bfusb_disconnect(struct usb_interface *intf) { |
9c724357f
|
683 684 |
struct bfusb_data *data = usb_get_intfdata(intf); struct hci_dev *hdev = data->hdev; |
1da177e4c
|
685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 |
BT_DBG("intf %p", intf); if (!hdev) return; usb_set_intfdata(intf, NULL); bfusb_close(hdev); if (hci_unregister_dev(hdev) < 0) BT_ERR("Can't unregister HCI device %s", hdev->name); hci_free_dev(hdev); } static struct usb_driver bfusb_driver = { |
1da177e4c
|
702 703 704 705 706 707 708 709 710 711 712 |
.name = "bfusb", .probe = bfusb_probe, .disconnect = bfusb_disconnect, .id_table = bfusb_table, }; static int __init bfusb_init(void) { int err; BT_INFO("BlueFRITZ! USB driver ver %s", VERSION); |
9c724357f
|
713 714 |
err = usb_register(&bfusb_driver); if (err < 0) |
1da177e4c
|
715 716 717 718 719 720 721 722 723 724 725 726 |
BT_ERR("Failed to register BlueFRITZ! USB driver"); return err; } static void __exit bfusb_exit(void) { usb_deregister(&bfusb_driver); } module_init(bfusb_init); module_exit(bfusb_exit); |
1da177e4c
|
727 728 729 730 |
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); MODULE_DESCRIPTION("BlueFRITZ! USB driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); |
2312119af
|
731 |
MODULE_FIRMWARE("bfubase.frm"); |