2 Mode switching tool for controlling flip flop (multiple device) USB gear
3 Version 2.0.1, 2013/09/03
5 Copyright (C) 2007 - 2013 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 stuff 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.0.1"
59 #include "usb_modeswitch.h"
62 /* libusb 1.0 wrappers */
64 int usb_bulk_io(struct libusb_device_handle
*handle
, int ep
, 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, (unsigned char *)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))
81 static int usb_interrupt_io(libusb_device_handle
*handle
, int ep
, char *bytes
,
82 int size
, int timeout
)
86 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
87 r
= libusb_interrupt_transfer(handle
, ep
& 0xff, (unsigned char *)bytes
, size
,
88 &actual_length
, timeout
);
90 /* if we timed out but did transfer some data, report as successful short
91 * read. FIXME: is this how libusb-0.1 works? */
92 if (r
== 0 || (r
== LIBUSB_ERROR_TIMEOUT
&& actual_length
> 0))
101 #define BUF_SIZE 4096
102 #define DESCR_MAX 129
104 #define SEARCH_DEFAULT 0
105 #define SEARCH_TARGET 1
106 #define SEARCH_BUSDEV 2
108 #define SWITCH_CONFIG_MAXTRIES 5
110 #define SHOW_PROGRESS if (show_progress) fprintf
114 static struct libusb_context
*ctx
= NULL
;
115 static struct libusb_device
*dev
;
116 static struct libusb_device_handle
*devh
;
118 int DefaultVendor
=0, DefaultProduct
=0, TargetVendor
=0, TargetProduct
=-1, TargetClass
=0;
119 int MessageEndpoint
=0, ResponseEndpoint
=0, ReleaseDelay
=0;
120 int targetDeviceCount
=0, searchMode
;
121 int devnum
=-1, busnum
=-1;
124 unsigned int ModeMap
= 0;
125 #define DETACHONLY_MODE 0x00000001
126 #define HUAWEI_MODE 0x00000002
127 #define SIERRA_MODE 0x00000004
128 #define SONY_MODE 0x00000008
129 #define GCT_MODE 0x00000010
130 #define KOBIL_MODE 0x00000020
131 #define SEQUANS_MODE 0x00000040
132 #define MOBILEACTION_MODE 0x00000080
133 #define CISCO_MODE 0x00000100
134 #define QISDA_MODE 0x00000200
135 #define QUANTA_MODE 0x00000400
136 #define BLACKBERRY_MODE 0x00000800
137 #define PANTECH_MODE 0x00001000
139 char verbose
=0, show_progress
=1, ResetUSB
=0, CheckSuccess
=0, config_read
=0;
140 char NeedResponse
=0, NoDriverLoading
=0, InquireDevice
=1, sysmode
=0, mbim
=0;
142 char imanufact
[DESCR_MAX
], iproduct
[DESCR_MAX
], iserial
[DESCR_MAX
];
144 char MessageContent
[LINE_DIM
];
145 char MessageContent2
[LINE_DIM
];
146 char MessageContent3
[LINE_DIM
];
147 char TargetProductList
[LINE_DIM
];
148 char DefaultProductList
[5];
149 char ByteString
[LINE_DIM
/2];
150 char buffer
[BUF_SIZE
];
155 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
156 int Interface
= -1, Configuration
= 0, AltSetting
= -1;
159 static struct option long_options
[] = {
160 {"help", no_argument
, 0, 'h'},
161 {"version", no_argument
, 0, 'e'},
162 {"default-vendor", required_argument
, 0, 'v'},
163 {"default-product", required_argument
, 0, 'p'},
164 {"target-vendor", required_argument
, 0, 'V'},
165 {"target-product", required_argument
, 0, 'P'},
166 {"target-class", required_argument
, 0, 'C'},
167 {"message-endpoint", required_argument
, 0, 'm'},
168 {"message-content", required_argument
, 0, 'M'},
169 {"message-content2", required_argument
, 0, '2'},
170 {"message-content3", required_argument
, 0, '3'},
171 {"release-delay", required_argument
, 0, 'w'},
172 {"response-endpoint", required_argument
, 0, 'r'},
173 {"bus-num", required_argument
, 0, 'b'},
174 {"device-num", required_argument
, 0, 'g'},
175 {"detach-only", no_argument
, 0, 'd'},
176 {"huawei-mode", no_argument
, 0, 'H'},
177 {"sierra-mode", no_argument
, 0, 'S'},
178 {"sony-mode", no_argument
, 0, 'O'},
179 {"qisda-mode", no_argument
, 0, 'B'},
180 {"quanta-mode", no_argument
, 0, 'E'},
181 {"kobil-mode", no_argument
, 0, 'T'},
182 {"gct-mode", no_argument
, 0, 'G'},
183 {"sequans-mode", no_argument
, 0, 'N'},
184 {"mobileaction-mode", no_argument
, 0, 'A'},
185 {"cisco-mode", no_argument
, 0, 'L'},
186 {"blackberry-mode", no_argument
, 0, 'Z'},
187 {"pantech-mode", no_argument
, 0, 'F'},
188 {"need-response", no_argument
, 0, 'n'},
189 {"reset-usb", no_argument
, 0, 'R'},
190 {"config-file", required_argument
, 0, 'c'},
191 {"verbose", no_argument
, 0, 'W'},
192 {"quiet", no_argument
, 0, 'Q'},
193 {"sysmode", no_argument
, 0, 'D'},
194 {"no-inquire", no_argument
, 0, 'I'},
195 {"stdinput", no_argument
, 0, 't'},
196 {"find-mbim", no_argument
, 0, 'j'},
197 {"long-config", required_argument
, 0, 'f'},
198 {"check-success", required_argument
, 0, 's'},
199 {"interface", required_argument
, 0, 'i'},
200 {"configuration", required_argument
, 0, 'u'},
201 {"altsetting", required_argument
, 0, 'a'},
206 void readConfigFile(const char *configFilename
)
208 ParseParamHex(configFilename
, TargetVendor
);
209 ParseParamHex(configFilename
, TargetProduct
);
210 ParseParamString(configFilename
, TargetProductList
);
211 ParseParamHex(configFilename
, TargetClass
);
212 ParseParamHex(configFilename
, DefaultVendor
);
213 ParseParamHex(configFilename
, DefaultProduct
);
214 ParseParamBoolMap(configFilename
, DetachStorageOnly
, ModeMap
, DETACHONLY_MODE
);
215 ParseParamBoolMap(configFilename
, HuaweiMode
, ModeMap
, HUAWEI_MODE
);
216 ParseParamBoolMap(configFilename
, SierraMode
, ModeMap
, SIERRA_MODE
);
217 ParseParamBoolMap(configFilename
, SonyMode
, ModeMap
, SONY_MODE
);
218 ParseParamBoolMap(configFilename
, GCTMode
, ModeMap
, GCT_MODE
);
219 ParseParamBoolMap(configFilename
, KobilMode
, ModeMap
, KOBIL_MODE
);
220 ParseParamBoolMap(configFilename
, SequansMode
, ModeMap
, SEQUANS_MODE
);
221 ParseParamBoolMap(configFilename
, MobileActionMode
, ModeMap
, MOBILEACTION_MODE
);
222 ParseParamBoolMap(configFilename
, CiscoMode
, ModeMap
, CISCO_MODE
);
223 ParseParamBoolMap(configFilename
, QisdaMode
, ModeMap
, QISDA_MODE
);
224 ParseParamBoolMap(configFilename
, QuantaMode
, ModeMap
, QUANTA_MODE
);
225 ParseParamBoolMap(configFilename
, BlackberryMode
, ModeMap
, BLACKBERRY_MODE
);
226 ParseParamBoolMap(configFilename
, PantechMode
, ModeMap
, PANTECH_MODE
);
227 ParseParamBool(configFilename
, NoDriverLoading
);
228 ParseParamHex(configFilename
, MessageEndpoint
);
229 ParseParamString(configFilename
, MessageContent
);
230 ParseParamString(configFilename
, MessageContent2
);
231 ParseParamString(configFilename
, MessageContent3
);
232 ParseParamInt(configFilename
, ReleaseDelay
);
233 ParseParamHex(configFilename
, NeedResponse
);
234 ParseParamHex(configFilename
, ResponseEndpoint
);
235 ParseParamHex(configFilename
, ResetUSB
);
236 ParseParamHex(configFilename
, InquireDevice
);
237 ParseParamInt(configFilename
, CheckSuccess
);
238 ParseParamHex(configFilename
, Interface
);
239 ParseParamHex(configFilename
, Configuration
);
240 ParseParamHex(configFilename
, AltSetting
);
242 /* TargetProductList has priority over TargetProduct */
243 if (TargetProduct
!= -1 && TargetProductList
[0] != '\0') {
245 SHOW_PROGRESS(output
,"Warning: TargetProductList overrides TargetProduct!\n");
255 fprintf (output
,"DefaultVendor= 0x%04x\n", DefaultVendor
);
256 if ( DefaultProduct
)
257 fprintf (output
,"DefaultProduct= 0x%04x\n", DefaultProduct
);
259 fprintf (output
,"TargetVendor= 0x%04x\n", TargetVendor
);
260 if ( TargetProduct
> -1 )
261 fprintf (output
,"TargetProduct= 0x%04x\n", TargetProduct
);
263 fprintf (output
,"TargetClass= 0x%02x\n", TargetClass
);
264 if ( strlen(TargetProductList
) )
265 fprintf (output
,"TargetProductList=\"%s\"\n", TargetProductList
);
266 if (ModeMap
& DETACHONLY_MODE
)
267 fprintf (output
,"\nDetachStorageOnly=1\n");
268 if (ModeMap
& HUAWEI_MODE
)
269 fprintf (output
,"HuaweiMode=1\n");
270 if (ModeMap
& SIERRA_MODE
)
271 fprintf (output
,"SierraMode=1\n");
272 if (ModeMap
& SONY_MODE
)
273 fprintf (output
,"SonyMode=1\n");
274 if (ModeMap
& QISDA_MODE
)
275 fprintf (output
,"QisdaMode=1\n");
276 if (ModeMap
& QUANTA_MODE
)
277 fprintf (output
,"QuantaMode=1\n");
278 if (ModeMap
& GCT_MODE
)
279 fprintf (output
,"GCTMode=1\n");
280 if (ModeMap
& KOBIL_MODE
)
281 fprintf (output
,"KobilMode=1\n");
282 if (ModeMap
& SEQUANS_MODE
)
283 fprintf (output
,"SequansMode=1\n");
284 if (ModeMap
& MOBILEACTION_MODE
)
285 fprintf (output
,"MobileActionMode=1\n");
286 if (ModeMap
& CISCO_MODE
)
287 fprintf (output
,"CiscoMode=1\n");
288 if (ModeMap
& BLACKBERRY_MODE
)
289 fprintf (output
,"BlackberryMode=1\n");
290 if (ModeMap
& PANTECH_MODE
)
291 fprintf (output
,"PantechMode=1\n");
292 if ( MessageEndpoint
)
293 fprintf (output
,"MessageEndpoint=0x%02x\n", MessageEndpoint
);
294 if ( strlen(MessageContent
) )
295 fprintf (output
,"MessageContent=\"%s\"\n", MessageContent
);
296 if ( strlen(MessageContent2
) )
297 fprintf (output
,"MessageContent2=\"%s\"\n", MessageContent2
);
298 if ( strlen(MessageContent3
) )
299 fprintf (output
,"MessageContent3=\"%s\"\n", MessageContent3
);
300 fprintf (output
,"NeedResponse=%i\n", (int)NeedResponse
);
301 if ( ResponseEndpoint
)
302 fprintf (output
,"ResponseEndpoint=0x%02x\n", ResponseEndpoint
);
303 if ( Interface
> -1 )
304 fprintf (output
,"Interface=0x%02x\n", Interface
);
305 if ( Configuration
> 0 )
306 fprintf (output
,"Configuration=0x%02x\n", Configuration
);
307 if ( AltSetting
> -1 )
308 fprintf (output
,"AltSetting=0x%02x\n", AltSetting
);
310 fprintf (output
,"\nInquireDevice enabled (default)\n");
312 fprintf (output
,"\nInquireDevice disabled\n");
314 fprintf (output
,"Success check enabled, max. wait time %d seconds\n", CheckSuccess
);
316 fprintf (output
,"System integration mode enabled\n");
320 int readArguments(int argc
, char **argv
)
322 int c
, option_index
= 0, count
=0;
323 char *longConfig
= NULL
;
333 c
= getopt_long (argc
, argv
, "hejWQDndHSOBEGTNALZFRItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
334 long_options
, &option_index
);
336 /* Detect the end of the options. */
342 case 'R': ResetUSB
= 1; break;
343 case 'v': DefaultVendor
= strtol(optarg
, NULL
, 16); break;
344 case 'p': DefaultProduct
= strtol(optarg
, NULL
, 16); break;
345 case 'V': TargetVendor
= strtol(optarg
, NULL
, 16); break;
346 case 'P': TargetProduct
= strtol(optarg
, NULL
, 16); break;
347 case 'C': TargetClass
= strtol(optarg
, NULL
, 16); break;
348 case 'm': MessageEndpoint
= strtol(optarg
, NULL
, 16); break;
349 case 'M': strncpy(MessageContent
, optarg
, LINE_DIM
); break;
350 case '2': strncpy(MessageContent2
, optarg
, LINE_DIM
); break;
351 case '3': strncpy(MessageContent3
, optarg
, LINE_DIM
); break;
352 case 'w': ReleaseDelay
= strtol(optarg
, NULL
, 10); break;
353 case 'n': NeedResponse
= 1; break;
354 case 'r': ResponseEndpoint
= strtol(optarg
, NULL
, 16); break;
355 case 'd': ModeMap
= ModeMap
+ DETACHONLY_MODE
; break;
356 case 'H': ModeMap
= ModeMap
+ HUAWEI_MODE
; break;
357 case 'S': ModeMap
= ModeMap
+ SIERRA_MODE
; break;
358 case 'O': ModeMap
= ModeMap
+ SONY_MODE
; break;; break;
359 case 'B': ModeMap
= ModeMap
+ QISDA_MODE
; break;
360 case 'E': ModeMap
= ModeMap
+ QUANTA_MODE
; break;
361 case 'G': ModeMap
= ModeMap
+ GCT_MODE
; break;
362 case 'T': ModeMap
= ModeMap
+ KOBIL_MODE
; break;
363 case 'N': ModeMap
= ModeMap
+ SEQUANS_MODE
; break;
364 case 'A': ModeMap
= ModeMap
+ MOBILEACTION_MODE
; break;
365 case 'L': ModeMap
= ModeMap
+ CISCO_MODE
; break;
366 case 'Z': ModeMap
= ModeMap
+ BLACKBERRY_MODE
; break;
367 case 'F': ModeMap
= ModeMap
+ PANTECH_MODE
; break;
368 case 'c': readConfigFile(optarg
); break;
369 case 't': readConfigFile("stdin"); break;
370 case 'W': verbose
= 1; show_progress
= 1; count
--; break;
371 case 'Q': show_progress
= 0; verbose
= 0; count
--; break;
372 case 'D': sysmode
= 1; InquireDevice
= 0; count
--; break;
373 case 's': CheckSuccess
= strtol(optarg
, NULL
, 10); count
--; break;
374 case 'I': InquireDevice
= 0; break;
375 case 'b': busnum
= strtol(optarg
, NULL
, 10); break;
376 case 'g': devnum
= strtol(optarg
, NULL
, 10); break;
378 case 'i': Interface
= strtol(optarg
, NULL
, 16); break;
379 case 'u': Configuration
= strtol(optarg
, NULL
, 16); break;
380 case 'a': AltSetting
= strtol(optarg
, NULL
, 16); break;
381 case 'j': mbim
= 1; break;
384 longConfig
= malloc(strlen(optarg
)+5);
385 strcpy(longConfig
,"##\n");
386 strcat(longConfig
,optarg
);
387 strcat(longConfig
,"\n");
388 readConfigFile(longConfig
);
402 default: /* Unsupported - error message has already been printed */
403 fprintf (output
,"\n");
413 int main(int argc
, char **argv
)
415 int numDefaults
=0, sonySuccess
=0;
416 int currentConfig
=0, defaultClass
=0, interfaceClass
=0;
417 struct libusb_device_descriptor descriptor
;
418 struct libusb_config_descriptor
*config
;
421 /* Make sure we have empty strings even if not set by config */
422 TargetProductList
[0] = '\0';
423 MessageContent
[0] = '\0';
424 MessageContent2
[0] = '\0';
425 MessageContent3
[0] = '\0';
426 DefaultProductList
[0] = '\0';
428 /* Useful for debugging during boot */
429 // output=fopen("/dev/console", "w");
432 signal(SIGTERM
, release_usb_device
);
435 * Parameter parsing, USB preparation/diagnosis, plausibility checks
438 /* Check command arguments, use params instead of config file when given */
439 switch (readArguments(argc
, argv
)) {
440 case 0: /* no argument or -W, -q or -s */
442 default: /* one or more arguments except -W, -q or -s */
443 if (!config_read
) /* if arguments contain -c, the config file was already processed */
444 if (verbose
) fprintf(output
,"Take all parameters from the command line\n\n");
450 fprintf(output
,"\n");
453 /* Some sanity checks. The default IDs are mandatory */
454 if (!(DefaultVendor
&& DefaultProduct
)) {
455 SHOW_PROGRESS(output
,"No default vendor/product ID given. Abort\n\n");
459 if (strlen(MessageContent
)) {
460 if (strlen(MessageContent
) % 2 != 0) {
461 fprintf(stderr
, "Error: MessageContent hex string has uneven length. Abort\n\n");
464 if ( hexstr2bin(MessageContent
, ByteString
, strlen(MessageContent
)/2) == -1) {
465 fprintf(stderr
, "Error: MessageContent %s\n is not a hex string. Abort\n\n", MessageContent
);
471 searchMode
= SEARCH_DEFAULT
;
473 SHOW_PROGRESS(output
,"Use given bus/device number: %03d/%03d ...\n", busnum
, devnum
);
474 searchMode
= SEARCH_BUSDEV
;
478 if (CheckSuccess
&& !(TargetVendor
|| TargetProduct
> -1 || TargetProductList
[0] != '\0') && !TargetClass
)
479 fprintf(output
,"Note: No target parameter given; success check limited\n");
481 if (TargetProduct
> -1 && TargetProductList
[0] == '\0') {
482 sprintf(TargetProductList
,"%04x",TargetProduct
);
486 /* libusb initialization */
490 libusb_set_debug(ctx
, 3);
493 printf("%d\n", findMBIMConfig(DefaultVendor
, DefaultProduct
, searchMode
) );
497 /* Count existing target devices, remember for success check */
498 if (searchMode
!= SEARCH_BUSDEV
&& (TargetVendor
|| TargetClass
)) {
499 SHOW_PROGRESS(output
,"Look for target devices ...\n");
500 search_devices(&targetDeviceCount
, TargetVendor
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
501 if (targetDeviceCount
) {
502 SHOW_PROGRESS(output
," Found devices in target mode or class (%d)\n", targetDeviceCount
);
504 SHOW_PROGRESS(output
," No devices in target mode or class found\n");
507 /* Count default devices, get the last one found */
508 SHOW_PROGRESS(output
,"Look for default devices ...\n");
510 sprintf(DefaultProductList
,"%04x",DefaultProduct
);
511 dev
= search_devices(&numDefaults
, DefaultVendor
, DefaultProductList
, TargetClass
, Configuration
, searchMode
);
513 SHOW_PROGRESS(output
," Found devices in default mode (%d)\n", numDefaults
);
515 SHOW_PROGRESS(output
," No devices in default mode found. Nothing to do. Bye!\n\n");
519 SHOW_PROGRESS(output
," No bus/device match. Is device connected? Abort\n\n");
523 devnum
= libusb_get_device_address(dev
);
524 busnum
= libusb_get_bus_number(dev
);
525 SHOW_PROGRESS(output
,"Access device %03d on bus %03d\n", devnum
, busnum
);
527 libusb_open(dev
, &devh
);
529 SHOW_PROGRESS(output
,"Error opening the device. Abort\n\n");
534 /* Get current configuration of default device
535 * A configuration value of -1 helps with quirky devices which have
536 * trouble determining the current configuration. We are just using the
537 * current config branch then.
538 * This affects only single-configuration devices so it's no problem.
539 * The dispatcher is using this always if no change of configuration
540 * is required for switching
542 if (Configuration
> -1)
543 currentConfig
= get_current_configuration(devh
);
545 SHOW_PROGRESS(output
,"Skip the check for the current configuration\n");
549 libusb_get_device_descriptor(dev
, &descriptor
);
550 defaultClass
= descriptor
.bDeviceClass
;
551 libusb_get_config_descriptor(dev
, 0, &config
);
553 Interface
= config
->interface
[0].altsetting
[0].bInterfaceNumber
;
554 SHOW_PROGRESS(output
,"Use interface number %d\n", Interface
);
556 /* Get class of default device/interface */
557 interfaceClass
= get_interface_class(config
, Interface
);
558 libusb_free_config_descriptor(config
);
559 if (interfaceClass
== -1) {
560 fprintf(stderr
, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface
);
564 if (defaultClass
== 0)
565 defaultClass
= interfaceClass
;
567 if (interfaceClass
== 8 && defaultClass
!= 8) {
568 /* Weird device with default class other than 0 and differing interface class */
569 SHOW_PROGRESS(output
,"Ambiguous Class/InterfaceClass: 0x%02x/0x08\n", defaultClass
);
573 if (strlen(MessageContent
) && strncmp("55534243",MessageContent
,8) == 0)
574 if (defaultClass
!= 8) {
575 fprintf(stderr
, "Error: can't use storage command in MessageContent with interface %d;\n"
576 " interface class is %d, expected 8. Abort\n\n", Interface
, defaultClass
);
580 /* Check or get endpoints */
581 if (strlen(MessageContent
) || InquireDevice
|| ModeMap
& CISCO_MODE
) {
582 if (!MessageEndpoint
)
583 MessageEndpoint
= find_first_bulk_output_endpoint(dev
);
584 if (!MessageEndpoint
) {
585 fprintf(stderr
,"Error: message endpoint not given or found. Abort\n\n");
588 if (!ResponseEndpoint
)
589 ResponseEndpoint
= find_first_bulk_input_endpoint(dev
);
590 if (!ResponseEndpoint
) {
591 fprintf(stderr
,"Error: response endpoint not given or found. Abort\n\n");
594 SHOW_PROGRESS(output
,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
, ResponseEndpoint
);
597 if (InquireDevice
&& show_progress
) {
598 if (defaultClass
== 0x08) {
599 SHOW_PROGRESS(output
,"Inquire device details; driver will be detached ...\n");
601 if (deviceInquire() >= 0)
604 SHOW_PROGRESS(output
,"Not a storage device, skip SCSI inquiry\n");
609 fprintf(output
,"\nUSB description data (for identification)\n");
610 fprintf(output
,"-------------------------\n");
611 fprintf(output
,"Manufacturer: %s\n", imanufact
);
612 fprintf(output
," Product: %s\n", iproduct
);
613 fprintf(output
," Serial No.: %s\n", iserial
);
614 fprintf(output
,"-------------------------\n");
617 /* Special modes are exclusive, so check for illegal combinations.
618 * More than one bit set?
620 if ( ModeMap
& (ModeMap
-1) ) {
621 fprintf(output
,"Multiple special modes selected; check configuration. Abort\n\n");
625 if (strlen(MessageContent
) && ModeMap
) {
626 MessageContent
[0] = '\0';
627 SHOW_PROGRESS(output
,"Warning: MessageContent ignored; can't combine with special mode\n");
630 if ( !ModeMap
&& !strlen(MessageContent
) && AltSetting
== -1 && Configuration
== 0 )
631 SHOW_PROGRESS(output
,"Warning: no switching method given. See documentation\n");
634 * The switching actions
638 openlog("usb_modeswitch", 0, LOG_SYSLOG
);
639 syslog(LOG_NOTICE
, "switch device %04x:%04x on %03d/%03d", DefaultVendor
, DefaultProduct
, busnum
, devnum
);
642 if (ModeMap
& DETACHONLY_MODE
) {
643 SHOW_PROGRESS(output
,"Detach storage driver as switching method ...\n");
644 if (InquireDevice
== 2) {
645 SHOW_PROGRESS(output
," Any driver was already detached for inquiry. Do nothing\n");
647 ret
= detachDriver();
649 SHOW_PROGRESS(output
," You may want to remove the storage driver manually\n");
653 if(ModeMap
& HUAWEI_MODE
) {
656 if(ModeMap
& SIERRA_MODE
) {
659 if(ModeMap
& GCT_MODE
) {
663 if(ModeMap
& QISDA_MODE
) {
666 if(ModeMap
& KOBIL_MODE
) {
670 if(ModeMap
& QUANTA_MODE
) {
673 if(ModeMap
& SEQUANS_MODE
) {
676 if(ModeMap
& MOBILEACTION_MODE
) {
679 if(ModeMap
& CISCO_MODE
) {
683 if(ModeMap
& BLACKBERRY_MODE
) {
685 switchBlackberryMode();
687 if(ModeMap
& PANTECH_MODE
) {
691 if(ModeMap
& SONY_MODE
) {
693 SHOW_PROGRESS(output
,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
694 CheckSuccess
= 0; /* separate and implied success control */
695 sonySuccess
= switchSonyMode();
698 if (strlen(MessageContent
) && MessageEndpoint
) {
699 if (InquireDevice
!= 2)
704 if (Configuration
> 0) {
705 if (currentConfig
!= Configuration
) {
706 if (switchConfiguration()) {
707 currentConfig
= get_current_configuration(devh
);
708 if (currentConfig
== Configuration
) {
709 SHOW_PROGRESS(output
,"The configuration was set successfully\n");
711 SHOW_PROGRESS(output
,"Changing the configuration has failed\n");
715 SHOW_PROGRESS(output
,"Target configuration %d found. Do nothing\n", currentConfig
);
719 if (AltSetting
!= -1) {
723 /* No "removal" check if these are set */
724 if ((Configuration
> 0 || AltSetting
> -1) && !ResetUSB
) {
735 if (searchMode
== SEARCH_BUSDEV
&& sysmode
) {
736 SHOW_PROGRESS(output
,"Bus/dev search active, refer success check to wrapper. Bye!\n\n");
737 printf("ok:busdev\n");
740 if (checkSuccess()) {
745 if (TargetProduct
< 1)
746 printf("ok:no_data\n");
748 printf("ok:%04x:%04x\n", TargetVendor
, TargetProduct
);
754 if (ModeMap
& SONY_MODE
)
757 syslog(LOG_NOTICE
, "switched S.E. MD400 to modem mode");
758 printf("ok:\n"); /* ACM device, no driver action */
760 SHOW_PROGRESS(output
,"-> device should be stable now. Bye!\n\n");
764 SHOW_PROGRESS(output
,"-> switching was probably not completed. Bye!\n\n");
767 SHOW_PROGRESS(output
,"-> Run lsusb to note any changes. Bye!\n\n");
778 /* Get descriptor strings if available (identification details) */
779 void deviceDescription ()
782 memset (imanufact
, ' ', DESCR_MAX
);
783 memset (iproduct
, ' ', DESCR_MAX
);
784 memset (iserial
, ' ', DESCR_MAX
);
786 struct libusb_device_descriptor descriptor
;
787 libusb_get_device_descriptor(dev
, &descriptor
);
789 int iManufacturer
= descriptor
.iManufacturer
;
790 int iProduct
= descriptor
.iProduct
;
791 int iSerialNumber
= descriptor
.iSerialNumber
;
794 ret
= libusb_get_string_descriptor_ascii(devh
, iManufacturer
, (unsigned char *)imanufact
, DESCR_MAX
);
796 fprintf(stderr
, "Error: could not get description string \"manufacturer\"\n");
798 strcpy(imanufact
, "not provided");
799 c
= strstr(imanufact
, " ");
801 memset((void*)c
, '\0', 1);
804 ret
= libusb_get_string_descriptor_ascii(devh
, iProduct
, (unsigned char *)iproduct
, DESCR_MAX
);
806 fprintf(stderr
, "Error: could not get description string \"product\"\n");
808 strcpy(iproduct
, "not provided");
809 c
= strstr(iproduct
, " ");
811 memset((void*)c
, '\0', 1);
814 ret
= libusb_get_string_descriptor_ascii(devh
, iSerialNumber
, (unsigned char *)iserial
, DESCR_MAX
);
816 fprintf(stderr
, "Error: could not get description string \"serial number\"\n");
818 strcpy(iserial
, "not provided");
819 c
= strstr(iserial
, " ");
821 memset((void*)c
, '\0', 1);
825 /* Print result of SCSI command INQUIRY (identification details) */
828 const unsigned char inquire_msg
[] = {
829 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
830 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
831 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
838 command
= malloc(31);
839 if (command
== NULL
) {
844 memcpy(command
, inquire_msg
, sizeof (inquire_msg
));
846 ret
= libusb_claim_interface(devh
, Interface
);
848 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip device inquiry\n", ret
);
851 libusb_clear_halt(devh
, MessageEndpoint
);
853 ret
= usb_bulk_io(devh
, MessageEndpoint
, (char *)command
, 31, 0);
855 SHOW_PROGRESS(output
," INQUIRY message failed (error %d)\n", ret
);
859 ret
= usb_bulk_io(devh
, ResponseEndpoint
, data
, 36, 0);
861 SHOW_PROGRESS(output
," INQUIRY response failed (error %d)\n", ret
);
865 i
= usb_bulk_io(devh
, ResponseEndpoint
, command
, 13, 0);
867 fprintf(output
,"\nSCSI inquiry data (for identification)\n");
868 fprintf(output
,"-------------------------\n");
870 fprintf(output
," Vendor String: ");
871 for (i
= 8; i
< 16; i
++) printf("%c",data
[i
]);
872 fprintf(output
,"\n");
874 fprintf(output
," Model String: ");
875 for (i
= 16; i
< 32; i
++) printf("%c",data
[i
]);
876 fprintf(output
,"\n");
878 fprintf(output
,"Revision String: ");
879 for (i
= 32; i
< 36; i
++) printf("%c",data
[i
]);
881 fprintf(output
,"\n-------------------------\n");
884 if (strlen(MessageContent
) == 0)
885 libusb_clear_halt(devh
, MessageEndpoint
);
886 libusb_release_interface(devh
, Interface
);
892 int findMBIMConfig(int vendor
, int product
, int mode
)
894 struct libusb_device
**devs
;
898 if (libusb_get_device_list(ctx
, &devs
) < 0) {
899 perror("Libusb could not access USB. Abort");
903 SHOW_PROGRESS(output
,"Search USB devices ...\n");
904 while ((dev
= devs
[i
++]) != NULL
) {
905 struct libusb_device_descriptor descriptor
;
906 libusb_get_device_descriptor(dev
, &descriptor
);
908 if (mode
== SEARCH_BUSDEV
) {
909 if ((libusb_get_bus_number(dev
) != busnum
) ||
910 (libusb_get_device_address(dev
) != devnum
)) {
913 if (descriptor
.idVendor
!= vendor
)
915 if (product
!= descriptor
.idProduct
)
919 SHOW_PROGRESS(output
,"Found device, search for MBIM configuration...\n");
921 // No check if there is only one configuration
922 if (descriptor
.bNumConfigurations
< 2)
925 // Checking all interfaces of all configurations
926 for (j
=0; j
<descriptor
.bNumConfigurations
; j
++) {
927 struct libusb_config_descriptor
*config
;
929 libusb_get_config_descriptor(dev
, j
, &config
);
930 resultConfig
= config
->bConfigurationValue
;
931 for (i
=0; i
<config
->bNumInterfaces
; i
++) {
932 if ( config
->interface
[i
].altsetting
[0].bInterfaceClass
== 2 )
933 if ( config
->interface
[i
].altsetting
[0].bInterfaceSubClass
== 0x0e ) {
934 // found MBIM interface in this configuration
935 libusb_free_config_descriptor(config
);
939 libusb_free_config_descriptor(config
);
952 fprintf(output
,"Reset USB device ");
957 success
= libusb_reset_device(devh
);
958 if ( ((bpoint
% 10) == 0) && show_progress
) {
965 } while (success
< 0);
968 SHOW_PROGRESS(output
,"\n Device reset failed.\n");
970 SHOW_PROGRESS(output
,"\n Device was reset\n");
974 int switchSendMessage ()
976 const char* cmdHead
= "55534243";
979 msg
[0] = MessageContent
;
980 msg
[1] = MessageContent2
;
981 msg
[2] = MessageContent3
;
983 /* May be activated in future versions */
984 // if (MessageContent2[0] != '\0' || MessageContent3[0] != '\0')
987 SHOW_PROGRESS(output
,"Set up interface %d\n", Interface
);
988 if (InquireDevice
!= 2) {
989 ret
= libusb_claim_interface(devh
, Interface
);
991 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip message sending\n", ret
);
995 libusb_clear_halt(devh
, MessageEndpoint
);
996 SHOW_PROGRESS(output
,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint
);
1000 for (i
=0; i
<3; i
++) {
1001 if ( strlen(msg
[i
]) == 0)
1004 if ( sendMessage(msg
[i
], i
+1) )
1008 if ( strstr(msg
[i
],cmdHead
) != NULL
) {
1010 SHOW_PROGRESS(output
,"Read the response to message %d (CSW) ...\n", i
+1);
1011 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1013 // Other bulk transfer
1014 SHOW_PROGRESS(output
,"Read the response to message %d ...\n", i
+1);
1015 ret
= read_bulk(ResponseEndpoint
, ByteString
, strlen(msg
[i
])/2 );
1022 SHOW_PROGRESS(output
,"Reset response endpoint 0x%02x\n", ResponseEndpoint
);
1023 ret
= libusb_clear_halt(devh
, ResponseEndpoint
);
1025 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1026 SHOW_PROGRESS(output
,"Reset message endpoint 0x%02x\n", MessageEndpoint
);
1027 ret
= libusb_clear_halt(devh
, MessageEndpoint
);
1029 SHOW_PROGRESS(output
," Could not reset endpoint (probably harmless): %d\n", ret
);
1033 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1034 usleep(ReleaseDelay
*1000);
1036 ret
= libusb_release_interface(devh
, Interface
);
1042 SHOW_PROGRESS(output
," Device is gone, skip any further commands\n");
1049 int switchConfiguration ()
1051 int count
= SWITCH_CONFIG_MAXTRIES
;
1053 SHOW_PROGRESS(output
,"Change configuration to %i ...\n", Configuration
);
1054 while (((ret
= libusb_set_configuration(devh
, Configuration
)) < 0) && --count
) {
1055 SHOW_PROGRESS(output
," Device is busy, try to detach kernel driver\n");
1059 SHOW_PROGRESS(output
," Changing the configuration failed (error %d). Try to continue\n", ret
);
1062 SHOW_PROGRESS(output
," OK, configuration set\n");
1067 int switchAltSetting ()
1070 SHOW_PROGRESS(output
,"Change to alt setting %i ...\n", AltSetting
);
1071 ret
= libusb_claim_interface(devh
, Interface
);
1072 ret
= libusb_set_interface_alt_setting(devh
, Interface
, AltSetting
);
1073 libusb_release_interface(devh
, Interface
);
1075 SHOW_PROGRESS(output
," Change to alt setting returned error %d. Try to continue\n", ret
);
1082 void switchHuaweiMode ()
1085 SHOW_PROGRESS(output
,"Send old Huawei control message ...\n");
1086 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_STANDARD
| LIBUSB_RECIPIENT_DEVICE
, \
1087 LIBUSB_REQUEST_SET_FEATURE
, 00000001, 0, (unsigned char *)buffer
, 0, 1000);
1089 fprintf(stderr
, "Error: Huawei control message failed (error %d). Abort\n\n", ret
);
1095 void switchSierraMode ()
1097 SHOW_PROGRESS(output
,"Send Sierra control message\n");
1098 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
, 0x0b, 00000001, 0, (unsigned char *)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 ()
1112 ret
= libusb_claim_interface(devh
, Interface
);
1114 SHOW_PROGRESS(output
," Could not claim interface (error %d). Skip GCT sequence\n", ret
);
1117 SHOW_PROGRESS(output
,"Send GCT control message 1 ...\n");
1118 ret
= libusb_control_transfer(devh
, 0xa1, 0xa0, 0, Interface
, (unsigned char *)buffer
, 1, 1000);
1120 SHOW_PROGRESS(output
," GCT control message 1 failed (error %d), continue anyway ...\n", ret
);
1122 SHOW_PROGRESS(output
,"Send GCT control message 2 ...\n");
1123 ret
= libusb_control_transfer(devh
, 0xa1, 0xfe, 0, Interface
, (unsigned char *)buffer
, 1, 1000);
1125 SHOW_PROGRESS(output
," GCT control message 2 failed (error %d). Abort\n\n", ret
);
1127 libusb_release_interface(devh
, Interface
);
1133 void switchKobilMode() {
1134 SHOW_PROGRESS(output
,"Send Kobil control message ...\n");
1135 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1136 0x88, 0, 0, (unsigned char *)buffer
, 8, 1000);
1138 fprintf(stderr
, "Error: Kobil control message failed (error %d). Abort\n\n", ret
);
1144 void switchQisdaMode () {
1145 SHOW_PROGRESS(output
,"Sending Qisda control message ...\n");
1146 memcpy(buffer
, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1147 ret
= libusb_control_transfer(devh
, 0x40, 0x04, 0, 0, (unsigned char *)buffer
, 16, 1000);
1149 fprintf(stderr
, "Error: Qisda control message failed (error %d). Abort\n\n", ret
);
1155 void switchQuantaMode() {
1156 SHOW_PROGRESS(output
,"Send Quanta control message ...\n");
1157 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1158 0xff, 0, 0, (unsigned char *)buffer
, 0, 1000);
1160 SHOW_PROGRESS(output
,"Error: Quanta control message failed (error %d). Abort\n\n", ret
);
1166 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, (unsigned char *)buffer
, 8, 1000);
1172 fprintf(stderr
, "Error: Blackberry control message 1 failed (result %d)\n", ret
);
1174 SHOW_PROGRESS(output
,"Send Blackberry control message 2 ...\n");
1175 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
| LIBUSB_ENDPOINT_IN
,
1176 0xa9, 0x000e, 0, (unsigned char *)buffer
, 2, 1000);
1178 fprintf(stderr
, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret
);
1184 void switchPantechMode()
1186 SHOW_PROGRESS(output
,"Send Pantech control message ...\n");
1187 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
, 0x70, 2, 0, (unsigned char *)buffer
, 0, 1000);
1189 SHOW_PROGRESS(output
," Error: Pantech control message failed (error %d). Abort\n\n", ret
);
1199 #define MOBILE_ACTION_READLOOP1 63
1200 #define MOBILE_ACTION_READLOOP2 73
1202 /* If anyone can test the MobileAction cable - I bet this
1203 * function (which is confirmed working) can be greatly
1207 void switchActionMode ()
1210 SHOW_PROGRESS(output
,"Send MobileAction control sequence ...\n");
1211 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1212 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
+ LIBUSB_RECIPIENT_INTERFACE
, 0x09, 0x0300, 0, (unsigned char *)buffer
, SIZE
, 1000);
1213 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1214 libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_CLASS
+ LIBUSB_RECIPIENT_INTERFACE
, 0x09, 0x0300, 0, (unsigned char *)buffer
, SIZE
, 1000);
1215 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1216 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1217 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1218 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1219 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1220 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1221 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1222 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1223 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1224 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1225 for (i
=0; i
< MOBILE_ACTION_READLOOP1
; i
++) {
1226 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1228 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1229 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1230 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1231 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1232 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1233 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1234 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1235 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1236 for (i
=0; i
< MOBILE_ACTION_READLOOP2
; i
++) {
1237 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1239 memcpy(buffer
, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE
);
1240 usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1241 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1242 memcpy(buffer
, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE
);
1243 ret
= usb_interrupt_io(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1244 usb_interrupt_io(devh
, EP_IN
, buffer
, SIZE
, 1000);
1246 SHOW_PROGRESS(output
," MobileAction control sequence did not complete\n Last error was %d\n",ret
);
1248 SHOW_PROGRESS(output
," MobileAction control sequence complete\n");
1253 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1254 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1256 #define SQN_DEFAULT_DEVICE_MODE 0x00
1257 #define SQN_MASS_STORAGE_MODE 0x01
1258 #define SQN_CUSTOM_DEVICE_MODE 0x02
1260 void switchSequansMode() {
1262 SHOW_PROGRESS(output
,"Send Sequans control message\n");
1263 ret
= libusb_control_transfer(devh
, LIBUSB_REQUEST_TYPE_VENDOR
| LIBUSB_RECIPIENT_DEVICE
, SQN_SET_DEVICE_MODE_REQUEST
, SQN_CUSTOM_DEVICE_MODE
, 0, (unsigned char *)buffer
, 0, 1000);
1265 fprintf(stderr
, "Error: Sequans request failed (error %d). Abort\n\n", ret
);
1270 void switchCiscoMode() {
1274 msg
[0] = "55534243f83bcd810002000080000afd000000030000000100000000000000";
1275 msg
[1] = "55534243984300820002000080000afd000000070000000100000000000000";
1276 msg
[2] = "55534243984300820000000000000afd000100071000000000000000000000";
1277 msg
[3] = "55534243984300820002000080000afd000200230000000100000000000000";
1278 msg
[4] = "55534243984300820000000000000afd000300238200000000000000000000";
1279 msg
[5] = "55534243984300820002000080000afd000200260000000100000000000000";
1280 msg
[6] = "55534243984300820000000000000afd00030026c800000000000000000000";
1281 msg
[7] = "55534243d84c04820002000080000afd000010730000000100000000000000";
1282 msg
[8] = "55534243d84c04820002000080000afd000200240000000100000000000000";
1283 msg
[9] = "55534243d84c04820000000000000afd000300241300000000000000000000";
1284 msg
[10] = "55534243d84c04820000000000000afd000110732400000000000000000000";
1286 SHOW_PROGRESS(output
,"Set up Cisco interface %d\n", Interface
);
1287 ret
= libusb_claim_interface(devh
, Interface
);
1289 SHOW_PROGRESS(output
," Could not claim interface (error %d). Abort\n", ret
);
1292 // libusb_clear_halt(devh, MessageEndpoint);
1296 for (i
=0; i
<11; i
++) {
1297 if ( sendMessage(msg
[i
], i
+1) )
1300 SHOW_PROGRESS(output
," Read the response (CSW) to bulk message %d ...\n",i
+1);
1301 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1307 SHOW_PROGRESS(output
,"Wait for %d ms before releasing interface ...\n", ReleaseDelay
);
1308 usleep(ReleaseDelay
*1000);
1310 ret
= libusb_release_interface(devh
, Interface
);
1316 SHOW_PROGRESS(output
,"Device returned error %d, skip further commands\n", ret
);
1322 int switchSonyMode ()
1331 SHOW_PROGRESS(output
,"Send Sony control message\n");
1332 ret
= libusb_control_transfer(devh
, 0xc0, 0x11, 2, 0, (unsigned char *)buffer
, 3, 100);
1334 fprintf(stderr
, "Error: Sony control message failed (error %d). Abort\n\n", ret
);
1337 SHOW_PROGRESS(output
," OK, control message sent, wait for device to return ...\n");
1342 /* Now waiting for the device to reappear */
1347 while ( dev
== 0 && i
< 30 ) {
1349 dev
= search_devices(&found
, DefaultVendor
, DefaultProductList
, TargetClass
, 0, SEARCH_TARGET
);
1354 if (show_progress
) {
1355 fprintf(output
,"#");
1360 SHOW_PROGRESS(output
,"\n After %d seconds:",i
);
1362 SHOW_PROGRESS(output
," device came back, proceed\n");
1363 libusb_open(dev
, &devh
);
1365 fprintf(stderr
, "Error: could not get handle on device\n");
1369 SHOW_PROGRESS(output
," device still gone, abort\n");
1374 SHOW_PROGRESS(output
,"Send Sony control message again ...\n");
1375 ret
= libusb_control_transfer(devh
, 0xc0, 0x11, 2, 0, (unsigned char *)buffer
, 3, 100);
1377 fprintf(stderr
, "Error: Sony control message (2) failed (error %d)\n", ret
);
1380 SHOW_PROGRESS(output
," OK, control message sent\n");
1390 SHOW_PROGRESS(output
,"Looking for active driver ...\n");
1391 ret
= libusb_kernel_driver_active(devh
, 0);
1392 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1393 fprintf(output
," Can't do driver detection on this platform.\n");
1397 fprintf(output
," Driver check failed with error %d. Try to continue\n", ret
);
1401 SHOW_PROGRESS(output
," No active driver found. Detached before or never attached\n");
1405 ret
= libusb_detach_kernel_driver(devh
, Interface
);
1406 if (ret
== LIBUSB_ERROR_NOT_SUPPORTED
) {
1407 fprintf(output
," Can't do driver detaching on this platform.\n");
1411 SHOW_PROGRESS(output
," OK, driver detached\n");
1413 SHOW_PROGRESS(output
," Driver detach failed (error %d). Try to continue\n", ret
);
1418 int sendMessage(char* message
, int count
)
1422 if (strlen(message
) % 2 != 0) {
1423 fprintf(stderr
, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count
);
1426 message_length
= strlen(message
) / 2;
1427 if ( hexstr2bin(message
, ByteString
, message_length
) == -1) {
1428 fprintf(stderr
, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", count
, MessageContent
);
1431 SHOW_PROGRESS(output
,"Trying to send message %d to endpoint 0x%02x ...\n", count
, MessageEndpoint
);
1433 ret
= write_bulk(MessageEndpoint
, ByteString
, message_length
);
1434 if (ret
== LIBUSB_ERROR_NO_DEVICE
)
1444 int newTargetCount
, success
=0;
1446 SHOW_PROGRESS(output
,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess
);
1449 /* If target parameters are given, don't check for vanished device
1450 * Changed for Cisco AM10 where a new device is added while the install
1451 * storage device stays active
1453 if ((TargetVendor
|| TargetClass
) && devh
) {
1458 /* if target ID is not given but target class is, assign default as target;
1459 * it will be needed for sysmode output
1461 if (!TargetVendor
&& TargetClass
) {
1462 TargetVendor
= DefaultVendor
;
1463 TargetProduct
= DefaultProduct
;
1466 /* devh is 0 if device vanished during command transmission or if target params were given
1469 for (i
=0; i
< CheckSuccess
; i
++) {
1471 /* Test if default device still can be accessed; positive result does
1472 * not necessarily mean failure
1474 SHOW_PROGRESS(output
," Wait for original device to vanish ...\n");
1476 ret
= libusb_claim_interface(devh
, Interface
);
1477 libusb_release_interface(devh
, Interface
);
1479 SHOW_PROGRESS(output
," Original device can't be accessed anymore. Good.\n");
1484 if (i
== CheckSuccess
-1) {
1485 SHOW_PROGRESS(output
," Original device still present after the timeout\n\nMode switch most likely failed. Bye!\n\n");
1490 if ( TargetVendor
&& (TargetProduct
> -1 || TargetProductList
[0] != '\0') ) {
1492 /* Recount target devices (compare with previous count) if target data is given.
1493 * Target device on the same bus with higher device number is returned,
1494 * description is read for syslog message
1496 for (i
=i
; i
< CheckSuccess
; i
++) {
1497 SHOW_PROGRESS(output
," Search for target devices ...\n");
1498 dev
= search_devices(&newTargetCount
, TargetVendor
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
1499 if (dev
&& (newTargetCount
> targetDeviceCount
)) {
1500 fprintf(output
,"\nFound target device, open it\n");
1501 libusb_open(dev
, &devh
);
1502 deviceDescription();
1506 fprintf(output
,"\nFound target device %03d on bus %03d\n", \
1507 libusb_get_device_address(dev
), libusb_get_bus_number(dev
));
1508 fprintf(output
,"\nTarget device description data\n");
1509 fprintf(output
,"-------------------------\n");
1510 fprintf(output
,"Manufacturer: %s\n", imanufact
);
1511 fprintf(output
," Product: %s\n", iproduct
);
1512 fprintf(output
," Serial No.: %s\n", iserial
);
1513 fprintf(output
,"-------------------------\n");
1515 SHOW_PROGRESS(output
," Found correct target device\n\nMode switch succeeded. Bye!\n\n");
1519 if (i
== CheckSuccess
-1) {
1520 SHOW_PROGRESS(output
," No new devices in target mode or class found\n\nMode switch has failed. Bye!\n\n");
1525 /* No target data given, rely on the vanished device */
1527 SHOW_PROGRESS(output
," (For a better success check provide target IDs or class)\n");
1528 SHOW_PROGRESS(output
," Original device vanished after switching\n\nMode switch most likely succeeded. Bye!\n\n");
1535 syslog(LOG_NOTICE
, "switched to new device, but hit libusb1 bug");
1541 syslog(LOG_NOTICE
, "switched to %04x:%04x on %03d/%03d", TargetVendor
, TargetProduct
, busnum
, devnum
);
1546 syslog(LOG_NOTICE
, "device seems to have switched");
1558 int write_bulk(int endpoint
, char *message
, int length
)
1560 ret
= usb_bulk_io(devh
, endpoint
, message
, length
, 3000);
1562 SHOW_PROGRESS(output
," OK, message successfully sent\n");
1564 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1565 SHOW_PROGRESS(output
," Device seems to have vanished right after sending. Good.\n");
1567 SHOW_PROGRESS(output
," Sending the message returned error %d. Try to continue\n", ret
);
1572 int read_bulk(int endpoint
, char *buffer
, int length
)
1574 ret
= usb_bulk_io(devh
, endpoint
, buffer
, length
, 3000);
1575 usb_bulk_io(devh
, endpoint
, buffer
, 13, 100);
1577 SHOW_PROGRESS(output
," Response successfully read (%d bytes).\n", ret
);
1579 if (ret
== LIBUSB_ERROR_NO_DEVICE
) {
1580 SHOW_PROGRESS(output
," Device seems to have vanished after reading. Good.\n");
1582 SHOW_PROGRESS(output
," Response reading failed (error %d)\n", ret
);
1587 void release_usb_device(int __attribute__((unused
)) dummy
) {
1588 SHOW_PROGRESS(output
,"Program cancelled by system. Bye!\n\n");
1590 libusb_release_interface(devh
, Interface
);
1600 /* Iterates over busses and devices, counts the ones which match the given
1601 * parameters and returns the last one of them
1603 struct libusb_device
* search_devices( int *numFound
, int vendor
, char* productList
, int targetClass
, int configuration
, int mode
)
1605 char *listcopy
=NULL
, *token
, buffer
[2];
1606 int devClass
, product
;
1607 struct libusb_device
* right_dev
= NULL
;
1608 struct libusb_device_handle
*testdevh
;
1609 struct libusb_device
**devs
;
1612 /* only target class given, target vendor and product assumed unchanged */
1613 if ( targetClass
&& !(vendor
|| strlen(productList
)) ) {
1614 vendor
= DefaultVendor
;
1615 productList
= DefaultProductList
;
1620 if (!vendor
|| productList
== '\0')
1623 listcopy
= malloc(strlen(productList
)+1);
1625 if (libusb_get_device_list(ctx
, &devs
) < 0) {
1626 perror("Libusb failed to get USB access!");
1630 while ((dev
= devs
[i
++]) != NULL
) {
1631 struct libusb_device_descriptor descriptor
;
1632 libusb_get_device_descriptor(dev
, &descriptor
);
1634 if (mode
== SEARCH_BUSDEV
) {
1635 if ((libusb_get_bus_number(dev
) != busnum
) ||
1636 (libusb_get_device_address(dev
) != devnum
))
1639 SHOW_PROGRESS(output
," bus/device number matched\n");
1643 fprintf (output
," found USB ID %04x:%04x\n",
1644 descriptor
.idVendor
, descriptor
.idProduct
);
1645 if (descriptor
.idVendor
!= vendor
)
1648 fprintf (output
," vendor ID matched\n");
1650 strcpy(listcopy
, productList
);
1651 token
= strtok(listcopy
, ",");
1652 while (token
!= NULL
) {
1653 if (strlen(token
) != 4) {
1654 SHOW_PROGRESS(output
,"Error: entry in product ID list has wrong length: %s. Ignored\n", token
);
1657 if ( hexstr2bin(token
, buffer
, strlen(token
)/2) == -1) {
1658 SHOW_PROGRESS(output
,"Error: entry in product ID list is not a hex string: %s. Ignored\n", token
);
1662 product
+= (unsigned char)buffer
[0];
1664 product
+= (unsigned char)buffer
[1];
1665 if (product
== descriptor
.idProduct
) {
1666 SHOW_PROGRESS(output
," product ID matched\n");
1668 if (targetClass
!= 0) {
1669 // TargetClass is set, check class of first interface
1670 struct libusb_device_descriptor descriptor
;
1671 libusb_get_device_descriptor(dev
, &descriptor
);
1672 devClass
= descriptor
.bDeviceClass
;
1673 struct libusb_config_descriptor
*config
;
1674 libusb_get_config_descriptor(dev
, 0, &config
);
1675 int ifaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
1676 libusb_free_config_descriptor(config
);
1678 devClass
= ifaceClass
;
1680 /* Check for some quirky devices */
1681 if (devClass
!= ifaceClass
)
1682 devClass
= ifaceClass
;
1683 if (devClass
== targetClass
) {
1685 fprintf (output
," target class %02x matches\n", targetClass
);
1686 if (mode
== SEARCH_TARGET
) {
1690 fprintf (output
," count device\n");
1693 fprintf (output
," device not counted, target class reached\n");
1696 fprintf (output
," device class %02x not matching target\n", devClass
);
1697 if (mode
== SEARCH_DEFAULT
|| mode
== SEARCH_BUSDEV
) {
1701 fprintf (output
," count device\n");
1704 } else if (configuration
> 0) {
1705 // Configuration is set, check device configuration
1706 libusb_open(dev
, &testdevh
);
1707 int testconfig
= get_current_configuration(testdevh
);
1708 if (testconfig
!= configuration
) {
1710 fprintf (output
," device configuration %d not matching target\n", testconfig
);
1714 fprintf (output
," count device\n");
1717 fprintf (output
," device not counted, target configuration reached\n");
1719 // Neither TargetClass nor Configuration are set
1722 if (mode
== SEARCH_BUSDEV
)
1728 token
= strtok(NULL
, ",");
1731 if (listcopy
!= NULL
)
1737 #define USB_DIR_OUT 0x00
1738 #define USB_DIR_IN 0x80
1740 /* Autodetect bulk endpoints (ab) */
1742 int find_first_bulk_output_endpoint(struct libusb_device
*dev
)
1745 struct libusb_config_descriptor
*config
;
1746 libusb_get_config_descriptor(dev
, 0, &config
);
1747 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1748 const struct libusb_endpoint_descriptor
*ep
;
1750 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1751 ep
=&(alt
->endpoint
[i
]);
1752 if( ( (ep
->bmAttributes
& LIBUSB_ENDPOINT_ADDRESS_MASK
) == LIBUSB_TRANSFER_TYPE_BULK
) &&
1753 ( (ep
->bEndpointAddress
& LIBUSB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
) ) {
1754 return ep
->bEndpointAddress
;
1757 libusb_free_config_descriptor(config
);
1762 int find_first_bulk_input_endpoint(struct libusb_device
*dev
)
1765 struct libusb_config_descriptor
*config
;
1766 libusb_get_config_descriptor(dev
, 0, &config
);
1767 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1768 const struct libusb_endpoint_descriptor
*ep
;
1769 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1770 ep
=&(alt
->endpoint
[i
]);
1771 if( ( (ep
->bmAttributes
& LIBUSB_ENDPOINT_ADDRESS_MASK
) == LIBUSB_TRANSFER_TYPE_BULK
) &&
1772 ( (ep
->bEndpointAddress
& LIBUSB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
) ) {
1773 return ep
->bEndpointAddress
;
1776 libusb_free_config_descriptor(config
);
1780 int get_current_configuration(struct libusb_device_handle
* devh
)
1782 SHOW_PROGRESS(output
,"Get the current device configuration ...\n");
1783 ret
= libusb_control_transfer(devh
, USB_DIR_IN
+ LIBUSB_REQUEST_TYPE_STANDARD
+ LIBUSB_RECIPIENT_DEVICE
, LIBUSB_REQUEST_GET_CONFIGURATION
, 0, 0, (unsigned char *)buffer
, 1, 1000);
1785 // There are quirky devices which fail to respond properly to this command
1786 fprintf(stderr
, "Error getting the current configuration (error %d). Assume configuration 1\n", ret
);
1787 if (Configuration
) {
1788 fprintf(stderr
, " No configuration setting possible for this device.\n");
1793 SHOW_PROGRESS(output
," OK, got current device configuration (%d)\n", buffer
[0]);
1798 int get_interface_class(struct libusb_config_descriptor
*cfg
, int ifcNumber
)
1801 for (i
=0; i
<cfg
->bNumInterfaces
; i
++) {
1802 // SHOW_PROGRESS(output,"Test: looking at ifc %d, class is %d\n",i,cfg->interface[i].altsetting[0].bInterfaceClass);
1803 if (cfg
->interface
[i
].altsetting
[0].bInterfaceNumber
== ifcNumber
)
1804 return cfg
->interface
[i
].altsetting
[0].bInterfaceClass
;
1809 /* Parameter parsing */
1811 char* ReadParseParam(const char* FileName
, char *VariableName
)
1813 static int numLines
= 0;
1814 static char* ConfigBuffer
[MAXLINES
];
1815 char *VarName
, *Comment
=NULL
, *Equal
=NULL
;
1816 char *FirstQuote
, *LastQuote
, *P1
, *P2
;
1818 unsigned Len
=0, Pos
=0;
1819 char Str
[LINE_DIM
], *token
, *configPos
;
1822 // Reading and storing input during the first call
1824 if (strncmp(FileName
,"##",2) == 0) {
1825 if (verbose
) fprintf(output
,"\nRead long config from command line\n");
1826 // "Embedded" configuration data
1827 configPos
= (char*)FileName
;
1828 token
= strtok(configPos
, "\n");
1829 strncpy(Str
,token
,LINE_DIM
-1);
1831 if (strcmp(FileName
, "stdin")==0) {
1832 if (verbose
) fprintf(output
,"\nRead long config from stdin\n");
1835 if (verbose
) fprintf(output
,"\nRead config file: %s\n", FileName
);
1836 file
=fopen(FileName
, "r");
1839 fprintf(stderr
, "Error: Could not find file %s. Abort\n\n", FileName
);
1842 token
= fgets(Str
, LINE_DIM
-1, file
);
1845 while (token
!= NULL
&& numLines
< MAXLINES
) {
1850 if (Str
[Len
-1]=='\n' or Str
[Len
-1]=='\r')
1852 Equal
= strchr (Str
, '='); // search for equal sign
1853 Pos
= strcspn (Str
, ";#!"); // search for comment
1854 Comment
= (Pos
==Len
) ? NULL
: Str
+Pos
;
1855 if (Equal
==NULL
or ( Comment
!=NULL
and Comment
<=Equal
))
1856 goto NextLine
; // Comment or irrelevant, don't save
1858 ConfigBuffer
[numLines
] = malloc(Len
*sizeof(char));
1859 strcpy(ConfigBuffer
[numLines
],Str
);
1863 token
= strtok(NULL
, "\n");
1865 strncpy(Str
,token
,LINE_DIM
-1);
1867 token
= fgets(Str
, LINE_DIM
-1, file
);
1873 // Now checking for parameters
1875 while (Line
< numLines
) {
1876 strcpy(Str
,ConfigBuffer
[Line
]);
1877 Equal
= strchr (Str
, '='); // search for equal sign
1881 FirstQuote
=strchr (Equal
, '"'); // search for double quote char
1882 LastQuote
=strrchr (Equal
, '"');
1883 if (FirstQuote
!=NULL
) {
1884 if (LastQuote
==NULL
) {
1885 fprintf(stderr
, "Error reading parameters from file %s - Missing end quote:\n%s\n", FileName
, Str
);
1888 *FirstQuote
=*LastQuote
='\0';
1892 // removes leading/trailing spaces
1893 Pos
=strspn (Str
, " \t");
1894 if (Pos
==strlen(Str
)) {
1895 fprintf(stderr
, "Error reading parameters from file %s - Missing variable name:\n%s\n", FileName
, Str
);
1898 while ((P1
=strrchr(Str
, ' '))!=NULL
or (P2
=strrchr(Str
, '\t'))!=NULL
)
1899 if (P1
!=NULL
) *P1
='\0';
1900 else if (P2
!=NULL
) *P2
='\0';
1903 Pos
=strspn (Equal
, " \t");
1904 if (Pos
==strlen(Equal
)) {
1905 fprintf(stderr
, "Error reading parameter from file %s - Missing value:\n%s\n", FileName
, Str
);
1910 if (strcmp(VarName
, VariableName
)==0) { // Found it
1923 if (c
>= '0' && c
<= '9')
1925 if (c
>= 'a' && c
<= 'f')
1926 return c
- 'a' + 10;
1927 if (c
>= 'A' && c
<= 'F')
1928 return c
- 'A' + 10;
1933 int hex2byte(const char *hex
)
1936 a
= hex2num(*hex
++);
1939 b
= hex2num(*hex
++);
1942 return (a
<< 4) | b
;
1945 int hexstr2bin(const char *hex
, char *buffer
, int len
)
1949 const char *ipos
= hex
;
1950 char *opos
= buffer
;
1952 for (i
= 0; i
< len
; i
++) {
1964 char* version
= VERSION
;
1965 fprintf(output
,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
1966 " * Version %s (C) Josua Dietze 2013\n"
1967 " * Based on libusb1/libusbx\n\n"
1968 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version
);
1973 fprintf(output
,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
1974 " -h, --help this help\n"
1975 " -e, --version print version information and exit\n"
1976 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
1977 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
1978 " -p, --default-product NUM product ID of original mode (mandatory)\n"
1979 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
1980 " -P, --target-product NUM target mode product ID (optional)\n"
1981 " -C, --target-class NUM target mode device class (optional)\n"
1982 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
1983 " -g, --device-num NUM system device number (for hard ID)\n"
1984 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
1985 " -M, --message-content <msg> message to send (hex number as string)\n"
1986 " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n"
1987 " -n, --need-response read response to the message transfer (CSW)\n"
1988 " -r, --response-endpoint NUM read response from there (optional)\n"
1989 " -d, --detach-only detach the active driver, no further action\n"
1990 " -H, --huawei-mode apply a special procedure\n"
1991 " -S, --sierra-mode apply a special procedure\n"
1992 " -O, --sony-mode apply a special procedure\n"
1993 " -G, --gct-mode apply a special procedure\n"
1994 " -N, --sequans-mode apply a special procedure\n"
1995 " -A, --mobileaction-mode apply a special procedure\n"
1996 " -T, --kobil-mode apply a special procedure\n"
1997 " -L, --cisco-mode apply a special procedure\n"
1998 " -B, --qisda-mode apply a special procedure\n"
1999 " -E, --quanta-mode apply a special procedure\n"
2000 " -R, --reset-usb reset the device after all other actions\n"
2001 " -Q, --quiet don't show progress or error messages\n"
2002 " -W, --verbose print all settings and debug output\n"
2003 " -D, --sysmode specific result and syslog message\n"
2004 " -s, --success <seconds> switching result check with timeout\n"
2005 " -I, --no-inquire do not get SCSI attributes (default on)\n\n"
2006 " -c, --config-file <filename> load long configuration from file\n\n"
2007 " -t, --stdinput read long configuration from stdin\n\n"
2008 " -f, --long-config <text> get long configuration from string\n\n"
2009 " -i, --interface NUM select initial USB interface (default 0)\n"
2010 " -u, --configuration NUM select USB configuration\n"
2011 " -a, --altsetting NUM select alternative USB interface setting\n\n");