Annotation of sys/dev/usb/ubt.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: ubt.c,v 1.8 2007/06/14 10:11:15 mbalmer Exp $ */
2:
3: /*-
4: * Copyright (c) 2006 Itronix Inc.
5: * All rights reserved.
6: *
7: * Written by Iain Hibbert for Itronix Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of Itronix Inc. may not be used to endorse
18: * or promote products derived from this software without specific
19: * prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY ITRONIX INC. ``AS IS'' AND
22: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ITRONIX INC. BE LIABLE FOR ANY
25: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28: * ON ANY THEORY OF LIABILITY, WHETHER IN
29: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31: * POSSIBILITY OF SUCH DAMAGE.
32: */
33: /*
34: * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
35: * All rights reserved.
36: *
37: * This code is derived from software contributed to The NetBSD Foundation
38: * by Lennart Augustsson (lennart@augustsson.net) and
39: * David Sainty (David.Sainty@dtsp.co.nz).
40: *
41: * Redistribution and use in source and binary forms, with or without
42: * modification, are permitted provided that the following conditions
43: * are met:
44: * 1. Redistributions of source code must retain the above copyright
45: * notice, this list of conditions and the following disclaimer.
46: * 2. Redistributions in binary form must reproduce the above copyright
47: * notice, this list of conditions and the following disclaimer in the
48: * documentation and/or other materials provided with the distribution.
49: * 3. All advertising materials mentioning features or use of this software
50: * must display the following acknowledgement:
51: * This product includes software developed by the NetBSD
52: * Foundation, Inc. and its contributors.
53: * 4. Neither the name of The NetBSD Foundation nor the names of its
54: * contributors may be used to endorse or promote products derived
55: * from this software without specific prior written permission.
56: *
57: * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
58: * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
59: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
60: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
61: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
62: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
63: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
64: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
65: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
66: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
67: * POSSIBILITY OF SUCH DAMAGE.
68: */
69: /*
70: * This driver originally written by Lennart Augustsson and David Sainty,
71: * but was mostly rewritten for the NetBSD Bluetooth protocol stack by
72: * Iain Hibbert for Itronix, Inc using the FreeBSD ng_ubt.c driver as a
73: * reference.
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: * debugging stuff
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 (/* CONSTCOND */0)
110:
111: #define DPRINTFN(n, fmt, args...) do { \
112: if (ubt_debug > (n)) \
113: printf("%s: "fmt, __func__ , ##args); \
114: } while (/* CONSTCOND */0)
115:
116: #else
117: #define DPRINTF(...)
118: #define DPRINTFN(...)
119: #endif
120:
121: /*******************************************************************************
122: *
123: * ubt softc structure
124: *
125: */
126:
127: /* buffer sizes */
128: /*
129: * NB: although ACL packets can extend to 65535 bytes, most devices
130: * have max_acl_size at much less (largest I have seen is 384)
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: /* Transmit timeouts */
137: #define UBT_CMD_TIMEOUT USBD_DEFAULT_TIMEOUT
138: #define UBT_ACL_TIMEOUT USBD_DEFAULT_TIMEOUT
139:
140: /*
141: * ISOC transfers
142: *
143: * xfer buffer size depends on the frame size, and the number
144: * of frames per transfer is fixed, as each frame should be
145: * 1ms worth of data. This keeps the rate that xfers complete
146: * fairly constant. We use multiple xfers to keep the hardware
147: * busy
148: */
149: #define UBT_NXFERS 3 /* max xfers to queue */
150: #define UBT_NFRAMES 10 /* frames per xfer */
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: /* Control Interface */
167: usbd_interface_handle sc_iface0;
168:
169: /* Commands (control) */
170: usbd_xfer_handle sc_cmd_xfer;
171: uint8_t *sc_cmd_buf;
172:
173: /* Events (interrupt) */
174: int sc_evt_addr; /* endpoint address */
175: usbd_pipe_handle sc_evt_pipe;
176: uint8_t *sc_evt_buf;
177:
178: /* ACL data (in) */
179: int sc_aclrd_addr; /* endpoint address */
180: usbd_pipe_handle sc_aclrd_pipe; /* read pipe */
181: usbd_xfer_handle sc_aclrd_xfer; /* read xfer */
182: uint8_t *sc_aclrd_buf; /* read buffer */
183: int sc_aclrd_busy; /* reading */
184:
185: /* ACL data (out) */
186: int sc_aclwr_addr; /* endpoint address */
187: usbd_pipe_handle sc_aclwr_pipe; /* write pipe */
188: usbd_xfer_handle sc_aclwr_xfer; /* write xfer */
189: uint8_t *sc_aclwr_buf; /* write buffer */
190:
191: /* ISOC interface */
192: usbd_interface_handle sc_iface1; /* ISOC interface */
193: struct sysctllog *sc_log; /* sysctl log */
194: int sc_config; /* current config no */
195: int sc_alt_config; /* no of alternates */
196:
197: /* SCO data (in) */
198: int sc_scord_addr; /* endpoint address */
199: usbd_pipe_handle sc_scord_pipe; /* read pipe */
200: int sc_scord_size; /* frame length */
201: struct ubt_isoc_xfer sc_scord[UBT_NXFERS];
202: struct mbuf *sc_scord_mbuf; /* current packet */
203:
204: /* SCO data (out) */
205: int sc_scowr_addr; /* endpoint address */
206: usbd_pipe_handle sc_scowr_pipe; /* write pipe */
207: int sc_scowr_size; /* frame length */
208: struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
209: struct mbuf *sc_scowr_mbuf; /* current packet */
210:
211: /* Protocol structure */
212: struct hci_unit sc_unit;
213:
214: /* Successfully attached */
215: int sc_ok;
216: };
217:
218: /*
219: * Bluetooth unit/USB callback routines
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: * Match against the whole device, since we want to take
270: * both interfaces. If a device should be ignored then add
271: *
272: * { VendorID, ProductID }
273: *
274: * to the ubt_ignore list.
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 } /* end of list */
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: * Move the device into the configured state
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: * Interface 0 must have 3 endpoints
335: * 1) Interrupt endpoint to receive HCI events
336: * 2) Bulk IN endpoint to receive ACL data
337: * 3) Bulk OUT endpoint to send ACL data
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: * Interface 1 must have 2 endpoints
397: * 1) Isochronous IN endpoint to receive SCO data
398: * 2) Isochronous OUT endpoint to send SCO data
399: *
400: * and will have several configurations, which can be selected
401: * via a sysctl variable. We select config 0 to start, which
402: * means that no SCO data will be available.
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: /* set initial config */
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: /* Attach HCI */
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; /* XXX: IPL_SOFTUSB ?? */
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: /* Detach HCI interface */
464: hci_detach(&sc->sc_unit);
465:
466: /*
467: * Abort all pipes. Causes processes waiting for transfer to wake.
468: *
469: * Actually, hci_detach() above will call ubt_disable() which may
470: * call ubt_abortdealloc(), but lets be sure since doing it twice
471: * wont cause an error.
472: */
473: ubt_abortdealloc(sc);
474:
475: /* wait for all processes to finish */
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: /* set ISOC configuration */
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: * We wont get past the above if there are any pipes open, so no
530: * need to worry about buf/xfer/pipe deallocation. If we get an
531: * error after this, the frame quantities will be 0 and no SCO
532: * data will be possible.
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: /* Abort all pipes */
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: /* Free event buffer */
651: if (sc->sc_evt_buf != NULL) {
652: free(sc->sc_evt_buf, M_USBDEV);
653: sc->sc_evt_buf = NULL;
654: }
655:
656: /* Free all xfers and xfer buffers (implicit) */
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: /* Free partial SCO packets */
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: * Bluetooth Unit/USB callbacks
704: *
705: * All of this will be called at the IPL_ we specified above
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: /* Events */
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: /* Commands */
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: /* ACL read */
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: /* ACL write */
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: /* SCO read */
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: /* SCO write */
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: * Fill the request buffer with data from the queue,
1082: * keeping any leftover packet on our private hook.
1083: *
1084: * Complete packets are passed back up to the stack
1085: * for disposal, since we can't rely on the controller
1086: * to tell us when it has finished with them.
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); /* packet type */
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) /* nothing to send */
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: * calculate number of isoc frames and sizes
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: * load incoming data into an mbuf with
1201: * leading type byte
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); // (extends if necessary)
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: /* and restart */
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: * Extract SCO packets from ISOC frames. The way we have it,
1441: * no SCO packet can be bigger than MHLEN. This is unlikely
1442: * to actually happen, but if we ran out of mbufs and lost
1443: * sync then we may get spurious data that makes it seem that
1444: * way, so we discard data that wont fit. This doesnt really
1445: * help with the lost sync situation alas.
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; /* lost sync */
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: * If we only got a header, add the packet
1499: * length to our want count. Send complete
1500: * packets up to protocol stack.
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: /* and restart */
1523: ubt_recv_sco_start1(sc, isoc);
1524: }
CVSweb