stop-overpopulation.org - Life could be so good if there'd be fewer of us ...
metabunk.org - Remove the bunk from scary claims
This site is powered by green energy; for details see the provider's page
USB_ModeSwitch - Handling Mode-Switching USB Devices on Linux
- Introduction
- Download
- How to install
- How to use
- Known working hardware
- Troubleshooting
- Contribute
- Whodunit
- History
Introduction
USB_ModeSwitch is (surprise!) a mode switching tool for controlling 'multi-mode' USB devices.
Many USB devices (primarily high-speed WAN modems) have their M$ Windoze
drivers onboard; when plugged in for the first time they act like a flash storage and start
installing the driver from there.
After installation (and on every consecutive plugging) the driver switches the
mode internally, the storage device vanishes (in most cases), and a new device
(like an USB modem) shows up. Modem maker "Option" called that feature "ZeroCD
(TM)" since it eliminates the need for shipping a separate driver carrier.
In the beginning, nothing of this was documented in any form and there was
hardly any Linux support available.
On the good side, most of the known devices do work well in both modes with the available
Linux drivers like "usb-storage" or "option" (an optimized serial driver,
the Linux
standard for 3G modems). Newer devices (4G) often appear as ethernet ports which
decreases overhead. They use drivers like "cdc_ether", "cdc_ncm" or
"cdc_mbim".
All that leaves only the problem of the mode-switching, from storage to modem (or whatever
the thing is supposed to do).
Fortunately, tools like human reason, USB sniffing programs and "libusb" are at hand. It is possible to 'eavesdrop' the communication of the Windoze driver, to isolate the command or action that triggers the mode switching, and finally to 'replay' the same sequence under the rule of Linux or the BSD variants.
USB_ModeSwitch makes the process of the last step easy to handle by taking the important
parameters from a configuration file and doing all the initialization and communication
stuff, with considerable help from "libusb".
It is mainly used automatically - via udev events and rules - to do the switch
without any user interaction, but it can also be run as a command line tool,
usually when trying to make unknown devices work.
Nowadays, this tool is part of most major distributions; you should not be having to install
from the source packages here unless you run into problems and need the very latest version.
Please read the information on this page carefully before you go around posting questions! If you encounter a new device, it really helps to understand the principle of what is happening, which in turn makes it easier to find out about the switching command and to add a new config entry.
For hints about doing your own sniffing see paragraph Contribute below.
Download
Important: For a working installation you need both program and data package !
Changes and updates to the configuration data may happen more often than new program releases; most of the knowledge about devices is contained in these files. That's why it is provided separately.
- Download usb-modeswitch-2.6.0.tar.bz2 (md5: be73dcc84025794081a1d4d4e5a75e4c), the source code release dated from 2019-11-28; a Debian package should be available soon at the Debian Repository.
- Download the usb-modeswitch-data package (2019-11-28, md5: e8fce7eb949cbe16c61fb71bade4cc17). It contains the device database and the rules file, including full paths. You need program releases from 2.4.0 upward because of updated parameters/functions.
- To compile the program, install libusb-1.x (formerly on
libusb.org) if it's not on your system yet.
In most distributions there is most likely a package named "libusb1-dev" or
"libusb1-devel" (or similar).
Older versions were based on libusb-0.1.12 but since version 2.0.0 only libusb1.x is supported.
As a small complication, there was a compatible fork of libusb1 called "libusbx" around for a while (read more).
For later Android versions from version 4 upward, use "PPP Widget 3" which does not need kernel modem drivers anymore and supports other protocols besides PPP (QMI, ECM, NCM).
If you are a system integrator (package maintainer) you can use this XML file to check for new
releases:
usb-modeswitch-versions.xml.
The maintainer of the USB_ModeSwitch Debian package has set up a PPA providing the most recent release; see his posting in the forum for the link.
How to install
Unpack the source file of the program (who might have thought!). In the newly created directory run as root or superuser:
# make installThis installs a small shell script for udev, the larger wrapper script, a config file, the man page and the freshly compiled binary.
Important: if you install this way, you will need the "tcl" package for the large dispatcher script. There are more ways to install which do not depend on that package. Refer to the included README for further install options !
Now do the same procedure for the data package. It will install the config files in
"/usr/share/usb_modeswitch" and the udev rule file in "/lib/udev/rules.d". The
folder "/etc/usb_modeswitch.d" is reserved for custom config files (new or changed).
You are now set already; if your device is known, you should be able to just plug it and use it.
If it doesn't work right away we can find out why.
For manual use - when testing and analyzing - you just need to install the binary program. Work with the command line interface or use a custom config file with the -c parameter. See also the next paragraph, How to use.
How to use
In most cases, you will be able to use your device without any interaction except plugging it in.
If you think your device is supported, but things are not working out as they should, turn on logging first as described in Troubleshooting.
For testing, debugging and taming new devices from the wild, you can use the binary
part of USB_ModeSwitch in manual mode.
There are two ways for that: using a config file or using the command line.
Run "usb-modeswitch -h" to list the command line parameters. If any of them except -W, -D, -I and -q are used, a config file given with -c is ignored and all mandatory parameters have to be provided on the command line. See also the included man page.
To work directly with a specific configuration, use one of the little files in
"/usr/share/usb_modeswitch" or create one yourself. Then give the path and file
name to usb_modeswitch with the -c option.
For a complete reference have a look into the
parameter_reference.txt. Together with the existing config files you should
be able to get a good overview about the handling of a device.
Important: USB_ModeSwitch - like all programs using libusb - has to be run as root (or with "sudo") when calling it manually. Otherwise strange error messages turn up and things won't work. When trying out switching commands and strategies, it's probably easier to work at a root shell for a while ("sudo bash" or "su -").
The automatic approach consists of several components working together, listed in the logical order of usage:
- /lib/udev/rules.d/40-usb_modeswitch.rules - the udev rules starting the wrapper
if a known device ID (vendor/product) is recognized.
To add a trigger for a new modem for which you have a working config file, append a line with its USB ID as seen in the existing entries.
If the switched device provides standard serial ports, a second rule calls the wrapper again and adds a symbolic link to the correct connection port (see below) - /lib/udev/usb_modeswitch - a shell script forking to the real wrapper script. Since version 1.1.6 the script is fully compatible with the "dash" shell used in Ubuntu as well as with older "bash" variants. Recent versions make use of upstart or systemd features in order to detach the usb_modeswitch run from the udev process
- /usr/sbin/usb_modeswitch_dispatcher - this is doing additional device checking and then using the binary to switch with the selected device config file.
- /etc/usb_modeswitch.conf - a global config file to enable extensive logging when troubleshooting, or to disable switching alltogether (mostly to access the install part of devices). Some other global switches are explained by comments in the file itself.
- /usr/share/usb_modeswitch - a folder containing the individual setup information files per device, named according to the IDs and possibly further identity tokens (to resolve known ambiguities). If your device ID shows up in one of the file names, chances are your device is supported even if the model or brand name does not match.
- /etc/usb_modeswitch.d - a folder for customized config files. You can put new or modified config files here; they will take precedence over the collection of configurations in /usr/share/usb_modeswitch.
- /usr/sbin/usb_modeswitch - the binary program effectively doing the switch. This is designed to be independent from kernel or system specifics, and should be portable to non-Linux platforms, wherever libusb is available.
Current releases of NetworkManager (or its ModemManager component) are usually quite
good at making use of wireless modems. Even newer models that don't use PPP interfaces anymore are
recognized and integrated seamlessly.
There may be issues with older versions of these programs which may run into touble when trying
to auto-detect USB modems and how to use them.
If you are stuck with an older system, try disabling NM and MM. Good results were reported by
working with wvdial, UMTSmon and several tools providing a user interface to PPP
like kppp; some of these programs may require a bit of basic knowledge though.
Starting from version 1.1.2, usb_modeswitch will add a symbolic link to the correct port with
interrupt transfer if the device provides standard serial ports. The link will have the name
/dev/gsmmodem, with a number appended if more than one device is attached.
You can use this name with connection helpers like wvdial. Note that in many cases you
may have to edit the configuration file manually.
Obviously, this feature becomes obsolete with more recent, non-serial modems.
If you managed to get a new or badly supported device to switch correctly in manual mode, you can add a udev rule and a config file yourself. But please report it back to share it !!
See Contribute.
Known working hardware
Personally, I could not test the vast majority of supported devices; the list here - as well as the necessary data - relies on reports from third parties (people, that is). So it may happen that you hit sudden obstacles even with your device listed here.
That said, the user base of this little tool has grown considerably, so that any data related problems are generally surfacing quite soon.
There are hitherto three known methods for initiating the switching process:
- sending a rarely used or seemingly misplaced storage command (equivalent to those of SCSI) to the storage device - "eject" for example which is designed for CD drives
- sending one or more vendor-specific control messages to the device
- actively removing (detaching) the storage driver from the device (only some early devices)
Again, if you don't find the name of your device in the list, it may still be supported.
The important thing is that you find your device's USB ID in the config file folder. If the vendor ID
matches but not the product ID, chances are that the method used for other models from the vendor will
work for your's too. Have a look into the latest data package (See Download).
Here is an earlier list of devices (not updated anymore), together with the respective contributors:
device_reference.txt.
Troubleshooting
E-mail may be used for device/config contributions only - no support questions!
Known issues:
- There is a problematic handling of devices with ID 19d2:2000 in kernels 2.6.26 to 2.6.28. This affects mostly ZTE devices and makes the "usb-storage" driver ignore the ID. In turn this will prevent proper initialization and may cause switching to fail. There is no other way around this than compiling your own kernel with some tiny edits. See Kernel related issues below for details.
For debugging of the automated system integration, edit (as root or su) /etc/usb_modeswitch.conf in a text editor and change the line
EnableLogging=0to
EnableLogging=1This gives you a verbose output of the hotplug activity to /var/log/usb_modeswitch_<device>.
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.
The first suspects are existing system rules for modems which handle things not
quite correctly.
If you own a device with the unswitched ID of 05c6:1000, it may get a wrong switching
command in older systems. There are four different types of switching devices,
all with that same ID; in the big distributions they were all treated alike as a
model from "Option" (the manufacturer) which is wrong in four out of five cases.
There are even cell phones with that ID which wrongly get the same treatment when connected
to an USB port.
To fix problems like that you can try to remove rules files from "/lib/udev/rules.d"
which contain calls to "modem-modeswitch".
USB_ModeSwitch will do additional checks beside the USB ID and treat all known
ambiguous devices in the right way. For example, it will leave unknown devices with
the 05c6:1000 ID alone.
Kernel related issues
In some newer kernels, certain devices (some Option, some Huawei, some ZTE as mentioned above) get a special treatment in the usb-storage code to enable switching right away. You would not need USB_ModeSwitch anymore for these specific devices; on the other hand you have no choice of accessing the "CD-ROM" part of your device. Plus, there were cases when the special treatment brought no results and furthermore prevented USB_ModeSwitch to work properly afterwards (happened with ZTE devices, error "-2").
In case of trouble, look into "unusual_devs.h" in the "drivers/usb/storage" folder of
your kernel source. If your default ID (vendor and product ID of the storage part) can be found there and
you get errors when running USB_ModeSwitch, try first to blacklist "usb-storage".
If that helps, you should consider rebuilding your kernel with the entry in "unusual_devs.h" deactivated.
The only thing that will happen is that usb-storage works in the default way afterwards.
I found a tip in the Russian Gentoo wiki to
do exactly what I just suggested for the ZTE MF626.
By the way, at one point there was an agreement among USB developers to keep all future mode switching code
out of the kernel drivers if the neccessary steps can be taken in "user space".
Annother way of influencing the kernel behaviour is the parameter "delay_use" of
"usb-storage" which sets the time in seconds after plugging when the storage device will
actually be used (and probably automounted). The default value is 5; this might affect
the switching result under certain conditions.
To change the default add in /etc/modprobe.conf:
options usb-storage delay_use=1 (or 10, or other)
Old systems (e.g. CentOS 5 or Xandros 6)
If you are running a not-quite-fresh system (with a kernel below 2.6.27), you may run into incompatibilities between versions of "udev", the device manager. If you get no indication of the usb_modeswitch components doing anything at all (no log files), follow these steps:- Check if there are other files alongside "40-usb_modeswitch.rules" in the folder
"/lib/udev/rules.d".
If this is not the case, move the file to the folder "/etc/udev/rules.d". - If there is still no action, see if other files in "/etc/udev/rules.d" contain the
string "ATTRS".
If this is not the case, edit the file "40-usb_modeswitch.rules" and replace all occurences of "ATTR" and "ATTRS" with "SYSFS". Save the changes and see if something happens when you plug in again. - In particularly tough cases of "non-action", it might be necessary to analyze udev's actions; this is done by editing "/etc/udev/udev.conf" and change the logging level to "debug".
Contribute
For Huawei devices (vendor ID 0x12d1), use "HuaweiNewMode" or "HuaweiAlt Mode". For non-Huawei devices, the first step should be to try the "StandardEject" method used by the majority of modems.
See the REFERENCE file coming with the data package to get an idea.
Don't worry, it's almost impossible to break anything by experimenting with possibly wrong sequences. Just make sure you re-plug your device after each attempt!
If none of the existing methods has any effect, you can 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 spy out the USB communication to the device with the same ID inside M$ Windoze, with the on-board
driver installed. The device has to be mode-switched there too, and you want to log that moment.
Since "SniffUSB" seems not to be available anymore, I know of only one free and serious tool to monitor USB traffic: Wireshark.
That said, there is a ton of knowledge about this available, and it may be fun to learn new things. The entry point for that adventure would be here
Please post any improvements, new device information and/or bug reports to the ModeSwitchForum !
If you don't need support you can also send me an old-fashioned - and at your demand
confidential - e-mail (see below).
Whodunit
- Josua Dietze (usb_admin at this domain)
Other contributors
Command line parsing, decent usage/config output and handling, bugfixes added by:- Joakim Wennergren
- Paul Hardwick (http://www.pharscape.org)
- "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl)
- Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
- Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
- Lars Melin, DD-WRT maintainer,
Code, ideas and other input from:
- Aki Makkonen
- Denis Sutter
- Lucas Benedičič
- Roman Laube
- Luigi Iotti
- Vincent Teoh
- Tommy Cheng
- Daniel Cooper
- Andrew Bird
- Yaroslav Levandovskiy
- Sakis Dimopoulos
- Steven Fernandez
- Christophe Fergeau
- Nils Radtke
- Andrei Nazarenko
- Filip Aben
- Amit Mendapara
- Roman S. Samarev
- Chi-Hang Long
- Andrey Tikhomirov
- Nicholas Carrier
- Adam Goode
- Daniel Mende
- Leonid Lisovskiy
- Vladislav Grishenko
- Lubomir Rintel
History
Legal
This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details:
http://www.gnu.org/licenses/gpl.txt