ubt.c revision 1.7 1 /* $NetBSD: ubt.c,v 1.7 2003/01/20 21:14:57 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.7 2003/01/20 21:14:57 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 unsigned int sc_blocked;
111
112 int sc_refcnt;
113 char sc_dying;
114 };
115
116 static int ubt_open(void *h, int flag, int mode, usb_proc_ptr p);
117 static int ubt_close(void *h, int flag, int mode, usb_proc_ptr p);
118
119 static u_int8_t* ubt_alloc_control(void*, size_t, struct btframe_buffer**);
120 static int ubt_send_control(void*, struct btframe_buffer*, size_t);
121
122 static u_int8_t* ubt_alloc_acldata(void*, size_t, struct btframe_buffer**);
123 static int ubt_send_acldata(void*, struct btframe_buffer*, size_t);
124
125 static u_int8_t* ubt_alloc_scodata(void*, size_t, struct btframe_buffer**);
126 static int ubt_send_scodata(void*, struct btframe_buffer*, size_t);
127
128 static int ubt_splraise(void);
129 static unsigned int ubt_blockcb(void *h, unsigned int cbblocks);
130 static unsigned int ubt_unblockcb(void *h, unsigned int cbblocks);
131
132 static void ubt_event_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
133 static void ubt_aclrd_cb(usbd_xfer_handle, usbd_private_handle, usbd_status);
134 static void ubt_aclrd_request(struct ubt_softc *);
135
136 static struct btframe_methods const ubt_methods = {
137 ubt_open, ubt_close,
138 {ubt_alloc_control, ubt_send_control},
139 {ubt_alloc_acldata, ubt_send_acldata},
140 {ubt_alloc_scodata, ubt_send_scodata},
141 ubt_splraise, ubt_blockcb, ubt_unblockcb
142 };
143
144 USB_DECLARE_DRIVER(ubt);
145
146 USB_MATCH(ubt)
147 {
148 USB_MATCH_START(ubt, uaa);
149 usb_interface_descriptor_t *id;
150
151 DPRINTFN(50,("ubt_match\n"));
152
153 if (uaa->iface == NULL)
154 return (UMATCH_NONE);
155
156 id = usbd_get_interface_descriptor(uaa->iface);
157 if (id != NULL &&
158 id->bInterfaceClass == UICLASS_WIRELESS &&
159 id->bInterfaceSubClass == UISUBCLASS_RF &&
160 id->bInterfaceProtocol == UIPROTO_BLUETOOTH)
161 return (UMATCH_IFACECLASS_IFACESUBCLASS_IFACEPROTO);
162 return (UMATCH_NONE);
163 }
164
165 USB_ATTACH(ubt)
166 {
167 USB_ATTACH_START(ubt, sc, uaa);
168 usbd_device_handle dev = uaa->device;
169 usbd_interface_handle iface = uaa->iface;
170 struct bt_attach_args bt;
171 usb_interface_descriptor_t const *id;
172 char devinfo[1024];
173 usb_endpoint_descriptor_t const *ed;
174 u_int8_t epcount;
175 int i;
176
177 DPRINTFN(10,("ubt_attach: sc=%p\n", sc));
178
179 usbd_devinfo(dev, 0, devinfo);
180 USB_ATTACH_SETUP;
181 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
182
183 sc->sc_udev = dev;
184 sc->sc_ctl_iface = iface;
185
186 /*
187 * The control interface comes before the isoc interface
188 * according to the spec, so we find it first.
189 */
190 epcount = 0;
191 (void)usbd_endpoint_count(iface, &epcount);
192
193 sc->sc_evt_addr = -1;
194 sc->sc_aclrd_addr = -1;
195 sc->sc_aclwr_addr = -1;
196
197 for (i = 0; i < epcount; i++) {
198 ed = usbd_interface2endpoint_descriptor(iface, i);
199 if (ed == NULL) {
200 printf("%s: couldn't get ep %d\n",
201 USBDEVNAME(sc->sc_dev), i);
202 USB_ATTACH_ERROR_RETURN;
203 }
204
205 DPRINTFN(10, ("%s: addr=%d attr=%d\n", __func__,
206 (int)ed->bEndpointAddress,
207 (int)ed->bmAttributes));
208
209 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
210 UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
211 sc->sc_evt_addr = ed->bEndpointAddress;
212 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
213 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
214 sc->sc_aclrd_addr = ed->bEndpointAddress;
215 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
216 UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
217 sc->sc_aclwr_addr = ed->bEndpointAddress;
218 }
219 }
220
221 if (sc->sc_evt_addr == -1 ||
222 sc->sc_aclrd_addr == -1 || sc->sc_aclwr_addr == -1) {
223 printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
224 USB_ATTACH_ERROR_RETURN;
225 }
226
227 /* XXX works because isoc comes after ctl */
228 /* Grab isoc interface as well. */
229 for (i = 0; i < uaa->nifaces; i++) {
230 if (uaa->ifaces[i] == NULL)
231 continue;
232 id = usbd_get_interface_descriptor(uaa->ifaces[i]);
233 if (id != NULL &&
234 id->bInterfaceClass == UICLASS_WIRELESS &&
235 id->bInterfaceSubClass == UISUBCLASS_RF &&
236 id->bInterfaceProtocol == UIPROTO_BLUETOOTH) {
237 sc->sc_isoc_iface = uaa->ifaces[i];
238 uaa->ifaces[i] = NULL;
239 }
240 }
241
242 printf("%s: has%s isoc data\n", USBDEVNAME(sc->sc_dev),
243 sc->sc_isoc_iface != NULL ? "" : " no");
244
245 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
246 USBDEV(sc->sc_dev));
247
248 bt.bt_methods = &ubt_methods;
249 bt.bt_cb = &sc->sc_cb;
250
251 sc->sc_child = config_found(self, &bt, bt_print);
252
253 USB_ATTACH_SUCCESS_RETURN;
254 }
255
256 static void
257 ubt_abortdealloc(struct ubt_softc *sc)
258 {
259 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
260
261 if (sc->sc_evt_pipe != NULL) {
262 usbd_abort_pipe(sc->sc_evt_pipe);
263 usbd_close_pipe(sc->sc_evt_pipe);
264 sc->sc_evt_pipe = NULL;
265 }
266 if (sc->sc_evt_buf != NULL) {
267 free(sc->sc_evt_buf, M_USBDEV);
268 sc->sc_evt_buf = NULL;
269 }
270 if (sc->sc_aclrd_pipe != NULL) {
271 usbd_abort_pipe(sc->sc_aclrd_pipe);
272 usbd_close_pipe(sc->sc_aclrd_pipe);
273 sc->sc_aclrd_pipe = NULL;
274 }
275 if (sc->sc_aclwr_pipe != NULL) {
276 usbd_abort_pipe(sc->sc_aclwr_pipe);
277 usbd_close_pipe(sc->sc_aclwr_pipe);
278 sc->sc_aclwr_pipe = NULL;
279 }
280 if (sc->sc_aclrd_xfer != NULL) {
281 usbd_free_xfer(sc->sc_aclrd_xfer);
282 sc->sc_aclrd_xfer = NULL;
283 sc->sc_aclrd_buf = NULL;
284 }
285 if (sc->sc_aclwr_xfer != NULL) {
286 usbd_free_xfer(sc->sc_aclwr_xfer);
287 sc->sc_aclwr_xfer = NULL;
288 sc->sc_aclwr_buf = NULL;
289 }
290 }
291
292 USB_DETACH(ubt)
293 {
294 USB_DETACH_START(ubt, sc);
295 int s;
296 int rv = 0;
297
298 DPRINTF(("%s: sc=%p flags=%d\n", __func__, sc, flags));
299
300 sc->sc_dying = 1;
301
302 /* Abort all pipes. Causes processes waiting for transfer to wake. */
303 ubt_abortdealloc(sc);
304
305 DPRINTFN(1, ("%s: waiting for USB detach\n", __func__));
306 s = splusb();
307 if (--sc->sc_refcnt >= 0) {
308 /* Wait for processes to go away. */
309 usb_detach_wait(USBDEV(sc->sc_dev));
310 }
311 splx(s);
312 DPRINTFN(1, ("%s: USB detach complete\n", __func__));
313
314 if (sc->sc_child != NULL) {
315 DPRINTFN(1, ("%s: waiting for child detach\n", __func__));
316 rv = config_detach(sc->sc_child, flags);
317 sc->sc_child = NULL;
318 DPRINTFN(1, ("%s: child detach complete\n", __func__));
319 }
320
321 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
322 USBDEV(sc->sc_dev));
323
324 DPRINTFN(1, ("%s: driver detached\n", __func__));
325
326 return (rv);
327 }
328
329 int
330 ubt_activate(device_ptr_t self, enum devact act)
331 {
332 struct ubt_softc *sc = (struct ubt_softc *)self;
333 int error = 0;
334
335 switch (act) {
336 case DVACT_ACTIVATE:
337 return (EOPNOTSUPP);
338 break;
339
340 case DVACT_DEACTIVATE:
341 sc->sc_dying = 1;
342 if (sc->sc_child != NULL)
343 error = config_deactivate(sc->sc_child);
344 break;
345 }
346 return (error);
347 }
348
349 static int
350 ubt_open(void *h, int flag, int mode, usb_proc_ptr p)
351 {
352 struct ubt_softc *sc = h;
353 int error;
354 usbd_status err;
355
356 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
357
358 sc->sc_evt_buf = malloc(BTHCI_EVENT_MAX_LEN, M_USBDEV, M_NOWAIT);
359 if (sc->sc_evt_buf == NULL) {
360 error = ENOMEM;
361 goto bad0;
362 }
363
364 err = usbd_open_pipe_intr(sc->sc_ctl_iface, sc->sc_evt_addr,
365 USBD_SHORT_XFER_OK, &sc->sc_evt_pipe,
366 sc, sc->sc_evt_buf, BTHCI_EVENT_MAX_LEN,
367 ubt_event_cb, UBT_EVENT_EP_INTERVAL);
368 if (err != USBD_NORMAL_COMPLETION) {
369 error = EIO;
370 goto bad1;
371 }
372
373 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclrd_addr,
374 0, &sc->sc_aclrd_pipe);
375 if (err != USBD_NORMAL_COMPLETION) {
376 error = EIO;
377 goto bad2;
378 }
379
380 err = usbd_open_pipe(sc->sc_ctl_iface, sc->sc_aclwr_addr,
381 0, &sc->sc_aclwr_pipe);
382 if (err != USBD_NORMAL_COMPLETION) {
383 error = EIO;
384 goto bad3;
385 }
386
387 sc->sc_ctl_xfer = usbd_alloc_xfer(sc->sc_udev);
388 if (sc->sc_ctl_xfer == NULL) {
389 error = ENOMEM;
390 goto bad4;
391 }
392 sc->sc_aclrd_xfer = usbd_alloc_xfer(sc->sc_udev);
393 if (sc->sc_aclrd_xfer == NULL) {
394 error = ENOMEM;
395 goto bad5;
396 }
397 sc->sc_aclwr_xfer = usbd_alloc_xfer(sc->sc_udev);
398 if (sc->sc_aclwr_xfer == NULL) {
399 error = ENOMEM;
400 goto bad6;
401 }
402
403 /* Buffers */
404 sc->sc_ctl_buf = usbd_alloc_buffer(sc->sc_ctl_xfer,
405 BTHCI_COMMAND_MAX_LEN);
406 if (sc->sc_ctl_buf == NULL) {
407 error = ENOMEM;
408 goto bad7;
409 }
410 sc->sc_aclrd_buf = usbd_alloc_buffer(sc->sc_aclrd_xfer,
411 BTHCI_ACL_DATA_MAX_LEN);
412 if (sc->sc_aclrd_buf == NULL) {
413 error = ENOMEM;
414 goto bad7;
415 }
416 sc->sc_aclwr_buf = usbd_alloc_buffer(sc->sc_aclwr_xfer,
417 BTHCI_ACL_DATA_MAX_LEN);
418 if (sc->sc_aclwr_buf == NULL) {
419 error = ENOMEM;
420 goto bad7;
421 }
422
423 /* Start reading */
424 ubt_aclrd_request(sc);
425
426 return 0;
427
428 bad7:
429 usbd_free_xfer(sc->sc_aclwr_xfer);
430 sc->sc_aclwr_xfer = NULL;
431 bad6:
432 usbd_free_xfer(sc->sc_aclrd_xfer);
433 sc->sc_aclrd_xfer = NULL;
434 bad5:
435 usbd_free_xfer(sc->sc_ctl_xfer);
436 sc->sc_ctl_xfer = NULL;
437 bad4:
438 usbd_close_pipe(sc->sc_aclwr_pipe);
439 sc->sc_aclwr_pipe = NULL;
440 bad3:
441 usbd_close_pipe(sc->sc_aclrd_pipe);
442 sc->sc_aclrd_pipe = NULL;
443 bad2:
444 usbd_close_pipe(sc->sc_evt_pipe);
445 sc->sc_evt_pipe = NULL;
446 bad1:
447 free(sc->sc_evt_buf, M_USBDEV);
448 sc->sc_evt_buf = NULL;
449 bad0:
450 return error;
451 }
452
453 static int
454 ubt_close(void *h, int flag, int mode, usb_proc_ptr p)
455 {
456 struct ubt_softc *sc = h;
457
458 DPRINTFN(0, ("%s: sc=%p\n", __func__, sc));
459
460 ubt_abortdealloc(sc);
461
462 return 0;
463 }
464
465 static u_int8_t*
466 ubt_alloc_control(void *h, size_t len, struct btframe_buffer **buf)
467 {
468 struct ubt_softc *sc = h;
469
470 /*
471 * We should be catching this earlier, but at the moment a
472 * user request can generate oversized allocations.
473 */
474 if (len > BTHCI_COMMAND_MAX_LEN)
475 return NULL;
476
477 *buf = (struct btframe_buffer*)sc->sc_ctl_buf;
478 return sc->sc_ctl_buf;
479 }
480
481 static int
482 ubt_send_control(void *h, struct btframe_buffer *buf, size_t len)
483 {
484 struct ubt_softc *sc = h;
485 usb_device_request_t req;
486 usbd_status status;
487
488 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
489
490 #ifdef DIAGNOSTIC
491 if ((u_int8_t*)buf != sc->sc_ctl_buf)
492 panic("ubt_control() called with wrong buffer");
493 #endif
494
495 if (sc->sc_dying)
496 return EIO;
497
498 if (len < BTHCI_COMMAND_MIN_LEN || len > BTHCI_COMMAND_MAX_LEN)
499 return EINVAL;
500
501 sc->sc_refcnt++;
502
503 memset(&req, 0, sizeof(req));
504 req.bmRequestType = UT_WRITE_CLASS_DEVICE;
505 USETW(req.wLength, len);
506
507 usbd_setup_default_xfer(sc->sc_ctl_xfer,
508 sc->sc_udev,
509 sc,
510 USBD_DEFAULT_TIMEOUT,
511 &req, sc->sc_ctl_buf, len,
512 USBD_SYNCHRONOUS | USBD_NO_COPY, NULL);
513
514 status = usbd_transfer(sc->sc_ctl_xfer);
515
516 if (--sc->sc_refcnt < 0)
517 usb_detach_wakeup(USBDEV(sc->sc_dev));
518
519 if (status != USBD_NORMAL_COMPLETION)
520 return EIO;
521
522 return 0;
523 }
524
525 static u_int8_t*
526 ubt_alloc_acldata(void *h, size_t len, struct btframe_buffer **buf)
527 {
528 struct ubt_softc *sc = h;
529
530 /*
531 * We should be catching this earlier, but at the moment a
532 * user request can generate oversized allocations.
533 */
534 if (len > BTHCI_ACL_DATA_MAX_LEN)
535 return NULL;
536
537 *buf = (struct btframe_buffer*)sc->sc_aclwr_buf;
538 return sc->sc_aclwr_buf;
539 }
540
541 static int
542 ubt_send_acldata(void *h, struct btframe_buffer *buf, size_t len)
543 {
544 struct ubt_softc *sc = h;
545 usbd_status status;
546
547 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
548
549 #ifdef DIAGNOSTIC
550 if ((u_int8_t*)buf != sc->sc_aclwr_buf)
551 panic("ubt_sendacldata() called with wrong buffer");
552 #endif
553
554 if (sc->sc_dying)
555 return EIO;
556
557 if (len < BTHCI_ACL_DATA_MIN_LEN || len > BTHCI_ACL_DATA_MAX_LEN)
558 return EINVAL;
559
560 sc->sc_refcnt++;
561
562 usbd_setup_xfer(sc->sc_aclwr_xfer,
563 sc->sc_aclwr_pipe,
564 (usbd_private_handle)sc,
565 sc->sc_aclwr_buf, len,
566 USBD_SYNCHRONOUS | USBD_NO_COPY,
567 USBD_DEFAULT_TIMEOUT,
568 NULL);
569
570 status = usbd_transfer(sc->sc_aclwr_xfer);
571
572 if (--sc->sc_refcnt < 0)
573 usb_detach_wakeup(USBDEV(sc->sc_dev));
574
575 if (status != USBD_NORMAL_COMPLETION)
576 return EIO;
577
578 return 0;
579 }
580
581 static u_int8_t*
582 ubt_alloc_scodata(void *h, size_t len, struct btframe_buffer **buf)
583 {
584 return NULL;
585 }
586
587 static int
588 ubt_send_scodata(void *h, struct btframe_buffer *buf, size_t len)
589 {
590 struct ubt_softc *sc = h;
591
592 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
593
594 if (sc->sc_dying)
595 return EIO;
596
597 return ENXIO;
598 }
599
600 static void
601 ubt_event_cb(usbd_xfer_handle xfer, usbd_private_handle h, usbd_status status)
602 {
603 struct ubt_softc *sc = h;
604 void *buf;
605 u_int32_t size;
606
607 DPRINTFN(1,("%s: sc=%p status=%s\n", __func__, sc,
608 usbd_errstr(status)));
609
610 if (status != USBD_NORMAL_COMPLETION || sc->sc_dying ||
611 sc->sc_child == NULL)
612 return;
613
614 usbd_get_xfer_status(xfer, NULL, &buf, &size, NULL);
615
616 sc->sc_cb->bt_recveventdata(sc->sc_child, buf, (size_t)size);
617 }
618
619 static void
620 ubt_aclrd_request(struct ubt_softc *sc)
621 {
622 usbd_status status;
623 int s;
624
625 DPRINTFN(1,("%s: sc=%p\n", __func__, sc));
626
627 if (sc->sc_dying)
628 return;
629
630 s = splusb();
631 if (sc->sc_aclrd_running) {
632 splx(s);
633 return;
634 }
635 sc->sc_aclrd_running = 1;
636 splx(s);
637
638 usbd_setup_xfer(sc->sc_aclrd_xfer, sc->sc_aclrd_pipe,
639 sc, sc->sc_aclrd_buf, BTHCI_ACL_DATA_MAX_LEN,
640 USBD_SHORT_XFER_OK | USBD_NO_COPY,
641 USBD_NO_TIMEOUT, ubt_aclrd_cb);
642
643 status = usbd_transfer(sc->sc_aclrd_xfer);
644 if (status == USBD_IN_PROGRESS || 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 sc->sc_blocked |= BT_CBBLOCK_ACL_DATA;
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 if not blocked */
675 if (!sc->sc_dying && !(sc->sc_blocked & BT_CBBLOCK_ACL_DATA))
676 ubt_aclrd_request(sc);
677 }
678
679 static unsigned int
680 ubt_blockcb(void *h, unsigned int cbblocks)
681 {
682 struct ubt_softc *sc = h;
683
684 sc->sc_blocked |= (cbblocks & BT_CBBLOCK_ACL_DATA);
685
686 return sc->sc_blocked;
687 }
688
689 static unsigned int
690 ubt_unblockcb(void *h, unsigned int cbblocks)
691 {
692 struct ubt_softc *sc = h;
693 unsigned int oblocks, changes;
694
695 oblocks = sc->sc_blocked;
696 sc->sc_blocked = oblocks & ~cbblocks;
697
698 changes = oblocks & cbblocks;
699
700 if (changes & BT_CBBLOCK_ACL_DATA)
701 /* Re-issue the request if action un-blocked reads */
702 ubt_aclrd_request(sc);
703
704 return sc->sc_blocked;
705 }
706
707 static int
708 ubt_splraise(void)
709 {
710 return splusb();
711 }
712