2 * Copyright (c) 2009 Fredrik Lindberg <fli@shapeshifter.se>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD$");
29 #include <sys/param.h>
30 #include <sys/types.h>
31 #include <sys/sockio.h>
33 #include <sys/malloc.h>
34 #include <sys/kernel.h>
35 #include <sys/module.h>
36 #include <sys/socket.h>
38 #include <sys/sysctl.h>
39 #include <sys/condvar.h>
44 #include <sys/systm.h>
46 #include <machine/bus.h>
49 #include <net/if_types.h>
50 #include <net/netisr.h>
52 #include <netinet/in.h>
53 #include <netinet/ip.h>
54 #include <netinet/ip6.h>
56 #include <dev/usb/usb.h>
57 #include <dev/usb/usbdi.h>
58 #include <dev/usb/usbdi_util.h>
59 #include <dev/usb/usb_cdc.h>
61 #define USB_DEBUG_VAR uhso_debug
62 #include <dev/usb/usb_debug.h>
63 #include <dev/usb/usb_process.h>
64 #include <dev/usb/usb_device.h>
65 #include <dev/usb/usb_busdma.h>
66 #include <dev/usb/usb_controller.h>
67 #include <dev/usb/usb_bus.h>
68 #include <dev/usb/serial/usb_serial.h>
69 #include <dev/usb/usb_msctest.h>
72 struct uhso_softc *ht_sc;
73 struct usb_xfer *ht_xfer[3];
74 int ht_muxport; /* Mux. port no */
81 struct usb_device *sc_udev;
83 uint32_t sc_type; /* Interface definition */
85 struct usb_xfer *sc_xfer[3];
87 uint8_t sc_iface_index;
90 struct usb_xfer * sc_ctrl_xfer[2];
91 uint8_t sc_ctrl_iface_no;
94 struct usb_xfer *sc_if_xfer[2];
96 struct mbuf *sc_mwait; /* Partial packet */
97 size_t sc_waitlen; /* No. of outstanding bytes */
98 struct ifqueue sc_rxq;
101 /* TTY related structures */
102 struct ucom_super_softc sc_super_ucom;
104 struct uhso_tty *sc_tty;
105 struct ucom_softc *sc_ucom;
111 #define UHSO_MAX_MTU 2048
114 * There are mainly two type of cards floating around.
115 * The first one has 2,3 or 4 interfaces with a multiplexed serial port
116 * and packet interface on the first interface and bulk serial ports
118 * The second type of card has several other interfaces, their purpose
119 * can be detected during run-time.
121 #define UHSO_IFACE_SPEC(usb_type, port, port_type) \
122 (((usb_type) << 24) | ((port) << 16) | (port_type))
124 #define UHSO_IFACE_USB_TYPE(x) ((x >> 24) & 0xff)
125 #define UHSO_IFACE_PORT(x) ((x >> 16) & 0xff)
126 #define UHSO_IFACE_PORT_TYPE(x) (x & 0xff)
129 * USB interface types
131 #define UHSO_IF_NET 0x01 /* Network packet interface */
132 #define UHSO_IF_MUX 0x02 /* Multiplexed serial port */
133 #define UHSO_IF_BULK 0x04 /* Bulk interface */
138 #define UHSO_PORT_UNKNOWN 0x00
139 #define UHSO_PORT_SERIAL 0x01 /* Serial port */
140 #define UHSO_PORT_NETWORK 0x02 /* Network packet interface */
143 * Multiplexed serial port destination sub-port names
145 #define UHSO_MPORT_TYPE_CTL 0x00 /* Control port */
146 #define UHSO_MPORT_TYPE_APP 0x01 /* Application */
147 #define UHSO_MPORT_TYPE_PCSC 0x02
148 #define UHSO_MPORT_TYPE_GPS 0x03
149 #define UHSO_MPORT_TYPE_APP2 0x04 /* Secondary application */
150 #define UHSO_MPORT_TYPE_MAX UHSO_MPORT_TYPE_APP2
151 #define UHSO_MPORT_TYPE_NOMAX 8 /* Max number of mux ports */
155 * Note that these definitions are arbitrary and do not match the values
156 * returned by the auto config descriptor.
158 #define UHSO_PORT_TYPE_CTL 0x01
159 #define UHSO_PORT_TYPE_APP 0x02
160 #define UHSO_PORT_TYPE_APP2 0x03
161 #define UHSO_PORT_TYPE_MODEM 0x04
162 #define UHSO_PORT_TYPE_NETWORK 0x05
163 #define UHSO_PORT_TYPE_DIAG 0x06
164 #define UHSO_PORT_TYPE_DIAG2 0x07
165 #define UHSO_PORT_TYPE_GPS 0x08
166 #define UHSO_PORT_TYPE_GPSCTL 0x09
167 #define UHSO_PORT_TYPE_PCSC 0x0a
168 #define UHSO_PORT_TYPE_MSD 0x0b
169 #define UHSO_PORT_TYPE_VOICE 0x0c
170 #define UHSO_PORT_TYPE_MAX 0x0c
172 static eventhandler_tag uhso_etag;
174 /* Overall port type */
175 static char *uhso_port[] = {
183 * Map between interface port type read from device and description type.
184 * The position in this array is a direct map to the auto config
187 static unsigned char uhso_port_map[] = {
191 UHSO_PORT_TYPE_GPSCTL,
195 UHSO_PORT_TYPE_NETWORK,
196 UHSO_PORT_TYPE_MODEM,
201 static char uhso_port_map_max = sizeof(uhso_port_map) / sizeof(char);
203 static unsigned char uhso_mux_port_map[] = {
211 static char *uhso_port_type[] = {
212 "Unknown", /* Not a valid port */
215 "Application (Secondary)",
219 "Diagnostic (Secondary)",
227 static char *uhso_port_type_sysctl[] = {
243 #define UHSO_STATIC_IFACE 0x01
244 #define UHSO_AUTO_IFACE 0x02
246 static const struct usb_device_id uhso_devs[] = {
247 #define UHSO_DEV(v,p,i) { USB_VPI(USB_VENDOR_##v, USB_PRODUCT_##v##_##p, i) }
248 /* Option GlobeSurfer iCON 7.2 */
249 UHSO_DEV(OPTION, GSICON72, UHSO_STATIC_IFACE),
250 /* Option iCON 225 */
251 UHSO_DEV(OPTION, GTHSDPA, UHSO_STATIC_IFACE),
252 /* Option GlobeSurfer iCON HSUPA */
253 UHSO_DEV(OPTION, GSICONHSUPA, UHSO_STATIC_IFACE),
254 /* Option GlobeTrotter HSUPA */
255 UHSO_DEV(OPTION, GTHSUPA, UHSO_STATIC_IFACE),
257 UHSO_DEV(OPTION, GE40X, UHSO_AUTO_IFACE),
258 UHSO_DEV(OPTION, GE40X_1, UHSO_AUTO_IFACE),
259 UHSO_DEV(OPTION, GE40X_2, UHSO_AUTO_IFACE),
260 UHSO_DEV(OPTION, GE40X_3, UHSO_AUTO_IFACE),
261 /* Option GlobeSurfer iCON 401 */
262 UHSO_DEV(OPTION, ICON401, UHSO_AUTO_IFACE),
263 /* Option GlobeTrotter Module 382 */
264 UHSO_DEV(OPTION, GMT382, UHSO_AUTO_IFACE),
265 /* Option iCON EDGE */
266 UHSO_DEV(OPTION, ICONEDGE, UHSO_STATIC_IFACE),
267 /* Option Module HSxPA */
268 UHSO_DEV(OPTION, MODHSXPA, UHSO_STATIC_IFACE),
269 /* Option iCON 321 */
270 UHSO_DEV(OPTION, ICON321, UHSO_STATIC_IFACE),
271 /* Option iCON 322 */
272 UHSO_DEV(OPTION, GTICON322, UHSO_STATIC_IFACE),
273 /* Option iCON 505 */
274 UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE),
278 SYSCTL_NODE(_hw_usb, OID_AUTO, uhso, CTLFLAG_RW, 0, "USB uhso");
279 static int uhso_autoswitch = 1;
280 SYSCTL_INT(_hw_usb_uhso, OID_AUTO, auto_switch, CTLFLAG_RW,
281 &uhso_autoswitch, 0, "Automatically switch to modem mode");
285 static int uhso_debug = UHSO_DEBUG;
287 static int uhso_debug = -1;
290 SYSCTL_INT(_hw_usb_uhso, OID_AUTO, debug, CTLFLAG_RW,
291 &uhso_debug, 0, "Debug level");
293 #define UHSO_DPRINTF(n, x, ...) {\
294 if (uhso_debug >= n) {\
295 printf("%s: " x, __func__, ##__VA_ARGS__);\
299 #define UHSO_DPRINTF(n, x, ...)
302 #ifdef UHSO_DEBUG_HEXDUMP
303 # define UHSO_HEXDUMP(_buf, _len) do { \
306 const char *__buf = (const char *)_buf; \
307 for (__tmp = 0; __tmp < _len; __tmp++) \
308 printf("%02hhx ", *__buf++); \
313 # define UHSO_HEXDUMP(_buf, _len)
317 UHSO_MUX_ENDPT_INTR = 0,
334 UHSO_BULK_ENDPT_READ = 0,
335 UHSO_BULK_ENDPT_WRITE,
336 UHSO_BULK_ENDPT_INTR,
340 static usb_callback_t uhso_mux_intr_callback;
341 static usb_callback_t uhso_mux_read_callback;
342 static usb_callback_t uhso_mux_write_callback;
343 static usb_callback_t uhso_bs_read_callback;
344 static usb_callback_t uhso_bs_write_callback;
345 static usb_callback_t uhso_bs_intr_callback;
346 static usb_callback_t uhso_ifnet_read_callback;
347 static usb_callback_t uhso_ifnet_write_callback;
349 /* Config used for the default control pipes */
350 static const struct usb_config uhso_ctrl_config[UHSO_CTRL_MAX] = {
354 .direction = UE_DIR_ANY,
355 .flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
356 .bufsize = sizeof(struct usb_device_request) + 1024,
357 .callback = &uhso_mux_read_callback
360 [UHSO_CTRL_WRITE] = {
363 .direction = UE_DIR_ANY,
364 .flags = { .pipe_bof = 1, .force_short_xfer = 1 },
365 .bufsize = sizeof(struct usb_device_request) + 1024,
367 .callback = &uhso_mux_write_callback
371 /* Config for the multiplexed serial ports */
372 static const struct usb_config uhso_mux_config[UHSO_MUX_ENDPT_MAX] = {
373 [UHSO_MUX_ENDPT_INTR] = {
374 .type = UE_INTERRUPT,
375 .endpoint = UE_ADDR_ANY,
376 .direction = UE_DIR_IN,
377 .flags = { .short_xfer_ok = 1 },
379 .callback = &uhso_mux_intr_callback,
383 /* Config for the raw IP-packet interface */
384 static const struct usb_config uhso_ifnet_config[UHSO_IFNET_MAX] = {
385 [UHSO_IFNET_READ] = {
387 .endpoint = UE_ADDR_ANY,
388 .direction = UE_DIR_IN,
389 .flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
391 .callback = &uhso_ifnet_read_callback
393 [UHSO_IFNET_WRITE] = {
395 .endpoint = UE_ADDR_ANY,
396 .direction = UE_DIR_OUT,
397 .flags = { .pipe_bof = 1, .force_short_xfer = 1 },
399 .timeout = 5 * USB_MS_HZ,
400 .callback = &uhso_ifnet_write_callback
404 /* Config for interfaces with normal bulk serial ports */
405 static const struct usb_config uhso_bs_config[UHSO_BULK_ENDPT_MAX] = {
406 [UHSO_BULK_ENDPT_READ] = {
408 .endpoint = UE_ADDR_ANY,
409 .direction = UE_DIR_IN,
410 .flags = { .pipe_bof = 1, .short_xfer_ok = 1 },
412 .callback = &uhso_bs_read_callback
415 [UHSO_BULK_ENDPT_WRITE] = {
417 .endpoint = UE_ADDR_ANY,
418 .direction = UE_DIR_OUT,
419 .flags = { .pipe_bof = 1, .force_short_xfer = 1 },
421 .callback = &uhso_bs_write_callback
424 [UHSO_BULK_ENDPT_INTR] = {
425 .type = UE_INTERRUPT,
426 .endpoint = UE_ADDR_ANY,
427 .direction = UE_DIR_IN,
428 .flags = { .short_xfer_ok = 1 },
430 .callback = &uhso_bs_intr_callback,
434 static int uhso_probe_iface(struct uhso_softc *, int,
435 int (*probe)(struct uhso_softc *, int));
436 static int uhso_probe_iface_auto(struct uhso_softc *, int);
437 static int uhso_probe_iface_static(struct uhso_softc *, int);
438 static int uhso_attach_muxserial(struct uhso_softc *, struct usb_interface *,
440 static int uhso_attach_bulkserial(struct uhso_softc *, struct usb_interface *,
442 static int uhso_attach_ifnet(struct uhso_softc *, struct usb_interface *,
444 static void uhso_test_autoinst(void *, struct usb_device *,
445 struct usb_attach_arg *);
446 static int uhso_driver_loaded(struct module *, int, void *);
448 static void uhso_ucom_start_read(struct ucom_softc *);
449 static void uhso_ucom_stop_read(struct ucom_softc *);
450 static void uhso_ucom_start_write(struct ucom_softc *);
451 static void uhso_ucom_stop_write(struct ucom_softc *);
452 static void uhso_ucom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
453 static void uhso_ucom_cfg_set_dtr(struct ucom_softc *, uint8_t);
454 static void uhso_ucom_cfg_set_rts(struct ucom_softc *, uint8_t);
455 static void uhso_if_init(void *);
456 static void uhso_if_start(struct ifnet *);
457 static void uhso_if_stop(struct uhso_softc *);
458 static int uhso_if_ioctl(struct ifnet *, u_long, caddr_t);
459 static int uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *,
461 static void uhso_if_rxflush(void *);
463 static device_probe_t uhso_probe;
464 static device_attach_t uhso_attach;
465 static device_detach_t uhso_detach;
467 static device_method_t uhso_methods[] = {
468 DEVMETHOD(device_probe, uhso_probe),
469 DEVMETHOD(device_attach, uhso_attach),
470 DEVMETHOD(device_detach, uhso_detach),
474 static driver_t uhso_driver = {
477 sizeof(struct uhso_softc)
480 static devclass_t uhso_devclass;
481 DRIVER_MODULE(uhso, uhub, uhso_driver, uhso_devclass, uhso_driver_loaded, 0);
482 MODULE_DEPEND(uhso, ucom, 1, 1, 1);
483 MODULE_DEPEND(uhso, usb, 1, 1, 1);
484 MODULE_VERSION(uhso, 1);
486 static struct ucom_callback uhso_ucom_callback = {
487 .ucom_cfg_get_status = &uhso_ucom_cfg_get_status,
488 .ucom_cfg_set_dtr = &uhso_ucom_cfg_set_dtr,
489 .ucom_cfg_set_rts = &uhso_ucom_cfg_set_rts,
490 .ucom_start_read = uhso_ucom_start_read,
491 .ucom_stop_read = uhso_ucom_stop_read,
492 .ucom_start_write = uhso_ucom_start_write,
493 .ucom_stop_write = uhso_ucom_stop_write
497 uhso_probe(device_t self)
499 struct usb_attach_arg *uaa = device_get_ivars(self);
501 if (uaa->usb_mode != USB_MODE_HOST)
503 if (uaa->info.bConfigIndex != 0)
505 if (uaa->device->ddesc.bDeviceClass != 0xff)
508 return (usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa));
512 uhso_attach(device_t self)
514 struct uhso_softc *sc = device_get_softc(self);
515 struct usb_attach_arg *uaa = device_get_ivars(self);
516 struct usb_config_descriptor *cd;
517 struct usb_interface_descriptor *id;
518 struct sysctl_ctx_list *sctx;
519 struct sysctl_oid *soid;
520 struct sysctl_oid *tree, *tty_node;
521 struct ucom_softc *ucom;
529 sc->sc_udev = uaa->device;
530 mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
535 cd = usbd_get_config_descriptor(uaa->device);
536 id = usbd_get_interface_descriptor(uaa->iface);
537 sc->sc_ctrl_iface_no = id->bInterfaceNumber;
539 sc->sc_iface_no = uaa->info.bIfaceNum;
540 sc->sc_iface_index = uaa->info.bIfaceIndex;
542 /* Setup control pipe */
543 uerr = usbd_transfer_setup(uaa->device,
544 &sc->sc_iface_index, sc->sc_ctrl_xfer,
545 uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx);
547 device_printf(self, "Failed to setup control pipe: %s\n",
552 if (USB_GET_DRIVER_INFO(uaa) == UHSO_STATIC_IFACE)
553 probe_f = uhso_probe_iface_static;
554 else if (USB_GET_DRIVER_INFO(uaa) == UHSO_AUTO_IFACE)
555 probe_f = uhso_probe_iface_auto;
559 error = uhso_probe_iface(sc, uaa->info.bIfaceNum, probe_f);
563 sctx = device_get_sysctl_ctx(sc->sc_dev);
564 soid = device_get_sysctl_tree(sc->sc_dev);
566 SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "type",
567 CTLFLAG_RD, uhso_port[UHSO_IFACE_PORT(sc->sc_type)], 0,
568 "Port available at this interface");
571 * The default interface description on most Option devices isn't
572 * very helpful. So we skip device_set_usb_desc and set the
573 * device description manually.
575 device_set_desc_copy(self, uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)]);
576 /* Announce device */
577 device_printf(self, "<%s port> at <%s %s> on %s\n",
578 uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)],
579 uaa->device->manufacturer, uaa->device->product,
580 device_get_nameunit(uaa->device->bus->bdev));
582 if (sc->sc_ttys > 0) {
583 SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "ports",
584 CTLFLAG_RD, &sc->sc_ttys, 0, "Number of attached serial ports");
586 tree = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(soid), OID_AUTO,
587 "port", CTLFLAG_RD, NULL, "Serial ports");
591 * Loop through the number of found TTYs and create sysctl
594 for (i = 0; i < sc->sc_ttys; i++) {
596 ucom = &sc->sc_ucom[i];
598 if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX)
599 port = uhso_mux_port_map[ht->ht_muxport];
601 port = UHSO_IFACE_PORT_TYPE(sc->sc_type);
603 desc = uhso_port_type_sysctl[port];
605 tty_node = SYSCTL_ADD_NODE(sctx, SYSCTL_CHILDREN(tree), OID_AUTO,
606 desc, CTLFLAG_RD, NULL, "");
609 if (sc->sc_ttys == 1)
610 snprintf(ht->ht_name, 32, "cuaU%d", ucom->sc_unit);
612 snprintf(ht->ht_name, 32, "cuaU%d.%d",
613 ucom->sc_unit - ucom->sc_local_unit,
614 ucom->sc_local_unit);
617 desc = uhso_port_type[port];
618 SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO,
619 "tty", CTLFLAG_RD, ht->ht_name, 0, "");
620 SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(tty_node), OID_AUTO,
621 "desc", CTLFLAG_RD, desc, 0, "");
624 device_printf(sc->sc_dev,
625 "\"%s\" port at %s\n", desc, ht->ht_name);
630 uhso_detach(sc->sc_dev);
635 uhso_detach(device_t self)
637 struct uhso_softc *sc = device_get_softc(self);
640 usbd_transfer_unsetup(sc->sc_xfer, 3);
641 usbd_transfer_unsetup(sc->sc_ctrl_xfer, UHSO_CTRL_MAX);
642 if (sc->sc_ttys > 0) {
643 ucom_detach(&sc->sc_super_ucom, sc->sc_ucom, sc->sc_ttys);
645 for (i = 0; i < sc->sc_ttys; i++) {
646 if (sc->sc_tty[i].ht_muxport != -1) {
647 usbd_transfer_unsetup(sc->sc_tty[i].ht_xfer,
652 free(sc->sc_tty, M_USBDEV);
653 free(sc->sc_ucom, M_USBDEV);
656 if (sc->sc_ifp != NULL) {
657 callout_drain(&sc->sc_c);
658 mtx_lock(&sc->sc_mtx);
660 bpfdetach(sc->sc_ifp);
661 if_detach(sc->sc_ifp);
663 mtx_unlock(&sc->sc_mtx);
664 usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
667 mtx_destroy(&sc->sc_mtx);
672 uhso_test_autoinst(void *arg, struct usb_device *udev,
673 struct usb_attach_arg *uaa)
675 struct usb_interface *iface;
676 struct usb_interface_descriptor *id;
678 if (uaa->dev_state != UAA_DEV_READY || !uhso_autoswitch)
681 iface = usbd_get_iface(udev, 0);
685 if (id == NULL || id->bInterfaceClass != UICLASS_MASS)
687 if (usbd_lookup_id_by_uaa(uhso_devs, sizeof(uhso_devs), uaa))
688 return; /* no device match */
690 if (usb_msc_eject(udev, 0, MSC_EJECT_REZERO) == 0) {
691 /* success, mark the udev as disappearing */
692 uaa->dev_state = UAA_DEV_EJECTING;
697 uhso_driver_loaded(struct module *mod, int what, void *arg)
701 /* register our autoinstall handler */
702 uhso_etag = EVENTHANDLER_REGISTER(usb_dev_configured,
703 uhso_test_autoinst, NULL, EVENTHANDLER_PRI_ANY);
706 EVENTHANDLER_DEREGISTER(usb_dev_configured, uhso_etag);
715 * Probe the interface type by querying the device. The elements
716 * of an array indicates the capabilities of a particular interface.
717 * Returns a bit mask with the interface capabilities.
720 uhso_probe_iface_auto(struct uhso_softc *sc, int index)
722 struct usb_device_request req;
728 req.bmRequestType = UT_READ_VENDOR_DEVICE;
730 USETW(req.wValue, 0);
731 USETW(req.wIndex, 0);
732 USETW(req.wLength, 17);
734 uerr = usbd_do_request_flags(sc->sc_udev, NULL, &req, buf,
735 0, &actlen, USB_MS_HZ);
737 device_printf(sc->sc_dev, "usbd_do_request_flags failed: %s\n",
742 UHSO_DPRINTF(1, "actlen=%d\n", actlen);
743 UHSO_HEXDUMP(buf, 17);
745 if (index < 0 || index > 16) {
746 UHSO_DPRINTF(0, "Index %d out of range\n", index);
750 UHSO_DPRINTF(1, "index=%d, type=%x[%s]\n", index, buf[index],
751 uhso_port_type[(int)uhso_port_map[(int)buf[index]]]);
753 if (buf[index] >= uhso_port_map_max)
756 port = uhso_port_map[(int)buf[index]];
759 case UHSO_PORT_TYPE_NETWORK:
760 return (UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
761 UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port));
762 case UHSO_PORT_TYPE_VOICE:
763 /* Don't claim 'voice' ports */
766 return (UHSO_IFACE_SPEC(UHSO_IF_BULK,
767 UHSO_PORT_SERIAL, port));
774 uhso_probe_iface_static(struct uhso_softc *sc, int index)
776 struct usb_config_descriptor *cd;
778 cd = usbd_get_config_descriptor(sc->sc_udev);
779 if (cd->bNumInterface <= 3) {
780 /* Cards with 3 or less interfaces */
783 return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
784 UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
785 UHSO_PORT_TYPE_NETWORK);
787 return UHSO_IFACE_SPEC(UHSO_IF_BULK,
788 UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG);
790 return UHSO_IFACE_SPEC(UHSO_IF_BULK,
791 UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM);
794 /* Cards with 4 interfaces */
797 return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
798 UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
799 UHSO_PORT_TYPE_NETWORK);
801 return UHSO_IFACE_SPEC(UHSO_IF_BULK,
802 UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG2);
804 return UHSO_IFACE_SPEC(UHSO_IF_BULK,
805 UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM);
807 return UHSO_IFACE_SPEC(UHSO_IF_BULK,
808 UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG);
815 * Probes an interface for its particular capabilities and attaches if
816 * it's a supported interface.
819 uhso_probe_iface(struct uhso_softc *sc, int index,
820 int (*probe)(struct uhso_softc *, int))
822 struct usb_interface *iface;
825 UHSO_DPRINTF(1, "Probing for interface %d, probe_func=%p\n", index, probe);
827 type = probe(sc, index);
828 UHSO_DPRINTF(1, "Probe result %x\n", type);
833 iface = usbd_get_iface(sc->sc_udev, index);
835 if (UHSO_IFACE_PORT_TYPE(type) == UHSO_PORT_TYPE_NETWORK) {
836 error = uhso_attach_ifnet(sc, iface, type);
838 UHSO_DPRINTF(1, "uhso_attach_ifnet failed");
843 * If there is an additional interrupt endpoint on this
844 * interface then we most likely have a multiplexed serial port
847 if (iface->idesc->bNumEndpoints < 3) {
848 sc->sc_type = UHSO_IFACE_SPEC(
849 UHSO_IFACE_USB_TYPE(type) & ~UHSO_IF_MUX,
850 UHSO_IFACE_PORT(type) & ~UHSO_PORT_SERIAL,
851 UHSO_IFACE_PORT_TYPE(type));
855 UHSO_DPRINTF(1, "Trying to attach mux. serial\n");
856 error = uhso_attach_muxserial(sc, iface, type);
857 if (error == 0 && sc->sc_ttys > 0) {
858 error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
859 sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
861 device_printf(sc->sc_dev, "ucom_attach failed\n");
865 mtx_lock(&sc->sc_mtx);
866 usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
867 mtx_unlock(&sc->sc_mtx);
869 } else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) &&
870 UHSO_IFACE_PORT(type) & UHSO_PORT_SERIAL) {
872 error = uhso_attach_bulkserial(sc, iface, type);
876 error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
877 sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
879 device_printf(sc->sc_dev, "ucom_attach failed\n");
884 UHSO_DPRINTF(0, "Unknown type %x\n", type);
892 * Expands allocated memory to fit an additional TTY.
893 * Two arrays are kept with matching indexes, one for ucom and one
894 * for our private data.
897 uhso_alloc_tty(struct uhso_softc *sc)
901 sc->sc_tty = reallocf(sc->sc_tty, sizeof(struct uhso_tty) * sc->sc_ttys,
902 M_USBDEV, M_WAITOK | M_ZERO);
903 if (sc->sc_tty == NULL)
906 sc->sc_ucom = reallocf(sc->sc_ucom,
907 sizeof(struct ucom_softc) * sc->sc_ttys, M_USBDEV, M_WAITOK | M_ZERO);
908 if (sc->sc_ucom == NULL)
911 sc->sc_tty[sc->sc_ttys - 1].ht_sc = sc;
913 UHSO_DPRINTF(1, "Allocated TTY %d\n", sc->sc_ttys - 1);
914 return (sc->sc_ttys - 1);
918 * Attach a multiplexed serial port
919 * Data is read/written with requests on the default control pipe. An interrupt
920 * endpoint returns when there is new data to be read.
923 uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
926 struct usb_descriptor *desc;
931 * The class specific interface (type 0x24) descriptor subtype field
932 * contains a bitmask that specifies which (and how many) ports that
933 * are available through this multiplexed serial port.
935 desc = usbd_find_descriptor(sc->sc_udev, NULL,
936 iface->idesc->bInterfaceNumber, UDESC_CS_INTERFACE, 0xff, 0, 0);
938 UHSO_DPRINTF(0, "Failed to find UDESC_CS_INTERFACE\n");
942 UHSO_DPRINTF(1, "Mux port mask %x\n", desc->bDescriptorSubtype);
943 if (desc->bDescriptorSubtype == 0)
947 * The bitmask is one octet, loop through the number of
948 * bits that are set and create a TTY for each.
950 for (i = 0; i < 8; i++) {
952 if ((port & desc->bDescriptorSubtype) == port) {
953 UHSO_DPRINTF(2, "Found mux port %x (%d)\n", port, i);
954 tty = uhso_alloc_tty(sc);
957 sc->sc_tty[tty].ht_muxport = i;
958 uerr = usbd_transfer_setup(sc->sc_udev,
959 &sc->sc_iface_index, sc->sc_tty[tty].ht_xfer,
960 uhso_ctrl_config, UHSO_CTRL_MAX, sc, &sc->sc_mtx);
962 device_printf(sc->sc_dev,
963 "Failed to setup control pipe: %s\n",
970 /* Setup the intr. endpoint */
971 uerr = usbd_transfer_setup(sc->sc_udev,
972 &iface->idesc->bInterfaceNumber, sc->sc_xfer,
973 uhso_mux_config, 1, sc, &sc->sc_mtx);
981 * Interrupt callback for the multiplexed serial port. Indicates
982 * which serial port has data waiting.
985 uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error)
987 struct usb_page_cache *pc;
988 struct usb_page_search res;
989 struct uhso_softc *sc = usbd_xfer_softc(xfer);
992 UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));
994 switch (USB_GET_STATE(xfer)) {
995 case USB_ST_TRANSFERRED:
997 * The multiplexed port number can be found at the first byte.
998 * It contains a bit mask, we transform this in to an integer.
1000 pc = usbd_xfer_get_frame(xfer, 0);
1001 usbd_get_page(pc, 0, &res);
1003 i = *((unsigned char *)res.buffer);
1009 UHSO_DPRINTF(3, "mux port %d (%d)\n", mux, i);
1010 if (mux > UHSO_MPORT_TYPE_NOMAX)
1013 /* Issue a read for this serial port */
1015 sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ],
1017 usbd_transfer_start(sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ]);
1022 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1023 usbd_transfer_submit(xfer);
1026 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1027 if (error == USB_ERR_CANCELLED)
1030 usbd_xfer_set_stall(xfer);
1036 uhso_mux_read_callback(struct usb_xfer *xfer, usb_error_t error)
1038 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1039 struct usb_page_cache *pc;
1040 struct usb_device_request req;
1041 struct uhso_tty *ht;
1044 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1046 UHSO_DPRINTF(3, "status %d\n", USB_GET_STATE(xfer));
1048 ht = usbd_xfer_get_priv(xfer);
1049 UHSO_DPRINTF(3, "ht=%p open=%d\n", ht, ht->ht_open);
1051 switch (USB_GET_STATE(xfer)) {
1052 case USB_ST_TRANSFERRED:
1053 /* Got data, send to ucom */
1054 pc = usbd_xfer_get_frame(xfer, 1);
1055 len = usbd_xfer_frame_len(xfer, 1);
1057 UHSO_DPRINTF(3, "got %d bytes on mux port %d\n", len,
1060 usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1064 /* Deliver data if the TTY is open, discard otherwise */
1066 ucom_put_data(&sc->sc_ucom[ht->ht_muxport], pc, 0, len);
1070 bzero(&req, sizeof(struct usb_device_request));
1071 req.bmRequestType = UT_READ_CLASS_INTERFACE;
1072 req.bRequest = UCDC_GET_ENCAPSULATED_RESPONSE;
1073 USETW(req.wValue, 0);
1074 USETW(req.wIndex, ht->ht_muxport);
1075 USETW(req.wLength, 1024);
1077 pc = usbd_xfer_get_frame(xfer, 0);
1078 usbd_copy_in(pc, 0, &req, sizeof(req));
1080 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1081 usbd_xfer_set_frame_len(xfer, 1, 1024);
1082 usbd_xfer_set_frames(xfer, 2);
1083 usbd_transfer_submit(xfer);
1086 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1087 if (error == USB_ERR_CANCELLED)
1089 usbd_xfer_set_stall(xfer);
1095 uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error)
1097 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1098 struct uhso_tty *ht;
1099 struct usb_page_cache *pc;
1100 struct usb_device_request req;
1102 struct usb_page_search res;
1104 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1106 ht = usbd_xfer_get_priv(xfer);
1107 UHSO_DPRINTF(3, "status=%d, using mux port %d\n",
1108 USB_GET_STATE(xfer), ht->ht_muxport);
1110 switch (USB_GET_STATE(xfer)) {
1111 case USB_ST_TRANSFERRED:
1112 UHSO_DPRINTF(3, "wrote %zd data bytes to muxport %d\n",
1113 actlen - sizeof(struct usb_device_request) ,
1117 pc = usbd_xfer_get_frame(xfer, 1);
1118 if (ucom_get_data(&sc->sc_ucom[ht->ht_muxport], pc,
1121 usbd_get_page(pc, 0, &res);
1123 bzero(&req, sizeof(struct usb_device_request));
1124 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1125 req.bRequest = UCDC_SEND_ENCAPSULATED_COMMAND;
1126 USETW(req.wValue, 0);
1127 USETW(req.wIndex, ht->ht_muxport);
1128 USETW(req.wLength, actlen);
1130 pc = usbd_xfer_get_frame(xfer, 0);
1131 usbd_copy_in(pc, 0, &req, sizeof(req));
1133 usbd_xfer_set_frame_len(xfer, 0, sizeof(req));
1134 usbd_xfer_set_frame_len(xfer, 1, actlen);
1135 usbd_xfer_set_frames(xfer, 2);
1137 UHSO_DPRINTF(3, "Prepared %d bytes for transmit "
1138 "on muxport %d\n", actlen, ht->ht_muxport);
1140 usbd_transfer_submit(xfer);
1144 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1145 if (error == USB_ERR_CANCELLED)
1152 uhso_attach_bulkserial(struct uhso_softc *sc, struct usb_interface *iface,
1158 /* Try attaching RD/WR/INTR first */
1159 uerr = usbd_transfer_setup(sc->sc_udev,
1160 &iface->idesc->bInterfaceNumber, sc->sc_xfer,
1161 uhso_bs_config, UHSO_BULK_ENDPT_MAX, sc, &sc->sc_mtx);
1163 /* Try only RD/WR */
1164 uerr = usbd_transfer_setup(sc->sc_udev,
1165 &iface->idesc->bInterfaceNumber, sc->sc_xfer,
1166 uhso_bs_config, UHSO_BULK_ENDPT_MAX - 1, sc, &sc->sc_mtx);
1169 UHSO_DPRINTF(0, "usbd_transfer_setup failed");
1173 tty = uhso_alloc_tty(sc);
1175 usbd_transfer_unsetup(sc->sc_xfer, UHSO_BULK_ENDPT_MAX);
1179 sc->sc_tty[tty].ht_muxport = -1;
1184 uhso_bs_read_callback(struct usb_xfer *xfer, usb_error_t error)
1186 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1187 struct usb_page_cache *pc;
1190 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1192 UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1194 switch (USB_GET_STATE(xfer)) {
1195 case USB_ST_TRANSFERRED:
1196 pc = usbd_xfer_get_frame(xfer, 0);
1197 ucom_put_data(&sc->sc_ucom[0], pc, 0, actlen);
1201 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1202 usbd_transfer_submit(xfer);
1205 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1206 if (error == USB_ERR_CANCELLED)
1208 usbd_xfer_set_stall(xfer);
1214 uhso_bs_write_callback(struct usb_xfer *xfer, usb_error_t error)
1216 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1217 struct usb_page_cache *pc;
1220 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1222 UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1224 switch (USB_GET_STATE(xfer)) {
1225 case USB_ST_TRANSFERRED:
1228 pc = usbd_xfer_get_frame(xfer, 0);
1229 if (ucom_get_data(&sc->sc_ucom[0], pc, 0, 8192, &actlen)) {
1230 usbd_xfer_set_frame_len(xfer, 0, actlen);
1231 usbd_transfer_submit(xfer);
1236 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1237 if (error == USB_ERR_CANCELLED)
1239 usbd_xfer_set_stall(xfer);
1245 uhso_bs_cfg(struct uhso_softc *sc)
1247 struct usb_device_request req;
1250 if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1253 req.bmRequestType = UT_WRITE_CLASS_INTERFACE;
1254 req.bRequest = UCDC_SET_CONTROL_LINE_STATE;
1255 USETW(req.wValue, sc->sc_line);
1256 USETW(req.wIndex, sc->sc_iface_no);
1257 USETW(req.wLength, 0);
1259 uerr = ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom[0], &req, NULL, 0, 1000);
1261 device_printf(sc->sc_dev, "failed to set ctrl line state to "
1262 "0x%02x: %s\n", sc->sc_line, usbd_errstr(uerr));
1267 uhso_bs_intr_callback(struct usb_xfer *xfer, usb_error_t error)
1269 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1270 struct usb_page_cache *pc;
1272 struct usb_cdc_notification cdc;
1274 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1275 UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1277 switch (USB_GET_STATE(xfer)) {
1278 case USB_ST_TRANSFERRED:
1279 if (actlen < UCDC_NOTIFICATION_LENGTH) {
1280 UHSO_DPRINTF(0, "UCDC notification too short: %d\n", actlen);
1283 else if (actlen > sizeof(struct usb_cdc_notification)) {
1284 UHSO_DPRINTF(0, "UCDC notification too large: %d\n", actlen);
1285 actlen = sizeof(struct usb_cdc_notification);
1288 pc = usbd_xfer_get_frame(xfer, 0);
1289 usbd_copy_out(pc, 0, &cdc, actlen);
1291 if (UGETW(cdc.wIndex) != sc->sc_iface_no) {
1292 UHSO_DPRINTF(0, "Interface mismatch, got %d expected %d\n",
1293 UGETW(cdc.wIndex), sc->sc_iface_no);
1297 if (cdc.bmRequestType == UCDC_NOTIFICATION &&
1298 cdc.bNotification == UCDC_N_SERIAL_STATE) {
1299 UHSO_DPRINTF(2, "notify = 0x%02x\n", cdc.data[0]);
1303 if (cdc.data[0] & UCDC_N_SERIAL_RI)
1304 sc->sc_msr |= SER_RI;
1305 if (cdc.data[0] & UCDC_N_SERIAL_DSR)
1306 sc->sc_msr |= SER_DSR;
1307 if (cdc.data[0] & UCDC_N_SERIAL_DCD)
1308 sc->sc_msr |= SER_DCD;
1310 ucom_status_change(&sc->sc_ucom[0]);
1315 if (error == USB_ERR_CANCELLED)
1317 usbd_xfer_set_stall(xfer);
1323 uhso_ucom_cfg_get_status(struct ucom_softc *ucom, uint8_t *lsr, uint8_t *msr)
1325 struct uhso_softc *sc = ucom->sc_parent;
1332 uhso_ucom_cfg_set_dtr(struct ucom_softc *ucom, uint8_t onoff)
1334 struct uhso_softc *sc = ucom->sc_parent;
1336 if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1340 sc->sc_line |= UCDC_LINE_DTR;
1342 sc->sc_line &= ~UCDC_LINE_DTR;
1348 uhso_ucom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
1350 struct uhso_softc *sc = ucom->sc_parent;
1352 if (!(UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK))
1356 sc->sc_line |= UCDC_LINE_RTS;
1358 sc->sc_line &= ~UCDC_LINE_RTS;
1364 uhso_ucom_start_read(struct ucom_softc *ucom)
1366 struct uhso_softc *sc = ucom->sc_parent;
1368 UHSO_DPRINTF(3, "unit=%d, local_unit=%d\n",
1369 ucom->sc_unit, ucom->sc_local_unit);
1371 if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1372 sc->sc_tty[ucom->sc_local_unit].ht_open = 1;
1373 usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1375 else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1376 sc->sc_tty[0].ht_open = 1;
1377 usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
1378 if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
1379 usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
1384 uhso_ucom_stop_read(struct ucom_softc *ucom)
1387 struct uhso_softc *sc = ucom->sc_parent;
1389 if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1390 sc->sc_tty[ucom->sc_local_unit].ht_open = 0;
1392 sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_READ]);
1394 else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1395 sc->sc_tty[0].ht_open = 0;
1396 usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_READ]);
1397 if (sc->sc_xfer[UHSO_BULK_ENDPT_INTR] != NULL)
1398 usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_INTR]);
1403 uhso_ucom_start_write(struct ucom_softc *ucom)
1405 struct uhso_softc *sc = ucom->sc_parent;
1407 if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1408 UHSO_DPRINTF(3, "local unit %d\n", ucom->sc_local_unit);
1410 usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
1413 sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE],
1414 &sc->sc_tty[ucom->sc_local_unit]);
1415 usbd_transfer_start(
1416 sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
1419 else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1420 usbd_transfer_start(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
1425 uhso_ucom_stop_write(struct ucom_softc *ucom)
1427 struct uhso_softc *sc = ucom->sc_parent;
1429 if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX) {
1431 sc->sc_tty[ucom->sc_local_unit].ht_xfer[UHSO_CTRL_WRITE]);
1433 else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
1434 usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
1438 static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface,
1443 struct sysctl_ctx_list *sctx;
1444 struct sysctl_oid *soid;
1446 uerr = usbd_transfer_setup(sc->sc_udev,
1447 &iface->idesc->bInterfaceNumber, sc->sc_if_xfer,
1448 uhso_ifnet_config, UHSO_IFNET_MAX, sc, &sc->sc_mtx);
1450 UHSO_DPRINTF(0, "usbd_transfer_setup failed: %s\n",
1455 sc->sc_ifp = ifp = if_alloc(IFT_OTHER);
1456 if (sc->sc_ifp == NULL) {
1457 device_printf(sc->sc_dev, "if_alloc() failed\n");
1461 callout_init_mtx(&sc->sc_c, &sc->sc_mtx, 0);
1462 mtx_lock(&sc->sc_mtx);
1463 callout_reset(&sc->sc_c, 1, uhso_if_rxflush, sc);
1464 mtx_unlock(&sc->sc_mtx);
1466 if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
1467 ifp->if_mtu = UHSO_MAX_MTU;
1468 ifp->if_ioctl = uhso_if_ioctl;
1469 ifp->if_init = uhso_if_init;
1470 ifp->if_start = uhso_if_start;
1471 ifp->if_output = uhso_if_output;
1474 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1475 ifp->if_snd.ifq_drv_maxlen = IFQ_MAXLEN;
1476 IFQ_SET_READY(&ifp->if_snd);
1479 bpfattach(ifp, DLT_RAW, 0);
1481 sctx = device_get_sysctl_ctx(sc->sc_dev);
1482 soid = device_get_sysctl_tree(sc->sc_dev);
1483 /* Unlocked read... */
1484 SYSCTL_ADD_STRING(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "netif",
1485 CTLFLAG_RD, ifp->if_xname, 0, "Attached network interface");
1491 uhso_ifnet_read_callback(struct usb_xfer *xfer, usb_error_t error)
1493 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1495 struct usb_page_cache *pc;
1498 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1500 UHSO_DPRINTF(3, "status=%d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1502 switch (USB_GET_STATE(xfer)) {
1503 case USB_ST_TRANSFERRED:
1504 if (actlen > 0 && (sc->sc_ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1505 pc = usbd_xfer_get_frame(xfer, 0);
1506 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1507 usbd_copy_out(pc, 0, mtod(m, uint8_t *), actlen);
1508 m->m_pkthdr.len = m->m_len = actlen;
1509 /* Enqueue frame for further processing */
1510 _IF_ENQUEUE(&sc->sc_rxq, m);
1511 if (!callout_pending(&sc->sc_c) ||
1512 !callout_active(&sc->sc_c)) {
1513 callout_schedule(&sc->sc_c, 1);
1519 usbd_xfer_set_frame_len(xfer, 0, usbd_xfer_max_len(xfer));
1520 usbd_transfer_submit(xfer);
1523 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1524 if (error == USB_ERR_CANCELLED)
1526 usbd_xfer_set_stall(xfer);
1532 * Deferred RX processing, called with mutex locked.
1534 * Each frame we receive might contain several small ip-packets as well
1535 * as partial ip-packets. We need to separate/assemble them into individual
1536 * packets before sending them to the ip-layer.
1539 uhso_if_rxflush(void *arg)
1541 struct uhso_softc *sc = arg;
1542 struct ifnet *ifp = sc->sc_ifp;
1544 struct mbuf *m, *m0, *mwait;
1547 struct ip6_hdr *ip6;
1553 mwait = sc->sc_mwait;
1556 _IF_DEQUEUE(&sc->sc_rxq, m);
1559 UHSO_DPRINTF(3, "dequeue m=%p, len=%d\n", m, m->m_len);
1561 mtx_unlock(&sc->sc_mtx);
1563 /* Do we have a partial packet waiting? */
1564 if (mwait != NULL) {
1568 UHSO_DPRINTF(3, "partial m0=%p(%d), concat w/ m=%p(%d)\n",
1569 m0, m0->m_len, m, m->m_len);
1570 len = m->m_len + m0->m_len;
1572 /* Concat mbufs and fix headers */
1574 m0->m_pkthdr.len = len;
1575 m->m_flags &= ~M_PKTHDR;
1577 m = m_pullup(m0, sizeof(struct ip));
1580 UHSO_DPRINTF(0, "m_pullup failed\n");
1581 mtx_lock(&sc->sc_mtx);
1584 UHSO_DPRINTF(3, "Constructed mbuf=%p, len=%d\n",
1585 m, m->m_pkthdr.len);
1588 cp = mtod(m, uint8_t *);
1589 ip = (struct ip *)cp;
1591 ip6 = (struct ip6_hdr *)cp;
1594 /* Check for IPv4 */
1595 if (ip->ip_v == IPVERSION) {
1596 iplen = htons(ip->ip_len);
1600 /* Check for IPv6 */
1601 else if ((ip6->ip6_vfc & IPV6_VERSION_MASK) == IPV6_VERSION) {
1602 iplen = htons(ip6->ip6_plen);
1607 UHSO_DPRINTF(0, "got unexpected ip version %d, "
1608 "m=%p, len=%d\n", (*cp & 0xf0) >> 4, m, m->m_len);
1610 UHSO_HEXDUMP(cp, 4);
1613 mtx_lock(&sc->sc_mtx);
1618 UHSO_DPRINTF(0, "Zero IP length\n");
1622 mtx_lock(&sc->sc_mtx);
1626 UHSO_DPRINTF(3, "m=%p, len=%d, cp=%p, iplen=%d\n",
1627 m, m->m_pkthdr.len, cp, iplen);
1631 /* More IP packets in this mbuf */
1632 if (iplen < m->m_pkthdr.len) {
1636 * Allocate a new mbuf for this IP packet and
1637 * copy the IP-packet into it.
1639 m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
1640 bcopy(mtod(m0, uint8_t *), mtod(m, uint8_t *), iplen);
1641 m->m_pkthdr.len = m->m_len = iplen;
1643 /* Adjust the size of the original mbuf */
1645 m0 = m_defrag(m0, M_WAIT);
1647 UHSO_DPRINTF(3, "New mbuf=%p, len=%d/%d, m0=%p, "
1648 "m0_len=%d/%d\n", m, m->m_pkthdr.len, m->m_len,
1649 m0, m0->m_pkthdr.len, m0->m_len);
1651 else if (iplen > m->m_pkthdr.len) {
1652 UHSO_DPRINTF(3, "Deferred mbuf=%p, len=%d\n",
1653 m, m->m_pkthdr.len);
1656 mtx_lock(&sc->sc_mtx);
1661 m->m_pkthdr.rcvif = ifp;
1663 /* Dispatch to IP layer */
1664 BPF_MTAP(sc->sc_ifp, m);
1665 netisr_dispatch(isr, m);
1666 m = m0 != NULL ? m0 : NULL;
1667 mtx_lock(&sc->sc_mtx);
1669 sc->sc_mwait = mwait;
1673 uhso_ifnet_write_callback(struct usb_xfer *xfer, usb_error_t error)
1675 struct uhso_softc *sc = usbd_xfer_softc(xfer);
1676 struct ifnet *ifp = sc->sc_ifp;
1677 struct usb_page_cache *pc;
1681 usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
1683 UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
1685 switch (USB_GET_STATE(xfer)) {
1686 case USB_ST_TRANSFERRED:
1688 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
1691 IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
1695 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
1697 if (m->m_pkthdr.len > MCLBYTES)
1698 m->m_pkthdr.len = MCLBYTES;
1700 usbd_xfer_set_frame_len(xfer, 0, m->m_pkthdr.len);
1701 pc = usbd_xfer_get_frame(xfer, 0);
1702 usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len);
1703 usbd_transfer_submit(xfer);
1709 UHSO_DPRINTF(0, "error: %s\n", usbd_errstr(error));
1710 if (error == USB_ERR_CANCELLED)
1712 usbd_xfer_set_stall(xfer);
1718 uhso_if_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
1720 struct uhso_softc *sc;
1726 if (ifp->if_flags & IFF_UP) {
1727 if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
1732 if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
1733 mtx_lock(&sc->sc_mtx);
1735 mtx_unlock(&sc->sc_mtx);
1740 case SIOCSIFDSTADDR:
1751 uhso_if_init(void *priv)
1753 struct uhso_softc *sc = priv;
1754 struct ifnet *ifp = sc->sc_ifp;
1756 mtx_lock(&sc->sc_mtx);
1759 ifp->if_flags |= IFF_UP;
1760 ifp->if_drv_flags |= IFF_DRV_RUNNING;
1761 mtx_unlock(&sc->sc_mtx);
1763 UHSO_DPRINTF(2, "ifnet initialized\n");
1767 uhso_if_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
1772 /* Only IPv4/6 support */
1773 if (dst->sa_family != AF_INET
1775 && dst->sa_family != AF_INET6
1778 return (EAFNOSUPPORT);
1781 error = (ifp->if_transmit)(ifp, m0);
1791 uhso_if_start(struct ifnet *ifp)
1793 struct uhso_softc *sc = ifp->if_softc;
1795 if ((ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) {
1796 UHSO_DPRINTF(1, "Not running\n");
1800 mtx_lock(&sc->sc_mtx);
1801 usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_READ]);
1802 usbd_transfer_start(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
1803 mtx_unlock(&sc->sc_mtx);
1804 UHSO_DPRINTF(3, "interface started\n");
1808 uhso_if_stop(struct uhso_softc *sc)
1811 usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_READ]);
1812 usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
1813 sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);