Remove spl*() calls from the bus/ infrastructure, replacing them with
[dragonfly.git] / sys / dev / usbmisc / udbp / udbp.c
CommitLineData
1550dfd9
MD
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 $
4e01b467 30 * $DragonFly: src/sys/dev/usbmisc/udbp/Attic/udbp.c,v 1.5 2005/06/02 20:40:46 dillon Exp $
1550dfd9
MD
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>
d47ac1a2 81#if defined(__FreeBSD__) && __FreeBSD_version >= 500014
1550dfd9
MD
82#include <sys/selinfo.h>
83#else
84#include <sys/select.h>
85#endif
86#include <sys/poll.h>
87#include <sys/mbuf.h>
88#include <sys/socket.h>
89#include <sys/ctype.h>
90#include <sys/errno.h>
91#include <sys/sysctl.h>
92#include <net/if.h>
93#include <machine/bus.h>
94
95#include <dev/usb/usb.h>
96#include <dev/usb/usbdi.h>
97#include <dev/usb/usbdi_util.h>
98#include <dev/usb/usbdivar.h>
99#include <dev/usb/usbhid.h>
100
101#include <dev/usb/usbdevs.h>
102
103
104#include <netgraph/ng_message.h>
105#include <netgraph/ng_parse.h>
106#include <dev/usb/udbp.h>
107#include <netgraph/netgraph.h>
108
109#ifdef USB_DEBUG
110#define DPRINTF(x) if (udbpdebug) logprintf x
111#define DPRINTFN(n,x) if (udbpdebug>(n)) logprintf x
112int udbpdebug = 0;
113SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
114SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
115 &udbpdebug, 0, "udbp debug level");
116#else
117#define DPRINTF(x)
118#define DPRINTFN(n,x)
119#endif
120
121#define MS_TO_TICKS(ms) ((ms) * hz / 1000)
122
123#define UDBP_TIMEOUT 2000 /* timeout on outbound transfers, in msecs */
124#define UDBP_BUFFERSIZE 2048 /* maximum number of bytes in one transfer */
125
126
127struct udbp_softc {
128 device_t sc_dev; /* base device */
129 usbd_interface_handle sc_iface;
130
131 usbd_pipe_handle sc_bulkin_pipe;
132 int sc_bulkin;
133 usbd_xfer_handle sc_bulkin_xfer;
134 void *sc_bulkin_buffer;
135 int sc_bulkin_bufferlen;
136 int sc_bulkin_datalen;
137
138 usbd_pipe_handle sc_bulkout_pipe;
139 int sc_bulkout;
140 usbd_xfer_handle sc_bulkout_xfer;
141 void *sc_bulkout_buffer;
142 int sc_bulkout_bufferlen;
143 int sc_bulkout_datalen;
144
145 int flags;
146# define DISCONNECTED 0x01
147# define OUT_BUSY 0x02
148# define NETGRAPH_INITIALISED 0x04
149 node_p node; /* back pointer to node */
150 hook_p hook; /* pointer to the hook */
151 u_int packets_in; /* packets in from downstream */
152 u_int packets_out; /* packets out towards downstream */
153 struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
154 struct ifqueue xmitq; /* low-priority transmit queue */
155
156};
157typedef struct udbp_softc *udbp_p;
158
159
160
161Static ng_constructor_t ng_udbp_constructor;
162Static ng_rcvmsg_t ng_udbp_rcvmsg;
163Static ng_shutdown_t ng_udbp_rmnode;
164Static ng_newhook_t ng_udbp_newhook;
165Static ng_connect_t ng_udbp_connect;
166Static ng_rcvdata_t ng_udbp_rcvdata;
167Static ng_disconnect_t ng_udbp_disconnect;
168
169/* Parse type for struct ngudbpstat */
170Static const struct ng_parse_struct_field
171 ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
172Static const struct ng_parse_type ng_udbp_stat_type = {
173 &ng_parse_struct_type,
174 &ng_udbp_stat_type_fields
175};
176
177/* List of commands and how to convert arguments to/from ASCII */
178Static const struct ng_cmdlist ng_udbp_cmdlist[] = {
179 {
180 NGM_UDBP_COOKIE,
181 NGM_UDBP_GET_STATUS,
182 "getstatus",
183 NULL,
184 &ng_udbp_stat_type,
185 },
186 {
187 NGM_UDBP_COOKIE,
188 NGM_UDBP_SET_FLAG,
189 "setflag",
190 &ng_parse_int32_type,
191 NULL
192 },
193 { 0 }
194};
195
196/* Netgraph node type descriptor */
197Static struct ng_type ng_udbp_typestruct = {
198 NG_ABI_VERSION,
199 NG_UDBP_NODE_TYPE,
200 NULL,
201 ng_udbp_constructor,
202 ng_udbp_rcvmsg,
203 ng_udbp_rmnode,
204 ng_udbp_newhook,
205 NULL,
206 ng_udbp_connect,
207 ng_udbp_rcvdata,
208 ng_udbp_disconnect,
209 ng_udbp_cmdlist
210};
211
212Static int udbp_setup_in_transfer (udbp_p sc);
213Static void udbp_in_transfer_cb (usbd_xfer_handle xfer,
214 usbd_private_handle priv,
215 usbd_status err);
216
217Static int udbp_setup_out_transfer (udbp_p sc);
218Static void udbp_out_transfer_cb (usbd_xfer_handle xfer,
219 usbd_private_handle priv,
220 usbd_status err);
221
222USB_DECLARE_DRIVER(udbp);
223
224USB_MATCH(udbp)
225{
226 USB_MATCH_START(udbp, uaa);
227 usb_interface_descriptor_t *id;
228 if (!uaa->iface)
229 return (UMATCH_NONE);
230 id = usbd_get_interface_descriptor(uaa->iface);
231
232 /* XXX Julian, add the id of the device if you have one to test
233 * things with. run 'usbdevs -v' and note the 3 ID's that appear.
234 * The Vendor Id and Product Id are in hex and the Revision Id is in
235 * bcd. But as usual if the revision is 0x101 then you should compare
236 * the revision id in the device descriptor with 0x101
237 * Or go search the file usbdevs.h. Maybe the device is already in
238 * there.
239 */
240 if ((uaa->vendor == USB_VENDOR_NETCHIP &&
241 uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
242 return(UMATCH_VENDOR_PRODUCT);
243
244 if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
245 (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
246 uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
247 return(UMATCH_VENDOR_PRODUCT);
248
249 if ((uaa->vendor == USB_VENDOR_ANCHOR &&
250 uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
251 return(UMATCH_VENDOR_PRODUCT);
252
253 return (UMATCH_NONE);
254}
255
256USB_ATTACH(udbp)
257{
258 USB_ATTACH_START(udbp, sc, uaa);
259 usbd_interface_handle iface = uaa->iface;
260 usb_interface_descriptor_t *id;
261 usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
262 usbd_status err;
263 char devinfo[1024];
264 int i;
265 static int ngudbp_done_init=0;
266
267 sc->flags |= DISCONNECTED;
268 /* fetch the interface handle for the first interface */
269 (void) usbd_device2interface_handle(uaa->device, 0, &iface);
270 id = usbd_get_interface_descriptor(iface);
271 usbd_devinfo(uaa->device, 0, devinfo);
272 USB_ATTACH_SETUP;
273 printf("%s: %s, iclass %d/%d\n", USBDEVNAME(sc->sc_dev),
274 devinfo, id->bInterfaceClass, id->bInterfaceSubClass);
275
276 /* Find the two first bulk endpoints */
277 for (i = 0 ; i < id->bNumEndpoints; i++) {
278 ed = usbd_interface2endpoint_descriptor(iface, i);
279 if (!ed) {
280 printf("%s: could not read endpoint descriptor\n",
281 USBDEVNAME(sc->sc_dev));
282 USB_ATTACH_ERROR_RETURN;
283 }
284
285 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
286 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
287 ed_bulkin = ed;
288 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
289 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
290 ed_bulkout = ed;
291 }
292
293 if (ed_bulkin && ed_bulkout) /* found all we need */
294 break;
295 }
296
297 /* Verify that we goething sensible */
298 if (ed_bulkin == NULL || ed_bulkout == NULL) {
299 printf("%s: bulk-in and/or bulk-out endpoint not found\n",
300 USBDEVNAME(sc->sc_dev));
301 USB_ATTACH_ERROR_RETURN;
302 }
303
304 if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
305 ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
306 printf("%s: bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
307 USBDEVNAME(sc->sc_dev),
308 ed_bulkin->wMaxPacketSize[0],
309 ed_bulkout->wMaxPacketSize[0],
310 ed_bulkin->wMaxPacketSize[1],
311 ed_bulkout->wMaxPacketSize[1]);
312 USB_ATTACH_ERROR_RETURN;
313 }
314
315 sc->sc_bulkin = ed_bulkin->bEndpointAddress;
316 sc->sc_bulkout = ed_bulkout->bEndpointAddress;
317
318 DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
319 USBDEVNAME(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
320 ed_bulkin->wMaxPacketSize[0]));
321
322 /* Allocate the in transfer struct */
323 sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
324 if (!sc->sc_bulkin_xfer) {
325 goto bad;
326 }
327 sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
328 if (!sc->sc_bulkout_xfer) {
329 goto bad;
330 }
ad86f6b6 331 sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
1550dfd9
MD
332 if (!sc->sc_bulkin_buffer) {
333 goto bad;
334 }
ad86f6b6 335 sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_INTWAIT);
1550dfd9
MD
336 if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
337 goto bad;
338 }
339 sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
340 sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
341
342 /* We have decided on which endpoints to use, now open the pipes */
343 err = usbd_open_pipe(iface, sc->sc_bulkin,
344 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
345 if (err) {
346 printf("%s: cannot open bulk-in pipe (addr %d)\n",
347 USBDEVNAME(sc->sc_dev), sc->sc_bulkin);
348 goto bad;
349 }
350 err = usbd_open_pipe(iface, sc->sc_bulkout,
351 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
352 if (err) {
353 printf("%s: cannot open bulk-out pipe (addr %d)\n",
354 USBDEVNAME(sc->sc_dev), sc->sc_bulkout);
355 goto bad;
356 }
357
358 if (!ngudbp_done_init){
359 ngudbp_done_init=1;
360 if (ng_newtype(&ng_udbp_typestruct)) {
361 printf("ngudbp install failed\n");
362 goto bad;
363 }
364 }
365
366 if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
367 char nodename[128];
368 sprintf(nodename, "%s", USBDEVNAME(sc->sc_dev));
369 if ((err = ng_name_node(sc->node, nodename))) {
370 NG_NODE_UNREF(sc->node);
371 sc->node = NULL;
372 goto bad;
373 } else {
374 NG_NODE_SET_PRIVATE(sc->node, sc);
375 sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
376 sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
377 mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
378 MTX_DEF);
379 mtx_init(&sc->xmitq_hipri.ifq_mtx,
380 "usb_xmitq_hipri", NULL, MTX_DEF);
381 }
382 }
383 sc->flags = NETGRAPH_INITIALISED;
384 /* sc->flags &= ~DISCONNECTED; */ /* XXX */
385
386
387 /* the device is now operational */
388
389
390 /* schedule the first incoming xfer */
391 err = udbp_setup_in_transfer(sc);
392 if (err) {
393 goto bad;
394 }
395 USB_ATTACH_SUCCESS_RETURN;
396bad:
397#if 0 /* probably done in udbp_detach() */
398 if (sc->sc_bulkout_buffer) {
399 FREE(sc->sc_bulkout_buffer, M_USBDEV);
400 }
401 if (sc->sc_bulkin_buffer) {
402 FREE(sc->sc_bulkin_buffer, M_USBDEV);
403 }
404 if (sc->sc_bulkout_xfer) {
405 usbd_free_xfer(sc->sc_bulkout_xfer);
406 }
407 if (sc->sc_bulkin_xfer) {
408 usbd_free_xfer(sc->sc_bulkin_xfer);
409 }
410#endif
411 udbp_detach(self);
412 USB_ATTACH_ERROR_RETURN;
413}
414
415
416USB_DETACH(udbp)
417{
418 USB_DETACH_START(udbp, sc);
419
420 sc->flags |= DISCONNECTED;
421
422 DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));
423
424 if (sc->sc_bulkin_pipe) {
425 usbd_abort_pipe(sc->sc_bulkin_pipe);
426 usbd_close_pipe(sc->sc_bulkin_pipe);
427 }
428 if (sc->sc_bulkout_pipe) {
429 usbd_abort_pipe(sc->sc_bulkout_pipe);
430 usbd_close_pipe(sc->sc_bulkout_pipe);
431 }
432
433 if (sc->flags & NETGRAPH_INITIALISED) {
434 ng_rmnode_self(sc->node);
435 NG_NODE_SET_PRIVATE(sc->node, NULL);
436 NG_NODE_UNREF(sc->node);
437 sc->node = NULL; /* Paranoid */
438 }
439
440 if (sc->sc_bulkin_xfer)
441 usbd_free_xfer(sc->sc_bulkin_xfer);
442 if (sc->sc_bulkout_xfer)
443 usbd_free_xfer(sc->sc_bulkout_xfer);
444
445 if (sc->sc_bulkin_buffer)
446 free(sc->sc_bulkin_buffer, M_USBDEV);
447 if (sc->sc_bulkout_buffer)
448 free(sc->sc_bulkout_buffer, M_USBDEV);
449 return 0;
450}
451
452
453Static int
454udbp_setup_in_transfer(udbp_p sc)
455{
456 void *priv = sc; /* XXX this should probably be some pointer to
457 * struct describing the transfer (mbuf?)
458 * See also below.
459 */
460 usbd_status err;
461
462 /* XXX
463 * How should we arrange for 2 extra bytes at the start of the
464 * packet?
465 */
466
467 /* Initialise a USB transfer and then schedule it */
468
469 (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
470 sc->sc_bulkin_pipe,
471 priv,
472 sc->sc_bulkin_buffer,
473 sc->sc_bulkin_bufferlen,
474 USBD_SHORT_XFER_OK,
475 USBD_NO_TIMEOUT,
476 udbp_in_transfer_cb);
477
478 err = usbd_transfer(sc->sc_bulkin_xfer);
479 if (err && err != USBD_IN_PROGRESS) {
480 DPRINTF(("%s: failed to setup in-transfer, %s\n",
481 USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
482 return(err);
483 }
484
485 return (USBD_NORMAL_COMPLETION);
486}
487
488Static void
489udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
490 usbd_status err)
491{
492 udbp_p sc = priv; /* XXX see priv above */
493 int s;
494 int len;
495 struct mbuf *m;
496
497 if (err) {
498 if (err != USBD_CANCELLED) {
499 DPRINTF(("%s: bulk-out transfer failed: %s\n",
500 USBDEVNAME(sc->sc_dev), usbd_errstr(err)));
501 } else {
502 /* USBD_CANCELLED happens at unload of the driver */
503 return;
504 }
505
506 /* Transfer has failed, packet is not received */
507 } else {
508
509 len = xfer->actlen;
510
511 s = splimp(); /* block network stuff too */
512 if (sc->hook) {
513 /* get packet from device and send on */
514 m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
515 NG_SEND_DATA_ONLY(err, sc->hook, m);
516 }
517 splx(s);
518
519 }
520 /* schedule the next in transfer */
521 udbp_setup_in_transfer(sc);
522}
523
524
525Static int
526udbp_setup_out_transfer(udbp_p sc)
527{
528 void *priv = sc; /* XXX this should probably be some pointer to
529 * struct describing the transfer (mbuf?)
530 * See also below.
531 */
532 int pktlen;
533 usbd_status err;
4e01b467 534 int s1;
1550dfd9
MD
535 struct mbuf *m;
536
4e01b467 537 crit_enter();
1550dfd9
MD
538 if (sc->flags & OUT_BUSY)
539 panic("out transfer already in use, we should add queuing");
540 sc->flags |= OUT_BUSY;
4e01b467 541 crit_exit();
1550dfd9
MD
542 s1 = splimp(); /* Queueing happens at splnet */
543 IF_DEQUEUE(&sc->xmitq_hipri, m);
544 if (m == NULL) {
545 IF_DEQUEUE(&sc->xmitq, m);
546 }
547 splx(s1);
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
586Static void
587udbp_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 */
1550dfd9
MD
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
4e01b467 602 crit_enter();
1550dfd9
MD
603 sc->flags &= ~OUT_BUSY;
604 udbp_setup_out_transfer(sc);
4e01b467 605 crit_exit();
1550dfd9
MD
606}
607
608DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
609MODULE_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 */
621Static int
622ng_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 */
638Static int
639ng_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 */
670Static int
671ng_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 */
723Static int
724ng_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;
1550dfd9
MD
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 }
4e01b467 743 crit_enter();
fd81ccf9
JS
744 if (IF_QFULL(xmitq_p)) {
745 IF_DROP(xmitq_p);
4e01b467 746 crit_exit();
1550dfd9
MD
747 error = ENOBUFS;
748 goto bad;
749 }
fd81ccf9 750 IF_ENQUEUE(xmitq_p, m);
1550dfd9
MD
751 if (!(sc->flags & OUT_BUSY))
752 udbp_setup_out_transfer(sc);
4e01b467 753 crit_exit();
1550dfd9
MD
754 return (0);
755
756bad: /*
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 */
770Static int
771ng_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 */
813Static int
814ng_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 */
827Static int
828ng_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