Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 17 Jan 2010 18:22:42 +0000 (UTC)
From:      Andrew Thompson <thompsa@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org
Subject:   svn commit: r202503 - in stable/8: share/man/man4 sys/conf sys/dev/usb sys/dev/usb/net sys/modules/usb/uhso usr.sbin usr.sbin/uhsoctl
Message-ID:  <201001171822.o0HIMgRl007217@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: thompsa
Date: Sun Jan 17 18:22:42 2010
New Revision: 202503
URL: http://svn.freebsd.org/changeset/base/202503

Log:
  MFC r202181,202243,202270
  
   Add a driver by Fredrik Lindberg for Option HSDPA USB devices. These differ
   from standard 3G wireless units by supplying a raw IP/IPv6 endpoint rather than
   using PPP over serial. uhsoctl(1) is used to initiate and close the WAN
   connection.
  
  Obtained from:	Fredrik Lindberg <fli@shapeshifter.se>

Added:
  stable/8/share/man/man4/uhso.4
     - copied, changed from r202181, head/share/man/man4/uhso.4
  stable/8/sys/dev/usb/net/uhso.c
     - copied, changed from r202181, head/sys/dev/usb/net/uhso.c
  stable/8/sys/modules/usb/uhso/
     - copied from r202181, head/sys/modules/usb/uhso/
  stable/8/usr.sbin/uhsoctl/
  stable/8/usr.sbin/uhsoctl/Makefile   (contents, props changed)
  stable/8/usr.sbin/uhsoctl/uhsoctl.1   (contents, props changed)
  stable/8/usr.sbin/uhsoctl/uhsoctl.c   (contents, props changed)
Modified:
  stable/8/share/man/man4/Makefile
  stable/8/sys/conf/NOTES
  stable/8/sys/conf/files
  stable/8/sys/dev/usb/usbdevs
  stable/8/usr.sbin/Makefile
Directory Properties:
  stable/8/share/man/man4/   (props changed)
  stable/8/share/man/man4/de.4   (props changed)
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/share/man/man4/Makefile
==============================================================================
--- stable/8/share/man/man4/Makefile	Sun Jan 17 18:18:01 2010	(r202502)
+++ stable/8/share/man/man4/Makefile	Sun Jan 17 18:22:42 2010	(r202503)
@@ -421,6 +421,7 @@ MAN=	aac.4 \
 	ugen.4 \
 	uhci.4 \
 	uhid.4 \
+	uhso.4 \
 	uipaq.4 \
 	ukbd.4 \
 	ulpt.4 \

Copied and modified: stable/8/share/man/man4/uhso.4 (from r202181, head/share/man/man4/uhso.4)
==============================================================================
--- head/share/man/man4/uhso.4	Wed Jan 13 03:16:31 2010	(r202181, copy source)
+++ stable/8/share/man/man4/uhso.4	Sun Jan 17 18:22:42 2010	(r202503)
@@ -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
-AT commands
+Establishing a connection on 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 c
 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

Modified: stable/8/sys/conf/NOTES
==============================================================================
--- stable/8/sys/conf/NOTES	Sun Jan 17 18:18:01 2010	(r202502)
+++ stable/8/sys/conf/NOTES	Sun Jan 17 18:22:42 2010	(r202503)
@@ -2589,6 +2589,9 @@ device		rue
 #
 # Davicom DM9601E USB to fast ethernet. Supports the Corega FEther USB-TXC.
 device		udav
+#
+# HSxPA devices from Option N.V
+device		uhso
 
 #
 # Ralink Technology RT2501USB/RT2601USB wireless driver

Modified: stable/8/sys/conf/files
==============================================================================
--- stable/8/sys/conf/files	Sun Jan 17 18:18:01 2010	(r202502)
+++ stable/8/sys/conf/files	Sun Jan 17 18:22:42 2010	(r202503)
@@ -1615,7 +1615,7 @@ dev/usb/usb_request.c		optional usb
 dev/usb/usb_transfer.c		optional usb
 dev/usb/usb_util.c		optional usb
 #
-# USB ethernet drivers
+# USB network drivers
 #
 dev/usb/net/if_aue.c		optional aue
 dev/usb/net/if_axe.c		optional axe
@@ -1626,6 +1626,7 @@ dev/usb/net/if_rue.c		optional rue
 dev/usb/net/if_udav.c		optional udav
 dev/usb/net/usb_ethernet.c	optional aue | axe | cdce | cue | kue | rue | \
 					 udav
+dev/usb/net/uhso.c		optional uhso
 #
 # USB WLAN drivers
 #

Copied and modified: stable/8/sys/dev/usb/net/uhso.c (from r202181, head/sys/dev/usb/net/uhso.c)
==============================================================================
--- head/sys/dev/usb/net/uhso.c	Wed Jan 13 03:16:31 2010	(r202181, copy source)
+++ stable/8/sys/dev/usb/net/uhso.c	Sun Jan 17 18:22:42 2010	(r202503)
@@ -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 arbitrary and do not match the 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_d
 	/* 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_callb
 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 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 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_ifne
 	}
 };
 
+/* 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_c
 	}
 };
 
-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 
 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 isn'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
 	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, i
 	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 
 		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 
 		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_soft
 
 	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_soft
 			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_soft
 	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, 
 	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 then we most likely 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, 
 		}
 	}
 	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 
 	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 
 		}
 	}
 
+	/* 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 
 	return (0);
 }
 
+/*
+ * Interrupt callback for the multiplexed serial port. Indicates
+ * which serial port 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 *
 		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 
 			break;
 		break;
 	}
-
 }
 
 static int
@@ -1089,9 +1155,7 @@ uhso_attach_bulkserial(struct uhso_softc
 	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 *x
 	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 *x
 		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 
 	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 *
 	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
 		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
 
 	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
 			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 as well
+ * 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
 		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);
 }

Modified: stable/8/sys/dev/usb/usbdevs
==============================================================================
--- stable/8/sys/dev/usb/usbdevs	Sun Jan 17 18:18:01 2010	(r202502)
+++ stable/8/sys/dev/usb/usbdevs	Sun Jan 17 18:22:42 2010	(r202503)
@@ -2095,6 +2095,18 @@ product OPTION E7041		0x7041	3G modem
 product OPTION E7061		0x7061	3G modem
 product OPTION E7100		0x7100	3G modem
 product OPTION GTM380		0x7201	3G modem
+product OPTION GSICON72		0x6911	GlobeSurfer iCON
+product OPTION GSICONHSUPA	0x7251	Globetrotter HSUPA
+product OPTION ICON401		0x7401	GlobeSurfer iCON 401
+product OPTION GTHSUPA		0x7011	Globetrotter HSUPA
+product OPTION GMT382		0x7501	Globetrotter HSUPA
+product OPTION GE40X_1		0x7301	Globetrotter HSUPA
+product OPTION GE40X_2		0x7361	Globetrotter HSUPA
+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

Modified: stable/8/usr.sbin/Makefile
==============================================================================
--- stable/8/usr.sbin/Makefile	Sun Jan 17 18:18:01 2010	(r202502)
+++ stable/8/usr.sbin/Makefile	Sun Jan 17 18:22:42 2010	(r202503)
@@ -189,6 +189,7 @@ SUBDIR=	${_ac} \
 	tzsetup \
 	${_uathload} \
 	ugidfw \
+	${_uhsoctl} \
 	${_usbdevs} \
 	${_usbconfig} \
 	${_vidcontrol} \
@@ -410,6 +411,7 @@ _crunch=	crunch
 .if ${MACHINE_ARCH} != "ia64"
 _uathload=	uathload
 .endif
+_uhsoctl=	uhsoctl
 #_usbdevs=	usbdevs
 _usbconfig=	usbconfig
 .endif

Added: stable/8/usr.sbin/uhsoctl/Makefile
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.sbin/uhsoctl/Makefile	Sun Jan 17 18:22:42 2010	(r202503)
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG=	uhsoctl
+MAN=	uhsoctl.1
+WARNS=	1
+
+DPADD=	${LIBUTIL}
+LDADD=	-lutil
+
+.include <bsd.prog.mk>

Added: stable/8/usr.sbin/uhsoctl/uhsoctl.1
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ stable/8/usr.sbin/uhsoctl/uhsoctl.1	Sun Jan 17 18:22:42 2010	(r202503)
@@ -0,0 +1,104 @@
+.\" Copyright (c) 2008-2009 Fredrik Lindberg
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\"    notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\"    notice, this list of conditions and the following disclaimer in the
+.\"    documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd Aug 12, 2009
+.Os
+.Dt UHSOCTL 1
+.Sh NAME
+.Nm uhsoctl
+.Nd connection utility for Option based devices
+.Sh SYNOPSIS
+.Nm
+.Op Fl a Ar apn
+.Op Fl c Ar cid
+.Op Fl p Ar pin
+.Op Fl u Ar username
+.Op Fl k Ar password
+.Op Fl r Ar path
+.Op Fl f Ar path
+.Op Fl b | n
+.Ar interface
+.Nm
+.Fl d
+.Ar interface
+.Nm
+.Fl h
+.Sh DESCRIPTION
+.Nm
+is a small connection utility for Option N.V. devices that are based on Options
+packet interface and uses proprietary AT_* calls to establish connections.
+The utility (tries to) configure both default route and name servers
+(/etc/resolv.conf).
+.Pp
+By default
+.Nm
+detaches from the terminal upon on a successful connection, a few command-line
+options exists that allows this behavior to be changed.
+.Pp
+.Nm
+attempts to find a usable controlling serial port based on the provided network
+interface.
+If this fails you might specify a serial port manually.
+.Sh OPTIONS
+.Bl -tag -width XXXX
+.It Fl a Ar apn
+Specify APN to connect to.
+.It Fl c Ar cid
+Specify CID (Context ID) to use, by default CID 1 is used.
+If an APN has been configured once, it's enough to specify the CID used for
+further accesses.
+.It Fl p Ar pin
+Specify SIM PIN.
+.It Fl u Ar username
+Specify username.
+.It Fl k Ar password
+Specify username.
+.It Fl r Ar path
+Path to resolv.conf, default /etc/resolv.conf.
+Use /dev/null to disable updating of name servers.
+.It Fl f Ar path
+Explicitly set the serial port to use as controlling terminal.
+Might be needed if the automatic detection fails.
+.It Fl b
+Fork into background directly, before a connection has been established.
+.It Fl n
+Never fork into background, run entirely in foreground.
+.El
+.Sh EXAMPLES
+Connect to
+.Dq Li apn.example.com
+on interface
+.Dq Li uhso0
+and use PIN
+.Dq 1234
+to enable the SIM card.
+

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201001171822.o0HIMgRl007217>