FreeBSD/Linux Kernel Cross Reference
sys/dev/usb/ubt.c
1 /* $NetBSD: ubt.c,v 1.10 2004/01/04 05:47:43 dsainty 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@augustsson.net) and
9 * David Sainty (David.Sainty@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.10 2004/01/04 05:47:43 dsainty 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 devinfo[1024];
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 usbd_devinfo(dev, 0, devinfo);
176 USB_ATTACH_SETUP;
177 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
178
179 sc->sc_udev = dev;
180 sc->sc_ctl_iface = iface;
181
182 /*
183 * The control interface comes before the isoc interface
184 * according to the spec, so we find it first.
185 */
186 epcount = 0;
187 (void)usbd_endpoint_count(iface, &epcount);
188
189 sc->sc_evt_addr = -1;
190 sc->sc_aclrd_addr = -1;
191 sc->sc_aclwr_addr = -1;
192
193 for (i = 0; i < epcount; i++) {
194 ed = usbd_interface2endpoint_descriptor(iface, i);
195 if (ed == NULL) {
196 printf("%s: couldn't get ep %d\n",
197 USBDEVNAME(sc->sc_dev), i);
198 USB_ATTACH_ERROR_RETURN;
199 }
200
201 DPRINTFN(10, ("%s: addr=%d attr=%d\n", __func__,
202 (int)ed->bEndpointAddress,
203 (int)ed->bmAttributes));
204
205 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
206 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
207 sc->sc_evt_addr = ed->bEndpointAddress;
208 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
209 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
210 sc->sc_aclrd_addr = ed->bEndpointAddress;
211 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
212 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
213 sc->sc_aclwr_addr = ed->bEndpointAddress;
214 }
215 }
216
217 if (sc->sc_evt_addr == -1 ||
218 sc->sc_aclrd_addr == -1 || sc->sc_aclwr_addr == -1) {
219 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
220 USB_ATTACH_ERROR_RETURN;
221 }
222
223 /* XXX works because isoc comes after ctl */
224 /* Grab isoc interface as well. */
225 for (i = 0; i < uaa->nifaces; i++) {
226 if (uaa->ifaces[i] == NULL)
227 continue;
228 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
229 if (id != NULL &&
230 id->bInterfaceClass == UICLASS_WIRELESS &&
231 id->bInterfaceSubClass == UISUBCLASS_RF &&
232 id->bInterfaceProtocol == UIPROTO_BLUETOOTH) {
233 sc->sc_isoc_iface = uaa->ifaces[i];
234 uaa->ifaces[i] = NULL;
235 }
236 }
237
238 printf("%s: has%s isoc data\n", USBDEVNAME(sc->sc_dev),
239 sc->sc_isoc_iface != NULL ? "" : " no");
240
241 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
242 USBDEV(sc->sc_dev));
243
244 bt.bt_methods = &ubt_methods;
245 bt.bt_cb = &sc->sc_cb;
246 bt.bt_handle = sc;
247
248 sc->sc_child = config_found(self, &bt, bt_print);
249
250 USB_ATTACH_SUCCESS_RETURN;
251 }
252
253 static void
254 ubt_abortdealloc(struct ubt_softc *sc)
255 {
256 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
257
258 if (sc->sc_evt_pipe != NULL) {
259 usbd_abort_pipe(sc->sc_evt_pipe);
260 usbd_close_pipe(sc->sc_evt_pipe);
261 sc->sc_evt_pipe = NULL;
262 }
263 if (sc->sc_evt_buf != NULL) {
264 free(sc->sc_evt_buf, M_USBDEV);
265 sc->sc_evt_buf = NULL;
266 }
267 if (sc->sc_aclrd_pipe != NULL) {
268 usbd_abort_pipe(sc->sc_aclrd_pipe);
269 usbd_close_pipe(sc->sc_aclrd_pipe);
270 sc->sc_aclrd_pipe = NULL;
271 }
272 if (sc->sc_aclwr_pipe != NULL) {
273 usbd_abort_pipe(sc->sc_aclwr_pipe);
274 usbd_close_pipe(sc->sc_aclwr_pipe);
275 sc->sc_aclwr_pipe = NULL;
276 }
277 if (sc->sc_aclrd_xfer != NULL) {
278 usbd_free_xfer(sc->sc_aclrd_xfer);
279 sc->sc_aclrd_xfer = NULL;
280 sc->sc_aclrd_buf = NULL;
281 }
282 if (sc->sc_aclwr_xfer != NULL) {
283 usbd_free_xfer(sc->sc_aclwr_xfer);
284 sc->sc_aclwr_xfer = NULL;
285 sc->sc_aclwr_buf = NULL;
286 }
287 }
288
289 USB_DETACH(ubt)
290 {
291 USB_DETACH_START(ubt, sc);
292 int s;
293 int rv = 0;
294
295 DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags));
296
297 sc->sc_dying = 1;
298
299 /* Abort all pipes. Causes processes waiting for transfer to wake. */
300 ubt_abortdealloc(sc);
301
302 DPRINTFN(1, ("%s: waiting for USB detach\n", __func__));
303 s = splusb();
304 if (--sc->sc_refcnt >= 0) {
305 /* Wait for processes to go away. */
306 usb_detach_wait(USBDEV(sc->sc_dev));
307 }
308 splx(s);
309 DPRINTFN(1, ("%s: USB detach complete\n", __func__));
310
311 if (sc->sc_child != NULL) {
312 DPRINTFN(1, ("%s: waiting for child detach\n", __func__));
313 rv = config_detach(sc->sc_child, flags);
314 sc->sc_child = NULL;
315 DPRINTFN(1, ("%s: child detach complete\n", __func__));
316 }
317
318 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
319 USBDEV(sc->sc_dev));
320
321 DPRINTFN(1, ("%s: driver detached\n", __func__));
322
323 return (rv);
324 }
325
326 int
327 ubt_activate(device_ptr_t self, enum devact act)
328 {
329 struct ubt_softc *sc = (struct ubt_softc *)self;
330 int error = 0;
331
332 switch (act) {
333 case DVACT_ACTIVATE:
334 return (EOPNOTSUPP);
335 break;
336
337 case DVACT_DEACTIVATE:
338 sc->sc_dying = 1;
339 if (sc->sc_child != NULL)
340 error = config_deactivate(sc->sc_child);
341 break;
342 }
343 return (error);
344 }
345
346 static int
347 ubt_open(void *h, int flag, int mode, usb_proc_ptr p)
348 {
349 struct ubt_softc *sc = h;
350 int error;
351 usbd_status err;
352
353 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
354
355 sc->sc_evt_buf = malloc(BTHCI_EVENT_MAX_LEN, M_USBDEV, M_NOWAIT);
356 if (sc->sc_evt_buf == NULL) {
357 error = ENOMEM;
358 goto bad0;
359 }
360
361 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_evt_addr,
362 USBD_SHORT_XFER_OK, &sc->sc_evt_pipe,
363 sc, sc->sc_evt_buf, BTHCI_EVENT_MAX_LEN,
364 ubt_event_cb, UBT_EVENT_EP_INTERVAL);
365 if (err != USBD_NORMAL_COMPLETION) {
366 error = EIO;
367 goto bad1;
368 }
369
370 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclrd_addr,
371 0, &sc->sc_aclrd_pipe);
372 if (err != USBD_NORMAL_COMPLETION) {
373 error = EIO;
374 goto bad2;
375 }
376
377 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclwr_addr,
378 0, &sc->sc_aclwr_pipe);
379 if (err != USBD_NORMAL_COMPLETION) {
380 error = EIO;
381 goto bad3;
382 }
383
384 sc->sc_ctl_xfer = usbd_alloc_xfer(sc->sc_udev);
385 if (sc->sc_ctl_xfer == NULL) {
386 error = ENOMEM;
387 goto bad4;
388 }
389 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
390 if (sc->sc_aclrd_xfer == NULL) {
391 error = ENOMEM;
392 goto bad5;
393 }
394 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
395 if (sc->sc_aclwr_xfer == NULL) {
396 error = ENOMEM;
397 goto bad6;
398 }
399
400 /* Buffers */
401 sc->sc_ctl_buf = usbd_alloc_buffer(sc->sc_ctl_xfer,
402 BTHCI_COMMAND_MAX_LEN);
403 if (sc->sc_ctl_buf == NULL) {
404 error = ENOMEM;
405 goto bad7;
406 }
407 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer,
408 BTHCI_ACL_DATA_MAX_LEN);
409 if (sc->sc_aclrd_buf == NULL) {
410 error = ENOMEM;
411 goto bad7;
412 }
413 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer,
414 BTHCI_ACL_DATA_MAX_LEN);
415 if (sc->sc_aclwr_buf == NULL) {
416 error = ENOMEM;
417 goto bad7;
418 }
419
420 /* Start reading */
421 ubt_aclrd_request(sc);
422
423 return 0;
424
425 bad7:
426 usbd_free_xfer(sc->sc_aclwr_xfer);
427 sc->sc_aclwr_xfer = NULL;
428 bad6:
429 usbd_free_xfer(sc->sc_aclrd_xfer);
430 sc->sc_aclrd_xfer = NULL;
431 bad5:
432 usbd_free_xfer(sc->sc_ctl_xfer);
433 sc->sc_ctl_xfer = NULL;
434 bad4:
435 usbd_close_pipe(sc->sc_aclwr_pipe);
436 sc->sc_aclwr_pipe = NULL;
437 bad3:
438 usbd_close_pipe(sc->sc_aclrd_pipe);
439 sc->sc_aclrd_pipe = NULL;
440 bad2:
441 usbd_close_pipe(sc->sc_evt_pipe);
442 sc->sc_evt_pipe = NULL;
443 bad1:
444 free(sc->sc_evt_buf, M_USBDEV);
445 sc->sc_evt_buf = NULL;
446 bad0:
447 return error;
448 }
449
450 static int
451 ubt_close(void *h, int flag, int mode, usb_proc_ptr p)
452 {
453 struct ubt_softc *sc = h;
454
455 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
456
457 ubt_abortdealloc(sc);
458
459 return 0;
460 }
461
462 static u_int8_t*
463 ubt_alloc_control(void *h, size_t len, struct btframe_buffer **buf)
464 {
465 struct ubt_softc *sc = h;
466
467 /*
468 * We should be catching this earlier, but at the moment a
469 * user request can generate oversized allocations.
470 */
471 if (len > BTHCI_COMMAND_MAX_LEN)
472 return NULL;
473
474 *buf = (struct btframe_buffer*)sc->sc_ctl_buf;
475 return sc->sc_ctl_buf;
476 }
477
478 static int
479 ubt_send_control(void *h, struct btframe_buffer *buf, size_t len)
480 {
481 struct ubt_softc *sc = h;
482 usb_device_request_t req;
483 usbd_status status;
484
485 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
486
487 #ifdef DIAGNOSTIC
488 if ((u_int8_t*)buf != sc->sc_ctl_buf)
489 panic("ubt_control() called with wrong buffer");
490 #endif
491
492 if (sc->sc_dying)
493 return EIO;
494
495 if (len < BTHCI_COMMAND_MIN_LEN || len > BTHCI_COMMAND_MAX_LEN)
496 return EINVAL;
497
498 sc->sc_refcnt++;
499
500 memset(&req, 0, sizeof(req));
501 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
502 USETW(req.wLength, len);
503
504 usbd_setup_default_xfer(sc->sc_ctl_xfer,
505 sc->sc_udev,
506 sc,
507 USBD_DEFAULT_TIMEOUT,
508 &req, sc->sc_ctl_buf, len,
509 USBD_SYNCHRONOUS | USBD_NO_COPY, NULL);
510
511 status = usbd_transfer(sc->sc_ctl_xfer);
512
513 if (--sc->sc_refcnt < 0)
514 usb_detach_wakeup(USBDEV(sc->sc_dev));
515
516 if (status != USBD_NORMAL_COMPLETION)
517 return EIO;
518
519 return 0;
520 }
521
522 static u_int8_t*
523 ubt_alloc_acldata(void *h, size_t len, struct btframe_buffer **buf)
524 {
525 struct ubt_softc *sc = h;
526
527 /*
528 * We should be catching this earlier, but at the moment a
529 * user request can generate oversized allocations.
530 */
531 if (len > BTHCI_ACL_DATA_MAX_LEN)
532 return NULL;
533
534 *buf = (struct btframe_buffer*)sc->sc_aclwr_buf;
535 return sc->sc_aclwr_buf;
536 }
537
538 static int
539 ubt_send_acldata(void *h, struct btframe_buffer *buf, size_t len)
540 {
541 struct ubt_softc *sc = h;
542 usbd_status status;
543
544 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
545
546 #ifdef DIAGNOSTIC
547 if ((u_int8_t*)buf != sc->sc_aclwr_buf)
548 panic("ubt_sendacldata() called with wrong buffer");
549 #endif
550
551 if (sc->sc_dying)
552 return EIO;
553
554 if (len < BTHCI_ACL_DATA_MIN_LEN || len > BTHCI_ACL_DATA_MAX_LEN)
555 return EINVAL;
556
557 sc->sc_refcnt++;
558
559 usbd_setup_xfer(sc->sc_aclwr_xfer,
560 sc->sc_aclwr_pipe,
561 (usbd_private_handle)sc,
562 sc->sc_aclwr_buf, len,
563 USBD_SYNCHRONOUS | USBD_NO_COPY,
564 USBD_DEFAULT_TIMEOUT,
565 NULL);
566
567 status = usbd_transfer(sc->sc_aclwr_xfer);
568
569 if (--sc->sc_refcnt < 0)
570 usb_detach_wakeup(USBDEV(sc->sc_dev));
571
572 if (status != USBD_NORMAL_COMPLETION)
573 return EIO;
574
575 return 0;
576 }
577
578 static u_int8_t*
579 ubt_alloc_scodata(void *h, size_t len, struct btframe_buffer **buf)
580 {
581 return NULL;
582 }
583
584 static int
585 ubt_send_scodata(void *h, struct btframe_buffer *buf, size_t len)
586 {
587 struct ubt_softc *sc = h;
588
589 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
590
591 if (sc->sc_dying)
592 return EIO;
593
594 return ENXIO;
595 }
596
597 static void
598 ubt_event_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
599 {
600 struct ubt_softc *sc = h;
601 void *buf;
602 u_int32_t size;
603
604 DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
605 usbd_errstr(status)));
606
607 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
608 sc->sc_child == NULL)
609 return;
610
611 usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
612
613 sc->sc_cb->bt_recveventdata(sc->sc_child, buf, (size_t)size);
614 }
615
616 static void
617 ubt_aclrd_request(struct ubt_softc *sc)
618 {
619 usbd_status status;
620 int s;
621
622 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
623
624 if (sc->sc_dying)
625 return;
626
627 s = splusb();
628 if (sc->sc_aclrd_running) {
629 splx(s);
630 return;
631 }
632 sc->sc_aclrd_running = 1;
633 splx(s);
634
635 usbd_setup_xfer(sc->sc_aclrd_xfer, sc->sc_aclrd_pipe,
636 sc, sc->sc_aclrd_buf, BTHCI_ACL_DATA_MAX_LEN,
637 USBD_SHORT_XFER_OK | USBD_NO_COPY,
638 USBD_NO_TIMEOUT, ubt_aclrd_cb);
639
640 status = usbd_transfer(sc->sc_aclrd_xfer);
641
642 /* Cancellation is normal on device shutdown */
643 if (status == USBD_IN_PROGRESS || status == USBD_CANCELLED)
644 return;
645
646 DPRINTFN(1,("%s: read request failed: %s\n", __func__,
647 usbd_errstr(status)));
648
649 sc->sc_aclrd_running = 0;
650 /* XXX now what!? */
651 }
652
653 static void
654 ubt_aclrd_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
655 {
656 struct ubt_softc *sc = h;
657 void *buf;
658 u_int32_t size;
659
660 DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
661 usbd_errstr(status)));
662
663 sc->sc_aclrd_running = 0;
664
665 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
666 sc->sc_child == NULL)
667 return;
668
669 usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
670
671 sc->sc_cb->bt_recvacldata(sc->sc_child, buf, (size_t)size);
672
673 /* Re-issue the request */
674 if (!sc->sc_dying)
675 ubt_aclrd_request(sc);
676 }
677
678 static int
679 ubt_splraise(void)
680 {
681 return splusb();
682 }
Cache object: f7d7da8d107e88003fe7f030302e924a
|