2 Mode switching tool for controlling mode of 'multi-state' USB devices
3 Version 2.3.0, 2016/01/12
5 Copyright (C) 2007 - 2016 Josua Dietze (mail to "digidietze" at the domain
6 of the home page; or write a personal message through the forum to "Josh".
7 NO SUPPORT VIA E-MAIL - please use the forum for that)
11 Command line parsing, decent usage/config output/handling, bugfixes and advanced
15 TargetClass parameter implementation to support new Option devices/firmware:
16 Paul Hardwick (http://www.pharscape.org)
18 Created with initial help from:
19 "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl)
21 Config file parsing code borrowed from:
22 Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
24 Hexstr2bin function borrowed from:
25 Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
27 Other contributions: see README
29 Device information contributors are named in the "device_reference.txt" file. See
32 This program is free software; you can redistribute it and/or modify
33 it under the terms of the GNU General Public License as published by
34 the Free Software Foundation; either version 2 of the License, or
35 (at your option) any later version.
37 This program is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details:
42 http://www.gnu.org/licenses/gpl.txt
46 /* Recommended tab size: 4 */
48 #define VERSION "2.3.0"
59 #include "usb_modeswitch.h"
64 int usb_bulk_io(struct libusb_device_handle
*handle
, int ep
, unsigned char *bytes
,
65 int size
, int timeout
)
69 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
70 r
= libusb_bulk_transfer(handle
, ep
& 0xff, bytes
, size
,
71 &actual_length
, timeout
);
73 /* if we timed out but did transfer some data, report as successful short
74 * read. FIXME: is this how libusb-0.1 works? */
75 if (r
== 0 || (r
== LIBUSB_ERROR_TIMEOUT
&& actual_length
> 0))
82 static int usb_interrupt_io(libusb_device_handle
*handle
, int ep
, unsigned char *bytes
,
83 int size
, int timeout
)
87 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
88 r
= libusb_interrupt_transfer(handle
, ep
& 0xff, bytes
, size
,
89 &actual_length
, timeout
);
91 /* if we timed out but did transfer some data, report as successful short
92 * read. FIXME: is this how libusb-0.1 works? */
93 if (r
== 0 || (r
== LIBUSB_ERROR_TIMEOUT
&& actual_length
> 0))
100 #define LINE_DIM 1024
102 #define BUF_SIZE 4096
103 #define DESCR_MAX 129
105 #define SEARCH_DEFAULT 0
106 #define SEARCH_TARGET 1
107 #define SEARCH_BUSDEV 2
109 #define SWITCH_CONFIG_MAXTRIES 5
111 #define SHOW_PROGRESS if (show_progress) fprintf
115 static struct libusb_context
*ctx
= NULL
;
116 static struct libusb_device
*dev
= NULL
;
117 static struct libusb_device_handle
*devh
= NULL
;
118 static struct libusb_config_descriptor
*active_config
= NULL
;
120 int DefaultVendor
=0, DefaultProduct
=0, TargetVendor
=0, TargetProduct
=-1, TargetClass
=0;
121 int MessageEndpoint
=0, ResponseEndpoint
=0, ReleaseDelay
=0;
122 int targetDeviceCount
=0, searchMode
;
123 int devnum
=-1, busnum
=-1;
125 unsigned int ModeMap
= 0;
126 #define DETACHONLY_MODE 0x00000001
127 #define HUAWEI_MODE 0x00000002
128 #define SIERRA_MODE 0x00000004
129 #define SONY_MODE 0x00000008
130 #define GCT_MODE 0x00000010
131 #define KOBIL_MODE 0x00000020
132 #define SEQUANS_MODE 0x00000040
133 #define MOBILEACTION_MODE 0x00000080
134 #define CISCO_MODE 0x00000100
135 #define QISDA_MODE 0x00000200
136 #define QUANTA_MODE 0x00000400
137 #define BLACKBERRY_MODE 0x00000800
138 #define PANTECH_MODE 0x00001000
139 #define HUAWEINEW_MODE 0x00002000
140 #define OPTION_MODE 0x00004000
144 char verbose
=0, show_progress
=1, ResetUSB
=0, CheckSuccess
=0, config_read
=0;
145 char NoDriverLoading
=0, sysmode
=0, mbim
=0;
146 char StandardEject
=0;
148 char MessageContent
[LINE_DIM
];
149 char MessageContent2
[LINE_DIM
];
150 char MessageContent3
[LINE_DIM
];
151 char TargetProductList
[LINE_DIM
];
152 char DefaultProductList
[5];
153 unsigned char ByteString
[LINE_DIM
/2];
154 unsigned char buffer
[BUF_SIZE
];
159 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
160 int Interface
= -1, Configuration
= 0, AltSetting
= -1;
163 static struct option long_options
[] = {
164 {"help", no_argument
, 0, 'h'},
165 {"version", no_argument
, 0, 'e'},
166 {"default-vendor", required_argument
, 0, 'v'},
167 {"default-product", required_argument
, 0, 'p'},
168 {"target-vendor", required_argument
, 0, 'V'},
169 {"target-product", required_argument
, 0, 'P'},
170 {"target-class", required_argument
, 0, 'C'},
171 {"message-endpoint", required_argument
, 0, 'm'},
172 {"message-content", required_argument
, 0, 'M'},
173 {"message-content2", required_argument
, 0, '2'},
174 {"message-content3", required_argument
, 0, '3'},
175 {"release-delay", required_argument
, 0, 'w'},
176 {"response-endpoint", required_argument
, 0, 'r'},
177 {"bus-num", required_argument
, 0, 'b'},
178 {"device-num", required_argument
, 0, 'g'},
179 {"detach-only", no_argument
, 0, 'd'},
180 {"huawei-mode", no_argument
, 0, 'H'},
181 {"huawei-new-mode", no_argument
, 0, 'J'},
182 {"sierra-mode", no_argument
, 0, 'S'},
183 {"sony-mode", no_argument
, 0, 'O'},
184 {"qisda-mode", no_argument
, 0, 'B'},
185 {"quanta-mode", no_argument
, 0, 'E'},
186 {"kobil-mode", no_argument
, 0, 'T'},
187 {"gct-mode", no_argument
, 0, 'G'},
188 {"sequans-mode", no_argument
, 0, 'N'},
189 {"mobileaction-mode", no_argument
, 0, 'A'},
190 {"cisco-mode", no_argument
, 0, 'L'},
191 {"blackberry-mode", no_argument
, 0, 'Z'},
192 {"option-mode", no_argument
, 0, 'U'},
193 {"pantech-mode", required_argument
, 0, 'F'},
194 {"std-eject", no_argument
, 0, 'K'},
195 {"need-response", no_argument
, 0, 'n'},
196 {"reset-usb", no_argument
, 0, 'R'},
197 {"config-file", required_argument
, 0, 'c'},
198 {"verbose", no_argument
, 0, 'W'},
199 {"quiet", no_argument
, 0, 'Q'},
200 {"sysmode", no_argument
, 0, 'D'},
201 {"inquire", no_argument
, 0, 'I'},
202 {"stdinput", no_argument
, 0, 't'},
203 {"find-mbim", no_argument
, 0, 'j'},
204 {"long-config", required_argument
, 0, 'f'},
205 {"check-success", required_argument
, 0, 's'},
206 {"interface", required_argument
, 0, 'i'},
207 {"configuration", required_argument
, 0, 'u'},
208 {"altsetting", required_argument
, 0, 'a'},
213 void readConfigFile(const char *configFilename
)
215 ParseParamHex(configFilename
, TargetVendor
);
216 ParseParamHex(configFilename
, TargetProduct
);
217 ParseParamString(configFilename
, TargetProductList
);
218 ParseParamHex(configFilename
, TargetClass
);
219 ParseParamHex(configFilename
, DefaultVendor
);
220 ParseParamHex(configFilename
, DefaultProduct
);
221 ParseParamBoolMap(configFilename
, DetachStorageOnly
, ModeMap
, DETACHONLY_MODE
);
222 ParseParamBoolMap(configFilename
, HuaweiMode
, ModeMap
, HUAWEI_MODE
);
223 ParseParamBoolMap(configFilename
, HuaweiNewMode
, ModeMap
, HUAWEINEW_MODE
);
224 ParseParamBoolMap(configFilename
, SierraMode
, ModeMap
, SIERRA_MODE
);
225 ParseParamBoolMap(configFilename
, SonyMode
, ModeMap
, SONY_MODE
);
226 ParseParamBoolMap(configFilename
, GCTMode
, ModeMap
, GCT_MODE
);
227 ParseParamBoolMap(configFilename
, KobilMode
, ModeMap
, KOBIL_MODE
);
228 ParseParamBoolMap(configFilename
, SequansMode
, ModeMap
, SEQUANS_MODE
);
229 ParseParamBoolMap(configFilename
, MobileActionMode
, ModeMap
, MOBILEACTION_MODE
);
230 ParseParamBoolMap(configFilename
, CiscoMode
, ModeMap
, CISCO_MODE
);
231 ParseParamBoolMap(configFilename
, QisdaMode
, ModeMap
, QISDA_MODE
);
232 ParseParamBoolMap(configFilename
, QuantaMode
, ModeMap
, QUANTA_MODE
);
233 ParseParamBoolMap(configFilename
, OptionMode
, ModeMap
, OPTION_MODE
);
234 ParseParamBoolMap(configFilename
, BlackberryMode
, ModeMap
, BLACKBERRY_MODE
);
235 ParseParamInt(configFilename
, PantechMode
);
237 ModeMap
|= PANTECH_MODE
;
238 ParseParamBool(configFilename
, StandardEject
);
239 ParseParamBool(configFilename
, NoDriverLoading
);
240 ParseParamHex(configFilename
, MessageEndpoint
);
241 ParseParamString(configFilename
, MessageContent
);
242 ParseParamString(configFilename
, MessageContent2
);
243 ParseParamString(configFilename
, MessageContent3
);
244 ParseParamInt(configFilename
, ReleaseDelay
);
245 ParseParamHex(configFilename
, ResponseEndpoint
);
246 ParseParamHex(configFilename
, ResetUSB
);
247 ParseParamInt(configFilename
, CheckSuccess
);
248 ParseParamHex(configFilename
, Interface
);
249 ParseParamHex(configFilename
, Configuration
);
250 ParseParamHex(configFilename
, AltSetting
);
252 /* TargetProductList has priority over TargetProduct */
253 if (TargetProduct
!= -1 && TargetProductList
[0] != '\0') {
255 SHOW_PROGRESS(output
,"Warning: TargetProductList overrides TargetProduct!\n");
265 fprintf (output
,"DefaultVendor= 0x%04x\n", DefaultVendor
);
266 if ( DefaultProduct
)
267 fprintf (output
,"DefaultProduct= 0x%04x\n", DefaultProduct
);
269 fprintf (output
,"TargetVendor= 0x%04x\n", TargetVendor
);
270 if ( TargetProduct
> -1 )
271 fprintf (output
,"TargetProduct= 0x%04x\n", TargetProduct
);
273 fprintf (output
,"TargetClass= 0x%02x\n", TargetClass
);
274 if ( strlen(TargetProductList
) )
275 fprintf (output
,"TargetProductList=\"%s\"\n", TargetProductList
);
277 fprintf (output
,"\nStandardEject=1\n");
278 if (ModeMap
& DETACHONLY_MODE
)
279 fprintf (output
,"\nDetachStorageOnly=1\n");
280 if (ModeMap
& HUAWEI_MODE
)
281 fprintf (output
,"HuaweiMode=1\n");
282 if (ModeMap
& HUAWEINEW_MODE
)
283 fprintf (output
,"HuaweiNewMode=1\n");
284 if (ModeMap
& SIERRA_MODE
)
285 fprintf (output
,"SierraMode=1\n");
286 if (ModeMap
& SONY_MODE
)
287 fprintf (output
,"SonyMode=1\n");
288 if (ModeMap
& QISDA_MODE
)
289 fprintf (output
,"QisdaMode=1\n");
290 if (ModeMap
& QUANTA_MODE
)
291 fprintf (output
,"QuantaMode=1\n");
292 if (ModeMap
& GCT_MODE
)
293 fprintf (output
,"GCTMode=1\n");
294 if (ModeMap
& KOBIL_MODE
)
295 fprintf (output
,"KobilMode=1\n");
296 if (ModeMap
& SEQUANS_MODE
)
297 fprintf (output
,"SequansMode=1\n");
298 if (ModeMap
& MOBILEACTION_MODE
)
299 fprintf (output
,"MobileActionMode=1\n");
300 if (ModeMap
& CISCO_MODE
)
301 fprintf (output
,"CiscoMode=1\n");
302 if (ModeMap
& BLACKBERRY_MODE
)
303 fprintf (output
,"BlackberryMode=1\n");
304 if (ModeMap
& OPTION_MODE
)
305 fprintf (output
,"OptionMode=1\n");
306 if (ModeMap
& PANTECH_MODE
)
307 fprintf (output
,"PantechMode=1\n");
308 if ( MessageEndpoint
)
309 fprintf (output
,"MessageEndpoint=0x%02x\n", MessageEndpoint
);
310 if ( strlen(MessageContent
) )
311 fprintf (output
,"MessageContent=\"%s\"\n", MessageContent
);
312 if ( strlen(MessageContent2
) )
313 fprintf (output
,"MessageContent2=\"%s\"\n", MessageContent2
);
314 if ( strlen(MessageContent3
) )
315 fprintf (output
,"MessageContent3=\"%s\"\n", MessageContent3
);
316 if ( ResponseEndpoint
)
317 fprintf (output
,"ResponseEndpoint=0x%02x\n", ResponseEndpoint
);
318 if ( Interface
> -1 )
319 fprintf (output
,"Interface=0x%02x\n", Interface
);
320 if ( Configuration
> 0 )
321 fprintf (output
,"Configuration=0x%02x\n", Configuration
);
322 if ( AltSetting
> -1 )
323 fprintf (output
,"AltSetting=0x%02x\n", AltSetting
);
325 fprintf (output
,"Success check enabled, max. wait time %d seconds\n", CheckSuccess
);
327 fprintf (output
,"System integration mode enabled\n");
331 int readArguments(int argc
, char **argv
)
333 int c
, option_index
= 0, count
=0;
334 char *longConfig
= NULL
;
344 c
= getopt_long (argc
, argv
, "hejWQDndKHJSOBEGTNALZUF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
345 long_options
, &option_index
);
347 /* Detect the end of the options. */
353 case 'R': ResetUSB
= 1; break;
354 case 'v': DefaultVendor
= strtol(optarg
, NULL
, 16); break;
355 case 'p': DefaultProduct
= strtol(optarg
, NULL
, 16); break;
356 case 'V': TargetVendor
= strtol(optarg
, NULL
, 16); break;
357 case 'P': TargetProduct
= strtol(optarg
, NULL
, 16); break;
358 case 'C': TargetClass
= strtol(optarg
, NULL
, 16); break;
359 case 'm': MessageEndpoint
= strtol(optarg
, NULL
, 16); break;
360 case 'M': strncpy(MessageContent
, optarg
, LINE_DIM
); break;
361 case '2': strncpy(MessageContent2
, optarg
, LINE_DIM
); break;
362 case '3': strncpy(MessageContent3
, optarg
, LINE_DIM
); break;
363 case 'w': ReleaseDelay
= strtol(optarg
, NULL
, 10); break;
365 case 'r': ResponseEndpoint
= strtol(optarg
, NULL
, 16); break;
366 case 'K': StandardEject
= 1; break;
367 case 'd': ModeMap
= ModeMap
+ DETACHONLY_MODE
; break;
368 case 'H': ModeMap
= ModeMap
+ HUAWEI_MODE
; break;
369 case 'J': ModeMap
= ModeMap
+ HUAWEINEW_MODE
; break;
370 case 'S': ModeMap
= ModeMap
+ SIERRA_MODE
; break;
371 case 'O': ModeMap
= ModeMap
+ SONY_MODE
; break;; break;
372 case 'B': ModeMap
= ModeMap
+ QISDA_MODE
; break;
373 case 'E': ModeMap
= ModeMap
+ QUANTA_MODE
; break;
374 case 'G': ModeMap
= ModeMap
+ GCT_MODE
; break;
375 case 'T': ModeMap
= ModeMap
+ KOBIL_MODE
; break;
376 case 'N': ModeMap
= ModeMap
+ SEQUANS_MODE
; break;
377 case 'A': ModeMap
= ModeMap
+ MOBILEACTION_MODE
; break;
378 case 'L': ModeMap
= ModeMap
+ CISCO_MODE
; break;
379 case 'Z': ModeMap
= ModeMap
+ BLACKBERRY_MODE
; break;
380 case 'U': ModeMap
= ModeMap
+ OPTION_MODE
; break;
381 case 'F': ModeMap
= ModeMap
+ PANTECH_MODE
;
382 PantechMode
= strtol(optarg
, NULL
, 10); break;
383 case 'c': readConfigFile(optarg
); break;
384 case 't': readConfigFile("stdin"); break;
385 case 'W': verbose
= 1; show_progress
= 1; count
--; break;
386 case 'Q': show_progress
= 0; verbose
= 0; count
--; break;
387 case 'D': sysmode
= 1; count
--; break;
388 case 's': CheckSuccess
= strtol(optarg
, NULL
, 10); count
--; break;
390 case 'b': busnum
= strtol(optarg
, NULL
, 10); break;
391 case 'g': devnum
= strtol(optarg
, NULL
, 10); break;
393 case 'i': Interface
= strtol(optarg
, NULL
, 16); break;
394 case 'u': Configuration
= strtol(optarg
, NULL
, 16); break;
395 case 'a': AltSetting
= strtol(optarg
, NULL
, 16); break;
396 case 'j': mbim
= 1; break;
399 longConfig
= malloc(strlen(optarg
)+5);
400 strcpy(longConfig
,"##\n");
401 strcat(longConfig
,optarg
);
402 strcat(longConfig
,"\n");
403 readConfigFile(longConfig
);
417 default: /* Unsupported - error message has already been printed */
418 fprintf (output
,"\n");
427 int main(int argc
, char **argv
)
429 int ret
=0, numDefaults
=0, sonySuccess
=0;
430 int currentConfigVal
=0, defaultClass
=0, interfaceClass
=0;
431 struct libusb_device_descriptor descriptor
;
432 enum libusb_error libusbError
;
434 /* Make sure we have empty strings even if not set by config */
435 TargetProductList
[0] = '\0';
436 MessageContent
[0] = '\0';
437 MessageContent2
[0] = '\0';
438 MessageContent3
[0] = '\0';
439 DefaultProductList
[0] = '\0';
441 /* Useful for debugging during boot */
442 // output=fopen("/dev/console", "w");
445 signal(SIGTERM
, release_usb_device
);
448 * Parameter parsing, USB preparation/diagnosis, plausibility checks
451 /* Check command arguments, use params instead of config file when given */
452 switch (readArguments(argc
, argv
)) {
453 case 0: /* no argument or -W, -q or -s */
455 default: /* one or more arguments except -W, -q or -s */
456 if (!config_read
) /* if arguments contain -c, the config file was already processed */
457 if (verbose
) fprintf(output
,"Take all parameters from the command line\n\n");
463 fprintf(output
,"\n");
466 /* Some sanity checks. The default IDs are mandatory */
467 if (!(DefaultVendor
&& DefaultProduct
)) {
468 SHOW_PROGRESS(output
,"No default vendor/product ID given. Abort\n\n");
472 if (strlen(MessageContent
)) {
473 if (strlen(MessageContent
) % 2 != 0) {
474 fprintf(stderr
, "Error: MessageContent hex string has uneven length. Abort\n\n");
477 if ( hexstr2bin(MessageContent
, ByteString
, strlen(MessageContent
)/2) == -1) {
478 fprintf(stderr
, "Error: MessageContent %s\n is not a hex string. Abort\n\n",
486 searchMode
= SEARCH_DEFAULT
;
488 SHOW_PROGRESS(output
,"Use given bus/device number: %03d/%03d ...\n", busnum
, devnum
);
489 searchMode
= SEARCH_BUSDEV
;
493 if (CheckSuccess
&& !(TargetVendor
|| TargetProduct
> -1 || TargetProductList
[0] != '\0')
496 fprintf(output
,"Note: No target parameter given; success check limited\n");
498 if (TargetProduct
> -1 && TargetProductList
[0] == '\0') {
499 sprintf(TargetProductList
,"%04x",TargetProduct
);
503 /* libusb initialization */
504 if ((libusbError
= libusb_init(&ctx
)) != LIBUSB_SUCCESS
) {
505 fprintf(stderr
, "Error: Failed to initialize libusb. \n\n");
510 libusb_set_debug(ctx
, 3);
513 printf("%d\n", findMBIMConfig(DefaultVendor
, DefaultProduct
, searchMode
) );
517 /* Count existing target devices, remember for success check */
518 if (searchMode
!= SEARCH_BUSDEV
&& (TargetVendor
|| TargetClass
)) {
519 SHOW_PROGRESS(output
,"Look for target devices ...\n");
520 search_devices(&targetDeviceCount
, TargetVendor
, TargetProductList
, TargetClass
, 0,
523 if (targetDeviceCount
) {
524 SHOW_PROGRESS(output
," Found devices in target mode or class (%d)\n", targetDeviceCount
);
526 SHOW_PROGRESS(output
," No devices in target mode or class found\n");
529 /* Count default devices, get the last one found */
530 SHOW_PROGRESS(output
,"Look for default devices ...\n");
532 sprintf(DefaultProductList
,"%04x",DefaultProduct
);
533 dev
= search_devices(&numDefaults
, DefaultVendor
, DefaultProductList
, TargetClass
,
534 Configuration
, searchMode
);
537 SHOW_PROGRESS(output
," Found devices in default mode (%d)\n", numDefaults
);
539 SHOW_PROGRESS(output
," No devices in default mode found. Nothing to do. Bye!\n\n");
545 SHOW_PROGRESS(output
," No bus/device match. Is device connected? Abort\n\n");
550 devnum
= libusb_get_device_address(dev
);
551 busnum
= libusb_get_bus_number(dev
);
552 SHOW_PROGRESS(output
,"Access device %03d on bus %03d\n", devnum
, busnum
);
554 libusb_open(dev
, &devh
);
556 SHOW_PROGRESS(output
,"Error opening the device. Abort\n\n");
561 /* Get current configuration of default device, note value if Configuration
562 * parameter is set. Also sets active_config
564 currentConfigVal
= get_current_config_value(dev
);
565 if (Configuration
> -1) {
566 SHOW_PROGRESS(output
,"Current configuration number is %d\n", currentConfigVal
);
568 currentConfigVal
= 0;
570 libusb_get_device_descriptor(dev
, &descriptor
);
571 defaultClass
= descriptor
.bDeviceClass
;
573 Interface
= active_config
->interface
[0].altsetting
[0].bInterfaceNumber
;
574 SHOW_PROGRESS(output
,"Use interface number %d\n", Interface
);
576 /* Get class of default device/interface */
577 interfaceClass
= get_interface_class();
579 /* Check or get endpoints */
580 if (strlen(MessageContent
) || StandardEject
|| ModeMap
& CISCO_MODE
581 || ModeMap
& HUAWEINEW_MODE
|| ModeMap
& OPTION_MODE
) {
583 if (!MessageEndpoint
)
584 MessageEndpoint
= find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT
);
585 if (!ResponseEndpoint
)
586 ResponseEndpoint
= find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN
);
587 if (!MessageEndpoint
) {
588 fprintf(stderr
,"Error: message endpoint not given or found. Abort\n\n");
591 if (!ResponseEndpoint
) {
592 fprintf(stderr
,"Error: response endpoint not given or found. Abort\n\n");
595 SHOW_PROGRESS(output
,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
,
600 if (interfaceClass
== -1) {
601 fprintf(stderr
, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface
);
605 if (defaultClass
== 0)
606 defaultClass
= interfaceClass
;
608 if (interfaceClass
== LIBUSB_CLASS_MASS_STORAGE
&& defaultClass
!= LIBUSB_CLASS_MASS_STORAGE
609 && defaultClass
!= 0xef && defaultClass
!= LIBUSB_CLASS_VENDOR_SPEC
) {
611 /* Unexpected default class combined with differing interface class */
612 SHOW_PROGRESS(output
,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass
);
616 if (strlen(MessageContent
) && strncmp("55534243",MessageContent
,8) == 0)
617 if (defaultClass
!= 8) {
618 fprintf(stderr
, "Error: can't use storage command in MessageContent with interface %d;\n"
619 " interface class is %d, expected 8. Abort\n\n", Interface
, defaultClass
);
624 fprintf(output
,"\nUSB description data (for identification)\n");
628 /* Special modes are exclusive, so check for illegal combinations.
629 * More than one bit set?
631 if ( ModeMap
& (ModeMap
-1) ) {
632 fprintf(output
,"Multiple special modes selected; check configuration. Abort\n\n");
636 if ((strlen(MessageContent
) || StandardEject
) && ModeMap
) {
637 MessageContent
[0] = '\0';
639 fprintf(output
,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n");
642 if (StandardEject
&& (strlen(MessageContent2
) || strlen(MessageContent3
))) {
643 fprintf(output
,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n");
646 if ( !ModeMap
&& !strlen(MessageContent
) && AltSetting
== -1 && !Configuration
&& !StandardEject
)
647 SHOW_PROGRESS(output
,"Warning: no switching method given. See documentation\n");
650 * The switching actions
654 openlog("usb_modeswitch", 0, LOG_SYSLOG
);
655 syslog(LOG_NOTICE
, "switch device %04x:%04x on %03d/%03d", DefaultVendor
, DefaultProduct
,
660 if (ModeMap
& DETACHONLY_MODE
) {
661 SHOW_PROGRESS(output
,"Detach storage driver as switching method ...\n");
662 ret
= detachDriver();
664 SHOW_PROGRESS(output
," You may want to remove the storage driver manually\n");
667 if(ModeMap
& HUAWEI_MODE
) {
670 if(ModeMap
& SIERRA_MODE
) {
673 if(ModeMap
& GCT_MODE
) {
677 if(ModeMap
& QISDA_MODE
) {
680 if(ModeMap
& KOBIL_MODE
) {
684 if(ModeMap
& QUANTA_MODE
) {
687 if(ModeMap
& SEQUANS_MODE
) {
690 if(ModeMap
& MOBILEACTION_MODE
) {
693 if(ModeMap
& CISCO_MODE
) {
697 if(ModeMap
& BLACKBERRY_MODE
) {
699 switchBlackberryMode();
701 if(ModeMap
& PANTECH_MODE
) {
706 SHOW_PROGRESS(output
,"Waiting for auto-switch of Pantech modem ...\n");
708 if(ModeMap
& SONY_MODE
) {
710 SHOW_PROGRESS(output
,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
711 CheckSuccess
= 0; /* separate and implied success control */
712 sonySuccess
= switchSonyMode();
716 SHOW_PROGRESS(output
,"Sending standard EJECT sequence\n");
718 if (MessageContent
[0] != '\0')
719 strcpy(MessageContent3
, MessageContent
);
721 MessageContent3
[0] = '\0';
723 strcpy(MessageContent
,"5553424387654321000000000000061e000000000000000000000000000000");
724 strcpy(MessageContent2
,"5553424397654321000000000000061b000000020000000000000000000000");
726 } else if (ModeMap
& HUAWEINEW_MODE
) {
727 SHOW_PROGRESS(output
,"Using standard Huawei switching message\n");
729 strcpy(MessageContent
,"55534243123456780000000000000011062000000101000100000000000000");
731 } else if (ModeMap
& OPTION_MODE
) {
732 SHOW_PROGRESS(output
,"Using standard Option switching message\n");
734 // strcpy(MessageContent,"55534243123456780100000080000601000000000000000000000000000000");
735 strcpy(MessageContent
,"55534243123456780000000000000601000000000000000000000000000000");
737 } else if (strlen(MessageContent
)) {
742 if (Configuration
> 0) {
743 if (currentConfigVal
!= Configuration
) {
744 if (switchConfiguration()) {
745 currentConfigVal
= get_current_config_value(dev
);
746 if (currentConfigVal
== Configuration
) {
747 SHOW_PROGRESS(output
,"The configuration was set successfully\n");
749 SHOW_PROGRESS(output
,"Changing the configuration has failed\n");
753 SHOW_PROGRESS(output
,"Target configuration %d found. Do nothing\n", currentConfigVal
);
757 if (AltSetting
!= -1) {
761 /* No "removal" check if these are set */
762 if ((Configuration
> 0 || AltSetting
> -1) && !ResetUSB
) {
772 if (searchMode
== SEARCH_BUSDEV
&& sysmode
) {
773 printf("ok:busdev\n");
779 if (checkSuccess()) {
784 if (TargetProduct
< 1)
785 printf("ok:no_data\n");
787 printf("ok:%04x:%04x\n", TargetVendor
, TargetProduct
);
793 if (ModeMap
& SONY_MODE
)
796 syslog(LOG_NOTICE
, "switched S.E. MD400 to modem mode");
797 printf("ok:\n"); /* ACM device, no driver action */
799 SHOW_PROGRESS(output
,"-> device should be stable now. Bye!\n\n");
803 SHOW_PROGRESS(output
,"-> switching was probably not completed. Bye!\n\n");
806 SHOW_PROGRESS(output
,"-> Run lsusb to note any changes. Bye!\n\n");
813 /* Get descriptor strings if available (identification details) */
814 void deviceDescription ()
816 char imanufact
[DESCR_MAX
], iproduct
[DESCR_MAX
], iserial
[DESCR_MAX
];
819 memset (imanufact
, ' ', DESCR_MAX
);
820 memset (iproduct
, ' ', DESCR_MAX
);
821 memset (iserial
, ' ', DESCR_MAX
);
823 struct libusb_device_descriptor descriptor
;
824 libusb_get_device_descriptor(dev
, &descriptor
);
826 int iManufacturer
= descriptor
.iManufacturer
;
827 int iProduct
= descriptor
.iProduct
;
828 int iSerialNumber
= descriptor
.iSerialNumber
;
831 ret
= libusb_get_string_descriptor_ascii(devh
, iManufacturer
, (unsigned char *)imanufact
, DESCR_MAX
);
833 fprintf(stderr
, "Error: could not get description string \"manufacturer\"\n");
834 strcpy(imanufact
, "read error");
837 strcpy(imanufact
, "not provided");
838 c
= strstr(imanufact
, " ");
840 memset((void*)c
, '\0', 1);
843 ret
= libusb_get_string_descriptor_ascii(devh
, iProduct
, (unsigned char *)iproduct
, DESCR_MAX
);
845 fprintf(stderr
, "Error: could not get description string \"product\"\n");
846 strcpy(iproduct
, "read error");
849 strcpy(iproduct
, "not provided");
850 c
= strstr(iproduct
, " ");
852 memset((void*)c
, '\0', 1);
855 ret
= libusb_get_string_descriptor_ascii(devh
, iSerialNumber
, (unsigned char *)iserial
, DESCR_MAX
);
857 fprintf(stderr
, "Error: could not get description string \"serial number\"\n");
858 strcpy(iserial
, "read error");
861 strcpy(iserial
, "not provided");
862 c
= strstr(iserial
, " ");
864 memset((void*)c
, '\0', 1);
865 fprintf(output
,"-------------------------\n");
866 fprintf(output
,"Manufacturer: %s\n", imanufact
);
867 fprintf(output
," Product: %s\n", iproduct
);
868 fprintf(output
," Serial No.: %s\n", iserial
);
869 fprintf(output
,"-------------------------\n");
873 /* Auxiliary function used by the wrapper */
874 int findMBIMConfig(int vendor
, int product
, int mode
)
876 struct libusb_device
**devs
;
880 if (libusb_get_device_list(ctx
, &devs
) < 0) {
881 perror("Libusb could not access USB. Abort");
885 SHOW_PROGRESS(output
,"Search USB devices ...\n");
886 while ((dev
= devs
[i
++]) != NULL
) {
887 struct libusb_device_descriptor descriptor
;
888 libusb_get_device_descriptor(dev
, &descriptor
);
890 if (mode
== SEARCH_BUSDEV
) {
891 if ((libusb_get_bus_number(dev
) != busnum
) ||
892 (libusb_get_device_address(dev
) != devnum
)) {
895 if (descriptor
.idVendor
!= vendor
)
897 if (product
!= descriptor
.idProduct
)
901 SHOW_PROGRESS(output
,"Found device, search for MBIM configuration...\n");
903 // No check if there is only one configuration
904 if (descriptor
.bNumConfigurations
< 2)
907 // Checking all interfaces of all configurations
908 for (j
=0; j
<descriptor
.bNumConfigurations
; j
++) {
909 struct libusb_config_descriptor
*config
;
911 libusb_get_config_descriptor(dev
, j
, &config
);
912 resultConfig
= config
->bConfigurationValue
;
913 for (i
=0; i
<config
->bNumInterfaces
; i
++) {
914 if ( config
->interface
[i
].altsetting
[0].bInterfaceClass
== 2 )
915 if ( config
->interface
[i
].altsetting
[0].bInterfaceSubClass
== 0x0e ) {
916 // found MBIM interface in this configuration
917 libusb_free_config_descriptor(config
);
921 libusb_free_config_descriptor(config
);
935 fprintf(output
,"Device handle empty, skip USB reset\n");
939 fprintf(output
,"Reset USB device ");
944 success
= libusb_reset_device(devh
);
945 if ( ((bpoint
% 10) == 0) && show_progress
) {
952 } while (success
< 0);
955 SHOW_PROGRESS(output
,"\n Device reset failed.\n");
957 SHOW_PROGRESS(output
,"\n Device was reset\n");
961 int switchSendMessage ()
963 const char* cmdHead
= "55534243";
966 msg
[0] = MessageContent
;
967 msg
[1] = MessageContent2
;
968 msg
[2] = MessageContent3
;
970 SHOW_PROGRESS(output
,"Set up interface %d\n", Interface
);
971 ret
= libusb_claim_interface(devh
, Interface
);
973 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip message sending\n", ret
);
976 libusb_clear_halt(devh
, MessageEndpoint
);
977 SHOW_PROGRESS(output
,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint
);
981 for (i
=0; i
<3; i
++) {
982 if ( strlen(msg
[i
]) == 0)
985 if ( sendMessage(msg
[i
], i
+1) )
988 if ( strstr(msg
[i
],cmdHead
) != NULL
) {
990 SHOW_PROGRESS(output
,"Read the response to message %d (CSW) ...\n", i
+1);
991 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
993 // Other bulk transfer
994 SHOW_PROGRESS(output
,"Read the response to message %d ...\n", i
+1);
995 ret
= read_bulk(ResponseEndpoint
, ByteString
, strlen(msg
[i
])/2 );
1001 SHOW_PROGRESS(output
,"Reset response endpoint 0x%02x\n", ResponseEndpoint
);
1002 ret
= libusb_clear_halt(devh
, ResponseEndpoint
);
1004 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1005 SHOW_PROGRESS(output
,"Reset message endpoint 0x%02x\n", MessageEndpoint
);
1006 ret
= libusb_clear_halt(devh
, MessageEndpoint
);
1008 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1012 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1013 usleep(ReleaseDelay
*1000);
1015 ret
= libusb_release_interface(devh
, Interface
);
1021 SHOW_PROGRESS(output
," Device is gone, skip any further commands\n");
1028 int switchConfiguration ()
1030 int ret
, count
= SWITCH_CONFIG_MAXTRIES
;
1032 SHOW_PROGRESS(output
,"Change configuration to %i ...\n", Configuration
);
1033 while (((ret
= libusb_set_configuration(devh
, Configuration
)) < 0) && --count
) {
1034 SHOW_PROGRESS(output
," Device is busy, try to detach kernel driver\n");
1038 SHOW_PROGRESS(output
," Changing the configuration failed (error %d). Try to continue\n", ret
);
1041 SHOW_PROGRESS(output
," OK, configuration set\n");
1047 int switchAltSetting ()
1050 SHOW_PROGRESS(output
,"Change to alt setting %i ...\n", AltSetting
);
1051 ret
= libusb_claim_interface(devh
, Interface
);
1053 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip AltSetting\n", ret
);
1056 ret
= libusb_set_interface_alt_setting(devh
, Interface
, AltSetting
);
1057 libusb_release_interface(devh
, Interface
);
1059 SHOW_PROGRESS(output
," Change to alt setting returned error %d. Try to continue\n", ret
);
1066 void switchHuaweiMode ()
1069 SHOW_PROGRESS(output
,"Send old Huawei control message ...\n");
1070 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_STANDARD
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1071 LIBUSB_REQUEST_SET_FEATURE
, 00000001, 0, buffer
, 0, 1000);
1074 fprintf(stderr
, "Error: Huawei control message failed (error %d). Abort\n\n", ret
);
1080 void switchSierraMode ()
1083 SHOW_PROGRESS(output
,"Send Sierra control message\n");
1084 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1085 LIBUSB_REQUEST_SET_INTERFACE
, 00000001, 0, buffer
, 0, 1000);
1086 if (ret
== LIBUSB_ERROR_PIPE
) {
1087 SHOW_PROGRESS(output
," communication with device stopped. May have switched modes anyway\n");
1091 fprintf(stderr
, "Error: Sierra control message failed (error %d). Abort\n\n", ret
);
1097 void switchGCTMode ()
1100 ret
= libusb_claim_interface(devh
, Interface
);
1102 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip GCT sequence\n", ret
);
1105 SHOW_PROGRESS(output
,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d",
1106 LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
);
1108 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
,
1109 0xa0, 0, Interface
, buffer
, 1, 1000);
1112 SHOW_PROGRESS(output
," GCT control message 1 failed (error %d), continue anyway ...\n", ret
);
1114 SHOW_PROGRESS(output
,"Send GCT control message 2 ...\n");
1115 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
,
1116 0xfe, 0, Interface
, buffer
, 1, 1000);
1119 SHOW_PROGRESS(output
," GCT control message 2 failed (error %d). Abort\n\n", ret
);
1121 libusb_release_interface(devh
, Interface
);
1127 void switchKobilMode() {
1129 SHOW_PROGRESS(output
,"Send Kobil control message ...\n");
1130 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1131 0x88, 0, 0, buffer
, 8, 1000);
1134 fprintf(stderr
, "Error: Kobil control message failed (error %d). Abort\n\n", ret
);
1140 void switchQisdaMode () {
1142 SHOW_PROGRESS(output
,"Sending Qisda control message ...\n");
1143 memcpy(buffer
, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1144 ret
= libusb_control_transfer(devh
, 0x40, 0x04, 0, 0, buffer
, 16, 1000);
1146 fprintf(stderr
, "Error: Qisda control message failed (error %d). Abort\n\n", ret
);
1152 void switchQuantaMode() {
1154 SHOW_PROGRESS(output
,"Send Quanta control message ...\n");
1155 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1156 0xff, 0, 0, buffer
, 0, 1000);
1159 SHOW_PROGRESS(output
,"Error: Quanta control message failed (error %d). Abort\n\n", ret
);
1165 void switchBlackberryMode ()
1168 SHOW_PROGRESS(output
,"Send Blackberry control message 1 ...\n");
1169 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1170 0xb1, 0x0000, 0, buffer
, 8, 1000);
1173 fprintf(stderr
, "Error: Blackberry control message 1 failed (result %d)\n", ret
);
1175 SHOW_PROGRESS(output
,"Send Blackberry control message 2 ...\n");
1176 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1177 0xa9, 0x000e, 0, buffer
, 2, 1000);
1180 fprintf(stderr
, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret
);
1186 void switchPantechMode()
1189 SHOW_PROGRESS(output
,"Send Pantech control message, wValue %d ...\n", PantechMode
);
1190 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1191 0x70, PantechMode
, 0, buffer
, 0, 1000);
1194 SHOW_PROGRESS(output
," Error: Pantech control message failed (error %d). Abort\n\n", ret
);
1204 #define MOBILE_ACTION_READLOOP1 63
1205 #define MOBILE_ACTION_READLOOP2 73
1207 /* The code here is statically derived from sniffing (and confirmed working).
1208 * However I bet it could be simplified significantly.
1211 void switchActionMode ()
1214 SHOW_PROGRESS(output
,"Send MobileAction control sequence ...\n");
1215 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1216 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_OUT
,
1217 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1219 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1220 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_OUT
,
1221 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1223 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1224 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1225 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1226 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1227 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1228 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1229 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1230 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1231 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1232 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1233 for (i
=0; i
< MOBILE_ACTION_READLOOP1
; i
++) {
1234 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1236 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1237 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1238 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1239 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1240 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1241 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1242 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1243 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1244 for (i
=0; i
< MOBILE_ACTION_READLOOP2
; i
++) {
1245 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1247 memcpy(buffer
, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE
);
1248 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1249 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1250 memcpy(buffer
, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE
);
1251 ret
= usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1252 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1254 SHOW_PROGRESS(output
," MobileAction control sequence did not complete\n Last error was %d\n",ret
);
1256 SHOW_PROGRESS(output
," MobileAction control sequence complete\n");
1261 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1262 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1264 #define SQN_DEFAULT_DEVICE_MODE 0x00
1265 #define SQN_MASS_STORAGE_MODE 0x01
1266 #define SQN_CUSTOM_DEVICE_MODE 0x02
1268 void switchSequansMode()
1272 SHOW_PROGRESS(output
,"Send Sequans control message\n");
1273 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1274 SQN_SET_DEVICE_MODE_REQUEST
, SQN_CUSTOM_DEVICE_MODE
, 0, buffer
, 0, 1000);
1277 fprintf(stderr
, "Error: Sequans request failed (error %d). Abort\n\n", ret
);
1283 void switchCiscoMode()
1288 msg
[0] = "55534243f83bcd810002000080000afd000000030000000100000000000000";
1289 msg
[1] = "55534243984300820002000080000afd000000070000000100000000000000";
1290 msg
[2] = "55534243984300820000000000000afd000100071000000000000000000000";
1291 msg
[3] = "55534243984300820002000080000afd000200230000000100000000000000";
1292 msg
[4] = "55534243984300820000000000000afd000300238200000000000000000000";
1293 msg
[5] = "55534243984300820002000080000afd000200260000000100000000000000";
1294 msg
[6] = "55534243984300820000000000000afd00030026c800000000000000000000";
1295 msg
[7] = "55534243d84c04820002000080000afd000010730000000100000000000000";
1296 msg
[8] = "55534243d84c04820002000080000afd000200240000000100000000000000";
1297 msg
[9] = "55534243d84c04820000000000000afd000300241300000000000000000000";
1298 msg
[10] = "55534243d84c04820000000000000afd000110732400000000000000000000";
1300 SHOW_PROGRESS(output
,"Set up Cisco interface %d\n", Interface
);
1301 ret
= libusb_claim_interface(devh
, Interface
);
1303 SHOW_PROGRESS(output
," Could not claim interface (error %d). Abort\n", ret
);
1306 // libusb_clear_halt(devh, MessageEndpoint);
1310 // ret = read_bulk(ResponseEndpoint, ByteString, 13);
1311 // SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret);
1313 for (i
=0; i
<11; i
++) {
1314 if ( sendMessage(msg
[i
], i
+1) )
1317 for (j
=1; j
<4; j
++) {
1319 SHOW_PROGRESS(output
," Read the CSW for bulk message %d (attempt %d) ...\n",i
+1,j
);
1320 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1328 libusb_clear_halt(devh
, MessageEndpoint
);
1329 libusb_clear_halt(devh
, ResponseEndpoint
);
1331 ReleaseDelay
= 2000;
1333 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1334 usleep(ReleaseDelay
*1000);
1336 ret
= libusb_release_interface(devh
, Interface
);
1342 SHOW_PROGRESS(output
,"Device returned error %d, skip further commands\n", ret
);
1348 int switchSonyMode ()
1357 SHOW_PROGRESS(output
,"Send Sony control message\n");
1358 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1359 0x11, 2, 0, buffer
, 3, 100);
1362 fprintf(stderr
, "Error: Sony control message failed (error %d). Abort\n\n", ret
);
1365 SHOW_PROGRESS(output
," OK, control message sent, wait for device to return ...\n");
1370 /* Now waiting for the device to reappear */
1375 while ( dev
== 0 && i
< 30 ) {
1377 dev
= search_devices(&found
, DefaultVendor
, DefaultProductList
, TargetClass
, 0, SEARCH_TARGET
);
1382 if (show_progress
) {
1383 fprintf(output
,"#");
1388 SHOW_PROGRESS(output
,"\n After %d seconds:",i
);
1390 SHOW_PROGRESS(output
," device came back, proceed\n");
1391 libusb_open(dev
, &devh
);
1393 fprintf(stderr
, "Error: could not get handle on device\n");
1397 SHOW_PROGRESS(output
," device still gone, abort\n");
1402 SHOW_PROGRESS(output
,"Send Sony control message again ...\n");
1403 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1404 0x11, 2, 0, buffer
, 3, 100);
1407 fprintf(stderr
, "Error: Sony control message (2) failed (error %d)\n", ret
);
1410 SHOW_PROGRESS(output
," OK, control message sent\n");
1421 SHOW_PROGRESS(output
,"Looking for active driver ...\n");
1422 ret
= libusb_kernel_driver_active(devh
, 0);
1423 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1424 fprintf(output
," Can't do driver detection on this platform.\n");
1428 fprintf(output
," Driver check failed with error %d. Try to continue\n", ret
);
1432 SHOW_PROGRESS(output
," No active driver found. Detached before or never attached\n");
1436 ret
= libusb_detach_kernel_driver(devh
, Interface
);
1437 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1438 fprintf(output
," Can't do driver detaching on this platform.\n");
1442 SHOW_PROGRESS(output
," OK, driver detached\n");
1444 SHOW_PROGRESS(output
," Driver detach failed (error %d). Try to continue\n", ret
);
1449 int sendMessage(char* message
, int count
)
1451 int ret
, message_length
;
1453 if (strlen(message
) % 2 != 0) {
1454 fprintf(stderr
, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count
);
1457 message_length
= strlen(message
) / 2;
1458 if ( hexstr2bin(message
, ByteString
, message_length
) == -1) {
1459 fprintf(stderr
, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n",
1460 count
, MessageContent
);
1464 SHOW_PROGRESS(output
,"Trying to send message %d to endpoint 0x%02x ...\n", count
, MessageEndpoint
);
1466 ret
= write_bulk(MessageEndpoint
, ByteString
, message_length
);
1467 if (ret
== LIBUSB_ERROR_NO_DEVICE
)
1477 int newTargetCount
, success
=0;
1479 SHOW_PROGRESS(output
,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess
);
1482 /* If target parameters are given, don't check for vanished device
1483 * Changed for Cisco AM10 where a new device is added while the install
1484 * storage device stays active
1486 if ((TargetVendor
|| TargetClass
) && devh
) {
1491 /* if target ID is not given but target class is, assign default as target;
1492 * it will be needed for sysmode output
1494 if (!TargetVendor
&& TargetClass
) {
1495 TargetVendor
= DefaultVendor
;
1496 TargetProduct
= DefaultProduct
;
1499 /* devh is 0 if device vanished during command transmission or if target params were given
1502 for (i
=0; i
< CheckSuccess
; i
++) {
1504 /* Test if default device still can be accessed; positive result does
1505 * not necessarily mean failure
1507 SHOW_PROGRESS(output
," Wait for original device to vanish ...\n");
1509 ret
= libusb_claim_interface(devh
, Interface
);
1510 libusb_release_interface(devh
, Interface
);
1512 SHOW_PROGRESS(output
," Original device can't be accessed anymore. Good.\n");
1517 if (i
== CheckSuccess
-1) {
1518 SHOW_PROGRESS(output
," Original device still present after the timeout\n\n"
1519 "Mode switch most likely failed. Bye!\n\n");
1524 if ( TargetVendor
&& (TargetProduct
> -1 || TargetProductList
[0] != '\0') ) {
1526 /* Recount target devices (compare with previous count) if target data is given.
1527 * Target device on the same bus with higher device number is returned,
1528 * description is read for syslog message
1530 for (i
=i
; i
< CheckSuccess
; i
++) {
1531 SHOW_PROGRESS(output
," Search for target devices ...\n");
1532 dev
= search_devices(&newTargetCount
, TargetVendor
, TargetProductList
, TargetClass
,
1535 if (dev
&& (newTargetCount
> targetDeviceCount
)) {
1537 libusb_open(dev
, &devh
);
1538 fprintf(output
,"\nFound target device %03d on bus %03d\n",
1539 libusb_get_device_address(dev
), libusb_get_bus_number(dev
));
1541 fprintf(output
,"\nTarget device description data\n");
1542 deviceDescription();
1546 SHOW_PROGRESS(output
," Found correct target device\n\n"
1547 "Mode switch succeeded. Bye!\n\n");
1552 if (i
== CheckSuccess
-1) {
1553 SHOW_PROGRESS(output
," No new devices in target mode or class found\n\n"
1554 "Mode switch has failed. Bye!\n\n");
1559 /* No target data given, rely on the vanished device */
1561 SHOW_PROGRESS(output
," (For a better success check provide target IDs or class)\n");
1562 SHOW_PROGRESS(output
," Original device vanished after switching\n\n"
1563 "Mode switch most likely succeeded. Bye!\n\n");
1570 syslog(LOG_NOTICE
, "switched to new device, but hit libusb1 bug");
1576 syslog(LOG_NOTICE
, "switched to %04x:%04x on %03d/%03d", TargetVendor
,
1577 TargetProduct
, busnum
, devnum
);
1583 syslog(LOG_NOTICE
, "device seems to have switched");
1595 int write_bulk(int endpoint
, unsigned char *message
, int length
)
1597 int ret
= usb_bulk_io(devh
, endpoint
, message
, length
, 3000);
1599 SHOW_PROGRESS(output
," OK, message successfully sent\n");
1601 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1602 SHOW_PROGRESS(output
," Device seems to have vanished right after sending. Good.\n");
1604 SHOW_PROGRESS(output
," Sending the message returned error %d. Try to continue\n", ret
);
1610 int read_bulk(int endpoint
, unsigned char *buffer
, int length
)
1612 int ret
= usb_bulk_io(devh
, endpoint
, buffer
, length
, 3000);
1614 SHOW_PROGRESS(output
," Response successfully read (%d bytes).\n", ret
);
1616 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1617 SHOW_PROGRESS(output
," Device seems to have vanished after reading. Good.\n");
1619 SHOW_PROGRESS(output
," Response reading failed (error %d)\n", ret
);
1625 void release_usb_device(int __attribute__((unused
)) dummy
)
1627 SHOW_PROGRESS(output
,"Program cancelled by system. Bye!\n\n");
1629 libusb_release_interface(devh
, Interface
);
1636 /* Iterates over busses and devices, counts the ones which match the given
1637 * parameters and returns the last one of them
1639 struct libusb_device
* search_devices( int *numFound
, int vendor
, char* productList
,
1640 int targetClass
, int configuration
, int mode
)
1642 char *listcopy
=NULL
, *token
;
1643 unsigned char buffer
[2];
1644 int devClass
, product
;
1645 struct libusb_device
* right_dev
= NULL
;
1646 // struct libusb_device_handle *testdevh;
1647 struct libusb_device
**devs
;
1650 /* only target class given, target vendor and product assumed unchanged */
1651 if ( targetClass
&& !(vendor
|| strlen(productList
)) ) {
1652 vendor
= DefaultVendor
;
1653 productList
= DefaultProductList
;
1658 if (!vendor
|| productList
== '\0')
1661 listcopy
= malloc(strlen(productList
)+1);
1663 if (libusb_get_device_list(ctx
, &devs
) < 0) {
1664 perror("Libusb failed to get USB access!");
1668 while ((dev
= devs
[i
++]) != NULL
) {
1669 struct libusb_device_descriptor descriptor
;
1670 libusb_get_device_descriptor(dev
, &descriptor
);
1672 if (mode
== SEARCH_BUSDEV
) {
1673 if ((libusb_get_bus_number(dev
) != busnum
) ||
1674 (libusb_get_device_address(dev
) != devnum
))
1677 SHOW_PROGRESS(output
," bus/device number matched\n");
1681 fprintf (output
," found USB ID %04x:%04x\n",
1682 descriptor
.idVendor
, descriptor
.idProduct
);
1683 if (descriptor
.idVendor
!= vendor
)
1686 fprintf (output
," vendor ID matched\n");
1688 strcpy(listcopy
, productList
);
1689 token
= strtok(listcopy
, ",");
1690 while (token
!= NULL
) {
1691 if (strlen(token
) != 4) {
1692 SHOW_PROGRESS(output
,"Error: entry in product ID list has wrong length: %s. "
1693 "Ignored\n", token
);
1697 if ( hexstr2bin(token
, buffer
, strlen(token
)/2) == -1) {
1698 SHOW_PROGRESS(output
,"Error: entry in product ID list is not a hex string: %s. "
1699 "Ignored\n", token
);
1704 product
+= (unsigned char)buffer
[0];
1706 product
+= (unsigned char)buffer
[1];
1707 if (product
== descriptor
.idProduct
) {
1708 SHOW_PROGRESS(output
," product ID matched\n");
1710 if (targetClass
!= 0) {
1711 // TargetClass is set, check class of first interface
1712 struct libusb_device_descriptor descriptor
;
1713 libusb_get_device_descriptor(dev
, &descriptor
);
1714 devClass
= descriptor
.bDeviceClass
;
1715 struct libusb_config_descriptor
*config
;
1716 libusb_get_config_descriptor(dev
, 0, &config
);
1717 int ifaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
1718 libusb_free_config_descriptor(config
);
1720 devClass
= ifaceClass
;
1722 /* Check for some quirky devices */
1723 if (devClass
!= ifaceClass
)
1724 devClass
= ifaceClass
;
1725 if (devClass
== targetClass
) {
1727 fprintf (output
," target class %02x matches\n", targetClass
);
1728 if (mode
== SEARCH_TARGET
) {
1732 fprintf (output
," count device\n");
1735 fprintf (output
," device not counted, target class reached\n");
1738 fprintf (output
," device class %02x not matching target\n", devClass
);
1739 if (mode
== SEARCH_DEFAULT
|| mode
== SEARCH_BUSDEV
) {
1743 fprintf (output
," count device\n");
1746 } else if (configuration
> 0) {
1747 // Configuration parameter is set, check device configuration
1748 int testconfig
= get_current_config_value(dev
);
1749 if (testconfig
!= configuration
) {
1751 fprintf (output
," device configuration %d not matching target\n",
1757 fprintf (output
," count device\n");
1760 fprintf (output
," device not counted, target configuration reached\n");
1762 // Neither TargetClass nor Configuration are set
1765 if (mode
== SEARCH_BUSDEV
)
1771 token
= strtok(NULL
, ",");
1774 if (listcopy
!= NULL
)
1780 /* Autodetect bulk endpoints (ab) */
1782 int find_first_bulk_endpoint(int direction
)
1785 const struct libusb_interface_descriptor
*alt
;
1786 const struct libusb_endpoint_descriptor
*ep
;
1788 for (j
=0; j
< active_config
->bNumInterfaces
; j
++) {
1789 alt
= &(active_config
->interface
[j
].altsetting
[0]);
1790 if (alt
->bInterfaceNumber
== Interface
) {
1791 for (i
=0; i
< alt
->bNumEndpoints
; i
++) {
1792 ep
= &(alt
->endpoint
[i
]);
1793 if ( ( (ep
->bmAttributes
& LIBUSB_ENDPOINT_ADDRESS_MASK
) == LIBUSB_TRANSFER_TYPE_BULK
)
1794 && ( (ep
->bEndpointAddress
& LIBUSB_ENDPOINT_DIR_MASK
) == direction
) ) {
1796 return ep
->bEndpointAddress
;
1805 int get_current_config_value()
1807 SHOW_PROGRESS(output
,"Get the current device configuration ...\n");
1808 if (active_config
!= NULL
) {
1809 libusb_free_config_descriptor(active_config
);
1810 active_config
= NULL
;
1812 int ret
= libusb_get_active_config_descriptor(dev
, &active_config
);
1814 SHOW_PROGRESS(output
," Determining the active configuration failed (error %d). Abort\n", ret
);
1817 return active_config
->bConfigurationValue
;
1821 int get_interface_class()
1824 for (i
=0; i
< active_config
->bNumInterfaces
; i
++) {
1825 if (active_config
->interface
[i
].altsetting
[0].bInterfaceNumber
== Interface
)
1826 return active_config
->interface
[i
].altsetting
[0].bInterfaceClass
;
1832 /* Parameter parsing */
1834 char* ReadParseParam(const char* FileName
, char *VariableName
)
1836 static int numLines
= 0;
1837 static char* ConfigBuffer
[MAXLINES
];
1838 char *VarName
, *Comment
=NULL
, *Equal
=NULL
;
1839 char *FirstQuote
, *LastQuote
, *P1
, *P2
;
1841 unsigned Len
=0, Pos
=0;
1842 char Str
[LINE_DIM
], *token
, *configPos
;
1845 // Reading and storing input during the first call
1847 if (strncmp(FileName
,"##",2) == 0) {
1848 if (verbose
) fprintf(output
,"\nRead long config from command line\n");
1849 // "Embedded" configuration data
1850 configPos
= (char*)FileName
;
1851 token
= strtok(configPos
, "\n");
1852 strncpy(Str
,token
,LINE_DIM
-1);
1854 if (strcmp(FileName
, "stdin")==0) {
1855 if (verbose
) fprintf(output
,"\nRead long config from stdin\n");
1858 if (verbose
) fprintf(output
,"\nRead config file: %s\n", FileName
);
1859 file
=fopen(FileName
, "r");
1862 fprintf(stderr
, "Error: Could not find file %s. Abort\n\n", FileName
);
1865 token
= fgets(Str
, LINE_DIM
-1, file
);
1868 while (token
!= NULL
&& numLines
< MAXLINES
) {
1873 if (Str
[Len
-1]=='\n' or Str
[Len
-1]=='\r')
1875 Equal
= strchr (Str
, '='); // search for equal sign
1876 Pos
= strcspn (Str
, ";#!"); // search for comment
1877 Comment
= (Pos
==Len
) ? NULL
: Str
+Pos
;
1878 if (Equal
==NULL
or ( Comment
!=NULL
and Comment
<=Equal
))
1879 goto NextLine
; // Comment or irrelevant, don't save
1881 ConfigBuffer
[numLines
] = malloc(Len
*sizeof(char));
1882 strcpy(ConfigBuffer
[numLines
],Str
);
1886 token
= strtok(NULL
, "\n");
1888 strncpy(Str
,token
,LINE_DIM
-1);
1890 token
= fgets(Str
, LINE_DIM
-1, file
);
1896 // Now checking for parameters
1898 while (Line
< numLines
) {
1899 strcpy(Str
,ConfigBuffer
[Line
]);
1900 Equal
= strchr (Str
, '='); // search for equal sign
1904 FirstQuote
=strchr (Equal
, '"'); // search for double quote char
1905 LastQuote
=strrchr (Equal
, '"');
1906 if (FirstQuote
!=NULL
) {
1907 if (LastQuote
==NULL
) {
1908 fprintf(stderr
, "Error reading parameters from file %s - "
1909 "Missing end quote:\n%s\n", FileName
, Str
);
1913 *FirstQuote
=*LastQuote
='\0';
1917 // removes leading/trailing spaces
1918 Pos
=strspn (Str
, " \t");
1919 if (Pos
==strlen(Str
)) {
1920 fprintf(stderr
, "Error reading parameters from file %s - "
1921 "Missing variable name:\n%s\n", FileName
, Str
);
1925 while ((P1
=strrchr(Str
, ' '))!=NULL
or (P2
=strrchr(Str
, '\t'))!=NULL
)
1926 if (P1
!=NULL
) *P1
='\0';
1927 else if (P2
!=NULL
) *P2
='\0';
1930 Pos
=strspn (Equal
, " \t");
1931 if (Pos
==strlen(Equal
)) {
1932 fprintf(stderr
, "Error reading parameter from file %s - "
1933 "Missing value:\n%s\n", FileName
, Str
);
1939 if (strcmp(VarName
, VariableName
)==0) { // Found it
1952 if (c
>= '0' && c
<= '9')
1954 if (c
>= 'a' && c
<= 'f')
1955 return c
- 'a' + 10;
1956 if (c
>= 'A' && c
<= 'F')
1957 return c
- 'A' + 10;
1962 int hex2byte(const char *hex
)
1965 a
= hex2num(*hex
++);
1968 b
= hex2num(*hex
++);
1971 return (a
<< 4) | b
;
1975 int hexstr2bin(const char *hex
, unsigned char *buffer
, int len
)
1979 const char *ipos
= hex
;
1980 unsigned char *opos
= buffer
;
1982 for (i
= 0; i
< len
; i
++) {
1986 *opos
++ = (unsigned char) a
;
1996 libusb_free_config_descriptor(active_config
);
1999 // libusb_exit will crash on Raspbian 7, crude protection
2017 char* version
= VERSION
;
2018 fprintf(output
,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
2019 " * Version %s (C) Josua Dietze 2015\n"
2020 " * Based on libusb1/libusbx\n\n"
2021 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version
);
2027 fprintf(output
,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
2028 " -h, --help this help\n"
2029 " -e, --version print version information and exit\n"
2030 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
2031 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
2032 " -p, --default-product NUM product ID of original mode (mandatory)\n"
2033 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
2034 " -P, --target-product NUM target mode product ID (optional)\n"
2035 " -C, --target-class NUM target mode device class (optional)\n"
2036 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
2037 " -g, --device-num NUM system device number (for hard ID)\n"
2038 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
2039 " -M, --message-content <msg> message to send (hex number as string)\n"
2040 " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n"
2041 " -w, --release-delay NUM wait NUM ms before releasing the interface\n"
2042 " -n, --need-response obsolete, no effect (always on)\n"
2043 " -r, --response-endpoint NUM read response from there (optional)\n"
2044 " -K, --std-eject send standard EJECT sequence\n"
2045 " -d, --detach-only detach the active driver, no further action\n"
2046 " -H, --huawei-mode apply a special procedure\n"
2047 " -J, --huawei-new-mode apply a special procedure\n"
2048 " -S, --sierra-mode apply a special procedure\n"
2049 " -O, --sony-mode apply a special procedure\n"
2050 " -G, --gct-mode apply a special procedure\n"
2051 " -N, --sequans-mode apply a special procedure\n"
2052 " -A, --mobileaction-mode apply a special procedure\n"
2053 " -T, --kobil-mode apply a special procedure\n"
2054 " -L, --cisco-mode apply a special procedure\n"
2055 " -B, --qisda-mode apply a special procedure\n"
2056 " -E, --quanta-mode apply a special procedure\n"
2057 " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n"
2058 " -Z, --blackberry-mode apply a special procedure\n"
2059 " -U, --option-mode apply a special procedure\n"
2060 " -R, --reset-usb reset the device after all other actions\n"
2061 " -Q, --quiet don't show progress or error messages\n"
2062 " -W, --verbose print all settings and debug output\n"
2063 " -D, --sysmode specific result and syslog message\n"
2064 " -s, --success <seconds> switching result check with timeout\n"
2065 " -I, --inquire obsolete, no effect\n\n"
2066 " -c, --config-file <filename> load long configuration from file\n\n"
2067 " -t, --stdinput read long configuration from stdin\n\n"
2068 " -f, --long-config <text> get long configuration from string\n\n"
2069 " -i, --interface NUM select initial USB interface (default 0)\n"
2070 " -u, --configuration NUM select USB configuration\n"
2071 " -a, --altsetting NUM select alternative USB interface setting\n\n");