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