]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/udbp.c
add codes for Atheros USB devices; shuffle one ural code to
[FreeBSD/FreeBSD.git] / sys / dev / usb / udbp.c
1 /*-
2  * Copyright (c) 1996-2000 Whistle Communications, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of author nor the names of its
14  *    contributors may be used to endorse or promote products derived
15  *    from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY NICK HIBMA AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
21  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 /* Driver for arbitrary double bulk pipe devices.
35  * The driver assumes that there will be the same driver on the other side.
36  *
37  * XXX Some more information on what the framing of the IP packets looks like.
38  *
39  * To take full advantage of bulk transmission, packets should be chosen
40  * between 1k and 5k in size (1k to make sure the sending side starts
41  * straming, and <5k to avoid overflowing the system with small TDs).
42  */
43
44
45 /* probe/attach/detach:
46  *  Connect the driver to the hardware and netgraph
47  *
48  * udbp_setup_out_transfer(sc);
49  *  Setup an outbound transfer. Only one transmit can be active at the same
50  *  time.
51  *  XXX If it is required that the driver is able to queue multiple requests
52  *      let me know. That is slightly difficult, due to the fact that we
53  *      cannot call usbd_alloc_xfer in int context.
54  *
55  * udbp_setup_in_transfer(sc)
56  *  Prepare an in transfer that will be waiting for data to come in. It
57  *  is submitted and sits there until data is available.
58  *  The callback resubmits a new transfer on completion.
59  *
60  *  The reason we submit a bulk in transfer is that USB does not know about
61  *  interrupts. The bulk transfer continuously polls the device for data.
62  *  While the device has no data available, the device NAKs the TDs. As soon
63  *  as there is data, the transfer happens and the data comes flowing in.
64  *
65  *  In case you were wondering, interrupt transfers happen exactly that way.
66  *  It therefore doesn't make sense to use the interrupt pipe to signal
67  *  'data ready' and then schedule a bulk transfer to fetch it. That would
68  *  incur a 2ms delay at least, without reducing bandwidth requirements.
69  *
70  */
71
72
73
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/kernel.h>
77 #include <sys/malloc.h>
78 #include <sys/module.h>
79 #include <sys/bus.h>
80 #include <sys/conf.h>
81 #include <sys/file.h>
82 #if __FreeBSD_version >= 500014
83 #include <sys/selinfo.h>
84 #else
85 #include <sys/select.h>
86 #endif
87 #include <sys/poll.h>
88 #include <sys/mbuf.h>
89 #include <sys/socket.h>
90 #include <sys/ctype.h>
91 #include <sys/errno.h>
92 #include <sys/sysctl.h>
93 #include <net/if.h>
94 #include <machine/bus.h>
95
96 #include <dev/usb/usb.h>
97 #include <dev/usb/usbdi.h>
98 #include <dev/usb/usbdi_util.h>
99 #include <dev/usb/usbdivar.h>
100 #include <dev/usb/usbhid.h>
101
102 #include "usbdevs.h"
103
104
105 #include <netgraph/ng_message.h>
106 #include <netgraph/ng_parse.h>
107 #include <dev/usb/udbp.h>
108 #include <netgraph/netgraph.h>
109
110 #ifdef USB_DEBUG
111 #define DPRINTF(x)      if (udbpdebug) logprintf x
112 #define DPRINTFN(n,x)   if (udbpdebug>(n)) logprintf x
113 int     udbpdebug = 0;
114 SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
115 SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
116            &udbpdebug, 0, "udbp debug level");
117 #else
118 #define DPRINTF(x)
119 #define DPRINTFN(n,x)
120 #endif
121
122 #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
123
124 #define UDBP_TIMEOUT    2000    /* timeout on outbound transfers, in msecs */
125 #define UDBP_BUFFERSIZE 2048    /* maximum number of bytes in one transfer */
126
127
128 struct udbp_softc {
129         device_t                sc_dev;         /* base device */
130         usbd_interface_handle   sc_iface;
131
132         usbd_pipe_handle        sc_bulkin_pipe;
133         int                     sc_bulkin;
134         usbd_xfer_handle        sc_bulkin_xfer;
135         void                    *sc_bulkin_buffer;
136         int                     sc_bulkin_bufferlen;
137         int                     sc_bulkin_datalen;
138
139         usbd_pipe_handle        sc_bulkout_pipe;
140         int                     sc_bulkout;
141         usbd_xfer_handle        sc_bulkout_xfer;
142         void                    *sc_bulkout_buffer;
143         int                     sc_bulkout_bufferlen;
144         int                     sc_bulkout_datalen;
145
146         int                     flags;
147 #       define                  DISCONNECTED            0x01
148 #       define                  OUT_BUSY                0x02
149 #       define                  NETGRAPH_INITIALISED    0x04
150         node_p          node;           /* back pointer to node */
151         hook_p          hook;           /* pointer to the hook */
152         u_int           packets_in;     /* packets in from downstream */
153         u_int           packets_out;    /* packets out towards downstream */
154         struct  ifqueue xmitq_hipri;    /* hi-priority transmit queue */
155         struct  ifqueue xmitq;          /* low-priority transmit queue */
156
157 };
158 typedef struct udbp_softc *udbp_p;
159
160
161
162 static ng_constructor_t ng_udbp_constructor;
163 static ng_rcvmsg_t      ng_udbp_rcvmsg;
164 static ng_shutdown_t    ng_udbp_rmnode;
165 static ng_newhook_t     ng_udbp_newhook;
166 static ng_connect_t     ng_udbp_connect;
167 static ng_rcvdata_t     ng_udbp_rcvdata;
168 static ng_disconnect_t  ng_udbp_disconnect;
169
170 /* Parse type for struct ngudbpstat */
171 static const struct ng_parse_struct_field
172         ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
173 static const struct ng_parse_type ng_udbp_stat_type = {
174         &ng_parse_struct_type,
175         &ng_udbp_stat_type_fields
176 };
177
178 /* List of commands and how to convert arguments to/from ASCII */
179 static const struct ng_cmdlist ng_udbp_cmdlist[] = {
180         {
181           NGM_UDBP_COOKIE,
182           NGM_UDBP_GET_STATUS,
183           "getstatus",
184           NULL,
185           &ng_udbp_stat_type,
186         },
187         {
188           NGM_UDBP_COOKIE,
189           NGM_UDBP_SET_FLAG,
190           "setflag",
191           &ng_parse_int32_type,
192           NULL
193         },
194         { 0 }
195 };
196
197 /* Netgraph node type descriptor */
198 static struct ng_type ng_udbp_typestruct = {
199         .version =      NG_ABI_VERSION,
200         .name =         NG_UDBP_NODE_TYPE,
201         .constructor =  ng_udbp_constructor,
202         .rcvmsg =       ng_udbp_rcvmsg,
203         .shutdown =     ng_udbp_rmnode,
204         .newhook =      ng_udbp_newhook,
205         .connect =      ng_udbp_connect,
206         .rcvdata =      ng_udbp_rcvdata,
207         .disconnect =   ng_udbp_disconnect,
208         .cmdlist =      ng_udbp_cmdlist,
209 };
210
211 static int udbp_setup_in_transfer       (udbp_p sc);
212 static void udbp_in_transfer_cb         (usbd_xfer_handle xfer,
213                                         usbd_private_handle priv,
214                                         usbd_status err);
215
216 static int udbp_setup_out_transfer      (udbp_p sc);
217 static void udbp_out_transfer_cb        (usbd_xfer_handle xfer,
218                                         usbd_private_handle priv,
219                                         usbd_status err);
220
221 USB_DECLARE_DRIVER(udbp);
222
223 USB_MATCH(udbp)
224 {
225         USB_MATCH_START(udbp, uaa);
226         usb_interface_descriptor_t *id;
227         if (!uaa->iface)
228           return (UMATCH_NONE);
229         id = usbd_get_interface_descriptor(uaa->iface);
230
231         /* XXX Julian, add the id of the device if you have one to test
232          * things with. run 'usbdevs -v' and note the 3 ID's that appear.
233          * The Vendor Id and Product Id are in hex and the Revision Id is in
234          * bcd. But as usual if the revision is 0x101 then you should compare
235          * the revision id in the device descriptor with 0x101
236          * Or go search the file usbdevs.h. Maybe the device is already in
237          * there.
238          */
239         if ((uaa->vendor == USB_VENDOR_NETCHIP &&
240              uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
241                 return(UMATCH_VENDOR_PRODUCT);
242
243         if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
244              (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
245               uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
246                 return(UMATCH_VENDOR_PRODUCT);
247
248         if ((uaa->vendor == USB_VENDOR_ANCHOR &&
249              uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
250                 return(UMATCH_VENDOR_PRODUCT);
251
252         return (UMATCH_NONE);
253 }
254
255 USB_ATTACH(udbp)
256 {
257         USB_ATTACH_START(udbp, sc, uaa);
258         usbd_interface_handle iface = uaa->iface;
259         usb_interface_descriptor_t *id;
260         usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
261         usbd_status err;
262         char devinfo[1024];
263         int i;
264         static int ngudbp_done_init=0;
265
266         sc->flags |= DISCONNECTED;
267         /* fetch the interface handle for the first interface */
268         (void) usbd_device2interface_handle(uaa->device, 0, &iface);
269         id = usbd_get_interface_descriptor(iface);
270         usbd_devinfo(uaa->device, USBD_SHOW_INTERFACE_CLASS, devinfo);
271         USB_ATTACH_SETUP;
272
273         /* Find the two first bulk endpoints */
274         for (i = 0 ; i < id->bNumEndpoints; i++) {
275                 ed = usbd_interface2endpoint_descriptor(iface, i);
276                 if (!ed) {
277                         printf("%s: could not read endpoint descriptor\n",
278                                device_get_nameunit(sc->sc_dev));
279                         USB_ATTACH_ERROR_RETURN;
280                 }
281
282                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
283                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
284                         ed_bulkin = ed;
285                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
286                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
287                         ed_bulkout = ed;
288                 }
289
290                 if (ed_bulkin && ed_bulkout)    /* found all we need */
291                         break;
292         }
293
294         /* Verify that we goething sensible */
295         if (ed_bulkin == NULL || ed_bulkout == NULL) {
296                 printf("%s: bulk-in and/or bulk-out endpoint not found\n",
297                         device_get_nameunit(sc->sc_dev));
298                 USB_ATTACH_ERROR_RETURN;
299         }
300
301         if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
302            ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
303                 printf("%s: bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
304                         device_get_nameunit(sc->sc_dev),
305                        ed_bulkin->wMaxPacketSize[0],
306                        ed_bulkout->wMaxPacketSize[0],
307                        ed_bulkin->wMaxPacketSize[1],
308                        ed_bulkout->wMaxPacketSize[1]);
309                 USB_ATTACH_ERROR_RETURN;
310         }
311
312         sc->sc_bulkin = ed_bulkin->bEndpointAddress;
313         sc->sc_bulkout = ed_bulkout->bEndpointAddress;
314
315         DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
316                 device_get_nameunit(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
317                 ed_bulkin->wMaxPacketSize[0]));
318
319         /* Allocate the in transfer struct */
320         sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
321         if (!sc->sc_bulkin_xfer) {
322                 goto bad;
323         }
324         sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
325         if (!sc->sc_bulkout_xfer) {
326                 goto bad;
327         }
328         sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
329         if (!sc->sc_bulkin_buffer) {
330                 goto bad;
331         }
332         sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
333         if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
334                 goto bad;
335         }
336         sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
337         sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
338
339         /* We have decided on which endpoints to use, now open the pipes */
340         err = usbd_open_pipe(iface, sc->sc_bulkin,
341                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
342         if (err) {
343                 printf("%s: cannot open bulk-in pipe (addr %d)\n",
344                         device_get_nameunit(sc->sc_dev), sc->sc_bulkin);
345                 goto bad;
346         }
347         err = usbd_open_pipe(iface, sc->sc_bulkout,
348                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
349         if (err) {
350                 printf("%s: cannot open bulk-out pipe (addr %d)\n",
351                         device_get_nameunit(sc->sc_dev), sc->sc_bulkout);
352                 goto bad;
353         }
354
355         if (!ngudbp_done_init){
356                 ngudbp_done_init=1;
357                 if (ng_newtype(&ng_udbp_typestruct)) {
358                         printf("ngudbp install failed\n");
359                         goto bad;
360                 }
361         }
362
363         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
364                 char    nodename[128];
365                 sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
366                 if ((err = ng_name_node(sc->node, nodename))) {
367                         NG_NODE_UNREF(sc->node);
368                         sc->node = NULL;
369                         goto bad;
370                 } else {
371                         NG_NODE_SET_PRIVATE(sc->node, sc);
372                         sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
373                         sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
374                         mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
375                             MTX_DEF);
376                         mtx_init(&sc->xmitq_hipri.ifq_mtx,
377                             "usb_xmitq_hipri", NULL, MTX_DEF);
378                 }
379         }
380         sc->flags = NETGRAPH_INITIALISED;
381         /* sc->flags &= ~DISCONNECTED; */ /* XXX */
382
383
384         /* the device is now operational */
385
386
387         /* schedule the first incoming xfer */
388         err = udbp_setup_in_transfer(sc);
389         if (err) {
390                 goto bad;
391         }
392         USB_ATTACH_SUCCESS_RETURN;
393 bad:
394 #if 0 /* probably done in udbp_detach() */
395                 if (sc->sc_bulkout_buffer) {
396                         FREE(sc->sc_bulkout_buffer, M_USBDEV);
397                 }
398                 if (sc->sc_bulkin_buffer) {
399                         FREE(sc->sc_bulkin_buffer, M_USBDEV);
400                 }
401                 if (sc->sc_bulkout_xfer) {
402                         usbd_free_xfer(sc->sc_bulkout_xfer);
403                 }
404                 if (sc->sc_bulkin_xfer) {
405                         usbd_free_xfer(sc->sc_bulkin_xfer);
406                 }
407 #endif
408                 udbp_detach(self);
409                 USB_ATTACH_ERROR_RETURN;
410 }
411
412
413 USB_DETACH(udbp)
414 {
415         USB_DETACH_START(udbp, sc);
416
417         sc->flags |= DISCONNECTED;
418
419         DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
420
421         if (sc->sc_bulkin_pipe) {
422                 usbd_abort_pipe(sc->sc_bulkin_pipe);
423                 usbd_close_pipe(sc->sc_bulkin_pipe);
424         }
425         if (sc->sc_bulkout_pipe) {
426                 usbd_abort_pipe(sc->sc_bulkout_pipe);
427                 usbd_close_pipe(sc->sc_bulkout_pipe);
428         }
429
430         if (sc->flags & NETGRAPH_INITIALISED) {
431                 ng_rmnode_self(sc->node);
432                 NG_NODE_SET_PRIVATE(sc->node, NULL);
433                 NG_NODE_UNREF(sc->node);
434                 sc->node = NULL;        /* Paranoid */
435         }
436
437         if (sc->sc_bulkin_xfer)
438                 usbd_free_xfer(sc->sc_bulkin_xfer);
439         if (sc->sc_bulkout_xfer)
440                 usbd_free_xfer(sc->sc_bulkout_xfer);
441
442         if (sc->sc_bulkin_buffer)
443                 free(sc->sc_bulkin_buffer, M_USBDEV);
444         if (sc->sc_bulkout_buffer)
445                 free(sc->sc_bulkout_buffer, M_USBDEV);
446         return 0;
447 }
448
449
450 static int
451 udbp_setup_in_transfer(udbp_p sc)
452 {
453         void *priv = sc;        /* XXX this should probably be some pointer to
454                                  * struct describing the transfer (mbuf?)
455                                  * See also below.
456                                  */
457         usbd_status err;
458
459         /* XXX
460          * How should we arrange for 2 extra bytes at the start of the
461          * packet?
462          */
463
464         /* Initialise a USB transfer and then schedule it */
465
466         (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
467                                 sc->sc_bulkin_pipe,
468                                 priv,
469                                 sc->sc_bulkin_buffer,
470                                 sc->sc_bulkin_bufferlen,
471                                 USBD_SHORT_XFER_OK,
472                                 USBD_NO_TIMEOUT,
473                                 udbp_in_transfer_cb);
474
475         err = usbd_transfer(sc->sc_bulkin_xfer);
476         if (err && err != USBD_IN_PROGRESS) {
477                 DPRINTF(("%s: failed to setup in-transfer, %s\n",
478                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
479                 return(err);
480         }
481
482         return (USBD_NORMAL_COMPLETION);
483 }
484
485 static void
486 udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
487                         usbd_status err)
488 {
489         udbp_p          sc = priv;              /* XXX see priv above */
490         int             s;
491         int             len;
492         struct          mbuf *m;
493
494         if (err) {
495                 if (err != USBD_CANCELLED) {
496                         DPRINTF(("%s: bulk-out transfer failed: %s\n",
497                                 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
498                 } else {
499                         /* USBD_CANCELLED happens at unload of the driver */
500                         return;
501                 }
502
503                 /* Transfer has failed, packet is not received */
504         } else {
505
506                 len = xfer->actlen;
507
508                 s = splimp(); /* block network stuff too */
509                 if (sc->hook) {
510                         /* get packet from device and send on */
511                         m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
512                         NG_SEND_DATA_ONLY(err, sc->hook, m);
513                 }
514                 splx(s);
515
516         }
517         /* schedule the next in transfer */
518         udbp_setup_in_transfer(sc);
519 }
520
521
522 static int
523 udbp_setup_out_transfer(udbp_p sc)
524 {
525         void *priv = sc;        /* XXX this should probably be some pointer to
526                                  * struct describing the transfer (mbuf?)
527                                  * See also below.
528                                  */
529         int pktlen;
530         usbd_status err;
531         int s, s1;
532         struct mbuf *m;
533
534
535         s = splusb();
536         if (sc->flags & OUT_BUSY)
537                 panic("out transfer already in use, we should add queuing");
538         sc->flags |= OUT_BUSY;
539         splx(s);
540         s1 = splimp(); /* Queueing happens at splnet */
541         IF_DEQUEUE(&sc->xmitq_hipri, m);
542         if (m == NULL) {
543                 IF_DEQUEUE(&sc->xmitq, m);
544         }
545         splx(s1);
546
547         if (!m) {
548                 sc->flags &= ~OUT_BUSY;
549                 return (USBD_NORMAL_COMPLETION);
550         }
551
552         pktlen = m->m_pkthdr.len;
553         if (pktlen > sc->sc_bulkout_bufferlen) {
554                 printf("%s: Packet too large, %d > %d\n",
555                         device_get_nameunit(sc->sc_dev), pktlen,
556                         sc->sc_bulkout_bufferlen);
557                 return (USBD_IOERROR);
558         }
559
560         m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
561         m_freem(m);
562
563         /* Initialise a USB transfer and then schedule it */
564
565         (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
566                                 sc->sc_bulkout_pipe,
567                                 priv,
568                                 sc->sc_bulkout_buffer,
569                                 pktlen,
570                                 USBD_SHORT_XFER_OK,
571                                 UDBP_TIMEOUT,
572                                 udbp_out_transfer_cb);
573
574         err = usbd_transfer(sc->sc_bulkout_xfer);
575         if (err && err != USBD_IN_PROGRESS) {
576                 DPRINTF(("%s: failed to setup out-transfer, %s\n",
577                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
578                 return(err);
579         }
580
581         return (USBD_NORMAL_COMPLETION);
582 }
583
584 static void
585 udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
586                         usbd_status err)
587 {
588         udbp_p sc = priv;               /* XXX see priv above */
589         int s;
590
591         if (err) {
592                 DPRINTF(("%s: bulk-out transfer failed: %s\n",
593                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
594                 /* Transfer has failed, packet is not transmitted */
595                 /* XXX Invalidate packet */
596                 return;
597         }
598
599         /* packet has been transmitted */
600
601         s = splusb();                   /* mark the buffer available */
602         sc->flags &= ~OUT_BUSY;
603         udbp_setup_out_transfer(sc);
604         splx(s);
605 }
606
607 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
608 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
609
610
611 /***********************************************************************
612  * Start of Netgraph methods
613  **********************************************************************/
614
615 /*
616  * If this is a device node so this work is done in the attach()
617  * routine and the constructor will return EINVAL as you should not be able
618  * to create nodes that depend on hardware (unless you can add the hardware :)
619  */
620 static int
621 ng_udbp_constructor(node_p node)
622 {
623         return (EINVAL);
624 }
625
626 /*
627  * Give our ok for a hook to be added...
628  * If we are not running this might kick a device into life.
629  * Possibly decode information out of the hook name.
630  * Add the hook's private info to the hook structure.
631  * (if we had some). In this example, we assume that there is a
632  * an array of structs, called 'channel' in the private info,
633  * one for each active channel. The private
634  * pointer of each hook points to the appropriate UDBP_hookinfo struct
635  * so that the source of an input packet is easily identified.
636  */
637 static int
638 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
639 {
640         const udbp_p sc = NG_NODE_PRIVATE(node);
641
642 #if 0
643         /* Possibly start up the device if it's not already going */
644         if ((sc->flags & SCF_RUNNING) == 0) {
645                 ng_udbp_start_hardware(sc);
646         }
647 #endif
648
649         if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
650                 sc->hook = hook;
651                 NG_HOOK_SET_PRIVATE(hook, NULL);
652         } else {
653                 return (EINVAL);        /* not a hook we know about */
654         }
655         return(0);
656 }
657
658 /*
659  * Get a netgraph control message.
660  * Check it is one we understand. If needed, send a response.
661  * We could save the address for an async action later, but don't here.
662  * Always free the message.
663  * The response should be in a malloc'd region that the caller can 'free'.
664  * A response is not required.
665  * Theoretically you could respond defferently to old message types if
666  * the cookie in the header didn't match what we consider to be current
667  * (so that old userland programs could continue to work).
668  */
669 static int
670 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
671 {
672         const udbp_p sc = NG_NODE_PRIVATE(node);
673         struct ng_mesg *resp = NULL;
674         int error = 0;
675         struct ng_mesg *msg;
676
677         NGI_GET_MSG(item, msg);
678         /* Deal with message according to cookie and command */
679         switch (msg->header.typecookie) {
680         case NGM_UDBP_COOKIE:
681                 switch (msg->header.cmd) {
682                 case NGM_UDBP_GET_STATUS:
683                     {
684                         struct ngudbpstat *stats;
685
686                         NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
687                         if (!resp) {
688                                 error = ENOMEM;
689                                 break;
690                         }
691                         stats = (struct ngudbpstat *) resp->data;
692                         stats->packets_in = sc->packets_in;
693                         stats->packets_out = sc->packets_out;
694                         break;
695                     }
696                 case NGM_UDBP_SET_FLAG:
697                         if (msg->header.arglen != sizeof(u_int32_t)) {
698                                 error = EINVAL;
699                                 break;
700                         }
701                         sc->flags = *((u_int32_t *) msg->data);
702                         break;
703                 default:
704                         error = EINVAL;         /* unknown command */
705                         break;
706                 }
707                 break;
708         default:
709                 error = EINVAL;                 /* unknown cookie type */
710                 break;
711         }
712
713         /* Take care of synchronous response, if any */
714         NG_RESPOND_MSG(error, node, item, resp);
715         NG_FREE_MSG(msg);
716         return(error);
717 }
718
719 /*
720  * Accept data from the hook and queue it for output.
721  */
722 static int
723 ng_udbp_rcvdata(hook_p hook, item_p item)
724 {
725         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
726         int error;
727         struct ifqueue  *xmitq_p;
728         int     s;
729         struct mbuf *m;
730         struct ng_tag_prio *ptag;
731
732         NGI_GET_M(item, m);
733         NG_FREE_ITEM(item);
734
735         /*
736          * Now queue the data for when it can be sent
737          */
738         if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE,
739             NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) )
740                 xmitq_p = (&sc->xmitq_hipri);
741         else
742                 xmitq_p = (&sc->xmitq);
743
744         s = splusb();
745         IF_LOCK(xmitq_p);
746         if (_IF_QFULL(xmitq_p)) {
747                 _IF_DROP(xmitq_p);
748                 IF_UNLOCK(xmitq_p);
749                 splx(s);
750                 error = ENOBUFS;
751                 goto bad;
752         }
753         _IF_ENQUEUE(xmitq_p, m);
754         IF_UNLOCK(xmitq_p);
755         if (!(sc->flags & OUT_BUSY))
756                 udbp_setup_out_transfer(sc);
757         splx(s);
758         return (0);
759
760 bad:    /*
761          * It was an error case.
762          * check if we need to free the mbuf, and then return the error
763          */
764         NG_FREE_M(m);
765         return (error);
766 }
767
768 /*
769  * Do local shutdown processing..
770  * We are a persistant device, we refuse to go away, and
771  * only remove our links and reset ourself.
772  */
773 static int
774 ng_udbp_rmnode(node_p node)
775 {
776         const udbp_p sc = NG_NODE_PRIVATE(node);
777         int err;
778
779         if (sc->flags & DISCONNECTED) {
780                 /*
781                  * WE are really going away.. hardware must have gone.
782                  * Assume that the hardware drive part will clear up the
783                  * sc, in fact it may already have done so..
784                  * In which case we may have just segfaulted..XXX
785                  */
786                 return (0);
787         }
788
789         /* stolen from attach routine */
790         /* Drain the queues */
791         IF_DRAIN(&sc->xmitq_hipri);
792         IF_DRAIN(&sc->xmitq);
793
794         sc->packets_in = 0;             /* reset stats */
795         sc->packets_out = 0;
796         NG_NODE_UNREF(node);                    /* forget it ever existed */
797
798         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
799                 char    nodename[128];
800                 sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
801                 if ((err = ng_name_node(sc->node, nodename))) {
802                         NG_NODE_UNREF(sc->node); /* out damned spot! */
803                         sc->flags &= ~NETGRAPH_INITIALISED;
804                         sc->node = NULL;
805                 } else {
806                         NG_NODE_SET_PRIVATE(sc->node, sc);
807                 }
808         }
809         return (err);
810 }
811
812 /*
813  * This is called once we've already connected a new hook to the other node.
814  * It gives us a chance to balk at the last minute.
815  */
816 static int
817 ng_udbp_connect(hook_p hook)
818 {
819         /* probably not at splnet, force outward queueing */
820         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
821         /* be really amiable and just say "YUP that's OK by me! " */
822         return (0);
823 }
824
825 /*
826  * Dook disconnection
827  *
828  * For this type, removal of the last link destroys the node
829  */
830 static int
831 ng_udbp_disconnect(hook_p hook)
832 {
833         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
834         sc->hook = NULL;
835
836         if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
837         && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
838                 ng_rmnode_self(NG_HOOK_NODE(hook));
839         return (0);
840 }
841