e1a2eba2b2b471fb6f1706fe2ef7c46f398a7448
[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.13 2007/06/28 13:55:12 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 USB_MATCH(udbp)
222 {
223         USB_MATCH_START(udbp, uaa);
224         usb_interface_descriptor_t *id;
225         if (!uaa->iface)
226           return (UMATCH_NONE);
227         id = usbd_get_interface_descriptor(uaa->iface);
228
229         /* XXX Julian, add the id of the device if you have one to test
230          * things with. run 'usbdevs -v' and note the 3 ID's that appear.
231          * The Vendor Id and Product Id are in hex and the Revision Id is in
232          * bcd. But as usual if the revision is 0x101 then you should compare
233          * the revision id in the device descriptor with 0x101
234          * Or go search the file usbdevs.h. Maybe the device is already in
235          * there.
236          */
237         if ((uaa->vendor == USB_VENDOR_NETCHIP &&
238              uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
239                 return(UMATCH_VENDOR_PRODUCT);
240
241         if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
242              (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
243               uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
244                 return(UMATCH_VENDOR_PRODUCT);
245
246         if ((uaa->vendor == USB_VENDOR_ANCHOR &&
247              uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
248                 return(UMATCH_VENDOR_PRODUCT);
249
250         return (UMATCH_NONE);
251 }
252
253 USB_ATTACH(udbp)
254 {
255         USB_ATTACH_START(udbp, sc, uaa);
256         usbd_interface_handle iface = uaa->iface;
257         usb_interface_descriptor_t *id;
258         usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
259         usbd_status err;
260         char devinfo[1024];
261         int i;
262         static int ngudbp_done_init=0;
263
264         sc->flags |= DISCONNECTED;
265         /* fetch the interface handle for the first interface */
266         (void) usbd_device2interface_handle(uaa->device, 0, &iface);
267         id = usbd_get_interface_descriptor(iface);
268         usbd_devinfo(uaa->device, 0, devinfo);
269         USB_ATTACH_SETUP;
270         kprintf("%s: %s, iclass %d/%d\n", device_get_nameunit(sc->sc_dev),
271                devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
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                         kprintf("%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                 kprintf("%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                 kprintf("%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 = kmalloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
329         if (!sc->sc_bulkin_buffer) {
330                 goto bad;
331         }
332         sc->sc_bulkout_buffer = kmalloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
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                 kprintf("%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                 kprintf("%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                         kprintf("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                 ksprintf(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                 kfree(sc->sc_bulkin_buffer, M_USBDEV);
444         if (sc->sc_bulkout_buffer)
445                 kfree(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                 crit_enter();
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                 crit_exit();
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         struct mbuf *m;
532
533         crit_enter();
534         if (sc->flags & OUT_BUSY)
535                 panic("out transfer already in use, we should add queuing");
536         sc->flags |= OUT_BUSY;
537         crit_exit();
538         crit_enter();
539         IF_DEQUEUE(&sc->xmitq_hipri, m);
540         if (m == NULL) {
541                 IF_DEQUEUE(&sc->xmitq, m);
542         }
543         crit_exit();
544
545         if (!m) {
546                 sc->flags &= ~OUT_BUSY;
547                 return (USBD_NORMAL_COMPLETION);
548         }
549
550         pktlen = m->m_pkthdr.len;
551         if (pktlen > sc->sc_bulkout_bufferlen) {
552                 kprintf("%s: Packet too large, %d > %d\n",
553                         device_get_nameunit(sc->sc_dev), pktlen,
554                         sc->sc_bulkout_bufferlen);
555                 return (USBD_IOERROR);
556         }
557
558         m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
559         m_freem(m);
560
561         /* Initialise a USB transfer and then schedule it */
562
563         (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
564                                 sc->sc_bulkout_pipe,
565                                 priv,
566                                 sc->sc_bulkout_buffer,
567                                 pktlen,
568                                 USBD_SHORT_XFER_OK,
569                                 UDBP_TIMEOUT,
570                                 udbp_out_transfer_cb);
571
572         err = usbd_transfer(sc->sc_bulkout_xfer);
573         if (err && err != USBD_IN_PROGRESS) {
574                 DPRINTF(("%s: failed to setup out-transfer, %s\n",
575                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
576                 return(err);
577         }
578
579         return (USBD_NORMAL_COMPLETION);
580 }
581
582 static void
583 udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
584                         usbd_status err)
585 {
586         udbp_p sc = priv;               /* XXX see priv above */
587
588         if (err) {
589                 DPRINTF(("%s: bulk-out transfer failed: %s\n",
590                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
591                 /* Transfer has failed, packet is not transmitted */
592                 /* XXX Invalidate packet */
593                 return;
594         }
595
596         /* packet has been transmitted */
597
598         crit_enter();
599         sc->flags &= ~OUT_BUSY;
600         udbp_setup_out_transfer(sc);
601         crit_exit();
602 }
603
604 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
605 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
606
607
608 /***********************************************************************
609  * Start of Netgraph methods
610  **********************************************************************/
611
612 /*
613  * If this is a device node so this work is done in the attach()
614  * routine and the constructor will return EINVAL as you should not be able
615  * to create nodes that depend on hardware (unless you can add the hardware :)
616  */
617 static int
618 ng_udbp_constructor(node_p node)
619 {
620         return (EINVAL);
621 }
622
623 /*
624  * Give our ok for a hook to be added...
625  * If we are not running this might kick a device into life.
626  * Possibly decode information out of the hook name.
627  * Add the hook's private info to the hook structure.
628  * (if we had some). In this example, we assume that there is a
629  * an array of structs, called 'channel' in the private info,
630  * one for each active channel. The private
631  * pointer of each hook points to the appropriate UDBP_hookinfo struct
632  * so that the source of an input packet is easily identified.
633  */
634 static int
635 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
636 {
637         const udbp_p sc = NG_NODE_PRIVATE(node);
638
639 #if 0
640         /* Possibly start up the device if it's not already going */
641         if ((sc->flags & SCF_RUNNING) == 0) {
642                 ng_udbp_start_hardware(sc);
643         }
644 #endif
645
646         if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
647                 sc->hook = hook;
648                 NG_HOOK_SET_PRIVATE(hook, NULL);
649         } else {
650                 return (EINVAL);        /* not a hook we know about */
651         }
652         return(0);
653 }
654
655 /*
656  * Get a netgraph control message.
657  * Check it is one we understand. If needed, send a response.
658  * We could save the address for an async action later, but don't here.
659  * Always free the message.
660  * The response should be in a malloc'd region that the caller can 'free'.
661  * A response is not required.
662  * Theoretically you could respond defferently to old message types if
663  * the cookie in the header didn't match what we consider to be current
664  * (so that old userland programs could continue to work).
665  */
666 static int
667 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
668 {
669         const udbp_p sc = NG_NODE_PRIVATE(node);
670         struct ng_mesg *resp = NULL;
671         int error = 0;
672         struct ng_mesg *msg;
673
674         NGI_GET_MSG(item, msg);
675         /* Deal with message according to cookie and command */
676         switch (msg->header.typecookie) {
677         case NGM_UDBP_COOKIE:
678                 switch (msg->header.cmd) {
679                 case NGM_UDBP_GET_STATUS:
680                     {
681                         struct ngudbpstat *stats;
682
683                         NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
684                         if (!resp) {
685                                 error = ENOMEM;
686                                 break;
687                         }
688                         stats = (struct ngudbpstat *) resp->data;
689                         stats->packets_in = sc->packets_in;
690                         stats->packets_out = sc->packets_out;
691                         break;
692                     }
693                 case NGM_UDBP_SET_FLAG:
694                         if (msg->header.arglen != sizeof(u_int32_t)) {
695                                 error = EINVAL;
696                                 break;
697                         }
698                         sc->flags = *((u_int32_t *) msg->data);
699                         break;
700                 default:
701                         error = EINVAL;         /* unknown command */
702                         break;
703                 }
704                 break;
705         default:
706                 error = EINVAL;                 /* unknown cookie type */
707                 break;
708         }
709
710         /* Take care of synchronous response, if any */
711         NG_RESPOND_MSG(error, node, item, resp);
712         NG_FREE_MSG(msg);
713         return(error);
714 }
715
716 /*
717  * Accept data from the hook and queue it for output.
718  */
719 static int
720 ng_udbp_rcvdata(hook_p hook, item_p item)
721 {
722         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
723         int error;
724         struct ifqueue  *xmitq_p;
725         struct mbuf *m;
726         meta_p meta;
727
728         NGI_GET_M(item, m);
729         NGI_GET_META(item, meta);
730         NG_FREE_ITEM(item);
731         /*
732          * Now queue the data for when it can be sent
733          */
734         if (meta && meta->priority > 0) {
735                 xmitq_p = (&sc->xmitq_hipri);
736         } else {
737                 xmitq_p = (&sc->xmitq);
738         }
739         crit_enter();
740         if (IF_QFULL(xmitq_p)) {
741                 IF_DROP(xmitq_p);
742                 crit_exit();
743                 error = ENOBUFS;
744                 goto bad;
745         }
746         IF_ENQUEUE(xmitq_p, m);
747         if (!(sc->flags & OUT_BUSY))
748                 udbp_setup_out_transfer(sc);
749         crit_exit();
750         return (0);
751
752 bad:    /*
753          * It was an error case.
754          * check if we need to free the mbuf, and then return the error
755          */
756         NG_FREE_M(m);
757         NG_FREE_META(meta);
758         return (error);
759 }
760
761 /*
762  * Do local shutdown processing..
763  * We are a persistant device, we refuse to go away, and
764  * only remove our links and reset ourself.
765  */
766 static int
767 ng_udbp_rmnode(node_p node)
768 {
769         const udbp_p sc = NG_NODE_PRIVATE(node);
770         int err;
771
772         if (sc->flags & DISCONNECTED) {
773                 /*
774                  * WE are really going away.. hardware must have gone.
775                  * Assume that the hardware drive part will clear up the
776                  * sc, in fact it may already have done so..
777                  * In which case we may have just segfaulted..XXX
778                  */
779                 return (0);
780         }
781
782         /* stolen from attach routine */
783         /* Drain the queues */
784         IF_DRAIN(&sc->xmitq_hipri);
785         IF_DRAIN(&sc->xmitq);
786
787         sc->packets_in = 0;             /* reset stats */
788         sc->packets_out = 0;
789         NG_NODE_UNREF(node);                    /* forget it ever existed */
790
791         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
792                 char    nodename[128];
793                 ksprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
794                 if ((err = ng_name_node(sc->node, nodename))) {
795                         NG_NODE_UNREF(sc->node); /* out damned spot! */
796                         sc->flags &= ~NETGRAPH_INITIALISED;
797                         sc->node = NULL;
798                 } else {
799                         NG_NODE_SET_PRIVATE(sc->node, sc);
800                 }
801         }
802         return (err);
803 }
804
805 /*
806  * This is called once we've already connected a new hook to the other node.
807  * It gives us a chance to balk at the last minute.
808  */
809 static int
810 ng_udbp_connect(hook_p hook)
811 {
812         /* probably not at splnet, force outward queueing */
813         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
814         /* be really amiable and just say "YUP that's OK by me! " */
815         return (0);
816 }
817
818 /*
819  * Dook disconnection
820  *
821  * For this type, removal of the last link destroys the node
822  */
823 static int
824 ng_udbp_disconnect(hook_p hook)
825 {
826         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
827         sc->hook = NULL;
828
829         if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
830         && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
831                 ng_rmnode_self(NG_HOOK_NODE(hook));
832         return (0);
833 }
834