]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/usb/misc/udbp.c
MFV: ACPICA 20090521
[FreeBSD/FreeBSD.git] / sys / dev / usb / misc / 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  * streaming, 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  *  The reason we submit a bulk in transfer is that USB does not know about
49  *  interrupts. The bulk transfer continuously polls the device for data.
50  *  While the device has no data available, the device NAKs the TDs. As soon
51  *  as there is data, the transfer happens and the data comes flowing in.
52  *
53  *  In case you were wondering, interrupt transfers happen exactly that way.
54  *  It therefore doesn't make sense to use the interrupt pipe to signal
55  *  'data ready' and then schedule a bulk transfer to fetch it. That would
56  *  incur a 2ms delay at least, without reducing bandwidth requirements.
57  *
58  */
59
60 #include "usbdevs.h"
61 #include <dev/usb/usb.h>
62 #include <dev/usb/usb_mfunc.h>
63 #include <dev/usb/usb_error.h>
64
65 #define USB_DEBUG_VAR udbp_debug
66
67 #include <dev/usb/usb_core.h>
68 #include <dev/usb/usb_debug.h>
69 #include <dev/usb/usb_parse.h>
70 #include <dev/usb/usb_lookup.h>
71 #include <dev/usb/usb_util.h>
72 #include <dev/usb/usb_busdma.h>
73
74 #include <sys/mbuf.h>
75
76 #include <netgraph/ng_message.h>
77 #include <netgraph/netgraph.h>
78 #include <netgraph/ng_parse.h>
79 #include <netgraph/bluetooth/include/ng_bluetooth.h>
80
81 #include <dev/usb/misc/udbp.h>
82
83 #if USB_DEBUG
84 static int udbp_debug = 0;
85
86 SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
87 SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
88     &udbp_debug, 0, "udbp debug level");
89 #endif
90
91 #define UDBP_TIMEOUT    2000            /* timeout on outbound transfers, in
92                                          * msecs */
93 #define UDBP_BUFFERSIZE MCLBYTES        /* maximum number of bytes in one
94                                          * transfer */
95 #define UDBP_T_WR       0
96 #define UDBP_T_RD       1
97 #define UDBP_T_WR_CS    2
98 #define UDBP_T_RD_CS    3
99 #define UDBP_T_MAX      4
100 #define UDBP_Q_MAXLEN   50
101
102 struct udbp_softc {
103
104         struct mtx sc_mtx;
105         struct ng_bt_mbufq sc_xmitq_hipri;      /* hi-priority transmit queue */
106         struct ng_bt_mbufq sc_xmitq;    /* low-priority transmit queue */
107
108         struct usb_xfer *sc_xfer[UDBP_T_MAX];
109         node_p  sc_node;                /* back pointer to node */
110         hook_p  sc_hook;                /* pointer to the hook */
111         struct mbuf *sc_bulk_in_buffer;
112
113         uint32_t sc_packets_in;         /* packets in from downstream */
114         uint32_t sc_packets_out;        /* packets out towards downstream */
115
116         uint8_t sc_flags;
117 #define UDBP_FLAG_READ_STALL    0x01    /* read transfer stalled */
118 #define UDBP_FLAG_WRITE_STALL   0x02    /* write transfer stalled */
119
120         uint8_t sc_name[16];
121 };
122
123 /* prototypes */
124
125 static int udbp_modload(module_t mod, int event, void *data);
126
127 static device_probe_t udbp_probe;
128 static device_attach_t udbp_attach;
129 static device_detach_t udbp_detach;
130
131 static usb_callback_t udbp_bulk_read_callback;
132 static usb_callback_t udbp_bulk_read_clear_stall_callback;
133 static usb_callback_t udbp_bulk_write_callback;
134 static usb_callback_t udbp_bulk_write_clear_stall_callback;
135
136 static void     udbp_bulk_read_complete(node_p, hook_p, void *, int);
137
138 static ng_constructor_t ng_udbp_constructor;
139 static ng_rcvmsg_t      ng_udbp_rcvmsg;
140 static ng_shutdown_t    ng_udbp_rmnode;
141 static ng_newhook_t     ng_udbp_newhook;
142 static ng_connect_t     ng_udbp_connect;
143 static ng_rcvdata_t     ng_udbp_rcvdata;
144 static ng_disconnect_t  ng_udbp_disconnect;
145
146 /* Parse type for struct ngudbpstat */
147 static const struct ng_parse_struct_field
148         ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
149
150 static const struct ng_parse_type ng_udbp_stat_type = {
151         &ng_parse_struct_type,
152         &ng_udbp_stat_type_fields
153 };
154
155 /* List of commands and how to convert arguments to/from ASCII */
156 static const struct ng_cmdlist ng_udbp_cmdlist[] = {
157         {
158                 NGM_UDBP_COOKIE,
159                 NGM_UDBP_GET_STATUS,
160                 "getstatus",
161                 NULL,
162                 &ng_udbp_stat_type,
163         },
164         {
165                 NGM_UDBP_COOKIE,
166                 NGM_UDBP_SET_FLAG,
167                 "setflag",
168                 &ng_parse_int32_type,
169                 NULL
170         },
171         {0}
172 };
173
174 /* Netgraph node type descriptor */
175 static struct ng_type ng_udbp_typestruct = {
176         .version = NG_ABI_VERSION,
177         .name = NG_UDBP_NODE_TYPE,
178         .constructor = ng_udbp_constructor,
179         .rcvmsg = ng_udbp_rcvmsg,
180         .shutdown = ng_udbp_rmnode,
181         .newhook = ng_udbp_newhook,
182         .connect = ng_udbp_connect,
183         .rcvdata = ng_udbp_rcvdata,
184         .disconnect = ng_udbp_disconnect,
185         .cmdlist = ng_udbp_cmdlist,
186 };
187
188 /* USB config */
189 static const struct usb_config udbp_config[UDBP_T_MAX] = {
190
191         [UDBP_T_WR] = {
192                 .type = UE_BULK,
193                 .endpoint = UE_ADDR_ANY,
194                 .direction = UE_DIR_OUT,
195                 .bufsize = UDBP_BUFFERSIZE,
196                 .flags = {.pipe_bof = 1,.force_short_xfer = 1,},
197                 .callback = &udbp_bulk_write_callback,
198                 .timeout = UDBP_TIMEOUT,
199         },
200
201         [UDBP_T_RD] = {
202                 .type = UE_BULK,
203                 .endpoint = UE_ADDR_ANY,
204                 .direction = UE_DIR_IN,
205                 .bufsize = UDBP_BUFFERSIZE,
206                 .flags = {.pipe_bof = 1,.short_xfer_ok = 1,},
207                 .callback = &udbp_bulk_read_callback,
208         },
209
210         [UDBP_T_WR_CS] = {
211                 .type = UE_CONTROL,
212                 .endpoint = 0x00,       /* Control pipe */
213                 .direction = UE_DIR_ANY,
214                 .bufsize = sizeof(struct usb_device_request),
215                 .callback = &udbp_bulk_write_clear_stall_callback,
216                 .timeout = 1000,        /* 1 second */
217                 .interval = 50, /* 50ms */
218         },
219
220         [UDBP_T_RD_CS] = {
221                 .type = UE_CONTROL,
222                 .endpoint = 0x00,       /* Control pipe */
223                 .direction = UE_DIR_ANY,
224                 .bufsize = sizeof(struct usb_device_request),
225                 .callback = &udbp_bulk_read_clear_stall_callback,
226                 .timeout = 1000,        /* 1 second */
227                 .interval = 50, /* 50ms */
228         },
229 };
230
231 static devclass_t udbp_devclass;
232
233 static device_method_t udbp_methods[] = {
234         /* Device interface */
235         DEVMETHOD(device_probe, udbp_probe),
236         DEVMETHOD(device_attach, udbp_attach),
237         DEVMETHOD(device_detach, udbp_detach),
238         {0, 0}
239 };
240
241 static driver_t udbp_driver = {
242         .name = "udbp",
243         .methods = udbp_methods,
244         .size = sizeof(struct udbp_softc),
245 };
246
247 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, udbp_modload, 0);
248 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
249 MODULE_DEPEND(udbp, usb, 1, 1, 1);
250
251 static int
252 udbp_modload(module_t mod, int event, void *data)
253 {
254         int error;
255
256         switch (event) {
257         case MOD_LOAD:
258                 error = ng_newtype(&ng_udbp_typestruct);
259                 if (error != 0) {
260                         printf("%s: Could not register "
261                             "Netgraph node type, error=%d\n",
262                             NG_UDBP_NODE_TYPE, error);
263                 }
264                 break;
265
266         case MOD_UNLOAD:
267                 error = ng_rmtype(&ng_udbp_typestruct);
268                 break;
269
270         default:
271                 error = EOPNOTSUPP;
272                 break;
273         }
274         return (error);
275 }
276
277 static int
278 udbp_probe(device_t dev)
279 {
280         struct usb_attach_arg *uaa = device_get_ivars(dev);
281
282         if (uaa->usb_mode != USB_MODE_HOST) {
283                 return (ENXIO);
284         }
285         /*
286          * XXX Julian, add the id of the device if you have one to test
287          * things with. run 'usbdevs -v' and note the 3 ID's that appear.
288          * The Vendor Id and Product Id are in hex and the Revision Id is in
289          * bcd. But as usual if the revision is 0x101 then you should
290          * compare the revision id in the device descriptor with 0x101 Or go
291          * search the file usbdevs.h. Maybe the device is already in there.
292          */
293         if (((uaa->info.idVendor == USB_VENDOR_NETCHIP) &&
294             (uaa->info.idProduct == USB_PRODUCT_NETCHIP_TURBOCONNECT)))
295                 return (0);
296
297         if (((uaa->info.idVendor == USB_VENDOR_PROLIFIC) &&
298             ((uaa->info.idProduct == USB_PRODUCT_PROLIFIC_PL2301) ||
299             (uaa->info.idProduct == USB_PRODUCT_PROLIFIC_PL2302))))
300                 return (0);
301
302         if ((uaa->info.idVendor == USB_VENDOR_ANCHOR) &&
303             (uaa->info.idProduct == USB_PRODUCT_ANCHOR_EZLINK))
304                 return (0);
305
306         if ((uaa->info.idVendor == USB_VENDOR_GENESYS) &&
307             (uaa->info.idProduct == USB_PRODUCT_GENESYS_GL620USB))
308                 return (0);
309
310         return (ENXIO);
311 }
312
313 static int
314 udbp_attach(device_t dev)
315 {
316         struct usb_attach_arg *uaa = device_get_ivars(dev);
317         struct udbp_softc *sc = device_get_softc(dev);
318         int error;
319
320         device_set_usb2_desc(dev);
321
322         snprintf(sc->sc_name, sizeof(sc->sc_name),
323             "%s", device_get_nameunit(dev));
324
325         mtx_init(&sc->sc_mtx, "udbp lock", NULL, MTX_DEF | MTX_RECURSE);
326
327         error = usb2_transfer_setup(uaa->device, &uaa->info.bIfaceIndex,
328             sc->sc_xfer, udbp_config, UDBP_T_MAX, sc, &sc->sc_mtx);
329         if (error) {
330                 DPRINTF("error=%s\n", usb2_errstr(error));
331                 goto detach;
332         }
333         NG_BT_MBUFQ_INIT(&sc->sc_xmitq, UDBP_Q_MAXLEN);
334
335         NG_BT_MBUFQ_INIT(&sc->sc_xmitq_hipri, UDBP_Q_MAXLEN);
336
337         /* create Netgraph node */
338
339         if (ng_make_node_common(&ng_udbp_typestruct, &sc->sc_node) != 0) {
340                 printf("%s: Could not create Netgraph node\n",
341                     sc->sc_name);
342                 sc->sc_node = NULL;
343                 goto detach;
344         }
345         /* name node */
346
347         if (ng_name_node(sc->sc_node, sc->sc_name) != 0) {
348                 printf("%s: Could not name node\n",
349                     sc->sc_name);
350                 NG_NODE_UNREF(sc->sc_node);
351                 sc->sc_node = NULL;
352                 goto detach;
353         }
354         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
355
356         /* the device is now operational */
357
358         return (0);                     /* success */
359
360 detach:
361         udbp_detach(dev);
362         return (ENOMEM);                /* failure */
363 }
364
365 static int
366 udbp_detach(device_t dev)
367 {
368         struct udbp_softc *sc = device_get_softc(dev);
369
370         /* destroy Netgraph node */
371
372         if (sc->sc_node != NULL) {
373                 NG_NODE_SET_PRIVATE(sc->sc_node, NULL);
374                 ng_rmnode_self(sc->sc_node);
375                 sc->sc_node = NULL;
376         }
377         /* free USB transfers, if any */
378
379         usb2_transfer_unsetup(sc->sc_xfer, UDBP_T_MAX);
380
381         mtx_destroy(&sc->sc_mtx);
382
383         /* destroy queues */
384
385         NG_BT_MBUFQ_DESTROY(&sc->sc_xmitq);
386         NG_BT_MBUFQ_DESTROY(&sc->sc_xmitq_hipri);
387
388         /* extra check */
389
390         if (sc->sc_bulk_in_buffer) {
391                 m_freem(sc->sc_bulk_in_buffer);
392                 sc->sc_bulk_in_buffer = NULL;
393         }
394         return (0);                     /* success */
395 }
396
397 static void
398 udbp_bulk_read_callback(struct usb_xfer *xfer)
399 {
400         struct udbp_softc *sc = xfer->priv_sc;
401         struct mbuf *m;
402
403         switch (USB_GET_STATE(xfer)) {
404         case USB_ST_TRANSFERRED:
405
406                 /* allocate new mbuf */
407
408                 MGETHDR(m, M_DONTWAIT, MT_DATA);
409
410                 if (m == NULL) {
411                         goto tr_setup;
412                 }
413                 MCLGET(m, M_DONTWAIT);
414
415                 if (!(m->m_flags & M_EXT)) {
416                         m_freem(m);
417                         goto tr_setup;
418                 }
419                 m->m_pkthdr.len = m->m_len = xfer->actlen;
420
421                 usb2_copy_out(xfer->frbuffers, 0, m->m_data, xfer->actlen);
422
423                 sc->sc_bulk_in_buffer = m;
424
425                 DPRINTF("received package %d "
426                     "bytes\n", xfer->actlen);
427
428         case USB_ST_SETUP:
429 tr_setup:
430                 if (sc->sc_bulk_in_buffer) {
431                         ng_send_fn(sc->sc_node, NULL, &udbp_bulk_read_complete, NULL, 0);
432                         return;
433                 }
434                 if (sc->sc_flags & UDBP_FLAG_READ_STALL) {
435                         usb2_transfer_start(sc->sc_xfer[UDBP_T_RD_CS]);
436                         return;
437                 }
438                 xfer->frlengths[0] = xfer->max_data_length;
439                 usb2_start_hardware(xfer);
440                 return;
441
442         default:                        /* Error */
443                 if (xfer->error != USB_ERR_CANCELLED) {
444                         /* try to clear stall first */
445                         sc->sc_flags |= UDBP_FLAG_READ_STALL;
446                         usb2_transfer_start(sc->sc_xfer[UDBP_T_RD_CS]);
447                 }
448                 return;
449
450         }
451 }
452
453 static void
454 udbp_bulk_read_clear_stall_callback(struct usb_xfer *xfer)
455 {
456         struct udbp_softc *sc = xfer->priv_sc;
457         struct usb_xfer *xfer_other = sc->sc_xfer[UDBP_T_RD];
458
459         if (usb2_clear_stall_callback(xfer, xfer_other)) {
460                 DPRINTF("stall cleared\n");
461                 sc->sc_flags &= ~UDBP_FLAG_READ_STALL;
462                 usb2_transfer_start(xfer_other);
463         }
464 }
465
466 static void
467 udbp_bulk_read_complete(node_p node, hook_p hook, void *arg1, int arg2)
468 {
469         struct udbp_softc *sc = NG_NODE_PRIVATE(node);
470         struct mbuf *m;
471         int error;
472
473         if (sc == NULL) {
474                 return;
475         }
476         mtx_lock(&sc->sc_mtx);
477
478         m = sc->sc_bulk_in_buffer;
479
480         if (m) {
481
482                 sc->sc_bulk_in_buffer = NULL;
483
484                 if ((sc->sc_hook == NULL) ||
485                     NG_HOOK_NOT_VALID(sc->sc_hook)) {
486                         DPRINTF("No upstream hook\n");
487                         goto done;
488                 }
489                 sc->sc_packets_in++;
490
491                 NG_SEND_DATA_ONLY(error, sc->sc_hook, m);
492
493                 m = NULL;
494         }
495 done:
496         if (m) {
497                 m_freem(m);
498         }
499         /* start USB bulk-in transfer, if not already started */
500
501         usb2_transfer_start(sc->sc_xfer[UDBP_T_RD]);
502
503         mtx_unlock(&sc->sc_mtx);
504 }
505
506 static void
507 udbp_bulk_write_callback(struct usb_xfer *xfer)
508 {
509         struct udbp_softc *sc = xfer->priv_sc;
510         struct mbuf *m;
511
512         switch (USB_GET_STATE(xfer)) {
513         case USB_ST_TRANSFERRED:
514
515                 sc->sc_packets_out++;
516
517         case USB_ST_SETUP:
518                 if (sc->sc_flags & UDBP_FLAG_WRITE_STALL) {
519                         usb2_transfer_start(sc->sc_xfer[UDBP_T_WR_CS]);
520                         return;
521                 }
522                 /* get next mbuf, if any */
523
524                 NG_BT_MBUFQ_DEQUEUE(&sc->sc_xmitq_hipri, m);
525                 if (m == NULL) {
526                         NG_BT_MBUFQ_DEQUEUE(&sc->sc_xmitq, m);
527                         if (m == NULL) {
528                                 DPRINTF("Data queue is empty\n");
529                                 return;
530                         }
531                 }
532                 if (m->m_pkthdr.len > MCLBYTES) {
533                         DPRINTF("truncating large packet "
534                             "from %d to %d bytes\n", m->m_pkthdr.len,
535                             MCLBYTES);
536                         m->m_pkthdr.len = MCLBYTES;
537                 }
538                 usb2_m_copy_in(xfer->frbuffers, 0, m, 0, m->m_pkthdr.len);
539
540                 xfer->frlengths[0] = m->m_pkthdr.len;
541
542                 m_freem(m);
543
544                 DPRINTF("packet out: %d bytes\n",
545                     xfer->frlengths[0]);
546
547                 usb2_start_hardware(xfer);
548                 return;
549
550         default:                        /* Error */
551                 if (xfer->error != USB_ERR_CANCELLED) {
552                         /* try to clear stall first */
553                         sc->sc_flags |= UDBP_FLAG_WRITE_STALL;
554                         usb2_transfer_start(sc->sc_xfer[UDBP_T_WR_CS]);
555                 }
556                 return;
557
558         }
559 }
560
561 static void
562 udbp_bulk_write_clear_stall_callback(struct usb_xfer *xfer)
563 {
564         struct udbp_softc *sc = xfer->priv_sc;
565         struct usb_xfer *xfer_other = sc->sc_xfer[UDBP_T_WR];
566
567         if (usb2_clear_stall_callback(xfer, xfer_other)) {
568                 DPRINTF("stall cleared\n");
569                 sc->sc_flags &= ~UDBP_FLAG_WRITE_STALL;
570                 usb2_transfer_start(xfer_other);
571         }
572 }
573
574 /***********************************************************************
575  * Start of Netgraph methods
576  **********************************************************************/
577
578 /*
579  * If this is a device node so this work is done in the attach()
580  * routine and the constructor will return EINVAL as you should not be able
581  * to create nodes that depend on hardware (unless you can add the hardware :)
582  */
583 static int
584 ng_udbp_constructor(node_p node)
585 {
586         return (EINVAL);
587 }
588
589 /*
590  * Give our ok for a hook to be added...
591  * If we are not running this might kick a device into life.
592  * Possibly decode information out of the hook name.
593  * Add the hook's private info to the hook structure.
594  * (if we had some). In this example, we assume that there is a
595  * an array of structs, called 'channel' in the private info,
596  * one for each active channel. The private
597  * pointer of each hook points to the appropriate UDBP_hookinfo struct
598  * so that the source of an input packet is easily identified.
599  */
600 static int
601 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
602 {
603         struct udbp_softc *sc = NG_NODE_PRIVATE(node);
604         int32_t error = 0;
605
606         if (strcmp(name, NG_UDBP_HOOK_NAME)) {
607                 return (EINVAL);
608         }
609         mtx_lock(&sc->sc_mtx);
610
611         if (sc->sc_hook != NULL) {
612                 error = EISCONN;
613         } else {
614                 sc->sc_hook = hook;
615                 NG_HOOK_SET_PRIVATE(hook, NULL);
616         }
617
618         mtx_unlock(&sc->sc_mtx);
619
620         return (error);
621 }
622
623 /*
624  * Get a netgraph control message.
625  * Check it is one we understand. If needed, send a response.
626  * We could save the address for an async action later, but don't here.
627  * Always free the message.
628  * The response should be in a malloc'd region that the caller can 'free'.
629  * A response is not required.
630  * Theoretically you could respond defferently to old message types if
631  * the cookie in the header didn't match what we consider to be current
632  * (so that old userland programs could continue to work).
633  */
634 static int
635 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
636 {
637         struct udbp_softc *sc = NG_NODE_PRIVATE(node);
638         struct ng_mesg *resp = NULL;
639         int error = 0;
640         struct ng_mesg *msg;
641
642         NGI_GET_MSG(item, msg);
643         /* Deal with message according to cookie and command */
644         switch (msg->header.typecookie) {
645         case NGM_UDBP_COOKIE:
646                 switch (msg->header.cmd) {
647                 case NGM_UDBP_GET_STATUS:
648                         {
649                                 struct ngudbpstat *stats;
650
651                                 NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
652                                 if (!resp) {
653                                         error = ENOMEM;
654                                         break;
655                                 }
656                                 stats = (struct ngudbpstat *)resp->data;
657                                 mtx_lock(&sc->sc_mtx);
658                                 stats->packets_in = sc->sc_packets_in;
659                                 stats->packets_out = sc->sc_packets_out;
660                                 mtx_unlock(&sc->sc_mtx);
661                                 break;
662                         }
663                 case NGM_UDBP_SET_FLAG:
664                         if (msg->header.arglen != sizeof(uint32_t)) {
665                                 error = EINVAL;
666                                 break;
667                         }
668                         DPRINTF("flags = 0x%08x\n",
669                             *((uint32_t *)msg->data));
670                         break;
671                 default:
672                         error = EINVAL; /* unknown command */
673                         break;
674                 }
675                 break;
676         default:
677                 error = EINVAL;         /* unknown cookie type */
678                 break;
679         }
680
681         /* Take care of synchronous response, if any */
682         NG_RESPOND_MSG(error, node, item, resp);
683         NG_FREE_MSG(msg);
684         return (error);
685 }
686
687 /*
688  * Accept data from the hook and queue it for output.
689  */
690 static int
691 ng_udbp_rcvdata(hook_p hook, item_p item)
692 {
693         struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
694         struct ng_bt_mbufq *queue_ptr;
695         struct mbuf *m;
696         struct ng_tag_prio *ptag;
697         int error;
698
699         if (sc == NULL) {
700                 NG_FREE_ITEM(item);
701                 return (EHOSTDOWN);
702         }
703         NGI_GET_M(item, m);
704         NG_FREE_ITEM(item);
705
706         /*
707          * Now queue the data for when it can be sent
708          */
709         ptag = (void *)m_tag_locate(m, NGM_GENERIC_COOKIE,
710             NG_TAG_PRIO, NULL);
711
712         if (ptag && (ptag->priority > NG_PRIO_CUTOFF))
713                 queue_ptr = &sc->sc_xmitq_hipri;
714         else
715                 queue_ptr = &sc->sc_xmitq;
716
717         mtx_lock(&sc->sc_mtx);
718
719         if (NG_BT_MBUFQ_FULL(queue_ptr)) {
720                 NG_BT_MBUFQ_DROP(queue_ptr);
721                 NG_FREE_M(m);
722                 error = ENOBUFS;
723         } else {
724                 NG_BT_MBUFQ_ENQUEUE(queue_ptr, m);
725                 /*
726                  * start bulk-out transfer, if not already started:
727                  */
728                 usb2_transfer_start(sc->sc_xfer[UDBP_T_WR]);
729                 error = 0;
730         }
731
732         mtx_unlock(&sc->sc_mtx);
733
734         return (error);
735 }
736
737 /*
738  * Do local shutdown processing..
739  * We are a persistant device, we refuse to go away, and
740  * only remove our links and reset ourself.
741  */
742 static int
743 ng_udbp_rmnode(node_p node)
744 {
745         struct udbp_softc *sc = NG_NODE_PRIVATE(node);
746
747         /* Let old node go */
748         NG_NODE_SET_PRIVATE(node, NULL);
749         NG_NODE_UNREF(node);            /* forget it ever existed */
750
751         if (sc == NULL) {
752                 goto done;
753         }
754         /* Create Netgraph node */
755         if (ng_make_node_common(&ng_udbp_typestruct, &sc->sc_node) != 0) {
756                 printf("%s: Could not create Netgraph node\n",
757                     sc->sc_name);
758                 sc->sc_node = NULL;
759                 goto done;
760         }
761         /* Name node */
762         if (ng_name_node(sc->sc_node, sc->sc_name) != 0) {
763                 printf("%s: Could not name Netgraph node\n",
764                     sc->sc_name);
765                 NG_NODE_UNREF(sc->sc_node);
766                 sc->sc_node = NULL;
767                 goto done;
768         }
769         NG_NODE_SET_PRIVATE(sc->sc_node, sc);
770
771 done:
772         if (sc) {
773                 mtx_unlock(&sc->sc_mtx);
774         }
775         return (0);
776 }
777
778 /*
779  * This is called once we've already connected a new hook to the other node.
780  * It gives us a chance to balk at the last minute.
781  */
782 static int
783 ng_udbp_connect(hook_p hook)
784 {
785         struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
786
787         /* probably not at splnet, force outward queueing */
788         NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
789
790         mtx_lock(&sc->sc_mtx);
791
792         sc->sc_flags |= (UDBP_FLAG_READ_STALL |
793             UDBP_FLAG_WRITE_STALL);
794
795         /* start bulk-in transfer */
796         usb2_transfer_start(sc->sc_xfer[UDBP_T_RD]);
797
798         /* start bulk-out transfer */
799         usb2_transfer_start(sc->sc_xfer[UDBP_T_WR]);
800
801         mtx_unlock(&sc->sc_mtx);
802
803         return (0);
804 }
805
806 /*
807  * Dook disconnection
808  *
809  * For this type, removal of the last link destroys the node
810  */
811 static int
812 ng_udbp_disconnect(hook_p hook)
813 {
814         struct udbp_softc *sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
815         int error = 0;
816
817         if (sc != NULL) {
818
819                 mtx_lock(&sc->sc_mtx);
820
821                 if (hook != sc->sc_hook) {
822                         error = EINVAL;
823                 } else {
824
825                         /* stop bulk-in transfer */
826                         usb2_transfer_stop(sc->sc_xfer[UDBP_T_RD_CS]);
827                         usb2_transfer_stop(sc->sc_xfer[UDBP_T_RD]);
828
829                         /* stop bulk-out transfer */
830                         usb2_transfer_stop(sc->sc_xfer[UDBP_T_WR_CS]);
831                         usb2_transfer_stop(sc->sc_xfer[UDBP_T_WR]);
832
833                         /* cleanup queues */
834                         NG_BT_MBUFQ_DRAIN(&sc->sc_xmitq);
835                         NG_BT_MBUFQ_DRAIN(&sc->sc_xmitq_hipri);
836
837                         if (sc->sc_bulk_in_buffer) {
838                                 m_freem(sc->sc_bulk_in_buffer);
839                                 sc->sc_bulk_in_buffer = NULL;
840                         }
841                         sc->sc_hook = NULL;
842                 }
843
844                 mtx_unlock(&sc->sc_mtx);
845         }
846         if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
847             && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
848                 ng_rmnode_self(NG_HOOK_NODE(hook));
849
850         return (error);
851 }