2 Mode switching tool for controlling flip flop (multiple device) USB gear
3 Version 1.1.9, 2011/08/05
5 Copyright (C) 2007 - 2011 Josua Dietze (mail to "usb_admin" at the domain
6 from the README; please do not post the complete address to the Internet!
7 Or write a personal message through the forum to "Josh". NO SUPPORT VIA
8 E-MAIL - please use the forum for that)
10 Command line parsing, decent usage/config output/handling, bugfixes and advanced
14 TargetClass parameter implementation to support new Option devices/firmware:
15 Paul Hardwick (http://www.pharscape.org)
17 Created with initial help from:
18 "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl)
20 Config file parsing stuff borrowed from:
21 Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
23 Hexstr2bin function borrowed from:
24 Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
26 Other contributions: see README
28 Device information contributors are named in the "usb_modeswitch.setup" file.
30 This program is free software; you can redistribute it and/or modify
31 it under the terms of the GNU General Public License as published by
32 the Free Software Foundation; either version 2 of the License, or
33 (at your option) any later version.
35 This program is distributed in the hope that it will be useful,
36 but WITHOUT ANY WARRANTY; without even the implied warranty of
37 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 GNU General Public License for more details:
40 http://www.gnu.org/licenses/gpl.txt
44 /* Recommended tab size: 4 */
46 #define VERSION "1.1.9"
57 #include "usb_modeswitch.h"
59 #define LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
60 #define LIBUSB_HAS_GET_DRIVER_NP
62 #define USB_ENDPOINT_IN LIBUSB_ENDPOINT_IN
63 #define USB_ENDPOINT_OUT LIBUSB_ENDPOINT_OUT
64 #define USB_ENDPOINT_TYPE_MASK LIBUSB_ENDPOINT_ADDRESS_MASK
65 #define USB_ENDPOINT_DIR_MASK LIBUSB_ENDPOINT_DIR_MASK
66 #define USB_ENDPOINT_TYPE_BULK LIBUSB_TRANSFER_TYPE_BULK
67 #define USB_TYPE_STANDARD LIBUSB_REQUEST_TYPE_STANDARD
68 #define USB_TYPE_CLASS LIBUSB_REQUEST_TYPE_CLASS
69 #define USB_TYPE_VENDOR LIBUSB_REQUEST_TYPE_VENDOR
70 #define USB_RECIP_DEVICE LIBUSB_RECIPIENT_DEVICE
71 #define USB_RECIP_INTERFACE LIBUSB_RECIPIENT_INTERFACE
72 #define USB_REQ_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
73 #define USB_REQ_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
75 #define usb_set_debug(x) libusb_set_debug(ctx, 3)
76 #define usb_close libusb_close
77 #define usb_get_string_simple libusb_get_string_descriptor_ascii
78 #define usb_reset libusb_reset_device
79 #define usb_claim_interface libusb_claim_interface
80 #define usb_clear_halt libusb_clear_halt
81 #define usb_release_interface libusb_release_interface
82 #define usb_control_msg libusb_control_transfer
83 #define usb_set_configuration libusb_set_configuration
84 #define usb_detach_kernel_driver_np libusb_detach_kernel_driver
86 /* libusb 1.0 wrappers */
87 int usb_bulk_io(struct libusb_device_handle
*handle
, int ep
, char *bytes
,
88 int size
, int timeout
)
92 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
93 r
= libusb_bulk_transfer(handle
, ep
& 0xff, bytes
, size
,
94 &actual_length
, timeout
);
96 /* if we timed out but did transfer some data, report as successful short
97 * read. FIXME: is this how libusb-0.1 works? */
98 if (r
== 0 || (r
== LIBUSB_ERROR_TIMEOUT
&& actual_length
> 0))
104 int usb_bulk_read(struct libusb_device_handle
*handle
, int ep
, char *bytes
,
105 int size
, int timeout
)
107 if (!(ep
& LIBUSB_ENDPOINT_IN
)) {
108 /* libusb-0.1 will strangely fix up a read request from endpoint
109 * 0x01 to be from endpoint 0x81. do the same thing here, but
110 * warn about this silly behaviour. */
111 printf("endpoint %x is missing IN direction bit, fixing", ep
);
112 ep
|= LIBUSB_ENDPOINT_IN
;
115 return usb_bulk_io(handle
, ep
, bytes
, size
, timeout
);
118 int usb_bulk_write(struct libusb_device_handle
*handle
, int ep
, char *bytes
,
119 int size
, int timeout
)
121 if (ep
& LIBUSB_ENDPOINT_IN
) {
122 /* libusb-0.1 on BSD strangely fix up a write request to endpoint
123 * 0x81 to be to endpoint 0x01. do the same thing here, but
124 * warn about this silly behaviour. */
125 printf("endpoint %x has excessive IN direction bit, fixing", ep
);
126 ep
&= ~LIBUSB_ENDPOINT_IN
;
129 return usb_bulk_io(handle
, ep
, bytes
, size
, timeout
);
132 static int usb_interrupt_io(libusb_device_handle
*handle
, int ep
, char *bytes
,
133 int size
, int timeout
)
137 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
138 r
= libusb_interrupt_transfer(handle
, ep
& 0xff, bytes
, size
,
139 &actual_length
, timeout
);
141 /* if we timed out but did transfer some data, report as successful short
142 * read. FIXME: is this how libusb-0.1 works? */
143 if (r
== 0 || (r
== LIBUSB_ERROR_TIMEOUT
&& actual_length
> 0))
144 return actual_length
;
149 int usb_interrupt_read(libusb_device_handle
*handle
, int ep
, char *bytes
,
150 int size
, int timeout
)
152 if (!(ep
& USB_ENDPOINT_IN
)) {
153 /* libusb-0.1 will strangely fix up a read request from endpoint
154 * 0x01 to be from endpoint 0x81. do the same thing here, but
155 * warn about this silly behaviour. */
156 printf("endpoint %x is missing IN direction bit, fixing", ep
);
157 ep
|= USB_ENDPOINT_IN
;
159 return usb_interrupt_io(handle
, ep
, bytes
, size
, timeout
);
162 int usb_interrupt_write(libusb_device_handle
*handle
, int ep
, char *bytes
,
163 int size
, int timeout
)
165 if (ep
& USB_ENDPOINT_IN
) {
166 /* libusb-0.1 on BSD strangely fix up a write request to endpoint
167 * 0x81 to be to endpoint 0x01. do the same thing here, but
168 * warn about this silly behaviour. */
169 printf("endpoint %x has excessive IN direction bit, fixing", ep
);
170 ep
&= ~USB_ENDPOINT_IN
;
173 return usb_interrupt_io(handle
, ep
, bytes
, size
, timeout
);
176 int usb_get_driver_np(struct libusb_device_handle
*dev
, int interface
,
177 char *name
, unsigned int namelen
)
179 int r
= libusb_kernel_driver_active(dev
, interface
);
181 /* libusb-1.0 doesn't expose driver name, so fill in a dummy value */
182 snprintf(name
, namelen
, "dummy");
187 #define LINE_DIM 1024
188 #define BUF_SIZE 4096
189 #define DESCR_MAX 129
191 #define SEARCH_DEFAULT 0
192 #define SEARCH_TARGET 1
194 #define SHOW_PROGRESS if (show_progress) printf
198 static struct libusb_context
*ctx
= NULL
;
199 static struct libusb_device
*dev
;
200 static struct libusb_device_handle
*devh
;
202 int DefaultVendor
=0, DefaultProduct
=0, TargetVendor
=0, TargetProduct
=-1, TargetClass
=0;
203 int MessageEndpoint
=0, ResponseEndpoint
=0, ReleaseDelay
=0;
204 int targetDeviceCount
=0;
205 int devnum
=-1, busnum
=-1;
208 char DetachStorageOnly
=0, HuaweiMode
=0, SierraMode
=0, SonyMode
=0, GCTMode
=0, KobilMode
=0;
209 char SequansMode
=0, MobileActionMode
=0, CiscoMode
=0;
210 char verbose
=0, show_progress
=1, ResetUSB
=0, CheckSuccess
=0, config_read
=0;
211 char NeedResponse
=0, NoDriverLoading
=0, InquireDevice
=1, sysmode
=0;
213 char imanufact
[DESCR_MAX
], iproduct
[DESCR_MAX
], iserial
[DESCR_MAX
];
215 char MessageContent
[LINE_DIM
];
216 char MessageContent2
[LINE_DIM
];
217 char MessageContent3
[LINE_DIM
];
218 char TargetProductList
[LINE_DIM
];
219 char ByteString
[LINE_DIM
/2];
220 char buffer
[BUF_SIZE
];
222 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
223 int Interface
= 0, Configuration
= 0, AltSetting
= -1;
226 static struct option long_options
[] = {
227 {"help", no_argument
, 0, 'h'},
228 {"version", no_argument
, 0, 'e'},
229 {"default-vendor", required_argument
, 0, 'v'},
230 {"default-product", required_argument
, 0, 'p'},
231 {"target-vendor", required_argument
, 0, 'V'},
232 {"target-product", required_argument
, 0, 'P'},
233 {"target-class", required_argument
, 0, 'C'},
234 {"message-endpoint", required_argument
, 0, 'm'},
235 {"message-content", required_argument
, 0, 'M'},
236 {"message-content2", required_argument
, 0, '2'},
237 {"message-content3", required_argument
, 0, '3'},
238 {"release-delay", required_argument
, 0, 'w'},
239 {"response-endpoint", required_argument
, 0, 'r'},
240 {"detach-only", no_argument
, 0, 'd'},
241 {"huawei-mode", no_argument
, 0, 'H'},
242 {"sierra-mode", no_argument
, 0, 'S'},
243 {"sony-mode", no_argument
, 0, 'O'},
244 {"kobil-mode", no_argument
, 0, 'T'},
245 {"gct-mode", no_argument
, 0, 'G'},
246 {"sequans-mode", no_argument
, 0, 'N'},
247 {"mobileaction-mode", no_argument
, 0, 'A'},
248 {"cisco-mode", no_argument
, 0, 'L'},
249 {"need-response", no_argument
, 0, 'n'},
250 {"reset-usb", no_argument
, 0, 'R'},
251 {"config-file", required_argument
, 0, 'c'},
252 {"verbose", no_argument
, 0, 'W'},
253 {"quiet", no_argument
, 0, 'Q'},
254 {"sysmode", no_argument
, 0, 'D'},
255 {"no-inquire", no_argument
, 0, 'I'},
256 {"check-success", required_argument
, 0, 's'},
257 {"interface", required_argument
, 0, 'i'},
258 {"configuration", required_argument
, 0, 'u'},
259 {"altsetting", required_argument
, 0, 'a'},
264 void readConfigFile(const char *configFilename
)
266 if (verbose
) printf("\nReading config file: %s\n", configFilename
);
267 ParseParamHex(configFilename
, TargetVendor
);
268 ParseParamHex(configFilename
, TargetProduct
);
269 ParseParamString(configFilename
, TargetProductList
);
270 ParseParamHex(configFilename
, TargetClass
);
271 ParseParamHex(configFilename
, DefaultVendor
);
272 ParseParamHex(configFilename
, DefaultProduct
);
273 ParseParamBool(configFilename
, DetachStorageOnly
);
274 ParseParamBool(configFilename
, HuaweiMode
);
275 ParseParamBool(configFilename
, SierraMode
);
276 ParseParamBool(configFilename
, SonyMode
);
277 ParseParamBool(configFilename
, GCTMode
);
278 ParseParamBool(configFilename
, KobilMode
);
279 ParseParamBool(configFilename
, SequansMode
);
280 ParseParamBool(configFilename
, MobileActionMode
);
281 ParseParamBool(configFilename
, CiscoMode
);
282 ParseParamBool(configFilename
, NoDriverLoading
);
283 ParseParamHex(configFilename
, MessageEndpoint
);
284 ParseParamString(configFilename
, MessageContent
);
285 ParseParamString(configFilename
, MessageContent2
);
286 ParseParamString(configFilename
, MessageContent3
);
287 ParseParamInt(configFilename
, ReleaseDelay
);
288 ParseParamHex(configFilename
, NeedResponse
);
289 ParseParamHex(configFilename
, ResponseEndpoint
);
290 ParseParamHex(configFilename
, ResetUSB
);
291 ParseParamHex(configFilename
, InquireDevice
);
292 ParseParamInt(configFilename
, CheckSuccess
);
293 ParseParamHex(configFilename
, Interface
);
294 ParseParamHex(configFilename
, Configuration
);
295 ParseParamHex(configFilename
, AltSetting
);
297 /* TargetProductList has priority over TargetProduct */
298 if (TargetProduct
!= -1 && TargetProductList
[0] != '\0') {
300 SHOW_PROGRESS("Warning: TargetProductList overrides TargetProduct!\n");
310 printf ("DefaultVendor= 0x%04x\n", DefaultVendor
);
312 printf ("DefaultVendor= not set\n");
313 if ( DefaultProduct
)
314 printf ("DefaultProduct= 0x%04x\n", DefaultProduct
);
316 printf ("DefaultProduct= not set\n");
318 printf ("TargetVendor= 0x%04x\n", TargetVendor
);
320 printf ("TargetVendor= not set\n");
321 if ( TargetProduct
> -1 )
322 printf ("TargetProduct= 0x%04x\n", TargetProduct
);
324 printf ("TargetProduct= not set\n");
326 printf ("TargetClass= 0x%02x\n", TargetClass
);
328 printf ("TargetClass= not set\n");
329 printf ("TargetProductList=\"%s\"\n", TargetProductList
);
330 printf ("\nDetachStorageOnly=%i\n", (int)DetachStorageOnly
);
331 printf ("HuaweiMode=%i\n", (int)HuaweiMode
);
332 printf ("SierraMode=%i\n", (int)SierraMode
);
333 printf ("SonyMode=%i\n", (int)SonyMode
);
334 printf ("GCTMode=%i\n", (int)GCTMode
);
335 printf ("KobilMode=%i\n", (int)KobilMode
);
336 printf ("SequansMode=%i\n", (int)SequansMode
);
337 printf ("MobileActionMode=%i\n", (int)MobileActionMode
);
338 printf ("CiscoMode=%i\n", (int)CiscoMode
);
339 if ( MessageEndpoint
)
340 printf ("MessageEndpoint=0x%02x\n", MessageEndpoint
);
342 printf ("MessageEndpoint= not set\n");
343 printf ("MessageContent=\"%s\"\n", MessageContent
);
344 if ( strlen(MessageContent2
) )
345 printf ("MessageContent2=\"%s\"\n", MessageContent2
);
346 if ( strlen(MessageContent3
) )
347 printf ("MessageContent3=\"%s\"\n", MessageContent3
);
348 printf ("NeedResponse=%i\n", (int)NeedResponse
);
349 if ( ResponseEndpoint
)
350 printf ("ResponseEndpoint=0x%02x\n", ResponseEndpoint
);
352 printf ("ResponseEndpoint= not set\n");
353 printf ("Interface=0x%02x\n", Interface
);
354 if ( Configuration
> 0 )
355 printf ("Configuration=0x%02x\n", Configuration
);
356 if ( AltSetting
> -1 )
357 printf ("AltSetting=0x%02x\n", AltSetting
);
359 printf ("\nInquireDevice enabled (default)\n");
361 printf ("\nInquireDevice disabled\n");
363 printf ("Success check enabled, max. wait time %d seconds\n", CheckSuccess
);
365 printf ("Success check disabled\n");
367 printf ("System integration mode enabled\n");
369 printf ("System integration mode disabled\n");
374 int readArguments(int argc
, char **argv
)
376 int c
, option_index
= 0, count
=0;
386 c
= getopt_long (argc
, argv
, "heWQDndHSOGTNALRIv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:",
387 long_options
, &option_index
);
389 /* Detect the end of the options. */
395 case 'R': ResetUSB
= 1; break;
396 case 'v': DefaultVendor
= strtol(optarg
, NULL
, 16); break;
397 case 'p': DefaultProduct
= strtol(optarg
, NULL
, 16); break;
398 case 'V': TargetVendor
= strtol(optarg
, NULL
, 16); break;
399 case 'P': TargetProduct
= strtol(optarg
, NULL
, 16); break;
400 case 'C': TargetClass
= strtol(optarg
, NULL
, 16); break;
401 case 'm': MessageEndpoint
= strtol(optarg
, NULL
, 16); break;
402 case 'M': strcpy(MessageContent
, optarg
); break;
403 case '2': strcpy(MessageContent2
, optarg
); break;
404 case '3': strcpy(MessageContent3
, optarg
); break;
405 case 'w': ReleaseDelay
= strtol(optarg
, NULL
, 10); count
--; break;
406 case 'n': NeedResponse
= 1; break;
407 case 'r': ResponseEndpoint
= strtol(optarg
, NULL
, 16); break;
408 case 'd': DetachStorageOnly
= 1; break;
409 case 'H': HuaweiMode
= 1; break;
410 case 'S': SierraMode
= 1; break;
411 case 'O': SonyMode
= 1; break;
412 case 'G': GCTMode
= 1; break;
413 case 'T': KobilMode
= 1; break;
414 case 'N': SequansMode
= 1; break;
415 case 'A': MobileActionMode
= 1; break;
416 case 'L': CiscoMode
= 1; break;
417 case 'c': readConfigFile(optarg
); break;
418 case 'W': verbose
= 1; show_progress
= 1; count
--; break;
419 case 'Q': show_progress
= 0; verbose
= 0; count
--; break;
420 case 'D': sysmode
= 1; count
--; break;
421 case 's': CheckSuccess
= strtol(optarg
, NULL
, 10); count
--; break;
422 case 'I': InquireDevice
= 0; break;
424 case 'i': Interface
= strtol(optarg
, NULL
, 16); break;
425 case 'u': Configuration
= strtol(optarg
, NULL
, 16); break;
426 case 'a': AltSetting
= strtol(optarg
, NULL
, 16); break;
438 default: /* Unsupported - error message has already been printed */
449 int main(int argc
, char **argv
)
451 int numDefaults
=0, specialMode
=0, sonySuccess
=0;
452 int currentConfig
=0, defaultClass
=0, interfaceClass
=0;
454 /* Make sure we have empty strings even if not set by config */
455 TargetProductList
[0] = '\0';
456 MessageContent
[0] = '\0';
457 MessageContent2
[0] = '\0';
458 MessageContent3
[0] = '\0';
461 signal(SIGTERM
, release_usb_device
);
463 * Parameter parsing, USB preparation/diagnosis, plausibility checks
466 /* Check command arguments, use params instead of config file when given */
467 switch (readArguments(argc
, argv
)) {
468 case 0: /* no argument or -W, -q or -s */
470 default: /* one or more arguments except -W, -q or -s */
471 if (!config_read
) /* if arguments contain -c, the config file was already processed */
472 if (verbose
) printf("Taking all parameters from the command line\n\n");
481 /* libusb initialization */
487 /* Plausibility checks. The default IDs are mandatory */
488 if (!(DefaultVendor
&& DefaultProduct
)) {
489 SHOW_PROGRESS("No default vendor/product ID given. Aborting.\n\n");
492 if (strlen(MessageContent
)) {
493 if (strlen(MessageContent
) % 2 != 0) {
494 fprintf(stderr
, "Error: MessageContent hex string has uneven length. Aborting.\n\n");
497 if ( hexstr2bin(MessageContent
, ByteString
, strlen(MessageContent
)/2) == -1) {
498 fprintf(stderr
, "Error: MessageContent %s\n is not a hex string. Aborting.\n\n", MessageContent
);
505 if (CheckSuccess
&& !(TargetVendor
|| TargetProduct
> -1 || TargetProductList
[0] != '\0') && !TargetClass
)
506 printf("Note: target parameter missing; success check limited\n");
508 /* Count existing target devices, remember for success check */
509 if (TargetVendor
|| TargetClass
) {
510 SHOW_PROGRESS("Looking for target devices ...\n");
511 search_devices(&targetDeviceCount
, TargetVendor
, TargetProduct
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
512 if (targetDeviceCount
) {
513 SHOW_PROGRESS(" Found devices in target mode or class (%d)\n", targetDeviceCount
);
515 SHOW_PROGRESS(" No devices in target mode or class found\n");
518 /* Count default devices, get the last one found */
519 SHOW_PROGRESS("Looking for default devices ...\n");
520 dev
= search_devices(&numDefaults
, DefaultVendor
, DefaultProduct
, "\0", TargetClass
, Configuration
, SEARCH_DEFAULT
);
522 SHOW_PROGRESS(" Found devices in default mode, class or configuration (%d)\n", numDefaults
);
524 SHOW_PROGRESS(" No devices in default mode found. Nothing to do. Bye.\n\n");
528 devnum
= libusb_get_device_address(dev
);
529 busnum
= libusb_get_bus_number(dev
);
530 SHOW_PROGRESS("Accessing device %03d on bus %03d ...\n", devnum
, busnum
);
531 libusb_open(dev
, &devh
);
533 SHOW_PROGRESS(" No default device found. Is it connected? Bye.\n\n");
537 /* Get current configuration of default device
538 * A configuration value of -1 denotes a quirky device which has
539 * trouble determining the current configuration. Just use the first
540 * branch (which may be incorrect)
542 if (Configuration
> -1)
543 currentConfig
= get_current_configuration(devh
);
545 SHOW_PROGRESS("Skipping the check for the current configuration\n");
549 /* Get class of default device/interface */
550 struct libusb_device_descriptor descriptor
;
551 libusb_get_device_descriptor(dev
, &descriptor
);
552 defaultClass
= descriptor
.bDeviceClass
;
553 struct libusb_config_descriptor
*config
;
554 libusb_get_config_descriptor(dev
, 0, &config
);
555 interfaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
556 libusb_free_config_descriptor(config
);
557 if (interfaceClass
== -1) {
558 fprintf(stderr
, "Error: getting the interface class failed. Aborting.\n\n");
562 if (defaultClass
== 0)
563 defaultClass
= interfaceClass
;
565 if (interfaceClass
== 8 && defaultClass
!= 8) {
566 /* Weird device with default class other than 0 and differing interface class */
567 SHOW_PROGRESS("Ambiguous Class/InterfaceClass: 0x%02x/0x08\n", defaultClass
);
571 /* Check or get endpoints */
572 if (strlen(MessageContent
) || InquireDevice
|| CiscoMode
) {
573 if (!MessageEndpoint
)
574 MessageEndpoint
= find_first_bulk_output_endpoint(dev
);
575 if (!MessageEndpoint
) {
576 fprintf(stderr
,"Error: message endpoint not given or found. Aborting.\n\n");
579 if (!ResponseEndpoint
)
580 ResponseEndpoint
= find_first_bulk_input_endpoint(dev
);
581 if (!ResponseEndpoint
) {
582 fprintf(stderr
,"Error: response endpoint not given or found. Aborting.\n\n");
585 SHOW_PROGRESS("Using endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
, ResponseEndpoint
);
588 if (!MessageEndpoint
|| !ResponseEndpoint
)
589 if (InquireDevice
&& defaultClass
== 0x08) {
590 SHOW_PROGRESS("Endpoints not found, skipping SCSI inquiry\n");
594 if (InquireDevice
&& show_progress
) {
595 if (defaultClass
== 0x08) {
596 SHOW_PROGRESS("Inquiring device details; driver will be detached ...\n");
598 if (deviceInquire() >= 0)
601 SHOW_PROGRESS("Not a storage device, skipping SCSI inquiry\n");
606 printf("\nUSB description data (for identification)\n");
607 printf("-------------------------\n");
608 printf("Manufacturer: %s\n", imanufact
);
609 printf(" Product: %s\n", iproduct
);
610 printf(" Serial No.: %s\n", iserial
);
611 printf("-------------------------\n");
614 /* Some scenarios are exclusive, so check for unwanted combinations */
615 specialMode
= DetachStorageOnly
+ HuaweiMode
+ SierraMode
+ SonyMode
+ KobilMode
616 + SequansMode
+ MobileActionMode
+ CiscoMode
;
617 if ( specialMode
> 1 ) {
618 SHOW_PROGRESS("Invalid mode combination. Check your configuration. Aborting.\n\n");
622 if ( !specialMode
&& !strlen(MessageContent
) && AltSetting
== -1 && Configuration
== 0 )
623 SHOW_PROGRESS("Warning: no switching method given.\n");
626 * The switching actions
630 openlog("usb_modeswitch", 0, LOG_SYSLOG
);
631 syslog(LOG_NOTICE
, "switching %04x:%04x (%s: %s)", DefaultVendor
, DefaultProduct
, imanufact
, iproduct
);
634 if (DetachStorageOnly
) {
635 SHOW_PROGRESS("Only detaching storage driver for switching ...\n");
636 if (InquireDevice
== 2) {
637 SHOW_PROGRESS(" Any driver was already detached for inquiry\n");
639 ret
= detachDriver();
641 SHOW_PROGRESS(" You may want to remove the storage driver manually\n");
662 if(MobileActionMode
) {
671 SHOW_PROGRESS("Note: ignoring CheckSuccess. Separate checks for Sony mode\n");
672 CheckSuccess
= 0; /* separate and implied success control */
673 sonySuccess
= switchSonyMode();
676 if (strlen(MessageContent
) && MessageEndpoint
) {
677 if (specialMode
== 0) {
678 if (InquireDevice
!= 2)
682 SHOW_PROGRESS("Warning: ignoring MessageContent. Can't combine with special mode\n");
685 if (Configuration
> 0) {
686 if (currentConfig
!= Configuration
) {
687 if (switchConfiguration()) {
688 currentConfig
= get_current_configuration(devh
);
689 if (currentConfig
== Configuration
) {
690 SHOW_PROGRESS("The configuration was set successfully\n");
692 SHOW_PROGRESS("Changing the configuration has failed\n");
696 SHOW_PROGRESS("Target configuration %d already active. Doing nothing\n", currentConfig
);
700 if (AltSetting
!= -1) {
704 /* No "removal" check if these are set */
705 if ((Configuration
> 0 || AltSetting
> -1) && !ResetUSB
) {
717 if (checkSuccess()) {
722 if (TargetProduct
< 1)
723 printf("ok:no_data\n");
725 printf("ok:%04x:%04x\n", TargetVendor
, TargetProduct
);
734 syslog(LOG_NOTICE
, "switched S.E. MD400 to modem mode");
735 printf("ok:\n"); /* ACM device, no driver action */
737 SHOW_PROGRESS("-> device should be stable now. Bye.\n\n");
741 SHOW_PROGRESS("-> switching was probably not completed. Bye.\n\n");
744 SHOW_PROGRESS("-> Run lsusb to note any changes. Bye.\n\n");
755 /* Get descriptor strings if available (identification details) */
756 void deviceDescription ()
760 memset (imanufact
, ' ', DESCR_MAX
);
761 memset (iproduct
, ' ', DESCR_MAX
);
762 memset (iserial
, ' ', DESCR_MAX
);
764 struct libusb_device_descriptor descriptor
;
765 libusb_get_device_descriptor(dev
, &descriptor
);
767 int iManufacturer
= descriptor
.iManufacturer
;
768 int iProduct
= descriptor
.iProduct
;
769 int iSerialNumber
= descriptor
.iSerialNumber
;
772 ret
= usb_get_string_simple(devh
, iManufacturer
, imanufact
, DESCR_MAX
);
774 fprintf(stderr
, "Error: could not get description string \"manufacturer\"\n");
776 strcpy(imanufact
, "not provided");
777 c
= strstr(imanufact
, " ");
779 memset((void*)c
, '\0', 1);
782 ret
= usb_get_string_simple(devh
, iProduct
, iproduct
, DESCR_MAX
);
784 fprintf(stderr
, "Error: could not get description string \"product\"\n");
786 strcpy(iproduct
, "not provided");
787 c
= strstr(iproduct
, " ");
789 memset((void*)c
, '\0', 1);
792 ret
= usb_get_string_simple(devh
, iSerialNumber
, iserial
, DESCR_MAX
);
794 fprintf(stderr
, "Error: could not get description string \"serial number\"\n");
796 strcpy(iserial
, "not provided");
797 c
= strstr(iserial
, " ");
799 memset((void*)c
, '\0', 1);
803 /* Print result of SCSI command INQUIRY (identification details) */
806 const unsigned char inquire_msg
[] = {
807 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
808 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
809 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
810 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
816 command
= malloc(31);
817 if (command
== NULL
) {
822 memcpy(command
, inquire_msg
, sizeof (inquire_msg
));
824 ret
= usb_claim_interface(devh
, Interface
);
826 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping device inquiry\n", ret
);
829 usb_clear_halt(devh
, MessageEndpoint
);
831 ret
= usb_bulk_write(devh
, MessageEndpoint
, (char *)command
, 31, 0);
833 SHOW_PROGRESS(" Could not send INQUIRY message (error %d)\n", ret
);
837 ret
= usb_bulk_read(devh
, ResponseEndpoint
, data
, 36, 0);
839 SHOW_PROGRESS(" Could not get INQUIRY response (error %d)\n", ret
);
843 i
= usb_bulk_read(devh
, ResponseEndpoint
, command
, 13, 0);
845 printf("\nSCSI inquiry data (for identification)\n");
846 printf("-------------------------\n");
848 printf(" Vendor String: ");
849 for (i
= 8; i
< 16; i
++) printf("%c",data
[i
]);
852 printf(" Model String: ");
853 for (i
= 16; i
< 32; i
++) printf("%c",data
[i
]);
856 printf("Revision String: ");
857 for (i
= 32; i
< 36; i
++) printf("%c",data
[i
]);
859 printf("\n-------------------------\n");
862 if (strlen(MessageContent
) == 0)
863 usb_clear_halt(devh
, MessageEndpoint
);
864 usb_release_interface(devh
, Interface
);
876 printf("Resetting usb device ");
882 success
= usb_reset(devh
);
883 if ( ((bpoint
% 10) == 0) && show_progress
) {
890 } while (success
< 0);
893 SHOW_PROGRESS("\n Reset failed. Can be ignored if device switched OK.\n");
895 SHOW_PROGRESS("\n OK, device was reset\n");
899 int switchSendMessage ()
901 const char* cmdHead
= "55534243";
904 msg
[0] = MessageContent
;
905 msg
[1] = MessageContent2
;
906 msg
[2] = MessageContent3
;
908 /* May be activated in future versions */
909 // if (MessageContent2[0] != '\0' || MessageContent3[0] != '\0')
912 SHOW_PROGRESS("Setting up communication with interface %d\n", Interface
);
913 if (InquireDevice
!= 2) {
914 ret
= usb_claim_interface(devh
, Interface
);
916 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping message sending\n", ret
);
920 usb_clear_halt(devh
, MessageEndpoint
);
921 SHOW_PROGRESS("Using endpoint 0x%02x for message sending ...\n", MessageEndpoint
);
925 for (i
=0; i
<3; i
++) {
926 if ( strlen(msg
[i
]) == 0)
929 if ( sendMessage(msg
[i
], i
+1) )
933 if ( strstr(msg
[i
],cmdHead
) != NULL
) {
935 SHOW_PROGRESS("Reading the response to message %d (CSW) ...\n", i
+1);
936 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
938 // Other bulk transfer
939 SHOW_PROGRESS("Reading the response to message %d ...\n", i
+1);
940 ret
= read_bulk(ResponseEndpoint
, ByteString
, strlen(msg
[i
])/2 );
947 SHOW_PROGRESS("Resetting response endpoint 0x%02x\n", ResponseEndpoint
);
948 ret
= usb_clear_halt(devh
, ResponseEndpoint
);
950 SHOW_PROGRESS(" Could not reset endpoint (probably harmless): %d\n", ret
);
951 SHOW_PROGRESS("Resetting message endpoint 0x%02x\n", MessageEndpoint
);
952 ret
= usb_clear_halt(devh
, MessageEndpoint
);
954 SHOW_PROGRESS(" Could not reset endpoint (probably harmless): %d\n", ret
);
957 SHOW_PROGRESS("Blocking the interface for %d ms before releasing ...\n", ReleaseDelay
);
958 usleep(ReleaseDelay
*1000);
960 ret
= usb_release_interface(devh
, Interface
);
966 SHOW_PROGRESS(" Device is gone, skipping any further commands\n");
972 #define SWITCH_CONFIG_MAXTRIES 5
974 int switchConfiguration ()
976 int count
= SWITCH_CONFIG_MAXTRIES
;
979 SHOW_PROGRESS("Changing configuration to %i ...\n", Configuration
);
980 while (((ret
= usb_set_configuration(devh
, Configuration
)) < 0) && --count
) {
981 SHOW_PROGRESS(" Device is busy, trying to detach kernel driver\n");
985 SHOW_PROGRESS(" OK, configuration set\n");
988 SHOW_PROGRESS(" Setting the configuration returned error %d. Trying to continue\n", ret
);
993 int switchAltSetting ()
997 SHOW_PROGRESS("Changing to alt setting %i ...\n", AltSetting
);
998 ret
= usb_claim_interface(devh
, Interface
);
999 ret
= libusb_set_interface_alt_setting(devh
, Interface
, AltSetting
);
1000 usb_release_interface(devh
, Interface
);
1002 SHOW_PROGRESS(" Changing to alt setting returned error %d. Trying to continue\n", ret
);
1005 SHOW_PROGRESS(" OK, changed to alt setting\n");
1011 void switchHuaweiMode ()
1015 SHOW_PROGRESS("Sending Huawei control message ...\n");
1016 ret
= usb_control_msg(devh
, USB_TYPE_STANDARD
| USB_RECIP_DEVICE
, USB_REQ_SET_FEATURE
, 00000001, 0, buffer
, 0, 1000);
1018 fprintf(stderr
, "Error: sending Huawei control message failed (error %d). Aborting.\n\n", ret
);
1021 SHOW_PROGRESS(" OK, Huawei control message sent\n");
1025 void switchSierraMode ()
1029 SHOW_PROGRESS("Trying to send Sierra control message\n");
1030 ret
= usb_control_msg(devh
, 0x40, 0x0b, 00000001, 0, buffer
, 0, 1000);
1032 fprintf(stderr
, "Error: sending Sierra control message failed (error %d). Aborting.\n\n", ret
);
1035 SHOW_PROGRESS(" OK, Sierra control message sent\n");
1039 void switchGCTMode ()
1043 ret
= usb_claim_interface(devh
, Interface
);
1045 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping GCT sequence \n", ret
);
1049 SHOW_PROGRESS("Sending GCT control message 1 ...\n");
1050 ret
= usb_control_msg(devh
, 0xa1, 0xa0, 0, Interface
, buffer
, 1, 1000);
1051 SHOW_PROGRESS("Sending GCT control message 2 ...\n");
1052 ret
= usb_control_msg(devh
, 0xa1, 0xfe, 0, Interface
, buffer
, 1, 1000);
1053 SHOW_PROGRESS(" OK, GCT control messages sent\n");
1054 usb_release_interface(devh
, Interface
);
1058 int switchKobilMode() {
1061 SHOW_PROGRESS("Sending Kobil control message ...\n");
1062 ret
= usb_control_msg(devh
, USB_TYPE_VENDOR
| USB_RECIP_DEVICE
| USB_ENDPOINT_IN
, 0x88, 0, 0, buffer
, 8, 1000);
1064 fprintf(stderr
, "Error: sending Kobil control message failed (error %d). Aborting.\n\n", ret
);
1067 SHOW_PROGRESS(" OK, Kobil control message sent\n");
1072 int switchSonyMode ()
1078 printf("Note: CheckSuccess pointless with Sony mode, disabling\n");
1082 SHOW_PROGRESS("Trying to send Sony control message\n");
1083 ret
= usb_control_msg(devh
, 0xc0, 0x11, 2, 0, buffer
, 3, 100);
1085 fprintf(stderr
, "Error: sending Sony control message failed (error %d). Aborting.\n\n", ret
);
1088 SHOW_PROGRESS(" OK, control message sent, waiting for device to return ...\n");
1093 /* Now waiting for the device to reappear */
1098 while ( dev
== 0 && i
< 30 ) {
1100 dev
= search_devices(&found
, DefaultVendor
, DefaultProduct
, "\0", TargetClass
, 0, SEARCH_TARGET
);
1105 if (show_progress
) {
1111 SHOW_PROGRESS("\n After %d seconds:",i
);
1113 SHOW_PROGRESS(" device came back, proceeding\n");
1114 libusb_open(dev
, &devh
);
1116 fprintf(stderr
, "Error: could not get handle on device\n");
1120 SHOW_PROGRESS(" device still gone, cancelling\n");
1125 SHOW_PROGRESS("Sending Sony control message again ...\n");
1126 ret
= usb_control_msg(devh
, 0xc0, 0x11, 2, 0, buffer
, 3, 100);
1128 fprintf(stderr
, "Error: sending Sony control message (2) failed (error %d)\n", ret
);
1131 SHOW_PROGRESS(" OK, control message sent\n");
1140 #define MOBILE_ACTION_READLOOP1 63
1141 #define MOBILE_ACTION_READLOOP2 73
1143 int switchActionMode ()
1146 SHOW_PROGRESS("Sending MobileAction control sequence ...\n");
1147 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1148 usb_control_msg(devh
, USB_TYPE_CLASS
+ USB_RECIP_INTERFACE
, 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1149 memcpy(buffer
, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE
);
1150 usb_control_msg(devh
, USB_TYPE_CLASS
+ USB_RECIP_INTERFACE
, 0x09, 0x0300, 0, buffer
, SIZE
, 1000);
1151 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1152 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1153 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1154 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1155 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1156 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1157 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1158 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1159 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1160 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1161 for (i
=0; i
< MOBILE_ACTION_READLOOP1
; i
++) {
1162 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1164 memcpy(buffer
, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE
);
1165 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1166 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1167 memcpy(buffer
, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE
);
1168 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1169 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1170 memcpy(buffer
, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE
);
1171 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1172 for (i
=0; i
< MOBILE_ACTION_READLOOP2
; i
++) {
1173 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1175 memcpy(buffer
, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE
);
1176 usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1177 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1178 memcpy(buffer
, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE
);
1179 ret
= usb_interrupt_write(devh
, EP_OUT
, buffer
, SIZE
, 1000);
1180 usb_interrupt_read(devh
, EP_IN
, buffer
, SIZE
, 1000);
1182 SHOW_PROGRESS(" MobileAction control sequence did not complete\n Last error was %d\n",ret
);
1185 SHOW_PROGRESS(" MobileAction control sequence complete\n");
1191 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1192 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1194 #define SQN_DEFAULT_DEVICE_MODE 0x00
1195 #define SQN_MASS_STORAGE_MODE 0x01
1196 #define SQN_CUSTOM_DEVICE_MODE 0x02
1198 int switchSequansMode() {
1201 SHOW_PROGRESS("Sending Sequans vendor request\n");
1202 ret
= usb_control_msg(devh
, USB_TYPE_VENDOR
| USB_RECIP_DEVICE
, SQN_SET_DEVICE_MODE_REQUEST
, SQN_CUSTOM_DEVICE_MODE
, 0, buffer
, 0, 1000);
1204 fprintf(stderr
, "Error: sending Sequans request failed (error %d). Aborting.\n\n", ret
);
1207 SHOW_PROGRESS(" OK, Sequans request was sent\n");
1212 int switchCiscoMode() {
1216 SHOW_PROGRESS("Preparing for sending Cisco message sequence\n");
1218 msg
[0] = "55534243f83bcd810002000080000afd000000030000000100000000000000";
1219 msg
[1] = "55534243984300820002000080000afd000000070000000100000000000000";
1220 msg
[2] = "55534243984300820000000000000afd000100071000000000000000000000";
1221 msg
[3] = "55534243984300820002000080000afd000200230000000100000000000000";
1222 msg
[4] = "55534243984300820000000000000afd000300238200000000000000000000";
1223 msg
[5] = "55534243984300820002000080000afd000200260000000100000000000000";
1224 msg
[6] = "55534243984300820000000000000afd00030026c800000000000000000000";
1225 msg
[7] = "55534243d84c04820002000080000afd000010730000000100000000000000";
1226 msg
[8] = "55534243d84c04820002000080000afd000200240000000100000000000000";
1227 msg
[9] = "55534243d84c04820000000000000afd000300241300000000000000000000";
1228 msg
[10] = "55534243d84c04820000000000000afd000110732400000000000000000000";
1230 SHOW_PROGRESS("Setting up communication with interface %d\n", Interface
);
1231 ret
= usb_claim_interface(devh
, Interface
);
1233 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping message sending\n", ret
);
1236 // usb_clear_halt(devh, MessageEndpoint);
1240 for (i
=0; i
<11; i
++) {
1241 if ( sendMessage(msg
[i
], i
+1) )
1244 SHOW_PROGRESS("Reading the response (CSW) to bulk message %d ...\n",i
+1);
1245 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
1251 SHOW_PROGRESS("Blocking the interface for %d ms before releasing ...\n", ReleaseDelay
);
1252 usleep(ReleaseDelay
*1000);
1254 ret
= usb_release_interface(devh
, Interface
);
1260 SHOW_PROGRESS("Device returned error, skipping any further commands\n");
1272 #ifndef LIBUSB_HAS_GET_DRIVER_NP
1273 printf(" Cant't do driver detection and detaching on this platform.\n");
1277 SHOW_PROGRESS("Looking for active driver ...\n");
1278 ret
= usb_get_driver_np(devh
, Interface
, buffer
, BUF_SIZE
);
1280 SHOW_PROGRESS(" No driver found. Either detached before or never attached\n");
1283 SHOW_PROGRESS(" OK, driver found (\"%s\")\n", buffer
);
1284 if (DetachStorageOnly
&& strcmp(buffer
,"usb-storage")) {
1285 SHOW_PROGRESS(" Warning: driver is not usb-storage\n");
1289 #ifndef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
1290 SHOW_PROGRESS(" Can't do driver detaching on this platform\n");
1294 ret
= usb_detach_kernel_driver_np(devh
, Interface
);
1296 SHOW_PROGRESS(" OK, driver \"%s\" detached\n", buffer
);
1298 SHOW_PROGRESS(" Driver \"%s\" detach failed with error %d. Trying to continue\n", buffer
, ret
);
1304 int sendMessage(char* message
, int count
)
1306 int message_length
, ret
;
1308 if (strlen(message
) % 2 != 0) {
1309 fprintf(stderr
, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count
);
1312 message_length
= strlen(message
) / 2;
1313 if ( hexstr2bin(message
, ByteString
, message_length
) == -1) {
1314 fprintf(stderr
, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", count
, MessageContent
);
1317 SHOW_PROGRESS("Trying to send message %d to endpoint 0x%02x ...\n", count
, MessageEndpoint
);
1319 ret
= write_bulk(MessageEndpoint
, ByteString
, message_length
);
1330 int newTargetCount
, success
=0;
1332 SHOW_PROGRESS("\nChecking for mode switch (max. %d times, once per second) ...\n", CheckSuccess
);
1335 /* If target parameters are given, don't check for vanished device
1336 * Changed for Cisco AM10 where a new device is added while the install
1337 * storage device stays active
1339 if ((TargetVendor
|| TargetClass
) && devh
) {
1344 /* if target ID is not given but target class is, assign default as target;
1345 * it will be needed for sysmode output
1347 if (!TargetVendor
&& TargetClass
) {
1348 TargetVendor
= DefaultVendor
;
1349 TargetProduct
= DefaultProduct
;
1352 /* devh is 0 if device vanished during command transmission or if target params were given
1355 for (i
=0; i
< CheckSuccess
; i
++) {
1357 /* Test if default device still can be accessed; positive result does
1358 * not necessarily mean failure
1360 SHOW_PROGRESS(" Waiting for original device to vanish ...\n");
1362 ret
= usb_claim_interface(devh
, Interface
);
1363 usb_release_interface(devh
, Interface
);
1365 SHOW_PROGRESS(" Original device can't be accessed anymore. Good.\n");
1370 if (i
== CheckSuccess
-1) {
1371 SHOW_PROGRESS(" Original device still present after the timeout\n\nMode switch most likely failed. Bye.\n\n");
1376 if ( TargetVendor
&& (TargetProduct
> -1 || TargetProductList
[0] != '\0') ) {
1378 /* Recount target devices (compare with previous count) if target data is given.
1379 * Target device on the same bus with higher device number is returned,
1380 * description is read for syslog message
1382 for (i
=i
; i
< CheckSuccess
; i
++) {
1383 SHOW_PROGRESS(" Searching for target devices ...\n");
1384 dev
= search_devices(&newTargetCount
, TargetVendor
, TargetProduct
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
1385 if (dev
&& (newTargetCount
> targetDeviceCount
)) {
1386 printf("\nFound target device, now opening\n");
1387 libusb_open(dev
, &devh
);
1388 deviceDescription();
1392 printf("\nFound target device %03d on bus %03d\n", \
1393 libusb_get_device_address(dev
), libusb_get_bus_number(dev
));
1394 printf("\nTarget device description data\n");
1395 printf("-------------------------\n");
1396 printf("Manufacturer: %s\n", imanufact
);
1397 printf(" Product: %s\n", iproduct
);
1398 printf(" Serial No.: %s\n", iserial
);
1399 printf("-------------------------\n");
1401 SHOW_PROGRESS(" Found correct target device\n\nMode switch succeeded. Bye.\n\n");
1405 if (i
== CheckSuccess
-1) {
1406 SHOW_PROGRESS(" No new devices in target mode or class found\n\nMode switch has failed. Bye.\n\n");
1411 /* No target data given, rely on the vanished device */
1413 SHOW_PROGRESS(" (For a better success check provide target IDs or class)\n");
1414 SHOW_PROGRESS(" Original device vanished after switching\n\nMode switch most likely succeeded. Bye.\n\n");
1421 syslog(LOG_NOTICE
, "switched to new device, but hit libusb1 bug");
1427 syslog(LOG_NOTICE
, "switched to %04x:%04x (%s: %s)", TargetVendor
, TargetProduct
, imanufact
, iproduct
);
1432 syslog(LOG_NOTICE
, "device seems to have switched");
1444 int write_bulk(int endpoint
, char *message
, int length
)
1447 ret
= usb_bulk_write(devh
, endpoint
, message
, length
, 3000);
1449 SHOW_PROGRESS(" OK, message successfully sent\n");
1452 SHOW_PROGRESS(" Device seems to have vanished right after sending. Good.\n");
1454 SHOW_PROGRESS(" Sending the message returned error %d. Trying to continue\n", ret
);
1459 int read_bulk(int endpoint
, char *buffer
, int length
)
1462 ret
= usb_bulk_read(devh
, endpoint
, buffer
, length
, 3000);
1463 usb_bulk_read(devh
, endpoint
, buffer
, 13, 100);
1465 SHOW_PROGRESS(" OK, response successfully read (%d bytes).\n", ret
);
1468 SHOW_PROGRESS(" Device seems to have vanished after reading. Good.\n");
1470 SHOW_PROGRESS(" Response reading got error %d\n", ret
);
1475 void release_usb_device(int dummy
) {
1476 SHOW_PROGRESS("Program cancelled by system. Bye.\n\n");
1478 usb_release_interface(devh
, Interface
);
1488 /* Iterates over busses and devices, counts the ones with the given
1489 * ID/class and returns the last one of them
1491 struct libusb_device
* search_devices( int *numFound
, int vendor
, int product
, char* productList
, int targetClass
, int configuration
, int mode
)
1493 char *listcopy
=NULL
, *token
, buffer
[2];
1495 struct libusb_device
* right_dev
= NULL
;
1496 struct libusb_device_handle
*testdevh
;
1498 /* only target class given, target vendor and product assumed unchanged */
1499 if ( targetClass
&& !(vendor
|| product
) ) {
1500 vendor
= DefaultVendor
;
1501 product
= DefaultProduct
;
1506 if (!vendor
|| (!product
&& productList
== '\0') )
1509 if (productList
!= '\0')
1510 listcopy
= malloc(strlen(productList
)+1);
1512 struct libusb_device
**devs
;
1515 if (libusb_get_device_list(ctx
, &devs
) < 0) {
1516 perror ("failed to access USB");
1520 while ((dev
= devs
[i
++]) != NULL
) {
1521 struct libusb_device_descriptor descriptor
;
1522 libusb_get_device_descriptor(dev
, &descriptor
);
1523 int idVendor
= descriptor
.idVendor
;
1524 int idProduct
= descriptor
.idProduct
;
1527 printf (" searching devices, found USB ID %04x:%04x\n", idVendor
, idProduct
);
1528 if (idVendor
!= vendor
)
1531 printf (" found matching vendor ID\n");
1532 // product list given
1533 if ( strlen(productList
) ) {
1534 strcpy(listcopy
, productList
);
1535 token
= strtok(listcopy
, ",");
1536 while (token
!= NULL
) {
1537 if (strlen(token
) != 4) {
1538 SHOW_PROGRESS("Error: entry in product ID list has wrong length: %s. Ignoring\n", token
);
1541 if ( hexstr2bin(token
, buffer
, strlen(token
)/2) == -1) {
1542 SHOW_PROGRESS("Error: entry in product ID list is not a hex string: %s. Ignoring\n", token
);
1546 product
+= (unsigned char)buffer
[0];
1548 product
+= (unsigned char)buffer
[1];
1549 if (product
== idProduct
) {
1551 printf (" found matching product ID from list\n");
1556 if (libusb_get_device_address(dev
) >= devnum
&& libusb_get_bus_number(dev
) == busnum
) {
1558 TargetProduct
= idProduct
;
1564 token
= strtok(NULL
, ",");
1566 /* Product ID is given */
1568 if (product
== idProduct
) {
1570 printf (" found matching product ID\n");
1571 if (targetClass
== 0 && configuration
< 1) {
1575 printf (" adding device\n");
1577 if (targetClass
!= 0) {
1578 struct libusb_device_descriptor descriptor
;
1579 libusb_get_device_descriptor(dev
, &descriptor
);
1580 devClass
= descriptor
.bDeviceClass
;
1581 struct libusb_config_descriptor
*config
;
1582 libusb_get_config_descriptor(dev
, 0, &config
);
1583 int ifaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
1584 libusb_free_config_descriptor(config
);
1587 devClass
= ifaceClass
;
1589 /* Check for some quirky devices */
1590 if (devClass
!= ifaceClass
)
1591 devClass
= ifaceClass
;
1592 if (devClass
== targetClass
) {
1594 printf (" target class %02x matching\n", targetClass
);
1595 if (mode
== SEARCH_TARGET
) {
1599 printf (" adding device\n");
1602 printf (" not adding device\n");
1605 printf (" target class %02x not matching\n", targetClass
);
1606 if (mode
== SEARCH_DEFAULT
) {
1610 printf (" adding device\n");
1614 // check configuration (only if no target class given)
1615 libusb_open(dev
, &testdevh
);
1616 int testconfig
= get_current_configuration(testdevh
);
1617 if (testconfig
!= configuration
) {
1619 printf (" device configuration %d not matching parameter\n", testconfig
);
1623 printf (" adding device\n");
1626 printf (" not adding device, target configuration already set\n");
1629 /* hack: if busnum has other than init value, we are called from
1630 * successCheck() and do probe for plausible new devnum/busnum
1633 if (libusb_get_device_address(dev
) < devnum
|| libusb_get_bus_number(dev
) != busnum
) {
1635 printf (" warning: busnum/devnum indicates an unrelated device\n");
1640 if (productList
!= NULL
)
1646 #define USB_DIR_OUT 0x00
1647 #define USB_DIR_IN 0x80
1649 /* Autodetect bulk endpoints (ab) */
1651 int find_first_bulk_output_endpoint(struct libusb_device
*dev
)
1654 struct libusb_config_descriptor
*config
;
1655 libusb_get_config_descriptor(dev
, 0, &config
);
1656 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1657 const struct libusb_endpoint_descriptor
*ep
;
1659 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1660 ep
=&(alt
->endpoint
[i
]);
1661 if( ( (ep
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
) &&
1662 ( (ep
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
) ) {
1663 return ep
->bEndpointAddress
;
1666 libusb_free_config_descriptor(config
);
1672 int find_first_bulk_input_endpoint(struct libusb_device
*dev
)
1675 struct libusb_config_descriptor
*config
;
1676 libusb_get_config_descriptor(dev
, 0, &config
);
1677 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1678 const struct libusb_endpoint_descriptor
*ep
;
1679 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1680 ep
=&(alt
->endpoint
[i
]);
1681 if( ( (ep
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
) &&
1682 ( (ep
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
) ) {
1683 return ep
->bEndpointAddress
;
1686 libusb_free_config_descriptor(config
);
1691 int get_current_configuration(struct libusb_device_handle
* devh
)
1695 SHOW_PROGRESS("Getting the current device configuration ...\n");
1696 ret
= usb_control_msg(devh
, USB_DIR_IN
+ USB_TYPE_STANDARD
+ USB_RECIP_DEVICE
, USB_REQ_GET_CONFIGURATION
, 0, 0, buffer
, 1, 1000);
1698 // There are quirky devices which fail to respond properly to this command
1699 fprintf(stderr
, "Error getting the current configuration (error %d). Assuming configuration 1.\n", ret
);
1700 if (Configuration
) {
1701 fprintf(stderr
, " No configuration setting possible for this device.\n");
1706 SHOW_PROGRESS(" OK, got current device configuration (%d)\n", buffer
[0]);
1712 /* Parameter parsing */
1714 char* ReadParseParam(const char* FileName
, char *VariableName
)
1716 static char Str
[LINE_DIM
];
1717 char *VarName
, *Comment
=NULL
, *Equal
=NULL
;
1718 char *FirstQuote
, *LastQuote
, *P1
, *P2
;
1719 int Line
=0, Len
=0, Pos
=0;
1720 FILE *file
=fopen(FileName
, "r");
1723 fprintf(stderr
, "Error: Could not find file %s\n\n", FileName
);
1727 while (fgets(Str
, LINE_DIM
-1, file
) != NULL
) {
1730 if (Len
==0) goto Next
;
1731 if (Str
[Len
-1]=='\n' or Str
[Len
-1]=='\r') Str
[--Len
]='\0';
1732 Equal
= strchr (Str
, '='); // search for equal sign
1733 Pos
= strcspn (Str
, ";#!"); // search for comment
1734 Comment
= (Pos
==Len
) ? NULL
: Str
+Pos
;
1735 if (Equal
==NULL
or ( Comment
!=NULL
and Comment
<=Equal
)) goto Next
; // Only comment
1737 if (Comment
!=NULL
) *Comment
='\0';
1740 FirstQuote
=strchr (Equal
, '"'); // search for double quote char
1741 LastQuote
=strrchr (Equal
, '"');
1742 if (FirstQuote
!=NULL
) {
1743 if (LastQuote
==NULL
) {
1744 fprintf(stderr
, "Error reading parameter file %s line %d - Missing end quote.\n", FileName
, Line
);
1747 *FirstQuote
=*LastQuote
='\0';
1751 // removes leading/trailing spaces
1752 Pos
=strspn (Str
, " \t");
1753 if (Pos
==strlen(Str
)) {
1754 fprintf(stderr
, "Error reading parameter file %s line %d - Missing variable name.\n", FileName
, Line
);
1755 goto Next
; // No function name
1757 while ((P1
=strrchr(Str
, ' '))!=NULL
or (P2
=strrchr(Str
, '\t'))!=NULL
)
1758 if (P1
!=NULL
) *P1
='\0';
1759 else if (P2
!=NULL
) *P2
='\0';
1762 Pos
=strspn (Equal
, " \t");
1763 if (Pos
==strlen(Equal
)) {
1764 fprintf(stderr
, "Error reading parameter file %s line %d - Missing value.\n", FileName
, Line
);
1765 goto Next
; // No function name
1769 if (strcmp(VarName
, VariableName
)==0) { // Found it
1783 if (c
>= '0' && c
<= '9')
1785 if (c
>= 'a' && c
<= 'f')
1786 return c
- 'a' + 10;
1787 if (c
>= 'A' && c
<= 'F')
1788 return c
- 'A' + 10;
1793 int hex2byte(const char *hex
)
1796 a
= hex2num(*hex
++);
1799 b
= hex2num(*hex
++);
1802 return (a
<< 4) | b
;
1805 int hexstr2bin(const char *hex
, char *buffer
, int len
)
1809 const char *ipos
= hex
;
1810 char *opos
= buffer
;
1812 for (i
= 0; i
< len
; i
++) {
1824 char* version
= VERSION
;
1825 printf("\n * usb_modeswitch: handle USB devices with multiple modes\n");
1826 printf(" * Version %s (C) Josua Dietze 2011\n", version
);
1827 printf(" * Based on libusb0 (0.1.12 and above)\n\n");
1828 printf(" ! PLEASE REPORT NEW CONFIGURATIONS !\n\n");
1833 printf ("\nUsage: usb_modeswitch [-hvpVPmMrndHSOGATRIQWDiua] [-c filename]\n\n");
1834 printf (" -h, --help this help\n");
1835 printf (" -e, --version print version information and exit\n");
1836 printf (" -v, --default-vendor NUM vendor ID of original mode (mandatory)\n");
1837 printf (" -p, --default-product NUM product ID of original mode (mandatory)\n");
1838 printf (" -V, --target-vendor NUM target mode vendor ID (optional)\n");
1839 printf (" -P, --target-product NUM target mode product ID (optional)\n");
1840 printf (" -C, --target-class NUM target mode device class (optional)\n");
1841 printf (" -m, --message-endpoint NUM direct the message transfer there (optional)\n");
1842 printf (" -M, --message-content <msg> message to send (hex number as string)\n");
1843 printf (" -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n");
1844 printf (" -n, --need-response read response to the message transfer (CSW)\n");
1845 printf (" -r, --response-endpoint NUM read response from there (optional)\n");
1846 printf (" -d, --detach-only detach the active driver, no further action\n");
1847 printf (" -H, --huawei-mode apply a special procedure\n");
1848 printf (" -S, --sierra-mode apply a special procedure\n");
1849 printf (" -O, --sony-mode apply a special procedure\n");
1850 printf (" -G, --gct-mode apply a special procedure\n");
1851 printf (" -N, --sequans-mode apply a special procedure\n");
1852 printf (" -A, --mobileaction-mode apply a special procedure\n");
1853 printf (" -T, --kobil-mode apply a special procedure\n");
1854 printf (" -L, --cisco-mode apply a special procedure\n");
1855 printf (" -R, --reset-usb reset the device after all other actions\n");
1856 printf (" -Q, --quiet don't show progress or error messages\n");
1857 printf (" -W, --verbose print all settings and debug output\n");
1858 printf (" -D, --sysmode specific result and syslog message\n");
1859 printf (" -s, --success <seconds> switching result check with timeout\n");
1860 printf (" -I, --no-inquire do not get SCSI attributes (default on)\n\n");
1861 printf (" -c, --config-file <filename> load configuration from file\n\n");
1862 printf (" -i, --interface NUM select initial USB interface (default 0)\n");
1863 printf (" -u, --configuration NUM select USB configuration\n");
1864 printf (" -a, --altsetting NUM select alternative USB interface setting\n\n");