summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorthompsa <thompsa@FreeBSD.org>2010-01-13 20:54:18 +0000
committerthompsa <thompsa@FreeBSD.org>2010-01-13 20:54:18 +0000
commit6bc46506163ea6a3bcf17069c043fe68da3067bc (patch)
treee667af2c012a004ce1896625fb827523d9c75235
parentc69b7d3b1afbb78e29ff4573e7b70d09c3a046d1 (diff)
downloadFreeBSD-src-6bc46506163ea6a3bcf17069c043fe68da3067bc.zip
FreeBSD-src-6bc46506163ea6a3bcf17069c043fe68da3067bc.tar.gz
Update to Fredrik's latest uhso driver. This changes port detection, adds
comments and other code nits. Submitted by: Fredrik Lindberg <fli@shapeshifter.se>
-rw-r--r--share/man/man4/uhso.423
-rw-r--r--sys/dev/usb/net/uhso.c242
-rw-r--r--sys/dev/usb/usbdevs1
3 files changed, 169 insertions, 97 deletions
diff --git a/share/man/man4/uhso.4 b/share/man/man4/uhso.4
index 0ec602a..5d6832c 100644
--- a/share/man/man4/uhso.4
+++ b/share/man/man4/uhso.4
@@ -23,11 +23,11 @@
.\"
.\" $FreeBSD$
.\"
-.Dd Aug 12, 2009
+.Dd January 14, 2010
.Os
.Dt UHSO 4
.Sh NAME
-.Nm hso
+.Nm uhso
.Nd support for several HSxPA devices from Option N.V.
.Sh SYNOPSIS
The module can be loaded at boot time by placing the following line in
@@ -47,12 +47,12 @@ driver which makes them behave like a
.Xr tty 4 .
The packet interface is exposed as a network interface.
.Pp
-To establish a connection on the packet interface the use of the proprietary
+Connection of the packet interface is achieved by using the proprietary
AT commands
.Dq Li AT_OWANCALL
and
.Dq Li AT_OWANDATA
-are required on any of the serial ports.
+on any of the available serial ports.
.Pp
The network interface must be configured manually using the data obtain from
these calls.
@@ -70,12 +70,23 @@ driver supports at least the following cards
Option GlobeSurfer iCON 7.2 (new firmware)
.It
Option iCON 225
+.It
+Option iCON 505
.El
.Pp
The device features a mass storage device referred to as
.Dq Zero-CD
-which contains drivers for Microsoft Windows.
-The driver automatically switches the device to modem mode.
+which contains drivers for Microsoft Windows, this is the default
+mode for the device.
+The
+.Nm
+driver automatically switches the device from
+.Dq Zero-CD
+mode to modem mode.
+This behavior can be disabled by setting
+.Va hw.usb.uhso.auto_switch
+to 0 using
+.Xr sysctl 8
.Sh EXAMPLES
Establishing a packet interface connection
.Bd -literal -offset indent
diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c
index 4a3edd3..bbada71 100644
--- a/sys/dev/usb/net/uhso.c
+++ b/sys/dev/usb/net/uhso.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2009 Fredrik Lindberg
+ * Copyright (c) 2009 Fredrik Lindberg <fli@shapeshifter.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -63,13 +63,15 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_process.h>
#include <dev/usb/usb_device.h>
#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
#include <dev/usb/serial/usb_serial.h>
#include <dev/usb/usb_msctest.h>
struct uhso_tty {
struct uhso_softc *ht_sc;
struct usb_xfer *ht_xfer[3];
- int ht_muxport;
+ int ht_muxport; /* Mux. port no */
int ht_open;
char ht_name[32];
};
@@ -78,7 +80,7 @@ struct uhso_softc {
device_t sc_dev;
struct usb_device *sc_udev;
struct mtx sc_mtx;
- uint32_t sc_type;
+ uint32_t sc_type; /* Interface definition */
struct usb_xfer *sc_xfer[3];
uint8_t sc_iface_no;
@@ -91,14 +93,14 @@ struct uhso_softc {
/* Network */
struct usb_xfer *sc_if_xfer[2];
struct ifnet *sc_ifp;
- struct mbuf *sc_mwait; /* partial packet */
- size_t sc_waitlen; /* no. of outstanding bytes */
+ struct mbuf *sc_mwait; /* Partial packet */
+ size_t sc_waitlen; /* No. of outstanding bytes */
struct ifqueue sc_rxq;
struct callout sc_c;
/* TTY related structures */
struct ucom_super_softc sc_super_ucom;
- int sc_ttys;
+ int sc_ttys;
struct uhso_tty *sc_tty;
struct ucom_softc *sc_ucom;
int sc_msr;
@@ -106,7 +108,6 @@ struct uhso_softc {
int sc_line;
};
-
#define UHSO_MAX_MTU 2048
/*
@@ -135,7 +136,7 @@ struct uhso_softc {
* Port types
*/
#define UHSO_PORT_UNKNOWN 0x00
-#define UHSO_PORT_SERIAL 0x01 /* Serial port */
+#define UHSO_PORT_SERIAL 0x01 /* Serial port */
#define UHSO_PORT_NETWORK 0x02 /* Network packet interface */
/*
@@ -145,12 +146,14 @@ struct uhso_softc {
#define UHSO_MPORT_TYPE_APP 0x01 /* Application */
#define UHSO_MPORT_TYPE_PCSC 0x02
#define UHSO_MPORT_TYPE_GPS 0x03
-#define UHSO_MPORT_TYPE_APP2 0x04
+#define UHSO_MPORT_TYPE_APP2 0x04 /* Secondary application */
#define UHSO_MPORT_TYPE_MAX UHSO_MPORT_TYPE_APP2
#define UHSO_MPORT_TYPE_NOMAX 8 /* Max number of mux ports */
/*
* Port definitions
+ * Note that these definitions are arbitray and doesn't match
+ * values returned by the auto config descriptor.
*/
#define UHSO_PORT_TYPE_CTL 0x01
#define UHSO_PORT_TYPE_APP 0x02
@@ -176,8 +179,12 @@ static char *uhso_port[] = {
"Network/Serial"
};
-/* Map between interface port type read from device and description type */
-static char uhso_port_map[] = {
+/*
+ * Map between interface port type read from device and description type.
+ * The position in this array is a direct map to the auto config
+ * descriptor values.
+ */
+static unsigned char uhso_port_map[] = {
0,
UHSO_PORT_TYPE_DIAG,
UHSO_PORT_TYPE_GPS,
@@ -193,7 +200,7 @@ static char uhso_port_map[] = {
};
static char uhso_port_map_max = sizeof(uhso_port_map) / sizeof(char);
-static char uhso_mux_port_map[] = {
+static unsigned char uhso_mux_port_map[] = {
UHSO_PORT_TYPE_CTL,
UHSO_PORT_TYPE_APP,
UHSO_PORT_TYPE_PCSC,
@@ -202,7 +209,7 @@ static char uhso_mux_port_map[] = {
};
static char *uhso_port_type[] = {
- "Unknown",
+ "Unknown", /* Not a valid port */
"Control",
"Application",
"Application (Secondary)",
@@ -233,7 +240,6 @@ static char *uhso_port_type_sysctl[] = {
"voice",
};
-
#define UHSO_STATIC_IFACE 0x01
#define UHSO_AUTO_IFACE 0x02
@@ -263,11 +269,16 @@ static const struct usb_device_id uhso_devs[] = {
/* Option iCON 321 */
UHSO_DEV(OPTION, ICON321, UHSO_STATIC_IFACE),
/* Option iCON 322 */
- UHSO_DEV(OPTION, GTICON322, UHSO_STATIC_IFACE)
+ UHSO_DEV(OPTION, GTICON322, UHSO_STATIC_IFACE),
+ /* Option iCON 505 */
+ UHSO_DEV(OPTION, ICON505, UHSO_AUTO_IFACE),
#undef UHSO_DEV
};
SYSCTL_NODE(_hw_usb, OID_AUTO, uhso, CTLFLAG_RW, 0, "USB uhso");
+static int uhso_autoswitch = 1;
+SYSCTL_INT(_hw_usb_uhso, OID_AUTO, auto_switch, CTLFLAG_RW,
+ &uhso_autoswitch, 0, "Automatically switch to modem mode");
#ifdef USB_DEBUG
#ifdef UHSO_DEBUG
@@ -335,6 +346,7 @@ static usb_callback_t uhso_bs_intr_callback;
static usb_callback_t uhso_ifnet_read_callback;
static usb_callback_t uhso_ifnet_write_callback;
+/* Config used for the default control pipes */
static const struct usb_config uhso_ctrl_config[UHSO_CTRL_MAX] = {
[UHSO_CTRL_READ] = {
.type = UE_CONTROL,
@@ -356,6 +368,7 @@ static const struct usb_config uhso_ctrl_config[UHSO_CTRL_MAX] = {
}
};
+/* Config for the multiplexed serial ports */
static const struct usb_config uhso_mux_config[UHSO_MUX_ENDPT_MAX] = {
[UHSO_MUX_ENDPT_INTR] = {
.type = UE_INTERRUPT,
@@ -367,6 +380,7 @@ static const struct usb_config uhso_mux_config[UHSO_MUX_ENDPT_MAX] = {
}
};
+/* Config for the raw IP-packet interface */
static const struct usb_config uhso_ifnet_config[UHSO_IFNET_MAX] = {
[UHSO_IFNET_READ] = {
.type = UE_BULK,
@@ -387,6 +401,7 @@ static const struct usb_config uhso_ifnet_config[UHSO_IFNET_MAX] = {
}
};
+/* Config for interfaces with normal bulk serial ports */
static const struct usb_config uhso_bs_config[UHSO_BULK_ENDPT_MAX] = {
[UHSO_BULK_ENDPT_READ] = {
.type = UE_BULK,
@@ -416,20 +431,19 @@ static const struct usb_config uhso_bs_config[UHSO_BULK_ENDPT_MAX] = {
}
};
-static int uhso_probe_iface(struct uhso_softc *, int,
+static int uhso_probe_iface(struct uhso_softc *, int,
int (*probe)(struct uhso_softc *, int));
-static int uhso_probe_iface_auto(struct uhso_softc *, int);
-static int uhso_probe_iface_static(struct uhso_softc *, int);
-
-static int uhso_attach_muxserial(struct uhso_softc *, struct usb_interface *,
+static int uhso_probe_iface_auto(struct uhso_softc *, int);
+static int uhso_probe_iface_static(struct uhso_softc *, int);
+static int uhso_attach_muxserial(struct uhso_softc *, struct usb_interface *,
int type);
-static int uhso_attach_bulkserial(struct uhso_softc *, struct usb_interface *,
+static int uhso_attach_bulkserial(struct uhso_softc *, struct usb_interface *,
int type);
-static int uhso_attach_ifnet(struct uhso_softc *, struct usb_interface *,
+static int uhso_attach_ifnet(struct uhso_softc *, struct usb_interface *,
int type);
static void uhso_test_autoinst(void *, struct usb_device *,
struct usb_attach_arg *);
-static int uhso_driver_loaded(struct module *, int, void *);
+static int uhso_driver_loaded(struct module *, int, void *);
static void uhso_ucom_start_read(struct ucom_softc *);
static void uhso_ucom_stop_read(struct ucom_softc *);
@@ -438,12 +452,11 @@ static void uhso_ucom_stop_write(struct ucom_softc *);
static void uhso_ucom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
static void uhso_ucom_cfg_set_dtr(struct ucom_softc *, uint8_t);
static void uhso_ucom_cfg_set_rts(struct ucom_softc *, uint8_t);
-
static void uhso_if_init(void *);
static void uhso_if_start(struct ifnet *);
static void uhso_if_stop(struct uhso_softc *);
-static int uhso_if_ioctl(struct ifnet *, u_long, caddr_t);
-static int uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *,
+static int uhso_if_ioctl(struct ifnet *, u_long, caddr_t);
+static int uhso_if_output(struct ifnet *, struct mbuf *, struct sockaddr *,
struct route *);
static void uhso_if_rxflush(void *);
@@ -512,11 +525,6 @@ uhso_attach(device_t self)
usb_error_t uerr;
char *desc;
- device_set_usb_desc(self);
-
- UHSO_DPRINTF(0, "Device is in modem mode, devClass=%x\n",
- uaa->device->ddesc.bDeviceClass);
-
sc->sc_dev = self;
sc->sc_udev = uaa->device;
mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF);
@@ -552,7 +560,6 @@ uhso_attach(device_t self)
if (error != 0)
goto out;
-
sctx = device_get_sysctl_ctx(sc->sc_dev);
soid = device_get_sysctl_tree(sc->sc_dev);
@@ -560,6 +567,18 @@ uhso_attach(device_t self)
CTLFLAG_RD, uhso_port[UHSO_IFACE_PORT(sc->sc_type)], 0,
"Port available at this interface");
+ /*
+ * The default interface description on most Option devices aren't
+ * very helpful. So we skip device_set_usb_desc and set the
+ * device description manually.
+ */
+ device_set_desc_copy(self, uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)]);
+ /* Announce device */
+ device_printf(self, "<%s port> at <%s %s> on %s\n",
+ uhso_port_type[UHSO_IFACE_PORT_TYPE(sc->sc_type)],
+ uaa->device->manufacturer, uaa->device->product,
+ device_get_nameunit(uaa->device->bus->bdev));
+
if (sc->sc_ttys > 0) {
SYSCTL_ADD_INT(sctx, SYSCTL_CHILDREN(soid), OID_AUTO, "ports",
CTLFLAG_RD, &sc->sc_ttys, 0, "Number of attached serial ports");
@@ -568,11 +587,14 @@ uhso_attach(device_t self)
"port", CTLFLAG_RD, NULL, "Serial ports");
}
+ /*
+ * Loop through the number of found TTYs and create sysctl
+ * nodes for them.
+ */
for (i = 0; i < sc->sc_ttys; i++) {
ht = &sc->sc_tty[i];
ucom = &sc->sc_ucom[i];
-
if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_MUX)
port = uhso_mux_port_map[ht->ht_muxport];
else
@@ -607,7 +629,6 @@ uhso_attach(device_t self)
out:
uhso_detach(sc->sc_dev);
return (ENXIO);
-
}
static int
@@ -633,21 +654,17 @@ uhso_detach(device_t self)
}
if (sc->sc_ifp != NULL) {
-
callout_drain(&sc->sc_c);
-
mtx_lock(&sc->sc_mtx);
uhso_if_stop(sc);
bpfdetach(sc->sc_ifp);
if_detach(sc->sc_ifp);
if_free(sc->sc_ifp);
mtx_unlock(&sc->sc_mtx);
-
usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX);
}
mtx_destroy(&sc->sc_mtx);
-
return (0);
}
@@ -658,7 +675,7 @@ uhso_test_autoinst(void *arg, struct usb_device *udev,
struct usb_interface *iface;
struct usb_interface_descriptor *id;
- if (uaa->dev_state != UAA_DEV_READY)
+ if (uaa->dev_state != UAA_DEV_READY || !uhso_autoswitch)
return;
iface = usbd_get_iface(udev, 0);
@@ -694,7 +711,13 @@ uhso_driver_loaded(struct module *mod, int what, void *arg)
return (0);
}
-static int uhso_probe_iface_auto(struct uhso_softc *sc, int index)
+/*
+ * Probe the interface type by querying the device. The elements
+ * of an array indicates the capabilities of a particular interface.
+ * Returns a bit mask with the interface capabilities.
+ */
+static int
+uhso_probe_iface_auto(struct uhso_softc *sc, int index)
{
struct usb_device_request req;
usb_error_t uerr;
@@ -716,7 +739,7 @@ static int uhso_probe_iface_auto(struct uhso_softc *sc, int index)
return (0);
}
- UHSO_DPRINTF(3, "actlen=%d\n", actlen);
+ UHSO_DPRINTF(1, "actlen=%d\n", actlen);
UHSO_HEXDUMP(buf, 17);
if (index < 0 || index > 16) {
@@ -724,21 +747,25 @@ static int uhso_probe_iface_auto(struct uhso_softc *sc, int index)
return (0);
}
- UHSO_DPRINTF(3, "index=%d, type=%x\n", index, buf[index]);
+ UHSO_DPRINTF(1, "index=%d, type=%x[%s]\n", index, buf[index],
+ uhso_port_type[(int)uhso_port_map[(int)buf[index]]]);
if (buf[index] >= uhso_port_map_max)
port = 0;
else
port = uhso_port_map[(int)buf[index]];
- if (port == UHSO_PORT_TYPE_NETWORK)
- return (UHSO_IFACE_SPEC(UHSO_IF_BULK,
- UHSO_PORT_NETWORK, port));
- else if (port == UHSO_PORT_TYPE_VOICE)
+ switch (port) {
+ case UHSO_PORT_TYPE_NETWORK:
+ return (UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
+ UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, port));
+ case UHSO_PORT_TYPE_VOICE:
+ /* Don't claim 'voice' ports */
return (0);
- else
+ default:
return (UHSO_IFACE_SPEC(UHSO_IF_BULK,
UHSO_PORT_SERIAL, port));
+ }
return (0);
}
@@ -750,10 +777,12 @@ uhso_probe_iface_static(struct uhso_softc *sc, int index)
cd = usbd_get_config_descriptor(sc->sc_udev);
if (cd->bNumInterface <= 3) {
+ /* Cards with 3 or less interfaces */
switch (index) {
case 0:
return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
- UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, 0);
+ UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
+ UHSO_PORT_TYPE_NETWORK);
case 1:
return UHSO_IFACE_SPEC(UHSO_IF_BULK,
UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG);
@@ -761,12 +790,13 @@ uhso_probe_iface_static(struct uhso_softc *sc, int index)
return UHSO_IFACE_SPEC(UHSO_IF_BULK,
UHSO_PORT_SERIAL, UHSO_PORT_TYPE_MODEM);
}
- }
- else {
+ } else {
+ /* Cards with 4 interfaces */
switch (index) {
case 0:
return UHSO_IFACE_SPEC(UHSO_IF_NET | UHSO_IF_MUX,
- UHSO_PORT_SERIAL | UHSO_PORT_NETWORK, 0);
+ UHSO_PORT_SERIAL | UHSO_PORT_NETWORK,
+ UHSO_PORT_TYPE_NETWORK);
case 1:
return UHSO_IFACE_SPEC(UHSO_IF_BULK,
UHSO_PORT_SERIAL, UHSO_PORT_TYPE_DIAG2);
@@ -781,14 +811,18 @@ uhso_probe_iface_static(struct uhso_softc *sc, int index)
return (0);
}
+/*
+ * Probes an interface for its particular capabilities and attaches if
+ * it's a supported interface.
+ */
static int
uhso_probe_iface(struct uhso_softc *sc, int index,
int (*probe)(struct uhso_softc *, int))
{
struct usb_interface *iface;
- int type, error, error0;
+ int type, error;
- UHSO_DPRINTF(1, "Probing for interface %d, cb=%p\n", index, probe);
+ UHSO_DPRINTF(1, "Probing for interface %d, probe_func=%p\n", index, probe);
type = probe(sc, index);
UHSO_DPRINTF(1, "Probe result %x\n", type);
@@ -798,27 +832,41 @@ uhso_probe_iface(struct uhso_softc *sc, int index,
sc->sc_type = type;
iface = usbd_get_iface(sc->sc_udev, index);
- if (UHSO_IFACE_USB_TYPE(type) & (UHSO_IF_MUX | UHSO_IF_NET)) {
- error0 = uhso_attach_muxserial(sc, iface, type);
+ if (UHSO_IFACE_PORT_TYPE(type) == UHSO_PORT_TYPE_NETWORK) {
error = uhso_attach_ifnet(sc, iface, type);
-
- if (error0 && error)
+ if (error) {
+ UHSO_DPRINTF(1, "uhso_attach_ifnet failed");
return (ENXIO);
+ }
- if (sc->sc_ttys > 0) {
+ /*
+ * If there is an additional interrupt endpoint on this
+ * interface we most likley have a multiplexed serial port
+ * available.
+ */
+ if (iface->idesc->bNumEndpoints < 3) {
+ sc->sc_type = UHSO_IFACE_SPEC(
+ UHSO_IFACE_USB_TYPE(type) & ~UHSO_IF_MUX,
+ UHSO_IFACE_PORT(type) & ~UHSO_PORT_SERIAL,
+ UHSO_IFACE_PORT_TYPE(type));
+ return (0);
+ }
+
+ UHSO_DPRINTF(1, "Trying to attach mux. serial\n");
+ error = uhso_attach_muxserial(sc, iface, type);
+ if (error == 0 && sc->sc_ttys > 0) {
error = ucom_attach(&sc->sc_super_ucom, sc->sc_ucom,
sc->sc_ttys, sc, &uhso_ucom_callback, &sc->sc_mtx);
if (error) {
device_printf(sc->sc_dev, "ucom_attach failed\n");
return (ENXIO);
}
- }
- mtx_lock(&sc->sc_mtx);
- usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
- mtx_unlock(&sc->sc_mtx);
- }
- else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) &&
+ mtx_lock(&sc->sc_mtx);
+ usbd_transfer_start(sc->sc_xfer[UHSO_MUX_ENDPT_INTR]);
+ mtx_unlock(&sc->sc_mtx);
+ }
+ } else if ((UHSO_IFACE_USB_TYPE(type) & UHSO_IF_BULK) &&
UHSO_IFACE_PORT(type) & UHSO_PORT_SERIAL) {
error = uhso_attach_bulkserial(sc, iface, type);
@@ -833,12 +881,18 @@ uhso_probe_iface(struct uhso_softc *sc, int index,
}
}
else {
+ UHSO_DPRINTF(0, "Unknown type %x\n", type);
return (ENXIO);
}
return (0);
}
+/*
+ * Expands allocated memory to fit an additional TTY.
+ * Two arrays are kept with matching indexes, one for ucom and one
+ * for our private data.
+ */
static int
uhso_alloc_tty(struct uhso_softc *sc)
{
@@ -856,11 +910,15 @@ uhso_alloc_tty(struct uhso_softc *sc)
sc->sc_tty[sc->sc_ttys - 1].ht_sc = sc;
- UHSO_DPRINTF(2, "Allocated TTY %d\n", sc->sc_ttys - 1);
+ UHSO_DPRINTF(1, "Allocated TTY %d\n", sc->sc_ttys - 1);
return (sc->sc_ttys - 1);
}
-
+/*
+ * Attach a multiplexed serial port
+ * Data is read/written with requests on the default control pipe. An interrupt
+ * endpoint returns when there is new data to be read.
+ */
static int
uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
int type)
@@ -885,6 +943,10 @@ uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
if (desc->bDescriptorSubtype == 0)
return (ENXIO);
+ /*
+ * The bitmask is one octet, loop through the number of
+ * bits that are set and create a TTY for each.
+ */
for (i = 0; i < 8; i++) {
port = (1 << i);
if ((port & desc->bDescriptorSubtype) == port) {
@@ -905,6 +967,7 @@ uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
}
}
+ /* Setup the intr. endpoint */
uerr = usbd_transfer_setup(sc->sc_udev,
&iface->idesc->bInterfaceNumber, sc->sc_xfer,
uhso_mux_config, 1, sc, &sc->sc_mtx);
@@ -914,6 +977,10 @@ uhso_attach_muxserial(struct uhso_softc *sc, struct usb_interface *iface,
return (0);
}
+/*
+ * Interrupt callback for the multiplexed serial port. Indicates
+ * which serial port that has data waiting.
+ */
static void
uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error)
{
@@ -943,6 +1010,7 @@ uhso_mux_intr_callback(struct usb_xfer *xfer, usb_error_t error)
if (mux > UHSO_MPORT_TYPE_NOMAX)
break;
+ /* Issue a read for this serial port */
usbd_xfer_set_priv(
sc->sc_tty[mux].ht_xfer[UHSO_CTRL_READ],
&sc->sc_tty[mux]);
@@ -962,7 +1030,6 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
-
}
static void
@@ -1079,7 +1146,6 @@ uhso_mux_write_callback(struct usb_xfer *xfer, usb_error_t error)
break;
break;
}
-
}
static int
@@ -1089,9 +1155,7 @@ uhso_attach_bulkserial(struct uhso_softc *sc, struct usb_interface *iface,
usb_error_t uerr;
int tty;
- /*
- * Try attaching RD/WR/INTR first
- */
+ /* Try attaching RD/WR/INTR first */
uerr = usbd_transfer_setup(sc->sc_udev,
&iface->idesc->bInterfaceNumber, sc->sc_xfer,
uhso_bs_config, UHSO_BULK_ENDPT_MAX, sc, &sc->sc_mtx);
@@ -1146,7 +1210,6 @@ tr_setup:
}
}
-
static void
uhso_bs_write_callback(struct usb_xfer *xfer, usb_error_t error)
{
@@ -1208,9 +1271,7 @@ uhso_bs_intr_callback(struct usb_xfer *xfer, usb_error_t error)
int actlen;
struct usb_cdc_notification cdc;
-
usbd_xfer_status(xfer, &actlen, NULL, NULL, NULL);
-
UHSO_DPRINTF(3, "status %d, actlen=%d\n", USB_GET_STATE(xfer), actlen);
switch (USB_GET_STATE(xfer)) {
@@ -1228,14 +1289,14 @@ uhso_bs_intr_callback(struct usb_xfer *xfer, usb_error_t error)
usbd_copy_out(pc, 0, &cdc, actlen);
if (UGETW(cdc.wIndex) != sc->sc_iface_no) {
- UHSO_DPRINTF(0, "Interface missmatch, got %d expected %d\n",
+ UHSO_DPRINTF(0, "Interface mismatch, got %d expected %d\n",
UGETW(cdc.wIndex), sc->sc_iface_no);
goto tr_setup;
}
if (cdc.bmRequestType == UCDC_NOTIFICATION &&
cdc.bNotification == UCDC_N_SERIAL_STATE) {
- UHSO_DPRINTF(1, "notify = 0x%02x\n", cdc.data[0]);
+ UHSO_DPRINTF(2, "notify = 0x%02x\n", cdc.data[0]);
sc->sc_msr = 0;
sc->sc_lsr = 0;
@@ -1299,7 +1360,6 @@ uhso_ucom_cfg_set_rts(struct ucom_softc *ucom, uint8_t onoff)
uhso_bs_cfg(sc);
}
-
static void
uhso_ucom_start_read(struct ucom_softc *ucom)
{
@@ -1373,7 +1433,6 @@ uhso_ucom_stop_write(struct ucom_softc *ucom)
else if (UHSO_IFACE_USB_TYPE(sc->sc_type) & UHSO_IF_BULK) {
usbd_transfer_stop(sc->sc_xfer[UHSO_BULK_ENDPT_WRITE]);
}
-
}
static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface,
@@ -1393,7 +1452,7 @@ static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface,
return (-1);
}
- sc->sc_ifp = ifp = if_alloc(IFT_PPP);
+ sc->sc_ifp = ifp = if_alloc(IFT_OTHER);
if (sc->sc_ifp == NULL) {
device_printf(sc->sc_dev, "if_alloc() failed\n");
return (-1);
@@ -1406,7 +1465,6 @@ static int uhso_attach_ifnet(struct uhso_softc *sc, struct usb_interface *iface,
if_initname(ifp, device_get_name(sc->sc_dev), device_get_unit(sc->sc_dev));
ifp->if_mtu = UHSO_MAX_MTU;
-
ifp->if_ioctl = uhso_if_ioctl;
ifp->if_init = uhso_if_init;
ifp->if_start = uhso_if_start;
@@ -1448,6 +1506,7 @@ uhso_ifnet_read_callback(struct usb_xfer *xfer, usb_error_t error)
m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR);
usbd_copy_out(pc, 0, mtod(m, uint8_t *), actlen);
m->m_pkthdr.len = m->m_len = actlen;
+ /* Enqueue frame for further processing */
_IF_ENQUEUE(&sc->sc_rxq, m);
if (!callout_pending(&sc->sc_c) ||
!callout_active(&sc->sc_c)) {
@@ -1470,7 +1529,11 @@ tr_setup:
}
/*
- * Defered RX processing, called with mutex locked.
+ * Deferred RX processing, called with mutex locked.
+ *
+ * Each frame we receive might contain several small ip-packets aswell
+ * as partial ip-packets. We need to separate/assemble them into individual
+ * packets before sending them to the ip-layer.
*/
static void
uhso_if_rxflush(void *arg)
@@ -1493,7 +1556,7 @@ uhso_if_rxflush(void *arg)
_IF_DEQUEUE(&sc->sc_rxq, m);
if (m == NULL)
break;
- UHSO_DPRINTF(2, "dequeue m=%p, len=%d\n", m, m->m_len);
+ UHSO_DPRINTF(3, "dequeue m=%p, len=%d\n", m, m->m_len);
}
mtx_unlock(&sc->sc_mtx);
@@ -1502,7 +1565,7 @@ uhso_if_rxflush(void *arg)
m0 = mwait;
mwait = NULL;
- UHSO_DPRINTF(1, "partial m0=%p(%d), concat w/ m=%p(%d)\n",
+ UHSO_DPRINTF(3, "partial m0=%p(%d), concat w/ m=%p(%d)\n",
m0, m0->m_len, m, m->m_len);
len = m->m_len + m0->m_len;
@@ -1518,7 +1581,7 @@ uhso_if_rxflush(void *arg)
mtx_lock(&sc->sc_mtx);
continue;
}
- UHSO_DPRINTF(2, "Constructed mbuf=%p, len=%d\n",
+ UHSO_DPRINTF(3, "Constructed mbuf=%p, len=%d\n",
m, m->m_pkthdr.len);
}
@@ -1560,7 +1623,7 @@ uhso_if_rxflush(void *arg)
continue;
}
- UHSO_DPRINTF(1, "m=%p, len=%d, cp=%p, iplen=%d\n",
+ UHSO_DPRINTF(3, "m=%p, len=%d, cp=%p, iplen=%d\n",
m, m->m_pkthdr.len, cp, iplen);
m0 = NULL;
@@ -1581,12 +1644,12 @@ uhso_if_rxflush(void *arg)
m_adj(m0, iplen);
m0 = m_defrag(m0, M_WAIT);
- UHSO_DPRINTF(1, "New mbuf=%p, len=%d/%d, m0=%p, "
+ UHSO_DPRINTF(3, "New mbuf=%p, len=%d/%d, m0=%p, "
"m0_len=%d/%d\n", m, m->m_pkthdr.len, m->m_len,
m0, m0->m_pkthdr.len, m0->m_len);
}
else if (iplen > m->m_pkthdr.len) {
- UHSO_DPRINTF(1, "Defered mbuf=%p, len=%d\n",
+ UHSO_DPRINTF(3, "Deferred mbuf=%p, len=%d\n",
m, m->m_pkthdr.len);
mwait = m;
m = NULL;
@@ -1649,7 +1712,6 @@ tr_setup:
usbd_xfer_set_stall(xfer);
goto tr_setup;
}
-
}
static int
@@ -1698,7 +1760,7 @@ uhso_if_init(void *priv)
ifp->if_drv_flags |= IFF_DRV_RUNNING;
mtx_unlock(&sc->sc_mtx);
- UHSO_DPRINTF(3, "ifnet initialized\n");
+ UHSO_DPRINTF(2, "ifnet initialized\n");
}
static int
@@ -1722,7 +1784,6 @@ uhso_if_output(struct ifnet *ifp, struct mbuf *m0, struct sockaddr *dst,
return (ENOBUFS);
}
ifp->if_opackets++;
-
return (0);
}
@@ -1749,6 +1810,5 @@ uhso_if_stop(struct uhso_softc *sc)
usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_READ]);
usbd_transfer_stop(sc->sc_if_xfer[UHSO_IFNET_WRITE]);
-
sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
}
diff --git a/sys/dev/usb/usbdevs b/sys/dev/usb/usbdevs
index 2037a5c..53d676d 100644
--- a/sys/dev/usb/usbdevs
+++ b/sys/dev/usb/usbdevs
@@ -2111,6 +2111,7 @@ product OPTION GE40X_3 0x7381 Globetrotter HSUPA
product OPTION ICONEDGE 0xc031 GlobeSurfer iCON EDGE
product OPTION MODHSXPA 0xd013 Globetrotter HSUPA
product OPTION ICON321 0xd031 Globetrotter HSUPA
+product OPTION ICON505 0xd055 Globetrotter iCON 505
/* OQO */
product OQO WIFI01 0x0002 model 01 WiFi interface
OpenPOWER on IntegriCloud