b8f17be83b976fd2fde46664e6d1103cb3c4e45e
[dragonfly.git] / sys / netgraph7 / bluetooth / drivers / ubt / ng_ubt.c
1 /*
2  * ng_ubt.c
3  */
4
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: ng_ubt.c,v 1.16 2003/10/10 19:15:06 max Exp $
31  * $FreeBSD: src/sys/netgraph/bluetooth/drivers/ubt/ng_ubt.c,v 1.33 2007/06/23 04:34:38 imp Exp $
32  */
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/bus.h>
37 #include <sys/conf.h>
38 #include <sys/endian.h>
39 #include <sys/filio.h>
40 #include <sys/fcntl.h>
41 #include <sys/mbuf.h>
42 #include <sys/malloc.h>
43 #include <sys/kernel.h>
44 #include <sys/module.h>
45 #include <sys/poll.h>
46 #include <sys/uio.h>
47 #include <machine/bus.h>
48
49 #include <dev/usb/usb.h>
50 #include <dev/usb/usbdi.h>
51 #include <dev/usb/usbdi_util.h>
52 #include <dev/usb/usbdivar.h>
53
54 #include <netgraph/ng_message.h>
55 #include <netgraph/netgraph.h>
56 #include <netgraph/ng_parse.h>
57 #include <netgraph/bluetooth/include/ng_bluetooth.h>
58 #include <netgraph/bluetooth/include/ng_hci.h>
59 #include <netgraph/bluetooth/include/ng_ubt.h>
60 #include <netgraph/bluetooth/drivers/ubt/ng_ubt_var.h>
61
62 #include "usbdevs.h"
63
64 /*
65  * USB methods
66  */
67
68 static device_probe_t ubt_match;
69 static device_attach_t ubt_attach;
70 static device_detach_t ubt_detach;
71
72 static device_method_t ubt_methods[] = {
73         /* Device interface */
74         DEVMETHOD(device_probe,         ubt_match),
75         DEVMETHOD(device_attach,        ubt_attach),
76         DEVMETHOD(device_detach,        ubt_detach),
77
78         { 0, 0 }
79 };
80
81 static driver_t ubt_driver = {
82         "ubt",
83         ubt_methods,
84         sizeof(struct ubt_softc)
85 };
86
87 static devclass_t ubt_devclass;
88
89 static int         ubt_modevent           (module_t, int, void *);
90
91 static usbd_status ubt_request_start      (ubt_softc_p);
92 static void        ubt_request_complete   (usbd_xfer_handle, 
93                                            usbd_private_handle, usbd_status);
94 static void        ubt_request_complete2  (node_p, hook_p, void *, int);
95
96 static usbd_status ubt_intr_start         (ubt_softc_p);
97 static void        ubt_intr_complete      (usbd_xfer_handle, 
98                                            usbd_private_handle, usbd_status);
99 static void        ubt_intr_complete2     (node_p, hook_p, void *, int); 
100
101 static usbd_status ubt_bulk_in_start      (ubt_softc_p);
102 static void        ubt_bulk_in_complete   (usbd_xfer_handle, 
103                                            usbd_private_handle, usbd_status);
104 static void        ubt_bulk_in_complete2  (node_p, hook_p, void *, int);
105
106 static usbd_status ubt_bulk_out_start     (ubt_softc_p);
107 static void        ubt_bulk_out_complete  (usbd_xfer_handle, 
108                                            usbd_private_handle, usbd_status);
109 static void        ubt_bulk_out_complete2 (node_p, hook_p, void *, int); 
110
111 static usbd_status ubt_isoc_in_start      (ubt_softc_p);
112 static void        ubt_isoc_in_complete   (usbd_xfer_handle, 
113                                            usbd_private_handle, usbd_status);
114 static void        ubt_isoc_in_complete2  (node_p, hook_p, void *, int);
115
116 static usbd_status ubt_isoc_out_start     (ubt_softc_p);
117 static void        ubt_isoc_out_complete  (usbd_xfer_handle, 
118                                            usbd_private_handle, usbd_status);
119 static void        ubt_isoc_out_complete2 (node_p, hook_p, void *, int);
120
121 static void        ubt_reset              (ubt_softc_p);
122
123 /*
124  * Netgraph methods
125  */
126
127 static ng_constructor_t ng_ubt_constructor;
128 static ng_shutdown_t    ng_ubt_shutdown;
129 static ng_newhook_t     ng_ubt_newhook;
130 static ng_connect_t     ng_ubt_connect;
131 static ng_disconnect_t  ng_ubt_disconnect;
132 static ng_rcvmsg_t      ng_ubt_rcvmsg;
133 static ng_rcvdata_t     ng_ubt_rcvdata;
134
135 /* Queue length */
136 static const struct ng_parse_struct_field       ng_ubt_node_qlen_type_fields[] =
137 {
138         { "queue", &ng_parse_int32_type, },
139         { "qlen",  &ng_parse_int32_type, },
140         { NULL, }
141 };
142 static const struct ng_parse_type               ng_ubt_node_qlen_type = {
143         &ng_parse_struct_type,
144         &ng_ubt_node_qlen_type_fields
145 };
146
147 /* Stat info */
148 static const struct ng_parse_struct_field       ng_ubt_node_stat_type_fields[] =
149 {
150         { "pckts_recv", &ng_parse_uint32_type, },
151         { "bytes_recv", &ng_parse_uint32_type, },
152         { "pckts_sent", &ng_parse_uint32_type, },
153         { "bytes_sent", &ng_parse_uint32_type, },
154         { "oerrors",    &ng_parse_uint32_type, },
155         { "ierrors",    &ng_parse_uint32_type, },
156         { NULL, }
157 };
158 static const struct ng_parse_type       ng_ubt_node_stat_type = {
159         &ng_parse_struct_type,
160         &ng_ubt_node_stat_type_fields
161 };
162
163 /* Netgraph node command list */
164 static const struct ng_cmdlist  ng_ubt_cmdlist[] = {
165 {
166         NGM_UBT_COOKIE,
167         NGM_UBT_NODE_SET_DEBUG,
168         "set_debug",
169         &ng_parse_uint16_type,
170         NULL
171 },
172 {
173         NGM_UBT_COOKIE,
174         NGM_UBT_NODE_GET_DEBUG,
175         "get_debug",
176         NULL,
177         &ng_parse_uint16_type
178 },
179 {
180         NGM_UBT_COOKIE,
181         NGM_UBT_NODE_SET_QLEN,
182         "set_qlen",
183         &ng_ubt_node_qlen_type,
184         NULL
185 },
186 {
187         NGM_UBT_COOKIE,
188         NGM_UBT_NODE_GET_QLEN,
189         "get_qlen",
190         &ng_ubt_node_qlen_type,
191         &ng_ubt_node_qlen_type
192 },
193 {
194         NGM_UBT_COOKIE,
195         NGM_UBT_NODE_GET_STAT,
196         "get_stat",
197         NULL,
198         &ng_ubt_node_stat_type
199 },
200 {
201         NGM_UBT_COOKIE,
202         NGM_UBT_NODE_RESET_STAT,
203         "reset_stat",
204         NULL,
205         NULL
206 },
207 { 0, }
208 };
209
210 /* Netgraph node type */
211 static struct ng_type   typestruct = {
212         .version =      NG_ABI_VERSION,
213         .name =         NG_UBT_NODE_TYPE,
214         .constructor =  ng_ubt_constructor,
215         .rcvmsg =       ng_ubt_rcvmsg,
216         .shutdown =     ng_ubt_shutdown,
217         .newhook =      ng_ubt_newhook,
218         .connect =      ng_ubt_connect,
219         .rcvdata =      ng_ubt_rcvdata,
220         .disconnect =   ng_ubt_disconnect,
221         .cmdlist =      ng_ubt_cmdlist  
222 };
223
224 /*
225  * Module
226  */
227
228 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
229 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
230 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
231 MODULE_DEPEND(ubt, usb, 1, 1, 1);
232
233
234 /****************************************************************************
235  ****************************************************************************
236  **                              USB specific
237  ****************************************************************************
238  ****************************************************************************/
239
240 /*
241  * Load/Unload the driver module
242  */
243
244 static int
245 ubt_modevent(module_t mod, int event, void *data)
246 {
247         int     error;
248
249         switch (event) {
250         case MOD_LOAD:
251                 error = ng_newtype(&typestruct);
252                 if (error != 0)
253                         printf(
254 "%s: Could not register Netgraph node type, error=%d\n",
255                                 NG_UBT_NODE_TYPE, error);
256                 else
257                         error = usbd_driver_load(mod, event, data);
258                 break;
259
260         case MOD_UNLOAD:
261                 error = ng_rmtype(&typestruct);
262                 if (error == 0)
263                         error = usbd_driver_load(mod, event, data);
264                 break;
265
266         default:
267                 error = EOPNOTSUPP;
268                 break;
269         }
270
271         return (error);
272 } /* ubt_modevent */
273
274 /*
275  * Probe for a USB Bluetooth device
276  */
277
278 static int
279 ubt_match(device_t self)
280 {
281         /*
282          * If for some reason device should not be attached then put
283          * VendorID/ProductID pair into the list below. The format is
284          * as follows:
285          *
286          *      { VENDOR_ID, PRODUCT_ID },
287          *
288          * where VENDOR_ID and PRODUCT_ID are hex numbers.
289          */
290
291         static struct usb_devno const   ubt_ignored_devices[] = {
292                 { USB_VENDOR_AVM, 0x2200 }, /* AVM USB Bluetooth-Adapter BlueFritz! v1.0 */
293                 { 0, 0 } /* This should be the last item in the list */
294         };
295
296         /*
297          * If device violates Bluetooth specification and has bDeviceClass,
298          * bDeviceSubClass and bDeviceProtocol set to wrong values then you
299          * could try to put VendorID/ProductID pair into the list below.
300          * Adding VendorID/ProductID pair into this list forces ng_ubt(4)
301          * to attach to the broken device.
302          */
303
304         static struct usb_devno const   ubt_broken_devices[] = {
305                 { USB_VENDOR_AVM, 0x3800 }, /* AVM USB Bluetooth-Adapter BlueFritz! v2.0 */
306                 { 0, 0 } /* This should be the last item in the list */
307         };
308
309         struct usb_attach_arg *uaa = device_get_ivars(self);
310         usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
311
312         if (uaa->iface == NULL ||
313             usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
314                 return (UMATCH_NONE);
315         
316         if (dd->bDeviceClass == UDCLASS_WIRELESS &&
317             dd->bDeviceSubClass == UDSUBCLASS_RF &&
318             dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
319                 return (UMATCH_DEVCLASS_DEVSUBCLASS);
320
321         if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
322                 return (UMATCH_VENDOR_PRODUCT);
323
324         return (UMATCH_NONE);
325 } /* ubt_match */
326
327 /*
328  * Attach the device
329  */
330
331 static int
332 ubt_attach(device_t self)
333 {
334         struct ubt_softc *sc = device_get_softc(self);
335         struct usb_attach_arg *uaa = device_get_ivars(self);
336         usb_config_descriptor_t         *cd = NULL;
337         usb_interface_descriptor_t      *id = NULL;
338         usb_endpoint_descriptor_t       *ed = NULL;
339         usbd_status                      error;
340         int                              i, ai, alt_no, isoc_in, isoc_out,
341                                          isoc_isize, isoc_osize;
342
343         /* Get USB device info */
344         sc->sc_dev = self;
345         sc->sc_udev = uaa->device;
346
347         /* 
348          * Initialize device softc structure
349          */
350
351         /* State */
352         sc->sc_debug = NG_UBT_WARN_LEVEL;
353         sc->sc_flags = 0;
354         NG_UBT_STAT_RESET(sc->sc_stat);
355
356         /* Interfaces */
357         sc->sc_iface0 = sc->sc_iface1 = NULL;
358
359         /* Interrupt pipe */
360         sc->sc_intr_ep = -1;
361         sc->sc_intr_pipe = NULL;
362         sc->sc_intr_xfer = NULL;
363         sc->sc_intr_buffer = NULL;
364
365         /* Control pipe */
366         sc->sc_ctrl_xfer = NULL;
367         sc->sc_ctrl_buffer = NULL;
368         NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
369
370         /* Bulk-in pipe */
371         sc->sc_bulk_in_ep = -1;
372         sc->sc_bulk_in_pipe = NULL;
373         sc->sc_bulk_in_xfer = NULL;
374         sc->sc_bulk_in_buffer = NULL;
375
376         /* Bulk-out pipe */
377         sc->sc_bulk_out_ep = -1;
378         sc->sc_bulk_out_pipe = NULL;
379         sc->sc_bulk_out_xfer = NULL;
380         sc->sc_bulk_out_buffer = NULL;
381         NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
382
383         /* Isoc-in pipe */
384         sc->sc_isoc_in_ep = -1;
385         sc->sc_isoc_in_pipe = NULL;
386         sc->sc_isoc_in_xfer = NULL;
387
388         /* Isoc-out pipe */
389         sc->sc_isoc_out_ep = -1;
390         sc->sc_isoc_out_pipe = NULL;
391         sc->sc_isoc_out_xfer = NULL;
392         sc->sc_isoc_size = -1;
393         NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
394
395         /* Netgraph part */
396         sc->sc_node = NULL;
397         sc->sc_hook = NULL;
398
399         /*
400          * XXX set configuration?
401          *
402          * Configure Bluetooth USB device. Discover all required USB interfaces
403          * and endpoints.
404          *
405          * USB device must present two interfaces:
406          * 1) Interface 0 that has 3 endpoints
407          *      1) Interrupt endpoint to receive HCI events
408          *      2) Bulk IN endpoint to receive ACL data
409          *      3) Bulk OUT endpoint to send ACL data
410          *
411          * 2) Interface 1 then has 2 endpoints
412          *      1) Isochronous IN endpoint to receive SCO data
413          *      2) Isochronous OUT endpoint to send SCO data
414          *
415          * Interface 1 (with isochronous endpoints) has several alternate 
416          * configurations with different packet size.
417          */
418
419         /*
420          * Interface 0
421          */
422
423         error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
424         if (error || sc->sc_iface0 == NULL) {
425                 printf("%s: Could not get interface 0 handle. %s (%d), " \
426                         "handle=%p\n", device_get_nameunit(sc->sc_dev),
427                         usbd_errstr(error), error, sc->sc_iface0);
428                 goto bad;
429         }
430
431         id = usbd_get_interface_descriptor(sc->sc_iface0);
432         if (id == NULL) {
433                 printf("%s: Could not get interface 0 descriptor\n",
434                         device_get_nameunit(sc->sc_dev));
435                 goto bad;
436         }
437
438         for (i = 0; i < id->bNumEndpoints; i ++) {
439                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
440                 if (ed == NULL) {
441                         printf("%s: Could not read endpoint descriptor for " \
442                                 "interface 0, i=%d\n", device_get_nameunit(sc->sc_dev),
443                                 i);
444                         goto bad;
445                 }
446
447                 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
448                 case UE_BULK:
449                         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
450                                 sc->sc_bulk_in_ep = ed->bEndpointAddress;
451                         else
452                                 sc->sc_bulk_out_ep = ed->bEndpointAddress;
453                         break;
454
455                 case UE_INTERRUPT:
456                         sc->sc_intr_ep = ed->bEndpointAddress;
457                         break;
458                 }
459         }
460
461         /* Check if we got everything we wanted on Interface 0 */
462         if (sc->sc_intr_ep == -1) {
463                 printf("%s: Could not detect interrupt endpoint\n",
464                         device_get_nameunit(sc->sc_dev));
465                 goto bad;
466         }
467         if (sc->sc_bulk_in_ep == -1) {
468                 printf("%s: Could not detect bulk-in endpoint\n",
469                         device_get_nameunit(sc->sc_dev));
470                 goto bad;
471         }
472         if (sc->sc_bulk_out_ep == -1) {
473                 printf("%s: Could not detect bulk-out endpoint\n",
474                         device_get_nameunit(sc->sc_dev));
475                 goto bad;
476         }
477
478         printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
479                 "bulk-out=%#x\n", device_get_nameunit(sc->sc_dev), 
480                 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
481
482         /*
483          * Interface 1
484          */
485
486         cd = usbd_get_config_descriptor(sc->sc_udev);
487         if (cd == NULL) {
488                 printf("%s: Could not get device configuration descriptor\n",
489                         device_get_nameunit(sc->sc_dev));
490                 goto bad;
491         }
492
493         error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
494         if (error || sc->sc_iface1 == NULL) {
495                 printf("%s: Could not get interface 1 handle. %s (%d), " \
496                         "handle=%p\n", device_get_nameunit(sc->sc_dev), 
497                         usbd_errstr(error), error, sc->sc_iface1);
498                 goto bad;
499         }
500
501         id = usbd_get_interface_descriptor(sc->sc_iface1);
502         if (id == NULL) {
503                 printf("%s: Could not get interface 1 descriptor\n",
504                         device_get_nameunit(sc->sc_dev));
505                 goto bad;
506         }
507
508         /*
509          * Scan all alternate configurations for interface 1
510          */
511
512         alt_no = -1;
513
514         for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++)  {
515                 error = usbd_set_interface(sc->sc_iface1, ai);
516                 if (error) {
517                         printf("%s: [SCAN] Could not set alternate " \
518                                 "configuration %d for interface 1. %s (%d)\n",
519                                 device_get_nameunit(sc->sc_dev),  ai, usbd_errstr(error),
520                                 error);
521                         goto bad;
522                 }
523                 id = usbd_get_interface_descriptor(sc->sc_iface1);
524                 if (id == NULL) {
525                         printf("%s: Could not get interface 1 descriptor for " \
526                                 "alternate configuration %d\n",
527                                 device_get_nameunit(sc->sc_dev), ai);
528                         goto bad;
529                 }
530
531                 isoc_in = isoc_out = -1;
532                 isoc_isize = isoc_osize = 0;
533
534                 for (i = 0; i < id->bNumEndpoints; i ++) {
535                         ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
536                         if (ed == NULL) {
537                                 printf("%s: Could not read endpoint " \
538                                         "descriptor for interface 1, " \
539                                         "alternate configuration %d, i=%d\n",
540                                         device_get_nameunit(sc->sc_dev), ai, i);
541                                 goto bad;
542                         }
543
544                         if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
545                                 continue;
546
547                         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
548                                 isoc_in = ed->bEndpointAddress;
549                                 isoc_isize = UGETW(ed->wMaxPacketSize);
550                         } else {
551                                 isoc_out = ed->bEndpointAddress;
552                                 isoc_osize = UGETW(ed->wMaxPacketSize);
553                         }
554                 }
555
556                 /*
557                  * Make sure that configuration looks sane and if so
558                  * update current settings
559                  */
560
561                 if (isoc_in != -1 && isoc_out != -1 &&
562                     isoc_isize > 0  && isoc_osize > 0 &&
563                     isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
564                         sc->sc_isoc_in_ep = isoc_in;
565                         sc->sc_isoc_out_ep = isoc_out;
566                         sc->sc_isoc_size = isoc_isize;
567                         alt_no = ai;
568                 }
569         }
570
571         /* Check if we got everything we wanted on Interface 0 */
572         if (sc->sc_isoc_in_ep == -1) {
573                 printf("%s: Could not detect isoc-in endpoint\n",
574                         device_get_nameunit(sc->sc_dev));
575                 goto bad;
576         }
577         if (sc->sc_isoc_out_ep == -1) {
578                 printf("%s: Could not detect isoc-out endpoint\n",
579                         device_get_nameunit(sc->sc_dev));
580                 goto bad;
581         }
582         if (sc->sc_isoc_size <= 0) {
583                 printf("%s: Invalid isoc. packet size=%d\n",
584                         device_get_nameunit(sc->sc_dev), sc->sc_isoc_size);
585                 goto bad;
586         }
587
588         error = usbd_set_interface(sc->sc_iface1, alt_no);
589         if (error) {
590                 printf("%s: Could not set alternate configuration " \
591                         "%d for interface 1. %s (%d)\n", device_get_nameunit(sc->sc_dev),
592                         alt_no, usbd_errstr(error), error);
593                 goto bad;
594         }
595
596         /* Allocate USB transfer handles and buffers */
597         sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
598         if (sc->sc_ctrl_xfer == NULL) {
599                 printf("%s: Could not allocate control xfer handle\n",
600                         device_get_nameunit(sc->sc_dev));
601                 goto bad;
602         }
603         sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer, 
604                                                 UBT_CTRL_BUFFER_SIZE);
605         if (sc->sc_ctrl_buffer == NULL) {
606                 printf("%s: Could not allocate control buffer\n",
607                         device_get_nameunit(sc->sc_dev));
608                 goto bad;
609         }
610
611         sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
612         if (sc->sc_intr_xfer == NULL) {
613                 printf("%s: Could not allocate interrupt xfer handle\n",
614                         device_get_nameunit(sc->sc_dev));
615                 goto bad;
616         }
617
618         sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
619         if (sc->sc_bulk_in_xfer == NULL) {
620                 printf("%s: Could not allocate bulk-in xfer handle\n",
621                         device_get_nameunit(sc->sc_dev));
622                 goto bad;
623         }
624
625         sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
626         if (sc->sc_bulk_out_xfer == NULL) {
627                 printf("%s: Could not allocate bulk-out xfer handle\n",
628                         device_get_nameunit(sc->sc_dev));
629                 goto bad;
630         }
631         sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
632                                                 UBT_BULK_BUFFER_SIZE);
633         if (sc->sc_bulk_out_buffer == NULL) {
634                 printf("%s: Could not allocate bulk-out buffer\n",
635                         device_get_nameunit(sc->sc_dev));
636                 goto bad;
637         }
638
639         /*
640          * Allocate buffers for isoc. transfers
641          */
642
643         sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
644
645         sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
646         if (sc->sc_isoc_in_xfer == NULL) {
647                 printf("%s: Could not allocate isoc-in xfer handle\n",
648                         device_get_nameunit(sc->sc_dev));
649                 goto bad;
650         }
651         sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
652                                         sc->sc_isoc_nframes * sc->sc_isoc_size);
653         if (sc->sc_isoc_in_buffer == NULL) {
654                 printf("%s: Could not allocate isoc-in buffer\n",
655                         device_get_nameunit(sc->sc_dev));
656                 goto bad;
657         }
658         sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 
659                                                 M_USBDEV, M_NOWAIT);
660         if (sc->sc_isoc_in_frlen == NULL) {
661                 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
662                         device_get_nameunit(sc->sc_dev));
663                 goto bad;
664         }
665
666         sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
667         if (sc->sc_isoc_out_xfer == NULL) {
668                 printf("%s: Could not allocate isoc-out xfer handle\n",
669                         device_get_nameunit(sc->sc_dev));
670                 goto bad;
671         }
672         sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
673                                         sc->sc_isoc_nframes * sc->sc_isoc_size);
674         if (sc->sc_isoc_out_buffer == NULL) {
675                 printf("%s: Could not allocate isoc-out buffer\n",
676                         device_get_nameunit(sc->sc_dev));
677                 goto bad;
678         }
679         sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 
680                                                 M_USBDEV, M_NOWAIT);
681         if (sc->sc_isoc_out_frlen == NULL) {
682                 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
683                         device_get_nameunit(sc->sc_dev));
684                 goto bad;
685         }
686
687         printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
688                 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
689                 device_get_nameunit(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
690                 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes, 
691                 (sc->sc_isoc_nframes * sc->sc_isoc_size));
692
693         /*
694          * Open pipes
695          */
696
697         /* Interrupt */ 
698         error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
699                         USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
700         if (error != USBD_NORMAL_COMPLETION) {
701                 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
702                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
703                         error);
704                 goto bad;
705         }
706
707         /* Bulk-in */
708         error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
709                         USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
710         if (error != USBD_NORMAL_COMPLETION) {
711                 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
712                         __func__,  device_get_nameunit(sc->sc_dev), usbd_errstr(error),
713                         error);
714                 goto bad;
715         }
716
717         /* Bulk-out */
718         error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
719                         USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
720         if (error != USBD_NORMAL_COMPLETION) {
721                 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
722                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
723                         error);
724                 goto bad;
725         }
726
727 #if 0 /* XXX FIXME */
728         /* Isoc-in */
729         error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
730                         USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
731         if (error != USBD_NORMAL_COMPLETION) {
732                 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
733                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
734                         error);
735                 goto bad;
736         }
737
738         /* Isoc-out */
739         error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep, 
740                         USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
741         if (error != USBD_NORMAL_COMPLETION) {
742                 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
743                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(error),
744                         error);
745                 goto bad;
746         }
747 #endif
748
749         /* Create Netgraph node */
750         if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
751                 printf("%s: Could not create Netgraph node\n",
752                         device_get_nameunit(sc->sc_dev));
753                 sc->sc_node = NULL;
754                 goto bad;
755         }
756
757         /* Name node */
758         if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
759                 printf("%s: Could not name Netgraph node\n",
760                         device_get_nameunit(sc->sc_dev));
761                 NG_NODE_UNREF(sc->sc_node);
762                 sc->sc_node = NULL;
763                 goto bad;
764         }
765
766         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
767         NG_NODE_FORCE_WRITER(sc->sc_node);
768
769         /* Claim all interfaces on the device */
770         for (i = 0; i < uaa->nifaces; i++)
771                 uaa->ifaces[i] = NULL;
772
773         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
774                 sc->sc_dev);
775
776         return 0;
777 bad:
778         ubt_detach(self);
779
780         return ENXIO;
781 } /* ubt_attach */
782
783 /*
784  * Detach the device
785  */
786
787 static int
788 ubt_detach(device_t self)
789 {
790         struct ubt_softc *sc = device_get_softc(self);
791
792         /* Destroy Netgraph node */
793         if (sc->sc_node != NULL) {
794                 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
795                 ng_rmnode_self(sc->sc_node);
796                 sc->sc_node = NULL;
797         }
798
799         /* Close pipes */
800         if (sc->sc_intr_pipe != NULL) {
801                 usbd_close_pipe(sc->sc_intr_pipe);
802                 sc->sc_intr_pipe = NULL;
803         }
804
805         if (sc->sc_bulk_in_pipe != NULL) {
806                 usbd_close_pipe(sc->sc_bulk_in_pipe);
807                 sc->sc_bulk_in_pipe = NULL;
808         }
809         if (sc->sc_bulk_out_pipe != NULL) {
810                 usbd_close_pipe(sc->sc_bulk_out_pipe);
811                 sc->sc_bulk_out_pipe = NULL;
812         }
813
814         if (sc->sc_isoc_in_pipe != NULL) {
815                 usbd_close_pipe(sc->sc_isoc_in_pipe);
816                 sc->sc_isoc_in_pipe = NULL;
817         }
818         if (sc->sc_isoc_out_pipe != NULL) {
819                 usbd_close_pipe(sc->sc_isoc_out_pipe);
820                 sc->sc_isoc_out_pipe = NULL;
821         }
822
823         /* Destroy USB transfer handles */
824         if (sc->sc_ctrl_xfer != NULL) {
825                 usbd_free_xfer(sc->sc_ctrl_xfer);
826                 sc->sc_ctrl_xfer = NULL;
827         }
828
829         if (sc->sc_intr_xfer != NULL) {
830                 usbd_free_xfer(sc->sc_intr_xfer);
831                 sc->sc_intr_xfer = NULL;
832         }
833
834         if (sc->sc_bulk_in_xfer != NULL) {
835                 usbd_free_xfer(sc->sc_bulk_in_xfer);
836                 sc->sc_bulk_in_xfer = NULL;
837         }
838         if (sc->sc_bulk_out_xfer != NULL) {
839                 usbd_free_xfer(sc->sc_bulk_out_xfer);
840                 sc->sc_bulk_out_xfer = NULL;
841         }
842
843         if (sc->sc_isoc_in_xfer != NULL) {
844                 usbd_free_xfer(sc->sc_isoc_in_xfer);
845                 sc->sc_isoc_in_xfer = NULL;
846         }
847         if (sc->sc_isoc_out_xfer != NULL) {
848                 usbd_free_xfer(sc->sc_isoc_out_xfer);
849                 sc->sc_isoc_out_xfer = NULL;
850         }
851
852         /* Destroy isoc. frame size buffers */
853         if (sc->sc_isoc_in_frlen != NULL) {
854                 free(sc->sc_isoc_in_frlen, M_USBDEV);
855                 sc->sc_isoc_in_frlen = NULL;
856         }
857         if (sc->sc_isoc_out_frlen != NULL) {
858                 free(sc->sc_isoc_out_frlen, M_USBDEV);
859                 sc->sc_isoc_out_frlen = NULL;
860         }
861
862         /* Destroy queues */
863         NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
864         NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
865         NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
866
867         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
868                         sc->sc_dev);
869
870         return (0);
871 } /* ubt_detach */
872
873 /*
874  * Start USB control request (HCI command). Must be called with node locked
875  */
876
877 static usbd_status
878 ubt_request_start(ubt_softc_p sc)
879 {
880         usb_device_request_t     req;
881         struct mbuf             *m = NULL;
882         usbd_status              status;
883
884         KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
885 "%s: %s - Another control request is pending\n",
886                 __func__, device_get_nameunit(sc->sc_dev)));
887
888         NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
889         if (m == NULL) {
890                 NG_UBT_INFO(
891 "%s: %s - HCI command queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
892
893                 return (USBD_NORMAL_COMPLETION);
894         }
895
896         /*
897          * Check HCI command frame size and copy it back to 
898          * linear USB transfer buffer.
899          */ 
900
901         if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
902                 panic(
903 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
904                         __func__, device_get_nameunit(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
905                         m->m_pkthdr.len);
906
907         m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
908
909         /* Initialize a USB control request and then schedule it */
910         bzero(&req, sizeof(req));
911         req.bmRequestType = UBT_HCI_REQUEST;
912         USETW(req.wLength, m->m_pkthdr.len);
913
914         NG_UBT_INFO(
915 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
916                 __func__, device_get_nameunit(sc->sc_dev), req.bmRequestType,
917                 UGETW(req.wLength));
918
919         usbd_setup_default_xfer(
920                 sc->sc_ctrl_xfer,
921                 sc->sc_udev,
922                 (usbd_private_handle) sc->sc_node,
923                 USBD_DEFAULT_TIMEOUT, /* XXX */
924                 &req,
925                 sc->sc_ctrl_buffer,
926                 m->m_pkthdr.len,
927                 USBD_NO_COPY,
928                 ubt_request_complete);
929
930         NG_NODE_REF(sc->sc_node);
931
932         status = usbd_transfer(sc->sc_ctrl_xfer);
933         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
934                 NG_UBT_ERR(
935 "%s: %s - Could not start control request. %s (%d)\n",
936                         __func__, device_get_nameunit(sc->sc_dev),
937                         usbd_errstr(status), status);
938
939                 NG_NODE_UNREF(sc->sc_node);
940
941                 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
942                 NG_UBT_STAT_OERROR(sc->sc_stat);
943
944                 /* XXX FIXME should we try to resubmit another request? */
945         } else {
946                 NG_UBT_INFO(
947 "%s: %s - Control request has been started\n",
948                         __func__, device_get_nameunit(sc->sc_dev));
949
950                 sc->sc_flags |= UBT_CMD_XMIT;
951                 status = USBD_NORMAL_COMPLETION;
952         }
953
954         NG_FREE_M(m);
955
956         return (status);
957 } /* ubt_request_start */
958
959 /*
960  * USB control request callback
961  */
962
963 static void
964 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
965 {
966         ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
967         NG_NODE_UNREF((node_p) p);
968 } /* ubt_request_complete */
969
970 static void
971 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
972
973         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
974         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
975         usbd_status             s = (usbd_status) arg2;
976
977         if (sc == NULL)
978                 return;
979
980         KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
981 "%s: %s - No control request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
982
983         sc->sc_flags &= ~UBT_CMD_XMIT;
984
985         if (s == USBD_CANCELLED) {
986                 NG_UBT_INFO(
987 "%s: %s - Control request cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
988
989                 return;
990         }
991
992         if (s != USBD_NORMAL_COMPLETION) {    
993                 NG_UBT_ERR(
994 "%s: %s - Control request failed. %s (%d)\n",
995                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
996
997                 if (s == USBD_STALLED)
998                         usbd_clear_endpoint_stall_async(h->pipe);
999
1000                 NG_UBT_STAT_OERROR(sc->sc_stat);
1001         } else {
1002                 NG_UBT_INFO(
1003 "%s: %s - Sent %d bytes to control pipe\n",
1004                         __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1005
1006                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1007                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1008         }
1009
1010         if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1011                 ubt_request_start(sc);
1012 } /* ubt_request_complete2 */
1013
1014 /*
1015  * Start interrupt transfer. Must be called when node is locked
1016  */
1017
1018 static usbd_status
1019 ubt_intr_start(ubt_softc_p sc)
1020 {
1021         struct mbuf     *m = NULL;
1022         usbd_status      status;
1023
1024         KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1025 "%s: %s - Another interrupt request is pending\n",
1026                 __func__, device_get_nameunit(sc->sc_dev)));
1027
1028         /* Allocate new mbuf cluster */
1029         MGETHDR(m, M_DONTWAIT, MT_DATA);
1030         if (m == NULL)
1031                 return (USBD_NOMEM);
1032
1033         MCLGET(m, M_DONTWAIT);
1034         if (!(m->m_flags & M_EXT)) {
1035                 NG_FREE_M(m);
1036                 return (USBD_NOMEM);
1037         }
1038
1039         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1040                 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1041                 m->m_pkthdr.len = m->m_len = 1;
1042         } else
1043                 m->m_pkthdr.len = m->m_len = 0;
1044         
1045         /* Initialize a USB transfer and then schedule it */
1046         usbd_setup_xfer(
1047                         sc->sc_intr_xfer,
1048                         sc->sc_intr_pipe,
1049                         (usbd_private_handle) sc->sc_node,
1050                         (void *)(mtod(m, u_int8_t *) + m->m_len),
1051                         MCLBYTES - m->m_len,
1052                         USBD_SHORT_XFER_OK,
1053                         USBD_NO_TIMEOUT,
1054                         ubt_intr_complete);
1055
1056         NG_NODE_REF(sc->sc_node);
1057
1058         status = usbd_transfer(sc->sc_intr_xfer);
1059         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1060                 NG_UBT_ERR(
1061 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1062                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1063                         status);
1064
1065                 NG_NODE_UNREF(sc->sc_node);
1066
1067                 NG_FREE_M(m);
1068
1069                 return (status);
1070         }
1071
1072         sc->sc_flags |= UBT_EVT_RECV;
1073         sc->sc_intr_buffer = m;
1074
1075         return (USBD_NORMAL_COMPLETION);
1076 } /* ubt_intr_start */
1077
1078 /*
1079  * Process interrupt from USB device (We got data from interrupt pipe)
1080  */
1081
1082 static void
1083 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1084 {
1085         ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1086         NG_NODE_UNREF((node_p) p);
1087 } /* ubt_intr_complete */
1088
1089 static void
1090 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1091 {
1092         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1093         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1094         usbd_status              s = (usbd_status) arg2;
1095         struct mbuf             *m = NULL;
1096         ng_hci_event_pkt_t      *hdr = NULL;
1097         int                      error;
1098
1099         if (sc == NULL)
1100                 return;
1101
1102         KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1103 "%s: %s - No interrupt request is pending\n",
1104                 __func__, device_get_nameunit(sc->sc_dev)));
1105
1106         sc->sc_flags &= ~UBT_EVT_RECV;
1107
1108         m = sc->sc_intr_buffer;
1109         sc->sc_intr_buffer = NULL;
1110
1111         hdr = mtod(m, ng_hci_event_pkt_t *);
1112
1113         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1114                 NG_UBT_INFO(
1115 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1116
1117                 NG_FREE_M(m);
1118                 return;
1119         }
1120
1121         if (s == USBD_CANCELLED) {
1122                 NG_UBT_INFO(
1123 "%s: %s - Interrupt xfer cancelled\n", __func__, device_get_nameunit(sc->sc_dev));
1124
1125                 NG_FREE_M(m);
1126                 return;
1127         }
1128                 
1129         if (s != USBD_NORMAL_COMPLETION) {    
1130                 NG_UBT_WARN(
1131 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1132                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1133
1134                 if (s == USBD_STALLED)
1135                         usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1136
1137                 NG_UBT_STAT_IERROR(sc->sc_stat);
1138                 NG_FREE_M(m);
1139
1140                 return; /* XXX FIXME we should restart after some delay */
1141         }
1142
1143         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1144         m->m_pkthdr.len += h->actlen;
1145         m->m_len += h->actlen;
1146
1147         NG_UBT_INFO(
1148 "%s: %s - Got %d bytes from interrupt pipe\n",
1149                 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1150
1151         if (m->m_pkthdr.len < sizeof(*hdr)) {
1152                 NG_FREE_M(m);
1153                 goto done;
1154         }
1155
1156         if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1157                 NG_UBT_INFO(
1158 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1159                         __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1160                         hdr->length);
1161
1162                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1163
1164                 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1165                 if (error != 0)
1166                         NG_UBT_STAT_IERROR(sc->sc_stat);
1167         } else {
1168                 NG_UBT_ERR(
1169 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1170                         __func__, device_get_nameunit(sc->sc_dev), hdr->length, 
1171                         m->m_pkthdr.len);
1172
1173                 NG_UBT_STAT_IERROR(sc->sc_stat);
1174                 NG_FREE_M(m);
1175         }
1176 done:
1177         ubt_intr_start(sc);
1178 } /* ubt_intr_complete2 */
1179
1180 /*
1181  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1182  */
1183
1184 static usbd_status
1185 ubt_bulk_in_start(ubt_softc_p sc)
1186 {
1187         struct mbuf     *m = NULL;
1188         usbd_status      status;
1189
1190         KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1191 "%s: %s - Another bulk-in request is pending\n",
1192                 __func__, device_get_nameunit(sc->sc_dev)));
1193
1194         /* Allocate new mbuf cluster */
1195         MGETHDR(m, M_DONTWAIT, MT_DATA);
1196         if (m == NULL)
1197                 return (USBD_NOMEM);
1198
1199         MCLGET(m, M_DONTWAIT);
1200         if (!(m->m_flags & M_EXT)) {
1201                 NG_FREE_M(m);
1202                 return (USBD_NOMEM);
1203         }
1204
1205         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1206                 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1207                 m->m_pkthdr.len = m->m_len = 1;
1208         } else
1209                 m->m_pkthdr.len = m->m_len = 0;
1210         
1211         /* Initialize a bulk-in USB transfer and then schedule it */
1212         usbd_setup_xfer(
1213                         sc->sc_bulk_in_xfer,
1214                         sc->sc_bulk_in_pipe,
1215                         (usbd_private_handle) sc->sc_node,
1216                         (void *)(mtod(m, u_int8_t *) + m->m_len),
1217                         MCLBYTES - m->m_len,
1218                         USBD_SHORT_XFER_OK,
1219                         USBD_NO_TIMEOUT,
1220                         ubt_bulk_in_complete);
1221
1222         NG_NODE_REF(sc->sc_node);
1223
1224         status = usbd_transfer(sc->sc_bulk_in_xfer);
1225         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1226                 NG_UBT_ERR(
1227 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1228                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1229                         status);
1230
1231                 NG_NODE_UNREF(sc->sc_node);
1232
1233                 NG_FREE_M(m);
1234
1235                 return (status);
1236         }
1237
1238         sc->sc_flags |= UBT_ACL_RECV;
1239         sc->sc_bulk_in_buffer = m;
1240
1241         return (USBD_NORMAL_COMPLETION);
1242 } /* ubt_bulk_in_start */
1243
1244 /*
1245  * USB bulk-in transfer callback
1246  */
1247
1248 static void
1249 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1250 {
1251         ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1252         NG_NODE_UNREF((node_p) p);
1253 } /* ubt_bulk_in_complete */
1254
1255 static void
1256 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1257 {
1258         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1259         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1260         usbd_status              s = (usbd_status) arg2;
1261         struct mbuf             *m = NULL;
1262         ng_hci_acldata_pkt_t    *hdr = NULL;
1263         int                      len;
1264
1265         if (sc == NULL)
1266                 return;
1267
1268         KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1269 "%s: %s - No bulk-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1270
1271         sc->sc_flags &= ~UBT_ACL_RECV;
1272
1273         m = sc->sc_bulk_in_buffer;
1274         sc->sc_bulk_in_buffer = NULL;
1275
1276         hdr = mtod(m, ng_hci_acldata_pkt_t *);
1277
1278         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1279                 NG_UBT_INFO(
1280 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1281
1282                 NG_FREE_M(m);
1283                 return;
1284         }
1285
1286         if (s == USBD_CANCELLED) {
1287                 NG_UBT_INFO(
1288 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1289                         __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_in_pipe);
1290
1291                 NG_FREE_M(m);
1292                 return;
1293         }
1294
1295         if (s != USBD_NORMAL_COMPLETION) {    
1296                 NG_UBT_WARN(
1297 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1298                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1299
1300                 if (s == USBD_STALLED)
1301                         usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1302
1303                 NG_UBT_STAT_IERROR(sc->sc_stat);
1304                 NG_FREE_M(m);
1305
1306                 return; /* XXX FIXME we should restart after some delay */
1307         }
1308
1309         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1310         m->m_pkthdr.len += h->actlen;
1311         m->m_len += h->actlen;
1312
1313         NG_UBT_INFO(
1314 "%s: %s - Got %d bytes from bulk-in pipe\n",
1315                 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1316
1317         if (m->m_pkthdr.len < sizeof(*hdr)) {
1318                 NG_FREE_M(m);
1319                 goto done;
1320         }
1321
1322         len = le16toh(hdr->length);
1323         if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1324                 NG_UBT_INFO(
1325 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1326                         __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len, len);
1327
1328                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1329
1330                 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1331                 if (len != 0)
1332                         NG_UBT_STAT_IERROR(sc->sc_stat);
1333         } else {
1334                 NG_UBT_ERR(
1335 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1336                         __func__, device_get_nameunit(sc->sc_dev), len,
1337                         m->m_pkthdr.len);
1338
1339                 NG_UBT_STAT_IERROR(sc->sc_stat);
1340                 NG_FREE_M(m);
1341         }
1342 done:
1343         ubt_bulk_in_start(sc);
1344 } /* ubt_bulk_in_complete2 */
1345
1346 /*
1347  * Start bulk-out USB transfer. Must be called with node locked
1348  */
1349
1350 static usbd_status
1351 ubt_bulk_out_start(ubt_softc_p sc)
1352 {
1353         struct mbuf     *m = NULL;
1354         usbd_status     status;
1355
1356         KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1357 "%s: %s - Another bulk-out request is pending\n",
1358                 __func__, device_get_nameunit(sc->sc_dev)));
1359
1360         NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1361         if (m == NULL) {
1362                 NG_UBT_INFO(
1363 "%s: %s - ACL data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1364
1365                 return (USBD_NORMAL_COMPLETION);
1366         }
1367
1368         /*
1369          * Check ACL data frame size and copy it back to linear USB 
1370          * transfer buffer.
1371          */ 
1372
1373         if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1374                 panic(
1375 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1376                         __func__, device_get_nameunit(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1377                         m->m_pkthdr.len);
1378
1379         m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1380
1381         /* Initialize a bulk-out USB transfer and then schedule it */
1382         usbd_setup_xfer(
1383                         sc->sc_bulk_out_xfer,
1384                         sc->sc_bulk_out_pipe,
1385                         (usbd_private_handle) sc->sc_node,
1386                         sc->sc_bulk_out_buffer,
1387                         m->m_pkthdr.len,
1388                         USBD_NO_COPY,
1389                         USBD_DEFAULT_TIMEOUT, /* XXX */
1390                         ubt_bulk_out_complete);
1391
1392         NG_NODE_REF(sc->sc_node);
1393
1394         status = usbd_transfer(sc->sc_bulk_out_xfer);
1395         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1396                 NG_UBT_ERR(
1397 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1398                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1399                         status);
1400
1401                 NG_NODE_UNREF(sc->sc_node);
1402
1403                 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1404                 NG_UBT_STAT_OERROR(sc->sc_stat);
1405
1406                 /* XXX FIXME should we try to start another transfer? */
1407         } else {
1408                 NG_UBT_INFO(
1409 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1410                         __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len);
1411
1412                 sc->sc_flags |= UBT_ACL_XMIT;
1413                 status = USBD_NORMAL_COMPLETION;
1414         }
1415
1416         NG_FREE_M(m);
1417
1418         return (status);
1419 } /* ubt_bulk_out_start */
1420
1421 /*
1422  * USB bulk-out transfer callback
1423  */
1424
1425 static void
1426 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1427 {
1428         ng_send_fn((node_p) p,  NULL, ubt_bulk_out_complete2, (void *) h, s);
1429         NG_NODE_UNREF((node_p) p);
1430 } /* ubt_bulk_out_complete */
1431
1432 static void
1433 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1434 {
1435         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1436         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
1437         usbd_status             s = (usbd_status) arg2;
1438
1439         if (sc == NULL)
1440                 return;
1441
1442         KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1443 "%s: %s - No bulk-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1444
1445         sc->sc_flags &= ~UBT_ACL_XMIT;
1446
1447         if (s == USBD_CANCELLED) {
1448                 NG_UBT_INFO(
1449 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1450                         __func__, device_get_nameunit(sc->sc_dev), sc->sc_bulk_out_pipe);
1451
1452                 return;
1453         }
1454
1455         if (s != USBD_NORMAL_COMPLETION) {    
1456                 NG_UBT_WARN(
1457 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1458                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1459
1460                 if (s == USBD_STALLED)
1461                         usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1462
1463                 NG_UBT_STAT_OERROR(sc->sc_stat);
1464         } else {
1465                 NG_UBT_INFO(
1466 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1467                         __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1468
1469                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1470                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); 
1471         }
1472
1473         if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1474                 ubt_bulk_out_start(sc);
1475 } /* ubt_bulk_out_complete2 */
1476
1477 /*
1478  * Start Isochronous-in USB transfer. Must be called with node locked
1479  */
1480
1481 static usbd_status
1482 ubt_isoc_in_start(ubt_softc_p sc)
1483 {
1484         usbd_status     status;
1485         int             i;
1486
1487         KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1488 "%s: %s - Another isoc-in request is pending\n",
1489                 __func__, device_get_nameunit(sc->sc_dev)));
1490
1491         /* Initialize a isoc-in USB transfer and then schedule it */
1492         for (i = 0; i < sc->sc_isoc_nframes; i++)
1493                 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1494
1495         usbd_setup_isoc_xfer(
1496                         sc->sc_isoc_in_xfer,
1497                         sc->sc_isoc_in_pipe,
1498                         (usbd_private_handle) sc->sc_node,
1499                         sc->sc_isoc_in_frlen,
1500                         sc->sc_isoc_nframes,
1501                         USBD_NO_COPY, /* XXX flags */
1502                         ubt_isoc_in_complete);
1503
1504         NG_NODE_REF(sc->sc_node);
1505
1506         status = usbd_transfer(sc->sc_isoc_in_xfer);
1507         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1508                 NG_UBT_ERR(
1509 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1510                         __func__, device_get_nameunit(sc->sc_dev),
1511                         usbd_errstr(status), status);
1512
1513                 NG_NODE_UNREF(sc->sc_node);
1514
1515                 return (status);
1516         }
1517
1518         sc->sc_flags |= UBT_SCO_RECV;
1519
1520         return (USBD_NORMAL_COMPLETION);
1521 } /* ubt_isoc_in_start */
1522
1523 /*
1524  * USB isochronous transfer callback
1525  */
1526
1527 static void
1528 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1529 {
1530         ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1531         NG_NODE_UNREF((node_p) p);
1532 } /* ubt_isoc_in_complete */
1533
1534 static void
1535 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1536 {
1537         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1538         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1539         usbd_status              s = (usbd_status) arg2;
1540         struct mbuf             *m = NULL;
1541         ng_hci_scodata_pkt_t    *hdr = NULL;
1542         u_int8_t                *b = NULL;
1543         int                      i;
1544
1545         if (sc == NULL)
1546                 return;
1547
1548         KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1549 "%s: %s - No isoc-in request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1550
1551         sc->sc_flags &= ~UBT_SCO_RECV;
1552
1553         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1554                 NG_UBT_INFO(
1555 "%s: %s - No upstream hook\n", __func__, device_get_nameunit(sc->sc_dev));
1556
1557                 return;
1558         }
1559
1560         if (s == USBD_CANCELLED) {
1561                 NG_UBT_INFO(
1562 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1563                         __func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_in_pipe);
1564
1565                 return;
1566         }
1567
1568         if (s != USBD_NORMAL_COMPLETION) {    
1569                 NG_UBT_WARN(
1570 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1571                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1572
1573                 if (s == USBD_STALLED)
1574                         usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1575
1576                 NG_UBT_STAT_IERROR(sc->sc_stat);
1577
1578                 return; /* XXX FIXME we should restart after some delay */
1579         }
1580
1581         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1582
1583         NG_UBT_INFO(
1584 "%s: %s - Got %d bytes from isoc-in pipe\n",
1585                 __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1586
1587         /* Copy SCO data frame to mbuf */
1588         MGETHDR(m, M_DONTWAIT, MT_DATA);
1589         if (m == NULL) {
1590                 NG_UBT_ALERT(
1591 "%s: %s - Could not allocate mbuf\n",
1592                         __func__, device_get_nameunit(sc->sc_dev));
1593
1594                 NG_UBT_STAT_IERROR(sc->sc_stat);
1595                 goto done;
1596         }
1597
1598         /* Fix SCO data frame header if required */
1599         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1600                 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1601                 m->m_pkthdr.len = 1;
1602                 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1603         } else {
1604                 m->m_pkthdr.len = 0;
1605                 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1606         }
1607
1608         /*
1609          * XXX FIXME how do we know how many frames we have received?
1610          * XXX use frlen for now. is that correct?
1611          */
1612
1613         b = (u_int8_t *) sc->sc_isoc_in_buffer;
1614
1615         for (i = 0; i < sc->sc_isoc_nframes; i++) {
1616                 b += (i * sc->sc_isoc_size);
1617
1618                 if (sc->sc_isoc_in_frlen[i] > 0)
1619                         m_copyback(m, m->m_pkthdr.len,
1620                                 sc->sc_isoc_in_frlen[i], b);
1621         }
1622
1623         if (m->m_pkthdr.len < sizeof(*hdr))
1624                 goto done;
1625
1626         hdr = mtod(m, ng_hci_scodata_pkt_t *);
1627
1628         if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1629                 NG_UBT_INFO(
1630 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1631                         __func__, device_get_nameunit(sc->sc_dev), m->m_pkthdr.len,
1632                         hdr->length);
1633
1634                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1635
1636                 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1637                 if (i != 0)
1638                         NG_UBT_STAT_IERROR(sc->sc_stat);
1639         } else {
1640                 NG_UBT_ERR(
1641 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1642                         __func__, device_get_nameunit(sc->sc_dev), hdr->length, 
1643                         m->m_pkthdr.len);
1644
1645                 NG_UBT_STAT_IERROR(sc->sc_stat);
1646                 NG_FREE_M(m);
1647         }
1648 done:
1649         ubt_isoc_in_start(sc);
1650 } /* ubt_isoc_in_complete2 */
1651
1652 /*
1653  * Start isochronous-out USB transfer. Must be called with node locked
1654  */
1655
1656 static usbd_status
1657 ubt_isoc_out_start(ubt_softc_p sc)
1658 {
1659         struct mbuf     *m = NULL;
1660         u_int8_t        *b = NULL;
1661         int              i, len, nframes;
1662         usbd_status      status;
1663
1664         KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1665 "%s: %s - Another isoc-out request is pending\n",
1666                 __func__, device_get_nameunit(sc->sc_dev)));
1667
1668         NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1669         if (m == NULL) {
1670                 NG_UBT_INFO(
1671 "%s: %s - SCO data queue is empty\n", __func__, device_get_nameunit(sc->sc_dev));
1672
1673                 return (USBD_NORMAL_COMPLETION);
1674         }
1675
1676         /* Copy entire SCO frame into USB transfer buffer and start transfer */ 
1677         b = (u_int8_t *) sc->sc_isoc_out_buffer;
1678         nframes = 0;
1679
1680         for (i = 0; i < sc->sc_isoc_nframes; i++) {
1681                 b += (i * sc->sc_isoc_size);
1682
1683                 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1684                 if (len > 0) {
1685                         m_copydata(m, 0, len, b);
1686                         m_adj(m, len);
1687                         nframes ++;
1688                 }
1689
1690                 sc->sc_isoc_out_frlen[i] = len;
1691         }
1692
1693         if (m->m_pkthdr.len > 0)
1694                 panic(
1695 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1696                         __func__, device_get_nameunit(sc->sc_dev), sc->sc_isoc_nframes,
1697                         sc->sc_isoc_size, m->m_pkthdr.len);
1698
1699         NG_FREE_M(m);
1700
1701         /* Initialize a isoc-out USB transfer and then schedule it */
1702         usbd_setup_isoc_xfer(
1703                         sc->sc_isoc_out_xfer,
1704                         sc->sc_isoc_out_pipe,
1705                         (usbd_private_handle) sc->sc_node,
1706                         sc->sc_isoc_out_frlen,
1707                         nframes,
1708                         USBD_NO_COPY,
1709                         ubt_isoc_out_complete);
1710
1711         NG_NODE_REF(sc->sc_node);
1712
1713         status = usbd_transfer(sc->sc_isoc_out_xfer);
1714         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1715                 NG_UBT_ERR(
1716 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1717                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1718                         status);
1719
1720                 NG_NODE_UNREF(sc->sc_node);
1721
1722                 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1723                 NG_UBT_STAT_OERROR(sc->sc_stat);
1724         } else {
1725                 NG_UBT_INFO(
1726 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1727                         __func__, device_get_nameunit(sc->sc_dev), nframes,
1728                         sc->sc_isoc_size);
1729
1730                 sc->sc_flags |= UBT_SCO_XMIT;
1731                 status = USBD_NORMAL_COMPLETION;
1732         }
1733
1734         return (status);
1735 } /* ubt_isoc_out_start */
1736
1737 /*
1738  * USB isoc-out. transfer callback
1739  */
1740
1741 static void
1742 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1743 {
1744         ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1745         NG_NODE_UNREF((node_p) p);
1746 } /* ubt_isoc_out_complete */
1747
1748 static void
1749 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1750 {
1751         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1752         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
1753         usbd_status             s = (usbd_status) arg2;
1754
1755         if (sc == NULL)
1756                 return;
1757
1758         KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1759 "%s: %s - No isoc-out request is pending\n", __func__, device_get_nameunit(sc->sc_dev)));
1760
1761         sc->sc_flags &= ~UBT_SCO_XMIT;
1762
1763         if (s == USBD_CANCELLED) {
1764                 NG_UBT_INFO(
1765 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1766                         __func__, device_get_nameunit(sc->sc_dev),
1767                         sc->sc_isoc_out_pipe);
1768
1769                 return;
1770         }
1771
1772         if (s != USBD_NORMAL_COMPLETION) {    
1773                 NG_UBT_WARN(
1774 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1775                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(s), s);
1776
1777                 if (s == USBD_STALLED)
1778                         usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1779
1780                 NG_UBT_STAT_OERROR(sc->sc_stat);
1781         } else {
1782                 NG_UBT_INFO(
1783 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1784                         __func__, device_get_nameunit(sc->sc_dev), h->actlen);
1785
1786                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1787                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1788         }
1789
1790         if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1791                 ubt_isoc_out_start(sc);
1792 } /* ubt_isoc_out_complete2 */
1793
1794 /*
1795  * Abort transfers on all USB pipes
1796  */
1797
1798 static void
1799 ubt_reset(ubt_softc_p sc)
1800 {
1801         /* Interrupt */
1802         if (sc->sc_intr_pipe != NULL)
1803                 usbd_abort_pipe(sc->sc_intr_pipe);
1804
1805         /* Bulk-in/out */
1806         if (sc->sc_bulk_in_pipe != NULL)
1807                 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1808         if (sc->sc_bulk_out_pipe != NULL)
1809                 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1810
1811         /* Isoc-in/out */
1812         if (sc->sc_isoc_in_pipe != NULL)
1813                 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1814         if (sc->sc_isoc_out_pipe != NULL)
1815                 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1816
1817         /* Cleanup queues */
1818         NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1819         NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1820         NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1821 } /* ubt_reset */
1822
1823 /****************************************************************************
1824  ****************************************************************************
1825  **                        Netgraph specific
1826  ****************************************************************************
1827  ****************************************************************************/
1828
1829 /*
1830  * Netgraph node constructor. Do not allow to create node of this type.
1831  */
1832
1833 static int
1834 ng_ubt_constructor(node_p node)
1835 {
1836         return (EINVAL);
1837 } /* ng_ubt_constructor */
1838
1839 /*
1840  * Netgraph node destructor. Destroy node only when device has been detached
1841  */
1842
1843 static int
1844 ng_ubt_shutdown(node_p node)
1845 {
1846         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1847
1848         /* Let old node go */
1849         NG_NODE_SET_PRIVATE(node, NULL);
1850         NG_NODE_UNREF(node);
1851         
1852         if (sc == NULL)
1853                 goto done;
1854
1855         /* Create Netgraph node */
1856         if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1857                 printf("%s: Could not create Netgraph node\n",
1858                         device_get_nameunit(sc->sc_dev));
1859                 sc->sc_node = NULL;
1860                 goto done;
1861         }
1862         
1863         /* Name node */ 
1864         if (ng_name_node(sc->sc_node, device_get_nameunit(sc->sc_dev)) != 0) {
1865                 printf("%s: Could not name Netgraph node\n",
1866                         device_get_nameunit(sc->sc_dev));
1867                 NG_NODE_UNREF(sc->sc_node);
1868                 sc->sc_node = NULL;
1869                 goto done;
1870         }
1871
1872         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1873         NG_NODE_FORCE_WRITER(sc->sc_node);
1874 done:
1875         return (0);
1876 } /* ng_ubt_shutdown */
1877
1878 /*
1879  * Create new hook. There can only be one.
1880  */
1881
1882 static int
1883 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1884 {
1885         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1886
1887         if (strcmp(name, NG_UBT_HOOK) != 0)
1888                 return (EINVAL);
1889
1890         if (sc->sc_hook != NULL)
1891                 return (EISCONN);
1892
1893         sc->sc_hook = hook;
1894
1895         return (0);
1896 } /* ng_ubt_newhook */
1897
1898 /*
1899  * Connect hook. Start incoming USB transfers
1900  */
1901
1902 static int
1903 ng_ubt_connect(hook_p hook)
1904 {
1905         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1906         usbd_status     status;
1907
1908         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1909
1910         /* Start intr transfer */
1911         status = ubt_intr_start(sc);
1912         if (status != USBD_NORMAL_COMPLETION) {
1913                 NG_UBT_ALERT(
1914 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1915                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1916                         status);
1917                 goto fail;
1918         }
1919
1920         /* Start bulk-in transfer */
1921         status = ubt_bulk_in_start(sc);
1922         if (status != USBD_NORMAL_COMPLETION) {
1923                 NG_UBT_ALERT(
1924 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1925                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1926                         status);
1927                 goto fail;
1928         }
1929
1930 #if 0 /* XXX FIXME */
1931         /* Start isoc-in transfer */
1932         status = ubt_isoc_in_start(sc);
1933         if (status != USBD_NORMAL_COMPLETION) {
1934                 NG_UBT_ALERT(
1935 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1936                         __func__, device_get_nameunit(sc->sc_dev), usbd_errstr(status),
1937                         status);
1938                 goto fail;
1939         }
1940 #endif
1941
1942         return (0);
1943 fail:
1944         ubt_reset(sc);
1945         sc->sc_hook = NULL;
1946
1947         return (ENXIO);
1948 } /* ng_ubt_connect */
1949
1950 /*
1951  * Disconnect hook
1952  */
1953
1954 static int
1955 ng_ubt_disconnect(hook_p hook)
1956 {
1957         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1958
1959         if (sc != NULL) {
1960                 if (hook != sc->sc_hook)
1961                         return (EINVAL);
1962
1963                 ubt_reset(sc);
1964                 sc->sc_hook = NULL;
1965         }
1966
1967         return (0);
1968 } /* ng_ubt_disconnect */
1969
1970 /*
1971  * Process control message
1972  */
1973
1974 static int
1975 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
1976 {
1977         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1978         struct ng_mesg          *msg = NULL, *rsp = NULL;
1979         struct ng_bt_mbufq      *q = NULL;
1980         int                      error = 0, queue, qlen;
1981
1982         if (sc == NULL) {
1983                 NG_FREE_ITEM(item);
1984                 return (EHOSTDOWN);
1985         }
1986
1987         NGI_GET_MSG(item, msg);
1988
1989         switch (msg->header.typecookie) {
1990         case NGM_GENERIC_COOKIE:
1991                 switch (msg->header.cmd) {
1992                 case NGM_TEXT_STATUS:
1993                         NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
1994                         if (rsp == NULL)
1995                                 error = ENOMEM;
1996                         else
1997                                 snprintf(rsp->data, NG_TEXTRESPONSE,
1998                                         "Hook: %s\n"   \
1999                                         "Flags: %#x\n" \
2000                                         "Debug: %d\n"  \
2001                                         "CMD queue: [have:%d,max:%d]\n" \
2002                                         "ACL queue: [have:%d,max:%d]\n" \
2003                                         "SCO queue: [have:%d,max:%d]",
2004                                         (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2005                                         sc->sc_flags,
2006                                         sc->sc_debug,
2007                                         NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2008                                         sc->sc_cmdq.maxlen,
2009                                         NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2010                                         sc->sc_aclq.maxlen,
2011                                         NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2012                                         sc->sc_scoq.maxlen);
2013                         break;
2014
2015                 default:
2016                         error = EINVAL;
2017                         break;
2018                 }
2019                 break;
2020
2021         case NGM_UBT_COOKIE:
2022                 switch (msg->header.cmd) {
2023                 case NGM_UBT_NODE_SET_DEBUG:
2024                         if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2025                                 error = EMSGSIZE;
2026                         else
2027                                 sc->sc_debug =
2028                                         *((ng_ubt_node_debug_ep *)(msg->data));
2029                         break;
2030
2031                 case NGM_UBT_NODE_GET_DEBUG:
2032                         NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2033                                 M_NOWAIT);
2034                         if (rsp == NULL)
2035                                 error = ENOMEM;
2036                         else
2037                                 *((ng_ubt_node_debug_ep *)(rsp->data)) = 
2038                                         sc->sc_debug;
2039                         break;
2040
2041                 case NGM_UBT_NODE_SET_QLEN:
2042                         if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2043                                 error = EMSGSIZE;
2044                         else {
2045                                 queue = ((ng_ubt_node_qlen_ep *)
2046                                                 (msg->data))->queue;
2047                                 qlen = ((ng_ubt_node_qlen_ep *)
2048                                                 (msg->data))->qlen;
2049
2050                                 if (qlen <= 0) {
2051                                         error = EINVAL;
2052                                         break;
2053                                 }
2054
2055                                 switch (queue) {
2056                                 case NGM_UBT_NODE_QUEUE_CMD:
2057                                         q = &sc->sc_cmdq;
2058                                         break;
2059
2060                                 case NGM_UBT_NODE_QUEUE_ACL:
2061                                         q = &sc->sc_aclq;
2062                                         break;
2063
2064                                 case NGM_UBT_NODE_QUEUE_SCO:
2065                                         q = &sc->sc_scoq;
2066                                         break;
2067
2068                                 default:
2069                                         q = NULL;
2070                                         error = EINVAL;
2071                                         break;
2072                                 }
2073
2074                                 if (q != NULL)
2075                                         q->maxlen = qlen;
2076                         }
2077                         break;
2078
2079                 case NGM_UBT_NODE_GET_QLEN:
2080                         if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2081                                 error = EMSGSIZE;
2082                                 break;
2083                         }
2084
2085                         queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2086                         switch (queue) {
2087                         case NGM_UBT_NODE_QUEUE_CMD:
2088                                 q = &sc->sc_cmdq;
2089                                 break;
2090
2091                         case NGM_UBT_NODE_QUEUE_ACL:
2092                                 q = &sc->sc_aclq;
2093                                 break;
2094
2095                         case NGM_UBT_NODE_QUEUE_SCO:
2096                                 q = &sc->sc_scoq;
2097                                 break;
2098
2099                         default:
2100                                 q = NULL;
2101                                 error = EINVAL;
2102                                 break;
2103                         }
2104
2105                         if (q != NULL) {
2106                                 NG_MKRESPONSE(rsp, msg, 
2107                                         sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2108                                 if (rsp == NULL) {
2109                                         error = ENOMEM;
2110                                         break;
2111                                 }
2112
2113                                 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2114                                         queue;
2115                                 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2116                                         q->maxlen;
2117                         }
2118                         break;
2119
2120                 case NGM_UBT_NODE_GET_STAT:
2121                         NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2122                                 M_NOWAIT);
2123                         if (rsp == NULL)
2124                                 error = ENOMEM;
2125                         else
2126                                 bcopy(&sc->sc_stat, rsp->data,
2127                                         sizeof(ng_ubt_node_stat_ep));
2128                         break;
2129
2130                 case NGM_UBT_NODE_RESET_STAT:
2131                         NG_UBT_STAT_RESET(sc->sc_stat);
2132                         break;
2133
2134                 default:
2135                         error = EINVAL;
2136                         break;
2137                 }
2138                 break;
2139
2140         default:
2141                 error = EINVAL;
2142                 break;
2143         }
2144
2145         NG_RESPOND_MSG(error, node, item, rsp);
2146         NG_FREE_MSG(msg);
2147
2148         return (error);
2149 } /* ng_ubt_rcvmsg */
2150
2151 /*
2152  * Process data
2153  */
2154
2155 static int
2156 ng_ubt_rcvdata(hook_p hook, item_p item)
2157 {
2158         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2159         struct mbuf             *m = NULL;
2160         usbd_status             (*f)(ubt_softc_p) = NULL;
2161         struct ng_bt_mbufq      *q = NULL;
2162         int                      b, error = 0;
2163
2164         if (sc == NULL) {
2165                 error = EHOSTDOWN;
2166                 goto done;
2167         }
2168
2169         if (hook != sc->sc_hook) {
2170                 error = EINVAL;
2171                 goto done;
2172         }
2173
2174         /* Deatch mbuf and get HCI frame type */
2175         NGI_GET_M(item, m);
2176
2177         /* Process HCI frame */
2178         switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2179         case NG_HCI_CMD_PKT:
2180                 f = ubt_request_start;
2181                 q = &sc->sc_cmdq;
2182                 b = UBT_CMD_XMIT;
2183                 break;
2184
2185         case NG_HCI_ACL_DATA_PKT:
2186                 f = ubt_bulk_out_start;
2187                 q = &sc->sc_aclq;
2188                 b = UBT_ACL_XMIT;
2189                 break;
2190
2191 #if 0 /* XXX FIXME */
2192         case NG_HCI_SCO_DATA_PKT:
2193                 f = ubt_isoc_out_start;
2194                 q = &sc->sc_scoq;
2195                 b = UBT_SCO_XMIT;
2196                 break;
2197 #endif
2198
2199         default:
2200                 NG_UBT_ERR(
2201 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2202                         __func__, device_get_nameunit(sc->sc_dev), *mtod(m, u_int8_t *),
2203                         m->m_pkthdr.len);
2204
2205                 NG_FREE_M(m);
2206                 error = EINVAL;
2207
2208                 goto done;
2209                 /* NOT REACHED */
2210         }
2211
2212         /* Loose frame type, if required */
2213         if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2214                 m_adj(m, sizeof(u_int8_t)); 
2215
2216         if (NG_BT_MBUFQ_FULL(q)) {
2217                 NG_UBT_ERR(
2218 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2219                         __func__, device_get_nameunit(sc->sc_dev),
2220                         *mtod(m, u_int8_t *), m->m_pkthdr.len);
2221
2222                 NG_FREE_M(m);
2223         } else
2224                 NG_BT_MBUFQ_ENQUEUE(q, m);
2225
2226         if (!(sc->sc_flags & b))
2227                 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2228                         error = EIO;
2229 done:
2230         NG_FREE_ITEM(item);
2231
2232         return (error);
2233 } /* ng_ubt_rcvdata */
2234