This source file includes following definitions.
- ubt_match
- ubt_attach
- ubt_detach
- ubt_activate
- ubt_set_isoc_config
- ubt_abortdealloc
- ubt_enable
- ubt_disable
- ubt_xmit_cmd_start
- ubt_xmit_cmd_complete
- ubt_xmit_acl_start
- ubt_xmit_acl_complete
- ubt_xmit_sco_start
- ubt_xmit_sco_start1
- ubt_xmit_sco_complete
- ubt_mbufload
- ubt_recv_event
- ubt_recv_acl_start
- ubt_recv_acl_complete
- ubt_recv_sco_start1
- ubt_recv_sco_complete
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76 #include <sys/cdefs.h>
77
78 #include <sys/param.h>
79 #include <sys/device.h>
80 #include <sys/ioctl.h>
81 #include <sys/kernel.h>
82 #include <sys/malloc.h>
83 #include <sys/mbuf.h>
84 #include <sys/proc.h>
85 #include <sys/sysctl.h>
86 #include <sys/systm.h>
87
88 #include <dev/usb/usb.h>
89 #include <dev/usb/usbdi.h>
90 #include <dev/usb/usbdi_util.h>
91 #include <dev/usb/usbdevs.h>
92
93 #include <netbt/bluetooth.h>
94 #include <netbt/hci.h>
95
96
97
98
99
100 #undef DPRINTF
101 #undef DPRINTFN
102
103 #ifdef UBT_DEBUG
104 int ubt_debug = UBT_DEBUG;
105
106 #define DPRINTF(fmt, args...) do { \
107 if (ubt_debug) \
108 printf("%s: "fmt, __func__ , ##args); \
109 } while (0)
110
111 #define DPRINTFN(n, fmt, args...) do { \
112 if (ubt_debug > (n)) \
113 printf("%s: "fmt, __func__ , ##args); \
114 } while (0)
115
116 #else
117 #define DPRINTF(...)
118 #define DPRINTFN(...)
119 #endif
120
121
122
123
124
125
126
127
128
129
130
131
132 #define UBT_BUFSIZ_CMD (HCI_CMD_PKT_SIZE - 1)
133 #define UBT_BUFSIZ_ACL (2048 - 1)
134 #define UBT_BUFSIZ_EVENT (HCI_EVENT_PKT_SIZE - 1)
135
136
137 #define UBT_CMD_TIMEOUT USBD_DEFAULT_TIMEOUT
138 #define UBT_ACL_TIMEOUT USBD_DEFAULT_TIMEOUT
139
140
141
142
143
144
145
146
147
148
149 #define UBT_NXFERS 3
150 #define UBT_NFRAMES 10
151
152 struct ubt_isoc_xfer {
153 struct ubt_softc *softc;
154 usbd_xfer_handle xfer;
155 uint8_t *buf;
156 uint16_t size[UBT_NFRAMES];
157 int busy;
158 };
159
160 struct ubt_softc {
161 struct device sc_dev;
162 usbd_device_handle sc_udev;
163 int sc_refcnt;
164 int sc_dying;
165
166
167 usbd_interface_handle sc_iface0;
168
169
170 usbd_xfer_handle sc_cmd_xfer;
171 uint8_t *sc_cmd_buf;
172
173
174 int sc_evt_addr;
175 usbd_pipe_handle sc_evt_pipe;
176 uint8_t *sc_evt_buf;
177
178
179 int sc_aclrd_addr;
180 usbd_pipe_handle sc_aclrd_pipe;
181 usbd_xfer_handle sc_aclrd_xfer;
182 uint8_t *sc_aclrd_buf;
183 int sc_aclrd_busy;
184
185
186 int sc_aclwr_addr;
187 usbd_pipe_handle sc_aclwr_pipe;
188 usbd_xfer_handle sc_aclwr_xfer;
189 uint8_t *sc_aclwr_buf;
190
191
192 usbd_interface_handle sc_iface1;
193 struct sysctllog *sc_log;
194 int sc_config;
195 int sc_alt_config;
196
197
198 int sc_scord_addr;
199 usbd_pipe_handle sc_scord_pipe;
200 int sc_scord_size;
201 struct ubt_isoc_xfer sc_scord[UBT_NXFERS];
202 struct mbuf *sc_scord_mbuf;
203
204
205 int sc_scowr_addr;
206 usbd_pipe_handle sc_scowr_pipe;
207 int sc_scowr_size;
208 struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
209 struct mbuf *sc_scowr_mbuf;
210
211
212 struct hci_unit sc_unit;
213
214
215 int sc_ok;
216 };
217
218
219
220
221 int ubt_enable(struct hci_unit *);
222 void ubt_disable(struct hci_unit *);
223
224 void ubt_xmit_cmd_start(struct hci_unit *);
225 void ubt_xmit_cmd_complete(usbd_xfer_handle,
226 usbd_private_handle, usbd_status);
227
228 void ubt_xmit_acl_start(struct hci_unit *);
229 void ubt_xmit_acl_complete(usbd_xfer_handle,
230 usbd_private_handle, usbd_status);
231
232 void ubt_xmit_sco_start(struct hci_unit *);
233 void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
234 void ubt_xmit_sco_complete(usbd_xfer_handle,
235 usbd_private_handle, usbd_status);
236
237 void ubt_recv_event(usbd_xfer_handle,
238 usbd_private_handle, usbd_status);
239
240 void ubt_recv_acl_start(struct ubt_softc *);
241 void ubt_recv_acl_complete(usbd_xfer_handle,
242 usbd_private_handle, usbd_status);
243
244 void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
245 void ubt_recv_sco_complete(usbd_xfer_handle,
246 usbd_private_handle, usbd_status);
247
248 int ubt_match(struct device *, void *, void *);
249 void ubt_attach(struct device *, struct device *, void *);
250 int ubt_detach(struct device *, int);
251 int ubt_activate(struct device *, enum devact);
252
253 struct cfdriver ubt_cd = {
254 NULL, "ubt", DV_DULL
255 };
256
257 const struct cfattach ubt_ca = {
258 sizeof(struct ubt_softc),
259 ubt_match,
260 ubt_attach,
261 ubt_detach,
262 ubt_activate,
263 };
264
265 static int ubt_set_isoc_config(struct ubt_softc *);
266 static void ubt_abortdealloc(struct ubt_softc *);
267
268
269
270
271
272
273
274
275
276 static const struct usb_devno ubt_ignore[] = {
277 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033 },
278 { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033NF },
279 { 0, 0 }
280 };
281
282 int
283 ubt_match(struct device *parent, void *match, void *aux)
284 {
285
286 struct usb_attach_arg *uaa = aux;
287 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
288
289 DPRINTFN(50, "ubt_match\n");
290
291 if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
292 return UMATCH_NONE;
293
294 if (dd->bDeviceClass == UDCLASS_WIRELESS
295 && dd->bDeviceSubClass == UDSUBCLASS_RF
296 && dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
297 return UMATCH_DEVCLASS_DEVSUBCLASS_DEVPROTO;
298
299 return UMATCH_NONE;
300 }
301
302
303 void
304 ubt_attach(struct device *parent, struct device *self, void *aux)
305 {
306 struct ubt_softc *sc = (struct ubt_softc *)self;
307 struct usb_attach_arg *uaa = aux;
308 usb_config_descriptor_t *cd;
309 usb_endpoint_descriptor_t *ed;
310 char *devinfop;
311 int err;
312 uint8_t count, i;
313
314 DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
315
316 sc->sc_udev = uaa->device;
317
318 devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
319 printf("\n%s: %s\n", sc->sc_dev.dv_xname, devinfop);
320 usbd_devinfo_free(devinfop);
321
322
323
324
325 err = usbd_set_config_index(sc->sc_udev, 0, 1);
326 if (err) {
327 printf("%s: failed to set configuration idx 0: %s\n",
328 sc->sc_dev.dv_xname, usbd_errstr(err));
329
330 return;
331 }
332
333
334
335
336
337
338
339 err = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
340 if (err) {
341 printf("%s: Could not get interface 0 handle %s (%d)\n",
342 sc->sc_dev.dv_xname, usbd_errstr(err), err);
343
344 return;
345 }
346
347 sc->sc_evt_addr = -1;
348 sc->sc_aclrd_addr = -1;
349 sc->sc_aclwr_addr = -1;
350
351 count = 0;
352 (void)usbd_endpoint_count(sc->sc_iface0, &count);
353
354 for (i = 0 ; i < count ; i++) {
355 int dir, type;
356
357 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
358 if (ed == NULL) {
359 printf("%s: could not read endpoint descriptor %d\n",
360 sc->sc_dev.dv_xname, i);
361
362 return;
363 }
364
365 dir = UE_GET_DIR(ed->bEndpointAddress);
366 type = UE_GET_XFERTYPE(ed->bmAttributes);
367
368 if (dir == UE_DIR_IN && type == UE_INTERRUPT)
369 sc->sc_evt_addr = ed->bEndpointAddress;
370 else if (dir == UE_DIR_IN && type == UE_BULK)
371 sc->sc_aclrd_addr = ed->bEndpointAddress;
372 else if (dir == UE_DIR_OUT && type == UE_BULK)
373 sc->sc_aclwr_addr = ed->bEndpointAddress;
374 }
375
376 if (sc->sc_evt_addr == -1) {
377 printf("%s: missing INTERRUPT endpoint on interface 0\n",
378 sc->sc_dev.dv_xname);
379
380 return;
381 }
382 if (sc->sc_aclrd_addr == -1) {
383 printf("%s: missing BULK IN endpoint on interface 0\n",
384 sc->sc_dev.dv_xname);
385
386 return;
387 }
388 if (sc->sc_aclwr_addr == -1) {
389 printf("%s: missing BULK OUT endpoint on interface 0\n",
390 sc->sc_dev.dv_xname);
391
392 return;
393 }
394
395
396
397
398
399
400
401
402
403
404 err = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
405 if (err) {
406 printf("%s: Could not get interface 1 handle %s (%d)\n",
407 sc->sc_dev.dv_xname, usbd_errstr(err), err);
408
409 return;
410 }
411
412 cd = usbd_get_config_descriptor(sc->sc_udev);
413 if (cd == NULL) {
414 printf("%s: could not get config descriptor\n",
415 sc->sc_dev.dv_xname);
416
417 return;
418 }
419
420 sc->sc_alt_config = usbd_get_no_alts(cd, 1);
421
422
423 err = ubt_set_isoc_config(sc);
424 if (err) {
425 printf("%s: ISOC config failed\n",
426 sc->sc_dev.dv_xname);
427
428 return;
429 }
430
431
432 sc->sc_unit.hci_softc = self;
433 sc->sc_unit.hci_devname = sc->sc_dev.dv_xname;
434 sc->sc_unit.hci_enable = ubt_enable;
435 sc->sc_unit.hci_disable = ubt_disable;
436 sc->sc_unit.hci_start_cmd = ubt_xmit_cmd_start;
437 sc->sc_unit.hci_start_acl = ubt_xmit_acl_start;
438 sc->sc_unit.hci_start_sco = ubt_xmit_sco_start;
439 sc->sc_unit.hci_ipl = IPL_USB;
440 hci_attach(&sc->sc_unit);
441
442 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
443 &sc->sc_dev);
444
445 sc->sc_ok = 1;
446
447 return;
448 }
449
450 int
451 ubt_detach(struct device *self, int flags)
452 {
453 struct ubt_softc *sc = (struct ubt_softc *)self;
454 int s;
455
456 DPRINTF("sc=%p flags=%d\n", sc, flags);
457
458 sc->sc_dying = 1;
459
460 if (!sc->sc_ok)
461 return 0;
462
463
464 hci_detach(&sc->sc_unit);
465
466
467
468
469
470
471
472
473 ubt_abortdealloc(sc);
474
475
476 s = splusb();
477 if (sc->sc_refcnt-- > 0)
478 usb_detach_wait(&sc->sc_dev);
479
480 splx(s);
481
482 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
483 &sc->sc_dev);
484
485 DPRINTFN(1, "driver detached\n");
486
487 return 0;
488 }
489
490 int
491 ubt_activate(struct device *self, enum devact act)
492 {
493 struct ubt_softc *sc = (struct ubt_softc *)self;
494 int error = 0;
495
496 DPRINTFN(1, "ubt_activate: sc=%p, act=%d\n", sc, act);
497
498 switch (act) {
499 case DVACT_ACTIVATE:
500 return EOPNOTSUPP;
501 break;
502
503 case DVACT_DEACTIVATE:
504 sc->sc_dying = 1;
505 break;
506 }
507 return error;
508 }
509
510
511 int
512 ubt_set_isoc_config(struct ubt_softc *sc)
513 {
514 usb_endpoint_descriptor_t *ed;
515 int rd_addr, wr_addr, rd_size, wr_size;
516 uint8_t count, i;
517 int err;
518
519 err = usbd_set_interface(sc->sc_iface1, sc->sc_config);
520 if (err != USBD_NORMAL_COMPLETION) {
521 printf(
522 "%s: Could not set config %d on ISOC interface. %s (%d)\n",
523 sc->sc_dev.dv_xname, sc->sc_config, usbd_errstr(err), err);
524
525 return err == USBD_IN_USE ? EBUSY : EIO;
526 }
527
528
529
530
531
532
533
534
535 sc->sc_scord_size = rd_size = 0;
536 sc->sc_scord_addr = rd_addr = -1;
537
538 sc->sc_scowr_size = wr_size = 0;
539 sc->sc_scowr_addr = wr_addr = -1;
540
541 count = 0;
542 (void)usbd_endpoint_count(sc->sc_iface1, &count);
543
544 for (i = 0 ; i < count ; i++) {
545 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
546 if (ed == NULL) {
547 printf("%s: could not read endpoint descriptor %d\n",
548 sc->sc_dev.dv_xname, i);
549
550 return EIO;
551 }
552
553 DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n",
554 sc->sc_dev.dv_xname,
555 UE_GET_XFERTYPE(ed->bmAttributes),
556 UE_GET_ISO_TYPE(ed->bmAttributes),
557 ed->bEndpointAddress,
558 UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
559
560 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
561 continue;
562
563 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
564 rd_addr = ed->bEndpointAddress;
565 rd_size = UGETW(ed->wMaxPacketSize);
566 } else {
567 wr_addr = ed->bEndpointAddress;
568 wr_size = UGETW(ed->wMaxPacketSize);
569 }
570 }
571
572 if (rd_addr == -1) {
573 printf(
574 "%s: missing ISOC IN endpoint on interface config %d\n",
575 sc->sc_dev.dv_xname, sc->sc_config);
576
577 return ENOENT;
578 }
579 if (wr_addr == -1) {
580 printf(
581 "%s: missing ISOC OUT endpoint on interface config %d\n",
582 sc->sc_dev.dv_xname, sc->sc_config);
583
584 return ENOENT;
585 }
586
587 #ifdef DIAGNOSTIC
588 if (rd_size > MLEN) {
589 printf("%s: rd_size=%d exceeds MLEN\n",
590 sc->sc_dev.dv_xname, rd_size);
591
592 return EOVERFLOW;
593 }
594
595 if (wr_size > MLEN) {
596 printf("%s: wr_size=%d exceeds MLEN\n",
597 sc->sc_dev.dv_xname, wr_size);
598
599 return EOVERFLOW;
600 }
601 #endif
602
603 sc->sc_scord_size = rd_size;
604 sc->sc_scord_addr = rd_addr;
605
606 sc->sc_scowr_size = wr_size;
607 sc->sc_scowr_addr = wr_addr;
608
609 return 0;
610 }
611
612 void
613 ubt_abortdealloc(struct ubt_softc *sc)
614 {
615 int i;
616
617 DPRINTFN(1, "sc=%p\n", sc);
618
619
620 if (sc->sc_evt_pipe != NULL) {
621 usbd_abort_pipe(sc->sc_evt_pipe);
622 usbd_close_pipe(sc->sc_evt_pipe);
623 sc->sc_evt_pipe = NULL;
624 }
625
626 if (sc->sc_aclrd_pipe != NULL) {
627 usbd_abort_pipe(sc->sc_aclrd_pipe);
628 usbd_close_pipe(sc->sc_aclrd_pipe);
629 sc->sc_aclrd_pipe = NULL;
630 }
631
632 if (sc->sc_aclwr_pipe != NULL) {
633 usbd_abort_pipe(sc->sc_aclwr_pipe);
634 usbd_close_pipe(sc->sc_aclwr_pipe);
635 sc->sc_aclwr_pipe = NULL;
636 }
637
638 if (sc->sc_scord_pipe != NULL) {
639 usbd_abort_pipe(sc->sc_scord_pipe);
640 usbd_close_pipe(sc->sc_scord_pipe);
641 sc->sc_scord_pipe = NULL;
642 }
643
644 if (sc->sc_scowr_pipe != NULL) {
645 usbd_abort_pipe(sc->sc_scowr_pipe);
646 usbd_close_pipe(sc->sc_scowr_pipe);
647 sc->sc_scowr_pipe = NULL;
648 }
649
650
651 if (sc->sc_evt_buf != NULL) {
652 free(sc->sc_evt_buf, M_USBDEV);
653 sc->sc_evt_buf = NULL;
654 }
655
656
657 if (sc->sc_cmd_xfer != NULL) {
658 usbd_free_xfer(sc->sc_cmd_xfer);
659 sc->sc_cmd_xfer = NULL;
660 sc->sc_cmd_buf = NULL;
661 }
662
663 if (sc->sc_aclrd_xfer != NULL) {
664 usbd_free_xfer(sc->sc_aclrd_xfer);
665 sc->sc_aclrd_xfer = NULL;
666 sc->sc_aclrd_buf = NULL;
667 }
668
669 if (sc->sc_aclwr_xfer != NULL) {
670 usbd_free_xfer(sc->sc_aclwr_xfer);
671 sc->sc_aclwr_xfer = NULL;
672 sc->sc_aclwr_buf = NULL;
673 }
674
675 for (i = 0 ; i < UBT_NXFERS ; i++) {
676 if (sc->sc_scord[i].xfer != NULL) {
677 usbd_free_xfer(sc->sc_scord[i].xfer);
678 sc->sc_scord[i].xfer = NULL;
679 sc->sc_scord[i].buf = NULL;
680 }
681
682 if (sc->sc_scowr[i].xfer != NULL) {
683 usbd_free_xfer(sc->sc_scowr[i].xfer);
684 sc->sc_scowr[i].xfer = NULL;
685 sc->sc_scowr[i].buf = NULL;
686 }
687 }
688
689
690 if (sc->sc_scord_mbuf != NULL) {
691 m_freem(sc->sc_scord_mbuf);
692 sc->sc_scord_mbuf = NULL;
693 }
694
695 if (sc->sc_scowr_mbuf != NULL) {
696 m_freem(sc->sc_scowr_mbuf);
697 sc->sc_scowr_mbuf = NULL;
698 }
699 }
700
701
702
703
704
705
706
707 int
708 ubt_enable(struct hci_unit *unit)
709 {
710 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
711 usbd_status err;
712 int i, error;
713
714 DPRINTFN(1, "sc=%p\n", sc);
715
716 if (unit->hci_flags & BTF_RUNNING)
717 return 0;
718
719
720 sc->sc_evt_buf = malloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
721 if (sc->sc_evt_buf == NULL) {
722 error = ENOMEM;
723 goto bad;
724 }
725 err = usbd_open_pipe_intr(sc->sc_iface0,
726 sc->sc_evt_addr,
727 USBD_SHORT_XFER_OK,
728 &sc->sc_evt_pipe,
729 sc,
730 sc->sc_evt_buf,
731 UBT_BUFSIZ_EVENT,
732 ubt_recv_event,
733 USBD_DEFAULT_INTERVAL);
734 if (err != USBD_NORMAL_COMPLETION) {
735 error = EIO;
736 goto bad;
737 }
738
739
740 sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
741 if (sc->sc_cmd_xfer == NULL) {
742 error = ENOMEM;
743 goto bad;
744 }
745 sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
746 if (sc->sc_cmd_buf == NULL) {
747 error = ENOMEM;
748 goto bad;
749 }
750
751
752 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
753 USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
754 if (err != USBD_NORMAL_COMPLETION) {
755 error = EIO;
756 goto bad;
757 }
758 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
759 if (sc->sc_aclrd_xfer == NULL) {
760 error = ENOMEM;
761 goto bad;
762 }
763 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
764 if (sc->sc_aclrd_buf == NULL) {
765 error = ENOMEM;
766 goto bad;
767 }
768 sc->sc_aclrd_busy = 0;
769 ubt_recv_acl_start(sc);
770
771
772 err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
773 USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
774 if (err != USBD_NORMAL_COMPLETION) {
775 error = EIO;
776 goto bad;
777 }
778 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
779 if (sc->sc_aclwr_xfer == NULL) {
780 error = ENOMEM;
781 goto bad;
782 }
783 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
784 if (sc->sc_aclwr_buf == NULL) {
785 error = ENOMEM;
786 goto bad;
787 }
788
789
790 if (sc->sc_scord_size > 0) {
791 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
792 USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
793 if (err != USBD_NORMAL_COMPLETION) {
794 error = EIO;
795 goto bad;
796 }
797
798 for (i = 0 ; i < UBT_NXFERS ; i++) {
799 sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
800 if (sc->sc_scord[i].xfer == NULL) {
801 error = ENOMEM;
802 goto bad;
803 }
804 sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
805 sc->sc_scord_size * UBT_NFRAMES);
806 if (sc->sc_scord[i].buf == NULL) {
807 error = ENOMEM;
808 goto bad;
809 }
810 sc->sc_scord[i].softc = sc;
811 sc->sc_scord[i].busy = 0;
812 ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
813 }
814 }
815
816
817 if (sc->sc_scowr_size > 0) {
818 err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
819 USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
820 if (err != USBD_NORMAL_COMPLETION) {
821 error = EIO;
822 goto bad;
823 }
824
825 for (i = 0 ; i < UBT_NXFERS ; i++) {
826 sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
827 if (sc->sc_scowr[i].xfer == NULL) {
828 error = ENOMEM;
829 goto bad;
830 }
831 sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
832 sc->sc_scowr_size * UBT_NFRAMES);
833 if (sc->sc_scowr[i].buf == NULL) {
834 error = ENOMEM;
835 goto bad;
836 }
837 sc->sc_scowr[i].softc = sc;
838 sc->sc_scowr[i].busy = 0;
839 }
840 }
841
842 unit->hci_flags &= ~BTF_XMIT;
843 unit->hci_flags |= BTF_RUNNING;
844 return 0;
845
846 bad:
847 ubt_abortdealloc(sc);
848 return error;
849 }
850
851 void
852 ubt_disable(struct hci_unit *unit)
853 {
854 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
855
856 DPRINTFN(1, "sc=%p\n", sc);
857
858 if ((unit->hci_flags & BTF_RUNNING) == 0)
859 return;
860
861 ubt_abortdealloc(sc);
862
863 unit->hci_flags &= ~BTF_RUNNING;
864 }
865
866 void
867 ubt_xmit_cmd_start(struct hci_unit *unit)
868 {
869 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
870 usb_device_request_t req;
871 usbd_status status;
872 struct mbuf *m;
873 int len;
874
875 if (sc->sc_dying)
876 return;
877
878 if (IF_IS_EMPTY(&unit->hci_cmdq))
879 return;
880
881 IF_DEQUEUE(&unit->hci_cmdq, m);
882
883 DPRINTFN(15, "%s: xmit CMD packet (%d bytes)\n",
884 unit->hci_devname, m->m_pkthdr.len);
885
886 sc->sc_refcnt++;
887 unit->hci_flags |= BTF_XMIT_CMD;
888
889 len = m->m_pkthdr.len - 1;
890 m_copydata(m, 1, len, sc->sc_cmd_buf);
891 m_freem(m);
892
893 memset(&req, 0, sizeof(req));
894 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
895 USETW(req.wLength, len);
896
897 usbd_setup_default_xfer(sc->sc_cmd_xfer,
898 sc->sc_udev,
899 unit,
900 UBT_CMD_TIMEOUT,
901 &req,
902 sc->sc_cmd_buf,
903 len,
904 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
905 ubt_xmit_cmd_complete);
906
907 status = usbd_transfer(sc->sc_cmd_xfer);
908
909 KASSERT(status != USBD_NORMAL_COMPLETION);
910
911 if (status != USBD_IN_PROGRESS) {
912 DPRINTF("usbd_transfer status=%s (%d)\n",
913 usbd_errstr(status), status);
914
915 sc->sc_refcnt--;
916 unit->hci_flags &= ~BTF_XMIT_CMD;
917 }
918 }
919
920 void
921 ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
922 usbd_private_handle h, usbd_status status)
923 {
924 struct hci_unit *unit = h;
925 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
926 uint32_t count;
927
928 DPRINTFN(15, "%s: CMD complete status=%s (%d)\n",
929 unit->hci_devname, usbd_errstr(status), status);
930
931 unit->hci_flags &= ~BTF_XMIT_CMD;
932
933 if (--sc->sc_refcnt < 0) {
934 DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
935 usb_detach_wakeup(&sc->sc_dev);
936 return;
937 }
938
939 if (sc->sc_dying) {
940 DPRINTF("sc_dying\n");
941 return;
942 }
943
944 if (status != USBD_NORMAL_COMPLETION) {
945 DPRINTF("status=%s (%d)\n",
946 usbd_errstr(status), status);
947
948 unit->hci_stats.err_tx++;
949 return;
950 }
951
952 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
953 unit->hci_stats.cmd_tx++;
954 unit->hci_stats.byte_tx += count;
955
956 ubt_xmit_cmd_start(unit);
957 }
958
959 void
960 ubt_xmit_acl_start(struct hci_unit *unit)
961 {
962 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
963 struct mbuf *m;
964 usbd_status status;
965 int len;
966
967 if (sc->sc_dying)
968 return;
969
970 if (IF_IS_EMPTY(&unit->hci_acltxq) == NULL)
971 return;
972
973 sc->sc_refcnt++;
974 unit->hci_flags |= BTF_XMIT_ACL;
975
976 IF_DEQUEUE(&unit->hci_acltxq, m);
977
978 DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
979 unit->hci_devname, m->m_pkthdr.len);
980
981 len = m->m_pkthdr.len - 1;
982 if (len > UBT_BUFSIZ_ACL) {
983 DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
984 unit->hci_devname, len, UBT_BUFSIZ_ACL);
985
986 len = UBT_BUFSIZ_ACL;
987 }
988
989 m_copydata(m, 1, len, sc->sc_aclwr_buf);
990 m_freem(m);
991
992 unit->hci_stats.acl_tx++;
993 unit->hci_stats.byte_tx += len;
994
995 usbd_setup_xfer(sc->sc_aclwr_xfer,
996 sc->sc_aclwr_pipe,
997 unit,
998 sc->sc_aclwr_buf,
999 len,
1000 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1001 UBT_ACL_TIMEOUT,
1002 ubt_xmit_acl_complete);
1003
1004 status = usbd_transfer(sc->sc_aclwr_xfer);
1005
1006 KASSERT(status != USBD_NORMAL_COMPLETION);
1007
1008 if (status != USBD_IN_PROGRESS) {
1009 DPRINTF("usbd_transfer status=%s (%d)\n",
1010 usbd_errstr(status), status);
1011
1012 sc->sc_refcnt--;
1013 unit->hci_flags &= ~BTF_XMIT_ACL;
1014 }
1015 }
1016
1017 void
1018 ubt_xmit_acl_complete(usbd_xfer_handle xfer,
1019 usbd_private_handle h, usbd_status status)
1020 {
1021 struct hci_unit *unit = h;
1022 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
1023
1024 DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
1025 unit->hci_devname, usbd_errstr(status), status);
1026
1027 unit->hci_flags &= ~BTF_XMIT_ACL;
1028
1029 if (--sc->sc_refcnt < 0) {
1030 usb_detach_wakeup(&sc->sc_dev);
1031 return;
1032 }
1033
1034 if (sc->sc_dying)
1035 return;
1036
1037 if (status != USBD_NORMAL_COMPLETION) {
1038 DPRINTF("status=%s (%d)\n",
1039 usbd_errstr(status), status);
1040
1041 unit->hci_stats.err_tx++;
1042
1043 if (status == USBD_STALLED)
1044 usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
1045 else
1046 return;
1047 }
1048
1049 ubt_xmit_acl_start(unit);
1050 }
1051
1052 void
1053 ubt_xmit_sco_start(struct hci_unit *unit)
1054 {
1055 struct ubt_softc *sc = (struct ubt_softc *)unit->hci_softc;
1056 int i;
1057
1058 if (sc->sc_dying || sc->sc_scowr_size == 0)
1059 return;
1060
1061 for (i = 0 ; i < UBT_NXFERS ; i++) {
1062 if (sc->sc_scowr[i].busy)
1063 continue;
1064
1065 ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]);
1066 }
1067 }
1068
1069 void
1070 ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1071 {
1072 struct mbuf *m;
1073 uint8_t *buf;
1074 int num, len, size, space;
1075
1076 space = sc->sc_scowr_size * UBT_NFRAMES;
1077 buf = isoc->buf;
1078 len = 0;
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 m = sc->sc_scowr_mbuf;
1090 while (space > 0) {
1091 if (m == NULL) {
1092 IF_DEQUEUE(&sc->sc_unit.hci_scotxq, m);
1093 if (m == NULL)
1094 break;
1095
1096 m_adj(m, 1);
1097 }
1098
1099 if (m->m_pkthdr.len > 0) {
1100 size = MIN(m->m_pkthdr.len, space);
1101
1102 m_copydata(m, 0, size, buf);
1103 m_adj(m, size);
1104
1105 buf += size;
1106 len += size;
1107 space -= size;
1108 }
1109
1110 if (m->m_pkthdr.len == 0) {
1111 sc->sc_unit.hci_stats.sco_tx++;
1112 hci_complete_sco(&sc->sc_unit, m);
1113 m = NULL;
1114 }
1115 }
1116 sc->sc_scowr_mbuf = m;
1117
1118 DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);
1119
1120 if (len == 0)
1121 return;
1122
1123 sc->sc_refcnt++;
1124 sc->sc_unit.hci_flags |= BTF_XMIT_SCO;
1125 sc->sc_unit.hci_stats.byte_tx += len;
1126 isoc->busy = 1;
1127
1128
1129
1130
1131
1132 for (num = 0 ; len > 0 ; num++) {
1133 size = MIN(sc->sc_scowr_size, len);
1134
1135 isoc->size[num] = size;
1136 len -= size;
1137 }
1138
1139 usbd_setup_isoc_xfer(isoc->xfer,
1140 sc->sc_scowr_pipe,
1141 isoc,
1142 isoc->size,
1143 num,
1144 USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1145 ubt_xmit_sco_complete);
1146
1147 usbd_transfer(isoc->xfer);
1148 }
1149
1150 void
1151 ubt_xmit_sco_complete(usbd_xfer_handle xfer,
1152 usbd_private_handle h, usbd_status status)
1153 {
1154 struct ubt_isoc_xfer *isoc = h;
1155 struct ubt_softc *sc;
1156 int i;
1157
1158 KASSERT(xfer == isoc->xfer);
1159 sc = isoc->softc;
1160
1161 DPRINTFN(15, "isoc=%p, status=%s (%d)\n",
1162 isoc, usbd_errstr(status), status);
1163
1164 isoc->busy = 0;
1165
1166 for (i = 0 ; ; i++) {
1167 if (i == UBT_NXFERS) {
1168 sc->sc_unit.hci_flags &= ~BTF_XMIT_SCO;
1169 break;
1170 }
1171
1172 if (sc->sc_scowr[i].busy)
1173 break;
1174 }
1175
1176 if (--sc->sc_refcnt < 0) {
1177 usb_detach_wakeup(&sc->sc_dev);
1178 return;
1179 }
1180
1181 if (sc->sc_dying)
1182 return;
1183
1184 if (status != USBD_NORMAL_COMPLETION) {
1185 DPRINTF("status=%s (%d)\n",
1186 usbd_errstr(status), status);
1187
1188 sc->sc_unit.hci_stats.err_tx++;
1189
1190 if (status == USBD_STALLED)
1191 usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
1192 else
1193 return;
1194 }
1195
1196 ubt_xmit_sco_start(&sc->sc_unit);
1197 }
1198
1199
1200
1201
1202
1203 static struct mbuf *
1204 ubt_mbufload(uint8_t *buf, int count, uint8_t type)
1205 {
1206 struct mbuf *m;
1207
1208 MGETHDR(m, M_DONTWAIT, MT_DATA);
1209 if (m == NULL)
1210 return NULL;
1211
1212 *mtod(m, uint8_t *) = type;
1213 m->m_pkthdr.len = m->m_len = MHLEN;
1214 m_copyback(m, 1, count, buf);
1215 if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) {
1216 m_free(m);
1217 return NULL;
1218 }
1219
1220 m->m_pkthdr.len = count + 1;
1221 m->m_len = MIN(MHLEN, m->m_pkthdr.len);
1222
1223 return m;
1224 }
1225
1226 void
1227 ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
1228 {
1229 struct ubt_softc *sc = h;
1230 struct mbuf *m;
1231 uint32_t count;
1232 void *buf;
1233
1234 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1235 sc, usbd_errstr(status), status);
1236
1237 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying)
1238 return;
1239
1240 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1241
1242 if (count < sizeof(hci_event_hdr_t) - 1) {
1243 DPRINTF("dumped undersized event (count = %d)\n", count);
1244 sc->sc_unit.hci_stats.err_rx++;
1245 return;
1246 }
1247
1248 sc->sc_unit.hci_stats.evt_rx++;
1249 sc->sc_unit.hci_stats.byte_rx += count;
1250
1251 m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
1252 if (m != NULL)
1253 hci_input_event(&sc->sc_unit, m);
1254 else
1255 sc->sc_unit.hci_stats.err_rx++;
1256 }
1257
1258 void
1259 ubt_recv_acl_start(struct ubt_softc *sc)
1260 {
1261 usbd_status status;
1262
1263 DPRINTFN(15, "sc=%p\n", sc);
1264
1265 if (sc->sc_aclrd_busy || sc->sc_dying) {
1266 DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
1267 sc->sc_aclrd_busy,
1268 sc->sc_dying);
1269
1270 return;
1271 }
1272
1273 sc->sc_refcnt++;
1274 sc->sc_aclrd_busy = 1;
1275
1276 usbd_setup_xfer(sc->sc_aclrd_xfer,
1277 sc->sc_aclrd_pipe,
1278 sc,
1279 sc->sc_aclrd_buf,
1280 UBT_BUFSIZ_ACL,
1281 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1282 USBD_NO_TIMEOUT,
1283 ubt_recv_acl_complete);
1284
1285 status = usbd_transfer(sc->sc_aclrd_xfer);
1286
1287 KASSERT(status != USBD_NORMAL_COMPLETION);
1288
1289 if (status != USBD_IN_PROGRESS) {
1290 DPRINTF("usbd_transfer status=%s (%d)\n",
1291 usbd_errstr(status), status);
1292
1293 sc->sc_refcnt--;
1294 sc->sc_aclrd_busy = 0;
1295 }
1296 }
1297
1298 void
1299 ubt_recv_acl_complete(usbd_xfer_handle xfer,
1300 usbd_private_handle h, usbd_status status)
1301 {
1302 struct ubt_softc *sc = h;
1303 struct mbuf *m;
1304 uint32_t count;
1305 void *buf;
1306
1307 DPRINTFN(15, "sc=%p status=%s (%d)\n",
1308 sc, usbd_errstr(status), status);
1309
1310 sc->sc_aclrd_busy = 0;
1311
1312 if (--sc->sc_refcnt < 0) {
1313 DPRINTF("refcnt = %d\n", sc->sc_refcnt);
1314 usb_detach_wakeup(&sc->sc_dev);
1315 return;
1316 }
1317
1318 if (sc->sc_dying) {
1319 DPRINTF("sc_dying\n");
1320 return;
1321 }
1322
1323 if (status != USBD_NORMAL_COMPLETION) {
1324 DPRINTF("status=%s (%d)\n",
1325 usbd_errstr(status), status);
1326
1327 sc->sc_unit.hci_stats.err_rx++;
1328
1329 if (status == USBD_STALLED)
1330 usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
1331 else
1332 return;
1333 } else {
1334 usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1335
1336 if (count < sizeof(hci_acldata_hdr_t) - 1) {
1337 DPRINTF("dumped undersized packet (%d)\n", count);
1338 sc->sc_unit.hci_stats.err_rx++;
1339 } else {
1340 sc->sc_unit.hci_stats.acl_rx++;
1341 sc->sc_unit.hci_stats.byte_rx += count;
1342
1343 m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
1344 if (m != NULL)
1345 hci_input_acl(&sc->sc_unit, m);
1346 else
1347 sc->sc_unit.hci_stats.err_rx++;
1348 }
1349 }
1350
1351
1352 ubt_recv_acl_start(sc);
1353 }
1354
1355 void
1356 ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1357 {
1358 int i;
1359
1360 DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc);
1361
1362 if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) {
1363 DPRINTF("%s%s%s\n",
1364 isoc->busy ? " busy" : "",
1365 sc->sc_dying ? " dying" : "",
1366 sc->sc_scord_size == 0 ? " size=0" : "");
1367
1368 return;
1369 }
1370
1371 sc->sc_refcnt++;
1372 isoc->busy = 1;
1373
1374 for (i = 0 ; i < UBT_NFRAMES ; i++)
1375 isoc->size[i] = sc->sc_scord_size;
1376
1377 usbd_setup_isoc_xfer(isoc->xfer,
1378 sc->sc_scord_pipe,
1379 isoc,
1380 isoc->size,
1381 UBT_NFRAMES,
1382 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1383 ubt_recv_sco_complete);
1384
1385 usbd_transfer(isoc->xfer);
1386 }
1387
1388 void
1389 ubt_recv_sco_complete(usbd_xfer_handle xfer,
1390 usbd_private_handle h, usbd_status status)
1391 {
1392 struct ubt_isoc_xfer *isoc = h;
1393 struct ubt_softc *sc;
1394 struct mbuf *m;
1395 uint32_t count;
1396 uint8_t *ptr, *frame;
1397 int i, size, got, want;
1398
1399 KASSERT(isoc != NULL);
1400 KASSERT(isoc->xfer == xfer);
1401
1402 sc = isoc->softc;
1403 isoc->busy = 0;
1404
1405 if (--sc->sc_refcnt < 0) {
1406 DPRINTF("refcnt=%d\n", sc->sc_refcnt);
1407 usb_detach_wakeup(&sc->sc_dev);
1408 return;
1409 }
1410
1411 if (sc->sc_dying) {
1412 DPRINTF("sc_dying\n");
1413 return;
1414 }
1415
1416 if (status != USBD_NORMAL_COMPLETION) {
1417 DPRINTF("status=%s (%d)\n",
1418 usbd_errstr(status), status);
1419
1420 sc->sc_unit.hci_stats.err_rx++;
1421
1422 if (status == USBD_STALLED) {
1423 usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
1424 goto restart;
1425 }
1426
1427 return;
1428 }
1429
1430 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1431 if (count == 0)
1432 goto restart;
1433
1434 DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
1435 sc, isoc, count);
1436
1437 sc->sc_unit.hci_stats.byte_rx += count;
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448 m = sc->sc_scord_mbuf;
1449 if (m != NULL) {
1450 sc->sc_scord_mbuf = NULL;
1451 ptr = mtod(m, uint8_t *) + m->m_pkthdr.len;
1452 got = m->m_pkthdr.len;
1453 want = sizeof(hci_scodata_hdr_t);
1454 if (got >= want)
1455 want += mtod(m, hci_scodata_hdr_t *)->length ;
1456 } else {
1457 ptr = NULL;
1458 got = 0;
1459 want = 0;
1460 }
1461
1462 for (i = 0 ; i < UBT_NFRAMES ; i++) {
1463 frame = isoc->buf + (i * sc->sc_scord_size);
1464
1465 while (isoc->size[i] > 0) {
1466 size = isoc->size[i];
1467
1468 if (m == NULL) {
1469 MGETHDR(m, M_DONTWAIT, MT_DATA);
1470 if (m == NULL) {
1471 printf("%s: out of memory (xfer halted)\n",
1472 sc->sc_dev.dv_xname);
1473
1474 sc->sc_unit.hci_stats.err_rx++;
1475 return;
1476 }
1477
1478 ptr = mtod(m, uint8_t *);
1479 *ptr++ = HCI_SCO_DATA_PKT;
1480 got = 1;
1481 want = sizeof(hci_scodata_hdr_t);
1482 }
1483
1484 if (got + size > want)
1485 size = want - got;
1486
1487 if (got + size > MHLEN)
1488 memcpy(ptr, frame, MHLEN - got);
1489 else
1490 memcpy(ptr, frame, size);
1491
1492 ptr += size;
1493 got += size;
1494 frame += size;
1495
1496 if (got == want) {
1497
1498
1499
1500
1501
1502 if (want == sizeof(hci_scodata_hdr_t))
1503 want += mtod(m, hci_scodata_hdr_t *)->length;
1504
1505 if (got == want) {
1506 m->m_pkthdr.len = m->m_len = got;
1507 sc->sc_unit.hci_stats.sco_rx++;
1508 hci_input_sco(&sc->sc_unit, m);
1509 m = NULL;
1510 }
1511 }
1512
1513 isoc->size[i] -= size;
1514 }
1515 }
1516
1517 if (m != NULL) {
1518 m->m_pkthdr.len = m->m_len = got;
1519 sc->sc_scord_mbuf = m;
1520 }
1521
1522 restart:
1523 ubt_recv_sco_start1(sc, isoc);
1524 }