From owner-svn-src-stable-8@FreeBSD.ORG Sun Jan 17 18:22:42 2010 Return-Path: Delivered-To: svn-src-stable-8@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 8DC08106568F; Sun, 17 Jan 2010 18:22:42 +0000 (UTC) (envelope-from thompsa@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 79DC38FC12; Sun, 17 Jan 2010 18:22:42 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0HIMgqh007228; Sun, 17 Jan 2010 18:22:42 GMT (envelope-from thompsa@svn.freebsd.org) Received: (from thompsa@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0HIMgRl007217; Sun, 17 Jan 2010 18:22:42 GMT (envelope-from thompsa@svn.freebsd.org) Message-Id: <201001171822.o0HIMgRl007217@svn.freebsd.org> From: Andrew Thompson Date: Sun, 17 Jan 2010 18:22:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org X-SVN-Group: stable-8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: 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 X-BeenThere: svn-src-stable-8@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 8-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 17 Jan 2010 18:22:42 -0000 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 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 * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -63,13 +63,15 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include +#include #include #include 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 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 ***