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