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