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