USB_ModeSwitch – Activating Switchable USB Devices on Linux

Version française içi – merci au Bullteam


USB_ModeSwitch is (surprise!) a mode switching tool for controlling “flip flop” (multiple device) USB gear.
Several new USB devices (especially high-speed wireless WAN stuff, they’re expensive anyway) have their MS Windows drivers onboard; when plugged in for the first time they act like a flash storage and start installing the driver from there. After that (and on every consecutive plugging) this driver switches the mode internally, the storage device vanishes (in most cases), and a new device (like an USB modem) shows up. The WWAN gear maker Option calls that feature “ZeroCD (TM)”.
As you may have guessed, nothing of this is documented in any form and so far there are no official Linux drivers available. On the good side, most of the known devices work out of the box with the available Linux drivers like “usb-storage” or “usbserial”. That leaves the problem of the mode switching from storage to whatever the thing is supposed to do.
Fortunately there are things like human reason, USB sniffing programs and “libusb”. It is possible to eavesdrop the communication of the MS Windows driver, to isolate the command or action that does the switching, and to reproduce the same thing with Linux.
USB_ModeSwitch makes the last step considerably easier by taking the important parameters from a configuration file and doing all the initialization and communication stuff.
It does NOT check for success afterwards as of now. The right approach would be to consult /proc/bus/usb/devices (or the output of “lsusb”) before and after execution to note any changes.
For hints about doing your own sniffing see paragraph Contribute below
Breaking News: just found this humble tool in the source code of the fine Dovado UMR router, which they publish in compliance with the GPL. So if you want the power of your Wireless Broadband across your local network, but without the “fun” of setting up your own Linux router (which I did), consider investing in such a machine.


The latest release version is 0.9.5. The archive contains the source and a 686 binary (32 bit, VIA C7, GCC 4.2.2). I used libusb-0.1.12.
There are changes and updates to the config file more often than new releases; most of the valuable knowledge about devices is contained in this file. So you better use the latest version linked here.
With countless machine and distribution variants around, x86 compatibility is sometimes just not there. If you experience “floating point errors” or the like and are not able to recompile yourself, try one of the following drop-in replacements for the binary (all are 32 bit). And – thanks to Tobias Stoeber – we have a Debian package (for Xandros, Etch and others); I have to admit that I never warmed to those packaging details …

How to install

If you want to compile it for yourself, just run “” or type on the shell:
$ gcc -l usb -o usb_modeswitch usb_modeswitch.c
That’s as easy as it gets. And it should be as portable as libusb itself (some limitations on FreeBSD based systems are known).Take the fresh executable “usb_modeswitch” (or the one provided with the archive) and put it into your path (preferably “/sbin” or “/usr/sbin”).
Put “usb_modeswitch.conf” into “/etc” and edit it according to your hardware. It’s heavily commented and should tell you what to do.
Alternatively you can use the command line interface to tell USB_ModeSwitch the things it needs to know; try “usb_modeswitch -h” to list the parameters. This way you can handle multiple configurations. If any command line parameters except -W and -q are used, the default config file is NOT read.
Important: USB_ModeSwitch – like all programs with libusb routines – has to be run as root. Otherwise strange error messages come up …


If you’re next to certain that you have the right values for your device, followed all the hints (see Known working hardware), and USB_ModeSwitch seems to do something run after run but to no effect, there are most likely system issues involved. Almost all distributions today are using “udev” as a device and hotplug manager, and in some cases this daemon is not able to “release” the established connection of a switched device and to see it as a freshly plugged one (after all, this is something outside the USB specs).There are several ways to analyse and tackle these problems:
  • To see what udev is doing, run udevmonitor in one console and watch what happens if you plug the device and run USB_ModeSwitch. “lsusb” and “dmesg” can give additional information
  • If you suspect timing issues, try to run USB_ModeSwitch with a defined delay after plugging
  • Find the device’s sysfs access. It’s in the file system under /sys/bus/usb/devices. “dmesg” tells you what bus address it got after plugging; should look like “1-2″ or “2-4″ or similar. Then – after doing the switch – set it’s power level to suspend mode. For example like this:
    $ echo suspend > /sys/bus/usb/devices/1-2/power/level
    Mind that the USB powersaving option must have been configured in your kernel. Thanks to mixmaxtw for this neat trick; I’ll look into adding this as a built-in option
  • Try the ResetUSB option with your device. This is somewhat brutal and may also reset an internally switched device back to storage mode
  • Sometimes it is recommended to use the latest firmware available as there have been issues in the past with at least one device (Icon 7.2, resolved now). In other cases devices have stopped working with the usb-serial driver after a firmware update. So the advice is simple: update if not working, otherwise leave alone

Known working hardware

Very important note:
Personally, I could only test my Option Icon; the list here – as well as all the necessary data – relies on reports from third parties (people, that is). So don’t be surprised if you hit sudden obstacles even with your device listed here. You have been warned.There are hitherto three known methods for initiating the switching process:
1. sending a rarely or never used standard storage command (equivalent to those of SCSI) to the storage device
2. actively removing (rather detaching) the storage driver from the device
3. sending a special control message to the device
  • Option GlobeSurfer Icon (aka “Vodafone EasyBox“)
    The thing that started it all, because I wanted it to work on my Linux router.
    All known Option devices use the USB storage command REZERO UNIT for switching.
  • Option GlobeSurfer Icon 7.2
    If you get hardware lockups of this thing when plugging in (flashing LEDs), update the firmware.
  • Option GlobeSurfer Icon 7.2 with HSO driver interface
    A next generation firmware with vendor/device ID unchanging. Your “7.2 ready” device might change its behaviour after re-flashing with this firmware; newer Option devices most likely come loaded with it. Use the new “TargetClass” parameter to recognize already switched devices.
    If you have a newer Option device not listed here there is a good chance to get it working by using this entry and just adapting your vendor/product ID. Note: for HSO driver questions and howtos turn to the fine Pharscape site!
  • Option Icon 225 HSDPA (aka “T-Mobile web’n'walk Stick“)
    New Firmware, HSO interface
  • Option GlobeTrotter HSUPA Modem (aka “T-Mobile wnw Card Compact III“)
    New Firmware, HSO interface
  • Option GlobeTrotter GT MAX 3.6 (aka “T-Mobile wnw Card Compact II“)
  • Option GlobeTrotter EXPRESS 7.2 (aka “T-Mobile wnw Card Express II“)
  • Option GlobeTrotter GT MAX “7.2 Ready”
  • Huawei E220 (aka “Vodafone EasyBox II“, aka “T-Mobile wnw Box Micro“)
    We have two options (no pun intended!) for Huawei devices: 1. detaching of “usb-storage” 2. the special control message found by Miroslav Bobovsky. The latter is independent of “usb-storage” and even leaves the storage portion of the device functional. Both methods leave other USB storage devices alone (compared to removing the storage module completely, which works as well)
  • Huawei E160, Huawei E160G, Huawei E169, Huawei E270, Huawei E280
    Similar setup as the E220.
  • Huawei E630
    There are reportedly modem-only variants around (without the storage part); for these no switching is required.
  • Novatel Wireless Ovation MC950D HSUPA, Ovation 930D and Merlin XU950D
    They use the USB storage command START/STOP (Eject) for switching.
  • Novatel Wireless U727 USB modem
    Similar setup as the MC950D, different product ID
  • Novatel MC990D
    Uses new features of 0.9.5
  • ZTE MF620 (aka “Onda MH600HS“)
    Uses the USB storage command TEST UNIT READY for switching.
  • ZTE MF622 (aka “Onda MDC502HS“)
    Detachment of storage driver
  • ZTE MF628, ZTE MF628+
  • ZTE MF638 (aka “Onda MDC525UP“)
  • ONDA MT503HS (most likely a ZTE model)
  • ONDA MT505UP (most likely a ZTE model)
  • Alcatel OT-X020 (aka “MBD-100HU“, aka “Nuton 3.5G“, works with “Emobile D11LC“)
  • AnyDATA ADU-500A, AnyDATA ADU-510A, AnyDATA ADU-520A
  • BandLuxe C120
    Special treatment reportedly necessary. See Forum Entry
  • Solomon S3Gm-660
    Same notes apply as with the BandLuxe C120 above
  • C-Motech D-50 (aka “CDU-680“)
    Important notes at this Forum Entry
  • Toshiba G450
  • UTStarcom UM175 (distributor “Alltel”)
  • Hummer DTM5731
  • A-Link 3GU
  • Quanta MU-Q101, also referred to as “Quanta (NU) MU-Q101
    You probably need to do the “power suspend” trick (see Troubleshooting) to make it usable

How to automate

Mind that you have to run USB_ModeSwitch every time you plug your device or cold boot with it. If you have “udev” in your distribution it’s really not hard to automate this and just forget about it.
Note however that timing might be an issue with some of the more recent setups. If your automatic switching is unreliable the delayed execution of USB_ModeSwitch might help (see the special script below).
That said, since version 0.9.4 there are very few reports of timing issues.You should have a folder named “/etc/udev” or similar. Somewhere in there (I have a folder “rules.d”) you find some files with the extension “.rules”. Create a new one (or edit an existing one, but by convention not the default “50-something.rules”). I chose one named “45-hotplug.rules” since hotplugging is what USB is about after all.
In the chosen/new file add the line
SUBSYSTEM=="usb", SYSFS{idProduct}=="", SYSFS{idVendor}=="", RUN+=""
That’s basically it.From here, there are two ways to continue. If your GSM device is recognized by a recent version of the “option” driver you shouldn’t have to do anything but to load the module (most certainly handled by udev automatically). Instead or if your (serial) device is not supported by that module you can always use “usbserial”, but it needs to be told the device IDs (plus a performance-related option):
SUBSYSTEM=="usb", SYSFS{idProduct}=="", SYSFS{idVendor}=="",
  RUN+="/sbin/modprobe usbserial vendor= product= maxSize=4096"
As for the difference between “usbserial” and “option”, here is a quote from option.c:
  This driver exists because the "normal" serial driver doesn't work too well
  with GSM modems. Issues:
  - data loss -- one single Receive URB is not nearly enough
  - nonstandard flow (Option devices) control
  - controlling the baud rate doesn't make sense
Following that, I’d recommend trying the “option” driver first. In recent kernels it recognizes several Option, Huawei and Novatel devices (among others) out of the box. And following kernel developers mail traffic it looks like this driver is becoming the standard for GSM devices as more models are added. In the latest kernels the module entry reads “USB driver for GSM and CDMA modems” (Device Drivers / USB support / USB Serial Converter support).Devices supported by the “option” driver that don’t change their IDs after switching might run into problems because of the driver trying to attach before the switching happened. In this case it might help to blacklist it and to load it manually via the helper script after execution of usb_modeswitch. Again, developers are working on the “option” driver to probe for the device class before binding, so this problem might be handled in kernel 2.6.24.
Anyway, if your device works O.K. with “usbserial”, and you are not afraid to edit kernel sources, why not just add the vendor and product ID (after switching of course) to the “option” driver? I just did that with my cell phone, and now the “option” module is bound to it automatically when plugging in. Look at the other devices included in “option.c” and just add your IDs the same way – that’s it. Two or three lines in most cases. Recompile, add your device to one of the udev rules (see above) and enjoy!
For plain serial devices that keep their ID after switching a script “/sbin/” can be created:
sleep   # probably not necessary, try out
/sbin/modprobe usbserial vendor= product= maxSize=4096
And then add this rule:
SUBSYSTEM=="usb", SYSFS{idProduct}=="", SYSFS{idVendor}=="", RUN+="/sbin/"
If timing is an issue with your device or setup it might help to delay the execution of USB_ModeSwitch, to allow other drivers like “usb-storage” to finish their activation. Again, use the helper script – called “/sbin/” here – and fill it like this:
sh -c "sleep 4; /usr/bin/usb_modeswitch" &
exit 0
Luigi Iotti reported problems on some systems (RHEL 5, CentOS 5) of udev always waiting for background scripts to finish. Here is his solution for a changed “/sbin/”:
# close these FDs to detach from udev
exec 1<&- 2<&- 5<&- 7<&-
sh -c "sleep 4; /usr/bin/usb_modeswitch" &
exit 0


USB_ModeSwitch comes quite handy for experimenting with your own hardware if not supported yet. You could try this approach:Note the device’s Vendor and Product ID from /proc/bus/usb/devices (or from the output of “lsusb”); the assigned driver is usually “usb-storage”. Then try spying out the USB communication to the device with the same ID inside M$ Windoze.
I recommend this tool: “SniffUSB” (
This is the extremely short version. There is a very good case example from Mark A. Ziesemer here:
Alltel UM175AL USB EVDO under Ubuntu Hardy HeronPlease post any improvements, new device information and/or bug reports to the ModeSwitchForum !
Or send me an old-fashioned e-mail (see below).


Copyright (C) 2007 Josua Dietze (usb_admin at this domain)Command line parsing, decent usage/config output and handling, bugfixes added by:

Share this

Related Posts

Next Post »