add the 'y' and 'Y' options to ps, and add the 'iac' keyword. The 'y'
[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.3 2004/03/15 02:27:56 dillon 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 #if defined(__FreeBSD__) && __FreeBSD_version >= 500014
82 #include <sys/selinfo.h>
83 #else
84 #include <sys/select.h>
85 #endif
86 #include <sys/poll.h>
87 #include <sys/mbuf.h>
88 #include <sys/socket.h>
89 #include <sys/ctype.h>
90 #include <sys/errno.h>
91 #include <sys/sysctl.h>
92 #include <net/if.h>
93 #include <machine/bus.h>
94
95 #include <dev/usb/usb.h>
96 #include <dev/usb/usbdi.h>
97 #include <dev/usb/usbdi_util.h>
98 #include <dev/usb/usbdivar.h>
99 #include <dev/usb/usbhid.h>
100
101 #include <dev/usb/usbdevs.h>
102
103
104 #include <netgraph/ng_message.h>
105 #include <netgraph/ng_parse.h>
106 #include <dev/usb/udbp.h>
107 #include <netgraph/netgraph.h>
108
109 #ifdef USB_DEBUG
110 #define DPRINTF(x)      if (udbpdebug) logprintf x
111 #define DPRINTFN(n,x)   if (udbpdebug>(n)) logprintf x
112 int     udbpdebug = 0;
113 SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
114 SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
115            &udbpdebug, 0, "udbp debug level");
116 #else
117 #define DPRINTF(x)
118 #define DPRINTFN(n,x)
119 #endif
120
121 #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
122
123 #define UDBP_TIMEOUT    2000    /* timeout on outbound transfers, in msecs */
124 #define UDBP_BUFFERSIZE 2048    /* maximum number of bytes in one transfer */
125
126
127 struct udbp_softc {
128         device_t                sc_dev;         /* base device */
129         usbd_interface_handle   sc_iface;
130
131         usbd_pipe_handle        sc_bulkin_pipe;
132         int                     sc_bulkin;
133         usbd_xfer_handle        sc_bulkin_xfer;
134         void                    *sc_bulkin_buffer;
135         int                     sc_bulkin_bufferlen;
136         int                     sc_bulkin_datalen;
137
138         usbd_pipe_handle        sc_bulkout_pipe;
139         int                     sc_bulkout;
140         usbd_xfer_handle        sc_bulkout_xfer;
141         void                    *sc_bulkout_buffer;
142         int                     sc_bulkout_bufferlen;
143         int                     sc_bulkout_datalen;
144
145         int                     flags;
146 #       define                  DISCONNECTED            0x01
147 #       define                  OUT_BUSY                0x02
148 #       define                  NETGRAPH_INITIALISED    0x04
149         node_p          node;           /* back pointer to node */
150         hook_p          hook;           /* pointer to the hook */
151         u_int           packets_in;     /* packets in from downstream */
152         u_int           packets_out;    /* packets out towards downstream */
153         struct  ifqueue xmitq_hipri;    /* hi-priority transmit queue */
154         struct  ifqueue xmitq;          /* low-priority transmit queue */
155
156 };
157 typedef struct udbp_softc *udbp_p;
158
159
160
161 Static ng_constructor_t ng_udbp_constructor;
162 Static ng_rcvmsg_t      ng_udbp_rcvmsg;
163 Static ng_shutdown_t    ng_udbp_rmnode;
164 Static ng_newhook_t     ng_udbp_newhook;
165 Static ng_connect_t     ng_udbp_connect;
166 Static ng_rcvdata_t     ng_udbp_rcvdata;
167 Static ng_disconnect_t  ng_udbp_disconnect;
168
169 /* Parse type for struct ngudbpstat */
170 Static const struct ng_parse_struct_field
171         ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
172 Static const struct ng_parse_type ng_udbp_stat_type = {
173         &ng_parse_struct_type,
174         &ng_udbp_stat_type_fields
175 };
176
177 /* List of commands and how to convert arguments to/from ASCII */
178 Static const struct ng_cmdlist ng_udbp_cmdlist[] = {
179         {
180           NGM_UDBP_COOKIE,
181           NGM_UDBP_GET_STATUS,
182           "getstatus",
183           NULL,
184           &ng_udbp_stat_type,
185         },
186         {
187           NGM_UDBP_COOKIE,
188           NGM_UDBP_SET_FLAG,
189           "setflag",
190           &ng_parse_int32_type,
191           NULL
192         },
193         { 0 }
194 };
195
196 /* Netgraph node type descriptor */
197 Static struct ng_type ng_udbp_typestruct = {
198         NG_ABI_VERSION,
199         NG_UDBP_NODE_TYPE,
200         NULL,
201         ng_udbp_constructor,
202         ng_udbp_rcvmsg,
203         ng_udbp_rmnode,
204         ng_udbp_newhook,
205         NULL,
206         ng_udbp_connect,
207         ng_udbp_rcvdata,
208         ng_udbp_disconnect,
209         ng_udbp_cmdlist
210 };
211
212 Static int udbp_setup_in_transfer       (udbp_p sc);
213 Static void udbp_in_transfer_cb         (usbd_xfer_handle xfer,
214                                         usbd_private_handle priv,
215                                         usbd_status err);
216
217 Static int udbp_setup_out_transfer      (udbp_p sc);
218 Static void udbp_out_transfer_cb        (usbd_xfer_handle xfer,
219                                         usbd_private_handle priv,
220                                         usbd_status err);
221
222 USB_DECLARE_DRIVER(udbp);
223
224 USB_MATCH(udbp)
225 {
226         USB_MATCH_START(udbp, uaa);
227         usb_interface_descriptor_t *id;
228         if (!uaa->iface)
229           return (UMATCH_NONE);
230         id = usbd_get_interface_descriptor(uaa->iface);
231
232         /* XXX Julian, add the id of the device if you have one to test
233          * things with. run 'usbdevs -v' and note the 3 ID's that appear.
234          * The Vendor Id and Product Id are in hex and the Revision Id is in
235          * bcd. But as usual if the revision is 0x101 then you should compare
236          * the revision id in the device descriptor with 0x101
237          * Or go search the file usbdevs.h. Maybe the device is already in
238          * there.
239          */
240         if ((uaa->vendor == USB_VENDOR_NETCHIP &&
241              uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
242                 return(UMATCH_VENDOR_PRODUCT);
243
244         if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
245              (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
246               uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
247                 return(UMATCH_VENDOR_PRODUCT);
248
249         if ((uaa->vendor == USB_VENDOR_ANCHOR &&
250              uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
251                 return(UMATCH_VENDOR_PRODUCT);
252
253         return (UMATCH_NONE);
254 }
255
256 USB_ATTACH(udbp)
257 {
258         USB_ATTACH_START(udbp, sc, uaa);
259         usbd_interface_handle iface = uaa->iface;
260         usb_interface_descriptor_t *id;
261         usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
262         usbd_status err;
263         char devinfo[1024];
264         int i;
265         static int ngudbp_done_init=0;
266
267         sc->flags |= DISCONNECTED;
268         /* fetch the interface handle for the first interface */
269         (void) usbd_device2interface_handle(uaa->device, 0, &iface);
270         id = usbd_get_interface_descriptor(iface);
271         usbd_devinfo(uaa->device, 0, devinfo);
272         USB_ATTACH_SETUP;
273         printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
274                devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
275
276         /* Find the two first bulk endpoints */
277         for (i = 0 ; i < id->bNumEndpoints; i++) {
278                 ed = usbd_interface2endpoint_descriptor(iface, i);
279                 if (!ed) {
280                         printf("%s: could not read endpoint descriptor\n",
281                                USBDEVNAME(sc->sc_dev));
282                         USB_ATTACH_ERROR_RETURN;
283                 }
284
285                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
286                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
287                         ed_bulkin = ed;
288                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
289                     && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
290                         ed_bulkout = ed;
291                 }
292
293                 if (ed_bulkin && ed_bulkout)    /* found all we need */
294                         break;
295         }
296
297         /* Verify that we goething sensible */
298         if (ed_bulkin == NULL || ed_bulkout == NULL) {
299                 printf("%s: bulk-in and/or bulk-out endpoint not found\n",
300                         USBDEVNAME(sc->sc_dev));
301                 USB_ATTACH_ERROR_RETURN;
302         }
303
304         if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
305            ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
306                 printf("%s: bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
307                         USBDEVNAME(sc->sc_dev),
308                        ed_bulkin->wMaxPacketSize[0],
309                        ed_bulkout->wMaxPacketSize[0],
310                        ed_bulkin->wMaxPacketSize[1],
311                        ed_bulkout->wMaxPacketSize[1]);
312                 USB_ATTACH_ERROR_RETURN;
313         }
314
315         sc->sc_bulkin = ed_bulkin->bEndpointAddress;
316         sc->sc_bulkout = ed_bulkout->bEndpointAddress;
317
318         DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
319                 USBDEVNAME(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
320                 ed_bulkin->wMaxPacketSize[0]));
321
322         /* Allocate the in transfer struct */
323         sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
324         if (!sc->sc_bulkin_xfer) {
325                 goto bad;
326         }
327         sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
328         if (!sc->sc_bulkout_xfer) {
329                 goto bad;
330         }
331         sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
332         if (!sc->sc_bulkin_buffer) {
333                 goto bad;
334         }
335         sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
336         if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
337                 goto bad;
338         }
339         sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
340         sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
341
342         /* We have decided on which endpoints to use, now open the pipes */
343         err = usbd_open_pipe(iface, sc->sc_bulkin,
344                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
345         if (err) {
346                 printf("%s: cannot open bulk-in pipe (addr %d)\n",
347                         USBDEVNAME(sc->sc_dev), sc->sc_bulkin);
348                 goto bad;
349         }
350         err = usbd_open_pipe(iface, sc->sc_bulkout,
351                                 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
352         if (err) {
353                 printf("%s: cannot open bulk-out pipe (addr %d)\n",
354                         USBDEVNAME(sc->sc_dev), sc->sc_bulkout);
355                 goto bad;
356         }
357
358         if (!ngudbp_done_init){
359                 ngudbp_done_init=1;
360                 if (ng_newtype(&ng_udbp_typestruct)) {
361                         printf("ngudbp install failed\n");
362                         goto bad;
363                 }
364         }
365
366         if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
367                 char    nodename[128];
368                 sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev));
369                 if ((err = ng_name_node(sc->node, nodename))) {
370                         NG_NODE_UNREF(sc->node);
371                         sc->node = NULL;
372                         goto bad;
373                 } else {
374                         NG_NODE_SET_PRIVATE(sc->node, sc);
375                         sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
376                         sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
377                         mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
378                             MTX_DEF);
379                         mtx_init(&sc->xmitq_hipri.ifq_mtx,
380                             "usb_xmitq_hipri", NULL, MTX_DEF);
381                 }
382         }
383         sc->flags = NETGRAPH_INITIALISED;
384         /* sc->flags &= ~DISCONNECTED; */ /* XXX */
385
386
387         /* the device is now operational */
388
389
390         /* schedule the first incoming xfer */
391         err = udbp_setup_in_transfer(sc);
392         if (err) {
393                 goto bad;
394         }
395         USB_ATTACH_SUCCESS_RETURN;
396 bad:
397 #if 0 /* probably done in udbp_detach() */
398                 if (sc->sc_bulkout_buffer) {
399                         FREE(sc->sc_bulkout_buffer, M_USBDEV);
400                 }
401                 if (sc->sc_bulkin_buffer) {
402                         FREE(sc->sc_bulkin_buffer, M_USBDEV);
403                 }
404                 if (sc->sc_bulkout_xfer) {
405                         usbd_free_xfer(sc->sc_bulkout_xfer);
406                 }
407                 if (sc->sc_bulkin_xfer) {
408                         usbd_free_xfer(sc->sc_bulkin_xfer);
409                 }
410 #endif
411                 udbp_detach(self);
412                 USB_ATTACH_ERROR_RETURN;
413 }
414
415
416 USB_DETACH(udbp)
417 {
418         USB_DETACH_START(udbp, sc);
419
420         sc->flags |= DISCONNECTED;
421
422         DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));
423
424         if (sc->sc_bulkin_pipe) {
425                 usbd_abort_pipe(sc->sc_bulkin_pipe);
426                 usbd_close_pipe(sc->sc_bulkin_pipe);
427         }
428         if (sc->sc_bulkout_pipe) {
429                 usbd_abort_pipe(sc->sc_bulkout_pipe);
430                 usbd_close_pipe(sc->sc_bulkout_pipe);
431         }
432
433         if (sc->flags & NETGRAPH_INITIALISED) {
434                 ng_rmnode_self(sc->node);
435                 NG_NODE_SET_PRIVATE(sc->node, NULL);
436                 NG_NODE_UNREF(sc->node);
437                 sc->node = NULL;        /* Paranoid */
438         }
439
440         if (sc->sc_bulkin_xfer)
441                 usbd_free_xfer(sc->sc_bulkin_xfer);
442         if (sc->sc_bulkout_xfer)
443                 usbd_free_xfer(sc->sc_bulkout_xfer);
444
445         if (sc->sc_bulkin_buffer)
446                 free(sc->sc_bulkin_buffer, M_USBDEV);
447         if (sc->sc_bulkout_buffer)
448                 free(sc->sc_bulkout_buffer, M_USBDEV);
449         return 0;
450 }
451
452
453 Static int
454 udbp_setup_in_transfer(udbp_p sc)
455 {
456         void *priv = sc;        /* XXX this should probably be some pointer to
457                                  * struct describing the transfer (mbuf?)
458                                  * See also below.
459                                  */
460         usbd_status err;
461
462         /* XXX
463          * How should we arrange for 2 extra bytes at the start of the
464          * packet?
465          */
466
467         /* Initialise a USB transfer and then schedule it */
468
469         (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
470                                 sc->sc_bulkin_pipe,
471                                 priv,
472                                 sc->sc_bulkin_buffer,
473                                 sc->sc_bulkin_bufferlen,
474                                 USBD_SHORT_XFER_OK,
475                                 USBD_NO_TIMEOUT,
476                                 udbp_in_transfer_cb);
477
478         err = usbd_transfer(sc->sc_bulkin_xfer);
479         if (err && err != USBD_IN_PROGRESS) {
480                 DPRINTF(("%s: failed to setup in-transfer, %s\n",
481                         USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
482                 return(err);
483         }
484
485         return (USBD_NORMAL_COMPLETION);
486 }
487
488 Static void
489 udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
490                         usbd_status err)
491 {
492         udbp_p          sc = priv;              /* XXX see priv above */
493         int             s;
494         int             len;
495         struct          mbuf *m;
496
497         if (err) {
498                 if (err != USBD_CANCELLED) {
499                         DPRINTF(("%s: bulk-out transfer failed: %s\n",
500                                 USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
501                 } else {
502                         /* USBD_CANCELLED happens at unload of the driver */
503                         return;
504                 }
505
506                 /* Transfer has failed, packet is not received */
507         } else {
508
509                 len = xfer->actlen;
510
511                 s = splimp(); /* block network stuff too */
512                 if (sc->hook) {
513                         /* get packet from device and send on */
514                         m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
515                         NG_SEND_DATA_ONLY(err, sc->hook, m);
516                 }
517                 splx(s);
518
519         }
520         /* schedule the next in transfer */
521         udbp_setup_in_transfer(sc);
522 }
523
524
525 Static int
526 udbp_setup_out_transfer(udbp_p sc)
527 {
528         void *priv = sc;        /* XXX this should probably be some pointer to
529                                  * struct describing the transfer (mbuf?)
530                                  * See also below.
531                                  */
532         int pktlen;
533         usbd_status err;
534         int s, s1;
535         struct mbuf *m;
536
537
538         s = splusb();
539         if (sc->flags & OUT_BUSY)
540                 panic("out transfer already in use, we should add queuing");
541         sc->flags |= OUT_BUSY;
542         splx(s);
543         s1 = splimp(); /* Queueing happens at splnet */
544         IF_DEQUEUE(&sc->xmitq_hipri, m);
545         if (m == NULL) {
546                 IF_DEQUEUE(&sc->xmitq, m);
547         }
548         splx(s1);
549
550         if (!m) {
551                 sc->flags &= ~OUT_BUSY;
552                 return (USBD_NORMAL_COMPLETION);
553         }
554
555         pktlen = m->m_pkthdr.len;
556         if (pktlen > sc->sc_bulkout_bufferlen) {
557                 printf("%s: Packet too large, %d > %d\n",
558                         USBDEVNAME(sc->sc_dev), pktlen,
559                         sc->sc_bulkout_bufferlen);
560                 return (USBD_IOERROR);
561         }
562
563         m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
564         m_freem(m);
565
566         /* Initialise a USB transfer and then schedule it */
567
568         (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
569                                 sc->sc_bulkout_pipe,
570                                 priv,
571                                 sc->sc_bulkout_buffer,
572                                 pktlen,
573                                 USBD_SHORT_XFER_OK,
574                                 UDBP_TIMEOUT,
575                                 udbp_out_transfer_cb);
576
577         err = usbd_transfer(sc->sc_bulkout_xfer);
578         if (err && err != USBD_IN_PROGRESS) {
579                 DPRINTF(("%s: failed to setup out-transfer, %s\n",
580                         USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
581                 return(err);
582         }
583
584         return (USBD_NORMAL_COMPLETION);
585 }
586
587 Static void
588 udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
589                         usbd_status err)
590 {
591         udbp_p sc = priv;               /* XXX see priv above */
592         int s;
593
594         if (err) {
595                 DPRINTF(("%s: bulk-out transfer failed: %s\n",
596                         USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
597                 /* Transfer has failed, packet is not transmitted */
598                 /* XXX Invalidate packet */
599                 return;
600         }
601
602         /* packet has been transmitted */
603
604         s = splusb();                   /* mark the buffer available */
605         sc->flags &= ~OUT_BUSY;
606         udbp_setup_out_transfer(sc);
607         splx(s);
608 }
609
610 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
611 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
612
613
614 /***********************************************************************
615  * Start of Netgraph methods
616  **********************************************************************/
617
618 /*
619  * If this is a device node so this work is done in the attach()
620  * routine and the constructor will return EINVAL as you should not be able
621  * to create nodes that depend on hardware (unless you can add the hardware :)
622  */
623 Static int
624 ng_udbp_constructor(node_p node)
625 {
626         return (EINVAL);
627 }
628
629 /*
630  * Give our ok for a hook to be added...
631  * If we are not running this might kick a device into life.
632  * Possibly decode information out of the hook name.
633  * Add the hook's private info to the hook structure.
634  * (if we had some). In this example, we assume that there is a
635  * an array of structs, called 'channel' in the private info,
636  * one for each active channel. The private
637  * pointer of each hook points to the appropriate UDBP_hookinfo struct
638  * so that the source of an input packet is easily identified.
639  */
640 Static int
641 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
642 {
643         const udbp_p sc = NG_NODE_PRIVATE(node);
644
645 #if 0
646         /* Possibly start up the device if it's not already going */
647         if ((sc->flags & SCF_RUNNING) == 0) {
648                 ng_udbp_start_hardware(sc);
649         }
650 #endif
651
652         if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
653                 sc->hook = hook;
654                 NG_HOOK_SET_PRIVATE(hook, NULL);
655         } else {
656                 return (EINVAL);        /* not a hook we know about */
657         }
658         return(0);
659 }
660
661 /*
662  * Get a netgraph control message.
663  * Check it is one we understand. If needed, send a response.
664  * We could save the address for an async action later, but don't here.
665  * Always free the message.
666  * The response should be in a malloc'd region that the caller can 'free'.
667  * A response is not required.
668  * Theoretically you could respond defferently to old message types if
669  * the cookie in the header didn't match what we consider to be current
670  * (so that old userland programs could continue to work).
671  */
672 Static int
673 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
674 {
675         const udbp_p sc = NG_NODE_PRIVATE(node);
676         struct ng_mesg *resp = NULL;
677         int error = 0;
678         struct ng_mesg *msg;
679
680         NGI_GET_MSG(item, msg);
681         /* Deal with message according to cookie and command */
682         switch (msg->header.typecookie) {
683         case NGM_UDBP_COOKIE:
684                 switch (msg->header.cmd) {
685                 case NGM_UDBP_GET_STATUS:
686                     {
687                         struct ngudbpstat *stats;
688
689                         NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
690                         if (!resp) {
691                                 error = ENOMEM;
692                                 break;
693                         }
694                         stats = (struct ngudbpstat *) resp->data;
695                         stats->packets_in = sc->packets_in;
696                         stats->packets_out = sc->packets_out;
697                         break;
698                     }
699                 case NGM_UDBP_SET_FLAG:
700                         if (msg->header.arglen != sizeof(u_int32_t)) {
701                                 error = EINVAL;
702                                 break;
703                         }
704                         sc->flags = *((u_int32_t *) msg->data);
705                         break;
706                 default:
707                         error = EINVAL;         /* unknown command */
708                         break;
709                 }
710                 break;
711         default:
712                 error = EINVAL;                 /* unknown cookie type */
713                 break;
714         }
715
716         /* Take care of synchronous response, if any */
717         NG_RESPOND_MSG(error, node, item, resp);
718         NG_FREE_MSG(msg);
719         return(error);
720 }
721
722 /*
723  * Accept data from the hook and queue it for output.
724  */
725 Static int
726 ng_udbp_rcvdata(hook_p hook, item_p item)
727 {
728         const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
729         int error;
730         struct ifqueue  *xmitq_p;
731         int     s;
732         struct mbuf *m;
733         meta_p meta;
734
735         NGI_GET_M(item, m);
736         NGI_GET_META(item, meta);
737         NG_FREE_ITEM(item);
738         /*
739          * Now queue the data for when it can be sent
740          */
741         if (meta && meta->priority > 0) {
742                 xmitq_p = (&sc->xmitq_hipri);
743         } else {
744                 xmitq_p = (&sc->xmitq);
745         }
746         s = splusb();
747         IF_LOCK(xmitq_p);
748         if (_IF_QFULL(xmitq_p)) {
749                 _IF_DROP(xmitq_p);
750                 IF_UNLOCK(xmitq_p);
751                 splx(s);
752                 error = ENOBUFS;
753                 goto bad;
754         }
755         _IF_ENQUEUE(xmitq_p, m);
756         IF_UNLOCK(xmitq_p);
757         if (!(sc->flags & OUT_BUSY))
758                 udbp_setup_out_transfer(sc);
759         splx(s);
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                 sprintf(nodename, "%s", USBDEVNAME(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