usb_modeswitch: updated to 2.50, and data package to 20170120 (2017-01-20)

arm-sdk7
AndreDVJ 9 years ago committed by kille72
parent 20b096082c
commit 11fdf8e8e8

@ -2,6 +2,19 @@
History of USB_ModeSwitch History of USB_ModeSwitch
========================= =========================
Version 2.5.0, 2017/01/17
ATTENTION: Parameter transmitted from udev now reduced to %k (kernel
name), however, rules file parameters can be '%b/%k' or '%k' - this
fixes issues with parameter handling by the systemd unit file;
remove endpoint reset ahead of bulk message transmission, only reset
if endpoints are actually stalled, helping with quirky device behaviour
(see www.draisberghof.de/usb_modeswitch/bb/viewtopic.php?f=2&t=2582 );
stability fix by making a buffer in the config parser static, preventing
problems seen in Fedora (thanks to Lubomir Rintel for patches and hints
regarding the three previous issues); removed premature driver unbinding
in wrapper which could disrupt certain devices already in target mode
(reported by Aleksander Morgado); improved check for determining install
mode (essential with generic config files present, e.g. 12d1:#linux)
Version 2.4.0, 2016/06/12 Version 2.4.0, 2016/06/12
ATTENTION: All ad-hoc driver binding code (using new_id driver attribute) ATTENTION: All ad-hoc driver binding code (using new_id driver attribute)
removed - was a potential source of side effects and should now be removed - was a potential source of side effects and should now be

@ -1,5 +1,5 @@
PROG = usb_modeswitch PROG = usb_modeswitch
VERS = 2.4.0 VERS = 2.5.0
CC ?= gcc CC ?= gcc
CFLAGS += -Wall CFLAGS += -Wall
LIBS = `pkg-config --libs --cflags libusb-1.0` LIBS = `pkg-config --libs --cflags libusb-1.0`

@ -50,8 +50,8 @@ In Linux and friends it is intended to work automatically - via udev events
and rules - and doing the mode switch without any user interaction. and rules - and doing the mode switch without any user interaction.
However, the core C program should be as portable als libusb itself; it does not However, the core C program should be as portable als libusb itself; it does not
rely on specific Linux features. rely on specific Linux features.
It can also be run as an interactive command line tool, particularly useful when It can also be run as an interactive command line tool, which can be useful
trying to tinker with hitherto unknown devices. when trying to tinker with hitherto unknown devices.
We have already collected a wide range of information on how to mode-switch all We have already collected a wide range of information on how to mode-switch all
sorts of devices. If you run into a new one that is unknown yet, don't despair: sorts of devices. If you run into a new one that is unknown yet, don't despair:
@ -110,8 +110,8 @@ program and a man page.
Install the data package as well and you are set. Install the data package as well and you are set.
NOTE: installing over (possibly outdated) Linux distribution packages of this NOTE: installing over (possibly outdated) distribution packages of this
program and the data collection should not be a problem. program and the data collection should generally not be a problem.
How to use How to use
@ -123,18 +123,21 @@ it doesn't work - we will find out why.
For manual use just run "usb_modeswitch" (as root). Work with the command For manual use just run "usb_modeswitch" (as root). Work with the command
line interface or with a setup file. You can use any file and give its path line interface or with a setup file. You can use any file and give its path
with the "-c" parameter. with the "-c" parameter.
The file named "device_reference.txt" that you can find on the home site of The file named "device_reference.txt" that you can find on the home site of
this package is a device and configuration reference containing most known this package is a device and configuration reference containing most known
devices; you can use it as a "database" to create your own configuration file. devices; you can use it as a "database" to create your own configuration file.
It's heavily commented and should tell you what to do. It also contains a It's heavily commented and should tell you what to do. It also contains a
thorough explanation of all the parameters. thorough explanation of all the parameters.
However, the device list in that reference file is no longer maintained.
See the data package for the USB IDs of devices known to usb_modeswitch.
Run "usb_modeswitch -h" to list the command line parameters. Run "usb_modeswitch -h" to list the command line parameters.
See also the provided man page. See also the provided man page.
Important note: Manual use is mainly intended for testing and analyzing!! Important note: Manual use is mainly intended for testing and analyzing!!
The program puts no limits on what you can send to your USB device, so I The program puts no limits on what you can send to your USB device, so I
assume it is possible to screw it up profoundly. assume it is possible to screw it up profoundly. You have been warned.
Once your new device is switching fine you can add it to the data files to Once your new device is switching fine you can add it to the data files to
make the process automatic. make the process automatic.
@ -167,6 +170,8 @@ Known working hardware, Troubleshooting
Please go to the homepage (see link at the top). Read carefully. Please go to the homepage (see link at the top). Read carefully.
For support questions use ONLY public posts in the forum. For support questions use ONLY public posts in the forum.
Again - to see the USB IDs of known devices, see the data package.
Contribute Contribute
@ -177,9 +182,8 @@ not supported yet. You could try this approach:
Note the device's vendor and product ID from /proc/bus/usb/devices (or from the 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 output of lsusb); the assigned driver is usually "usb-storage". Then try spying
on the USB communication to the device with the same ID inside MS Windoze. I on the USB communication to the device with the same ID inside MS Windoze.
recommend this tool: Nowadays the standard tool for this is Wireshark/USBPcap.
"SniffUSB" (http://benoit.papillault.free.fr/usbsnoop/index.php.en).
PLEASE post any improvements, new device information and/or bug reports to the PLEASE post any improvements, new device information and/or bug reports to the
forum (see above) or send it to the author (see below)! forum (see above) or send it to the author (see below)!
@ -188,7 +192,7 @@ forum (see above) or send it to the author (see below)!
Whodunit Whodunit
======== ========
Copyright 2007 - 2015 Josua Dietze (for non-support notifications write a personal Copyright 2007 - 2017 Josua Dietze (for non-support notifications write a personal
message through the forum to "Josh"; everything else only in a forum thread) message through the forum to "Josh"; everything else only in a forum thread)
!!! NO SUPPORT QUESTIONS VIA E-MAIL, use the forum !!! !!! NO SUPPORT QUESTIONS VIA E-MAIL, use the forum !!!
@ -239,7 +243,7 @@ Code, fixes and ideas contributed by:
Adam Goode Adam Goode
Leonid Lisovskiy Leonid Lisovskiy
Vladislav Grishenko Vladislav Grishenko
Daniel Drake Lubomir Rintel
Device information contributors are named in the "device_reference.txt" file. Device information contributors are named in the "device_reference.txt" file.
@ -268,4 +272,4 @@ Or find it as the file COPYING in this folder.
Last revised: 2016-06-12, Josua Dietze Last revised: 2017-01-16, Josua Dietze

@ -1,3 +1,12 @@
20170120:
Added devices: [03f0:032a] HP LaserJet Professional P1102w, [03f0:9d1d]
HP lt4120, [0586:2030] ZyXel WAH1004/WAH3004, [148f:2878] RaLink
MT7601U, [19d2:0033] ZTE MF636DB, [19d2:0090] ZTE MU330, [2001:00a7]
D-Link DWM-157 C1, [2001:a809] D-Link DWM-157 A1, [2001:ab00] D-Link
DWM-222, [22de:6802] WeTelecom WM-D200A
Corrected/amended configs: [1004:6190] LG AD600, [19d2:1595] ZTE MF710
(Vietnam), [22de:6803] WeTelecom WM-D300
(collected and compiled by Lars Melin)
20160803: 20160803:
Added devices: [03f0:521d] HP hs3110, [03f0:531d] HP hs3120, Added devices: [03f0:521d] HP hs3110, [03f0:531d] HP hs3120,
[03f0:541d] HP hs3114, [03f0:581d] HP hs4112, [03f0:631d] HP lt4225, [03f0:541d] HP hs3114, [03f0:581d] HP hs4112, [03f0:631d] HP lt4225,

@ -1,5 +1,5 @@
PROG = usb-modeswitch-data PROG = usb-modeswitch-data
VERS = 20160803 VERS = 20170120
RM = /bin/rm -f RM = /bin/rm -f
PREFIX = $(DESTDIR)/usr PREFIX = $(DESTDIR)/usr
ETCDIR = $(DESTDIR)/etc ETCDIR = $(DESTDIR)/etc

@ -11,7 +11,7 @@
# Default version string # Default version string
set version "20160803" set version "20170120"
# Devices excluded from Huawei catch-all rule # Devices excluded from Huawei catch-all rule
set x_huaweiList {12d1:1573 12d1:15c1} set x_huaweiList {12d1:1573 12d1:15c1}
@ -20,7 +20,7 @@ if {[lindex $argv 0] == "--set-version" && [regexp {\d\d\d\d\d\d\d\d} [lindex $a
set version [lindex $argv 1] set version [lindex $argv 1]
} }
set template {ATTR{idVendor}=="+##+", ATTR{idProduct}=="#++#", RUN+="usb_modeswitch '%b/%k'"} set template {ATTR{idVendor}=="+##+", ATTR{idProduct}=="#++#", RUN+="usb_modeswitch '/%k'"}
if {![file isdirectory usb_modeswitch.d]} { if {![file isdirectory usb_modeswitch.d]} {
puts "No \"usb_modeswitch.d\" subfolder found" puts "No \"usb_modeswitch.d\" subfolder found"
@ -40,7 +40,8 @@ set wc [open "40-usb_modeswitch.rules" w]
puts -nonewline $wc {# Part of usb-modeswitch-data, version } puts -nonewline $wc {# Part of usb-modeswitch-data, version }
puts $wc $version puts $wc $version
puts $wc {# puts $wc {#
# Works with usb_modeswitch versions >= 2.4.0 (extension of StandardEject) # Works with usb_modeswitch versions >= 2.4.0. Slash before %k parameter
# is for compatibility only. Versions >= 2.5.0 don't need it.
# #
ACTION!="add|change", GOTO="modeswitch_rules_end" ACTION!="add|change", GOTO="modeswitch_rules_end"
@ -51,7 +52,7 @@ KERNEL=="ttyUSB*", ATTRS{bNumConfigurations}=="*", PROGRAM="usb_modeswitch --sym
SUBSYSTEM!="usb", ACTION!="add",, GOTO="modeswitch_rules_end" SUBSYSTEM!="usb", ACTION!="add",, GOTO="modeswitch_rules_end"
# Generic entry for most Huawei devices, excluding Android phones # Generic entry for most Huawei devices, excluding Android phones
ATTRS{idVendor}=="12d1", ATTRS{manufacturer}!="Android", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="usb_modeswitch '%b/%k'"} ATTRS{idVendor}=="12d1", ATTRS{manufacturer}!="Android", ATTR{bInterfaceNumber}=="00", ATTR{bInterfaceClass}=="08", RUN+="usb_modeswitch '/%k'"}
set vendorList "" set vendorList ""
set dvid "" set dvid ""

@ -1,4 +1,3 @@
# HP LaserJet Professional P1102 # HP LaserJet Professional P1102
TargetClass=0x07 TargetClass=0x07
MessageContent="555342431234567800000000000006d0000000000000000000000000000000" MessageContent="555342431234567800000000000006d0000000000000000000000000000000"
NeedResponse=1

@ -0,0 +1,3 @@
# HP LaserJet Professional P1102w
TargetClass=0x07
MessageContent="555342431234567800000000000006d0000000000000000000000000000000"

@ -0,0 +1,4 @@
# ZyXel WAH1004/WAH3004
TargetVendor=0x0586
TargetProductList="3443,3444"
StandardEject=1

@ -1,5 +1,5 @@
# LG AD600 # LG AD600
TargetVendor=0x1004 TargetVendor=0x1004
TargetProduct=0x61a7 TargetProductList="6183,61a7"
WaitBefore=10 WaitBefore=10
StandardEject=1 StandardEject=1

@ -1,4 +0,0 @@
# Huawei E630
TargetVendor=0x12d1
TargetProduct=0x1003
HuaweiMode=1

@ -1,2 +1,2 @@
# Huawei ME909u-521 (MBIM, handled by kernel, dummy config) # Huawei ME909u-521 (MBIM, dummy config)
Configuration=0 Configuration=0

@ -1,2 +1,2 @@
# Huawei ME906, ME909 (MBIM, handled by kernel, dummy config) # Huawei ME906, ME909 (MBIM, dummy config)
Configuration=0 Configuration=0

@ -2,5 +2,3 @@
TargetVendor=0x148f TargetVendor=0x148f
TargetProduct=0x9021 TargetProduct=0x9021
StandardEject=1 StandardEject=1

@ -0,0 +1,4 @@
# RaLink MT7601U
TargetVendor=0x148f
TargetProduct=0x7601
StandardEject=1

@ -1,5 +1,3 @@
# Amoi H-01 # Amoi H-01
TargetClass=0xff TargetClass=0xff
MessageContent="55534243123456780000000000000601000000000000000000000000000000" MessageContent="55534243123456780000000000000601000000000000000000000000000000"

@ -1,5 +1,3 @@
# Amoi H-02 # Amoi H-02
TargetClass=0xff TargetClass=0xff
MessageContent="55534243123456780000000000000601000000000000000000000000000000" MessageContent="55534243123456780000000000000601000000000000000000000000000000"

@ -0,0 +1,3 @@
# ZTE MF636DB
TargetClass=0xff
StandardEject=1

@ -0,0 +1,4 @@
# ZTE MU330
TargetVendor=0x19d2
TargetProduct=0x0034
StandardEject=1

@ -1,5 +1,5 @@
# ZTE MF710 (Vietnam) a.o. # ZTE MF710 (Vietnam) a.o.
TargetVendor= 0x19d2 TargetVendor= 0x19d2
TargetProductList="1592,1596,1600" TargetProductList="1534,1592,1596,1600"
StandardEject=1 StandardEject=1
MessageContent="55534243123456702000000080000c85010101180101010101000000000000" MessageContent="55534243123456702000000080000c85010101180101010101000000000000"

@ -1,3 +1,3 @@
# Vibe 3G Modem # Omega WL-72B ("Vibe 3G")
TargetClass=0xff TargetClass=0xff
MessageContent="55534243123456780000000000000606f50402527000000000000000000000" MessageContent="55534243123456780000000000000606f50402527000000000000000000000"

@ -0,0 +1,4 @@
# D-Link DWM-157 C1
TargetVendor=0x2001
TargetProduct=0x7d0e
StandardEject=1

@ -1,2 +1,2 @@
# D-Link DWM-157 C1 # D-Link DWP-157 C1
Configuration=2 Configuration=2

@ -0,0 +1,4 @@
# D-Link DWM-157 A1
TargetVendor=0x2001
TargetProduct=0x7900
StandardEject=1

@ -0,0 +1,4 @@
# D-Link DWM-222
TargetVendor=0x2001
TargetProduct=0x7e35
StandardEject=1

@ -0,0 +1,3 @@
# WeTelecom WM-D200A
TargetClass=0xff
StandardEject=1

@ -1,4 +1,3 @@
# WeTelecom WM-D300 # WeTelecom WM-D300
TargetVendor=0x22de TargetClass=0xff
TargetProduct=0x6801
StandardEject=1 StandardEject=1

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011-2016 Josua Dietze, usb_modeswitch version 2.3.0 * Copyright (c) 2011-2017 Josua Dietze, usb_modeswitch version 2.5.0
* Contains code under * Contains code under
* Copyright (c) 2010 Wojciech A. Koszek <wkoszek@FreeBSD.org> * Copyright (c) 2010 Wojciech A. Koszek <wkoszek@FreeBSD.org>
* All rights reserved. * All rights reserved.

@ -1,5 +1,5 @@
start on usb-modeswitch-upstart start on usb-modeswitch-upstart
task task
script script
exec /usr/sbin/usb_modeswitch_dispatcher --switch-upstart $UMS_PARAM exec /usr/sbin/usb_modeswitch_dispatcher --switch-mode $UMS_PARAM
end script end script

@ -1,8 +1,8 @@
/* /*
Mode switching tool for controlling mode of 'multi-state' USB devices Mode switching tool for controlling mode of 'multi-state' USB devices
Version 2.4.0, 2016/06/12 Version 2.5.0, 2017/01/17
Copyright (C) 2007 - 2016 Josua Dietze (mail to "usb_admin" at the domain Copyright (C) 2007 - 2017 Josua Dietze (mail to "usb_admin" at the domain
of the home page; or write a personal message through the forum to "Josh". of the home page; or write a personal message through the forum to "Josh".
NO SUPPORT VIA E-MAIL - please use the forum for that) NO SUPPORT VIA E-MAIL - please use the forum for that)
@ -45,7 +45,7 @@
/* Recommended tab size: 4 */ /* Recommended tab size: 4 */
#define VERSION "2.4.0" #define VERSION "2.5.0"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -473,11 +473,11 @@ int main(int argc, char **argv)
if (strlen(MessageContent)) { if (strlen(MessageContent)) {
if (strlen(MessageContent) % 2 != 0) { if (strlen(MessageContent) % 2 != 0) {
fprintf(stderr, "Error: MessageContent hex string has uneven length. Abort\n\n"); fprintf(stderr, "MessageContent hex string has uneven length. Abort\n\n");
exit(1); exit(1);
} }
if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) { if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) {
fprintf(stderr, "Error: MessageContent %s\n is not a hex string. Abort\n\n", fprintf(stderr, "MessageContent %s\n is not a hex string. Abort\n\n",
MessageContent); MessageContent);
exit(1); exit(1);
@ -579,6 +579,33 @@ int main(int argc, char **argv)
/* Get class of default device/interface */ /* Get class of default device/interface */
interfaceClass = get_interface_class(); interfaceClass = get_interface_class();
if (interfaceClass == -1) {
fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
abortExit();
} else {
SHOW_PROGRESS(output," with class %d\n", interfaceClass);
}
if (defaultClass == 0 || defaultClass == 0xef)
defaultClass = interfaceClass;
else
if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE
&& defaultClass != LIBUSB_CLASS_VENDOR_SPEC) {
/* Unexpected default class combined with differing interface class */
SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
defaultClass = 8;
}
if ((strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0)
|| StandardEject || ModeMap & HUAWEINEW_MODE || ModeMap & CISCO_MODE
|| ModeMap & OPTION_MODE)
if (defaultClass != 8) {
fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d; "
"interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
abortExit();
}
/* Check or get endpoints and alloc message list if needed*/ /* Check or get endpoints and alloc message list if needed*/
if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE
|| ModeMap & HUAWEINEW_MODE || ModeMap & OPTION_MODE) { || ModeMap & HUAWEINEW_MODE || ModeMap & OPTION_MODE) {
@ -606,29 +633,6 @@ int main(int argc, char **argv)
} }
if (interfaceClass == -1) {
fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
abortExit();
}
if (defaultClass == 0 || defaultClass == 0xef)
defaultClass = interfaceClass;
else
if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE
&& defaultClass != LIBUSB_CLASS_VENDOR_SPEC) {
/* Unexpected default class combined with differing interface class */
SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
defaultClass = 8;
}
if (strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0)
if (defaultClass != 8) {
fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n"
" interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
abortExit();
}
if (show_progress) { if (show_progress) {
fprintf(output,"\nUSB description data (for identification)\n"); fprintf(output,"\nUSB description data (for identification)\n");
deviceDescription(); deviceDescription();
@ -973,6 +977,7 @@ int switchSendMessage ()
{ {
const char* cmdHead = "55534243"; const char* cmdHead = "55534243";
int ret, i; int ret, i;
int retries = 1;
/* char* msg[3]; /* char* msg[3];
msg[0] = MessageContent; msg[0] = MessageContent;
msg[1] = MessageContent2; msg[1] = MessageContent2;
@ -984,11 +989,12 @@ int switchSendMessage ()
SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret); SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret);
return 0; return 0;
} }
libusb_clear_halt(devh, MessageEndpoint);
SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint); SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint);
if (show_progress) if (show_progress)
fflush(stdout); fflush(stdout);
retry:
for (i=0; i<MSG_DIM; i++) { for (i=0; i<MSG_DIM; i++) {
if ( strlen(Messages[i]) == 0) if ( strlen(Messages[i]) == 0)
break; break;
@ -1008,6 +1014,11 @@ int switchSendMessage ()
ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 ); ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 );
} }
SHOW_PROGRESS(output,"\n"); SHOW_PROGRESS(output,"\n");
if (ret == LIBUSB_TRANSFER_STALL && retries--) {
SHOW_PROGRESS(output,"Endpoint stalled. Resetting ...\n");
libusb_clear_halt(devh, MessageEndpoint);
goto retry;
}
if (ret < 0) if (ret < 0)
goto skip; goto skip;
} }
@ -1855,7 +1866,8 @@ char* ReadParseParam(const char* FileName, char *VariableName)
char *FirstQuote, *LastQuote, *P1, *P2; char *FirstQuote, *LastQuote, *P1, *P2;
int Line=0; int Line=0;
unsigned Len=0, Pos=0; unsigned Len=0, Pos=0;
char Str[LINE_DIM], *token, *configPos; static char Str[LINE_DIM];
char *token, *configPos;
FILE *file = NULL; FILE *file = NULL;
// Reading and storing input during the first call // Reading and storing input during the first call
@ -2030,6 +2042,8 @@ void close_all()
void abortExit() void abortExit()
{ {
fflush(output);
fflush(stderr);
close_all(); close_all();
exit(1); exit(1);
} }
@ -2039,7 +2053,7 @@ void printVersion()
{ {
char* version = VERSION; char* version = VERSION;
fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n" fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
" * Version %s (C) Josua Dietze 2016\n" " * Version %s (C) Josua Dietze 2017\n"
" * Based on libusb1/libusbx\n\n" " * Based on libusb1/libusbx\n\n"
" ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version); " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version);
} }

@ -2,7 +2,7 @@
This file is part of usb_modeswitch, a mode switching tool for controlling This file is part of usb_modeswitch, a mode switching tool for controlling
the mode of 'multi-state' USB devices the mode of 'multi-state' USB devices
Version 2.4.0, 2016/06/12 Version 2.3.0, 2016/01/12
Copyright (C) 2007 - 2016 Josua Dietze Copyright (C) 2007 - 2016 Josua Dietze
Config file parsing stuff borrowed from Guillaume Dargaud Config file parsing stuff borrowed from Guillaume Dargaud

@ -1,5 +1,5 @@
#!/bin/sh #!/bin/sh
# part of usb_modeswitch 2.4.0 # part of usb_modeswitch 2.5.0
device_in() device_in()
{ {
if [ ! -e /var/lib/usb_modeswitch/$1 ]; then if [ ! -e /var/lib/usb_modeswitch/$1 ]; then
@ -57,16 +57,19 @@ esac
IFS='/' read -r p1 p2 <<EOF IFS='/' read -r p1 p2 <<EOF
$1 $1
EOF EOF
if [ "$p2" = "" -a "$p1" != "" ]; then
p2=$p1
fi
PATH=/bin:/sbin:/usr/bin:/usr/sbin PATH=/bin:/sbin:/usr/bin:/usr/sbin
init_path=`readlink /sbin/init` init_path=`readlink /sbin/init`
if [ `basename $init_path` = "systemd" ]; then if [ `basename $init_path` = "systemd" ]; then
systemctl --no-block start usb_modeswitch@$p1'_'$p2.service systemctl --no-block start usb_modeswitch@$p2.service
elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then elif [ -e "/etc/init/usb-modeswitch-upstart.conf" ]; then
initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$1 initctl emit --no-wait usb-modeswitch-upstart UMS_PARAM=$p2
else else
# only old distros, new udev will kill all subprocesses # only old distros, new udev will kill all subprocesses
exec 1<&- 2<&- 5<&- 7<&- exec 1<&- 2<&- 5<&- 7<&-
exec usb_modeswitch_dispatcher --switch-mode $1 & exec usb_modeswitch_dispatcher --switch-mode $p2 &
fi fi
exit 0 exit 0

@ -9,8 +9,8 @@
# the mode switching program with the matching parameter # the mode switching program with the matching parameter
# file from /usr/share/usb_modeswitch # file from /usr/share/usb_modeswitch
# #
# Part of usb-modeswitch-2.4.0 package # Part of usb-modeswitch-2.5.0 package
# (C) Josua Dietze 2009-2016 # (C) Josua Dietze 2009-2017
set arg0 [lindex $argv 0] set arg0 [lindex $argv 0]
if [regexp {\.tcl$} $arg0] { if [regexp {\.tcl$} $arg0] {
@ -40,6 +40,11 @@ global scsi usb config match device flags setup devdir loginit
set flags(config) "" set flags(config) ""
Log "[ParseGlobalConfig]" Log "[ParseGlobalConfig]"
if {$flags(stordelay) > 0} {
SetStorageDelay $flags(stordelay)
}
# The facility to add a symbolic link pointing to the # The facility to add a symbolic link pointing to the
# ttyUSB port which provides interrupt transfer, i.e. # ttyUSB port which provides interrupt transfer, i.e.
# the port to connect through. # the port to connect through.
@ -55,74 +60,47 @@ if {[lindex $argv 0] == "--symlink-name"} {
SafeExit SafeExit
} }
if {[lindex $argv 0] == "--switch-systemd"} { # arg0: the bus id for the device (udev: %b), now deprecated
set argList [split [lindex $argv 1] _] # arg1: the "kernel name" for the device (udev: %k)
Log "\nStarted via systemd" #
} else { # From version 2.5.0 upward %b is removed by udev sh script
if {[lindex $argv 0] == "--switch-upstart"} { # which can handle old and new udev params ('%b/%k' and '%k')
Log "\nStarted via upstart"
Log "Raw parameters: $argv"
set device "noname"
if {[lindex $argv 0] == "--switch-mode"} {
if [string length [lindex $argv 1]] {
set arg1 [lindex $argv 1]
} else {
Log "\nNo data from udev. Exit"
SafeExit
} }
set argList [split [lindex $argv 1] /]
}
if [string length [lindex $argList 1]] {
set device [lindex $argList 1]
} else { } else {
set device "noname" Log "\nNo command given. Exit"
}
if {$flags(stordelay) > 0} {
SetStorageDelay $flags(stordelay)
}
Log "Raw args from udev: [lindex $argv 1]\n"
if {$device == "noname"} {
Log "\nNo data from udev. Exit"
SafeExit SafeExit
} }
if {![regexp -- {--switch-} [lindex $argv 0]]} { if {![regexp {(.*?):.*$} $arg1 d device]} {
Log "\nNo command given. Exit" if {![regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} $arg1 d device]} {
SafeExit Log "Could not determine device dir from udev values! Exit"
SafeExit
}
} }
set flags(logwrite) 1
set setup(dbdir) /usr/share/usb_modeswitch set setup(dbdir) /usr/share/usb_modeswitch
set setup(dbdir_etc) /etc/usb_modeswitch.d set setup(dbdir_etc) /etc/usb_modeswitch.d
if {![file exists $setup(dbdir)] && ![file exists $setup(dbdir_etc)]} { if {![file exists $setup(dbdir)] && ![file exists $setup(dbdir_etc)]} {
Log "\nError: no config database found in /usr/share or /etc. Exit" Log "\nError: no config database found in /usr/share or /etc. Exit"
SafeExit SafeExit
} }
set bindir /usr/sbin
set bindir /usr/sbin
set devList1 {} set devList1 {}
set devList2 {} set devList2 {}
# arg 0: the bus id for the device (udev: %b), often ommitted
# arg 1: the "kernel name" for the device (udev: %k)
#
# Used to determine the top directory for the device in sysfs
set ifChk 0 set ifChk 0
if {[string length [lindex $argList 0]] == 0} {
if {[string length [lindex $argList 1]] == 0} {
Log "No device number values given from udev! Exit"
SafeExit
} else {
if {![regexp {(.*?):} [lindex $argList 1] d dev_top]} {
if {![regexp {([0-9]+-[0-9]+\.?[0-9]*.*)} [lindex $argList 1] d dev_top]} {
Log "Could not determine device dir from udev values! Exit"
SafeExit
}
}
}
} else {
set dev_top [lindex $argList 0]
regexp {(.*?):} $dev_top d dev_top
}
set devdir /sys/bus/usb/devices/$dev_top set devdir /sys/bus/usb/devices/$device
if {![file isdirectory $devdir]} { if {![file isdirectory $devdir]} {
Log "Top device directory not found ($devdir)! Exit" Log "Top device directory not found ($devdir)! Exit"
SafeExit SafeExit
@ -141,8 +119,6 @@ Log " Interface 0 class is $config(class)."
set ifdir [file tail [IfDir $iface $devdir]] set ifdir [file tail [IfDir $iface $devdir]]
regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface regexp {:([0-9]+\.[0-9]+)$} $ifdir d iface
set flags(logwrite) 1
# Mapping of the short string identifiers (in the config # Mapping of the short string identifiers (in the config
# file names) to the long name used here # file names) to the long name used here
# #
@ -228,13 +204,10 @@ if $scsiNeeded {
Log "SCSI attributes not needed, move on" Log "SCSI attributes not needed, move on"
} }
# General wait - some devices need this
after 500
# Now check for a matching config file. Matching is done # Now check for a matching config file. Matching is done
# by MatchDevice # by MatchDevice
set report {} set report ""
foreach mconfig $configList { foreach mconfig $configList {
# skipping installer leftovers like "*.rpmnew" # skipping installer leftovers like "*.rpmnew"
@ -243,74 +216,89 @@ foreach mconfig $configList {
Log "Check config: $mconfig" Log "Check config: $mconfig"
if [MatchDevice $mconfig] { if [MatchDevice $mconfig] {
Log "! matched. Read config data" Log "! matched. Read config data"
# set flags(config) $mconfig
if [string length $usb(busnum)] {
set busParam "-b [string trimleft $usb(busnum) 0]"
set devParam "-g [string trimleft $usb(devnum) 0]"
} else {
set busParam ""
set devParam ""
}
set flags(config) [ConfigGet conffile $mconfig] set flags(config) [ConfigGet conffile $mconfig]
ParseDeviceConfig $flags(config) break
if [regexp -nocase {/[0-9a-f]+:#} $flags(config)] { } else {
Log "Note: Using generic manufacturer configuration for \"$flags(os)\"" Log "* no match, don't use this config"
} }
if $flags(nombim) { }
set config(NoMBIMCheck) 1 if {$flags(config) == ""} {
} Log "No matching config file found. Exit"
if {$config(WaitBefore) != ""} { SafeExit
Log "Delay time of $config(WaitBefore) seconds" }
append config(WaitBefore) "000"
after $config(WaitBefore) ParseDeviceConfig $flags(config)
Log " wait is over, start mode switch"
} if [regexp -nocase {0x([0-9a-f]+)} $config(TargetClass) d tc] {
if {$config(NoMBIMCheck)==0 && $usb(bNumConfigurations) > 1} { if {$tc == $config(class)} {
Log "Device may have an MBIM configuration, check driver ..." Log "Class of interface 0 matches target. Do nothing"
if [CheckMBIM] { set report "ok:busdev"
Log " driver for MBIM devices is available" }
Log "Find MBIM configuration number ..." }
if [catch {set cfgno [exec /usr/sbin/usb_modeswitch -j -Q $busParam $devParam -v $usb(idVendor) -p $usb(idProduct)]} err] {
Log "Error when trying to find MBIM configuration, switch to legacy modem mode" if [string length $usb(busnum)] {
} else { set busParam "-b [string trimleft $usb(busnum) 0]"
set cfgno [string trim $cfgno] set devParam "-g [string trimleft $usb(devnum) 0]"
if {$cfgno > 0} { } else {
set config(Configuration) $cfgno set busParam ""
set flags(config) "Configuration=$cfgno" set devParam ""
} else { }
Log " No MBIM configuration found, switch to legacy modem mode" if [regexp -nocase $flags(os) $flags(config)] {
} Log "Note: Using generic manufacturer configuration for \"$flags(os)\""
} }
if $flags(nombim) {
set config(NoMBIMCheck) 1
}
if {$config(NoMBIMCheck)==0 && $usb(bNumConfigurations) > 1} {
Log "Device may have an MBIM configuration, check driver ..."
if [CheckMBIM] {
Log " driver for MBIM devices is available"
Log "Find MBIM configuration number ..."
if [catch {set cfgno [exec /usr/sbin/usb_modeswitch -j -Q $busParam $devParam -v $usb(idVendor) -p $usb(idProduct)]} err] {
Log "Error when trying to find MBIM configuration, switch to legacy modem mode"
} else {
set cfgno [string trim $cfgno]
if {$cfgno > 0} {
set config(Configuration) $cfgno
set flags(config) "Configuration=$cfgno"
} else { } else {
Log " no MBIM driver found, switch to legacy modem mode" Log " No MBIM configuration found, switch to legacy modem mode"
} }
} }
if [PantechAutoSwitch] {
Log "Waiting for Pantech auto-modeswitch"
set report "ok:busdev"
break
}
if {$config(Configuration) == 0} {
Log "Config file contains dummy method, do nothing. Exit"
SafeExit
}
UnbindDriver $devdir $ifdir
# Now we are actually switching
if $flags(logging) {
Log "Command to be run:\nusb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$flags(config)"
set report [exec /usr/sbin/usb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]
Log "\nVerbose debug output of usb_modeswitch and libusb follows"
Log "(Note that some USB errors are to be expected in the process)"
Log "--------------------------------"
Log $report
Log "--------------------------------"
Log "(end of usb_modeswitch output)\n"
} else {
set report [exec /usr/sbin/usb_modeswitch -Q -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]
}
break
} else { } else {
Log "* no match, don't use this config" Log " no MBIM driver found, switch to legacy modem mode"
}
}
if [PantechAutoSwitch] {
Log "Waiting for Pantech auto-modeswitch"
set report "ok:busdev"
}
if {$config(Configuration) == 0} {
Log "Config file contains dummy method, do nothing. Exit"
SafeExit
}
# General wait - some devices need this
after 500
if {$config(WaitBefore) != ""} {
Log "Delay time of $config(WaitBefore) seconds"
append config(WaitBefore) "000"
after $config(WaitBefore)
}
if {$report == ""} {
# Now we are actually switching
if $flags(logging) {
Log "Command line:\nusb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f \$flags(config)"
catch {set report [exec /usr/sbin/usb_modeswitch -W -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]} report
Log "\nVerbose debug output of usb_modeswitch and libusb follows"
Log "(Note that some USB errors are to be expected in the process)"
Log "--------------------------------"
Log $report
Log "--------------------------------"
Log "(end of usb_modeswitch output)\n"
} else {
catch {set report [exec /usr/sbin/usb_modeswitch -Q -D $configParam $busParam $devParam -v $usb(idVendor) -p $usb(idProduct) -f "$flags(config)" 2>@1]} report
} }
} }
@ -976,16 +964,6 @@ if {$config(PantechMode) == 1} {
} }
proc UnbindDriver {devdir ifdir} {
set att $devdir/$ifdir/driver/unbind
if [file exists $att] {
Log "Unbinding driver"
exec echo -n "$ifdir" > $att
}
}
proc {LogAttributes} {} { proc {LogAttributes} {} {
global flags usb global flags usb

@ -3,6 +3,6 @@ Description=USB_ModeSwitch_%i
[Service] [Service]
Type=oneshot Type=oneshot
ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-systemd %i ExecStart=/usr/sbin/usb_modeswitch_dispatcher --switch-mode %i
#ExecStart=/bin/echo %i #ExecStart=/bin/echo %i

Loading…
Cancel
Save