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