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