ubt.c revision 1.12 1 /* $NetBSD: ubt.c,v 1.12 2005/05/11 10:02:28 augustss Exp $ */
2
3 /*
4 * Copyright (c) 2002, 2003 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (lennart (at) augustsson.net) and
9 * David Sainty (David.Sainty (at) dtsp.co.nz).
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 * must display the following acknowledgement:
21 * This product includes software developed by the NetBSD
22 * Foundation, Inc. and its contributors.
23 * 4. Neither the name of The NetBSD Foundation nor the names of its
24 * contributors may be used to endorse or promote products derived
25 * from this software without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40 #include <sys/cdefs.h>
41 __KERNEL_RCSID(0, "$NetBSD: ubt.c,v 1.12 2005/05/11 10:02:28 augustss Exp $");
42
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/malloc.h>
47 #include <sys/device.h>
48 #include <sys/lock.h>
49 #include <sys/ioctl.h>
50 #include <sys/conf.h>
51 #include <sys/file.h>
52 #include <sys/poll.h>
53 #include <sys/select.h>
54 #include <sys/proc.h>
55
56 #include <dev/usb/ubtreg.h>
57 #include <dev/usb/usb.h>
58 #include <dev/usb/usbdi.h>
59 #include <dev/usb/usbdi_util.h>
60 #include <dev/usb/usbdevs.h>
61
62 #include <dev/bluetooth/bluetooth.h>
63
64 #ifdef UBT_DEBUG
65 #define DPRINTF(x) if (ubtdebug) logprintf x
66 #define DPRINTFN(n,x) if (ubtdebug>(n)) logprintf x
67 int ubtdebug = 49;
68 #else
69 #define DPRINTF(x)
70 #define DPRINTFN(n,x)
71 #endif
72
73 /*
74 * Protocol related definitions
75 */
76
77 struct ubt_softc {
78 USBBASEDEVICE sc_dev;
79 usbd_device_handle sc_udev;
80 usbd_interface_handle sc_ctl_iface;
81 usbd_interface_handle sc_isoc_iface;
82
83 /* Control */
84 usbd_pipe_handle sc_ctl_pipe;
85 usbd_xfer_handle sc_ctl_xfer;
86 u_int8_t *sc_ctl_buf;
87
88 /* Events */
89 int sc_evt_addr;
90 usbd_pipe_handle sc_evt_pipe;
91 usbd_xfer_handle sc_evt_xfer;
92 u_int8_t *sc_evt_buf;
93
94 /* ACL data (in) */
95 int sc_aclrd_addr;
96 usbd_pipe_handle sc_aclrd_pipe;
97 usbd_xfer_handle sc_aclrd_xfer;
98 u_int8_t *sc_aclrd_buf;
99 int sc_aclrd_running;
100
101 /* ACL data (out) */
102 int sc_aclwr_addr;
103 usbd_pipe_handle sc_aclwr_pipe;
104 usbd_xfer_handle sc_aclwr_xfer;
105 u_int8_t *sc_aclwr_buf;
106
107 struct device *sc_child;
108 struct btframe_callback_methods const *sc_cb;
109
110 int sc_refcnt;
111 char sc_dying;
112 };
113
114 static int ubt_open(void *h, int flag, int mode, usb_proc_ptr p);
115 static int ubt_close(void *h, int flag, int mode, usb_proc_ptr p);
116
117 static u_int8_t* ubt_alloc_control(void*, size_t, struct btframe_buffer**);
118 static int ubt_send_control(void*, struct btframe_buffer*, size_t);
119
120 static u_int8_t* ubt_alloc_acldata(void*, size_t, struct btframe_buffer**);
121 static int ubt_send_acldata(void*, struct btframe_buffer*, size_t);
122
123 static u_int8_t* ubt_alloc_scodata(void*, size_t, struct btframe_buffer**);
124 static int ubt_send_scodata(void*, struct btframe_buffer*, size_t);
125
126 static int ubt_splraise(void);
127
128 static void ubt_event_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
129 static void ubt_aclrd_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
130 static void ubt_aclrd_request(struct ubt_softc *);
131
132 static struct btframe_methods const ubt_methods = {
133 ubt_open, ubt_close,
134 {ubt_alloc_control, ubt_send_control},
135 {ubt_alloc_acldata, ubt_send_acldata},
136 {ubt_alloc_scodata, ubt_send_scodata},
137 ubt_splraise
138 };
139
140 USB_DECLARE_DRIVER(ubt);
141
142 USB_MATCH(ubt)
143 {
144 USB_MATCH_START(ubt, uaa);
145 usb_interface_descriptor_t *id;
146
147 DPRINTFN(50,("ubt_match\n"));
148
149 if (uaa->iface == NULL)
150 return (UMATCH_NONE);
151
152 id = usbd_get_interface_descriptor(uaa->iface);
153 if (id != NULL &&
154 id->bInterfaceClass == UICLASS_WIRELESS &&
155 id->bInterfaceSubClass == UISUBCLASS_RF &&
156 id->bInterfaceProtocol == UIPROTO_BLUETOOTH)
157 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
158 return (UMATCH_NONE);
159 }
160
161 USB_ATTACH(ubt)
162 {
163 USB_ATTACH_START(ubt, sc, uaa);
164 usbd_device_handle dev = uaa->device;
165 usbd_interface_handle iface = uaa->iface;
166 struct bt_attach_args bt;
167 usb_interface_descriptor_t const *id;
168 char *devinfop;
169 usb_endpoint_descriptor_t const *ed;
170 u_int8_t epcount;
171 int i;
172
173 DPRINTFN(10,("ubt_attach: sc=%p\n", sc));
174
175 devinfop = usbd_devinfo_alloc(dev, 0);
176 USB_ATTACH_SETUP;
177 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfop);
178 usbd_devinfo_free(devinfop);
179
180 sc->sc_udev = dev;
181 sc->sc_ctl_iface = iface;
182
183 /*
184 * The control interface comes before the isoc interface
185 * according to the spec, so we find it first.
186 */
187 epcount = 0;
188 (void)usbd_endpoint_count(iface, &epcount);
189
190 sc->sc_evt_addr = -1;
191 sc->sc_aclrd_addr = -1;
192 sc->sc_aclwr_addr = -1;
193
194 for (i = 0; i < epcount; i++) {
195 ed = usbd_interface2endpoint_descriptor(iface, i);
196 if (ed == NULL) {
197 printf("%s: couldn't get ep %d\n",
198 USBDEVNAME(sc->sc_dev), i);
199 USB_ATTACH_ERROR_RETURN;
200 }
201
202 DPRINTFN(10, ("%s: addr=%d attr=%d\n", __func__,
203 (int)ed->bEndpointAddress,
204 (int)ed->bmAttributes));
205
206 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
207 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
208 sc->sc_evt_addr = ed->bEndpointAddress;
209 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
210 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
211 sc->sc_aclrd_addr = ed->bEndpointAddress;
212 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
213 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
214 sc->sc_aclwr_addr = ed->bEndpointAddress;
215 }
216 }
217
218 if (sc->sc_evt_addr == -1 ||
219 sc->sc_aclrd_addr == -1 || sc->sc_aclwr_addr == -1) {
220 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
221 USB_ATTACH_ERROR_RETURN;
222 }
223
224 /* XXX works because isoc comes after ctl */
225 /* Grab isoc interface as well. */
226 for (i = 0; i < uaa->nifaces; i++) {
227 if (uaa->ifaces[i] == NULL)
228 continue;
229 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
230 if (id != NULL &&
231 id->bInterfaceClass == UICLASS_WIRELESS &&
232 id->bInterfaceSubClass == UISUBCLASS_RF &&
233 id->bInterfaceProtocol == UIPROTO_BLUETOOTH) {
234 sc->sc_isoc_iface = uaa->ifaces[i];
235 uaa->ifaces[i] = NULL;
236 }
237 }
238
239 printf("%s: has%s isoc data\n", USBDEVNAME(sc->sc_dev),
240 sc->sc_isoc_iface != NULL ? "" : " no");
241
242 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
243 USBDEV(sc->sc_dev));
244
245 bt.bt_methods = &ubt_methods;
246 bt.bt_cb = &sc->sc_cb;
247 bt.bt_handle = sc;
248
249 sc->sc_child = config_found(self, &bt, bt_print);
250
251 USB_ATTACH_SUCCESS_RETURN;
252 }
253
254 static void
255 ubt_abortdealloc(struct ubt_softc *sc)
256 {
257 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
258
259 if (sc->sc_evt_pipe != NULL) {
260 usbd_abort_pipe(sc->sc_evt_pipe);
261 usbd_close_pipe(sc->sc_evt_pipe);
262 sc->sc_evt_pipe = NULL;
263 }
264 if (sc->sc_evt_buf != NULL) {
265 free(sc->sc_evt_buf, M_USBDEV);
266 sc->sc_evt_buf = NULL;
267 }
268 if (sc->sc_aclrd_pipe != NULL) {
269 usbd_abort_pipe(sc->sc_aclrd_pipe);
270 usbd_close_pipe(sc->sc_aclrd_pipe);
271 sc->sc_aclrd_pipe = NULL;
272 }
273 if (sc->sc_aclwr_pipe != NULL) {
274 usbd_abort_pipe(sc->sc_aclwr_pipe);
275 usbd_close_pipe(sc->sc_aclwr_pipe);
276 sc->sc_aclwr_pipe = NULL;
277 }
278 if (sc->sc_aclrd_xfer != NULL) {
279 usbd_free_xfer(sc->sc_aclrd_xfer);
280 sc->sc_aclrd_xfer = NULL;
281 sc->sc_aclrd_buf = NULL;
282 }
283 if (sc->sc_aclwr_xfer != NULL) {
284 usbd_free_xfer(sc->sc_aclwr_xfer);
285 sc->sc_aclwr_xfer = NULL;
286 sc->sc_aclwr_buf = NULL;
287 }
288 }
289
290 USB_DETACH(ubt)
291 {
292 USB_DETACH_START(ubt, sc);
293 int s;
294 int rv = 0;
295
296 DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags));
297
298 sc->sc_dying = 1;
299
300 /* Abort all pipes. Causes processes waiting for transfer to wake. */
301 ubt_abortdealloc(sc);
302
303 DPRINTFN(1, ("%s: waiting for USB detach\n", __func__));
304 s = splusb();
305 if (--sc->sc_refcnt >= 0) {
306 /* Wait for processes to go away. */
307 usb_detach_wait(USBDEV(sc->sc_dev));
308 }
309 splx(s);
310 DPRINTFN(1, ("%s: USB detach complete\n", __func__));
311
312 if (sc->sc_child != NULL) {
313 DPRINTFN(1, ("%s: waiting for child detach\n", __func__));
314 rv = config_detach(sc->sc_child, flags);
315 sc->sc_child = NULL;
316 DPRINTFN(1, ("%s: child detach complete\n", __func__));
317 }
318
319 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
320 USBDEV(sc->sc_dev));
321
322 DPRINTFN(1, ("%s: driver detached\n", __func__));
323
324 return (rv);
325 }
326
327 int
328 ubt_activate(device_ptr_t self, enum devact act)
329 {
330 struct ubt_softc *sc = (struct ubt_softc *)self;
331 int error = 0;
332
333 switch (act) {
334 case DVACT_ACTIVATE:
335 return (EOPNOTSUPP);
336 break;
337
338 case DVACT_DEACTIVATE:
339 sc->sc_dying = 1;
340 if (sc->sc_child != NULL)
341 error = config_deactivate(sc->sc_child);
342 break;
343 }
344 return (error);
345 }
346
347 static int
348 ubt_open(void *h, int flag, int mode, usb_proc_ptr p)
349 {
350 struct ubt_softc *sc = h;
351 int error;
352 usbd_status err;
353
354 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
355
356 sc->sc_evt_buf = malloc(BTHCI_EVENT_MAX_LEN, M_USBDEV, M_NOWAIT);
357 if (sc->sc_evt_buf == NULL) {
358 error = ENOMEM;
359 goto bad0;
360 }
361
362 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_evt_addr,
363 USBD_SHORT_XFER_OK, &sc->sc_evt_pipe,
364 sc, sc->sc_evt_buf, BTHCI_EVENT_MAX_LEN,
365 ubt_event_cb, UBT_EVENT_EP_INTERVAL);
366 if (err != USBD_NORMAL_COMPLETION) {
367 error = EIO;
368 goto bad1;
369 }
370
371 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclrd_addr,
372 0, &sc->sc_aclrd_pipe);
373 if (err != USBD_NORMAL_COMPLETION) {
374 error = EIO;
375 goto bad2;
376 }
377
378 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclwr_addr,
379 0, &sc->sc_aclwr_pipe);
380 if (err != USBD_NORMAL_COMPLETION) {
381 error = EIO;
382 goto bad3;
383 }
384
385 sc->sc_ctl_xfer = usbd_alloc_xfer(sc->sc_udev);
386 if (sc->sc_ctl_xfer == NULL) {
387 error = ENOMEM;
388 goto bad4;
389 }
390 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
391 if (sc->sc_aclrd_xfer == NULL) {
392 error = ENOMEM;
393 goto bad5;
394 }
395 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
396 if (sc->sc_aclwr_xfer == NULL) {
397 error = ENOMEM;
398 goto bad6;
399 }
400
401 /* Buffers */
402 sc->sc_ctl_buf = usbd_alloc_buffer(sc->sc_ctl_xfer,
403 BTHCI_COMMAND_MAX_LEN);
404 if (sc->sc_ctl_buf == NULL) {
405 error = ENOMEM;
406 goto bad7;
407 }
408 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer,
409 BTHCI_ACL_DATA_MAX_LEN);
410 if (sc->sc_aclrd_buf == NULL) {
411 error = ENOMEM;
412 goto bad7;
413 }
414 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer,
415 BTHCI_ACL_DATA_MAX_LEN);
416 if (sc->sc_aclwr_buf == NULL) {
417 error = ENOMEM;
418 goto bad7;
419 }
420
421 /* Start reading */
422 ubt_aclrd_request(sc);
423
424 return 0;
425
426 bad7:
427 usbd_free_xfer(sc->sc_aclwr_xfer);
428 sc->sc_aclwr_xfer = NULL;
429 bad6:
430 usbd_free_xfer(sc->sc_aclrd_xfer);
431 sc->sc_aclrd_xfer = NULL;
432 bad5:
433 usbd_free_xfer(sc->sc_ctl_xfer);
434 sc->sc_ctl_xfer = NULL;
435 bad4:
436 usbd_close_pipe(sc->sc_aclwr_pipe);
437 sc->sc_aclwr_pipe = NULL;
438 bad3:
439 usbd_close_pipe(sc->sc_aclrd_pipe);
440 sc->sc_aclrd_pipe = NULL;
441 bad2:
442 usbd_close_pipe(sc->sc_evt_pipe);
443 sc->sc_evt_pipe = NULL;
444 bad1:
445 free(sc->sc_evt_buf, M_USBDEV);
446 sc->sc_evt_buf = NULL;
447 bad0:
448 return error;
449 }
450
451 static int
452 ubt_close(void *h, int flag, int mode, usb_proc_ptr p)
453 {
454 struct ubt_softc *sc = h;
455
456 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
457
458 ubt_abortdealloc(sc);
459
460 return 0;
461 }
462
463 static u_int8_t*
464 ubt_alloc_control(void *h, size_t len, struct btframe_buffer **buf)
465 {
466 struct ubt_softc *sc = h;
467
468 /*
469 * We should be catching this earlier, but at the moment a
470 * user request can generate oversized allocations.
471 */
472 if (len > BTHCI_COMMAND_MAX_LEN)
473 return NULL;
474
475 *buf = (struct btframe_buffer*)sc->sc_ctl_buf;
476 return sc->sc_ctl_buf;
477 }
478
479 static int
480 ubt_send_control(void *h, struct btframe_buffer *buf, size_t len)
481 {
482 struct ubt_softc *sc = h;
483 usb_device_request_t req;
484 usbd_status status;
485
486 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
487
488 #ifdef DIAGNOSTIC
489 if ((u_int8_t*)buf != sc->sc_ctl_buf)
490 panic("ubt_control() called with wrong buffer");
491 #endif
492
493 if (sc->sc_dying)
494 return EIO;
495
496 if (len < BTHCI_COMMAND_MIN_LEN || len > BTHCI_COMMAND_MAX_LEN)
497 return EINVAL;
498
499 sc->sc_refcnt++;
500
501 memset(&req, 0, sizeof(req));
502 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
503 USETW(req.wLength, len);
504
505 usbd_setup_default_xfer(sc->sc_ctl_xfer,
506 sc->sc_udev,
507 sc,
508 USBD_DEFAULT_TIMEOUT,
509 &req, sc->sc_ctl_buf, len,
510 USBD_SYNCHRONOUS | USBD_NO_COPY, NULL);
511
512 status = usbd_transfer(sc->sc_ctl_xfer);
513
514 if (--sc->sc_refcnt < 0)
515 usb_detach_wakeup(USBDEV(sc->sc_dev));
516
517 if (status != USBD_NORMAL_COMPLETION)
518 return EIO;
519
520 return 0;
521 }
522
523 static u_int8_t*
524 ubt_alloc_acldata(void *h, size_t len, struct btframe_buffer **buf)
525 {
526 struct ubt_softc *sc = h;
527
528 /*
529 * We should be catching this earlier, but at the moment a
530 * user request can generate oversized allocations.
531 */
532 if (len > BTHCI_ACL_DATA_MAX_LEN)
533 return NULL;
534
535 *buf = (struct btframe_buffer*)sc->sc_aclwr_buf;
536 return sc->sc_aclwr_buf;
537 }
538
539 static int
540 ubt_send_acldata(void *h, struct btframe_buffer *buf, size_t len)
541 {
542 struct ubt_softc *sc = h;
543 usbd_status status;
544
545 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
546
547 #ifdef DIAGNOSTIC
548 if ((u_int8_t*)buf != sc->sc_aclwr_buf)
549 panic("ubt_sendacldata() called with wrong buffer");
550 #endif
551
552 if (sc->sc_dying)
553 return EIO;
554
555 if (len < BTHCI_ACL_DATA_MIN_LEN || len > BTHCI_ACL_DATA_MAX_LEN)
556 return EINVAL;
557
558 sc->sc_refcnt++;
559
560 usbd_setup_xfer(sc->sc_aclwr_xfer,
561 sc->sc_aclwr_pipe,
562 (usbd_private_handle)sc,
563 sc->sc_aclwr_buf, len,
564 USBD_SYNCHRONOUS | USBD_NO_COPY,
565 USBD_DEFAULT_TIMEOUT,
566 NULL);
567
568 status = usbd_transfer(sc->sc_aclwr_xfer);
569
570 if (--sc->sc_refcnt < 0)
571 usb_detach_wakeup(USBDEV(sc->sc_dev));
572
573 if (status != USBD_NORMAL_COMPLETION)
574 return EIO;
575
576 return 0;
577 }
578
579 static u_int8_t*
580 ubt_alloc_scodata(void *h, size_t len, struct btframe_buffer **buf)
581 {
582 return NULL;
583 }
584
585 static int
586 ubt_send_scodata(void *h, struct btframe_buffer *buf, size_t len)
587 {
588 struct ubt_softc *sc = h;
589
590 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
591
592 if (sc->sc_dying)
593 return EIO;
594
595 return ENXIO;
596 }
597
598 static void
599 ubt_event_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
600 {
601 struct ubt_softc *sc = h;
602 void *buf;
603 u_int32_t size;
604
605 DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
606 usbd_errstr(status)));
607
608 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
609 sc->sc_child == NULL)
610 return;
611
612 usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
613
614 sc->sc_cb->bt_recveventdata(sc->sc_child, buf, (size_t)size);
615 }
616
617 static void
618 ubt_aclrd_request(struct ubt_softc *sc)
619 {
620 usbd_status status;
621 int s;
622
623 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
624
625 if (sc->sc_dying)
626 return;
627
628 s = splusb();
629 if (sc->sc_aclrd_running) {
630 splx(s);
631 return;
632 }
633 sc->sc_aclrd_running = 1;
634 splx(s);
635
636 usbd_setup_xfer(sc->sc_aclrd_xfer, sc->sc_aclrd_pipe,
637 sc, sc->sc_aclrd_buf, BTHCI_ACL_DATA_MAX_LEN,
638 USBD_SHORT_XFER_OK | USBD_NO_COPY,
639 USBD_NO_TIMEOUT, ubt_aclrd_cb);
640
641 status = usbd_transfer(sc->sc_aclrd_xfer);
642
643 /* Cancellation is normal on device shutdown */
644 if (status == USBD_IN_PROGRESS || status == USBD_CANCELLED)
645 return;
646
647 DPRINTFN(1,("%s: read request failed: %s\n", __func__,
648 usbd_errstr(status)));
649
650 sc->sc_aclrd_running = 0;
651 /* XXX now what!? */
652 }
653
654 static void
655 ubt_aclrd_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
656 {
657 struct ubt_softc *sc = h;
658 void *buf;
659 u_int32_t size;
660
661 DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
662 usbd_errstr(status)));
663
664 sc->sc_aclrd_running = 0;
665
666 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
667 sc->sc_child == NULL)
668 return;
669
670 usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
671
672 sc->sc_cb->bt_recvacldata(sc->sc_child, buf, (size_t)size);
673
674 /* Re-issue the request */
675 if (!sc->sc_dying)
676 ubt_aclrd_request(sc);
677 }
678
679 static int
680 ubt_splraise(void)
681 {
682 return splusb();
683 }
684