Annotation of src/sys/dev/usb/ubt.c, Revision 1.21
1.21 ! drochner 1: /* $NetBSD: ubt.c,v 1.20 2006/11/16 01:33:26 christos Exp $ */
1.1 augustss 2:
1.14 gdamore 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: */
1.1 augustss 33: /*
1.5 dsainty 34: * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
1.1 augustss 35: * All rights reserved.
36: *
37: * This code is derived from software contributed to The NetBSD Foundation
1.5 dsainty 38: * by Lennart Augustsson (lennart@augustsson.net) and
39: * David Sainty (David.Sainty@dtsp.co.nz).
1.1 augustss 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: */
1.14 gdamore 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: */
1.1 augustss 75:
76: #include <sys/cdefs.h>
1.21 ! drochner 77: __KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.20 2006/11/16 01:33:26 christos Exp $");
1.1 augustss 78:
79: #include <sys/param.h>
1.14 gdamore 80: #include <sys/device.h>
81: #include <sys/ioctl.h>
1.1 augustss 82: #include <sys/kernel.h>
1.5 dsainty 83: #include <sys/malloc.h>
1.14 gdamore 84: #include <sys/mbuf.h>
1.1 augustss 85: #include <sys/proc.h>
1.14 gdamore 86: #include <sys/sysctl.h>
87: #include <sys/systm.h>
1.1 augustss 88:
89: #include <dev/usb/usb.h>
90: #include <dev/usb/usbdi.h>
91: #include <dev/usb/usbdi_util.h>
92: #include <dev/usb/usbdevs.h>
93:
1.14 gdamore 94: #include <netbt/bluetooth.h>
95: #include <netbt/hci.h>
96:
97: /*******************************************************************************
98: *
99: * debugging stuff
100: */
101: #undef DPRINTF
102: #undef DPRINTFN
1.3 augustss 103:
1.1 augustss 104: #ifdef UBT_DEBUG
1.14 gdamore 105: int ubt_debug = UBT_DEBUG;
106:
107: #define DPRINTF(fmt, args...) do { \
108: if (ubt_debug) \
109: printf("%s: "fmt, __func__ , ##args); \
110: } while (/* CONSTCOND */0)
111:
112: #define DPRINTFN(n, fmt, args...) do { \
113: if (ubt_debug > (n)) \
114: printf("%s: "fmt, __func__ , ##args); \
115: } while (/* CONSTCOND */0)
116:
117: SYSCTL_SETUP(sysctl_hw_ubt_debug_setup, "sysctl hw.ubt_debug setup")
118: {
119:
120: sysctl_createv(NULL, 0, NULL, NULL,
121: CTLFLAG_PERMANENT,
122: CTLTYPE_NODE, "hw",
123: NULL,
124: NULL, 0,
125: NULL, 0,
126: CTL_HW, CTL_EOL);
127:
128: sysctl_createv(NULL, 0, NULL, NULL,
129: CTLFLAG_PERMANENT | CTLFLAG_READWRITE,
130: CTLTYPE_INT, "ubt_debug",
131: SYSCTL_DESCR("ubt debug level"),
132: NULL, 0,
133: &ubt_debug, sizeof(ubt_debug),
134: CTL_HW, CTL_CREATE, CTL_EOL);
135: }
1.1 augustss 136: #else
1.14 gdamore 137: #define DPRINTF(...)
138: #define DPRINTFN(...)
1.1 augustss 139: #endif
140:
1.14 gdamore 141: /*******************************************************************************
142: *
143: * ubt softc structure
144: *
145: */
146:
147: /* buffer sizes */
1.1 augustss 148: /*
1.14 gdamore 149: * NB: although ACL packets can extend to 65535 bytes, most devices
150: * have max_acl_size at much less (largest I have seen is 384)
1.1 augustss 151: */
1.14 gdamore 152: #define UBT_BUFSIZ_CMD (HCI_CMD_PKT_SIZE - 1)
153: #define UBT_BUFSIZ_ACL (2048 - 1)
154: #define UBT_BUFSIZ_EVENT (HCI_EVENT_PKT_SIZE - 1)
155:
156: /* Transmit timeouts */
157: #define UBT_CMD_TIMEOUT USBD_DEFAULT_TIMEOUT
158: #define UBT_ACL_TIMEOUT USBD_DEFAULT_TIMEOUT
159:
160: /*
161: * ISOC transfers
162: *
163: * xfer buffer size depends on the frame size, and the number
164: * of frames per transfer is fixed, as each frame should be
165: * 1ms worth of data. This keeps the rate that xfers complete
166: * fairly constant. We use multiple xfers to keep the hardware
167: * busy
168: */
169: #define UBT_NXFERS 3 /* max xfers to queue */
170: #define UBT_NFRAMES 10 /* frames per xfer */
171:
172: struct ubt_isoc_xfer {
173: struct ubt_softc *softc;
174: usbd_xfer_handle xfer;
175: uint8_t *buf;
176: uint16_t size[UBT_NFRAMES];
177: int busy;
178: };
1.1 augustss 179:
180: struct ubt_softc {
1.14 gdamore 181: USBBASEDEVICE sc_dev;
182: usbd_device_handle sc_udev;
183: int sc_refcnt;
184: int sc_dying;
185:
186: /* Control Interface */
187: usbd_interface_handle sc_iface0;
188:
189: /* Commands (control) */
190: usbd_xfer_handle sc_cmd_xfer;
191: uint8_t *sc_cmd_buf;
192:
193: /* Events (interrupt) */
194: int sc_evt_addr; /* endpoint address */
195: usbd_pipe_handle sc_evt_pipe;
196: uint8_t *sc_evt_buf;
1.5 dsainty 197:
198: /* ACL data (in) */
1.14 gdamore 199: int sc_aclrd_addr; /* endpoint address */
200: usbd_pipe_handle sc_aclrd_pipe; /* read pipe */
201: usbd_xfer_handle sc_aclrd_xfer; /* read xfer */
202: uint8_t *sc_aclrd_buf; /* read buffer */
203: int sc_aclrd_busy; /* reading */
1.5 dsainty 204:
205: /* ACL data (out) */
1.14 gdamore 206: int sc_aclwr_addr; /* endpoint address */
207: usbd_pipe_handle sc_aclwr_pipe; /* write pipe */
208: usbd_xfer_handle sc_aclwr_xfer; /* write xfer */
209: uint8_t *sc_aclwr_buf; /* write buffer */
210:
211: /* ISOC interface */
212: usbd_interface_handle sc_iface1; /* ISOC interface */
213: struct sysctllog *sc_log; /* sysctl log */
214: int sc_config; /* current config no */
215: int sc_alt_config; /* no of alternates */
216:
217: /* SCO data (in) */
218: int sc_scord_addr; /* endpoint address */
219: usbd_pipe_handle sc_scord_pipe; /* read pipe */
220: int sc_scord_size; /* frame length */
221: struct ubt_isoc_xfer sc_scord[UBT_NXFERS];
222: struct mbuf *sc_scord_mbuf; /* current packet */
223:
224: /* SCO data (out) */
225: int sc_scowr_addr; /* endpoint address */
226: usbd_pipe_handle sc_scowr_pipe; /* write pipe */
227: int sc_scowr_size; /* frame length */
228: struct ubt_isoc_xfer sc_scowr[UBT_NXFERS];
229: struct mbuf *sc_scowr_mbuf; /* current packet */
1.1 augustss 230:
1.14 gdamore 231: /* Protocol structure */
232: struct hci_unit sc_unit;
233: };
234:
235: /*******************************************************************************
236: *
237: * Bluetooth unit/USB callback routines
238: *
239: */
240: static int ubt_enable(struct hci_unit *);
241: static void ubt_disable(struct hci_unit *);
242:
243: static void ubt_xmit_cmd_start(struct hci_unit *);
244: static void ubt_xmit_cmd_complete(usbd_xfer_handle,
245: usbd_private_handle, usbd_status);
246:
247: static void ubt_xmit_acl_start(struct hci_unit *);
248: static void ubt_xmit_acl_complete(usbd_xfer_handle,
249: usbd_private_handle, usbd_status);
250:
251: static void ubt_xmit_sco_start(struct hci_unit *);
252: static void ubt_xmit_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
253: static void ubt_xmit_sco_complete(usbd_xfer_handle,
254: usbd_private_handle, usbd_status);
1.5 dsainty 255:
1.14 gdamore 256: static void ubt_recv_event(usbd_xfer_handle,
257: usbd_private_handle, usbd_status);
1.1 augustss 258:
1.14 gdamore 259: static void ubt_recv_acl_start(struct ubt_softc *);
260: static void ubt_recv_acl_complete(usbd_xfer_handle,
261: usbd_private_handle, usbd_status);
1.5 dsainty 262:
1.14 gdamore 263: static void ubt_recv_sco_start1(struct ubt_softc *, struct ubt_isoc_xfer *);
264: static void ubt_recv_sco_complete(usbd_xfer_handle,
265: usbd_private_handle, usbd_status);
1.6 dsainty 266:
267:
1.14 gdamore 268: /*******************************************************************************
269: *
270: * USB Autoconfig stuff
271: *
272: */
1.5 dsainty 273:
1.1 augustss 274: USB_DECLARE_DRIVER(ubt);
275:
1.14 gdamore 276: static int ubt_set_isoc_config(struct ubt_softc *);
277: static int ubt_sysctl_config(SYSCTLFN_PROTO);
278: static void ubt_abortdealloc(struct ubt_softc *);
279:
1.15 plunky 280: /*
281: * If a device should be ignored then add
282: *
283: * { VendorID, ProductID }
284: *
285: * to this list.
286: */
287: static const struct usb_devno ubt_ignore[] = {
288: { USB_VENDOR_BROADCOM, USB_PRODUCT_BROADCOM_BCM2033NF },
289: { 0, 0 } /* end of list */
290: };
291:
1.1 augustss 292: USB_MATCH(ubt)
293: {
294: USB_MATCH_START(ubt, uaa);
295: usb_interface_descriptor_t *id;
296:
1.14 gdamore 297: DPRINTFN(50, "ubt_match\n");
1.1 augustss 298:
299: if (uaa->iface == NULL)
1.14 gdamore 300: return UMATCH_NONE;
1.1 augustss 301:
1.15 plunky 302: if (usb_lookup(ubt_ignore, uaa->vendor, uaa->product))
303: return UMATCH_NONE;
304:
1.1 augustss 305: id = usbd_get_interface_descriptor(uaa->iface);
1.14 gdamore 306: if (id != NULL
307: && id->bInterfaceClass == UICLASS_WIRELESS
308: && id->bInterfaceSubClass == UISUBCLASS_RF
309: && id->bInterfaceProtocol == UIPROTO_BLUETOOTH)
310: return UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO;
311:
312: return UMATCH_NONE;
1.1 augustss 313: }
314:
315: USB_ATTACH(ubt)
316: {
317: USB_ATTACH_START(ubt, sc, uaa);
1.14 gdamore 318: usbd_interface_handle iface;
319: usb_config_descriptor_t *cd;
320: usb_endpoint_descriptor_t *ed;
321: const struct sysctlnode *node;
322: char *devinfop;
323: int err;
324: uint8_t count, i;
1.1 augustss 325:
1.14 gdamore 326: DPRINTFN(50, "ubt_attach: sc=%p\n", sc);
1.1 augustss 327:
1.14 gdamore 328: sc->sc_udev = uaa->device;
329:
330: devinfop = usbd_devinfo_alloc(sc->sc_udev, 0);
1.1 augustss 331: USB_ATTACH_SETUP;
1.14 gdamore 332: aprint_normal("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
1.12 augustss 333: usbd_devinfo_free(devinfop);
1.1 augustss 334:
1.14 gdamore 335: /*
336: * We must have at least 2 interfaces.
337: */
338: if (uaa->nifaces < 2) {
339: aprint_error("%s: need 2 interfaces (got %d)\n",
340: USBDEVNAME(sc->sc_dev), uaa->nifaces);
341:
342: USB_ATTACH_ERROR_RETURN;
343: }
1.1 augustss 344:
1.5 dsainty 345: /*
1.14 gdamore 346: * Interface 0 must have 3 endpoints
347: * 1) Interrupt endpoint to receive HCI events
348: * 2) Bulk IN endpoint to receive ACL data
349: * 3) Bulk OUT endpoint to send ACL data
1.3 augustss 350: */
1.14 gdamore 351: err = usbd_device2interface_handle(sc->sc_udev, 0, &iface);
352: if (err) {
353: aprint_error("%s: Could not get interface 0 handle %s (%d)\n",
354: USBDEVNAME(sc->sc_dev), usbd_errstr(err), err);
355:
356: USB_ATTACH_ERROR_RETURN;
357: }
1.5 dsainty 358:
359: sc->sc_evt_addr = -1;
360: sc->sc_aclrd_addr = -1;
361: sc->sc_aclwr_addr = -1;
362:
1.14 gdamore 363: count = 0;
364: (void)usbd_endpoint_count(iface, &count);
365:
366: for (i = 0 ; i < count ; i++) {
367: int dir, type;
368:
1.1 augustss 369: ed = usbd_interface2endpoint_descriptor(iface, i);
370: if (ed == NULL) {
1.14 gdamore 371: aprint_error("%s: could not read endpoint descriptor %d\n",
1.1 augustss 372: USBDEVNAME(sc->sc_dev), i);
1.14 gdamore 373:
1.1 augustss 374: USB_ATTACH_ERROR_RETURN;
375: }
1.5 dsainty 376:
1.14 gdamore 377: dir = UE_GET_DIR(ed->bEndpointAddress);
378: type = UE_GET_XFERTYPE(ed->bmAttributes);
1.5 dsainty 379:
1.14 gdamore 380: if (dir == UE_DIR_IN && type == UE_INTERRUPT)
1.5 dsainty 381: sc->sc_evt_addr = ed->bEndpointAddress;
1.14 gdamore 382: else if (dir == UE_DIR_IN && type == UE_BULK)
1.5 dsainty 383: sc->sc_aclrd_addr = ed->bEndpointAddress;
1.14 gdamore 384: else if (dir == UE_DIR_OUT && type == UE_BULK)
1.5 dsainty 385: sc->sc_aclwr_addr = ed->bEndpointAddress;
1.1 augustss 386: }
1.5 dsainty 387:
1.14 gdamore 388: if (sc->sc_evt_addr == -1) {
389: aprint_error("%s: missing INTERRUPT endpoint on interface 0\n",
390: USBDEVNAME(sc->sc_dev));
391:
392: USB_ATTACH_ERROR_RETURN;
393: }
394: if (sc->sc_aclrd_addr == -1) {
395: aprint_error("%s: missing BULK IN endpoint on interface 0\n",
396: USBDEVNAME(sc->sc_dev));
397:
398: USB_ATTACH_ERROR_RETURN;
399: }
400: if (sc->sc_aclwr_addr == -1) {
401: aprint_error("%s: missing BULK OUT endpoint on interface 0\n",
402: USBDEVNAME(sc->sc_dev));
403:
404: USB_ATTACH_ERROR_RETURN;
405: }
406:
407: /* Interface 0 Ok */
408: sc->sc_iface0 = iface;
409: uaa->ifaces[0] = NULL;
410:
411: /*
412: * Interface 1 must have 2 endpoints
413: * 1) Isochronous IN endpoint to receive SCO data
414: * 2) Isochronous OUT endpoint to send SCO data
415: *
416: * and will have several configurations, which can be selected
417: * via a sysctl variable. We select config 0 to start, which
418: * means that no SCO data will be available.
419: */
420: err = usbd_device2interface_handle(sc->sc_udev, 1, &iface);
421: if (err) {
422: aprint_error("%s: Could not get interface 1 handle %s (%d)\n",
423: USBDEVNAME(sc->sc_dev), usbd_errstr(err), err);
424:
425: USB_ATTACH_ERROR_RETURN;
426: }
427:
428: cd = usbd_get_config_descriptor(sc->sc_udev);
429: if (cd == NULL) {
430: aprint_error("%s: could not get config descriptor\n",
431: USBDEVNAME(sc->sc_dev));
432:
433: USB_ATTACH_ERROR_RETURN;
434: }
435:
436: sc->sc_alt_config = usbd_get_no_alts(cd, 1);
437:
438: /* Interface 1 Ok */
439: sc->sc_iface1 = iface;
440: uaa->ifaces[1] = NULL;
441:
442: /* set initial config */
443: err = ubt_set_isoc_config(sc);
444: if (err) {
445: aprint_error("%s: ISOC config failed\n",
446: USBDEVNAME(sc->sc_dev));
447:
1.1 augustss 448: USB_ATTACH_ERROR_RETURN;
449: }
450:
1.14 gdamore 451: /* Attach HCI */
452: sc->sc_unit.hci_softc = sc;
453: sc->sc_unit.hci_devname = USBDEVNAME(sc->sc_dev);
454: sc->sc_unit.hci_enable = ubt_enable;
455: sc->sc_unit.hci_disable = ubt_disable;
456: sc->sc_unit.hci_start_cmd = ubt_xmit_cmd_start;
457: sc->sc_unit.hci_start_acl = ubt_xmit_acl_start;
458: sc->sc_unit.hci_start_sco = ubt_xmit_sco_start;
459: sc->sc_unit.hci_ipl = IPL_USB; /* XXX: IPL_SOFTUSB ?? */
460: hci_attach(&sc->sc_unit);
461:
462: usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
463: USBDEV(sc->sc_dev));
464:
465: /* sysctl set-up for alternate configs */
466: sysctl_createv(&sc->sc_log, 0, NULL, NULL,
467: CTLFLAG_PERMANENT,
468: CTLTYPE_NODE, "hw",
469: NULL,
470: NULL, 0,
471: NULL, 0,
472: CTL_HW, CTL_EOL);
473:
474: sysctl_createv(&sc->sc_log, 0, NULL, &node,
475: 0,
476: CTLTYPE_NODE, USBDEVNAME(sc->sc_dev),
477: SYSCTL_DESCR("ubt driver information"),
478: NULL, 0,
479: NULL, 0,
480: CTL_HW,
481: CTL_CREATE, CTL_EOL);
482:
483: if (node != NULL) {
484: sysctl_createv(&sc->sc_log, 0, NULL, NULL,
485: CTLFLAG_READWRITE,
486: CTLTYPE_INT, "config",
487: SYSCTL_DESCR("configuration number"),
488: ubt_sysctl_config, 0,
489: sc, 0,
490: CTL_HW, node->sysctl_num,
491: CTL_CREATE, CTL_EOL);
492:
493: sysctl_createv(&sc->sc_log, 0, NULL, NULL,
494: CTLFLAG_READONLY,
495: CTLTYPE_INT, "alt_config",
496: SYSCTL_DESCR("number of alternate configurations"),
497: NULL, 0,
498: &sc->sc_alt_config, sizeof(sc->sc_alt_config),
499: CTL_HW, node->sysctl_num,
500: CTL_CREATE, CTL_EOL);
501:
502: sysctl_createv(&sc->sc_log, 0, NULL, NULL,
503: CTLFLAG_READONLY,
504: CTLTYPE_INT, "sco_rxsize",
505: SYSCTL_DESCR("max SCO receive size"),
506: NULL, 0,
507: &sc->sc_scord_size, sizeof(sc->sc_scord_size),
508: CTL_HW, node->sysctl_num,
509: CTL_CREATE, CTL_EOL);
510:
511: sysctl_createv(&sc->sc_log, 0, NULL, NULL,
512: CTLFLAG_READONLY,
513: CTLTYPE_INT, "sco_txsize",
514: SYSCTL_DESCR("max SCO transmit size"),
515: NULL, 0,
516: &sc->sc_scowr_size, sizeof(sc->sc_scowr_size),
517: CTL_HW, node->sysctl_num,
518: CTL_CREATE, CTL_EOL);
519: }
520:
521: USB_ATTACH_SUCCESS_RETURN;
522: }
523:
524: USB_DETACH(ubt)
525: {
526: USB_DETACH_START(ubt, sc);
527: int s;
528:
529: DPRINTF("sc=%p flags=%d\n", sc, flags);
530:
531: sc->sc_dying = 1;
532:
533: /* delete sysctl nodes */
534: sysctl_teardown(&sc->sc_log);
535:
536: /* Detach HCI interface */
537: hci_detach(&sc->sc_unit);
538:
539: /*
540: * Abort all pipes. Causes processes waiting for transfer to wake.
541: *
542: * Actually, hci_detach() above will call ubt_disable() which may
543: * call ubt_abortdealloc(), but lets be sure since doing it twice
544: * wont cause an error.
545: */
546: ubt_abortdealloc(sc);
547:
548: /* wait for all processes to finish */
549: s = splusb();
550: if (sc->sc_refcnt-- > 0)
551: usb_detach_wait(USBDEV(sc->sc_dev));
552:
553: splx(s);
554:
555: usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
556: USBDEV(sc->sc_dev));
557:
558: DPRINTFN(1, "driver detached\n");
559:
560: return 0;
561: }
562:
563: int
564: ubt_activate(device_ptr_t self, enum devact act)
565: {
566: struct ubt_softc *sc = (struct ubt_softc *)self;
567: int error = 0;
568:
569: DPRINTFN(1, "ubt_activate: sc=%p, act=%d\n", sc, act);
570:
571: switch (act) {
572: case DVACT_ACTIVATE:
573: return EOPNOTSUPP;
574: break;
575:
576: case DVACT_DEACTIVATE:
577: sc->sc_dying = 1;
578: break;
579: }
580: return error;
581: }
582:
583: /* set ISOC configuration */
584: static int
585: ubt_set_isoc_config(struct ubt_softc *sc)
586: {
587: usb_endpoint_descriptor_t *ed;
588: int rd_addr, wr_addr, rd_size, wr_size;
589: uint8_t count, i;
590: int err;
591:
592: err = usbd_set_interface(sc->sc_iface1, sc->sc_config);
1.17 plunky 593: if (err != USBD_NORMAL_COMPLETION) {
1.14 gdamore 594: aprint_error(
595: "%s: Could not set config %d on ISOC interface. %s (%d)\n",
596: USBDEVNAME(sc->sc_dev), sc->sc_config, usbd_errstr(err), err);
597:
1.17 plunky 598: return err == USBD_IN_USE ? EBUSY : EIO;
1.14 gdamore 599: }
600:
601: /*
602: * We wont get past the above if there are any pipes open, so no
603: * need to worry about buf/xfer/pipe deallocation. If we get an
604: * error after this, the frame quantities will be 0 and no SCO
605: * data will be possible.
606: */
607:
608: sc->sc_scord_size = rd_size = 0;
609: sc->sc_scord_addr = rd_addr = -1;
610:
611: sc->sc_scowr_size = wr_size = 0;
612: sc->sc_scowr_addr = wr_addr = -1;
613:
614: count = 0;
615: (void)usbd_endpoint_count(sc->sc_iface1, &count);
616:
617: for (i = 0 ; i < count ; i++) {
618: ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
619: if (ed == NULL) {
620: printf("%s: could not read endpoint descriptor %d\n",
621: USBDEVNAME(sc->sc_dev), i);
622:
623: return EIO;
624: }
625:
626: DPRINTFN(5, "%s: endpoint type %02x (%02x) addr %02x (%s)\n",
627: USBDEVNAME(sc->sc_dev),
628: UE_GET_XFERTYPE(ed->bmAttributes),
629: UE_GET_ISO_TYPE(ed->bmAttributes),
630: ed->bEndpointAddress,
631: UE_GET_DIR(ed->bEndpointAddress) ? "in" : "out");
632:
633: if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
1.3 augustss 634: continue;
1.14 gdamore 635:
636: if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
637: rd_addr = ed->bEndpointAddress;
638: rd_size = UGETW(ed->wMaxPacketSize);
639: } else {
640: wr_addr = ed->bEndpointAddress;
641: wr_size = UGETW(ed->wMaxPacketSize);
1.3 augustss 642: }
643: }
644:
1.14 gdamore 645: if (rd_addr == -1) {
646: aprint_error(
647: "%s: missing ISOC IN endpoint on interface config %d\n",
648: USBDEVNAME(sc->sc_dev), sc->sc_config);
649:
650: return ENOENT;
651: }
652: if (wr_addr == -1) {
653: aprint_error(
654: "%s: missing ISOC OUT endpoint on interface config %d\n",
655: USBDEVNAME(sc->sc_dev), sc->sc_config);
656:
657: return ENOENT;
658: }
659:
660: #ifdef DIAGNOSTIC
661: if (rd_size > MLEN) {
662: printf("%s: rd_size=%d exceeds MLEN\n",
663: USBDEVNAME(sc->sc_dev), rd_size);
664:
665: return EOVERFLOW;
666: }
1.3 augustss 667:
1.14 gdamore 668: if (wr_size > MLEN) {
669: printf("%s: wr_size=%d exceeds MLEN\n",
670: USBDEVNAME(sc->sc_dev), wr_size);
671:
672: return EOVERFLOW;
673: }
674: #endif
675:
676: sc->sc_scord_size = rd_size;
677: sc->sc_scord_addr = rd_addr;
678:
679: sc->sc_scowr_size = wr_size;
680: sc->sc_scowr_addr = wr_addr;
681:
682: return 0;
683: }
1.1 augustss 684:
1.14 gdamore 685: /* sysctl helper to set alternate configurations */
686: static int
687: ubt_sysctl_config(SYSCTLFN_ARGS)
688: {
689: struct sysctlnode node;
690: struct ubt_softc *sc;
691: int t, error;
692:
693: node = *rnode;
694: sc = node.sysctl_data;
695:
696: t = sc->sc_config;
697: node.sysctl_data = &t;
698: error = sysctl_lookup(SYSCTLFN_CALL(&node));
699: if (error || newp == NULL)
700: return error;
1.5 dsainty 701:
1.14 gdamore 702: if (t < 0 || t >= sc->sc_alt_config)
703: return EINVAL;
1.1 augustss 704:
1.18 plunky 705: /* This may not change when the unit is enabled */
706: if (sc->sc_unit.hci_flags & BTF_RUNNING)
707: return EBUSY;
708:
1.14 gdamore 709: sc->sc_config = t;
710: return ubt_set_isoc_config(sc);
1.1 augustss 711: }
712:
1.5 dsainty 713: static void
714: ubt_abortdealloc(struct ubt_softc *sc)
715: {
1.14 gdamore 716: int i;
717:
718: DPRINTFN(1, "sc=%p\n", sc);
1.5 dsainty 719:
1.14 gdamore 720: /* Abort all pipes */
1.5 dsainty 721: if (sc->sc_evt_pipe != NULL) {
722: usbd_abort_pipe(sc->sc_evt_pipe);
723: usbd_close_pipe(sc->sc_evt_pipe);
724: sc->sc_evt_pipe = NULL;
725: }
1.14 gdamore 726:
1.5 dsainty 727: if (sc->sc_aclrd_pipe != NULL) {
728: usbd_abort_pipe(sc->sc_aclrd_pipe);
729: usbd_close_pipe(sc->sc_aclrd_pipe);
730: sc->sc_aclrd_pipe = NULL;
731: }
1.14 gdamore 732:
1.5 dsainty 733: if (sc->sc_aclwr_pipe != NULL) {
734: usbd_abort_pipe(sc->sc_aclwr_pipe);
735: usbd_close_pipe(sc->sc_aclwr_pipe);
736: sc->sc_aclwr_pipe = NULL;
737: }
1.14 gdamore 738:
739: if (sc->sc_scord_pipe != NULL) {
740: usbd_abort_pipe(sc->sc_scord_pipe);
741: usbd_close_pipe(sc->sc_scord_pipe);
742: sc->sc_scord_pipe = NULL;
743: }
744:
745: if (sc->sc_scowr_pipe != NULL) {
746: usbd_abort_pipe(sc->sc_scowr_pipe);
747: usbd_close_pipe(sc->sc_scowr_pipe);
748: sc->sc_scowr_pipe = NULL;
749: }
750:
751: /* Free event buffer */
752: if (sc->sc_evt_buf != NULL) {
753: free(sc->sc_evt_buf, M_USBDEV);
754: sc->sc_evt_buf = NULL;
755: }
756:
757: /* Free all xfers and xfer buffers (implicit) */
758: if (sc->sc_cmd_xfer != NULL) {
759: usbd_free_xfer(sc->sc_cmd_xfer);
760: sc->sc_cmd_xfer = NULL;
761: sc->sc_cmd_buf = NULL;
762: }
763:
1.5 dsainty 764: if (sc->sc_aclrd_xfer != NULL) {
765: usbd_free_xfer(sc->sc_aclrd_xfer);
766: sc->sc_aclrd_xfer = NULL;
767: sc->sc_aclrd_buf = NULL;
768: }
1.14 gdamore 769:
1.5 dsainty 770: if (sc->sc_aclwr_xfer != NULL) {
771: usbd_free_xfer(sc->sc_aclwr_xfer);
772: sc->sc_aclwr_xfer = NULL;
773: sc->sc_aclwr_buf = NULL;
774: }
775:
1.14 gdamore 776: for (i = 0 ; i < UBT_NXFERS ; i++) {
777: if (sc->sc_scord[i].xfer != NULL) {
778: usbd_free_xfer(sc->sc_scord[i].xfer);
779: sc->sc_scord[i].xfer = NULL;
780: sc->sc_scord[i].buf = NULL;
781: }
1.1 augustss 782:
1.14 gdamore 783: if (sc->sc_scowr[i].xfer != NULL) {
784: usbd_free_xfer(sc->sc_scowr[i].xfer);
785: sc->sc_scowr[i].xfer = NULL;
786: sc->sc_scowr[i].buf = NULL;
787: }
1.1 augustss 788: }
789:
1.14 gdamore 790: /* Free partial SCO packets */
791: if (sc->sc_scord_mbuf != NULL) {
792: m_freem(sc->sc_scord_mbuf);
793: sc->sc_scord_mbuf = NULL;
1.1 augustss 794: }
795:
1.14 gdamore 796: if (sc->sc_scowr_mbuf != NULL) {
797: m_freem(sc->sc_scowr_mbuf);
798: sc->sc_scowr_mbuf = NULL;
1.1 augustss 799: }
1.5 dsainty 800: }
801:
1.14 gdamore 802: /*******************************************************************************
803: *
804: * Bluetooth Unit/USB callbacks
805: *
806: * All of this will be called at the IPL_ we specified above
807: */
1.5 dsainty 808: static int
1.14 gdamore 809: ubt_enable(struct hci_unit *unit)
1.5 dsainty 810: {
1.14 gdamore 811: struct ubt_softc *sc = unit->hci_softc;
1.5 dsainty 812: usbd_status err;
1.14 gdamore 813: int i, error;
1.5 dsainty 814:
1.14 gdamore 815: DPRINTFN(1, "sc=%p\n", sc);
1.5 dsainty 816:
1.14 gdamore 817: if (unit->hci_flags & BTF_RUNNING)
818: return 0;
819:
820: /* Events */
821: sc->sc_evt_buf = malloc(UBT_BUFSIZ_EVENT, M_USBDEV, M_NOWAIT);
1.5 dsainty 822: if (sc->sc_evt_buf == NULL) {
823: error = ENOMEM;
1.14 gdamore 824: goto bad;
1.5 dsainty 825: }
1.14 gdamore 826: err = usbd_open_pipe_intr(sc->sc_iface0,
827: sc->sc_evt_addr,
828: USBD_SHORT_XFER_OK,
829: &sc->sc_evt_pipe,
830: sc,
831: sc->sc_evt_buf,
832: UBT_BUFSIZ_EVENT,
833: ubt_recv_event,
1.21 ! drochner 834: USBD_DEFAULT_INTERVAL);
1.5 dsainty 835: if (err != USBD_NORMAL_COMPLETION) {
836: error = EIO;
1.14 gdamore 837: goto bad;
1.5 dsainty 838: }
839:
1.14 gdamore 840: /* Commands */
841: sc->sc_cmd_xfer = usbd_alloc_xfer(sc->sc_udev);
842: if (sc->sc_cmd_xfer == NULL) {
843: error = ENOMEM;
844: goto bad;
845: }
846: sc->sc_cmd_buf = usbd_alloc_buffer(sc->sc_cmd_xfer, UBT_BUFSIZ_CMD);
847: if (sc->sc_cmd_buf == NULL) {
848: error = ENOMEM;
849: goto bad;
1.5 dsainty 850: }
851:
1.14 gdamore 852: /* ACL read */
853: err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclrd_addr,
854: USBD_EXCLUSIVE_USE, &sc->sc_aclrd_pipe);
1.5 dsainty 855: if (err != USBD_NORMAL_COMPLETION) {
856: error = EIO;
1.14 gdamore 857: goto bad;
1.5 dsainty 858: }
859: sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
860: if (sc->sc_aclrd_xfer == NULL) {
861: error = ENOMEM;
1.14 gdamore 862: goto bad;
1.5 dsainty 863: }
1.14 gdamore 864: sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer, UBT_BUFSIZ_ACL);
865: if (sc->sc_aclrd_buf == NULL) {
1.5 dsainty 866: error = ENOMEM;
1.14 gdamore 867: goto bad;
1.5 dsainty 868: }
1.14 gdamore 869: sc->sc_aclrd_busy = 0;
870: ubt_recv_acl_start(sc);
1.5 dsainty 871:
1.14 gdamore 872: /* ACL write */
873: err = usbd_open_pipe(sc->sc_iface0, sc->sc_aclwr_addr,
874: USBD_EXCLUSIVE_USE, &sc->sc_aclwr_pipe);
875: if (err != USBD_NORMAL_COMPLETION) {
876: error = EIO;
877: goto bad;
1.5 dsainty 878: }
1.14 gdamore 879: sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
880: if (sc->sc_aclwr_xfer == NULL) {
1.5 dsainty 881: error = ENOMEM;
1.14 gdamore 882: goto bad;
1.5 dsainty 883: }
1.14 gdamore 884: sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer, UBT_BUFSIZ_ACL);
1.5 dsainty 885: if (sc->sc_aclwr_buf == NULL) {
886: error = ENOMEM;
1.14 gdamore 887: goto bad;
888: }
889:
890: /* SCO read */
891: if (sc->sc_scord_size > 0) {
892: err = usbd_open_pipe(sc->sc_iface1, sc->sc_scord_addr,
893: USBD_EXCLUSIVE_USE, &sc->sc_scord_pipe);
894: if (err != USBD_NORMAL_COMPLETION) {
895: error = EIO;
896: goto bad;
897: }
898:
899: for (i = 0 ; i < UBT_NXFERS ; i++) {
900: sc->sc_scord[i].xfer = usbd_alloc_xfer(sc->sc_udev);
901: if (sc->sc_scord[i].xfer == NULL) {
902: error = ENOMEM;
903: goto bad;
904: }
905: sc->sc_scord[i].buf = usbd_alloc_buffer(sc->sc_scord[i].xfer,
906: sc->sc_scord_size * UBT_NFRAMES);
907: if (sc->sc_scord[i].buf == NULL) {
908: error = ENOMEM;
909: goto bad;
910: }
911: sc->sc_scord[i].softc = sc;
912: sc->sc_scord[i].busy = 0;
913: ubt_recv_sco_start1(sc, &sc->sc_scord[i]);
914: }
1.5 dsainty 915: }
916:
1.14 gdamore 917: /* SCO write */
918: if (sc->sc_scowr_size > 0) {
919: err = usbd_open_pipe(sc->sc_iface1, sc->sc_scowr_addr,
920: USBD_EXCLUSIVE_USE, &sc->sc_scowr_pipe);
921: if (err != USBD_NORMAL_COMPLETION) {
922: error = EIO;
923: goto bad;
924: }
925:
926: for (i = 0 ; i < UBT_NXFERS ; i++) {
927: sc->sc_scowr[i].xfer = usbd_alloc_xfer(sc->sc_udev);
928: if (sc->sc_scowr[i].xfer == NULL) {
929: error = ENOMEM;
930: goto bad;
931: }
932: sc->sc_scowr[i].buf = usbd_alloc_buffer(sc->sc_scowr[i].xfer,
933: sc->sc_scowr_size * UBT_NFRAMES);
934: if (sc->sc_scowr[i].buf == NULL) {
935: error = ENOMEM;
936: goto bad;
937: }
938: sc->sc_scowr[i].softc = sc;
939: sc->sc_scowr[i].busy = 0;
940: }
941: }
1.5 dsainty 942:
1.14 gdamore 943: unit->hci_flags &= ~BTF_XMIT;
944: unit->hci_flags |= BTF_RUNNING;
1.5 dsainty 945: return 0;
946:
1.14 gdamore 947: bad:
948: ubt_abortdealloc(sc);
1.5 dsainty 949: return error;
950: }
951:
1.14 gdamore 952: static void
953: ubt_disable(struct hci_unit *unit)
1.5 dsainty 954: {
1.14 gdamore 955: struct ubt_softc *sc = unit->hci_softc;
956:
957: DPRINTFN(1, "sc=%p\n", sc);
1.5 dsainty 958:
1.14 gdamore 959: if ((unit->hci_flags & BTF_RUNNING) == 0)
960: return;
1.5 dsainty 961:
962: ubt_abortdealloc(sc);
963:
1.14 gdamore 964: unit->hci_flags &= ~BTF_RUNNING;
1.5 dsainty 965: }
966:
1.14 gdamore 967: static void
968: ubt_xmit_cmd_start(struct hci_unit *unit)
1.5 dsainty 969: {
1.14 gdamore 970: struct ubt_softc *sc = unit->hci_softc;
1.5 dsainty 971: usb_device_request_t req;
972: usbd_status status;
1.14 gdamore 973: struct mbuf *m;
974: int len;
1.5 dsainty 975:
1.14 gdamore 976: if (sc->sc_dying)
977: return;
1.5 dsainty 978:
1.14 gdamore 979: if (MBUFQ_FIRST(&unit->hci_cmdq) == NULL)
980: return;
1.6 dsainty 981:
1.14 gdamore 982: MBUFQ_DEQUEUE(&unit->hci_cmdq, m);
983: KASSERT(m != NULL);
1.5 dsainty 984:
1.14 gdamore 985: DPRINTFN(15, "%s: xmit CMD packet (%d bytes)\n",
986: unit->hci_devname, m->m_pkthdr.len);
1.5 dsainty 987:
988: sc->sc_refcnt++;
1.14 gdamore 989: unit->hci_flags |= BTF_XMIT_CMD;
990:
991: len = m->m_pkthdr.len - 1;
992: m_copydata(m, 1, len, sc->sc_cmd_buf);
993: m_freem(m);
1.5 dsainty 994:
995: memset(&req, 0, sizeof(req));
996: req.bmRequestType = UT_WRITE_CLASS_DEVICE;
997: USETW(req.wLength, len);
998:
1.14 gdamore 999: usbd_setup_default_xfer(sc->sc_cmd_xfer,
1.5 dsainty 1000: sc->sc_udev,
1.14 gdamore 1001: unit,
1002: UBT_CMD_TIMEOUT,
1003: &req,
1004: sc->sc_cmd_buf,
1005: len,
1006: USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1007: ubt_xmit_cmd_complete);
1008:
1009: status = usbd_transfer(sc->sc_cmd_xfer);
1010:
1011: KASSERT(status != USBD_NORMAL_COMPLETION);
1012:
1013: if (status != USBD_IN_PROGRESS) {
1014: DPRINTF("usbd_transfer status=%s (%d)\n",
1015: usbd_errstr(status), status);
1016:
1017: sc->sc_refcnt--;
1018: unit->hci_flags &= ~BTF_XMIT_CMD;
1019: }
1020: }
1021:
1022: static void
1023: ubt_xmit_cmd_complete(usbd_xfer_handle xfer,
1024: usbd_private_handle h, usbd_status status)
1025: {
1026: struct hci_unit *unit = h;
1027: struct ubt_softc *sc = unit->hci_softc;
1028: uint32_t count;
1.5 dsainty 1029:
1.14 gdamore 1030: DPRINTFN(15, "%s: CMD complete status=%s (%d)\n",
1031: unit->hci_devname, usbd_errstr(status), status);
1.5 dsainty 1032:
1.14 gdamore 1033: unit->hci_flags &= ~BTF_XMIT_CMD;
1034:
1035: if (--sc->sc_refcnt < 0) {
1036: DPRINTF("sc_refcnt=%d\n", sc->sc_refcnt);
1.5 dsainty 1037: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.14 gdamore 1038: return;
1039: }
1.5 dsainty 1040:
1.14 gdamore 1041: if (sc->sc_dying) {
1042: DPRINTF("sc_dying\n");
1043: return;
1044: }
1.5 dsainty 1045:
1.14 gdamore 1046: if (status != USBD_NORMAL_COMPLETION) {
1047: DPRINTF("status=%s (%d)\n",
1048: usbd_errstr(status), status);
1.5 dsainty 1049:
1.14 gdamore 1050: unit->hci_stats.err_tx++;
1051: return;
1052: }
1.6 dsainty 1053:
1.14 gdamore 1054: usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1055: unit->hci_stats.cmd_tx++;
1056: unit->hci_stats.byte_tx += count;
1.6 dsainty 1057:
1.14 gdamore 1058: ubt_xmit_cmd_start(unit);
1.6 dsainty 1059: }
1060:
1.14 gdamore 1061: static void
1062: ubt_xmit_acl_start(struct hci_unit *unit)
1.5 dsainty 1063: {
1.14 gdamore 1064: struct ubt_softc *sc = unit->hci_softc;
1065: struct mbuf *m;
1.5 dsainty 1066: usbd_status status;
1.14 gdamore 1067: int len;
1068:
1069: if (sc->sc_dying)
1070: return;
1071:
1072: if (MBUFQ_FIRST(&unit->hci_acltxq) == NULL)
1073: return;
1.5 dsainty 1074:
1.14 gdamore 1075: sc->sc_refcnt++;
1076: unit->hci_flags |= BTF_XMIT_ACL;
1077:
1078: MBUFQ_DEQUEUE(&unit->hci_acltxq, m);
1079: KASSERT(m != NULL);
1.5 dsainty 1080:
1.14 gdamore 1081: DPRINTFN(15, "%s: xmit ACL packet (%d bytes)\n",
1082: unit->hci_devname, m->m_pkthdr.len);
1083:
1084: len = m->m_pkthdr.len - 1;
1085: if (len > UBT_BUFSIZ_ACL) {
1086: DPRINTF("%s: truncating ACL packet (%d => %d)!\n",
1087: unit->hci_devname, len, UBT_BUFSIZ_ACL);
1.6 dsainty 1088:
1.14 gdamore 1089: len = UBT_BUFSIZ_ACL;
1090: }
1.5 dsainty 1091:
1.14 gdamore 1092: m_copydata(m, 1, len, sc->sc_aclwr_buf);
1093: m_freem(m);
1.5 dsainty 1094:
1.14 gdamore 1095: unit->hci_stats.acl_tx++;
1096: unit->hci_stats.byte_tx += len;
1.5 dsainty 1097:
1098: usbd_setup_xfer(sc->sc_aclwr_xfer,
1099: sc->sc_aclwr_pipe,
1.14 gdamore 1100: unit,
1101: sc->sc_aclwr_buf,
1102: len,
1103: USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1104: UBT_ACL_TIMEOUT,
1105: ubt_xmit_acl_complete);
1.5 dsainty 1106:
1107: status = usbd_transfer(sc->sc_aclwr_xfer);
1108:
1.14 gdamore 1109: KASSERT(status != USBD_NORMAL_COMPLETION);
1110:
1111: if (status != USBD_IN_PROGRESS) {
1112: DPRINTF("usbd_transfer status=%s (%d)\n",
1113: usbd_errstr(status), status);
1114:
1115: sc->sc_refcnt--;
1116: unit->hci_flags &= ~BTF_XMIT_ACL;
1117: }
1118: }
1119:
1120: static void
1.20 christos 1121: ubt_xmit_acl_complete(usbd_xfer_handle xfer,
1.14 gdamore 1122: usbd_private_handle h, usbd_status status)
1123: {
1124: struct hci_unit *unit = h;
1125: struct ubt_softc *sc = unit->hci_softc;
1126:
1127: DPRINTFN(15, "%s: ACL complete status=%s (%d)\n",
1128: unit->hci_devname, usbd_errstr(status), status);
1129:
1130: unit->hci_flags &= ~BTF_XMIT_ACL;
1131:
1132: if (--sc->sc_refcnt < 0) {
1.5 dsainty 1133: usb_detach_wakeup(USBDEV(sc->sc_dev));
1.14 gdamore 1134: return;
1135: }
1.5 dsainty 1136:
1.14 gdamore 1137: if (sc->sc_dying)
1138: return;
1.5 dsainty 1139:
1.14 gdamore 1140: if (status != USBD_NORMAL_COMPLETION) {
1141: DPRINTF("status=%s (%d)\n",
1142: usbd_errstr(status), status);
1143:
1144: unit->hci_stats.err_tx++;
1145:
1146: if (status == USBD_STALLED)
1147: usbd_clear_endpoint_stall_async(sc->sc_aclwr_pipe);
1148: else
1149: return;
1150: }
1151:
1152: ubt_xmit_acl_start(unit);
1153: }
1154:
1155: static void
1156: ubt_xmit_sco_start(struct hci_unit *unit)
1157: {
1158: struct ubt_softc *sc = unit->hci_softc;
1159: int i;
1160:
1161: if (sc->sc_dying || sc->sc_scowr_size == 0)
1162: return;
1163:
1164: for (i = 0 ; i < UBT_NXFERS ; i++) {
1165: if (sc->sc_scowr[i].busy)
1166: continue;
1167:
1168: ubt_xmit_sco_start1(sc, &sc->sc_scowr[i]);
1169: }
1.5 dsainty 1170: }
1171:
1.14 gdamore 1172: static void
1173: ubt_xmit_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1.6 dsainty 1174: {
1.14 gdamore 1175: struct mbuf *m;
1176: uint8_t *buf;
1177: int num, len, size, space;
1178:
1179: space = sc->sc_scowr_size * UBT_NFRAMES;
1180: buf = isoc->buf;
1181: len = 0;
1182:
1183: /*
1184: * Fill the request buffer with data from the queue,
1185: * keeping any leftover packet on our private hook.
1186: *
1187: * Complete packets are passed back up to the stack
1188: * for disposal, since we can't rely on the controller
1189: * to tell us when it has finished with them.
1190: */
1191:
1192: m = sc->sc_scowr_mbuf;
1193: while (space > 0) {
1194: if (m == NULL) {
1195: MBUFQ_DEQUEUE(&sc->sc_unit.hci_scotxq, m);
1196: if (m == NULL)
1197: break;
1198:
1199: m_adj(m, 1); /* packet type */
1200: }
1201:
1202: if (m->m_pkthdr.len > 0) {
1203: size = MIN(m->m_pkthdr.len, space);
1204:
1205: m_copydata(m, 0, size, buf);
1206: m_adj(m, size);
1207:
1208: buf += size;
1209: len += size;
1210: space -= size;
1211: }
1212:
1213: if (m->m_pkthdr.len == 0) {
1214: sc->sc_unit.hci_stats.sco_tx++;
1215: hci_complete_sco(&sc->sc_unit, m);
1216: m = NULL;
1217: }
1218: }
1219: sc->sc_scowr_mbuf = m;
1220:
1221: DPRINTFN(15, "isoc=%p, len=%d, space=%d\n", isoc, len, space);
1222:
1223: if (len == 0) /* nothing to send */
1224: return;
1225:
1226: sc->sc_refcnt++;
1227: sc->sc_unit.hci_flags |= BTF_XMIT_SCO;
1228: sc->sc_unit.hci_stats.byte_tx += len;
1229: isoc->busy = 1;
1230:
1231: /*
1232: * calculate number of isoc frames and sizes
1233: */
1234:
1235: for (num = 0 ; len > 0 ; num++) {
1236: size = MIN(sc->sc_scowr_size, len);
1237:
1238: isoc->size[num] = size;
1239: len -= size;
1240: }
1241:
1242: usbd_setup_isoc_xfer(isoc->xfer,
1243: sc->sc_scowr_pipe,
1244: isoc,
1245: isoc->size,
1246: num,
1247: USBD_NO_COPY | USBD_FORCE_SHORT_XFER,
1248: ubt_xmit_sco_complete);
1249:
1250: usbd_transfer(isoc->xfer);
1.6 dsainty 1251: }
1252:
1.14 gdamore 1253: static void
1.20 christos 1254: ubt_xmit_sco_complete(usbd_xfer_handle xfer,
1.14 gdamore 1255: usbd_private_handle h, usbd_status status)
1.5 dsainty 1256: {
1.14 gdamore 1257: struct ubt_isoc_xfer *isoc = h;
1258: struct ubt_softc *sc;
1259: int i;
1260:
1261: KASSERT(xfer == isoc->xfer);
1262: sc = isoc->softc;
1263:
1264: DPRINTFN(15, "isoc=%p, status=%s (%d)\n",
1265: isoc, usbd_errstr(status), status);
1266:
1267: isoc->busy = 0;
1268:
1269: for (i = 0 ; ; i++) {
1270: if (i == UBT_NXFERS) {
1271: sc->sc_unit.hci_flags &= ~BTF_XMIT_SCO;
1272: break;
1273: }
1.5 dsainty 1274:
1.14 gdamore 1275: if (sc->sc_scowr[i].busy)
1276: break;
1277: }
1278:
1279: if (--sc->sc_refcnt < 0) {
1280: usb_detach_wakeup(USBDEV(sc->sc_dev));
1281: return;
1282: }
1.5 dsainty 1283:
1284: if (sc->sc_dying)
1.14 gdamore 1285: return;
1.5 dsainty 1286:
1.14 gdamore 1287: if (status != USBD_NORMAL_COMPLETION) {
1288: DPRINTF("status=%s (%d)\n",
1289: usbd_errstr(status), status);
1290:
1291: sc->sc_unit.hci_stats.err_tx++;
1292:
1293: if (status == USBD_STALLED)
1294: usbd_clear_endpoint_stall_async(sc->sc_scowr_pipe);
1295: else
1296: return;
1297: }
1298:
1299: ubt_xmit_sco_start(&sc->sc_unit);
1300: }
1301:
1302: /*
1303: * load incoming data into an mbuf with
1304: * leading type byte
1305: */
1306: static struct mbuf *
1307: ubt_mbufload(uint8_t *buf, int count, uint8_t type)
1308: {
1309: struct mbuf *m;
1310:
1311: MGETHDR(m, M_DONTWAIT, MT_DATA);
1312: if (m == NULL)
1313: return NULL;
1314:
1315: *mtod(m, uint8_t *) = type;
1316: m->m_pkthdr.len = m->m_len = MHLEN;
1317: m_copyback(m, 1, count, buf); // (extends if necessary)
1318: if (m->m_pkthdr.len != MAX(MHLEN, count + 1)) {
1319: m_free(m);
1320: return NULL;
1321: }
1322:
1323: m->m_pkthdr.len = count + 1;
1324: m->m_len = MIN(MHLEN, m->m_pkthdr.len);
1325:
1326: return m;
1.5 dsainty 1327: }
1328:
1329: static void
1.14 gdamore 1330: ubt_recv_event(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
1.5 dsainty 1331: {
1332: struct ubt_softc *sc = h;
1.14 gdamore 1333: struct mbuf *m;
1334: uint32_t count;
1.5 dsainty 1335: void *buf;
1336:
1.14 gdamore 1337: DPRINTFN(15, "sc=%p status=%s (%d)\n",
1338: sc, usbd_errstr(status), status);
1.5 dsainty 1339:
1.14 gdamore 1340: if (status != USBD_NORMAL_COMPLETION || sc->sc_dying)
1.5 dsainty 1341: return;
1342:
1.14 gdamore 1343: usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1344:
1.16 plunky 1345: if (count < sizeof(hci_event_hdr_t) - 1) {
1346: DPRINTF("dumped undersized event (count = %d)\n", count);
1347: sc->sc_unit.hci_stats.err_rx++;
1348: return;
1349: }
1350:
1.14 gdamore 1351: sc->sc_unit.hci_stats.evt_rx++;
1352: sc->sc_unit.hci_stats.byte_rx += count;
1.5 dsainty 1353:
1.14 gdamore 1354: m = ubt_mbufload(buf, count, HCI_EVENT_PKT);
1355: if (m != NULL)
1356: hci_input_event(&sc->sc_unit, m);
1357: else
1358: sc->sc_unit.hci_stats.err_rx++;
1.5 dsainty 1359: }
1360:
1361: static void
1.14 gdamore 1362: ubt_recv_acl_start(struct ubt_softc *sc)
1.5 dsainty 1363: {
1364: usbd_status status;
1365:
1.14 gdamore 1366: DPRINTFN(15, "sc=%p\n", sc);
1.5 dsainty 1367:
1.14 gdamore 1368: if (sc->sc_aclrd_busy || sc->sc_dying) {
1369: DPRINTF("sc_aclrd_busy=%d, sc_dying=%d\n",
1370: sc->sc_aclrd_busy,
1371: sc->sc_dying);
1.5 dsainty 1372:
1373: return;
1374: }
1.6 dsainty 1375:
1.14 gdamore 1376: sc->sc_refcnt++;
1377: sc->sc_aclrd_busy = 1;
1378:
1379: usbd_setup_xfer(sc->sc_aclrd_xfer,
1380: sc->sc_aclrd_pipe,
1381: sc,
1382: sc->sc_aclrd_buf,
1383: UBT_BUFSIZ_ACL,
1384: USBD_NO_COPY | USBD_SHORT_XFER_OK,
1385: USBD_NO_TIMEOUT,
1386: ubt_recv_acl_complete);
1.5 dsainty 1387:
1388: status = usbd_transfer(sc->sc_aclrd_xfer);
1.9 dsainty 1389:
1.14 gdamore 1390: KASSERT(status != USBD_NORMAL_COMPLETION);
1.5 dsainty 1391:
1.14 gdamore 1392: if (status != USBD_IN_PROGRESS) {
1393: DPRINTF("usbd_transfer status=%s (%d)\n",
1394: usbd_errstr(status), status);
1.5 dsainty 1395:
1.14 gdamore 1396: sc->sc_refcnt--;
1397: sc->sc_aclrd_busy = 0;
1398: }
1.5 dsainty 1399: }
1400:
1401: static void
1.14 gdamore 1402: ubt_recv_acl_complete(usbd_xfer_handle xfer,
1403: usbd_private_handle h, usbd_status status)
1.5 dsainty 1404: {
1405: struct ubt_softc *sc = h;
1.14 gdamore 1406: struct mbuf *m;
1407: uint32_t count;
1.5 dsainty 1408: void *buf;
1409:
1.14 gdamore 1410: DPRINTFN(15, "sc=%p status=%s (%d)\n",
1411: sc, usbd_errstr(status), status);
1412:
1413: sc->sc_aclrd_busy = 0;
1414:
1415: if (--sc->sc_refcnt < 0) {
1416: DPRINTF("refcnt = %d\n", sc->sc_refcnt);
1417: usb_detach_wakeup(USBDEV(sc->sc_dev));
1418: return;
1419: }
1420:
1421: if (sc->sc_dying) {
1422: DPRINTF("sc_dying\n");
1423: return;
1424: }
1425:
1426: if (status != USBD_NORMAL_COMPLETION) {
1427: DPRINTF("status=%s (%d)\n",
1428: usbd_errstr(status), status);
1429:
1430: sc->sc_unit.hci_stats.err_rx++;
1431:
1432: if (status == USBD_STALLED)
1433: usbd_clear_endpoint_stall_async(sc->sc_aclrd_pipe);
1434: else
1435: return;
1436: } else {
1437: usbd_get_xfer_status(xfer, NULL, &buf, &count, NULL);
1438:
1.16 plunky 1439: if (count < sizeof(hci_acldata_hdr_t) - 1) {
1440: DPRINTF("dumped undersized packet (%d)\n", count);
1441: sc->sc_unit.hci_stats.err_rx++;
1442: } else {
1443: sc->sc_unit.hci_stats.acl_rx++;
1444: sc->sc_unit.hci_stats.byte_rx += count;
1.14 gdamore 1445:
1.16 plunky 1446: m = ubt_mbufload(buf, count, HCI_ACL_DATA_PKT);
1447: if (m != NULL)
1448: hci_input_acl(&sc->sc_unit, m);
1449: else
1450: sc->sc_unit.hci_stats.err_rx++;
1451: }
1.14 gdamore 1452: }
1.5 dsainty 1453:
1.14 gdamore 1454: /* and restart */
1455: ubt_recv_acl_start(sc);
1456: }
1457:
1458: static void
1459: ubt_recv_sco_start1(struct ubt_softc *sc, struct ubt_isoc_xfer *isoc)
1460: {
1461: int i;
1462:
1463: DPRINTFN(15, "sc=%p, isoc=%p\n", sc, isoc);
1464:
1465: if (isoc->busy || sc->sc_dying || sc->sc_scord_size == 0) {
1466: DPRINTF("%s%s%s\n",
1467: isoc->busy ? " busy" : "",
1468: sc->sc_dying ? " dying" : "",
1469: sc->sc_scord_size == 0 ? " size=0" : "");
1.5 dsainty 1470:
1471: return;
1.14 gdamore 1472: }
1473:
1474: sc->sc_refcnt++;
1475: isoc->busy = 1;
1.5 dsainty 1476:
1.14 gdamore 1477: for (i = 0 ; i < UBT_NFRAMES ; i++)
1478: isoc->size[i] = sc->sc_scord_size;
1.5 dsainty 1479:
1.14 gdamore 1480: usbd_setup_isoc_xfer(isoc->xfer,
1481: sc->sc_scord_pipe,
1482: isoc,
1483: isoc->size,
1484: UBT_NFRAMES,
1485: USBD_NO_COPY | USBD_SHORT_XFER_OK,
1486: ubt_recv_sco_complete);
1.5 dsainty 1487:
1.14 gdamore 1488: usbd_transfer(isoc->xfer);
1.5 dsainty 1489: }
1490:
1.14 gdamore 1491: static void
1492: ubt_recv_sco_complete(usbd_xfer_handle xfer,
1493: usbd_private_handle h, usbd_status status)
1.5 dsainty 1494: {
1.14 gdamore 1495: struct ubt_isoc_xfer *isoc = h;
1496: struct ubt_softc *sc;
1497: struct mbuf *m;
1498: uint32_t count;
1499: uint8_t *ptr, *frame;
1500: int i, size, got, want;
1501:
1502: KASSERT(isoc != NULL);
1503: KASSERT(isoc->xfer == xfer);
1504:
1505: sc = isoc->softc;
1506: isoc->busy = 0;
1507:
1508: if (--sc->sc_refcnt < 0) {
1509: DPRINTF("refcnt=%d\n", sc->sc_refcnt);
1510: usb_detach_wakeup(USBDEV(sc->sc_dev));
1511: return;
1512: }
1513:
1514: if (sc->sc_dying) {
1515: DPRINTF("sc_dying\n");
1516: return;
1517: }
1518:
1519: if (status != USBD_NORMAL_COMPLETION) {
1520: DPRINTF("status=%s (%d)\n",
1521: usbd_errstr(status), status);
1522:
1523: sc->sc_unit.hci_stats.err_rx++;
1524:
1525: if (status == USBD_STALLED) {
1526: usbd_clear_endpoint_stall_async(sc->sc_scord_pipe);
1527: goto restart;
1528: }
1529:
1530: return;
1531: }
1532:
1533: usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1534: if (count == 0)
1535: goto restart;
1536:
1537: DPRINTFN(15, "sc=%p, isoc=%p, count=%u\n",
1538: sc, isoc, count);
1539:
1540: sc->sc_unit.hci_stats.byte_rx += count;
1541:
1542: /*
1543: * Extract SCO packets from ISOC frames. The way we have it,
1544: * no SCO packet can be bigger than MHLEN. This is unlikely
1545: * to actually happen, but if we ran out of mbufs and lost
1546: * sync then we may get spurious data that makes it seem that
1547: * way, so we discard data that wont fit. This doesnt really
1548: * help with the lost sync situation alas.
1549: */
1550:
1551: m = sc->sc_scord_mbuf;
1552: if (m != NULL) {
1553: sc->sc_scord_mbuf = NULL;
1554: ptr = mtod(m, uint8_t *) + m->m_pkthdr.len;
1555: got = m->m_pkthdr.len;
1556: want = sizeof(hci_scodata_hdr_t);
1557: if (got >= want)
1558: want += mtod(m, hci_scodata_hdr_t *)->length ;
1559: } else {
1560: ptr = NULL;
1561: got = 0;
1562: want = 0;
1563: }
1564:
1565: for (i = 0 ; i < UBT_NFRAMES ; i++) {
1566: frame = isoc->buf + (i * sc->sc_scord_size);
1567:
1568: while (isoc->size[i] > 0) {
1569: size = isoc->size[i];
1570:
1571: if (m == NULL) {
1572: MGETHDR(m, M_DONTWAIT, MT_DATA);
1573: if (m == NULL) {
1574: printf("%s: out of memory (xfer halted)\n",
1575: USBDEVNAME(sc->sc_dev));
1576:
1577: sc->sc_unit.hci_stats.err_rx++;
1578: return; /* lost sync */
1579: }
1580:
1581: ptr = mtod(m, uint8_t *);
1582: *ptr++ = HCI_SCO_DATA_PKT;
1583: got = 1;
1584: want = sizeof(hci_scodata_hdr_t);
1585: }
1586:
1587: if (got + size > want)
1588: size = want - got;
1589:
1590: if (got + size > MHLEN)
1591: memcpy(ptr, frame, MHLEN - got);
1592: else
1593: memcpy(ptr, frame, size);
1594:
1595: ptr += size;
1596: got += size;
1597: frame += size;
1598:
1599: if (got == want) {
1600: /*
1601: * If we only got a header, add the packet
1602: * length to our want count. Send complete
1603: * packets up to protocol stack.
1604: */
1605: if (want == sizeof(hci_scodata_hdr_t))
1606: want += mtod(m, hci_scodata_hdr_t *)->length;
1607:
1608: if (got == want) {
1609: m->m_pkthdr.len = m->m_len = got;
1610: sc->sc_unit.hci_stats.sco_rx++;
1611: hci_input_sco(&sc->sc_unit, m);
1612: m = NULL;
1613: }
1614: }
1615:
1616: isoc->size[i] -= size;
1617: }
1618: }
1619:
1620: if (m != NULL) {
1621: m->m_pkthdr.len = m->m_len = got;
1622: sc->sc_scord_mbuf = m;
1623: }
1624:
1625: restart: /* and restart */
1626: ubt_recv_sco_start1(sc, isoc);
1.1 augustss 1627: }
CVSweb <webmaster@jp.NetBSD.org>