Kill usage of USB_VENDOR_FOO and USB_PRODUCT_BAR defines mostly using two
[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.16 2007/11/05 13:32:28 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 static const struct usb_devno udbp_devs[] = {
220         { USB_DEVICE(0x0525, 0x1080) }, /* NetChip Turbo-Connect */
221         { USB_DEVICE(0x0547, 0x2720) }, /* Anchor EZLINK */
222         { USB_DEVICE(0x067b, 0x0000) }, /* Prolific PL2301 */
223         { USB_DEVICE(0x067b, 0x0001) }, /* Prolofic PL2302 */
224 };
225
226 static device_probe_t udbp_match;
227 static device_attach_t udbp_attach;
228 static device_detach_t udbp_detach;
229
230 static devclass_t udbp_devclass;
231
232 static kobj_method_t udbp_methods[] = {
233         DEVMETHOD(device_probe, udbp_match),
234         DEVMETHOD(device_attach, udbp_attach),
235         DEVMETHOD(device_detach, udbp_detach),
236         {0,0}
237 };
238
239 static driver_t udbp_driver = {
240         "udbp",
241         udbp_methods,
242         sizeof(struct udbp_softc)
243 };
244
245 MODULE_DEPEND(udbp, usb, 1, 1, 1);
246
247 static int
248 udbp_match(device_t self)
249 {
250         struct usb_attach_arg *uaa = device_get_ivars(self);
251
252         if (uaa->iface == NULL)
253                 return (UMATCH_NONE);
254
255         return (usb_lookup(udbp_devs, uaa->vendor, uaa->product) != NULL) ?
256             UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
257 }
258
259 static int
260 udbp_attach(device_t self)
261 {
262         struct udbp_softc *sc = device_get_softc(self);
263         struct usb_attach_arg *uaa = device_get_ivars(self);
264         usbd_interface_handle iface = uaa->iface;
265         usb_interface_descriptor_t *id;
266         usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
267         usbd_status err;
268         char devinfo[1024];
269         int i;
270         static int ngudbp_done_init=0;
271
272         sc->flags |= DISCONNECTED;
273         /* fetch the interface handle for the first interface */
274         (void) usbd_device2interface_handle(uaa->device, 0, &iface);
275         id = usbd_get_interface_descriptor(iface);
276         usbd_devinfo(uaa->device, 0, devinfo);
277         sc->sc_dev = self;
278         device_set_desc_copy(self, devinfo);
279         kprintf("%s: %s, iclass %d/%d\n", device_get_nameunit(sc->sc_dev),
280                devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
281
282         /* Find the two first bulk endpoints */
283         for (i = 0 ; i < id->bNumEndpoints; i++) {
284                 ed = usbd_interface2endpoint_descriptor(iface, i);
285                 if (!ed) {
286                         kprintf("%s: could not read endpoint descriptor\n",
287                                device_get_nameunit(sc->sc_dev));
288                         return ENXIO;
289                 }
290
291                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
292                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
293                         ed_bulkin = ed;
294                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
295                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
296                         ed_bulkout = ed;
297                 }
298
299                 if (ed_bulkin && ed_bulkout)    /* found all we need */
300                         break;
301         }
302
303         /* Verify that we goething sensible */
304         if (ed_bulkin == NULL || ed_bulkout == NULL) {
305                 kprintf("%s: bulk-in and/or bulk-out endpoint not found\n",
306                         device_get_nameunit(sc->sc_dev));
307                 return ENXIO;
308         }
309
310         if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
311            ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
312                 kprintf("%s: bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
313                         device_get_nameunit(sc->sc_dev),
314                        ed_bulkin->wMaxPacketSize[0],
315                        ed_bulkout->wMaxPacketSize[0],
316                        ed_bulkin->wMaxPacketSize[1],
317                        ed_bulkout->wMaxPacketSize[1]);
318                 return ENXIO;
319         }
320
321         sc->sc_bulkin = ed_bulkin->bEndpointAddress;
322         sc->sc_bulkout = ed_bulkout->bEndpointAddress;
323
324         DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
325                 device_get_nameunit(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
326                 ed_bulkin->wMaxPacketSize[0]));
327
328         /* Allocate the in transfer struct */
329         sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
330         if (!sc->sc_bulkin_xfer) {
331                 goto bad;
332         }
333         sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
334         if (!sc->sc_bulkout_xfer) {
335                 goto bad;
336         }
337         sc->sc_bulkin_buffer = kmalloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
338         if (!sc->sc_bulkin_buffer) {
339                 goto bad;
340         }
341         sc->sc_bulkout_buffer = kmalloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
342         if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
343                 goto bad;
344         }
345         sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
346         sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
347
348         /* We have decided on which endpoints to use, now open the pipes */
349         err = usbd_open_pipe(iface, sc->sc_bulkin,
350                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
351         if (err) {
352                 kprintf("%s: cannot open bulk-in pipe (addr %d)\n",
353                         device_get_nameunit(sc->sc_dev), sc->sc_bulkin);
354                 goto bad;
355         }
356         err = usbd_open_pipe(iface, sc->sc_bulkout,
357                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
358         if (err) {
359                 kprintf("%s: cannot open bulk-out pipe (addr %d)\n",
360                         device_get_nameunit(sc->sc_dev), sc->sc_bulkout);
361                 goto bad;
362         }
363
364         if (!ngudbp_done_init){
365                 ngudbp_done_init=1;
366                 if (ng_newtype(&ng_udbp_typestruct)) {
367                         kprintf("ngudbp install failed\n");
368                         goto bad;
369                 }
370         }
371
372         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
373                 char    nodename[128];
374                 ksprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
375                 if ((err = ng_name_node(sc->node, nodename))) {
376                         NG_NODE_UNREF(sc->node);
377                         sc->node = NULL;
378                         goto bad;
379                 } else {
380                         NG_NODE_SET_PRIVATE(sc->node, sc);
381                         sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
382                         sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
383                         mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
384                             MTX_DEF);
385                         mtx_init(&sc->xmitq_hipri.ifq_mtx,
386                             "usb_xmitq_hipri", NULL, MTX_DEF);
387                 }
388         }
389         sc->flags = NETGRAPH_INITIALISED;
390         /* sc->flags &= ~DISCONNECTED; */ /* XXX */
391
392
393         /* the device is now operational */
394
395
396         /* schedule the first incoming xfer */
397         err = udbp_setup_in_transfer(sc);
398         if (err) {
399                 goto bad;
400         }
401         return 0;
402 bad:
403 #if 0 /* probably done in udbp_detach() */
404                 if (sc->sc_bulkout_buffer) {
405                         FREE(sc->sc_bulkout_buffer, M_USBDEV);
406                 }
407                 if (sc->sc_bulkin_buffer) {
408                         FREE(sc->sc_bulkin_buffer, M_USBDEV);
409                 }
410                 if (sc->sc_bulkout_xfer) {
411                         usbd_free_xfer(sc->sc_bulkout_xfer);
412                 }
413                 if (sc->sc_bulkin_xfer) {
414                         usbd_free_xfer(sc->sc_bulkin_xfer);
415                 }
416 #endif
417                 udbp_detach(self);
418                 return ENXIO;
419 }
420
421
422 static int
423 udbp_detach(device_t self)
424 {
425         struct udbp_softc *sc = device_get_softc(self);
426
427         sc->flags |= DISCONNECTED;
428
429         DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
430
431         if (sc->sc_bulkin_pipe) {
432                 usbd_abort_pipe(sc->sc_bulkin_pipe);
433                 usbd_close_pipe(sc->sc_bulkin_pipe);
434         }
435         if (sc->sc_bulkout_pipe) {
436                 usbd_abort_pipe(sc->sc_bulkout_pipe);
437                 usbd_close_pipe(sc->sc_bulkout_pipe);
438         }
439
440         if (sc->flags & NETGRAPH_INITIALISED) {
441                 ng_rmnode_self(sc->node);
442                 NG_NODE_SET_PRIVATE(sc->node, NULL);
443                 NG_NODE_UNREF(sc->node);
444                 sc->node = NULL;        /* Paranoid */
445         }
446
447         if (sc->sc_bulkin_xfer)
448                 usbd_free_xfer(sc->sc_bulkin_xfer);
449         if (sc->sc_bulkout_xfer)
450                 usbd_free_xfer(sc->sc_bulkout_xfer);
451
452         if (sc->sc_bulkin_buffer)
453                 kfree(sc->sc_bulkin_buffer, M_USBDEV);
454         if (sc->sc_bulkout_buffer)
455                 kfree(sc->sc_bulkout_buffer, M_USBDEV);
456         return 0;
457 }
458
459
460 static int
461 udbp_setup_in_transfer(udbp_p sc)
462 {
463         void *priv = sc;        /* XXX this should probably be some pointer to
464                                  * struct describing the transfer (mbuf?)
465                                  * See also below.
466                                  */
467         usbd_status err;
468
469         /* XXX
470          * How should we arrange for 2 extra bytes at the start of the
471          * packet?
472          */
473
474         /* Initialise a USB transfer and then schedule it */
475
476         (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
477                                 sc->sc_bulkin_pipe,
478                                 priv,
479                                 sc->sc_bulkin_buffer,
480                                 sc->sc_bulkin_bufferlen,
481                                 USBD_SHORT_XFER_OK,
482                                 USBD_NO_TIMEOUT,
483                                 udbp_in_transfer_cb);
484
485         err = usbd_transfer(sc->sc_bulkin_xfer);
486         if (err && err != USBD_IN_PROGRESS) {
487                 DPRINTF(("%s: failed to setup in-transfer, %s\n",
488                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
489                 return(err);
490         }
491
492         return (USBD_NORMAL_COMPLETION);
493 }
494
495 static void
496 udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
497                         usbd_status err)
498 {
499         udbp_p          sc = priv;              /* XXX see priv above */
500         int             s;
501         int             len;
502         struct          mbuf *m;
503
504         if (err) {
505                 if (err != USBD_CANCELLED) {
506                         DPRINTF(("%s: bulk-out transfer failed: %s\n",
507                                 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
508                 } else {
509                         /* USBD_CANCELLED happens at unload of the driver */
510                         return;
511                 }
512
513                 /* Transfer has failed, packet is not received */
514         } else {
515
516                 len = xfer->actlen;
517
518                 crit_enter();
519                 if (sc->hook) {
520                         /* get packet from device and send on */
521                         m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
522                         NG_SEND_DATA_ONLY(err, sc->hook, m);
523                 }
524                 crit_exit();
525
526         }
527         /* schedule the next in transfer */
528         udbp_setup_in_transfer(sc);
529 }
530
531
532 static int
533 udbp_setup_out_transfer(udbp_p sc)
534 {
535         void *priv = sc;        /* XXX this should probably be some pointer to
536                                  * struct describing the transfer (mbuf?)
537                                  * See also below.
538                                  */
539         int pktlen;
540         usbd_status err;
541         struct mbuf *m;
542
543         crit_enter();
544         if (sc->flags & OUT_BUSY)
545                 panic("out transfer already in use, we should add queuing");
546         sc->flags |= OUT_BUSY;
547         crit_exit();
548         crit_enter();
549         IF_DEQUEUE(&sc->xmitq_hipri, m);
550         if (m == NULL) {
551                 IF_DEQUEUE(&sc->xmitq, m);
552         }
553         crit_exit();
554
555         if (!m) {
556                 sc->flags &= ~OUT_BUSY;
557                 return (USBD_NORMAL_COMPLETION);
558         }
559
560         pktlen = m->m_pkthdr.len;
561         if (pktlen > sc->sc_bulkout_bufferlen) {
562                 kprintf("%s: Packet too large, %d > %d\n",
563                         device_get_nameunit(sc->sc_dev), pktlen,
564                         sc->sc_bulkout_bufferlen);
565                 return (USBD_IOERROR);
566         }
567
568         m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
569         m_freem(m);
570
571         /* Initialise a USB transfer and then schedule it */
572
573         (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
574                                 sc->sc_bulkout_pipe,
575                                 priv,
576                                 sc->sc_bulkout_buffer,
577                                 pktlen,
578                                 USBD_SHORT_XFER_OK,
579                                 UDBP_TIMEOUT,
580                                 udbp_out_transfer_cb);
581
582         err = usbd_transfer(sc->sc_bulkout_xfer);
583         if (err && err != USBD_IN_PROGRESS) {
584                 DPRINTF(("%s: failed to setup out-transfer, %s\n",
585                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
586                 return(err);
587         }
588
589         return (USBD_NORMAL_COMPLETION);
590 }
591
592 static void
593 udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
594                         usbd_status err)
595 {
596         udbp_p sc = priv;               /* XXX see priv above */
597
598         if (err) {
599                 DPRINTF(("%s: bulk-out transfer failed: %s\n",
600                         device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
601                 /* Transfer has failed, packet is not transmitted */
602                 /* XXX Invalidate packet */
603                 return;
604         }
605
606         /* packet has been transmitted */
607
608         crit_enter();
609         sc->flags &= ~OUT_BUSY;
610         udbp_setup_out_transfer(sc);
611         crit_exit();
612 }
613
614 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
615 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
616
617
618 /***********************************************************************
619  * Start of Netgraph methods
620  **********************************************************************/
621
622 /*
623  * If this is a device node so this work is done in the attach()
624  * routine and the constructor will return EINVAL as you should not be able
625  * to create nodes that depend on hardware (unless you can add the hardware :)
626  */
627 static int
628 ng_udbp_constructor(node_p node)
629 {
630         return (EINVAL);
631 }
632
633 /*
634  * Give our ok for a hook to be added...
635  * If we are not running this might kick a device into life.
636  * Possibly decode information out of the hook name.
637  * Add the hook's private info to the hook structure.
638  * (if we had some). In this example, we assume that there is a
639  * an array of structs, called 'channel' in the private info,
640  * one for each active channel. The private
641  * pointer of each hook points to the appropriate UDBP_hookinfo struct
642  * so that the source of an input packet is easily identified.
643  */
644 static int
645 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
646 {
647         const udbp_p sc = NG_NODE_PRIVATE(node);
648
649 #if 0
650         /* Possibly start up the device if it's not already going */
651         if ((sc->flags & SCF_RUNNING) == 0) {
652                 ng_udbp_start_hardware(sc);
653         }
654 #endif
655
656         if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
657                 sc->hook = hook;
658                 NG_HOOK_SET_PRIVATE(hook, NULL);
659         } else {
660                 return (EINVAL);        /* not a hook we know about */
661         }
662         return(0);
663 }
664
665 /*
666  * Get a netgraph control message.
667  * Check it is one we understand. If needed, send a response.
668  * We could save the address for an async action later, but don't here.
669  * Always free the message.
670  * The response should be in a malloc'd region that the caller can 'free'.
671  * A response is not required.
672  * Theoretically you could respond defferently to old message types if
673  * the cookie in the header didn't match what we consider to be current
674  * (so that old userland programs could continue to work).
675  */
676 static int
677 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
678 {
679         const udbp_p sc = NG_NODE_PRIVATE(node);
680         struct ng_mesg *resp = NULL;
681         int error = 0;
682         struct ng_mesg *msg;
683
684         NGI_GET_MSG(item, msg);
685         /* Deal with message according to cookie and command */
686         switch (msg->header.typecookie) {
687         case NGM_UDBP_COOKIE:
688                 switch (msg->header.cmd) {
689                 case NGM_UDBP_GET_STATUS:
690                     {
691                         struct ngudbpstat *stats;
692
693                         NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
694                         if (!resp) {
695                                 error = ENOMEM;
696                                 break;
697                         }
698                         stats = (struct ngudbpstat *) resp->data;
699                         stats->packets_in = sc->packets_in;
700                         stats->packets_out = sc->packets_out;
701                         break;
702                     }
703                 case NGM_UDBP_SET_FLAG:
704                         if (msg->header.arglen != sizeof(u_int32_t)) {
705                                 error = EINVAL;
706                                 break;
707                         }
708                         sc->flags = *((u_int32_t *) msg->data);
709                         break;
710                 default:
711                         error = EINVAL;         /* unknown command */
712                         break;
713                 }
714                 break;
715         default:
716                 error = EINVAL;                 /* unknown cookie type */
717                 break;
718         }
719
720         /* Take care of synchronous response, if any */
721         NG_RESPOND_MSG(error, node, item, resp);
722         NG_FREE_MSG(msg);
723         return(error);
724 }
725
726 /*
727  * Accept data from the hook and queue it for output.
728  */
729 static int
730 ng_udbp_rcvdata(hook_p hook, item_p item)
731 {
732         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
733         int error;
734         struct ifqueue  *xmitq_p;
735         struct mbuf *m;
736         meta_p meta;
737
738         NGI_GET_M(item, m);
739         NGI_GET_META(item, meta);
740         NG_FREE_ITEM(item);
741         /*
742          * Now queue the data for when it can be sent
743          */
744         if (meta && meta->priority > 0) {
745                 xmitq_p = (&sc->xmitq_hipri);
746         } else {
747                 xmitq_p = (&sc->xmitq);
748         }
749         crit_enter();
750         if (IF_QFULL(xmitq_p)) {
751                 IF_DROP(xmitq_p);
752                 crit_exit();
753                 error = ENOBUFS;
754                 goto bad;
755         }
756         IF_ENQUEUE(xmitq_p, m);
757         if (!(sc->flags & OUT_BUSY))
758                 udbp_setup_out_transfer(sc);
759         crit_exit();
760         return (0);
761
762 bad:    /*
763          * It was an error case.
764          * check if we need to free the mbuf, and then return the error
765          */
766         NG_FREE_M(m);
767         NG_FREE_META(meta);
768         return (error);
769 }
770
771 /*
772  * Do local shutdown processing..
773  * We are a persistant device, we refuse to go away, and
774  * only remove our links and reset ourself.
775  */
776 static int
777 ng_udbp_rmnode(node_p node)
778 {
779         const udbp_p sc = NG_NODE_PRIVATE(node);
780         int err;
781
782         if (sc->flags & DISCONNECTED) {
783                 /*
784                  * WE are really going away.. hardware must have gone.
785                  * Assume that the hardware drive part will clear up the
786                  * sc, in fact it may already have done so..
787                  * In which case we may have just segfaulted..XXX
788                  */
789                 return (0);
790         }
791
792         /* stolen from attach routine */
793         /* Drain the queues */
794         IF_DRAIN(&sc->xmitq_hipri);
795         IF_DRAIN(&sc->xmitq);
796
797         sc->packets_in = 0;             /* reset stats */
798         sc->packets_out = 0;
799         NG_NODE_UNREF(node);                    /* forget it ever existed */
800
801         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
802                 char    nodename[128];
803                 ksprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
804                 if ((err = ng_name_node(sc->node, nodename))) {
805                         NG_NODE_UNREF(sc->node); /* out damned spot! */
806                         sc->flags &= ~NETGRAPH_INITIALISED;
807                         sc->node = NULL;
808                 } else {
809                         NG_NODE_SET_PRIVATE(sc->node, sc);
810                 }
811         }
812         return (err);
813 }
814
815 /*
816  * This is called once we've already connected a new hook to the other node.
817  * It gives us a chance to balk at the last minute.
818  */
819 static int
820 ng_udbp_connect(hook_p hook)
821 {
822         /* probably not at splnet, force outward queueing */
823         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
824         /* be really amiable and just say "YUP that's OK by me! " */
825         return (0);
826 }
827
828 /*
829  * Dook disconnection
830  *
831  * For this type, removal of the last link destroys the node
832  */
833 static int
834 ng_udbp_disconnect(hook_p hook)
835 {
836         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
837         sc->hook = NULL;
838
839         if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
840         && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
841                 ng_rmnode_self(NG_HOOK_NODE(hook));
842         return (0);
843 }
844