]> 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 r135446,
[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 {
187         NGM_UBT_COOKIE,
188         NGM_UBT_NODE_DEV_NODES,
189         "dev_nodes",
190         &ng_parse_uint16_type,
191         NULL
192 },
193 { 0, }
194 };
195
196 /* Netgraph node type */
197 Static struct ng_type   typestruct = {
198         .version =      NG_ABI_VERSION,
199         .name =         NG_UBT_NODE_TYPE,
200         .constructor =  ng_ubt_constructor,
201         .rcvmsg =       ng_ubt_rcvmsg,
202         .shutdown =     ng_ubt_shutdown,
203         .newhook =      ng_ubt_newhook,
204         .connect =      ng_ubt_connect,
205         .rcvdata =      ng_ubt_rcvdata,
206         .disconnect =   ng_ubt_disconnect,
207         .cmdlist =      ng_ubt_cmdlist  
208 };
209
210 /*
211  * Device methods
212  */
213
214 #define UBT_UNIT(n)     ((minor(n) >> 4) & 0xf)
215 #define UBT_ENDPOINT(n) (minor(n) & 0xf)
216 #define UBT_MINOR(u, e) (((u) << 4) | (e))
217 #define UBT_BSIZE       1024
218
219 Static d_open_t         ubt_open;
220 Static d_close_t        ubt_close;
221 Static d_read_t         ubt_read;
222 Static d_write_t        ubt_write;
223 Static d_ioctl_t        ubt_ioctl;
224 Static d_poll_t         ubt_poll;
225 Static void             ubt_create_device_nodes  (ubt_softc_p);
226 Static void             ubt_destroy_device_nodes (ubt_softc_p);
227
228 Static struct cdevsw    ubt_cdevsw = {
229         .d_version =    D_VERSION,
230         .d_flags =      D_NEEDGIANT,
231         .d_open =       ubt_open,
232         .d_close =      ubt_close,
233         .d_read =       ubt_read,
234         .d_write =      ubt_write,
235         .d_ioctl =      ubt_ioctl,
236         .d_poll =       ubt_poll,
237         .d_name =       "ubt",
238 };
239
240 /*
241  * Module
242  */
243
244 DRIVER_MODULE(ubt, uhub, ubt_driver, ubt_devclass, ubt_modevent, 0);
245 MODULE_VERSION(ng_ubt, NG_BLUETOOTH_VERSION);
246 MODULE_DEPEND(ng_ubt, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
247
248 /****************************************************************************
249  ****************************************************************************
250  **                              USB specific
251  ****************************************************************************
252  ****************************************************************************/
253
254 /*
255  * Load/Unload the driver module
256  */
257
258 Static int
259 ubt_modevent(module_t mod, int event, void *data)
260 {
261         int     error;
262
263         switch (event) {
264         case MOD_LOAD:
265                 error = ng_newtype(&typestruct);
266                 if (error != 0)
267                         printf(
268 "%s: Could not register Netgraph node type, error=%d\n",
269                                 NG_UBT_NODE_TYPE, error);
270                 else
271                         error = usbd_driver_load(mod, event, data);
272                 break;
273
274         case MOD_UNLOAD:
275                 error = ng_rmtype(&typestruct);
276                 if (error == 0)
277                         error = usbd_driver_load(mod, event, data);
278                 break;
279
280         default:
281                 error = EOPNOTSUPP;
282                 break;
283         }
284
285         return (error);
286 } /* ubt_modevent */
287
288 /*
289  * Probe for a USB Bluetooth device
290  */
291
292 USB_MATCH(ubt)
293 {
294         /*
295          * If for some reason device should not be attached then put
296          * VendorID/ProductID pair into the list below. Currently I
297          * do not know of any such devices. The format is as follows:
298          *
299          *      { VENDOR_ID, PRODUCT_ID },
300          *
301          * where VENDOR_ID and PRODUCT_ID are hex numbers.
302          */
303
304         Static struct usb_devno const   ubt_ignored_devices[] = {
305                 { 0, 0 } /* This should be the last item in the list */
306         };
307
308         /*
309          * If device violates Bluetooth specification and has bDeviceClass,
310          * bDeviceSubClass and bDeviceProtocol set to wrong values then you
311          * could try to put VendorID/ProductID pair into the list below. 
312          * Currently I do not know of any such devices.
313          */
314
315         Static struct usb_devno const   ubt_broken_devices[] = {
316                 { 0, 0 } /* This should be the last item in the list */
317         };
318
319         USB_MATCH_START(ubt, uaa);
320
321         usb_device_descriptor_t *dd = usbd_get_device_descriptor(uaa->device);
322
323         if (uaa->iface == NULL ||
324             usb_lookup(ubt_ignored_devices, uaa->vendor, uaa->product))
325                 return (UMATCH_NONE);
326         
327         if (dd->bDeviceClass == UDCLASS_WIRELESS &&
328             dd->bDeviceSubClass == UDSUBCLASS_RF &&
329             dd->bDeviceProtocol == UDPROTO_BLUETOOTH)
330                 return (UMATCH_DEVCLASS_DEVSUBCLASS);
331
332         if (usb_lookup(ubt_broken_devices, uaa->vendor, uaa->product))
333                 return (UMATCH_VENDOR_PRODUCT);
334
335         return (UMATCH_NONE);
336 } /* USB_MATCH(ubt) */
337
338 /*
339  * Attach the device
340  */
341
342 USB_ATTACH(ubt)
343 {
344         USB_ATTACH_START(ubt, sc, uaa);
345         usb_config_descriptor_t         *cd = NULL;
346         usb_interface_descriptor_t      *id = NULL;
347         usb_endpoint_descriptor_t       *ed = NULL;
348         char                             devinfo[UBT_BSIZE];
349         usbd_status                      error;
350         int                              i, ai, alt_no, isoc_in, isoc_out,
351                                          isoc_isize, isoc_osize;
352
353         /* Get USB device info */
354         sc->sc_udev = uaa->device;
355         usbd_devinfo(sc->sc_udev, 0, devinfo); 
356         USB_ATTACH_SETUP;
357         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
358
359         /* 
360          * Initialize device softc structure
361          */
362
363         /* State */
364         sc->sc_debug = NG_UBT_WARN_LEVEL;
365         sc->sc_flags = 0;
366         NG_UBT_STAT_RESET(sc->sc_stat);
367
368         /* Interfaces */
369         sc->sc_iface0 = sc->sc_iface1 = NULL;
370
371         /* Interrupt pipe */
372         sc->sc_intr_ep = -1;
373         sc->sc_intr_pipe = NULL;
374         sc->sc_intr_xfer = NULL;
375         sc->sc_intr_buffer = NULL;
376
377         /* Control pipe */
378         sc->sc_ctrl_xfer = NULL;
379         sc->sc_ctrl_buffer = NULL;
380         NG_BT_MBUFQ_INIT(&sc->sc_cmdq, UBT_DEFAULT_QLEN);
381
382         /* Bulk-in pipe */
383         sc->sc_bulk_in_ep = -1;
384         sc->sc_bulk_in_pipe = NULL;
385         sc->sc_bulk_in_xfer = NULL;
386         sc->sc_bulk_in_buffer = NULL;
387
388         /* Bulk-out pipe */
389         sc->sc_bulk_out_ep = -1;
390         sc->sc_bulk_out_pipe = NULL;
391         sc->sc_bulk_out_xfer = NULL;
392         sc->sc_bulk_out_buffer = NULL;
393         NG_BT_MBUFQ_INIT(&sc->sc_aclq, UBT_DEFAULT_QLEN);
394
395         /* Isoc-in pipe */
396         sc->sc_isoc_in_ep = -1;
397         sc->sc_isoc_in_pipe = NULL;
398         sc->sc_isoc_in_xfer = NULL;
399
400         /* Isoc-out pipe */
401         sc->sc_isoc_out_ep = -1;
402         sc->sc_isoc_out_pipe = NULL;
403         sc->sc_isoc_out_xfer = NULL;
404         sc->sc_isoc_size = -1;
405         NG_BT_MBUFQ_INIT(&sc->sc_scoq, UBT_DEFAULT_QLEN);
406
407         /* Netgraph part */
408         sc->sc_node = NULL;
409         sc->sc_hook = NULL;
410
411         /* Device part */
412         sc->sc_ctrl_dev = sc->sc_intr_dev = sc->sc_bulk_dev = NULL;
413         sc->sc_refcnt = sc->sc_dying = 0;
414
415         /*
416          * XXX set configuration?
417          *
418          * Configure Bluetooth USB device. Discover all required USB interfaces
419          * and endpoints.
420          *
421          * USB device must present two interfaces:
422          * 1) Interface 0 that has 3 endpoints
423          *      1) Interrupt endpoint to receive HCI events
424          *      2) Bulk IN endpoint to receive ACL data
425          *      3) Bulk OUT endpoint to send ACL data
426          *
427          * 2) Interface 1 then has 2 endpoints
428          *      1) Isochronous IN endpoint to receive SCO data
429          *      2) Isochronous OUT endpoint to send SCO data
430          *
431          * Interface 1 (with isochronous endpoints) has several alternate 
432          * configurations with different packet size.
433          */
434
435         /*
436          * Interface 0
437          */
438
439         error = usbd_device2interface_handle(sc->sc_udev, 0, &sc->sc_iface0);
440         if (error || sc->sc_iface0 == NULL) {
441                 printf("%s: Could not get interface 0 handle. %s (%d), " \
442                         "handle=%p\n", USBDEVNAME(sc->sc_dev),
443                         usbd_errstr(error), error, sc->sc_iface0);
444                 goto bad;
445         }
446
447         id = usbd_get_interface_descriptor(sc->sc_iface0);
448         if (id == NULL) {
449                 printf("%s: Could not get interface 0 descriptor\n",
450                         USBDEVNAME(sc->sc_dev));
451                 goto bad;
452         }
453
454         for (i = 0; i < id->bNumEndpoints; i ++) {
455                 ed = usbd_interface2endpoint_descriptor(sc->sc_iface0, i);
456                 if (ed == NULL) {
457                         printf("%s: Could not read endpoint descriptor for " \
458                                 "interface 0, i=%d\n", USBDEVNAME(sc->sc_dev),
459                                 i);
460                         goto bad;
461                 }
462
463                 switch (UE_GET_XFERTYPE(ed->bmAttributes)) {
464                 case UE_BULK:
465                         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
466                                 sc->sc_bulk_in_ep = ed->bEndpointAddress;
467                         else
468                                 sc->sc_bulk_out_ep = ed->bEndpointAddress;
469                         break;
470
471                 case UE_INTERRUPT:
472                         sc->sc_intr_ep = ed->bEndpointAddress;
473                         break;
474                 }
475         }
476
477         /* Check if we got everything we wanted on Interface 0 */
478         if (sc->sc_intr_ep == -1) {
479                 printf("%s: Could not detect interrupt endpoint\n",
480                         USBDEVNAME(sc->sc_dev));
481                 goto bad;
482         }
483         if (sc->sc_bulk_in_ep == -1) {
484                 printf("%s: Could not detect bulk-in endpoint\n",
485                         USBDEVNAME(sc->sc_dev));
486                 goto bad;
487         }
488         if (sc->sc_bulk_out_ep == -1) {
489                 printf("%s: Could not detect bulk-out endpoint\n",
490                         USBDEVNAME(sc->sc_dev));
491                 goto bad;
492         }
493
494         printf("%s: Interface 0 endpoints: interrupt=%#x, bulk-in=%#x, " \
495                 "bulk-out=%#x\n", USBDEVNAME(sc->sc_dev), 
496                 sc->sc_intr_ep, sc->sc_bulk_in_ep, sc->sc_bulk_out_ep);
497
498         /*
499          * Interface 1
500          */
501
502         cd = usbd_get_config_descriptor(sc->sc_udev);
503         if (cd == NULL) {
504                 printf("%s: Could not get device configuration descriptor\n",
505                         USBDEVNAME(sc->sc_dev));
506                 goto bad;
507         }
508
509         error = usbd_device2interface_handle(sc->sc_udev, 1, &sc->sc_iface1);
510         if (error || sc->sc_iface1 == NULL) {
511                 printf("%s: Could not get interface 1 handle. %s (%d), " \
512                         "handle=%p\n", USBDEVNAME(sc->sc_dev), 
513                         usbd_errstr(error), error, sc->sc_iface1);
514                 goto bad;
515         }
516
517         id = usbd_get_interface_descriptor(sc->sc_iface1);
518         if (id == NULL) {
519                 printf("%s: Could not get interface 1 descriptor\n",
520                         USBDEVNAME(sc->sc_dev));
521                 goto bad;
522         }
523
524         /*
525          * Scan all alternate configurations for interface 1
526          */
527
528         alt_no = -1;
529
530         for (ai = 0; ai < usbd_get_no_alts(cd, 1); ai++)  {
531                 error = usbd_set_interface(sc->sc_iface1, ai);
532                 if (error) {
533                         printf("%s: [SCAN] Could not set alternate " \
534                                 "configuration %d for interface 1. %s (%d)\n",
535                                 USBDEVNAME(sc->sc_dev),  ai, usbd_errstr(error),
536                                 error);
537                         goto bad;
538                 }
539                 id = usbd_get_interface_descriptor(sc->sc_iface1);
540                 if (id == NULL) {
541                         printf("%s: Could not get interface 1 descriptor for " \
542                                 "alternate configuration %d\n",
543                                 USBDEVNAME(sc->sc_dev), ai);
544                         goto bad;
545                 }
546
547                 isoc_in = isoc_out = -1;
548                 isoc_isize = isoc_osize = 0;
549
550                 for (i = 0; i < id->bNumEndpoints; i ++) {
551                         ed = usbd_interface2endpoint_descriptor(sc->sc_iface1, i);
552                         if (ed == NULL) {
553                                 printf("%s: Could not read endpoint " \
554                                         "descriptor for interface 1, " \
555                                         "alternate configuration %d, i=%d\n",
556                                         USBDEVNAME(sc->sc_dev), ai, i);
557                                 goto bad;
558                         }
559
560                         if (UE_GET_XFERTYPE(ed->bmAttributes) != UE_ISOCHRONOUS)
561                                 continue;
562
563                         if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) {
564                                 isoc_in = ed->bEndpointAddress;
565                                 isoc_isize = UGETW(ed->wMaxPacketSize);
566                         } else {
567                                 isoc_out = ed->bEndpointAddress;
568                                 isoc_osize = UGETW(ed->wMaxPacketSize);
569                         }
570                 }
571
572                 /*
573                  * Make sure that configuration looks sane and if so
574                  * update current settings
575                  */
576
577                 if (isoc_in != -1 && isoc_out != -1 &&
578                     isoc_isize > 0  && isoc_osize > 0 &&
579                     isoc_isize == isoc_osize && isoc_isize > sc->sc_isoc_size) {
580                         sc->sc_isoc_in_ep = isoc_in;
581                         sc->sc_isoc_out_ep = isoc_out;
582                         sc->sc_isoc_size = isoc_isize;
583                         alt_no = ai;
584                 }
585         }
586
587         /* Check if we got everything we wanted on Interface 0 */
588         if (sc->sc_isoc_in_ep == -1) {
589                 printf("%s: Could not detect isoc-in endpoint\n",
590                         USBDEVNAME(sc->sc_dev));
591                 goto bad;
592         }
593         if (sc->sc_isoc_out_ep == -1) {
594                 printf("%s: Could not detect isoc-out endpoint\n",
595                         USBDEVNAME(sc->sc_dev));
596                 goto bad;
597         }
598         if (sc->sc_isoc_size <= 0) {
599                 printf("%s: Invalid isoc. packet size=%d\n",
600                         USBDEVNAME(sc->sc_dev), sc->sc_isoc_size);
601                 goto bad;
602         }
603
604         error = usbd_set_interface(sc->sc_iface1, alt_no);
605         if (error) {
606                 printf("%s: Could not set alternate configuration " \
607                         "%d for interface 1. %s (%d)\n", USBDEVNAME(sc->sc_dev),
608                         alt_no, usbd_errstr(error), error);
609                 goto bad;
610         }
611
612         /* Allocate USB transfer handles and buffers */
613         sc->sc_ctrl_xfer = usbd_alloc_xfer(sc->sc_udev);
614         if (sc->sc_ctrl_xfer == NULL) {
615                 printf("%s: Could not allocate control xfer handle\n",
616                         USBDEVNAME(sc->sc_dev));
617                 goto bad;
618         }
619         sc->sc_ctrl_buffer = usbd_alloc_buffer(sc->sc_ctrl_xfer, 
620                                                 UBT_CTRL_BUFFER_SIZE);
621         if (sc->sc_ctrl_buffer == NULL) {
622                 printf("%s: Could not allocate control buffer\n",
623                         USBDEVNAME(sc->sc_dev));
624                 goto bad;
625         }
626
627         sc->sc_intr_xfer = usbd_alloc_xfer(sc->sc_udev);
628         if (sc->sc_intr_xfer == NULL) {
629                 printf("%s: Could not allocate interrupt xfer handle\n",
630                         USBDEVNAME(sc->sc_dev));
631                 goto bad;
632         }
633
634         sc->sc_bulk_in_xfer = usbd_alloc_xfer(sc->sc_udev);
635         if (sc->sc_bulk_in_xfer == NULL) {
636                 printf("%s: Could not allocate bulk-in xfer handle\n",
637                         USBDEVNAME(sc->sc_dev));
638                 goto bad;
639         }
640
641         sc->sc_bulk_out_xfer = usbd_alloc_xfer(sc->sc_udev);
642         if (sc->sc_bulk_out_xfer == NULL) {
643                 printf("%s: Could not allocate bulk-out xfer handle\n",
644                         USBDEVNAME(sc->sc_dev));
645                 goto bad;
646         }
647         sc->sc_bulk_out_buffer = usbd_alloc_buffer(sc->sc_bulk_out_xfer,
648                                                 UBT_BULK_BUFFER_SIZE);
649         if (sc->sc_bulk_out_buffer == NULL) {
650                 printf("%s: Could not allocate bulk-out buffer\n",
651                         USBDEVNAME(sc->sc_dev));
652                 goto bad;
653         }
654
655         /*
656          * Allocate buffers for isoc. transfers
657          */
658
659         sc->sc_isoc_nframes = (UBT_ISOC_BUFFER_SIZE / sc->sc_isoc_size) + 1;
660
661         sc->sc_isoc_in_xfer = usbd_alloc_xfer(sc->sc_udev);
662         if (sc->sc_isoc_in_xfer == NULL) {
663                 printf("%s: Could not allocate isoc-in xfer handle\n",
664                         USBDEVNAME(sc->sc_dev));
665                 goto bad;
666         }
667         sc->sc_isoc_in_buffer = usbd_alloc_buffer(sc->sc_isoc_in_xfer,
668                                         sc->sc_isoc_nframes * sc->sc_isoc_size);
669         if (sc->sc_isoc_in_buffer == NULL) {
670                 printf("%s: Could not allocate isoc-in buffer\n",
671                         USBDEVNAME(sc->sc_dev));
672                 goto bad;
673         }
674         sc->sc_isoc_in_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 
675                                                 M_USBDEV, M_NOWAIT);
676         if (sc->sc_isoc_in_frlen == NULL) {
677                 printf("%s: Could not allocate isoc-in frame sizes buffer\n",
678                         USBDEVNAME(sc->sc_dev));
679                 goto bad;
680         }
681
682         sc->sc_isoc_out_xfer = usbd_alloc_xfer(sc->sc_udev);
683         if (sc->sc_isoc_out_xfer == NULL) {
684                 printf("%s: Could not allocate isoc-out xfer handle\n",
685                         USBDEVNAME(sc->sc_dev));
686                 goto bad;
687         }
688         sc->sc_isoc_out_buffer = usbd_alloc_buffer(sc->sc_isoc_out_xfer,
689                                         sc->sc_isoc_nframes * sc->sc_isoc_size);
690         if (sc->sc_isoc_out_buffer == NULL) {
691                 printf("%s: Could not allocate isoc-out buffer\n",
692                         USBDEVNAME(sc->sc_dev));
693                 goto bad;
694         }
695         sc->sc_isoc_out_frlen = malloc(sizeof(u_int16_t) * sc->sc_isoc_nframes, 
696                                                 M_USBDEV, M_NOWAIT);
697         if (sc->sc_isoc_out_frlen == NULL) {
698                 printf("%s: Could not allocate isoc-out frame sizes buffer\n",
699                         USBDEVNAME(sc->sc_dev));
700                 goto bad;
701         }
702
703         printf("%s: Interface 1 (alt.config %d) endpoints: isoc-in=%#x, " \
704                 "isoc-out=%#x; wMaxPacketSize=%d; nframes=%d, buffer size=%d\n",
705                 USBDEVNAME(sc->sc_dev), alt_no, sc->sc_isoc_in_ep,
706                 sc->sc_isoc_out_ep, sc->sc_isoc_size, sc->sc_isoc_nframes, 
707                 (sc->sc_isoc_nframes * sc->sc_isoc_size));
708
709         /*
710          * Open pipes
711          */
712
713         /* Interrupt */ 
714         error = usbd_open_pipe(sc->sc_iface0, sc->sc_intr_ep,
715                         USBD_EXCLUSIVE_USE, &sc->sc_intr_pipe);
716         if (error != USBD_NORMAL_COMPLETION) {
717                 printf("%s: %s - Could not open interrupt pipe. %s (%d)\n",
718                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
719                         error);
720                 goto bad;
721         }
722
723         /* Bulk-in */
724         error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_in_ep,
725                         USBD_EXCLUSIVE_USE, &sc->sc_bulk_in_pipe);
726         if (error != USBD_NORMAL_COMPLETION) {
727                 printf("%s: %s - Could not open bulk-in pipe. %s (%d)\n",
728                         __func__,  USBDEVNAME(sc->sc_dev), usbd_errstr(error),
729                         error);
730                 goto bad;
731         }
732
733         /* Bulk-out */
734         error = usbd_open_pipe(sc->sc_iface0, sc->sc_bulk_out_ep,
735                         USBD_EXCLUSIVE_USE, &sc->sc_bulk_out_pipe);
736         if (error != USBD_NORMAL_COMPLETION) {
737                 printf("%s: %s - Could not open bulk-out pipe. %s (%d)\n",
738                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
739                         error);
740                 goto bad;
741         }
742
743 #if __broken__ /* XXX FIXME */
744         /* Isoc-in */
745         error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_in_ep,
746                         USBD_EXCLUSIVE_USE, &sc->sc_isoc_in_pipe);
747         if (error != USBD_NORMAL_COMPLETION) {
748                 printf("%s: %s - Could not open isoc-in pipe. %s (%d)\n",
749                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
750                         error);
751                 goto bad;
752         }
753
754         /* Isoc-out */
755         error = usbd_open_pipe(sc->sc_iface1, sc->sc_isoc_out_ep, 
756                         USBD_EXCLUSIVE_USE, &sc->sc_isoc_out_pipe);
757         if (error != USBD_NORMAL_COMPLETION) {
758                 printf("%s: %s - Could not open isoc-out pipe. %s (%d)\n",
759                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(error),
760                         error);
761                 goto bad;
762         }
763 #endif /* __broken__ */
764
765         /* Create Netgraph node */
766         if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
767                 printf("%s: Could not create Netgraph node\n",
768                         USBDEVNAME(sc->sc_dev));
769                 sc->sc_node = NULL;
770                 goto bad;
771         }
772
773         /* Name node */
774         if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
775                 printf("%s: Could not name Netgraph node\n",
776                         USBDEVNAME(sc->sc_dev));
777                 NG_NODE_UNREF(sc->sc_node);
778                 sc->sc_node = NULL;
779                 goto bad;
780         }
781
782         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
783         NG_NODE_FORCE_WRITER(sc->sc_node);
784
785         /* Claim all interfaces on the device */
786         for (i = 0; i < uaa->nifaces; i++)
787                 uaa->ifaces[i] = NULL;
788
789         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
790                 USBDEV(sc->sc_dev));
791
792         USB_ATTACH_SUCCESS_RETURN;
793 bad:
794         ubt_detach(self);
795
796         USB_ATTACH_ERROR_RETURN;
797 } /* USB_ATTACH(ubt) */
798
799 /*
800  * Detach the device
801  */
802
803 USB_DETACH(ubt)
804 {
805         USB_DETACH_START(ubt, sc);
806
807         sc->sc_dying = 1;
808
809         ubt_destroy_device_nodes(sc); /* XXX FIXME locking? */
810
811         /* Destroy Netgraph node */
812         if (sc->sc_node != NULL) {
813                 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
814                 ng_rmnode_self(sc->sc_node);
815                 sc->sc_node = NULL;
816         }
817
818         /* Close pipes */
819         if (sc->sc_intr_pipe != NULL) {
820                 usbd_close_pipe(sc->sc_intr_pipe);
821                 sc->sc_intr_pipe = NULL;
822         }
823
824         if (sc->sc_bulk_in_pipe != NULL) {
825                 usbd_close_pipe(sc->sc_bulk_in_pipe);
826                 sc->sc_bulk_in_pipe = NULL;
827         }
828         if (sc->sc_bulk_out_pipe != NULL) {
829                 usbd_close_pipe(sc->sc_bulk_out_pipe);
830                 sc->sc_bulk_out_pipe = NULL;
831         }
832
833         if (sc->sc_isoc_in_pipe != NULL) {
834                 usbd_close_pipe(sc->sc_isoc_in_pipe);
835                 sc->sc_isoc_in_pipe = NULL;
836         }
837         if (sc->sc_isoc_out_pipe != NULL) {
838                 usbd_close_pipe(sc->sc_isoc_out_pipe);
839                 sc->sc_isoc_out_pipe = NULL;
840         }
841
842         /* Destroy USB transfer handles */
843         if (sc->sc_ctrl_xfer != NULL) {
844                 usbd_free_xfer(sc->sc_ctrl_xfer);
845                 sc->sc_ctrl_xfer = NULL;
846         }
847
848         if (sc->sc_intr_xfer != NULL) {
849                 usbd_free_xfer(sc->sc_intr_xfer);
850                 sc->sc_intr_xfer = NULL;
851         }
852
853         if (sc->sc_bulk_in_xfer != NULL) {
854                 usbd_free_xfer(sc->sc_bulk_in_xfer);
855                 sc->sc_bulk_in_xfer = NULL;
856         }
857         if (sc->sc_bulk_out_xfer != NULL) {
858                 usbd_free_xfer(sc->sc_bulk_out_xfer);
859                 sc->sc_bulk_out_xfer = NULL;
860         }
861
862         if (sc->sc_isoc_in_xfer != NULL) {
863                 usbd_free_xfer(sc->sc_isoc_in_xfer);
864                 sc->sc_isoc_in_xfer = NULL;
865         }
866         if (sc->sc_isoc_out_xfer != NULL) {
867                 usbd_free_xfer(sc->sc_isoc_out_xfer);
868                 sc->sc_isoc_out_xfer = NULL;
869         }
870
871         /* Destroy isoc. frame size buffers */
872         if (sc->sc_isoc_in_frlen != NULL) {
873                 free(sc->sc_isoc_in_frlen, M_USBDEV);
874                 sc->sc_isoc_in_frlen = NULL;
875         }
876         if (sc->sc_isoc_out_frlen != NULL) {
877                 free(sc->sc_isoc_out_frlen, M_USBDEV);
878                 sc->sc_isoc_out_frlen = NULL;
879         }
880
881         /* Destroy queues */
882         NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
883         NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
884         NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
885
886         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
887                         USBDEV(sc->sc_dev));
888
889         return (0);
890 } /* USB_DETACH(ubt) */
891
892 /*
893  * Start USB control request (HCI command). Must be called with node locked
894  */
895
896 Static usbd_status
897 ubt_request_start(ubt_softc_p sc)
898 {
899         usb_device_request_t     req;
900         struct mbuf             *m = NULL;
901         usbd_status              status;
902
903         KASSERT(!(sc->sc_flags & UBT_CMD_XMIT), (
904 "%s: %s - Another control request is pending\n",
905                 __func__, USBDEVNAME(sc->sc_dev)));
906
907         NG_BT_MBUFQ_DEQUEUE(&sc->sc_cmdq, m);
908         if (m == NULL) {
909                 NG_UBT_INFO(
910 "%s: %s - HCI command queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
911
912                 return (USBD_NORMAL_COMPLETION);
913         }
914
915         /*
916          * Check HCI command frame size and copy it back to 
917          * linear USB transfer buffer.
918          */ 
919
920         if (m->m_pkthdr.len > UBT_CTRL_BUFFER_SIZE)
921                 panic(
922 "%s: %s - HCI command frame too big, size=%zd, len=%d\n",
923                         __func__, USBDEVNAME(sc->sc_dev), UBT_CTRL_BUFFER_SIZE,
924                         m->m_pkthdr.len);
925
926         m_copydata(m, 0, m->m_pkthdr.len, sc->sc_ctrl_buffer);
927
928         /* Initialize a USB control request and then schedule it */
929         bzero(&req, sizeof(req));
930         req.bmRequestType = UBT_HCI_REQUEST;
931         USETW(req.wLength, m->m_pkthdr.len);
932
933         NG_UBT_INFO(
934 "%s: %s - Sending control request, bmRequestType=%#x, wLength=%d\n",
935                 __func__, USBDEVNAME(sc->sc_dev), req.bmRequestType,
936                 UGETW(req.wLength));
937
938         usbd_setup_default_xfer(
939                 sc->sc_ctrl_xfer,
940                 sc->sc_udev,
941                 (usbd_private_handle) sc->sc_node,
942                 USBD_DEFAULT_TIMEOUT, /* XXX */
943                 &req,
944                 sc->sc_ctrl_buffer,
945                 m->m_pkthdr.len,
946                 USBD_NO_COPY,
947                 ubt_request_complete);
948
949         NG_NODE_REF(sc->sc_node);
950
951         status = usbd_transfer(sc->sc_ctrl_xfer);
952         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
953                 NG_UBT_ERR(
954 "%s: %s - Could not start control request. %s (%d)\n",
955                         __func__, USBDEVNAME(sc->sc_dev),
956                         usbd_errstr(status), status);
957
958                 NG_NODE_UNREF(sc->sc_node);
959
960                 NG_BT_MBUFQ_DROP(&sc->sc_cmdq);
961                 NG_UBT_STAT_OERROR(sc->sc_stat);
962
963                 /* XXX FIXME should we try to resubmit another request? */
964         } else {
965                 NG_UBT_INFO(
966 "%s: %s - Control request has been started\n",
967                         __func__, USBDEVNAME(sc->sc_dev));
968
969                 sc->sc_flags |= UBT_CMD_XMIT;
970                 status = USBD_NORMAL_COMPLETION;
971         }
972
973         NG_FREE_M(m);
974
975         return (status);
976 } /* ubt_request_start */
977
978 /*
979  * USB control request callback
980  */
981
982 Static void
983 ubt_request_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
984 {
985         ng_send_fn((node_p) p, NULL, ubt_request_complete2, (void *) h, s);
986         NG_NODE_UNREF((node_p) p);
987 } /* ubt_request_complete */
988
989 Static void
990 ubt_request_complete2(node_p node, hook_p hook, void *arg1, int arg2)
991
992         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
993         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
994         usbd_status             s = (usbd_status) arg2;
995
996         if (sc == NULL)
997                 return;
998
999         KASSERT((sc->sc_flags & UBT_CMD_XMIT), (
1000 "%s: %s - No control request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1001
1002         sc->sc_flags &= ~UBT_CMD_XMIT;
1003
1004         if (s == USBD_CANCELLED) {
1005                 NG_UBT_INFO(
1006 "%s: %s - Control request cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1007
1008                 return;
1009         }
1010
1011         if (s != USBD_NORMAL_COMPLETION) {    
1012                 NG_UBT_ERR(
1013 "%s: %s - Control request failed. %s (%d)\n",
1014                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1015
1016                 if (s == USBD_STALLED)
1017                         usbd_clear_endpoint_stall_async(h->pipe);
1018
1019                 NG_UBT_STAT_OERROR(sc->sc_stat);
1020         } else {
1021                 NG_UBT_INFO(
1022 "%s: %s - Sent %d bytes to control pipe\n",
1023                         __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1024
1025                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1026                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1027         }
1028
1029         if (NG_BT_MBUFQ_LEN(&sc->sc_cmdq) > 0)
1030                 ubt_request_start(sc);
1031 } /* ubt_request_complete2 */
1032
1033 /*
1034  * Start interrupt transfer. Must be called when node is locked
1035  */
1036
1037 Static usbd_status
1038 ubt_intr_start(ubt_softc_p sc)
1039 {
1040         struct mbuf     *m = NULL;
1041         usbd_status      status;
1042
1043         KASSERT(!(sc->sc_flags & UBT_EVT_RECV), (
1044 "%s: %s - Another interrupt request is pending\n",
1045                 __func__, USBDEVNAME(sc->sc_dev)));
1046
1047         /* Allocate new mbuf cluster */
1048         MGETHDR(m, M_DONTWAIT, MT_DATA);
1049         if (m == NULL)
1050                 return (USBD_NOMEM);
1051
1052         MCLGET(m, M_DONTWAIT);
1053         if (!(m->m_flags & M_EXT)) {
1054                 NG_FREE_M(m);
1055                 return (USBD_NOMEM);
1056         }
1057
1058         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1059                 *mtod(m, u_int8_t *) = NG_HCI_EVENT_PKT;
1060                 m->m_pkthdr.len = m->m_len = 1;
1061         } else
1062                 m->m_pkthdr.len = m->m_len = 0;
1063         
1064         /* Initialize a USB transfer and then schedule it */
1065         usbd_setup_xfer(
1066                         sc->sc_intr_xfer,
1067                         sc->sc_intr_pipe,
1068                         (usbd_private_handle) sc->sc_node,
1069                         (void *)(mtod(m, u_int8_t *) + m->m_len),
1070                         MCLBYTES - m->m_len,
1071                         USBD_SHORT_XFER_OK,
1072                         USBD_NO_TIMEOUT,
1073                         ubt_intr_complete);
1074
1075         NG_NODE_REF(sc->sc_node);
1076
1077         status = usbd_transfer(sc->sc_intr_xfer);
1078         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1079                 NG_UBT_ERR(
1080 "%s: %s - Failed to start intrerrupt transfer. %s (%d)\n",
1081                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1082                         status);
1083
1084                 NG_NODE_UNREF(sc->sc_node);
1085
1086                 NG_FREE_M(m);
1087
1088                 return (status);
1089         }
1090
1091         sc->sc_flags |= UBT_EVT_RECV;
1092         sc->sc_intr_buffer = m;
1093
1094         return (USBD_NORMAL_COMPLETION);
1095 } /* ubt_intr_start */
1096
1097 /*
1098  * Process interrupt from USB device (We got data from interrupt pipe)
1099  */
1100
1101 Static void
1102 ubt_intr_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1103 {
1104         ng_send_fn((node_p) p, NULL, ubt_intr_complete2, (void *) h, s);
1105         NG_NODE_UNREF((node_p) p);
1106 } /* ubt_intr_complete */
1107
1108 Static void
1109 ubt_intr_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1110 {
1111         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1112         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1113         usbd_status              s = (usbd_status) arg2;
1114         struct mbuf             *m = NULL;
1115         ng_hci_event_pkt_t      *hdr = NULL;
1116         int                      error;
1117
1118         if (sc == NULL)
1119                 return;
1120
1121         KASSERT((sc->sc_flags & UBT_EVT_RECV), (
1122 "%s: %s - No interrupt request is pending\n",
1123                 __func__, USBDEVNAME(sc->sc_dev)));
1124
1125         sc->sc_flags &= ~UBT_EVT_RECV;
1126
1127         m = sc->sc_intr_buffer;
1128         sc->sc_intr_buffer = NULL;
1129
1130         hdr = mtod(m, ng_hci_event_pkt_t *);
1131
1132         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1133                 NG_UBT_INFO(
1134 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1135
1136                 NG_FREE_M(m);
1137                 return;
1138         }
1139
1140         if (s == USBD_CANCELLED) {
1141                 NG_UBT_INFO(
1142 "%s: %s - Interrupt xfer cancelled\n", __func__, USBDEVNAME(sc->sc_dev));
1143
1144                 NG_FREE_M(m);
1145                 return;
1146         }
1147                 
1148         if (s != USBD_NORMAL_COMPLETION) {    
1149                 NG_UBT_WARN(
1150 "%s: %s - Interrupt xfer failed, %s (%d). No new xfer will be submitted!\n",
1151                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1152
1153                 if (s == USBD_STALLED)
1154                         usbd_clear_endpoint_stall_async(sc->sc_intr_pipe);
1155
1156                 NG_UBT_STAT_IERROR(sc->sc_stat);
1157                 NG_FREE_M(m);
1158
1159                 return; /* XXX FIXME we should restart after some delay */
1160         }
1161
1162         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1163         m->m_pkthdr.len += h->actlen;
1164         m->m_len += h->actlen;
1165
1166         NG_UBT_INFO(
1167 "%s: %s - Got %d bytes from interrupt pipe\n",
1168                 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1169
1170         if (m->m_pkthdr.len < sizeof(*hdr)) {
1171                 NG_FREE_M(m);
1172                 goto done;
1173         }
1174
1175         if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1176                 NG_UBT_INFO(
1177 "%s: %s - Got complete HCI event frame, pktlen=%d, length=%d\n",
1178                         __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1179                         hdr->length);
1180
1181                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1182
1183                 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
1184                 if (error != 0)
1185                         NG_UBT_STAT_IERROR(sc->sc_stat);
1186         } else {
1187                 NG_UBT_ERR(
1188 "%s: %s - Invalid HCI event frame size, length=%d, pktlen=%d\n",
1189                         __func__, USBDEVNAME(sc->sc_dev), hdr->length, 
1190                         m->m_pkthdr.len);
1191
1192                 NG_UBT_STAT_IERROR(sc->sc_stat);
1193                 NG_FREE_M(m);
1194         }
1195 done:
1196         ubt_intr_start(sc);
1197 } /* ubt_intr_complete2 */
1198
1199 /*
1200  * Start bulk-in USB transfer (ACL data). Must be called when node is locked
1201  */
1202
1203 Static usbd_status
1204 ubt_bulk_in_start(ubt_softc_p sc)
1205 {
1206         struct mbuf     *m = NULL;
1207         usbd_status      status;
1208
1209         KASSERT(!(sc->sc_flags & UBT_ACL_RECV), (
1210 "%s: %s - Another bulk-in request is pending\n",
1211                 __func__, USBDEVNAME(sc->sc_dev)));
1212
1213         /* Allocate new mbuf cluster */
1214         MGETHDR(m, M_DONTWAIT, MT_DATA);
1215         if (m == NULL)
1216                 return (USBD_NOMEM);
1217
1218         MCLGET(m, M_DONTWAIT);
1219         if (!(m->m_flags & M_EXT)) {
1220                 NG_FREE_M(m);
1221                 return (USBD_NOMEM);
1222         }
1223
1224         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1225                 *mtod(m, u_int8_t *) = NG_HCI_ACL_DATA_PKT;
1226                 m->m_pkthdr.len = m->m_len = 1;
1227         } else
1228                 m->m_pkthdr.len = m->m_len = 0;
1229         
1230         /* Initialize a bulk-in USB transfer and then schedule it */
1231         usbd_setup_xfer(
1232                         sc->sc_bulk_in_xfer,
1233                         sc->sc_bulk_in_pipe,
1234                         (usbd_private_handle) sc->sc_node,
1235                         (void *)(mtod(m, u_int8_t *) + m->m_len),
1236                         MCLBYTES - m->m_len,
1237                         USBD_SHORT_XFER_OK,
1238                         USBD_NO_TIMEOUT,
1239                         ubt_bulk_in_complete);
1240
1241         NG_NODE_REF(sc->sc_node);
1242
1243         status = usbd_transfer(sc->sc_bulk_in_xfer);
1244         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1245                 NG_UBT_ERR(
1246 "%s: %s - Failed to start bulk-in transfer. %s (%d)\n",
1247                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1248                         status);
1249
1250                 NG_NODE_UNREF(sc->sc_node);
1251
1252                 NG_FREE_M(m);
1253
1254                 return (status);
1255         }
1256
1257         sc->sc_flags |= UBT_ACL_RECV;
1258         sc->sc_bulk_in_buffer = m;
1259
1260         return (USBD_NORMAL_COMPLETION);
1261 } /* ubt_bulk_in_start */
1262
1263 /*
1264  * USB bulk-in transfer callback
1265  */
1266
1267 Static void
1268 ubt_bulk_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1269 {
1270         ng_send_fn((node_p) p, NULL, ubt_bulk_in_complete2, (void *) h, s);
1271         NG_NODE_UNREF((node_p) p);
1272 } /* ubt_bulk_in_complete */
1273
1274 Static void
1275 ubt_bulk_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1276 {
1277         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1278         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1279         usbd_status              s = (usbd_status) arg2;
1280         struct mbuf             *m = NULL;
1281         ng_hci_acldata_pkt_t    *hdr = NULL;
1282         int                      len;
1283
1284         if (sc == NULL)
1285                 return;
1286
1287         KASSERT((sc->sc_flags & UBT_ACL_RECV), (
1288 "%s: %s - No bulk-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1289
1290         sc->sc_flags &= ~UBT_ACL_RECV;
1291
1292         m = sc->sc_bulk_in_buffer;
1293         sc->sc_bulk_in_buffer = NULL;
1294
1295         hdr = mtod(m, ng_hci_acldata_pkt_t *);
1296
1297         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1298                 NG_UBT_INFO(
1299 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1300
1301                 NG_FREE_M(m);
1302                 return;
1303         }
1304
1305         if (s == USBD_CANCELLED) {
1306                 NG_UBT_INFO(
1307 "%s: %s - Bulk-in xfer cancelled, pipe=%p\n",
1308                         __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_in_pipe);
1309
1310                 NG_FREE_M(m);
1311                 return;
1312         }
1313
1314         if (s != USBD_NORMAL_COMPLETION) {    
1315                 NG_UBT_WARN(
1316 "%s: %s - Bulk-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1317                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1318
1319                 if (s == USBD_STALLED)
1320                         usbd_clear_endpoint_stall_async(sc->sc_bulk_in_pipe);
1321
1322                 NG_UBT_STAT_IERROR(sc->sc_stat);
1323                 NG_FREE_M(m);
1324
1325                 return; /* XXX FIXME we should restart after some delay */
1326         }
1327
1328         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1329         m->m_pkthdr.len += h->actlen;
1330         m->m_len += h->actlen;
1331
1332         NG_UBT_INFO(
1333 "%s: %s - Got %d bytes from bulk-in pipe\n",
1334                 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1335
1336         if (m->m_pkthdr.len < sizeof(*hdr)) {
1337                 NG_FREE_M(m);
1338                 goto done;
1339         }
1340
1341         len = le16toh(hdr->length);
1342         if (len == m->m_pkthdr.len - sizeof(*hdr)) {
1343                 NG_UBT_INFO(
1344 "%s: %s - Got complete ACL data frame, pktlen=%d, length=%d\n",
1345                         __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len, len);
1346
1347                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1348
1349                 NG_SEND_DATA_ONLY(len, sc->sc_hook, m);
1350                 if (len != 0)
1351                         NG_UBT_STAT_IERROR(sc->sc_stat);
1352         } else {
1353                 NG_UBT_ERR(
1354 "%s: %s - Invalid ACL frame size, length=%d, pktlen=%d\n",
1355                         __func__, USBDEVNAME(sc->sc_dev), len,
1356                         m->m_pkthdr.len);
1357
1358                 NG_UBT_STAT_IERROR(sc->sc_stat);
1359                 NG_FREE_M(m);
1360         }
1361 done:
1362         ubt_bulk_in_start(sc);
1363 } /* ubt_bulk_in_complete2 */
1364
1365 /*
1366  * Start bulk-out USB transfer. Must be called with node locked
1367  */
1368
1369 Static usbd_status
1370 ubt_bulk_out_start(ubt_softc_p sc)
1371 {
1372         struct mbuf     *m = NULL;
1373         usbd_status     status;
1374
1375         KASSERT(!(sc->sc_flags & UBT_ACL_XMIT), (
1376 "%s: %s - Another bulk-out request is pending\n",
1377                 __func__, USBDEVNAME(sc->sc_dev)));
1378
1379         NG_BT_MBUFQ_DEQUEUE(&sc->sc_aclq, m);
1380         if (m == NULL) {
1381                 NG_UBT_INFO(
1382 "%s: %s - ACL data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1383
1384                 return (USBD_NORMAL_COMPLETION);
1385         }
1386
1387         /*
1388          * Check ACL data frame size and copy it back to linear USB 
1389          * transfer buffer.
1390          */ 
1391
1392         if (m->m_pkthdr.len > UBT_BULK_BUFFER_SIZE)
1393                 panic(
1394 "%s: %s - ACL data frame too big, size=%d, len=%d\n",
1395                         __func__, USBDEVNAME(sc->sc_dev), UBT_BULK_BUFFER_SIZE,
1396                         m->m_pkthdr.len);
1397
1398         m_copydata(m, 0, m->m_pkthdr.len, sc->sc_bulk_out_buffer);
1399
1400         /* Initialize a bulk-out USB transfer and then schedule it */
1401         usbd_setup_xfer(
1402                         sc->sc_bulk_out_xfer,
1403                         sc->sc_bulk_out_pipe,
1404                         (usbd_private_handle) sc->sc_node,
1405                         sc->sc_bulk_out_buffer,
1406                         m->m_pkthdr.len,
1407                         USBD_NO_COPY,
1408                         USBD_DEFAULT_TIMEOUT, /* XXX */
1409                         ubt_bulk_out_complete);
1410
1411         NG_NODE_REF(sc->sc_node);
1412
1413         status = usbd_transfer(sc->sc_bulk_out_xfer);
1414         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1415                 NG_UBT_ERR(
1416 "%s: %s - Could not start bulk-out transfer. %s (%d)\n",
1417                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1418                         status);
1419
1420                 NG_NODE_UNREF(sc->sc_node);
1421
1422                 NG_BT_MBUFQ_DROP(&sc->sc_aclq);
1423                 NG_UBT_STAT_OERROR(sc->sc_stat);
1424
1425                 /* XXX FIXME should we try to start another transfer? */
1426         } else {
1427                 NG_UBT_INFO(
1428 "%s: %s - Bulk-out transfer has been started, len=%d\n",
1429                         __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len);
1430
1431                 sc->sc_flags |= UBT_ACL_XMIT;
1432                 status = USBD_NORMAL_COMPLETION;
1433         }
1434
1435         NG_FREE_M(m);
1436
1437         return (status);
1438 } /* ubt_bulk_out_start */
1439
1440 /*
1441  * USB bulk-out transfer callback
1442  */
1443
1444 Static void
1445 ubt_bulk_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1446 {
1447         ng_send_fn((node_p) p,  NULL, ubt_bulk_out_complete2, (void *) h, s);
1448         NG_NODE_UNREF((node_p) p);
1449 } /* ubt_bulk_out_complete */
1450
1451 Static void
1452 ubt_bulk_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1453 {
1454         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1455         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
1456         usbd_status             s = (usbd_status) arg2;
1457
1458         if (sc == NULL)
1459                 return;
1460
1461         KASSERT((sc->sc_flags & UBT_ACL_XMIT), (
1462 "%s: %s - No bulk-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1463
1464         sc->sc_flags &= ~UBT_ACL_XMIT;
1465
1466         if (s == USBD_CANCELLED) {
1467                 NG_UBT_INFO(
1468 "%s: %s - Bulk-out xfer cancelled, pipe=%p\n",
1469                         __func__, USBDEVNAME(sc->sc_dev), sc->sc_bulk_out_pipe);
1470
1471                 return;
1472         }
1473
1474         if (s != USBD_NORMAL_COMPLETION) {    
1475                 NG_UBT_WARN(
1476 "%s: %s - Bulk-out xfer failed. %s (%d)\n",
1477                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1478
1479                 if (s == USBD_STALLED)
1480                         usbd_clear_endpoint_stall_async(sc->sc_bulk_out_pipe);
1481
1482                 NG_UBT_STAT_OERROR(sc->sc_stat);
1483         } else {
1484                 NG_UBT_INFO(
1485 "%s: %s - Sent %d bytes to bulk-out pipe\n",
1486                         __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1487
1488                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1489                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat); 
1490         }
1491
1492         if (NG_BT_MBUFQ_LEN(&sc->sc_aclq) > 0)
1493                 ubt_bulk_out_start(sc);
1494 } /* ubt_bulk_out_complete2 */
1495
1496 /*
1497  * Start Isochronous-in USB transfer. Must be called with node locked
1498  */
1499
1500 Static usbd_status
1501 ubt_isoc_in_start(ubt_softc_p sc)
1502 {
1503         usbd_status     status;
1504         int             i;
1505
1506         KASSERT(!(sc->sc_flags & UBT_SCO_RECV), (
1507 "%s: %s - Another isoc-in request is pending\n",
1508                 __func__, USBDEVNAME(sc->sc_dev)));
1509
1510         /* Initialize a isoc-in USB transfer and then schedule it */
1511         for (i = 0; i < sc->sc_isoc_nframes; i++)
1512                 sc->sc_isoc_in_frlen[i] = sc->sc_isoc_size;
1513
1514         usbd_setup_isoc_xfer(
1515                         sc->sc_isoc_in_xfer,
1516                         sc->sc_isoc_in_pipe,
1517                         (usbd_private_handle) sc->sc_node,
1518                         sc->sc_isoc_in_frlen,
1519                         sc->sc_isoc_nframes,
1520                         USBD_NO_COPY, /* XXX flags */
1521                         ubt_isoc_in_complete);
1522
1523         NG_NODE_REF(sc->sc_node);
1524
1525         status = usbd_transfer(sc->sc_isoc_in_xfer);
1526         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1527                 NG_UBT_ERR(
1528 "%s: %s - Failed to start isoc-in transfer. %s (%d)\n",
1529                         __func__, USBDEVNAME(sc->sc_dev),
1530                         usbd_errstr(status), status);
1531
1532                 NG_NODE_UNREF(sc->sc_node);
1533
1534                 return (status);
1535         }
1536
1537         sc->sc_flags |= UBT_SCO_RECV;
1538
1539         return (USBD_NORMAL_COMPLETION);
1540 } /* ubt_isoc_in_start */
1541
1542 /*
1543  * USB isochronous transfer callback
1544  */
1545
1546 Static void
1547 ubt_isoc_in_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1548 {
1549         ng_send_fn((node_p) p, NULL, ubt_isoc_in_complete2, (void *) h, s);
1550         NG_NODE_UNREF((node_p) p);
1551 } /* ubt_isoc_in_complete */
1552
1553 Static void
1554 ubt_isoc_in_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1555 {
1556         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1557         usbd_xfer_handle         h = (usbd_xfer_handle) arg1;
1558         usbd_status              s = (usbd_status) arg2;
1559         struct mbuf             *m = NULL;
1560         ng_hci_scodata_pkt_t    *hdr = NULL;
1561         u_int8_t                *b = NULL;
1562         int                      i;
1563
1564         if (sc == NULL)
1565                 return;
1566
1567         KASSERT((sc->sc_flags & UBT_SCO_RECV), (
1568 "%s: %s - No isoc-in request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1569
1570         sc->sc_flags &= ~UBT_SCO_RECV;
1571
1572         if (sc->sc_hook == NULL || NG_HOOK_NOT_VALID(sc->sc_hook)) {
1573                 NG_UBT_INFO(
1574 "%s: %s - No upstream hook\n", __func__, USBDEVNAME(sc->sc_dev));
1575
1576                 return;
1577         }
1578
1579         if (s == USBD_CANCELLED) {
1580                 NG_UBT_INFO(
1581 "%s: %s - Isoc-in xfer cancelled, pipe=%p\n",
1582                         __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_in_pipe);
1583
1584                 return;
1585         }
1586
1587         if (s != USBD_NORMAL_COMPLETION) {    
1588                 NG_UBT_WARN(
1589 "%s: %s - Isoc-in xfer failed, %s (%d). No new xfer will be submitted!\n",
1590                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1591
1592                 if (s == USBD_STALLED)
1593                         usbd_clear_endpoint_stall_async(sc->sc_isoc_in_pipe);
1594
1595                 NG_UBT_STAT_IERROR(sc->sc_stat);
1596
1597                 return; /* XXX FIXME we should restart after some delay */
1598         }
1599
1600         NG_UBT_STAT_BYTES_RECV(sc->sc_stat, h->actlen);
1601
1602         NG_UBT_INFO(
1603 "%s: %s - Got %d bytes from isoc-in pipe\n",
1604                 __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1605
1606         /* Copy SCO data frame to mbuf */
1607         MGETHDR(m, M_DONTWAIT, MT_DATA);
1608         if (m == NULL) {
1609                 NG_UBT_ALERT(
1610 "%s: %s - Could not allocate mbuf\n",
1611                         __func__, USBDEVNAME(sc->sc_dev));
1612
1613                 NG_UBT_STAT_IERROR(sc->sc_stat);
1614                 goto done;
1615         }
1616
1617         /* Fix SCO data frame header if required */
1618         if (!(sc->sc_flags & UBT_HAVE_FRAME_TYPE)) {
1619                 *mtod(m, u_int8_t *) = NG_HCI_SCO_DATA_PKT;
1620                 m->m_pkthdr.len = 1;
1621                 m->m_len = min(MHLEN, h->actlen + 1); /* XXX m_copyback */
1622         } else {
1623                 m->m_pkthdr.len = 0;
1624                 m->m_len = min(MHLEN, h->actlen); /* XXX m_copyback */
1625         }
1626
1627         /*
1628          * XXX FIXME how do we know how many frames we have received?
1629          * XXX use frlen for now. is that correct?
1630          */
1631
1632         b = (u_int8_t *) sc->sc_isoc_in_buffer;
1633
1634         for (i = 0; i < sc->sc_isoc_nframes; i++) {
1635                 b += (i * sc->sc_isoc_size);
1636
1637                 if (sc->sc_isoc_in_frlen[i] > 0)
1638                         m_copyback(m, m->m_pkthdr.len,
1639                                 sc->sc_isoc_in_frlen[i], b);
1640         }
1641
1642         if (m->m_pkthdr.len < sizeof(*hdr))
1643                 goto done;
1644
1645         hdr = mtod(m, ng_hci_scodata_pkt_t *);
1646
1647         if (hdr->length == m->m_pkthdr.len - sizeof(*hdr)) {
1648                 NG_UBT_INFO(
1649 "%s: %s - Got complete SCO data frame, pktlen=%d, length=%d\n",
1650                         __func__, USBDEVNAME(sc->sc_dev), m->m_pkthdr.len,
1651                         hdr->length);
1652
1653                 NG_UBT_STAT_PCKTS_RECV(sc->sc_stat);
1654
1655                 NG_SEND_DATA_ONLY(i, sc->sc_hook, m);
1656                 if (i != 0)
1657                         NG_UBT_STAT_IERROR(sc->sc_stat);
1658         } else {
1659                 NG_UBT_ERR(
1660 "%s: %s - Invalid SCO frame size, length=%d, pktlen=%d\n",
1661                         __func__, USBDEVNAME(sc->sc_dev), hdr->length, 
1662                         m->m_pkthdr.len);
1663
1664                 NG_UBT_STAT_IERROR(sc->sc_stat);
1665                 NG_FREE_M(m);
1666         }
1667 done:
1668         ubt_isoc_in_start(sc);
1669 } /* ubt_isoc_in_complete2 */
1670
1671 /*
1672  * Start isochronous-out USB transfer. Must be called with node locked
1673  */
1674
1675 Static usbd_status
1676 ubt_isoc_out_start(ubt_softc_p sc)
1677 {
1678         struct mbuf     *m = NULL;
1679         u_int8_t        *b = NULL;
1680         int              i, len, nframes;
1681         usbd_status      status;
1682
1683         KASSERT(!(sc->sc_flags & UBT_SCO_XMIT), (
1684 "%s: %s - Another isoc-out request is pending\n",
1685                 __func__, USBDEVNAME(sc->sc_dev)));
1686
1687         NG_BT_MBUFQ_DEQUEUE(&sc->sc_scoq, m);
1688         if (m == NULL) {
1689                 NG_UBT_INFO(
1690 "%s: %s - SCO data queue is empty\n", __func__, USBDEVNAME(sc->sc_dev));
1691
1692                 return (USBD_NORMAL_COMPLETION);
1693         }
1694
1695         /* Copy entire SCO frame into USB transfer buffer and start transfer */ 
1696         b = (u_int8_t *) sc->sc_isoc_out_buffer;
1697         nframes = 0;
1698
1699         for (i = 0; i < sc->sc_isoc_nframes; i++) {
1700                 b += (i * sc->sc_isoc_size);
1701
1702                 len = min(m->m_pkthdr.len, sc->sc_isoc_size);
1703                 if (len > 0) {
1704                         m_copydata(m, 0, len, b);
1705                         m_adj(m, len);
1706                         nframes ++;
1707                 }
1708
1709                 sc->sc_isoc_out_frlen[i] = len;
1710         }
1711
1712         if (m->m_pkthdr.len > 0)
1713                 panic(
1714 "%s: %s - SCO data frame is too big, nframes=%d, size=%d, len=%d\n",
1715                         __func__, USBDEVNAME(sc->sc_dev), sc->sc_isoc_nframes,
1716                         sc->sc_isoc_size, m->m_pkthdr.len);
1717
1718         NG_FREE_M(m);
1719
1720         /* Initialize a isoc-out USB transfer and then schedule it */
1721         usbd_setup_isoc_xfer(
1722                         sc->sc_isoc_out_xfer,
1723                         sc->sc_isoc_out_pipe,
1724                         (usbd_private_handle) sc->sc_node,
1725                         sc->sc_isoc_out_frlen,
1726                         nframes,
1727                         USBD_NO_COPY,
1728                         ubt_isoc_out_complete);
1729
1730         NG_NODE_REF(sc->sc_node);
1731
1732         status = usbd_transfer(sc->sc_isoc_out_xfer);
1733         if (status != USBD_NORMAL_COMPLETION && status != USBD_IN_PROGRESS) {
1734                 NG_UBT_ERR(
1735 "%s: %s - Could not start isoc-out transfer. %s (%d)\n",
1736                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1737                         status);
1738
1739                 NG_NODE_UNREF(sc->sc_node);
1740
1741                 NG_BT_MBUFQ_DROP(&sc->sc_scoq);
1742                 NG_UBT_STAT_OERROR(sc->sc_stat);
1743         } else {
1744                 NG_UBT_INFO(
1745 "%s: %s - Isoc-out transfer has been started, nframes=%d, size=%d\n",
1746                         __func__, USBDEVNAME(sc->sc_dev), nframes,
1747                         sc->sc_isoc_size);
1748
1749                 sc->sc_flags |= UBT_SCO_XMIT;
1750                 status = USBD_NORMAL_COMPLETION;
1751         }
1752
1753         return (status);
1754 } /* ubt_isoc_out_start */
1755
1756 /*
1757  * USB isoc-out. transfer callback
1758  */
1759
1760 Static void
1761 ubt_isoc_out_complete(usbd_xfer_handle h, usbd_private_handle p, usbd_status s)
1762 {
1763         ng_send_fn((node_p) p, NULL, ubt_isoc_out_complete2, (void *) h, s);
1764         NG_NODE_UNREF((node_p) p);
1765 } /* ubt_isoc_out_complete */
1766
1767 Static void
1768 ubt_isoc_out_complete2(node_p node, hook_p hook, void *arg1, int arg2)
1769 {
1770         ubt_softc_p             sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1771         usbd_xfer_handle        h = (usbd_xfer_handle) arg1;
1772         usbd_status             s = (usbd_status) arg2;
1773
1774         if (sc == NULL)
1775                 return;
1776
1777         KASSERT((sc->sc_flags & UBT_SCO_XMIT), (
1778 "%s: %s - No isoc-out request is pending\n", __func__, USBDEVNAME(sc->sc_dev)));
1779
1780         sc->sc_flags &= ~UBT_SCO_XMIT;
1781
1782         if (s == USBD_CANCELLED) {
1783                 NG_UBT_INFO(
1784 "%s: %s - Isoc-out xfer cancelled, pipe=%p\n",
1785                         __func__, USBDEVNAME(sc->sc_dev),
1786                         sc->sc_isoc_out_pipe);
1787
1788                 return;
1789         }
1790
1791         if (s != USBD_NORMAL_COMPLETION) {    
1792                 NG_UBT_WARN(
1793 "%s: %s - Isoc-out xfer failed. %s (%d)\n",
1794                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(s), s);
1795
1796                 if (s == USBD_STALLED)
1797                         usbd_clear_endpoint_stall_async(sc->sc_isoc_out_pipe);
1798
1799                 NG_UBT_STAT_OERROR(sc->sc_stat);
1800         } else {
1801                 NG_UBT_INFO(
1802 "%s: %s - Sent %d bytes to isoc-out pipe\n",
1803                         __func__, USBDEVNAME(sc->sc_dev), h->actlen);
1804
1805                 NG_UBT_STAT_BYTES_SENT(sc->sc_stat, h->actlen);
1806                 NG_UBT_STAT_PCKTS_SENT(sc->sc_stat);
1807         }
1808
1809         if (NG_BT_MBUFQ_LEN(&sc->sc_scoq) > 0)
1810                 ubt_isoc_out_start(sc);
1811 } /* ubt_isoc_out_complete2 */
1812
1813 /*
1814  * Abort transfers on all USB pipes
1815  */
1816
1817 Static void
1818 ubt_reset(ubt_softc_p sc)
1819 {
1820         /* Interrupt */
1821         if (sc->sc_intr_pipe != NULL)
1822                 usbd_abort_pipe(sc->sc_intr_pipe);
1823
1824         /* Bulk-in/out */
1825         if (sc->sc_bulk_in_pipe != NULL)
1826                 usbd_abort_pipe(sc->sc_bulk_in_pipe);
1827         if (sc->sc_bulk_out_pipe != NULL)
1828                 usbd_abort_pipe(sc->sc_bulk_out_pipe);
1829
1830         /* Isoc-in/out */
1831         if (sc->sc_isoc_in_pipe != NULL)
1832                 usbd_abort_pipe(sc->sc_isoc_in_pipe);
1833         if (sc->sc_isoc_out_pipe != NULL)
1834                 usbd_abort_pipe(sc->sc_isoc_out_pipe);
1835
1836         /* Cleanup queues */
1837         NG_BT_MBUFQ_DRAIN(&sc->sc_cmdq);
1838         NG_BT_MBUFQ_DRAIN(&sc->sc_aclq);
1839         NG_BT_MBUFQ_DRAIN(&sc->sc_scoq);
1840 } /* ubt_reset */
1841
1842 /****************************************************************************
1843  ****************************************************************************
1844  **                        Netgraph specific
1845  ****************************************************************************
1846  ****************************************************************************/
1847
1848 /*
1849  * Netgraph node constructor. Do not allow to create node of this type.
1850  */
1851
1852 Static int
1853 ng_ubt_constructor(node_p node)
1854 {
1855         return (EINVAL);
1856 } /* ng_ubt_constructor */
1857
1858 /*
1859  * Netgraph node destructor. Destroy node only when device has been detached
1860  */
1861
1862 Static int
1863 ng_ubt_shutdown(node_p node)
1864 {
1865         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1866
1867         /* Let old node go */
1868         NG_NODE_SET_PRIVATE(node, NULL);
1869         NG_NODE_UNREF(node);
1870         
1871         if (sc == NULL)
1872                 goto done;
1873
1874         /* Create Netgraph node */
1875         if (ng_make_node_common(&typestruct, &sc->sc_node) != 0) {
1876                 printf("%s: Could not create Netgraph node\n",
1877                         USBDEVNAME(sc->sc_dev));
1878                 sc->sc_node = NULL;
1879                 goto done;
1880         }
1881         
1882         /* Name node */ 
1883         if (ng_name_node(sc->sc_node, USBDEVNAME(sc->sc_dev)) != 0) {
1884                 printf("%s: Could not name Netgraph node\n",
1885                         USBDEVNAME(sc->sc_dev));
1886                 NG_NODE_UNREF(sc->sc_node);
1887                 sc->sc_node = NULL;
1888                 goto done;
1889         }
1890
1891         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
1892         NG_NODE_FORCE_WRITER(sc->sc_node);
1893 done:
1894         return (0);
1895 } /* ng_ubt_shutdown */
1896
1897 /*
1898  * Create new hook. There can only be one.
1899  */
1900
1901 Static int
1902 ng_ubt_newhook(node_p node, hook_p hook, char const *name)
1903 {
1904         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
1905
1906         /* Refuse to create new hook if device interface is active */
1907         if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1908             sc->sc_bulk_dev != NULL)
1909                 return (EBUSY);
1910
1911         if (strcmp(name, NG_UBT_HOOK) != 0)
1912                 return (EINVAL);
1913
1914         if (sc->sc_hook != NULL)
1915                 return (EISCONN);
1916
1917         sc->sc_hook = hook;
1918
1919         return (0);
1920 } /* ng_ubt_newhook */
1921
1922 /*
1923  * Connect hook. Start incoming USB transfers
1924  */
1925
1926 Static int
1927 ng_ubt_connect(hook_p hook)
1928 {
1929         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1930         usbd_status     status;
1931
1932         /* Refuse to connect hook if device interface is active */
1933         if (sc->sc_ctrl_dev != NULL || sc->sc_intr_dev != NULL ||
1934             sc->sc_bulk_dev != NULL)
1935                 return (EBUSY);
1936
1937         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
1938
1939         /* Start intr transfer */
1940         status = ubt_intr_start(sc);
1941         if (status != USBD_NORMAL_COMPLETION) {
1942                 NG_UBT_ALERT(
1943 "%s: %s - Could not start interrupt transfer. %s (%d)\n",
1944                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1945                         status);
1946                 goto fail;
1947         }
1948
1949         /* Start bulk-in transfer */
1950         status = ubt_bulk_in_start(sc);
1951         if (status != USBD_NORMAL_COMPLETION) {
1952                 NG_UBT_ALERT(
1953 "%s: %s - Could not start bulk-in transfer. %s (%d)\n",
1954                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1955                         status);
1956                 goto fail;
1957         }
1958
1959 #if __broken__ /* XXX FIXME */
1960         /* Start isoc-in transfer */
1961         status = ubt_isoc_in_start(sc);
1962         if (status != USBD_NORMAL_COMPLETION) {
1963                 NG_UBT_ALERT(
1964 "%s: %s - Could not start isoc-in transfer. %s (%d)\n",
1965                         __func__, USBDEVNAME(sc->sc_dev), usbd_errstr(status),
1966                         status);
1967                 goto fail;
1968         }
1969 #endif /* __broken__ */
1970
1971         return (0);
1972 fail:
1973         ubt_reset(sc);
1974         sc->sc_hook = NULL;
1975
1976         return (ENXIO);
1977 } /* ng_ubt_connect */
1978
1979 /*
1980  * Disconnect hook
1981  */
1982
1983 Static int
1984 ng_ubt_disconnect(hook_p hook)
1985 {
1986         ubt_softc_p     sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
1987
1988         if (sc != NULL) {
1989                 if (hook != sc->sc_hook)
1990                         return (EINVAL);
1991
1992                 ubt_reset(sc);
1993                 sc->sc_hook = NULL;
1994         }
1995
1996         return (0);
1997 } /* ng_ubt_disconnect */
1998
1999 /*
2000  * Process control message
2001  */
2002
2003 Static int
2004 ng_ubt_rcvmsg(node_p node, item_p item, hook_p lasthook)
2005 {
2006         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(node);
2007         struct ng_mesg          *msg = NULL, *rsp = NULL;
2008         struct ng_bt_mbufq      *q = NULL;
2009         int                      error = 0, queue, qlen;
2010
2011         if (sc == NULL) {
2012                 NG_FREE_ITEM(item);
2013                 return (EHOSTDOWN);
2014         }
2015
2016         NGI_GET_MSG(item, msg);
2017
2018         switch (msg->header.typecookie) {
2019         case NGM_GENERIC_COOKIE:
2020                 switch (msg->header.cmd) {
2021                 case NGM_TEXT_STATUS:
2022                         NG_MKRESPONSE(rsp, msg, NG_TEXTRESPONSE, M_NOWAIT);
2023                         if (rsp == NULL)
2024                                 error = ENOMEM;
2025                         else
2026                                 snprintf(rsp->data, NG_TEXTRESPONSE,
2027                                         "Hook: %s\n"   \
2028                                         "Flags: %#x\n" \
2029                                         "Debug: %d\n"  \
2030                                         "CMD queue: [have:%d,max:%d]\n" \
2031                                         "ACL queue: [have:%d,max:%d]\n" \
2032                                         "SCO queue: [have:%d,max:%d]",
2033                                         (sc->sc_hook != NULL)? NG_UBT_HOOK : "",
2034                                         sc->sc_flags,
2035                                         sc->sc_debug,
2036                                         NG_BT_MBUFQ_LEN(&sc->sc_cmdq),
2037                                         sc->sc_cmdq.maxlen,
2038                                         NG_BT_MBUFQ_LEN(&sc->sc_aclq),
2039                                         sc->sc_aclq.maxlen,
2040                                         NG_BT_MBUFQ_LEN(&sc->sc_scoq),
2041                                         sc->sc_scoq.maxlen);
2042                         break;
2043
2044                 default:
2045                         error = EINVAL;
2046                         break;
2047                 }
2048                 break;
2049
2050         case NGM_UBT_COOKIE:
2051                 switch (msg->header.cmd) {
2052                 case NGM_UBT_NODE_SET_DEBUG:
2053                         if (msg->header.arglen != sizeof(ng_ubt_node_debug_ep))
2054                                 error = EMSGSIZE;
2055                         else
2056                                 sc->sc_debug =
2057                                         *((ng_ubt_node_debug_ep *)(msg->data));
2058                         break;
2059
2060                 case NGM_UBT_NODE_GET_DEBUG:
2061                         NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_debug_ep),
2062                                 M_NOWAIT);
2063                         if (rsp == NULL)
2064                                 error = ENOMEM;
2065                         else
2066                                 *((ng_ubt_node_debug_ep *)(rsp->data)) = 
2067                                         sc->sc_debug;
2068                         break;
2069
2070                 case NGM_UBT_NODE_SET_QLEN:
2071                         if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep))
2072                                 error = EMSGSIZE;
2073                         else {
2074                                 queue = ((ng_ubt_node_qlen_ep *)
2075                                                 (msg->data))->queue;
2076                                 qlen = ((ng_ubt_node_qlen_ep *)
2077                                                 (msg->data))->qlen;
2078
2079                                 if (qlen <= 0) {
2080                                         error = EINVAL;
2081                                         break;
2082                                 }
2083
2084                                 switch (queue) {
2085                                 case NGM_UBT_NODE_QUEUE_CMD:
2086                                         q = &sc->sc_cmdq;
2087                                         break;
2088
2089                                 case NGM_UBT_NODE_QUEUE_ACL:
2090                                         q = &sc->sc_aclq;
2091                                         break;
2092
2093                                 case NGM_UBT_NODE_QUEUE_SCO:
2094                                         q = &sc->sc_scoq;
2095                                         break;
2096
2097                                 default:
2098                                         q = NULL;
2099                                         error = EINVAL;
2100                                         break;
2101                                 }
2102
2103                                 if (q != NULL)
2104                                         q->maxlen = qlen;
2105                         }
2106                         break;
2107
2108                 case NGM_UBT_NODE_GET_QLEN:
2109                         if (msg->header.arglen != sizeof(ng_ubt_node_qlen_ep)) {
2110                                 error = EMSGSIZE;
2111                                 break;
2112                         }
2113
2114                         queue = ((ng_ubt_node_qlen_ep *)(msg->data))->queue;
2115                         switch (queue) {
2116                         case NGM_UBT_NODE_QUEUE_CMD:
2117                                 q = &sc->sc_cmdq;
2118                                 break;
2119
2120                         case NGM_UBT_NODE_QUEUE_ACL:
2121                                 q = &sc->sc_aclq;
2122                                 break;
2123
2124                         case NGM_UBT_NODE_QUEUE_SCO:
2125                                 q = &sc->sc_scoq;
2126                                 break;
2127
2128                         default:
2129                                 q = NULL;
2130                                 error = EINVAL;
2131                                 break;
2132                         }
2133
2134                         if (q != NULL) {
2135                                 NG_MKRESPONSE(rsp, msg, 
2136                                         sizeof(ng_ubt_node_qlen_ep), M_NOWAIT);
2137                                 if (rsp == NULL) {
2138                                         error = ENOMEM;
2139                                         break;
2140                                 }
2141
2142                                 ((ng_ubt_node_qlen_ep *)(rsp->data))->queue =
2143                                         queue;
2144                                 ((ng_ubt_node_qlen_ep *)(rsp->data))->qlen =
2145                                         q->maxlen;
2146                         }
2147                         break;
2148
2149                 case NGM_UBT_NODE_GET_STAT:
2150                         NG_MKRESPONSE(rsp, msg, sizeof(ng_ubt_node_stat_ep),
2151                                 M_NOWAIT);
2152                         if (rsp == NULL)
2153                                 error = ENOMEM;
2154                         else
2155                                 bcopy(&sc->sc_stat, rsp->data,
2156                                         sizeof(ng_ubt_node_stat_ep));
2157                         break;
2158
2159                 case NGM_UBT_NODE_RESET_STAT:
2160                         NG_UBT_STAT_RESET(sc->sc_stat);
2161                         break;
2162
2163                 case NGM_UBT_NODE_DEV_NODES:
2164                         if (msg->header.arglen !=
2165                                         sizeof(ng_ubt_node_dev_nodes_ep)) {
2166                                 error = EMSGSIZE;
2167                                 break;
2168                         }
2169
2170                         if ((sc->sc_flags & UBT_ANY_DEV) || 
2171                             sc->sc_hook != NULL) {
2172                                 error = EBUSY;
2173                                 break;
2174                         }
2175
2176                         if (*((ng_ubt_node_dev_nodes_ep *)(msg->data)))
2177                                 ubt_create_device_nodes(sc);
2178                         else
2179                                 ubt_destroy_device_nodes(sc);
2180                         break;
2181
2182                 default:
2183                         error = EINVAL;
2184                         break;
2185                 }
2186                 break;
2187
2188         default:
2189                 error = EINVAL;
2190                 break;
2191         }
2192
2193         NG_RESPOND_MSG(error, node, item, rsp);
2194         NG_FREE_MSG(msg);
2195
2196         return (error);
2197 } /* ng_ubt_rcvmsg */
2198
2199 /*
2200  * Process data
2201  */
2202
2203 Static int
2204 ng_ubt_rcvdata(hook_p hook, item_p item)
2205 {
2206         ubt_softc_p              sc = (ubt_softc_p) NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
2207         struct mbuf             *m = NULL;
2208         usbd_status             (*f)(ubt_softc_p) = NULL;
2209         struct ng_bt_mbufq      *q = NULL;
2210         int                      b, error = 0;
2211
2212         if (sc == NULL) {
2213                 error = EHOSTDOWN;
2214                 goto done;
2215         }
2216
2217         if (hook != sc->sc_hook) {
2218                 error = EINVAL;
2219                 goto done;
2220         }
2221
2222         /* Deatch mbuf and get HCI frame type */
2223         NGI_GET_M(item, m);
2224
2225         /* Process HCI frame */
2226         switch (*mtod(m, u_int8_t *)) { /* XXX call m_pullup ? */
2227         case NG_HCI_CMD_PKT:
2228                 f = ubt_request_start;
2229                 q = &sc->sc_cmdq;
2230                 b = UBT_CMD_XMIT;
2231                 break;
2232
2233         case NG_HCI_ACL_DATA_PKT:
2234                 f = ubt_bulk_out_start;
2235                 q = &sc->sc_aclq;
2236                 b = UBT_ACL_XMIT;
2237                 break;
2238
2239 #if __broken__ /* XXX FIXME */
2240         case NG_HCI_SCO_DATA_PKT:
2241                 f = ubt_isoc_out_start;
2242                 q = &sc->sc_scoq;
2243                 b = UBT_SCO_XMIT;
2244                 break;
2245 #endif /* __broken__ */
2246
2247         default:
2248                 NG_UBT_ERR(
2249 "%s: %s - Dropping unknown/unsupported HCI frame, type=%d, pktlen=%d\n",
2250                         __func__, USBDEVNAME(sc->sc_dev), *mtod(m, u_int8_t *),
2251                         m->m_pkthdr.len);
2252
2253                 NG_FREE_M(m);
2254                 error = EINVAL;
2255
2256                 goto done;
2257                 /* NOT REACHED */
2258         }
2259
2260         /* Loose frame type, if required */
2261         if (!(sc->sc_flags & UBT_NEED_FRAME_TYPE))
2262                 m_adj(m, sizeof(u_int8_t)); 
2263
2264         if (NG_BT_MBUFQ_FULL(q)) {
2265                 NG_UBT_ERR(
2266 "%s: %s - Dropping HCI frame %#x, len=%d. Queue full\n",
2267                         __func__, USBDEVNAME(sc->sc_dev),
2268                         *mtod(m, u_int8_t *), m->m_pkthdr.len);
2269
2270                 NG_FREE_M(m);
2271         } else
2272                 NG_BT_MBUFQ_ENQUEUE(q, m);
2273
2274         if (!(sc->sc_flags & b))
2275                 if ((*f)(sc) != USBD_NORMAL_COMPLETION)
2276                         error = EIO;
2277 done:
2278         NG_FREE_ITEM(item);
2279
2280         return (error);
2281 } /* ng_ubt_rcvdata */
2282
2283 /****************************************************************************
2284  ****************************************************************************
2285  **                              Device specific
2286  ****************************************************************************
2287  ****************************************************************************/
2288
2289 /*
2290  * Open endpoint device
2291  * XXX FIXME softc locking
2292  */
2293
2294 Static int
2295 ubt_open(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2296 {
2297         ubt_softc_p     sc = NULL;
2298         int             ep = UBT_ENDPOINT(dev);
2299
2300         USB_GET_SC_OPEN(ubt, UBT_UNIT(dev), sc); /* check for sc != NULL */
2301         if (sc->sc_dying)
2302                 return (ENXIO);
2303
2304         if (ep == USB_CONTROL_ENDPOINT) {
2305                 if (sc->sc_flags & UBT_CTRL_DEV)
2306                         return (EBUSY);
2307
2308                 sc->sc_flags |= UBT_CTRL_DEV;
2309         } else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2310                 if (sc->sc_flags & UBT_INTR_DEV)
2311                         return (EBUSY);
2312                 if (sc->sc_intr_pipe == NULL)
2313                         return (ENXIO);
2314
2315                 sc->sc_flags |= UBT_INTR_DEV;
2316         } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2317                 if (sc->sc_flags & UBT_BULK_DEV)
2318                         return (EBUSY);
2319                 if (sc->sc_bulk_in_pipe == NULL || sc->sc_bulk_out_pipe == NULL)
2320                         return (ENXIO);
2321
2322                 sc->sc_flags |= UBT_BULK_DEV;
2323         } else
2324                 return (EINVAL);
2325
2326         return (0);
2327 } /* ubt_open */
2328
2329 /*
2330  * Close endpoint device
2331  * XXX FIXME softc locking
2332  */
2333
2334 Static int
2335 ubt_close(struct cdev *dev, int flag, int mode, usb_proc_ptr p)
2336 {
2337         ubt_softc_p     sc = NULL;
2338         int             ep = UBT_ENDPOINT(dev);
2339
2340         USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2341         if (sc == NULL)
2342                 return (ENXIO);
2343
2344         if (ep == USB_CONTROL_ENDPOINT)
2345                 sc->sc_flags &= ~UBT_CTRL_DEV;
2346         else if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2347                 if (sc->sc_intr_pipe != NULL)
2348                         usbd_abort_pipe(sc->sc_intr_pipe);
2349
2350                 sc->sc_flags &= ~UBT_INTR_DEV;
2351         } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2352                 /* Close both in and out bulk pipes */
2353                 if (sc->sc_bulk_in_pipe != NULL)
2354                         usbd_abort_pipe(sc->sc_bulk_in_pipe);
2355
2356                 if (sc->sc_bulk_out_pipe != NULL)
2357                         usbd_abort_pipe(sc->sc_bulk_out_pipe);
2358
2359                 sc->sc_flags &= ~UBT_BULK_DEV;
2360         } else
2361                 return (EINVAL);
2362
2363         return (0);
2364 } /* ubt_close */
2365
2366 /*
2367  * Read from the endpoint device
2368  * XXX FIXME softc locking
2369  */
2370
2371 Static int
2372 ubt_read(struct cdev *dev, struct uio *uio, int flag)
2373 {
2374         ubt_softc_p             sc = NULL;
2375         int                     error = 0, n, tn, ep = UBT_ENDPOINT(dev);
2376         usbd_status             status;
2377         usbd_pipe_handle        pipe = NULL;
2378         usbd_xfer_handle        xfer = NULL;
2379         u_int8_t                buf[UBT_BSIZE];
2380
2381         USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2382         if (sc == NULL || sc->sc_dying)
2383                 return (ENXIO);
2384
2385         if (ep == USB_CONTROL_ENDPOINT)
2386                 return (EOPNOTSUPP);
2387
2388         if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2389                 pipe = sc->sc_intr_pipe;
2390                 xfer = sc->sc_intr_xfer;
2391         } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2392                 pipe = sc->sc_bulk_in_pipe;
2393                 xfer = sc->sc_bulk_in_xfer;
2394         } else
2395                 return (EINVAL);
2396
2397         if (pipe == NULL || xfer == NULL)
2398                 return (ENXIO);
2399
2400         sc->sc_refcnt ++;
2401
2402         while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2403                 tn = n;
2404                 status = usbd_bulk_transfer(xfer, pipe, USBD_SHORT_XFER_OK,
2405                                 USBD_DEFAULT_TIMEOUT, buf, &tn, "ubtrd");
2406                 switch (status) {
2407                 case USBD_NORMAL_COMPLETION:
2408                         error = uiomove(buf, tn, uio);
2409                         break;
2410
2411                 case USBD_INTERRUPTED:
2412                         error = EINTR;
2413                         break;
2414
2415                 case USBD_TIMEOUT:
2416                         error = ETIMEDOUT;
2417                         break;
2418
2419                 default:
2420                         error = EIO;
2421                         break;
2422                 }
2423
2424                 if (error != 0 || tn < n)
2425                         break;
2426         }
2427
2428         if (-- sc->sc_refcnt < 0)
2429                 usb_detach_wakeup(USBDEV(sc->sc_dev));
2430
2431         return (error);
2432 } /* ubt_read */
2433
2434 /*
2435  * Write into the endpoint device
2436  * XXX FIXME softc locking
2437  */
2438
2439 Static int
2440 ubt_write(struct cdev *dev, struct uio *uio, int flag)
2441 {
2442         ubt_softc_p     sc = NULL;
2443         int             error = 0, n, ep = UBT_ENDPOINT(dev);
2444         usbd_status     status;
2445         u_int8_t        buf[UBT_BSIZE];
2446
2447         USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2448         if (sc == NULL || sc->sc_dying)
2449                 return (ENXIO);
2450
2451         if (ep == USB_CONTROL_ENDPOINT || ep == UE_GET_ADDR(sc->sc_intr_ep))
2452                 return (EOPNOTSUPP);
2453         if (ep != UE_GET_ADDR(sc->sc_bulk_in_ep))
2454                 return (EINVAL);
2455
2456         sc->sc_refcnt ++;
2457
2458         while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
2459                 error = uiomove(buf, n, uio);
2460                 if (error != 0)
2461                         break;
2462
2463                 status = usbd_bulk_transfer(sc->sc_bulk_out_xfer,
2464                                 sc->sc_bulk_out_pipe, 0, USBD_DEFAULT_TIMEOUT,
2465                                 buf, &n,"ubtwr");
2466                 switch (status) {
2467                 case USBD_NORMAL_COMPLETION:
2468                         break;
2469
2470                 case USBD_INTERRUPTED:
2471                         error = EINTR;
2472                         break;
2473
2474                 case USBD_TIMEOUT:
2475                         error = ETIMEDOUT;
2476                         break;
2477
2478                 default:
2479                         error = EIO;
2480                         break;
2481                 }
2482
2483                 if (error != 0)
2484                         break;
2485         }
2486
2487         if (-- sc->sc_refcnt < 0)
2488                 usb_detach_wakeup(USBDEV(sc->sc_dev));
2489
2490         return (error);
2491 } /* ubt_write */
2492
2493 /*
2494  * Process ioctl on the endpoint device. Mostly stolen from ugen(4)
2495  * XXX FIXME softc locking
2496  */
2497
2498 Static int
2499 ubt_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
2500 {
2501         ubt_softc_p              sc = NULL;
2502         int                      len, error = 0, ep = UBT_ENDPOINT(dev);
2503         usbd_status              status;
2504         struct usb_string_desc  *si = NULL;
2505         struct usb_ctl_request  *ur = NULL;
2506         void                    *ptr = NULL;
2507         struct iovec             iov;
2508         struct uio               uio;
2509
2510         USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2511         if (sc == NULL || sc->sc_dying)
2512                 return (ENXIO);
2513
2514         if (ep != USB_CONTROL_ENDPOINT)
2515                 return (EOPNOTSUPP);
2516
2517         sc->sc_refcnt ++;
2518
2519         switch (cmd) {
2520         case USB_GET_DEVICE_DESC:
2521                 *(usb_device_descriptor_t *) data =
2522                                 *usbd_get_device_descriptor(sc->sc_udev);
2523                 break;
2524
2525         case USB_GET_STRING_DESC:
2526                 si = (struct usb_string_desc *) data;
2527                 status = usbd_get_string_desc(sc->sc_udev, si->usd_string_index,
2528                                 si->usd_language_id, &si->usd_desc, &len);
2529                 if (status != USBD_NORMAL_COMPLETION)
2530                         error = EINVAL;
2531                 break;
2532
2533         case USB_DO_REQUEST:
2534                 ur = (void *) data;
2535                 len = UGETW(ur->ucr_request.wLength);
2536
2537                 if (!(flag & FWRITE)) {
2538                         error = EPERM;
2539                         break;
2540                 }
2541
2542                 /* Avoid requests that would damage the bus integrity. */
2543                 if ((ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2544                      ur->ucr_request.bRequest == UR_SET_ADDRESS) ||
2545                     (ur->ucr_request.bmRequestType == UT_WRITE_DEVICE &&
2546                      ur->ucr_request.bRequest == UR_SET_CONFIG) ||
2547                     (ur->ucr_request.bmRequestType == UT_WRITE_INTERFACE &&
2548                      ur->ucr_request.bRequest == UR_SET_INTERFACE) ||
2549                     len < 0 || len > 32767) {
2550                         error = EINVAL;
2551                         break;
2552                 }
2553
2554                 if (len != 0) {
2555                         iov.iov_base = (caddr_t) ur->ucr_data;
2556                         iov.iov_len = len;
2557
2558                         uio.uio_iov = &iov;
2559                         uio.uio_iovcnt = 1;
2560                         uio.uio_resid = len;
2561                         uio.uio_offset = 0;
2562                         uio.uio_segflg = UIO_USERSPACE;
2563                         uio.uio_rw = ur->ucr_request.bmRequestType & UT_READ ?
2564                                                 UIO_READ : UIO_WRITE;
2565                         uio.uio_procp = p;
2566
2567                         ptr = malloc(len, M_TEMP, M_WAITOK);
2568                         if (uio.uio_rw == UIO_WRITE) {
2569                                 error = uiomove(ptr, len, &uio);
2570                                 if (error != 0)
2571                                         goto ret;
2572                         }
2573                 }
2574
2575                 status = usbd_do_request_flags(sc->sc_udev, &ur->ucr_request,
2576                                 ptr, ur->ucr_flags, &ur->ucr_actlen,
2577                                 USBD_DEFAULT_TIMEOUT);
2578                 if (status != USBD_NORMAL_COMPLETION) {
2579                         error = EIO;
2580                         goto ret;
2581                 }
2582
2583                 if (len != 0) {
2584                         if (uio.uio_rw == UIO_READ) {
2585                                 error = uiomove(ptr, len, &uio);
2586                                 if (error != 0)
2587                                         goto ret;
2588                         }
2589                 }
2590 ret:
2591                 if (ptr != NULL)
2592                         free(ptr, M_TEMP);
2593                 break;
2594
2595         case USB_GET_DEVICEINFO:
2596                 usbd_fill_deviceinfo(sc->sc_udev,
2597                         (struct usb_device_info *) data, 1);
2598                 break;
2599
2600         default:
2601                 error = EINVAL;
2602                 break;
2603         }
2604
2605         if (-- sc->sc_refcnt < 0)
2606                 usb_detach_wakeup(USBDEV(sc->sc_dev));
2607
2608         return (error);
2609 } /* ubt_ioctl */
2610
2611 /*
2612  * Poll the endpoint device
2613  * XXX FIXME softc locking
2614  */
2615
2616 Static int
2617 ubt_poll(struct cdev *dev, int events, usb_proc_ptr p)
2618 {
2619         ubt_softc_p     sc = NULL;
2620         int             revents = 0, ep = UBT_ENDPOINT(dev);
2621
2622         USB_GET_SC(ubt, UBT_UNIT(dev), sc);
2623         if (sc == NULL || sc->sc_dying)
2624                 return (ENXIO);
2625
2626         if (ep == USB_CONTROL_ENDPOINT)
2627                 return (EOPNOTSUPP);
2628
2629         if (ep == UE_GET_ADDR(sc->sc_intr_ep)) {
2630                 if (sc->sc_intr_pipe != NULL)
2631                         revents |= events & (POLLIN | POLLRDNORM);
2632                 else
2633                         revents = EIO;
2634         } else if (ep == UE_GET_ADDR(sc->sc_bulk_in_ep)) {
2635                 if (sc->sc_bulk_in_pipe != NULL) 
2636                         revents |= events & (POLLIN | POLLRDNORM);
2637
2638                 if (sc->sc_bulk_out_pipe != NULL)
2639                         revents |= events & (POLLOUT | POLLWRNORM);
2640
2641                 if (revents == 0)
2642                         revents = EIO; /* both pipes closed */
2643         } else
2644                 revents = EINVAL;
2645
2646         return (revents);
2647 } /* ubt_poll */
2648
2649 /*
2650  * Create device nodes for all endpoints. Must be called with node locked.
2651  */
2652
2653 Static void
2654 ubt_create_device_nodes(ubt_softc_p sc)
2655 {
2656         int     ep;
2657
2658         KASSERT((sc->sc_hook == NULL), (
2659 "%s: %s - hook != NULL!\n", __func__, USBDEVNAME(sc->sc_dev)));
2660
2661         /* Control device */
2662         if (sc->sc_ctrl_dev == NULL)
2663                 sc->sc_ctrl_dev = make_dev(&ubt_cdevsw,
2664                                         UBT_MINOR(USBDEVUNIT(sc->sc_dev), 0),
2665                                         UID_ROOT, GID_OPERATOR, 0644,
2666                                         "%s", USBDEVNAME(sc->sc_dev));
2667
2668         /* Interrupt device */
2669         if (sc->sc_intr_dev == NULL && sc->sc_intr_ep != -1) {
2670                 ep = UE_GET_ADDR(sc->sc_intr_ep);
2671                 sc->sc_intr_dev = make_dev(&ubt_cdevsw,
2672                                         UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2673                                         UID_ROOT, GID_OPERATOR, 0644,
2674                                         "%s.%d", USBDEVNAME(sc->sc_dev), ep);
2675         }
2676
2677         /* 
2678          * Bulk-in and bulk-out device
2679          * XXX will create one device for both in and out endpoints.
2680          * XXX note that address of the in and out endpoint should be the same
2681          */
2682
2683         if (sc->sc_bulk_dev == NULL && 
2684             sc->sc_bulk_in_ep != -1 && sc->sc_bulk_out_ep != -1 &&
2685             UE_GET_ADDR(sc->sc_bulk_in_ep) == UE_GET_ADDR(sc->sc_bulk_out_ep)) {
2686                 ep = UE_GET_ADDR(sc->sc_bulk_in_ep);
2687                 sc->sc_bulk_dev = make_dev(&ubt_cdevsw,
2688                                         UBT_MINOR(USBDEVUNIT(sc->sc_dev), ep),
2689                                         UID_ROOT, GID_OPERATOR, 0644,
2690                                         "%s.%d", USBDEVNAME(sc->sc_dev), ep);
2691         }
2692 } /* ubt_create_device_nodes */
2693
2694 /*
2695  * Destroy device nodes for all endpoints
2696  * XXX FIXME locking
2697  */
2698
2699 Static void
2700 ubt_destroy_device_nodes(ubt_softc_p sc)
2701 {
2702         /*
2703          * Wait for processes to go away. This should be safe as we will not
2704          * call ubt_destroy_device_nodes() from Netgraph unless all devices
2705          * were closed (and thus no active processes).
2706          */
2707
2708         if (-- sc->sc_refcnt >= 0) {
2709                 ubt_reset(sc);
2710                 usb_detach_wait(USBDEV(sc->sc_dev));
2711         }
2712
2713         sc->sc_refcnt = 0;
2714
2715         /* Destroy device nodes */
2716         if (sc->sc_bulk_dev != NULL) {
2717                 destroy_dev(sc->sc_bulk_dev);
2718                 sc->sc_bulk_dev = NULL;
2719         }
2720
2721         if (sc->sc_intr_dev != NULL) {
2722                 destroy_dev(sc->sc_intr_dev);
2723                 sc->sc_intr_dev = NULL;
2724         }
2725
2726         if (sc->sc_ctrl_dev != NULL) {
2727                 destroy_dev(sc->sc_ctrl_dev);
2728                 sc->sc_ctrl_dev = NULL;
2729         }
2730 } /* ubt_destroy_device_nodes */
2731