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