1 /* $OpenBSD: if_ubt.c,v 1.2 2005/06/24 20:06:11 martin Exp $ */
2
3 /*
4 * ng_ubt.c
5 *
6 * Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
7 * All rights reserved.
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 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
30 * $Id: if_ubt.c,v 1.2 2005/06/24 20:06:11 martin Exp $
31 * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.20 2004/10/12 23:33:46 emax Exp $
32 */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/conf.h>
37 #include <sys/device.h>
38 #include <sys/endian.h>
39 #include <sys/fcntl.h>
40 #include <sys/filio.h>
41 #include <sys/kernel.h>
42 #include <sys/malloc.h>
43 #include <sys/mbuf.h>
44 #include <sys/poll.h>
45 #include <sys/uio.h>
46 #include <sys/socket.h>
47
48 #include <machine/bus.h>
49
50 #include <net/if.h>
51 #include <net/if_types.h>
52
53 #include <netbt/bluetooth.h>
54 #include <netbt/hci.h>
55 #include <netbt/l2cap.h>
56 #include <netbt/bt.h>
57 #include <netbt/hci_var.h>
58
59 #include <dev/usb/usb.h>
60 #include <dev/usb/usbdi.h>
61 #include <dev/usb/usbdi_util.h>
62 #include <dev/usb/usbdivar.h>
63 #include <dev/usb/usbdevs.h>
64
65 #include <dev/usb/if_ubtreg.h>
66
67 USB_DECLARE_DRIVER(ubt);
68
69 Static usbd_status ubt_request_start(struct ubt_softc *);
70 Static void ubt_request_complete(usbd_xfer_handle,
71 usbd_private_handle, usbd_status);
72
73 Static usbd_status ubt_intr_start(struct ubt_softc *);
74 Static void ubt_intr_complete(usbd_xfer_handle,
75 usbd_private_handle, usbd_status);
76
77 Static usbd_status ubt_bulk_in_start(struct ubt_softc *);
78 Static void ubt_bulk_in_complete(usbd_xfer_handle,
79 usbd_private_handle, usbd_status);
80
81 Static usbd_status ubt_bulk_out_start(struct ubt_softc *);
82 Static void ubt_bulk_out_complete(usbd_xfer_handle,
83 usbd_private_handle, usbd_status);
84
85 Static usbd_status ubt_isoc_in_start(struct ubt_softc *);
86 Static void ubt_isoc_in_complete(usbd_xfer_handle,
87 usbd_private_handle, usbd_status);
88
89 Static usbd_status ubt_isoc_out_start(struct ubt_softc *);
90 Static void ubt_isoc_out_complete(usbd_xfer_handle,
91 usbd_private_handle, usbd_status);
92
93 Static void ubt_reset(struct ubt_softc *);
94 Static void ubt_stop(struct ubt_softc *);
95
96 Static int ubt_rcvdata(struct ubt_softc *, struct mbuf *);
97
98 Static void ubt_if_start(struct ifnet *);
99 Static int ubt_if_ioctl(struct ifnet *, u_long, caddr_t);
100 Static int ubt_if_init(struct ifnet *);
101 Static void ubt_if_watchdog(struct ifnet *);
102
USB_MATCH(ubt)103 USB_MATCH(ubt)
104 {
105 /*
106 * If for some reason device should not be attached then put
107 * VendorID/ProductID pair into the list below. Currently I
108 * do not know of any such devices. The format is as follows:
109 *
110 * { VENDOR_ID, PRODUCT_ID },
111 *
112 * where VENDOR_ID and PRODUCT_ID are hex numbers.
113 */
114
115 Static struct usb_devno const ubt_ignored_devices[] = {
116 { 0, 0 } /* This should be the last item in the list */
117 };
118
119 /*
120 * If device violates Bluetooth specification and has bDeviceClass,
121 * bDeviceSubClass and bDeviceProtocol set to wrong values then you
122 * could try to put VendorID/ProductID pair into the list below.
123 */
124
125 Static struct usb_devno const ubt_broken_devices[] = {
126 { USB_VENDOR_CSR, USB_PRODUCT_CSR_BLUECORE },
127 { USB_VENDOR_MSI, USB_PRODUCT_MSI_BLUETOOTH },
128 { 0, 0 } /* This should be the last item in the list */
129 };
130
131 USB_MATCH_START(ubt, uaa);
132
133 usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
134
135 if (uaa->iface == NULL ||
136 usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
137 return (UMATCH_NONE);
138
139 if (dd->bDeviceClass == UDCLASS_WIRELESS &&
140 dd->bDeviceSubClass == UDSUBCLASS_RF &&
141 dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
142 return (UMATCH_DEVCLASS_DEVSUBCLASS);
143
144 if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
145 return (UMATCH_VENDOR_PRODUCT);
146
147 return (UMATCH_NONE);
148 }
149
USB_ATTACH(ubt)150 USB_ATTACH(ubt)
151 {
152 USB_ATTACH_START(ubt, sc, uaa);
153 usb_config_descriptor_t *cd = NULL;
154 usb_interface_descriptor_t *id = NULL;
155 usb_endpoint_descriptor_t *ed = NULL;
156 char devinfo[1024];
157 usbd_status error;
158 int i, ai, alt_no, isoc_in, isoc_out,
159 isoc_isize, isoc_osize;
160 struct ifnet *ifp = &sc->sc_if;
161
162 /* Get USB device info */
163 sc->sc_udev = uaa->device;
164 usbd_devinfo(sc->sc_udev, 0, devinfo, sizeof(devinfo));
165 USB_ATTACH_SETUP;
166 printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
167
168 /*
169 * Initialize device softc structure
170 */
171
172 /* State */
173 sc->sc_debug = NG_UBT_WARN_LEVEL;
174 sc->sc_flags = 0;
175 NG_UBT_STAT_RESET(sc->sc_stat);
176
177 /* Interfaces */
178 sc->sc_iface0 = sc->sc_iface1 = NULL;
179
180 /* Interrupt pipe */
181 sc->sc_intr_ep = -1;
182 sc->sc_intr_pipe = NULL;
183 sc->sc_intr_xfer = NULL;
184 sc->sc_intr_buffer = NULL;
185
186 /* Control pipe */
187 sc->sc_ctrl_xfer = NULL;
188 sc->sc_ctrl_buffer = NULL;
189 NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
190
191 /* Bulk-in pipe */
192 sc->sc_bulk_in_ep = -1;
193 sc->sc_bulk_in_pipe = NULL;
194 sc->sc_bulk_in_xfer = NULL;
195 sc->sc_bulk_in_buffer = NULL;
196
197 /* Bulk-out pipe */
198 sc->sc_bulk_out_ep = -1;
199 sc->sc_bulk_out_pipe = NULL;
200 sc->sc_bulk_out_xfer = NULL;
201 sc->sc_bulk_out_buffer = NULL;
202 NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
203
204 /* Isoc-in pipe */
205 sc->sc_isoc_in_ep = -1;
206 sc->sc_isoc_in_pipe = NULL;
207 sc->sc_isoc_in_xfer = NULL;
208
209 /* Isoc-out pipe */
210 sc->sc_isoc_out_ep = -1;
211 sc->sc_isoc_out_pipe = NULL;
212 sc->sc_isoc_out_xfer = NULL;
213 sc->sc_isoc_size = -1;
214 NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
215
216 /*
217 * XXX set configuration?
218 *
219 * Configure Bluetooth USB device. Discover all required USB interfaces
220 * and endpoints.
221 *
222 * USB device must present two interfaces:
223 * 1) Interface 0 that has 3 endpoints
224 * 1) Interrupt endpoint to receive HCI events
225 * 2) Bulk IN endpoint to receive ACL data
226 * 3) Bulk OUT endpoint to send ACL data
227 *
228 * 2) Interface 1 then has 2 endpoints
229 * 1) Isochronous IN endpoint to receive SCO data
230 * 2) Isochronous OUT endpoint to send SCO data
231 *
232 * Interface 1 (with isochronous endpoints) has several alternate
233 * configurations with different packet size.
234 */
235
236 /*
237 * Interface 0
238 */
239
240 error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
241 if (error || sc->sc_iface0 == NULL) {
242 printf("%s: Could not get interface 0 handle. %s (%d), " \
243 "handle=%p\n", USBDEVNAME(sc->sc_dev),
244 usbd_errstr(error), error, sc->sc_iface0);
245 goto bad;
246 }
247
248 id = usbd_get_interface_descriptor(sc->sc_iface0);
249 if (id == NULL) {
250 printf("%s: Could not get interface 0 descriptor\n",
251 USBDEVNAME(sc->sc_dev));
252 goto bad;
253 }
254
255 for (i = 0; i < id->bNumEndpoints; i ++) {
256 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
257 if (ed == NULL) {
258 printf("%s: Could not read endpoint descriptor for " \
259 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
260 i);
261 goto bad;
262 }
263
264 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
265 case UE_BULK:
266 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
267 sc->sc_bulk_in_ep = ed->bEndpointAddress;
268 else
269 sc->sc_bulk_out_ep = ed->bEndpointAddress;
270 break;
271
272 case UE_INTERRUPT:
273 sc->sc_intr_ep = ed->bEndpointAddress;
274 break;
275 }
276 }
277
278 /* Check if we got everything we wanted on Interface 0 */
279 if (sc->sc_intr_ep == -1) {
280 printf("%s: Could not detect interrupt endpoint\n",
281 USBDEVNAME(sc->sc_dev));
282 goto bad;
283 }
284 if (sc->sc_bulk_in_ep == -1) {
285 printf("%s: Could not detect bulk-in endpoint\n",
286 USBDEVNAME(sc->sc_dev));
287 goto bad;
288 }
289 if (sc->sc_bulk_out_ep == -1) {
290 printf("%s: Could not detect bulk-out endpoint\n",
291 USBDEVNAME(sc->sc_dev));
292 goto bad;
293 }
294
295 printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
296 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev),
297 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
298
299 /*
300 * Interface 1
301 */
302
303 cd = usbd_get_config_descriptor(sc->sc_udev);
304 if (cd == NULL) {
305 printf("%s: Could not get device configuration descriptor\n",
306 USBDEVNAME(sc->sc_dev));
307 goto bad;
308 }
309
310 error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
311 if (error || sc->sc_iface1 == NULL) {
312 printf("%s: Could not get interface 1 handle. %s (%d), " \
313 "handle=%p\n", USBDEVNAME(sc->sc_dev),
314 usbd_errstr(error), error, sc->sc_iface1);
315 goto bad;
316 }
317
318 id = usbd_get_interface_descriptor(sc->sc_iface1);
319 if (id == NULL) {
320 printf("%s: Could not get interface 1 descriptor\n",
321 USBDEVNAME(sc->sc_dev));
322 goto bad;
323 }
324
325 /*
326 * Scan all alternate configurations for interface 1
327 */
328
329 alt_no = -1;
330
331 for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++) {
332 error = usbd_set_interface(sc->sc_iface1, ai);
333 if (error) {
334 printf("%s: [SCAN] Could not set alternate " \
335 "configuration %d for interface 1. %s (%d)\n",
336 USBDEVNAME(sc->sc_dev), ai, usbd_errstr(error),
337 error);
338 goto bad;
339 }
340 id = usbd_get_interface_descriptor(sc->sc_iface1);
341 if (id == NULL) {
342 printf("%s: Could not get interface 1 descriptor for " \
343 "alternate configuration %d\n",
344 USBDEVNAME(sc->sc_dev), ai);
345 goto bad;
346 }
347
348 isoc_in = isoc_out = -1;
349 isoc_isize = isoc_osize = 0;
350
351 for (i = 0; i < id->bNumEndpoints; i ++) {
352 ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
353 if (ed == NULL) {
354 printf("%s: Could not read endpoint " \
355 "descriptor for interface 1, " \
356 "alternate configuration %d, i=%d\n",
357 USBDEVNAME(sc->sc_dev), ai, i);
358 goto bad;
359 }
360
361 if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
362 continue;
363
364 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
365 isoc_in = ed->bEndpointAddress;
366 isoc_isize = UGETW(ed->wMaxPacketSize);
367 } else {
368 isoc_out = ed->bEndpointAddress;
369 isoc_osize = UGETW(ed->wMaxPacketSize);
370 }
371 }
372
373 /*
374 * Make sure that configuration looks sane and if so
375 * update current settings
376 */
377
378 if (isoc_in != -1 && isoc_out != -1 &&
379 isoc_isize > 0 && isoc_osize > 0 &&
380 isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
381 sc->sc_isoc_in_ep = isoc_in;
382 sc->sc_isoc_out_ep = isoc_out;
383 sc->sc_isoc_size = isoc_isize;
384 alt_no = ai;
385 }
386 }
387
388 /* Check if we got everything we wanted on Interface 0 */
389 if (sc->sc_isoc_in_ep == -1) {
390 printf("%s: Could not detect isoc-in endpoint\n",
391 USBDEVNAME(sc->sc_dev));
392 goto bad;
393 }
394 if (sc->sc_isoc_out_ep == -1) {
395 printf("%s: Could not detect isoc-out endpoint\n",
396 USBDEVNAME(sc->sc_dev));
397 goto bad;
398 }
399 if (sc->sc_isoc_size <= 0) {
400 printf("%s: Invalid isoc. packet size=%d\n",
401 USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
402 goto bad;
403 }
404
405 error = usbd_set_interface(sc->sc_iface1, alt_no);
406 if (error) {
407 printf("%s: Could not set alternate configuration " \
408 "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
409 alt_no, usbd_errstr(error), error);
410 goto bad;
411 }
412
413 /* Allocate USB transfer handles and buffers */
414 sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
415 if (sc->sc_ctrl_xfer == NULL) {
416 printf("%s: Could not allocate control xfer handle\n",
417 USBDEVNAME(sc->sc_dev));
418 goto bad;
419 }
420 sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer,
421 UBT_CTRL_BUFFER_SIZE);
422 if (sc->sc_ctrl_buffer == NULL) {
423 printf("%s: Could not allocate control buffer\n",
424 USBDEVNAME(sc->sc_dev));
425 goto bad;
426 }
427
428 sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
429 if (sc->sc_intr_xfer == NULL) {
430 printf("%s: Could not allocate interrupt xfer handle\n",
431 USBDEVNAME(sc->sc_dev));
432 goto bad;
433 }
434 sc->sc_intr_buffer = usbd_alloc_buffer(sc->sc_intr_xfer,
435 UBT_INTR_BUFFER_SIZE);
436 if (sc->sc_intr_buffer == NULL) {
437 printf("%s: Could not allocate interrupt buffer\n",
438 USBDEVNAME(sc->sc_dev));
439 goto bad;
440 }
441
442 sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
443 if (sc->sc_bulk_in_xfer == NULL) {
444 printf("%s: Could not allocate bulk-in xfer handle\n",
445 USBDEVNAME(sc->sc_dev));
446 goto bad;
447 }
448 sc->sc_bulk_in_buffer = usbd_alloc_buffer(sc->sc_bulk_in_xfer,
449 UBT_BULK_BUFFER_SIZE);
450 if (sc->sc_bulk_in_buffer == NULL) {
451 printf("%s: Could not allocate bulk-in buffer\n",
452 USBDEVNAME(sc->sc_dev));
453 goto bad;
454 }
455
456 sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
457 if (sc->sc_bulk_out_xfer == NULL) {
458 printf("%s: Could not allocate bulk-out xfer handle\n",
459 USBDEVNAME(sc->sc_dev));
460 goto bad;
461 }
462 sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
463 UBT_BULK_BUFFER_SIZE);
464 if (sc->sc_bulk_out_buffer == NULL) {
465 printf("%s: Could not allocate bulk-out buffer\n",
466 USBDEVNAME(sc->sc_dev));
467 goto bad;
468 }
469
470 /*
471 * Allocate buffers for isoc. transfers
472 */
473
474 sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
475
476 sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
477 if (sc->sc_isoc_in_xfer == NULL) {
478 printf("%s: Could not allocate isoc-in xfer handle\n",
479 USBDEVNAME(sc->sc_dev));
480 goto bad;
481 }
482 sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
483 sc->sc_isoc_nframes * sc->sc_isoc_size);
484 if (sc->sc_isoc_in_buffer == NULL) {
485 printf("%s: Could not allocate isoc-in buffer\n",
486 USBDEVNAME(sc->sc_dev));
487 goto bad;
488 }
489 sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
490 M_USBDEV, M_NOWAIT);
491 if (sc->sc_isoc_in_frlen == NULL) {
492 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
493 USBDEVNAME(sc->sc_dev));
494 goto bad;
495 }
496
497 sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
498 if (sc->sc_isoc_out_xfer == NULL) {
499 printf("%s: Could not allocate isoc-out xfer handle\n",
500 USBDEVNAME(sc->sc_dev));
501 goto bad;
502 }
503 sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
504 sc->sc_isoc_nframes * sc->sc_isoc_size);
505 if (sc->sc_isoc_out_buffer == NULL) {
506 printf("%s: Could not allocate isoc-out buffer\n",
507 USBDEVNAME(sc->sc_dev));
508 goto bad;
509 }
510 sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes,
511 M_USBDEV, M_NOWAIT);
512 if (sc->sc_isoc_out_frlen == NULL) {
513 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
514 USBDEVNAME(sc->sc_dev));
515 goto bad;
516 }
517
518 printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
519 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
520 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
521 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes,
522 (sc->sc_isoc_nframes * sc->sc_isoc_size));
523
524 /*
525 * Open pipes
526 */
527
528 /* Interrupt */
529 error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
530 USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
531 if (error != USBD_NORMAL_COMPLETION) {
532 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
533 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
534 error);
535 goto bad;
536 }
537
538 /* Bulk-in */
539 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
540 USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
541 if (error != USBD_NORMAL_COMPLETION) {
542 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
543 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
544 error);
545 goto bad;
546 }
547
548 /* Bulk-out */
549 error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
550 USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
551 if (error != USBD_NORMAL_COMPLETION) {
552 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
553 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
554 error);
555 goto bad;
556 }
557
558 #if __broken__ /* XXX FIXME */
559 /* Isoc-in */
560 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
561 USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
562 if (error != USBD_NORMAL_COMPLETION) {
563 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
564 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
565 error);
566 goto bad;
567 }
568
569 /* Isoc-out */
570 error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep,
571 USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
572 if (error != USBD_NORMAL_COMPLETION) {
573 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
574 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
575 error);
576 goto bad;
577 }
578 #endif /* __broken__ */
579
580 /* Start intr transfer */
581 error = ubt_intr_start(sc);
582 if (error != USBD_NORMAL_COMPLETION) {
583 NG_UBT_ALERT(
584 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
585 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
586 error);
587 goto bad;
588 }
589
590 /* Start bulk-in transfer */
591 error = ubt_bulk_in_start(sc);
592 if (error != USBD_NORMAL_COMPLETION) {
593 NG_UBT_ALERT(
594 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
595 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
596 error);
597 goto bad;
598 }
599
600 #if __broken__ /* XXX FIXME */
601 /* Start isoc-in transfer */
602 error = ubt_isoc_in_start(sc);
603 if (error != USBD_NORMAL_COMPLETION) {
604 NG_UBT_ALERT(
605 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
606 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
607 error);
608 goto bad;
609 }
610 #endif /* __broken__ */
611
612 /* Claim all interfaces on the device */
613 for (i = 0; i < uaa->nifaces; i++)
614 uaa->ifaces[i] = NULL;
615
616 /* Attach network interface */
617 bzero(ifp, sizeof(*ifp));
618 strlcpy(ifp->if_xname, USBDEVNAME(sc->sc_dev), sizeof(ifp->if_xname));
619 ifp->if_softc = sc;
620 ifp->if_mtu = 65536;
621 ifp->if_start = ubt_if_start;
622 ifp->if_ioctl = ubt_if_ioctl;
623 ifp->if_init = ubt_if_init;
624 ifp->if_watchdog = ubt_if_watchdog;
625 ifp->if_type = IFT_BLUETOOTH;
626 IFQ_SET_READY(&ifp->if_snd);
627 if_attach(ifp);
628 if_alloc_sadl(ifp);
629
630 usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
631 USBDEV(sc->sc_dev));
632
633 USB_ATTACH_SUCCESS_RETURN;
634 bad:
635 #if 0
636 ubt_detach(self);
637 #endif
638 USB_ATTACH_ERROR_RETURN;
639 }
640
USB_DETACH(ubt)641 USB_DETACH(ubt)
642 {
643 USB_DETACH_START(ubt, sc);
644 struct ifnet *ifp = &sc->sc_if;
645
646 /* Close pipes */
647 if (sc->sc_intr_pipe != NULL) {
648 usbd_close_pipe(sc->sc_intr_pipe);
649 sc->sc_intr_pipe = NULL;
650 }
651
652 if (sc->sc_bulk_in_pipe != NULL) {
653 usbd_close_pipe(sc->sc_bulk_in_pipe);
654 sc->sc_bulk_in_pipe = NULL;
655 }
656 if (sc->sc_bulk_out_pipe != NULL) {
657 usbd_close_pipe(sc->sc_bulk_out_pipe);
658 sc->sc_bulk_out_pipe = NULL;
659 }
660
661 if (sc->sc_isoc_in_pipe != NULL) {
662 usbd_close_pipe(sc->sc_isoc_in_pipe);
663 sc->sc_isoc_in_pipe = NULL;
664 }
665 if (sc->sc_isoc_out_pipe != NULL) {
666 usbd_close_pipe(sc->sc_isoc_out_pipe);
667 sc->sc_isoc_out_pipe = NULL;
668 }
669
670 /* Destroy USB transfer handles */
671 if (sc->sc_ctrl_xfer != NULL) {
672 usbd_free_xfer(sc->sc_ctrl_xfer);
673 sc->sc_ctrl_xfer = NULL;
674 }
675
676 if (sc->sc_intr_xfer != NULL) {
677 usbd_free_xfer(sc->sc_intr_xfer);
678 sc->sc_intr_xfer = NULL;
679 }
680
681 if (sc->sc_bulk_in_xfer != NULL) {
682 usbd_free_xfer(sc->sc_bulk_in_xfer);
683 sc->sc_bulk_in_xfer = NULL;
684 }
685 if (sc->sc_bulk_out_xfer != NULL) {
686 usbd_free_xfer(sc->sc_bulk_out_xfer);
687 sc->sc_bulk_out_xfer = NULL;
688 }
689
690 if (sc->sc_isoc_in_xfer != NULL) {
691 usbd_free_xfer(sc->sc_isoc_in_xfer);
692 sc->sc_isoc_in_xfer = NULL;
693 }
694 if (sc->sc_isoc_out_xfer != NULL) {
695 usbd_free_xfer(sc->sc_isoc_out_xfer);
696 sc->sc_isoc_out_xfer = NULL;
697 }
698
699 /* Destroy isoc. frame size buffers */
700 if (sc->sc_isoc_in_frlen != NULL) {
701 free(sc->sc_isoc_in_frlen, M_USBDEV);
702 sc->sc_isoc_in_frlen = NULL;
703 }
704 if (sc->sc_isoc_out_frlen != NULL) {
705 free(sc->sc_isoc_out_frlen, M_USBDEV);
706 sc->sc_isoc_out_frlen = NULL;
707 }
708
709 #if 0
710 /* Destroy queues */
711 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
712 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
713 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
714 #endif
715
716 if_detach(ifp);
717
718 usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
719 USBDEV(sc->sc_dev));
720
721 return (0);
722 }
723
724 int
ubt_activate(device_ptr_t self,enum devact act)725 ubt_activate(device_ptr_t self, enum devact act)
726 {
727 switch (act) {
728 case DVACT_ACTIVATE:
729 return (EOPNOTSUPP);
730 case DVACT_DEACTIVATE:
731 break;
732 }
733
734 return (0);
735 }
736
737 /*
738 * Start USB control request (HCI command).
739 */
740 Static usbd_status
ubt_request_start(struct ubt_softc * sc)741 ubt_request_start(struct ubt_softc * sc)
742 {
743 usb_device_request_t req;
744 struct mbuf *m = NULL;
745 usbd_status status;
746
747 KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
748 "%s: %s - Another control request is pending\n",
749 __func__, USBDEVNAME(sc->sc_dev)));
750
751 NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
752 if (m == NULL) {
753 NG_UBT_INFO(
754 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
755
756 return (USBD_NORMAL_COMPLETION);
757 }
758
759 /*
760 * Check HCI command frame size and copy it back to
761 * linear USB transfer buffer.
762 */
763
764 if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
765 panic("%s: %s - HCI command frame too big, size=%lu, len=%d\n",
766 __func__, USBDEVNAME(sc->sc_dev), (u_long)UBT_CTRL_BUFFER_SIZE,
767 m->m_pkthdr.len);
768
769 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
770
771 /* Initialize a USB control request and then schedule it */
772 bzero(&req, sizeof(req));
773 req.bmRequestType = UBT_HCI_REQUEST;
774 USETW(req.wLength, m->m_pkthdr.len);
775
776 NG_UBT_INFO(
777 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
778 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
779 UGETW(req.wLength));
780
781 usbd_setup_default_xfer(
782 sc->sc_ctrl_xfer,
783 sc->sc_udev,
784 (usbd_private_handle) sc,
785 USBD_DEFAULT_TIMEOUT, /* XXX */
786 &req,
787 sc->sc_ctrl_buffer,
788 m->m_pkthdr.len,
789 USBD_NO_COPY,
790 ubt_request_complete);
791
792 status = usbd_transfer(sc->sc_ctrl_xfer);
793 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
794 NG_UBT_ERR(
795 "%s: %s - Could not start control request. %s (%d)\n",
796 __func__, USBDEVNAME(sc->sc_dev),
797 usbd_errstr(status), status);
798
799 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
800 NG_UBT_STAT_OERROR(sc->sc_stat);
801
802 /* XXX FIXME should we try to resubmit another request? */
803 } else {
804 NG_UBT_INFO(
805 "%s: %s - Control request has been started\n",
806 __func__, USBDEVNAME(sc->sc_dev));
807
808 sc->sc_flags |= UBT_CMD_XMIT;
809 status = USBD_NORMAL_COMPLETION;
810 }
811
812 NG_FREE_M(m);
813
814 return (status);
815 } /* ubt_request_start */
816
817 /*
818 * USB control request callback
819 */
820 Static void
ubt_request_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)821 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
822 {
823 struct ubt_softc * sc = p;
824
825 if (sc == NULL)
826 return;
827
828 KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
829 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
830
831 sc->sc_flags &= ~UBT_CMD_XMIT;
832
833 if (s == USBD_CANCELLED) {
834 NG_UBT_INFO(
835 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
836
837 return;
838 }
839
840 if (s != USBD_NORMAL_COMPLETION) {
841 NG_UBT_ERR(
842 "%s: %s - Control request failed. %s (%d)\n",
843 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
844
845 if (s == USBD_STALLED)
846 usbd_clear_endpoint_stall_async(h->pipe);
847
848 NG_UBT_STAT_OERROR(sc->sc_stat);
849 } else {
850 NG_UBT_INFO(
851 "%s: %s - Sent %d bytes to control pipe\n",
852 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
853
854 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
855 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
856 }
857
858 if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
859 ubt_request_start(sc);
860 } /* ubt_request_complete2 */
861
862 /*
863 * Start interrupt transfer. Must be called when node is locked
864 */
865
866 Static usbd_status
ubt_intr_start(struct ubt_softc * sc)867 ubt_intr_start(struct ubt_softc * sc)
868 {
869 struct mbuf *m = NULL;
870 usbd_status status;
871
872 KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
873 "%s: %s - Another interrupt request is pending\n",
874 __func__, USBDEVNAME(sc->sc_dev)));
875
876 /* Allocate new mbuf cluster */
877 MGETHDR(m, M_DONTWAIT, MT_DATA);
878 if (m == NULL)
879 return (USBD_NOMEM);
880
881 MCLGET(m, M_DONTWAIT);
882 if (!(m->m_flags & M_EXT)) {
883 NG_FREE_M(m);
884 return (USBD_NOMEM);
885 }
886
887 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
888 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
889 m->m_pkthdr.len = m->m_len = 1;
890 } else
891 m->m_pkthdr.len = m->m_len = 0;
892
893 /* Initialize a USB transfer and then schedule it */
894 usbd_setup_xfer(
895 sc->sc_intr_xfer,
896 sc->sc_intr_pipe,
897 (usbd_private_handle) sc,
898 sc->sc_intr_buffer,
899 UBT_INTR_BUFFER_SIZE,
900 USBD_SHORT_XFER_OK,
901 USBD_NO_TIMEOUT,
902 ubt_intr_complete);
903
904 status = usbd_transfer(sc->sc_intr_xfer);
905 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
906 NG_UBT_ERR(
907 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
908 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
909 status);
910
911 NG_FREE_M(m);
912
913 return (status);
914 }
915
916 sc->sc_flags |= UBT_EVT_RECV;
917 sc->sc_intr_mbuf = m;
918
919 return (USBD_NORMAL_COMPLETION);
920 } /* ubt_intr_start */
921
922 /*
923 * Process interrupt from USB device (We got data from interrupt pipe)
924 */
925 Static void
ubt_intr_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)926 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
927 {
928 struct ubt_softc * sc = p;
929 struct mbuf *m = NULL;
930 ng_hci_event_pkt_t *hdr = NULL;
931 int error = 0;
932
933 if (sc == NULL)
934 return;
935
936 KASSERT((sc->sc_flags & UBT_EVT_RECV), (
937 "%s: %s - No interrupt request is pending\n",
938 __func__, USBDEVNAME(sc->sc_dev)));
939
940 sc->sc_flags &= ~UBT_EVT_RECV;
941
942 m = sc->sc_intr_mbuf;
943 bcopy(sc->sc_intr_buffer, mtod(m, void *) + m->m_len, h->actlen);
944
945 hdr = mtod(m, ng_hci_event_pkt_t *);
946
947 if (s == USBD_CANCELLED) {
948 NG_UBT_INFO(
949 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
950
951 NG_FREE_M(m);
952 return;
953 }
954
955 if (s != USBD_NORMAL_COMPLETION) {
956 NG_UBT_WARN(
957 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
958 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
959
960 if (s == USBD_STALLED)
961 usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
962
963 NG_UBT_STAT_IERROR(sc->sc_stat);
964 NG_FREE_M(m);
965
966 return; /* XXX FIXME we should restart after some delay */
967 }
968
969 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
970 m->m_pkthdr.len += h->actlen;
971 m->m_len += h->actlen;
972
973 NG_UBT_INFO(
974 "%s: %s - Got %d bytes from interrupt pipe\n",
975 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
976
977 if (m->m_pkthdr.len < sizeof(*hdr)) {
978 NG_FREE_M(m);
979 goto done;
980 }
981
982 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
983 NG_UBT_INFO(
984 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
985 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
986 hdr->length);
987
988 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
989
990 #if 0
991 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
992 #endif
993 ng_btsocket_hci_raw_node_rcvdata(&sc->sc_if, m);
994 if (error != 0)
995 NG_UBT_STAT_IERROR(sc->sc_stat);
996 } else {
997 NG_UBT_ERR(
998 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
999 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1000 m->m_pkthdr.len);
1001
1002 NG_UBT_STAT_IERROR(sc->sc_stat);
1003 NG_FREE_M(m);
1004 }
1005 done:
1006 ubt_intr_start(sc);
1007 } /* ubt_intr_complete */
1008
1009 /*
1010 * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1011 */
1012 Static usbd_status
ubt_bulk_in_start(struct ubt_softc * sc)1013 ubt_bulk_in_start(struct ubt_softc * sc)
1014 {
1015 struct mbuf *m = NULL;
1016 usbd_status status;
1017
1018 KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1019 "%s: %s - Another bulk-in request is pending\n",
1020 __func__, USBDEVNAME(sc->sc_dev)));
1021
1022 /* Allocate new mbuf cluster */
1023 MGETHDR(m, M_DONTWAIT, MT_DATA);
1024 if (m == NULL)
1025 return (USBD_NOMEM);
1026
1027 MCLGET(m, M_DONTWAIT);
1028 if (!(m->m_flags & M_EXT)) {
1029 NG_FREE_M(m);
1030 return (USBD_NOMEM);
1031 }
1032
1033 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1034 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1035 m->m_pkthdr.len = m->m_len = 1;
1036 } else
1037 m->m_pkthdr.len = m->m_len = 0;
1038
1039 /* Initialize a bulk-in USB transfer and then schedule it */
1040 usbd_setup_xfer(
1041 sc->sc_bulk_in_xfer,
1042 sc->sc_bulk_in_pipe,
1043 (usbd_private_handle) sc,
1044 sc->sc_bulk_in_buffer,
1045 UBT_BULK_BUFFER_SIZE,
1046 USBD_SHORT_XFER_OK,
1047 USBD_NO_TIMEOUT,
1048 ubt_bulk_in_complete);
1049
1050 status = usbd_transfer(sc->sc_bulk_in_xfer);
1051 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1052 NG_UBT_ERR(
1053 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1054 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1055 status);
1056
1057 NG_FREE_M(m);
1058
1059 return (status);
1060 }
1061
1062 sc->sc_flags |= UBT_ACL_RECV;
1063 sc->sc_bulk_in_mbuf = m;
1064
1065 return (USBD_NORMAL_COMPLETION);
1066 } /* ubt_bulk_in_start */
1067
1068 /*
1069 * USB bulk-in transfer callback
1070 */
1071 Static void
ubt_bulk_in_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1072 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1073 {
1074 struct ubt_softc * sc = p;
1075 struct mbuf *m = NULL;
1076 ng_hci_acldata_pkt_t *hdr = NULL;
1077 int len;
1078
1079 if (sc == NULL)
1080 return;
1081
1082 KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1083 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1084
1085 sc->sc_flags &= ~UBT_ACL_RECV;
1086
1087 m = sc->sc_bulk_in_mbuf;
1088 bcopy(sc->sc_intr_buffer, mtod(m, void *) + m->m_len, h->actlen);
1089
1090 hdr = mtod(m, ng_hci_acldata_pkt_t *);
1091
1092 if (s == USBD_CANCELLED) {
1093 NG_UBT_INFO(
1094 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1095 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1096
1097 NG_FREE_M(m);
1098 return;
1099 }
1100
1101 if (s != USBD_NORMAL_COMPLETION) {
1102 NG_UBT_WARN(
1103 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1104 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1105
1106 if (s == USBD_STALLED)
1107 usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1108
1109 NG_UBT_STAT_IERROR(sc->sc_stat);
1110 NG_FREE_M(m);
1111
1112 return; /* XXX FIXME we should restart after some delay */
1113 }
1114
1115 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1116 m->m_pkthdr.len += h->actlen;
1117 m->m_len += h->actlen;
1118
1119 NG_UBT_INFO(
1120 "%s: %s - Got %d bytes from bulk-in pipe\n",
1121 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1122
1123 if (m->m_pkthdr.len < sizeof(*hdr)) {
1124 NG_FREE_M(m);
1125 goto done;
1126 }
1127
1128 len = le16toh(hdr->length);
1129 if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1130 NG_UBT_INFO(
1131 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1132 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1133
1134 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1135
1136 #if 0
1137 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1138 #endif
1139 if (len != 0)
1140 NG_UBT_STAT_IERROR(sc->sc_stat);
1141 } else {
1142 NG_UBT_ERR(
1143 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1144 __func__, USBDEVNAME(sc->sc_dev), len,
1145 m->m_pkthdr.len);
1146
1147 NG_UBT_STAT_IERROR(sc->sc_stat);
1148 NG_FREE_M(m);
1149 }
1150 done:
1151 ubt_bulk_in_start(sc);
1152 } /* ubt_bulk_in_complete2 */
1153
1154 /*
1155 * Start bulk-out USB transfer. Must be called with node locked
1156 */
1157
1158 Static usbd_status
ubt_bulk_out_start(struct ubt_softc * sc)1159 ubt_bulk_out_start(struct ubt_softc * sc)
1160 {
1161 struct mbuf *m = NULL;
1162 usbd_status status;
1163
1164 KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1165 "%s: %s - Another bulk-out request is pending\n",
1166 __func__, USBDEVNAME(sc->sc_dev)));
1167
1168 NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1169 if (m == NULL) {
1170 NG_UBT_INFO(
1171 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1172
1173 return (USBD_NORMAL_COMPLETION);
1174 }
1175
1176 /*
1177 * Check ACL data frame size and copy it back to linear USB
1178 * transfer buffer.
1179 */
1180
1181 if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1182 panic(
1183 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1184 __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1185 m->m_pkthdr.len);
1186
1187 m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1188
1189 /* Initialize a bulk-out USB transfer and then schedule it */
1190 usbd_setup_xfer(
1191 sc->sc_bulk_out_xfer,
1192 sc->sc_bulk_out_pipe,
1193 (usbd_private_handle) sc,
1194 sc->sc_bulk_out_buffer,
1195 m->m_pkthdr.len,
1196 USBD_NO_COPY,
1197 USBD_DEFAULT_TIMEOUT, /* XXX */
1198 ubt_bulk_out_complete);
1199
1200 status = usbd_transfer(sc->sc_bulk_out_xfer);
1201 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1202 NG_UBT_ERR(
1203 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1204 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1205 status);
1206
1207 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1208 NG_UBT_STAT_OERROR(sc->sc_stat);
1209
1210 /* XXX FIXME should we try to start another transfer? */
1211 } else {
1212 NG_UBT_INFO(
1213 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1214 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1215
1216 sc->sc_flags |= UBT_ACL_XMIT;
1217 status = USBD_NORMAL_COMPLETION;
1218 }
1219
1220 NG_FREE_M(m);
1221
1222 return (status);
1223 } /* ubt_bulk_out_start */
1224
1225 /*
1226 * USB bulk-out transfer callback
1227 */
1228 Static void
ubt_bulk_out_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1229 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1230 {
1231 struct ubt_softc * sc = p;
1232
1233 if (sc == NULL)
1234 return;
1235
1236 KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1237 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1238
1239 sc->sc_flags &= ~UBT_ACL_XMIT;
1240
1241 if (s == USBD_CANCELLED) {
1242 NG_UBT_INFO(
1243 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1244 __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1245
1246 return;
1247 }
1248
1249 if (s != USBD_NORMAL_COMPLETION) {
1250 NG_UBT_WARN(
1251 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1252 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1253
1254 if (s == USBD_STALLED)
1255 usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1256
1257 NG_UBT_STAT_OERROR(sc->sc_stat);
1258 } else {
1259 NG_UBT_INFO(
1260 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1261 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1262
1263 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1264 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1265 }
1266
1267 if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1268 ubt_bulk_out_start(sc);
1269 } /* ubt_bulk_out_complete2 */
1270
1271 /*
1272 * Start Isochronous-in USB transfer. Must be called with node locked
1273 */
1274
1275 Static usbd_status
ubt_isoc_in_start(struct ubt_softc * sc)1276 ubt_isoc_in_start(struct ubt_softc * sc)
1277 {
1278 usbd_status status;
1279 int i;
1280
1281 KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1282 "%s: %s - Another isoc-in request is pending\n",
1283 __func__, USBDEVNAME(sc->sc_dev)));
1284
1285 /* Initialize a isoc-in USB transfer and then schedule it */
1286 for (i = 0; i < sc->sc_isoc_nframes; i++)
1287 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1288
1289 usbd_setup_isoc_xfer(
1290 sc->sc_isoc_in_xfer,
1291 sc->sc_isoc_in_pipe,
1292 (usbd_private_handle) sc,
1293 sc->sc_isoc_in_frlen,
1294 sc->sc_isoc_nframes,
1295 USBD_NO_COPY, /* XXX flags */
1296 ubt_isoc_in_complete);
1297
1298 status = usbd_transfer(sc->sc_isoc_in_xfer);
1299 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1300 NG_UBT_ERR(
1301 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1302 __func__, USBDEVNAME(sc->sc_dev),
1303 usbd_errstr(status), status);
1304
1305 return (status);
1306 }
1307
1308 sc->sc_flags |= UBT_SCO_RECV;
1309
1310 return (USBD_NORMAL_COMPLETION);
1311 } /* ubt_isoc_in_start */
1312
1313 /*
1314 * USB isochronous transfer callback
1315 */
1316 Static void
ubt_isoc_in_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1317 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1318 {
1319 struct ubt_softc * sc = p;
1320 struct mbuf *m = NULL;
1321 ng_hci_scodata_pkt_t *hdr = NULL;
1322 u_int8_t *b = NULL;
1323 int i;
1324
1325 if (sc == NULL)
1326 return;
1327
1328 KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1329 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1330
1331 sc->sc_flags &= ~UBT_SCO_RECV;
1332
1333 #if 0
1334 if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1335 NG_UBT_INFO(
1336 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1337
1338 return;
1339 }
1340 #endif
1341
1342 if (s == USBD_CANCELLED) {
1343 NG_UBT_INFO(
1344 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1345 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1346
1347 return;
1348 }
1349
1350 if (s != USBD_NORMAL_COMPLETION) {
1351 NG_UBT_WARN(
1352 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1353 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1354
1355 if (s == USBD_STALLED)
1356 usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1357
1358 NG_UBT_STAT_IERROR(sc->sc_stat);
1359
1360 return; /* XXX FIXME we should restart after some delay */
1361 }
1362
1363 NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1364
1365 NG_UBT_INFO(
1366 "%s: %s - Got %d bytes from isoc-in pipe\n",
1367 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1368
1369 /* Copy SCO data frame to mbuf */
1370 MGETHDR(m, M_DONTWAIT, MT_DATA);
1371 if (m == NULL) {
1372 NG_UBT_ALERT(
1373 "%s: %s - Could not allocate mbuf\n",
1374 __func__, USBDEVNAME(sc->sc_dev));
1375
1376 NG_UBT_STAT_IERROR(sc->sc_stat);
1377 goto done;
1378 }
1379
1380 /* Fix SCO data frame header if required */
1381 if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1382 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1383 m->m_pkthdr.len = 1;
1384 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1385 } else {
1386 m->m_pkthdr.len = 0;
1387 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1388 }
1389
1390 /*
1391 * XXX FIXME how do we know how many frames we have received?
1392 * XXX use frlen for now. is that correct?
1393 */
1394
1395 b = (u_int8_t *) sc->sc_isoc_in_buffer;
1396
1397 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1398 b += (i * sc->sc_isoc_size);
1399
1400 if (sc->sc_isoc_in_frlen[i] > 0)
1401 m_copyback(m, m->m_pkthdr.len,
1402 sc->sc_isoc_in_frlen[i], b);
1403 }
1404
1405 if (m->m_pkthdr.len < sizeof(*hdr))
1406 goto done;
1407
1408 hdr = mtod(m, ng_hci_scodata_pkt_t *);
1409
1410 if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1411 NG_UBT_INFO(
1412 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1413 __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1414 hdr->length);
1415
1416 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1417
1418 #if 0
1419 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1420 #endif
1421 if (i != 0)
1422 NG_UBT_STAT_IERROR(sc->sc_stat);
1423 } else {
1424 NG_UBT_ERR(
1425 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1426 __func__, USBDEVNAME(sc->sc_dev), hdr->length,
1427 m->m_pkthdr.len);
1428
1429 NG_UBT_STAT_IERROR(sc->sc_stat);
1430 NG_FREE_M(m);
1431 }
1432 done:
1433 ubt_isoc_in_start(sc);
1434 } /* ubt_isoc_in_complete2 */
1435
1436 /*
1437 * Start isochronous-out USB transfer. Must be called with node locked
1438 */
1439
1440 Static usbd_status
ubt_isoc_out_start(struct ubt_softc * sc)1441 ubt_isoc_out_start(struct ubt_softc * sc)
1442 {
1443 struct mbuf *m = NULL;
1444 u_int8_t *b = NULL;
1445 int i, len, nframes;
1446 usbd_status status;
1447
1448 KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1449 "%s: %s - Another isoc-out request is pending\n",
1450 __func__, USBDEVNAME(sc->sc_dev)));
1451
1452 NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1453 if (m == NULL) {
1454 NG_UBT_INFO(
1455 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1456
1457 return (USBD_NORMAL_COMPLETION);
1458 }
1459
1460 /* Copy entire SCO frame into USB transfer buffer and start transfer */
1461 b = (u_int8_t *) sc->sc_isoc_out_buffer;
1462 nframes = 0;
1463
1464 for (i = 0; i < sc->sc_isoc_nframes; i++) {
1465 b += (i * sc->sc_isoc_size);
1466
1467 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1468 if (len > 0) {
1469 m_copydata(m, 0, len, b);
1470 m_adj(m, len);
1471 nframes ++;
1472 }
1473
1474 sc->sc_isoc_out_frlen[i] = len;
1475 }
1476
1477 if (m->m_pkthdr.len > 0)
1478 panic(
1479 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1480 __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1481 sc->sc_isoc_size, m->m_pkthdr.len);
1482
1483 NG_FREE_M(m);
1484
1485 /* Initialize a isoc-out USB transfer and then schedule it */
1486 usbd_setup_isoc_xfer(
1487 sc->sc_isoc_out_xfer,
1488 sc->sc_isoc_out_pipe,
1489 (usbd_private_handle) sc,
1490 sc->sc_isoc_out_frlen,
1491 nframes,
1492 USBD_NO_COPY,
1493 ubt_isoc_out_complete);
1494
1495 status = usbd_transfer(sc->sc_isoc_out_xfer);
1496 if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1497 NG_UBT_ERR(
1498 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1499 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1500 status);
1501
1502 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1503 NG_UBT_STAT_OERROR(sc->sc_stat);
1504 } else {
1505 NG_UBT_INFO(
1506 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1507 __func__, USBDEVNAME(sc->sc_dev), nframes,
1508 sc->sc_isoc_size);
1509
1510 sc->sc_flags |= UBT_SCO_XMIT;
1511 status = USBD_NORMAL_COMPLETION;
1512 }
1513
1514 return (status);
1515 } /* ubt_isoc_out_start */
1516
1517 /*
1518 * USB isoc-out. transfer callback
1519 */
1520 Static void
ubt_isoc_out_complete(usbd_xfer_handle h,usbd_private_handle p,usbd_status s)1521 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1522 {
1523 struct ubt_softc * sc = p;
1524
1525 if (sc == NULL)
1526 return;
1527
1528 KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1529 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1530
1531 sc->sc_flags &= ~UBT_SCO_XMIT;
1532
1533 if (s == USBD_CANCELLED) {
1534 NG_UBT_INFO(
1535 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1536 __func__, USBDEVNAME(sc->sc_dev),
1537 sc->sc_isoc_out_pipe);
1538
1539 return;
1540 }
1541
1542 if (s != USBD_NORMAL_COMPLETION) {
1543 NG_UBT_WARN(
1544 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1545 __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1546
1547 if (s == USBD_STALLED)
1548 usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1549
1550 NG_UBT_STAT_OERROR(sc->sc_stat);
1551 } else {
1552 NG_UBT_INFO(
1553 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1554 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1555
1556 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1557 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1558 }
1559
1560 if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1561 ubt_isoc_out_start(sc);
1562 } /* ubt_isoc_out_complete2 */
1563
1564 /*
1565 * Abort transfers on all USB pipes
1566 */
1567
1568 Static void
ubt_reset(struct ubt_softc * sc)1569 ubt_reset(struct ubt_softc * sc)
1570 {
1571 /* Interrupt */
1572 if (sc->sc_intr_pipe != NULL)
1573 usbd_abort_pipe(sc->sc_intr_pipe);
1574
1575 /* Bulk-in/out */
1576 if (sc->sc_bulk_in_pipe != NULL)
1577 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1578 if (sc->sc_bulk_out_pipe != NULL)
1579 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1580
1581 /* Isoc-in/out */
1582 if (sc->sc_isoc_in_pipe != NULL)
1583 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1584 if (sc->sc_isoc_out_pipe != NULL)
1585 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1586
1587 #if 0
1588 /* Cleanup queues */
1589 NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1590 NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1591 NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1592 #endif
1593 } /* ubt_reset */
1594
1595 /*
1596 * Process data
1597 */
1598 Static int
ubt_rcvdata(struct ubt_softc * sc,struct mbuf * m)1599 ubt_rcvdata(struct ubt_softc *sc, struct mbuf *m)
1600 {
1601 usbd_status (*f)(struct ubt_softc *) = NULL;
1602 struct ng_bt_mbufq *q = NULL;
1603 int b, error = 0;
1604
1605 if (sc == NULL) {
1606 error = EHOSTDOWN;
1607 goto done;
1608 }
1609
1610 #if 0
1611 if (hook != sc->sc_hook) {
1612 error = EINVAL;
1613 goto done;
1614 }
1615 #endif
1616
1617 #if 0
1618 /* Deatch mbuf and get HCI frame type */
1619 NGI_GET_M(item, m);
1620 #endif
1621
1622 /* Process HCI frame */
1623 switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
1624 case NG_HCI_CMD_PKT:
1625 f = ubt_request_start;
1626 q = &sc->sc_cmdq;
1627 b = UBT_CMD_XMIT;
1628 break;
1629
1630 case NG_HCI_ACL_DATA_PKT:
1631 f = ubt_bulk_out_start;
1632 q = &sc->sc_aclq;
1633 b = UBT_ACL_XMIT;
1634 break;
1635
1636 #if __broken__ /* XXX FIXME */
1637 case NG_HCI_SCO_DATA_PKT:
1638 f = ubt_isoc_out_start;
1639 q = &sc->sc_scoq;
1640 b = UBT_SCO_XMIT;
1641 break;
1642 #endif /* __broken__ */
1643
1644 default:
1645 NG_UBT_ERR(
1646 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
1647 __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
1648 m->m_pkthdr.len);
1649
1650 NG_FREE_M(m);
1651 error = EINVAL;
1652
1653 goto done;
1654 /* NOT REACHED */
1655 }
1656
1657 /* Loose frame type, if required */
1658 if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
1659 m_adj(m, sizeof(u_int8_t));
1660
1661 if (NG_BT_MBUFQ_FULL(q)) {
1662 NG_UBT_ERR(
1663 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
1664 __func__, USBDEVNAME(sc->sc_dev),
1665 *mtod(m, u_int8_t *), m->m_pkthdr.len);
1666
1667 NG_FREE_M(m);
1668 } else
1669 NG_BT_MBUFQ_ENQUEUE(q, m);
1670
1671 if (!(sc->sc_flags & b))
1672 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
1673 error = EIO;
1674 done:
1675 #if 0
1676 NG_FREE_ITEM(item);
1677 #endif
1678
1679 return (error);
1680 } /* ubt_rcvdata */
1681
1682 void
ubt_stop(struct ubt_softc * sc)1683 ubt_stop(struct ubt_softc *sc)
1684 {
1685 /* nothing yet */
1686 return;
1687 }
1688
1689 void
ubt_if_start(struct ifnet * ifp)1690 ubt_if_start(struct ifnet *ifp)
1691 {
1692 struct ubt_softc *sc = ifp->if_softc;
1693 struct mbuf *m0;
1694
1695 for (;;) {
1696 IFQ_POLL(&ifp->if_snd, m0);
1697 if (m0 == NULL)
1698 break;
1699
1700 IFQ_DEQUEUE(&ifp->if_snd, m0);
1701 ubt_rcvdata(sc, m0);
1702 }
1703 }
1704
1705 int
ubt_if_ioctl(struct ifnet * ifp,u_long command,caddr_t data)1706 ubt_if_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
1707 {
1708 struct ubt_softc *sc = ifp->if_softc;
1709 struct ifreq *ifr = (struct ifreq *)data;
1710 int s;
1711 int error = 0;
1712
1713 s = splimp();
1714 switch(command) {
1715 case SIOCSIFADDR:
1716 ifp->if_flags |= IFF_UP;
1717 ubt_if_init(ifp);
1718 break;
1719 case SIOCSIFMTU:
1720 if (ifr->ifr_mtu > 65536)
1721 error = EINVAL;
1722 ifp->if_mtu = ifr->ifr_mtu;
1723 break;
1724 case SIOCSIFFLAGS:
1725 if (ifp->if_flags & IFF_UP) {
1726 ubt_if_init(ifp);
1727 } else {
1728 if (ifp->if_flags & IFF_RUNNING)
1729 ubt_stop(sc);
1730 }
1731 error = 0;
1732 break;
1733 default:
1734 error = EINVAL;
1735 break;
1736 }
1737 splx(s);
1738
1739 return(error);
1740 }
1741
1742 int
ubt_if_init(struct ifnet * ifp)1743 ubt_if_init(struct ifnet *ifp)
1744 {
1745 /* nothing yet */
1746 return (0);
1747 }
1748
1749 void
ubt_if_watchdog(struct ifnet * ifp)1750 ubt_if_watchdog(struct ifnet *ifp)
1751 {
1752 /* nothing yet */
1753 return;
1754 }
1755