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