2 Mode switching tool for controlling mode of 'multi-state' USB devices
3 Version 2.4.0, 2016/06/12
5 Copyright (C) 2007 - 2016 Josua Dietze (mail to "usb_admin" 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.4.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
103 #define BUF_SIZE 4096
104 #define DESCR_MAX 129
106 #define SEARCH_DEFAULT 0
107 #define SEARCH_TARGET 1
108 #define SEARCH_BUSDEV 2
110 #define SWITCH_CONFIG_MAXTRIES 5
112 #define SHOW_PROGRESS if (show_progress) fprintf
116 static struct libusb_context
*ctx
= NULL
;
117 static struct libusb_device
*dev
= NULL
;
118 static struct libusb_device_handle
*devh
= NULL
;
119 static struct libusb_config_descriptor
*active_config
= NULL
;
121 int DefaultVendor
=0, DefaultProduct
=0, TargetVendor
=0, TargetProduct
=-1, TargetClass
=0;
122 int MessageEndpoint
=0, ResponseEndpoint
=0, ReleaseDelay
=0;
123 int targetDeviceCount
=0, searchMode
;
124 int devnum
=-1, busnum
=-1;
126 unsigned int ModeMap
= 0;
127 #define DETACHONLY_MODE 0x00000001
128 #define HUAWEI_MODE 0x00000002
129 #define SIERRA_MODE 0x00000004
130 #define SONY_MODE 0x00000008
131 #define GCT_MODE 0x00000010
132 #define KOBIL_MODE 0x00000020
133 #define SEQUANS_MODE 0x00000040
134 #define MOBILEACTION_MODE 0x00000080
135 #define CISCO_MODE 0x00000100
136 #define QISDA_MODE 0x00000200
137 #define QUANTA_MODE 0x00000400
138 #define BLACKBERRY_MODE 0x00000800
139 #define PANTECH_MODE 0x00001000
140 #define HUAWEINEW_MODE 0x00002000
141 #define OPTION_MODE 0x00004000
145 char verbose
=0, show_progress
=1, ResetUSB
=0, CheckSuccess
=0, config_read
=0;
146 char NoDriverLoading
=0, sysmode
=0, mbim
=0;
147 char StandardEject
=0;
149 char MessageContent
[LINE_DIM
];
150 char MessageContent2
[LINE_DIM
];
151 char MessageContent3
[LINE_DIM
];
152 char TargetProductList
[LINE_DIM
];
153 char DefaultProductList
[5];
154 unsigned char ByteString
[LINE_DIM
/2];
155 unsigned char buffer
[BUF_SIZE
];
156 char **Messages
= NULL
;
161 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
162 int Interface
= -1, Configuration
= 0, AltSetting
= -1;
165 static struct option long_options
[] = {
166 {"help", no_argument
, 0, 'h'},
167 {"version", no_argument
, 0, 'e'},
168 {"default-vendor", required_argument
, 0, 'v'},
169 {"default-product", required_argument
, 0, 'p'},
170 {"target-vendor", required_argument
, 0, 'V'},
171 {"target-product", required_argument
, 0, 'P'},
172 {"target-class", required_argument
, 0, 'C'},
173 {"message-endpoint", required_argument
, 0, 'm'},
174 {"message-content", required_argument
, 0, 'M'},
175 {"message-content2", required_argument
, 0, '2'},
176 {"message-content3", required_argument
, 0, '3'},
177 {"release-delay", required_argument
, 0, 'w'},
178 {"response-endpoint", required_argument
, 0, 'r'},
179 {"bus-num", required_argument
, 0, 'b'},
180 {"device-num", required_argument
, 0, 'g'},
181 {"detach-only", no_argument
, 0, 'd'},
182 {"huawei-mode", no_argument
, 0, 'H'},
183 {"huawei-new-mode", no_argument
, 0, 'J'},
184 {"sierra-mode", no_argument
, 0, 'S'},
185 {"sony-mode", no_argument
, 0, 'O'},
186 {"qisda-mode", no_argument
, 0, 'B'},
187 {"quanta-mode", no_argument
, 0, 'E'},
188 {"kobil-mode", no_argument
, 0, 'T'},
189 {"gct-mode", no_argument
, 0, 'G'},
190 {"sequans-mode", no_argument
, 0, 'N'},
191 {"mobileaction-mode", no_argument
, 0, 'A'},
192 {"cisco-mode", no_argument
, 0, 'L'},
193 {"blackberry-mode", no_argument
, 0, 'Z'},
194 {"option-mode", no_argument
, 0, 'U'},
195 {"pantech-mode", required_argument
, 0, 'F'},
196 {"std-eject", no_argument
, 0, 'K'},
197 {"need-response", no_argument
, 0, 'n'},
198 {"reset-usb", no_argument
, 0, 'R'},
199 {"config-file", required_argument
, 0, 'c'},
200 {"verbose", no_argument
, 0, 'W'},
201 {"quiet", no_argument
, 0, 'Q'},
202 {"sysmode", no_argument
, 0, 'D'},
203 {"inquire", no_argument
, 0, 'I'},
204 {"stdinput", no_argument
, 0, 't'},
205 {"find-mbim", no_argument
, 0, 'j'},
206 {"long-config", required_argument
, 0, 'f'},
207 {"check-success", required_argument
, 0, 's'},
208 {"interface", required_argument
, 0, 'i'},
209 {"configuration", required_argument
, 0, 'u'},
210 {"altsetting", required_argument
, 0, 'a'},
215 void readConfigFile(const char *configFilename
)
217 ParseParamHex(configFilename
, TargetVendor
);
218 ParseParamHex(configFilename
, TargetProduct
);
219 ParseParamString(configFilename
, TargetProductList
);
220 ParseParamHex(configFilename
, TargetClass
);
221 ParseParamHex(configFilename
, DefaultVendor
);
222 ParseParamHex(configFilename
, DefaultProduct
);
223 ParseParamBoolMap(configFilename
, DetachStorageOnly
, ModeMap
, DETACHONLY_MODE
);
224 ParseParamBoolMap(configFilename
, HuaweiMode
, ModeMap
, HUAWEI_MODE
);
225 ParseParamBoolMap(configFilename
, HuaweiNewMode
, ModeMap
, HUAWEINEW_MODE
);
226 ParseParamBoolMap(configFilename
, SierraMode
, ModeMap
, SIERRA_MODE
);
227 ParseParamBoolMap(configFilename
, SonyMode
, ModeMap
, SONY_MODE
);
228 ParseParamBoolMap(configFilename
, GCTMode
, ModeMap
, GCT_MODE
);
229 ParseParamBoolMap(configFilename
, KobilMode
, ModeMap
, KOBIL_MODE
);
230 ParseParamBoolMap(configFilename
, SequansMode
, ModeMap
, SEQUANS_MODE
);
231 ParseParamBoolMap(configFilename
, MobileActionMode
, ModeMap
, MOBILEACTION_MODE
);
232 ParseParamBoolMap(configFilename
, CiscoMode
, ModeMap
, CISCO_MODE
);
233 ParseParamBoolMap(configFilename
, QisdaMode
, ModeMap
, QISDA_MODE
);
234 ParseParamBoolMap(configFilename
, QuantaMode
, ModeMap
, QUANTA_MODE
);
235 ParseParamBoolMap(configFilename
, OptionMode
, ModeMap
, OPTION_MODE
);
236 ParseParamBoolMap(configFilename
, BlackberryMode
, ModeMap
, BLACKBERRY_MODE
);
237 ParseParamInt(configFilename
, PantechMode
);
239 ModeMap
|= PANTECH_MODE
;
240 ParseParamBool(configFilename
, StandardEject
);
241 ParseParamBool(configFilename
, NoDriverLoading
);
242 ParseParamHex(configFilename
, MessageEndpoint
);
243 ParseParamString(configFilename
, MessageContent
);
244 ParseParamString(configFilename
, MessageContent2
);
245 ParseParamString(configFilename
, MessageContent3
);
246 ParseParamInt(configFilename
, ReleaseDelay
);
247 ParseParamHex(configFilename
, ResponseEndpoint
);
248 ParseParamHex(configFilename
, ResetUSB
);
249 ParseParamInt(configFilename
, CheckSuccess
);
250 ParseParamHex(configFilename
, Interface
);
251 ParseParamHex(configFilename
, Configuration
);
252 ParseParamHex(configFilename
, AltSetting
);
254 /* TargetProductList has priority over TargetProduct */
255 if (TargetProduct
!= -1 && TargetProductList
[0] != '\0') {
257 SHOW_PROGRESS(output
,"Warning: TargetProductList overrides TargetProduct!\n");
267 fprintf (output
,"DefaultVendor= 0x%04x\n", DefaultVendor
);
268 if ( DefaultProduct
)
269 fprintf (output
,"DefaultProduct= 0x%04x\n", DefaultProduct
);
271 fprintf (output
,"TargetVendor= 0x%04x\n", TargetVendor
);
272 if ( TargetProduct
> -1 )
273 fprintf (output
,"TargetProduct= 0x%04x\n", TargetProduct
);
275 fprintf (output
,"TargetClass= 0x%02x\n", TargetClass
);
276 if ( strlen(TargetProductList
) )
277 fprintf (output
,"TargetProductList=\"%s\"\n", TargetProductList
);
279 fprintf (output
,"\nStandardEject=1\n");
280 if (ModeMap
& DETACHONLY_MODE
)
281 fprintf (output
,"\nDetachStorageOnly=1\n");
282 if (ModeMap
& HUAWEI_MODE
)
283 fprintf (output
,"HuaweiMode=1\n");
284 if (ModeMap
& HUAWEINEW_MODE
)
285 fprintf (output
,"HuaweiNewMode=1\n");
286 if (ModeMap
& SIERRA_MODE
)
287 fprintf (output
,"SierraMode=1\n");
288 if (ModeMap
& SONY_MODE
)
289 fprintf (output
,"SonyMode=1\n");
290 if (ModeMap
& QISDA_MODE
)
291 fprintf (output
,"QisdaMode=1\n");
292 if (ModeMap
& QUANTA_MODE
)
293 fprintf (output
,"QuantaMode=1\n");
294 if (ModeMap
& GCT_MODE
)
295 fprintf (output
,"GCTMode=1\n");
296 if (ModeMap
& KOBIL_MODE
)
297 fprintf (output
,"KobilMode=1\n");
298 if (ModeMap
& SEQUANS_MODE
)
299 fprintf (output
,"SequansMode=1\n");
300 if (ModeMap
& MOBILEACTION_MODE
)
301 fprintf (output
,"MobileActionMode=1\n");
302 if (ModeMap
& CISCO_MODE
)
303 fprintf (output
,"CiscoMode=1\n");
304 if (ModeMap
& BLACKBERRY_MODE
)
305 fprintf (output
,"BlackberryMode=1\n");
306 if (ModeMap
& OPTION_MODE
)
307 fprintf (output
,"OptionMode=1\n");
308 if (ModeMap
& PANTECH_MODE
)
309 fprintf (output
,"PantechMode=1\n");
310 if ( MessageEndpoint
)
311 fprintf (output
,"MessageEndpoint=0x%02x\n", MessageEndpoint
);
312 if ( strlen(MessageContent
) )
313 fprintf (output
,"MessageContent=\"%s\"\n", MessageContent
);
314 if ( strlen(MessageContent2
) )
315 fprintf (output
,"MessageContent2=\"%s\"\n", MessageContent2
);
316 if ( strlen(MessageContent3
) )
317 fprintf (output
,"MessageContent3=\"%s\"\n", MessageContent3
);
318 if ( ResponseEndpoint
)
319 fprintf (output
,"ResponseEndpoint=0x%02x\n", ResponseEndpoint
);
320 if ( Interface
> -1 )
321 fprintf (output
,"Interface=0x%02x\n", Interface
);
322 if ( Configuration
> 0 )
323 fprintf (output
,"Configuration=0x%02x\n", Configuration
);
324 if ( AltSetting
> -1 )
325 fprintf (output
,"AltSetting=0x%02x\n", AltSetting
);
327 fprintf (output
,"Success check enabled, max. wait time %d seconds\n", CheckSuccess
);
329 fprintf (output
,"System integration mode enabled\n");
333 int readArguments(int argc
, char **argv
)
335 int c
, option_index
= 0, count
=0;
336 char *longConfig
= NULL
;
346 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:",
347 long_options
, &option_index
);
349 /* Detect the end of the options. */
355 case 'R': ResetUSB
= 1; break;
356 case 'v': DefaultVendor
= strtol(optarg
, NULL
, 16); break;
357 case 'p': DefaultProduct
= strtol(optarg
, NULL
, 16); break;
358 case 'V': TargetVendor
= strtol(optarg
, NULL
, 16); break;
359 case 'P': TargetProduct
= strtol(optarg
, NULL
, 16); break;
360 case 'C': TargetClass
= strtol(optarg
, NULL
, 16); break;
361 case 'm': MessageEndpoint
= strtol(optarg
, NULL
, 16); break;
362 case 'M': strncpy(MessageContent
, optarg
, LINE_DIM
); break;
363 case '2': strncpy(MessageContent2
, optarg
, LINE_DIM
); break;
364 case '3': strncpy(MessageContent3
, optarg
, LINE_DIM
); break;
365 case 'w': ReleaseDelay
= strtol(optarg
, NULL
, 10); break;
367 case 'r': ResponseEndpoint
= strtol(optarg
, NULL
, 16); break;
368 case 'K': StandardEject
= 1; break;
369 case 'd': ModeMap
= ModeMap
+ DETACHONLY_MODE
; break;
370 case 'H': ModeMap
= ModeMap
+ HUAWEI_MODE
; break;
371 case 'J': ModeMap
= ModeMap
+ HUAWEINEW_MODE
; break;
372 case 'S': ModeMap
= ModeMap
+ SIERRA_MODE
; break;
373 case 'O': ModeMap
= ModeMap
+ SONY_MODE
; break;; break;
374 case 'B': ModeMap
= ModeMap
+ QISDA_MODE
; break;
375 case 'E': ModeMap
= ModeMap
+ QUANTA_MODE
; break;
376 case 'G': ModeMap
= ModeMap
+ GCT_MODE
; break;
377 case 'T': ModeMap
= ModeMap
+ KOBIL_MODE
; break;
378 case 'N': ModeMap
= ModeMap
+ SEQUANS_MODE
; break;
379 case 'A': ModeMap
= ModeMap
+ MOBILEACTION_MODE
; break;
380 case 'L': ModeMap
= ModeMap
+ CISCO_MODE
; break;
381 case 'Z': ModeMap
= ModeMap
+ BLACKBERRY_MODE
; break;
382 case 'U': ModeMap
= ModeMap
+ OPTION_MODE
; break;
383 case 'F': ModeMap
= ModeMap
+ PANTECH_MODE
;
384 PantechMode
= strtol(optarg
, NULL
, 10); break;
385 case 'c': readConfigFile(optarg
); break;
386 case 't': readConfigFile("stdin"); break;
387 case 'W': verbose
= 1; show_progress
= 1; count
--; break;
388 case 'Q': show_progress
= 0; verbose
= 0; count
--; break;
389 case 'D': sysmode
= 1; count
--; break;
390 case 's': CheckSuccess
= strtol(optarg
, NULL
, 10); count
--; break;
392 case 'b': busnum
= strtol(optarg
, NULL
, 10); break;
393 case 'g': devnum
= strtol(optarg
, NULL
, 10); break;
395 case 'i': Interface
= strtol(optarg
, NULL
, 16); break;
396 case 'u': Configuration
= strtol(optarg
, NULL
, 16); break;
397 case 'a': AltSetting
= strtol(optarg
, NULL
, 16); break;
398 case 'j': mbim
= 1; break;
401 longConfig
= malloc(strlen(optarg
)+5);
402 strcpy(longConfig
,"##\n");
403 strcat(longConfig
,optarg
);
404 strcat(longConfig
,"\n");
405 readConfigFile(longConfig
);
419 default: /* Unsupported - error message has already been printed */
420 fprintf (output
,"\n");
429 int main(int argc
, char **argv
)
431 int ret
=0, numDefaults
=0, sonySuccess
=0, i
;
432 int currentConfigVal
=0, defaultClass
=0, interfaceClass
=0;
433 struct libusb_device_descriptor descriptor
;
434 enum libusb_error libusbError
;
436 /* Make sure we have empty strings even if not set by config */
437 TargetProductList
[0] = '\0';
438 MessageContent
[0] = '\0';
439 MessageContent2
[0] = '\0';
440 MessageContent3
[0] = '\0';
441 DefaultProductList
[0] = '\0';
443 /* Useful for debugging during boot */
444 // output=fopen("/dev/console", "w");
447 signal(SIGTERM
, release_usb_device
);
450 * Parameter parsing, USB preparation/diagnosis, plausibility checks
453 /* Check command arguments, use params instead of config file when given */
454 switch (readArguments(argc
, argv
)) {
455 case 0: /* no argument or -W, -q or -s */
457 default: /* one or more arguments except -W, -q or -s */
458 if (!config_read
) /* if arguments contain -c, the config file was already processed */
459 if (verbose
) fprintf(output
,"Take all parameters from the command line\n\n");
465 fprintf(output
,"\n");
468 /* Some sanity checks. The default IDs are mandatory */
469 if (!(DefaultVendor
&& DefaultProduct
)) {
470 SHOW_PROGRESS(output
,"No default vendor/product ID given. Abort\n\n");
474 if (strlen(MessageContent
)) {
475 if (strlen(MessageContent
) % 2 != 0) {
476 fprintf(stderr
, "Error: MessageContent hex string has uneven length. Abort\n\n");
479 if ( hexstr2bin(MessageContent
, ByteString
, strlen(MessageContent
)/2) == -1) {
480 fprintf(stderr
, "Error: MessageContent %s\n is not a hex string. Abort\n\n",
488 searchMode
= SEARCH_DEFAULT
;
490 SHOW_PROGRESS(output
,"Use given bus/device number: %03d/%03d ...\n", busnum
, devnum
);
491 searchMode
= SEARCH_BUSDEV
;
495 if (CheckSuccess
&& !(TargetVendor
|| TargetProduct
> -1 || TargetProductList
[0] != '\0')
498 fprintf(output
,"Note: No target parameter given; success check limited\n");
500 if (TargetProduct
> -1 && TargetProductList
[0] == '\0') {
501 sprintf(TargetProductList
,"%04x",TargetProduct
);
505 /* libusb initialization */
506 if ((libusbError
= libusb_init(&ctx
)) != LIBUSB_SUCCESS
) {
507 fprintf(stderr
, "Error: Failed to initialize libusb. %s (%d)\n\n");
512 libusb_set_debug(ctx
, 3);
515 printf("%d\n", findMBIMConfig(DefaultVendor
, DefaultProduct
, searchMode
) );
519 /* Count existing target devices, remember for success check */
520 if (searchMode
!= SEARCH_BUSDEV
&& (TargetVendor
|| TargetClass
)) {
521 SHOW_PROGRESS(output
,"Look for target devices ...\n");
522 search_devices(&targetDeviceCount
, TargetVendor
, TargetProductList
, TargetClass
, 0,
525 if (targetDeviceCount
) {
526 SHOW_PROGRESS(output
," Found devices in target mode or class (%d)\n", targetDeviceCount
);
528 SHOW_PROGRESS(output
," No devices in target mode or class found\n");
531 /* Count default devices, get the last one found */
532 SHOW_PROGRESS(output
,"Look for default devices ...\n");
534 sprintf(DefaultProductList
,"%04x",DefaultProduct
);
535 dev
= search_devices(&numDefaults
, DefaultVendor
, DefaultProductList
, TargetClass
,
536 Configuration
, searchMode
);
539 SHOW_PROGRESS(output
," Found devices in default mode (%d)\n", numDefaults
);
541 SHOW_PROGRESS(output
," No devices in default mode found. Nothing to do. Bye!\n\n");
547 SHOW_PROGRESS(output
," No bus/device match. Is device connected? Abort\n\n");
552 devnum
= libusb_get_device_address(dev
);
553 busnum
= libusb_get_bus_number(dev
);
554 SHOW_PROGRESS(output
,"Access device %03d on bus %03d\n", devnum
, busnum
);
556 libusb_open(dev
, &devh
);
558 SHOW_PROGRESS(output
,"Error opening the device. Abort\n\n");
563 /* Get current configuration of default device, note value if Configuration
564 * parameter is set. Also sets active_config
566 currentConfigVal
= get_current_config_value(dev
);
567 if (Configuration
> -1) {
568 SHOW_PROGRESS(output
,"Current configuration number is %d\n", currentConfigVal
);
570 currentConfigVal
= 0;
572 libusb_get_device_descriptor(dev
, &descriptor
);
573 defaultClass
= descriptor
.bDeviceClass
;
575 Interface
= active_config
->interface
[0].altsetting
[0].bInterfaceNumber
;
576 SHOW_PROGRESS(output
,"Use interface number %d\n", Interface
);
578 /* Get class of default device/interface */
579 interfaceClass
= get_interface_class();
581 /* Check or get endpoints and alloc message list if needed*/
582 if (strlen(MessageContent
) || StandardEject
|| ModeMap
& CISCO_MODE
583 || ModeMap
& HUAWEINEW_MODE
|| ModeMap
& OPTION_MODE
) {
585 Messages
= (char**) calloc(MSG_DIM
, sizeof(char*));
586 for (i
= 0; i
< MSG_DIM
; i
++) {
587 Messages
[i
] = (char*) calloc(LINE_DIM
, sizeof(char));
588 Messages
[i
][0] = '\0';
591 if (!MessageEndpoint
)
592 MessageEndpoint
= find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT
);
593 if (!ResponseEndpoint
)
594 ResponseEndpoint
= find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN
);
595 if (!MessageEndpoint
) {
596 fprintf(stderr
,"Error: message endpoint not given or found. Abort\n\n");
599 if (!ResponseEndpoint
) {
600 fprintf(stderr
,"Error: response endpoint not given or found. Abort\n\n");
603 SHOW_PROGRESS(output
,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
,
608 if (interfaceClass
== -1) {
609 fprintf(stderr
, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface
);
613 if (defaultClass
== 0 || defaultClass
== 0xef)
614 defaultClass
= interfaceClass
;
616 if (interfaceClass
== LIBUSB_CLASS_MASS_STORAGE
&& defaultClass
!= LIBUSB_CLASS_MASS_STORAGE
617 && defaultClass
!= LIBUSB_CLASS_VENDOR_SPEC
) {
619 /* Unexpected default class combined with differing interface class */
620 SHOW_PROGRESS(output
,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass
);
624 if (strlen(MessageContent
) && strncmp("55534243",MessageContent
,8) == 0)
625 if (defaultClass
!= 8) {
626 fprintf(stderr
, "Error: can't use storage command in MessageContent with interface %d;\n"
627 " interface class is %d, expected 8. Abort\n\n", Interface
, defaultClass
);
632 fprintf(output
,"\nUSB description data (for identification)\n");
636 /* Special modes are exclusive, so check for illegal combinations.
637 * More than one bit set?
639 if ( ModeMap
& (ModeMap
-1) ) {
640 fprintf(output
,"Multiple special modes selected; check configuration. Abort\n\n");
644 if ((strlen(MessageContent
) || StandardEject
) && ModeMap
) {
645 MessageContent
[0] = '\0';
647 fprintf(output
,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n");
650 if (StandardEject
&& (strlen(MessageContent2
) || strlen(MessageContent3
))) {
651 fprintf(output
,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n");
654 if ( !ModeMap
&& !strlen(MessageContent
) && AltSetting
== -1 && !Configuration
&& !StandardEject
)
655 SHOW_PROGRESS(output
,"Warning: no switching method given. See documentation\n");
658 * The switching actions
662 openlog("usb_modeswitch", 0, LOG_SYSLOG
);
663 syslog(LOG_NOTICE
, "switch device %04x:%04x on %03d/%03d", DefaultVendor
, DefaultProduct
,
668 if (ModeMap
& DETACHONLY_MODE
) {
669 SHOW_PROGRESS(output
,"Detach storage driver as switching method ...\n");
670 ret
= detachDriver();
672 SHOW_PROGRESS(output
," You may want to remove the storage driver manually\n");
675 if(ModeMap
& HUAWEI_MODE
) {
678 if(ModeMap
& SIERRA_MODE
) {
681 if(ModeMap
& GCT_MODE
) {
685 if(ModeMap
& QISDA_MODE
) {
688 if(ModeMap
& KOBIL_MODE
) {
692 if(ModeMap
& QUANTA_MODE
) {
695 if(ModeMap
& SEQUANS_MODE
) {
698 if(ModeMap
& MOBILEACTION_MODE
) {
701 if(ModeMap
& CISCO_MODE
) {
705 if(ModeMap
& BLACKBERRY_MODE
) {
707 switchBlackberryMode();
709 if(ModeMap
& PANTECH_MODE
) {
714 SHOW_PROGRESS(output
,"Waiting for auto-switch of Pantech modem ...\n");
716 if(ModeMap
& SONY_MODE
) {
718 SHOW_PROGRESS(output
,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
719 CheckSuccess
= 0; /* separate and implied success control */
720 sonySuccess
= switchSonyMode();
724 SHOW_PROGRESS(output
,"Sending standard EJECT sequence\n");
727 strcpy(Messages
[0],"5553424387654321000000000000061e000000000000000000000000000000");
728 strcpy(Messages
[1],"5553424397654321000000000000061b000000020000000000000000000000");
729 strcpy(Messages
[2],"5553424387654321000000000001061e000000000000000000000000000000");
730 strcpy(Messages
[3],"5553424397654321000000000001061b000000020000000000000000000000");
731 if (MessageContent
[0] != '\0')
732 strcpy(Messages
[4], MessageContent
);
735 } else if (ModeMap
& HUAWEINEW_MODE
) {
736 SHOW_PROGRESS(output
,"Using standard Huawei switching message\n");
738 strcpy(Messages
[0],"55534243123456780000000000000011062000000101000100000000000000");
740 } else if (ModeMap
& OPTION_MODE
) {
741 SHOW_PROGRESS(output
,"Using standard Option switching message\n");
743 // strcpy(MessageContent,"55534243123456780100000080000601000000000000000000000000000000");
744 strcpy(Messages
[0],"55534243123456780000000000000601000000000000000000000000000000");
746 } else if (strlen(MessageContent
)) {
748 strcpy(Messages
[0],MessageContent
);
752 if (Configuration
> 0) {
753 if (currentConfigVal
!= Configuration
) {
754 if (switchConfiguration()) {
755 currentConfigVal
= get_current_config_value(dev
);
756 if (currentConfigVal
== Configuration
) {
757 SHOW_PROGRESS(output
,"The configuration was set successfully\n");
759 SHOW_PROGRESS(output
,"Changing the configuration has failed\n");
763 SHOW_PROGRESS(output
,"Target configuration %d found. Do nothing\n", currentConfigVal
);
767 if (AltSetting
!= -1) {
771 /* No "removal" check if these are set */
772 if ((Configuration
> 0 || AltSetting
> -1) && !ResetUSB
) {
782 if (searchMode
== SEARCH_BUSDEV
&& sysmode
) {
783 printf("ok:busdev\n");
789 if (checkSuccess()) {
794 if (TargetProduct
< 1)
795 printf("ok:no_data\n");
797 printf("ok:%04x:%04x\n", TargetVendor
, TargetProduct
);
803 if (ModeMap
& SONY_MODE
)
806 syslog(LOG_NOTICE
, "switched S.E. MD400 to modem mode");
807 printf("ok:\n"); /* ACM device, no driver action */
809 SHOW_PROGRESS(output
,"-> device should be stable now. Bye!\n\n");
813 SHOW_PROGRESS(output
,"-> switching was probably not completed. Bye!\n\n");
816 SHOW_PROGRESS(output
,"-> Run lsusb to note any changes. Bye!\n\n");
823 /* Get descriptor strings if available (identification details) */
824 void deviceDescription ()
826 char imanufact
[DESCR_MAX
], iproduct
[DESCR_MAX
], iserial
[DESCR_MAX
];
829 memset (imanufact
, ' ', DESCR_MAX
);
830 memset (iproduct
, ' ', DESCR_MAX
);
831 memset (iserial
, ' ', DESCR_MAX
);
833 struct libusb_device_descriptor descriptor
;
834 libusb_get_device_descriptor(dev
, &descriptor
);
836 int iManufacturer
= descriptor
.iManufacturer
;
837 int iProduct
= descriptor
.iProduct
;
838 int iSerialNumber
= descriptor
.iSerialNumber
;
841 ret
= libusb_get_string_descriptor_ascii(devh
, iManufacturer
, (unsigned char *)imanufact
, DESCR_MAX
);
843 fprintf(stderr
, "Error: could not get description string \"manufacturer\"\n");
844 strcpy(imanufact
, "read error");
847 strcpy(imanufact
, "not provided");
848 c
= strstr(imanufact
, " ");
850 memset((void*)c
, '\0', 1);
853 ret
= libusb_get_string_descriptor_ascii(devh
, iProduct
, (unsigned char *)iproduct
, DESCR_MAX
);
855 fprintf(stderr
, "Error: could not get description string \"product\"\n");
856 strcpy(iproduct
, "read error");
859 strcpy(iproduct
, "not provided");
860 c
= strstr(iproduct
, " ");
862 memset((void*)c
, '\0', 1);
865 ret
= libusb_get_string_descriptor_ascii(devh
, iSerialNumber
, (unsigned char *)iserial
, DESCR_MAX
);
867 fprintf(stderr
, "Error: could not get description string \"serial number\"\n");
868 strcpy(iserial
, "read error");
871 strcpy(iserial
, "not provided");
872 c
= strstr(iserial
, " ");
874 memset((void*)c
, '\0', 1);
875 fprintf(output
,"-------------------------\n");
876 fprintf(output
,"Manufacturer: %s\n", imanufact
);
877 fprintf(output
," Product: %s\n", iproduct
);
878 fprintf(output
," Serial No.: %s\n", iserial
);
879 fprintf(output
,"-------------------------\n");
883 /* Auxiliary function used by the wrapper */
884 int findMBIMConfig(int vendor
, int product
, int mode
)
886 struct libusb_device
**devs
;
890 if (libusb_get_device_list(ctx
, &devs
) < 0) {
891 perror("Libusb could not access USB. Abort");
895 SHOW_PROGRESS(output
,"Search USB devices ...\n");
896 while ((dev
= devs
[i
++]) != NULL
) {
897 struct libusb_device_descriptor descriptor
;
898 libusb_get_device_descriptor(dev
, &descriptor
);
900 if (mode
== SEARCH_BUSDEV
) {
901 if ((libusb_get_bus_number(dev
) != busnum
) ||
902 (libusb_get_device_address(dev
) != devnum
)) {
905 if (descriptor
.idVendor
!= vendor
)
907 if (product
!= descriptor
.idProduct
)
911 SHOW_PROGRESS(output
,"Found device, search for MBIM configuration...\n");
913 // No check if there is only one configuration
914 if (descriptor
.bNumConfigurations
< 2)
917 // Checking all interfaces of all configurations
918 for (j
=0; j
<descriptor
.bNumConfigurations
; j
++) {
919 struct libusb_config_descriptor
*config
;
921 libusb_get_config_descriptor(dev
, j
, &config
);
922 resultConfig
= config
->bConfigurationValue
;
923 for (i
=0; i
<config
->bNumInterfaces
; i
++) {
924 if ( config
->interface
[i
].altsetting
[0].bInterfaceClass
== 2 )
925 if ( config
->interface
[i
].altsetting
[0].bInterfaceSubClass
== 0x0e ) {
926 // found MBIM interface in this configuration
927 libusb_free_config_descriptor(config
);
931 libusb_free_config_descriptor(config
);
945 fprintf(output
,"Device handle empty, skip USB reset\n");
949 fprintf(output
,"Reset USB device ");
954 success
= libusb_reset_device(devh
);
955 if ( ((bpoint
% 10) == 0) && show_progress
) {
962 } while (success
< 0);
965 SHOW_PROGRESS(output
,"\n Device reset failed.\n");
967 SHOW_PROGRESS(output
,"\n Device was reset\n");
971 int switchSendMessage ()
973 const char* cmdHead
= "55534243";
976 msg[0] = MessageContent;
977 msg[1] = MessageContent2;
978 msg[2] = MessageContent3;
980 SHOW_PROGRESS(output
,"Set up interface %d\n", Interface
);
981 ret
= libusb_claim_interface(devh
, Interface
);
983 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip message sending\n", ret
);
986 libusb_clear_halt(devh
, MessageEndpoint
);
987 SHOW_PROGRESS(output
,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint
);
991 for (i
=0; i
<MSG_DIM
; i
++) {
992 if ( strlen(Messages
[i
]) == 0)
995 if ( sendMessage(Messages
[i
], i
+1) )
998 if ( strstr(Messages
[i
],cmdHead
) != NULL
) {
1000 SHOW_PROGRESS(output
,"Read the response to message %d (CSW) ...\n", i
+1);
1001 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1003 SHOW_PROGRESS(output
,", status %d",ByteString
[12]);
1005 // Other bulk transfer
1006 SHOW_PROGRESS(output
,"Read the response to message %d ...\n", i
+1);
1007 ret
= read_bulk(ResponseEndpoint
, ByteString
, strlen(Messages
[i
])/2 );
1009 SHOW_PROGRESS(output
,"\n");
1014 SHOW_PROGRESS(output
,"Reset response endpoint 0x%02x\n", ResponseEndpoint
);
1015 ret
= libusb_clear_halt(devh
, ResponseEndpoint
);
1017 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1018 SHOW_PROGRESS(output
,"Reset message endpoint 0x%02x\n", MessageEndpoint
);
1019 ret
= libusb_clear_halt(devh
, MessageEndpoint
);
1021 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1025 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1026 usleep(ReleaseDelay
*1000);
1028 ret
= libusb_release_interface(devh
, Interface
);
1034 SHOW_PROGRESS(output
," Device is gone, skip any further commands\n");
1041 int switchConfiguration ()
1043 int ret
, count
= SWITCH_CONFIG_MAXTRIES
;
1045 SHOW_PROGRESS(output
,"Change configuration to %i ...\n", Configuration
);
1046 while (((ret
= libusb_set_configuration(devh
, Configuration
)) < 0) && --count
) {
1047 SHOW_PROGRESS(output
," Device is busy, try to detach kernel driver\n");
1051 SHOW_PROGRESS(output
," Changing the configuration failed (error %d). Try to continue\n", ret
);
1054 SHOW_PROGRESS(output
," OK, configuration set\n");
1060 int switchAltSetting ()
1063 SHOW_PROGRESS(output
,"Change to alt setting %i ...\n", AltSetting
);
1064 ret
= libusb_claim_interface(devh
, Interface
);
1066 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip AltSetting\n", ret
);
1069 ret
= libusb_set_interface_alt_setting(devh
, Interface
, AltSetting
);
1070 libusb_release_interface(devh
, Interface
);
1072 SHOW_PROGRESS(output
," Change to alt setting returned error %d. Try to continue\n", ret
);
1079 void switchHuaweiMode ()
1082 SHOW_PROGRESS(output
,"Send old Huawei control message ...\n");
1083 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_STANDARD
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1084 LIBUSB_REQUEST_SET_FEATURE
, 00000001, 0, buffer
, 0, 1000);
1087 fprintf(stderr
, "Error: Huawei control message failed (error %d). Abort\n\n", ret
);
1093 void switchSierraMode ()
1096 SHOW_PROGRESS(output
,"Send Sierra control message\n");
1097 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1098 LIBUSB_REQUEST_SET_INTERFACE
, 00000001, 0, buffer
, 0, 1000);
1099 if (ret
== LIBUSB_ERROR_PIPE
) {
1100 SHOW_PROGRESS(output
," communication with device stopped. May have switched modes anyway\n");
1104 fprintf(stderr
, "Error: Sierra control message failed (error %d). Abort\n\n", ret
);
1110 void switchGCTMode ()
1113 ret
= libusb_claim_interface(devh
, Interface
);
1115 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip GCT sequence\n", ret
);
1118 SHOW_PROGRESS(output
,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d",
1119 LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
);
1121 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
,
1122 0xa0, 0, Interface
, buffer
, 1, 1000);
1125 SHOW_PROGRESS(output
," GCT control message 1 failed (error %d), continue anyway ...\n", ret
);
1127 SHOW_PROGRESS(output
,"Send GCT control message 2 ...\n");
1128 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_IN
,
1129 0xfe, 0, Interface
, buffer
, 1, 1000);
1132 SHOW_PROGRESS(output
," GCT control message 2 failed (error %d). Abort\n\n", ret
);
1134 libusb_release_interface(devh
, Interface
);
1140 void switchKobilMode() {
1142 SHOW_PROGRESS(output
,"Send Kobil control message ...\n");
1143 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1144 0x88, 0, 0, buffer
, 8, 1000);
1147 fprintf(stderr
, "Error: Kobil control message failed (error %d). Abort\n\n", ret
);
1153 void switchQisdaMode () {
1155 SHOW_PROGRESS(output
,"Sending Qisda control message ...\n");
1156 memcpy(buffer
, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1157 ret
= libusb_control_transfer(devh
, 0x40, 0x04, 0, 0, buffer
, 16, 1000);
1159 fprintf(stderr
, "Error: Qisda control message failed (error %d). Abort\n\n", ret
);
1165 void switchQuantaMode() {
1167 SHOW_PROGRESS(output
,"Send Quanta control message ...\n");
1168 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1169 0xff, 0, 0, buffer
, 0, 1000);
1172 SHOW_PROGRESS(output
,"Error: Quanta control message failed (error %d). Abort\n\n", ret
);
1178 void switchBlackberryMode ()
1181 SHOW_PROGRESS(output
,"Send Blackberry control message 1 ...\n");
1182 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1183 0xb1, 0x0000, 0, buffer
, 8, 1000);
1186 fprintf(stderr
, "Error: Blackberry control message 1 failed (result %d)\n", ret
);
1188 SHOW_PROGRESS(output
,"Send Blackberry control message 2 ...\n");
1189 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1190 0xa9, 0x000e, 0, buffer
, 2, 1000);
1193 fprintf(stderr
, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret
);
1199 void switchPantechMode()
1202 SHOW_PROGRESS(output
,"Send Pantech control message, wValue %d ...\n", PantechMode
);
1203 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_OUT
,
1204 0x70, PantechMode
, 0, buffer
, 0, 1000);
1207 SHOW_PROGRESS(output
," Error: Pantech control message failed (error %d). Abort\n\n", ret
);
1217 #define MOBILE_ACTION_READLOOP1 63
1218 #define MOBILE_ACTION_READLOOP2 73
1220 /* The code here is statically derived from sniffing (and confirmed working).
1221 * However I bet it could be simplified significantly.
1224 void switchActionMode ()
1227 SHOW_PROGRESS(output
,"Send MobileAction control sequence ...\n");
1228 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1229 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_OUT
,
1230 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1232 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1233 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
| LIBUSB_RECIPIENT_INTERFACE
| LIBUSB_ENDPOINT_OUT
,
1234 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1236 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1237 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1238 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1239 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1240 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1241 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1242 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1243 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1244 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1245 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1246 for (i
=0; i
< MOBILE_ACTION_READLOOP1
; i
++) {
1247 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1249 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1250 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1251 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1252 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1253 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1254 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1255 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1256 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1257 for (i
=0; i
< MOBILE_ACTION_READLOOP2
; i
++) {
1258 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1260 memcpy(buffer
, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE
);
1261 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1262 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1263 memcpy(buffer
, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE
);
1264 ret
= usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1265 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1267 SHOW_PROGRESS(output
," MobileAction control sequence did not complete\n"
1268 " Last error was %d\n",ret
);
1270 SHOW_PROGRESS(output
," MobileAction control sequence complete\n");
1275 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1276 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1278 #define SQN_DEFAULT_DEVICE_MODE 0x00
1279 #define SQN_MASS_STORAGE_MODE 0x01
1280 #define SQN_CUSTOM_DEVICE_MODE 0x02
1282 void switchSequansMode()
1286 SHOW_PROGRESS(output
,"Send Sequans control message\n");
1287 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
1288 | LIBUSB_ENDPOINT_OUT
, SQN_SET_DEVICE_MODE_REQUEST
, SQN_CUSTOM_DEVICE_MODE
,
1289 0, buffer
, 0, 1000);
1292 fprintf(stderr
, "Error: Sequans request failed (error %d). Abort\n\n", ret
);
1298 void switchCiscoMode()
1302 strcpy(Messages
[0],"55534243f83bcd810002000080000afd000000030000000100000000000000");
1303 strcpy(Messages
[1],"55534243984300820002000080000afd000000070000000100000000000000");
1304 strcpy(Messages
[2],"55534243984300820000000000000afd000100071000000000000000000000");
1305 strcpy(Messages
[3],"55534243984300820002000080000afd000200230000000100000000000000");
1306 strcpy(Messages
[4],"55534243984300820000000000000afd000300238200000000000000000000");
1307 strcpy(Messages
[5],"55534243984300820002000080000afd000200260000000100000000000000");
1308 strcpy(Messages
[6],"55534243984300820000000000000afd00030026c800000000000000000000");
1309 strcpy(Messages
[7],"55534243d84c04820002000080000afd000010730000000100000000000000");
1310 strcpy(Messages
[8],"55534243d84c04820002000080000afd000200240000000100000000000000");
1311 strcpy(Messages
[9],"55534243d84c04820000000000000afd000300241300000000000000000000");
1312 strcpy(Messages
[10],"55534243d84c04820000000000000afd000110732400000000000000000000");
1314 SHOW_PROGRESS(output
,"Set up Cisco interface %d\n", Interface
);
1315 ret
= libusb_claim_interface(devh
, Interface
);
1317 SHOW_PROGRESS(output
," Could not claim interface (error %d). Abort\n", ret
);
1320 // libusb_clear_halt(devh, MessageEndpoint);
1324 // ret = read_bulk(ResponseEndpoint, ByteString, 13);
1325 // SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret);
1327 for (i
=0; i
<11; i
++) {
1328 if ( sendMessage(Messages
[i
], i
+1) )
1331 for (j
=1; j
<4; j
++) {
1333 SHOW_PROGRESS(output
," Read the CSW for bulk message %d (attempt %d) ...\n",i
+1,j
);
1334 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1335 SHOW_PROGRESS(output
,"\n");
1343 libusb_clear_halt(devh
, MessageEndpoint
);
1344 libusb_clear_halt(devh
, ResponseEndpoint
);
1346 ReleaseDelay
= 2000;
1347 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1348 usleep(ReleaseDelay
*1000);
1350 ret
= libusb_release_interface(devh
, Interface
);
1356 SHOW_PROGRESS(output
,"Device returned error %d, skip further commands\n", ret
);
1362 int switchSonyMode ()
1371 SHOW_PROGRESS(output
,"Send Sony control message\n");
1372 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
1373 | LIBUSB_ENDPOINT_IN
, 0x11, 2, 0, buffer
, 3, 100);
1376 fprintf(stderr
, "Error: Sony control message failed (error %d). Abort\n\n", ret
);
1379 SHOW_PROGRESS(output
," OK, control message sent, wait for device to return ...\n");
1384 /* Now waiting for the device to reappear */
1389 while ( dev
== 0 && i
< 30 ) {
1391 dev
= search_devices(&found
, DefaultVendor
, DefaultProductList
, TargetClass
,
1397 if (show_progress
) {
1398 fprintf(output
,"#");
1403 SHOW_PROGRESS(output
,"\n After %d seconds:",i
);
1405 SHOW_PROGRESS(output
," device came back, proceed\n");
1406 libusb_open(dev
, &devh
);
1408 fprintf(stderr
, "Error: could not get handle on device\n");
1412 SHOW_PROGRESS(output
," device still gone, abort\n");
1417 SHOW_PROGRESS(output
,"Send Sony control message again ...\n");
1418 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
1419 | LIBUSB_ENDPOINT_IN
, 0x11, 2, 0, buffer
, 3, 100);
1422 fprintf(stderr
, "Error: Sony control message (2) failed (error %d)\n", ret
);
1425 SHOW_PROGRESS(output
," OK, control message sent\n");
1436 SHOW_PROGRESS(output
,"Looking for active driver ...\n");
1437 ret
= libusb_kernel_driver_active(devh
, 0);
1438 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1439 fprintf(output
," Can't do driver detection on this platform.\n");
1443 fprintf(output
," Driver check failed with error %d. Try to continue\n", ret
);
1447 SHOW_PROGRESS(output
," No active driver found. Detached before or never attached\n");
1451 ret
= libusb_detach_kernel_driver(devh
, Interface
);
1452 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1453 fprintf(output
," Can't do driver detaching on this platform.\n");
1457 SHOW_PROGRESS(output
," OK, driver detached\n");
1459 SHOW_PROGRESS(output
," Driver detach failed (error %d). Try to continue\n", ret
);
1464 int sendMessage(char* message
, int count
)
1466 int ret
, message_length
;
1468 if (strlen(message
) % 2 != 0) {
1469 fprintf(stderr
, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count
);
1472 message_length
= strlen(message
) / 2;
1473 if ( hexstr2bin(message
, ByteString
, message_length
) == -1) {
1474 fprintf(stderr
, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n",
1475 count
, MessageContent
);
1479 SHOW_PROGRESS(output
,"Trying to send message %d to endpoint 0x%02x ...\n", count
, MessageEndpoint
);
1481 ret
= write_bulk(MessageEndpoint
, ByteString
, message_length
);
1482 if (ret
== LIBUSB_ERROR_NO_DEVICE
)
1492 int newTargetCount
, success
=0;
1494 SHOW_PROGRESS(output
,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess
);
1497 /* If target parameters are given, don't check for vanished device
1498 * Changed for Cisco AM10 where a new device is added while the install
1499 * storage device stays active
1501 if ((TargetVendor
|| TargetClass
) && devh
) {
1506 /* if target ID is not given but target class is, assign default as target;
1507 * it will be needed for sysmode output
1509 if (!TargetVendor
&& TargetClass
) {
1510 TargetVendor
= DefaultVendor
;
1511 TargetProduct
= DefaultProduct
;
1514 /* devh is 0 if device vanished during command transmission or if target params were given
1517 for (i
=0; i
< CheckSuccess
; i
++) {
1519 /* Test if default device still can be accessed; positive result does
1520 * not necessarily mean failure
1522 SHOW_PROGRESS(output
," Wait for original device to vanish ...\n");
1524 ret
= libusb_claim_interface(devh
, Interface
);
1525 libusb_release_interface(devh
, Interface
);
1527 SHOW_PROGRESS(output
," Original device can't be accessed anymore. Good.\n");
1532 if (i
== CheckSuccess
-1) {
1533 SHOW_PROGRESS(output
," Original device still present after the timeout\n\n"
1534 "Mode switch most likely failed. Bye!\n\n");
1539 if ( TargetVendor
&& (TargetProduct
> -1 || TargetProductList
[0] != '\0') ) {
1541 /* Recount target devices (compare with previous count) if target data is given.
1542 * Target device on the same bus with higher device number is returned,
1543 * description is read for syslog message
1545 for (i
=i
; i
< CheckSuccess
; i
++) {
1546 SHOW_PROGRESS(output
," Search for target devices ...\n");
1547 dev
= search_devices(&newTargetCount
, TargetVendor
, TargetProductList
,
1548 TargetClass
, 0, SEARCH_TARGET
);
1550 if (dev
&& (newTargetCount
> targetDeviceCount
)) {
1552 libusb_open(dev
, &devh
);
1553 fprintf(output
,"\nFound target device %03d on bus %03d\n",
1554 libusb_get_device_address(dev
), libusb_get_bus_number(dev
));
1556 fprintf(output
,"\nTarget device description data\n");
1557 deviceDescription();
1561 SHOW_PROGRESS(output
," Found correct target device\n\n"
1562 "Mode switch succeeded. Bye!\n\n");
1567 if (i
== CheckSuccess
-1) {
1568 SHOW_PROGRESS(output
," No new devices in target mode or class found\n\n"
1569 "Mode switch has failed. Bye!\n\n");
1574 /* No target data given, rely on the vanished device */
1576 SHOW_PROGRESS(output
," (For a better success check provide target IDs or class)\n");
1577 SHOW_PROGRESS(output
," Original device vanished after switching\n\n"
1578 "Mode switch most likely succeeded. Bye!\n\n");
1585 syslog(LOG_NOTICE
, "switched to new device, but hit libusb1 bug");
1591 syslog(LOG_NOTICE
, "switched to %04x:%04x on %03d/%03d", TargetVendor
,
1592 TargetProduct
, busnum
, devnum
);
1598 syslog(LOG_NOTICE
, "device seems to have switched");
1610 int write_bulk(int endpoint
, unsigned char *message
, int length
)
1612 int ret
= usb_bulk_io(devh
, endpoint
, message
, length
, 3000);
1614 SHOW_PROGRESS(output
," OK, message successfully sent\n");
1616 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1617 SHOW_PROGRESS(output
," Device seems to have vanished right after sending. Good.\n");
1619 SHOW_PROGRESS(output
," Sending the message returned error %d. Try to continue\n", ret
);
1625 int read_bulk(int endpoint
, unsigned char *buffer
, int length
)
1627 int ret
= usb_bulk_io(devh
, endpoint
, buffer
, length
, 3000);
1629 SHOW_PROGRESS(output
," Response successfully read (%d bytes)", ret
);
1631 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1632 SHOW_PROGRESS(output
," Device seems to have vanished after reading. Good.");
1634 SHOW_PROGRESS(output
," Response reading failed (error %d)", ret
);
1640 void release_usb_device(int __attribute__((unused
)) dummy
)
1642 SHOW_PROGRESS(output
,"Program cancelled by system. Bye!\n\n");
1644 libusb_release_interface(devh
, Interface
);
1651 /* Iterates over busses and devices, counts the ones which match the given
1652 * parameters and returns the last one of them
1654 struct libusb_device
* search_devices( int *numFound
, int vendor
, char* productList
,
1655 int targetClass
, int configuration
, int mode
)
1657 char *listcopy
=NULL
, *token
;
1658 unsigned char buffer
[2];
1659 int devClass
, product
;
1660 struct libusb_device
* right_dev
= NULL
;
1661 // struct libusb_device_handle *testdevh;
1662 struct libusb_device
**devs
;
1665 /* only target class given, target vendor and product assumed unchanged */
1666 if ( targetClass
&& !(vendor
|| strlen(productList
)) ) {
1667 vendor
= DefaultVendor
;
1668 productList
= DefaultProductList
;
1673 if (!vendor
|| productList
== '\0')
1676 listcopy
= malloc(strlen(productList
)+1);
1678 if (libusb_get_device_list(ctx
, &devs
) < 0) {
1679 perror("Libusb failed to get USB access!");
1683 while ((dev
= devs
[i
++]) != NULL
) {
1684 struct libusb_device_descriptor descriptor
;
1685 libusb_get_device_descriptor(dev
, &descriptor
);
1687 if (mode
== SEARCH_BUSDEV
) {
1688 if ((libusb_get_bus_number(dev
) != busnum
) ||
1689 (libusb_get_device_address(dev
) != devnum
))
1692 SHOW_PROGRESS(output
," bus/device number matched\n");
1696 fprintf (output
," found USB ID %04x:%04x\n",
1697 descriptor
.idVendor
, descriptor
.idProduct
);
1698 if (descriptor
.idVendor
!= vendor
)
1701 fprintf (output
," vendor ID matched\n");
1703 strcpy(listcopy
, productList
);
1704 token
= strtok(listcopy
, ",");
1705 while (token
!= NULL
) {
1706 if (strlen(token
) != 4) {
1707 SHOW_PROGRESS(output
,"Error: entry in product ID list has wrong length: %s. "
1708 "Ignored\n", token
);
1712 if ( hexstr2bin(token
, buffer
, strlen(token
)/2) == -1) {
1713 SHOW_PROGRESS(output
,"Error: entry in product ID list is not a hex string: %s. "
1714 "Ignored\n", token
);
1719 product
+= (unsigned char)buffer
[0];
1721 product
+= (unsigned char)buffer
[1];
1722 if (product
== descriptor
.idProduct
) {
1723 SHOW_PROGRESS(output
," product ID matched\n");
1725 if (targetClass
!= 0) {
1726 // TargetClass is set, check class of first interface
1727 struct libusb_device_descriptor descriptor
;
1728 libusb_get_device_descriptor(dev
, &descriptor
);
1729 devClass
= descriptor
.bDeviceClass
;
1730 struct libusb_config_descriptor
*config
;
1731 libusb_get_config_descriptor(dev
, 0, &config
);
1732 int ifaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
1733 libusb_free_config_descriptor(config
);
1735 devClass
= ifaceClass
;
1737 /* Check for some quirky devices */
1738 if (devClass
!= ifaceClass
)
1739 devClass
= ifaceClass
;
1740 if (devClass
== targetClass
) {
1742 fprintf (output
," target class %02x matches\n", targetClass
);
1743 if (mode
== SEARCH_TARGET
) {
1747 fprintf (output
," count device\n");
1750 fprintf (output
," device not counted, target class reached\n");
1753 fprintf (output
," device class %02x not matching target\n", devClass
);
1754 if (mode
== SEARCH_DEFAULT
|| mode
== SEARCH_BUSDEV
) {
1758 fprintf (output
," count device\n");
1761 } else if (configuration
> 0) {
1762 // Configuration parameter is set, check device configuration
1763 int testconfig
= get_current_config_value(dev
);
1764 if (testconfig
!= configuration
) {
1766 fprintf (output
," device configuration %d not matching target\n",
1772 fprintf (output
," count device\n");
1775 fprintf (output
," device not counted, target configuration reached\n");
1777 // Neither TargetClass nor Configuration are set
1780 if (mode
== SEARCH_BUSDEV
)
1786 token
= strtok(NULL
, ",");
1789 if (listcopy
!= NULL
)
1795 /* Autodetect bulk endpoints (ab) */
1797 int find_first_bulk_endpoint(int direction
)
1800 const struct libusb_interface_descriptor
*alt
;
1801 const struct libusb_endpoint_descriptor
*ep
;
1803 for (j
=0; j
< active_config
->bNumInterfaces
; j
++) {
1804 alt
= &(active_config
->interface
[j
].altsetting
[0]);
1805 if (alt
->bInterfaceNumber
== Interface
) {
1806 for (i
=0; i
< alt
->bNumEndpoints
; i
++) {
1807 ep
= &(alt
->endpoint
[i
]);
1808 if ( ( (ep
->bmAttributes
& LIBUSB_ENDPOINT_ADDRESS_MASK
) == LIBUSB_TRANSFER_TYPE_BULK
)
1809 && ( (ep
->bEndpointAddress
& LIBUSB_ENDPOINT_DIR_MASK
) == direction
) ) {
1811 return ep
->bEndpointAddress
;
1820 int get_current_config_value()
1822 SHOW_PROGRESS(output
,"Get the current device configuration ...\n");
1823 if (active_config
!= NULL
) {
1824 libusb_free_config_descriptor(active_config
);
1825 active_config
= NULL
;
1827 int ret
= libusb_get_active_config_descriptor(dev
, &active_config
);
1829 SHOW_PROGRESS(output
," Determining the active configuration failed (error %d). Abort\n", ret
);
1832 return active_config
->bConfigurationValue
;
1836 int get_interface_class()
1839 for (i
=0; i
< active_config
->bNumInterfaces
; i
++) {
1840 if (active_config
->interface
[i
].altsetting
[0].bInterfaceNumber
== Interface
)
1841 return active_config
->interface
[i
].altsetting
[0].bInterfaceClass
;
1847 /* Parameter parsing */
1849 char* ReadParseParam(const char* FileName
, char *VariableName
)
1851 static int numLines
= 0;
1852 static char* ConfigBuffer
[MAXLINES
];
1853 char *VarName
, *Comment
=NULL
, *Equal
=NULL
;
1854 char *FirstQuote
, *LastQuote
, *P1
, *P2
;
1856 unsigned Len
=0, Pos
=0;
1857 char Str
[LINE_DIM
], *token
, *configPos
;
1860 // Reading and storing input during the first call
1862 if (strncmp(FileName
,"##",2) == 0) {
1863 if (verbose
) fprintf(output
,"\nRead long config from command line\n");
1864 // "Embedded" configuration data
1865 configPos
= (char*)FileName
;
1866 token
= strtok(configPos
, "\n");
1867 strncpy(Str
,token
,LINE_DIM
-1);
1869 if (strcmp(FileName
, "stdin")==0) {
1870 if (verbose
) fprintf(output
,"\nRead long config from stdin\n");
1873 if (verbose
) fprintf(output
,"\nRead config file: %s\n", FileName
);
1874 file
=fopen(FileName
, "r");
1877 fprintf(stderr
, "Error: Could not find file %s. Abort\n\n", FileName
);
1880 token
= fgets(Str
, LINE_DIM
-1, file
);
1883 while (token
!= NULL
&& numLines
< MAXLINES
) {
1888 if (Str
[Len
-1]=='\n' or Str
[Len
-1]=='\r')
1890 Equal
= strchr (Str
, '='); // search for equal sign
1891 Pos
= strcspn (Str
, ";#!"); // search for comment
1892 Comment
= (Pos
==Len
) ? NULL
: Str
+Pos
;
1893 if (Equal
==NULL
or ( Comment
!=NULL
and Comment
<=Equal
))
1894 goto NextLine
; // Comment or irrelevant, don't save
1896 ConfigBuffer
[numLines
] = malloc(Len
*sizeof(char));
1897 strcpy(ConfigBuffer
[numLines
],Str
);
1901 token
= strtok(NULL
, "\n");
1903 strncpy(Str
,token
,LINE_DIM
-1);
1905 token
= fgets(Str
, LINE_DIM
-1, file
);
1911 // Now checking for parameters
1913 while (Line
< numLines
) {
1914 strcpy(Str
,ConfigBuffer
[Line
]);
1915 Equal
= strchr (Str
, '='); // search for equal sign
1919 FirstQuote
=strchr (Equal
, '"'); // search for double quote char
1920 LastQuote
=strrchr (Equal
, '"');
1921 if (FirstQuote
!=NULL
) {
1922 if (LastQuote
==NULL
) {
1923 fprintf(stderr
, "Error reading parameters from file %s - "
1924 "Missing end quote:\n%s\n", FileName
, Str
);
1928 *FirstQuote
=*LastQuote
='\0';
1932 // removes leading/trailing spaces
1933 Pos
=strspn (Str
, " \t");
1934 if (Pos
==strlen(Str
)) {
1935 fprintf(stderr
, "Error reading parameters from file %s - "
1936 "Missing variable name:\n%s\n", FileName
, Str
);
1940 while ((P1
=strrchr(Str
, ' '))!=NULL
or (P2
=strrchr(Str
, '\t'))!=NULL
)
1941 if (P1
!=NULL
) *P1
='\0';
1942 else if (P2
!=NULL
) *P2
='\0';
1945 Pos
=strspn (Equal
, " \t");
1946 if (Pos
==strlen(Equal
)) {
1947 fprintf(stderr
, "Error reading parameter from file %s - "
1948 "Missing value:\n%s\n", FileName
, Str
);
1954 if (strcmp(VarName
, VariableName
)==0) { // Found it
1967 if (c
>= '0' && c
<= '9')
1969 if (c
>= 'a' && c
<= 'f')
1970 return c
- 'a' + 10;
1971 if (c
>= 'A' && c
<= 'F')
1972 return c
- 'A' + 10;
1977 int hex2byte(const char *hex
)
1980 a
= hex2num(*hex
++);
1983 b
= hex2num(*hex
++);
1986 return (a
<< 4) | b
;
1990 int hexstr2bin(const char *hex
, unsigned char *buffer
, int len
)
1994 const char *ipos
= hex
;
1995 unsigned char *opos
= buffer
;
1997 for (i
= 0; i
< len
; i
++) {
2001 *opos
++ = (unsigned char) a
;
2012 for ( i
= 0; i
< MSG_DIM
; i
++ ) {
2018 libusb_free_config_descriptor(active_config
);
2021 // libusb_exit will crash on Raspbian 7, crude protection
2039 char* version
= VERSION
;
2040 fprintf(output
,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
2041 " * Version %s (C) Josua Dietze 2016\n"
2042 " * Based on libusb1/libusbx\n\n"
2043 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version
);
2049 fprintf(output
,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
2050 " -h, --help this help\n"
2051 " -e, --version print version information and exit\n"
2052 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
2053 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
2054 " -p, --default-product NUM product ID of original mode (mandatory)\n"
2055 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
2056 " -P, --target-product NUM target mode product ID (optional)\n"
2057 " -C, --target-class NUM target mode device class (optional)\n"
2058 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
2059 " -g, --device-num NUM system device number (for hard ID)\n"
2060 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
2061 " -M, --message-content <msg> message to send (hex number as string)\n"
2062 " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n"
2063 " -w, --release-delay NUM wait NUM ms before releasing the interface\n"
2064 " -n, --need-response obsolete, no effect (always on)\n"
2065 " -r, --response-endpoint NUM read response from there (optional)\n"
2066 " -K, --std-eject send standard EJECT sequence\n"
2067 " -d, --detach-only detach the active driver, no further action\n"
2068 " -H, --huawei-mode apply a special procedure\n"
2069 " -J, --huawei-new-mode apply a special procedure\n"
2070 " -S, --sierra-mode apply a special procedure\n"
2071 " -O, --sony-mode apply a special procedure\n"
2072 " -G, --gct-mode apply a special procedure\n"
2073 " -N, --sequans-mode apply a special procedure\n"
2074 " -A, --mobileaction-mode apply a special procedure\n"
2075 " -T, --kobil-mode apply a special procedure\n"
2076 " -L, --cisco-mode apply a special procedure\n"
2077 " -B, --qisda-mode apply a special procedure\n"
2078 " -E, --quanta-mode apply a special procedure\n"
2079 " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n"
2080 " -Z, --blackberry-mode apply a special procedure\n"
2081 " -U, --option-mode apply a special procedure\n"
2082 " -R, --reset-usb reset the device after all other actions\n"
2083 " -Q, --quiet don't show progress or error messages\n"
2084 " -W, --verbose print all settings and debug output\n"
2085 " -D, --sysmode specific result and syslog message\n"
2086 " -s, --success <seconds> switching result check with timeout\n"
2087 " -I, --inquire obsolete, no effect\n\n"
2088 " -c, --config-file <filename> load long configuration from file\n\n"
2089 " -t, --stdinput read long configuration from stdin\n\n"
2090 " -f, --long-config <text> get long configuration from string\n\n"
2091 " -i, --interface NUM select initial USB interface (default 0)\n"
2092 " -u, --configuration NUM select USB configuration\n"
2093 " -a, --altsetting NUM select alternative USB interface setting\n\n");