2 Mode switching tool for controlling flip flop (multiple device) USB gear
3 Version 1.1.7, 2011/02/27
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
12 Joakim Wennergren (jokedst) (gmail.com)
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.6"
60 inline int get_devnum(struct usb_device
* dev
)
64 inline int get_busnum(struct usb_device
* dev
)
66 return (int)strtol(dev
->bus
->dirname
,NULL
,10);
72 #define USB_ENDPOINT_IN LIBUSB_ENDPOINT_IN
73 #define USB_ENDPOINT_OUT LIBUSB_ENDPOINT_OUT
74 #define USB_ENDPOINT_TYPE_MASK LIBUSB_ENDPOINT_ADDRESS_MASK
75 #define USB_ENDPOINT_DIR_MASK LIBUSB_ENDPOINT_DIR_MASK
76 #define USB_ENDPOINT_TYPE_BULK LIBUSB_TRANSFER_TYPE_BULK
77 #define USB_TYPE_STANDARD LIBUSB_REQUEST_TYPE_STANDARD
78 #define USB_TYPE_VENDOR LIBUSB_REQUEST_TYPE_VENDOR
79 #define USB_RECIP_DEVICE LIBUSB_RECIPIENT_DEVICE
80 #define USB_REQ_SET_FEATURE LIBUSB_REQUEST_SET_FEATURE
81 #define USB_REQ_GET_CONFIGURATION LIBUSB_REQUEST_GET_CONFIGURATION
83 #define LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
84 #define LIBUSB_HAS_GET_DRIVER_NP
87 #define usb_device libusb_device
88 #define usb_dev_handle libusb_device_handle
89 #define usb_endpoint_descriptor libusb_endpoint_descriptor
91 #define usb_init() libusb_init ( &ctx )
92 #define usb_set_debug(x) libusb_set_debug( ctx, 3 )
93 #define usb_find_busses() (0)
94 #define usb_find_devices() (0)
95 #define usb_close libusb_close
96 #define usb_get_string_simple libusb_get_string_descriptor_ascii
97 #define usb_reset libusb_reset_device
98 #define usb_claim_interface libusb_claim_interface
99 #define usb_clear_halt libusb_clear_halt
100 #define usb_release_interface libusb_release_interface
101 #define usb_control_msg libusb_control_transfer
102 #define usb_set_configuration libusb_set_configuration
103 #define usb_detach_kernel_driver_np libusb_detach_kernel_driver
105 libusb_device_handle
* usb_open(libusb_device
*dev
){
106 libusb_device_handle
* handle
;
107 libusb_open(dev
, &handle
);
111 int get_busnum(struct libusb_device
* dev
)
113 return libusb_get_bus_number(dev
);
116 int get_devnum(struct libusb_device
* dev
)
118 return libusb_get_device_address(dev
);
121 int usb_get_driver_np(struct libusb_device_handle
*dev
, int interface
,
122 char *name
, unsigned int namelen
)
124 int r
= libusb_kernel_driver_active(dev
, interface
);
126 /* libusb-1.0 doesn't expose driver name, so fill in a dummy value */
127 snprintf(name
, namelen
, "dummy");
132 int usb_bulk_io(struct libusb_device_handle
*dev
, int ep
, char *bytes
,
133 int size
, int timeout
)
137 printf("endpoint %x size %d timeout %d", ep
, size
, timeout
);
138 r
= libusb_bulk_transfer(dev
, 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_bulk_read(struct usb_dev_handle
*dev
, int ep
, char *bytes
,
150 int size
, int timeout
)
152 if (!(ep
& LIBUSB_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 puts("endpoint %x is missing IN direction bit, fixing");
157 ep
|= LIBUSB_ENDPOINT_IN
;
160 return usb_bulk_io(dev
, ep
, bytes
, size
, timeout
);
163 int usb_bulk_write(struct usb_dev_handle
*dev
, int ep
, char *bytes
,
164 int size
, int timeout
)
166 if (ep
& LIBUSB_ENDPOINT_IN
) {
167 /* libusb-0.1 on BSD strangely fix up a write request to endpoint
168 * 0x81 to be to endpoint 0x01. do the same thing here, but
169 * warn about this silly behaviour. */
170 puts("endpoint %x has excessive IN direction bit, fixing");
171 ep
&= ~LIBUSB_ENDPOINT_IN
;
174 return usb_bulk_io(dev
, ep
, bytes
, size
, timeout
);
177 static struct libusb_context
*ctx
= NULL
;
181 #include "usb_modeswitch.h"
183 #define LINE_DIM 1024
184 #define BUF_SIZE 4096
185 #define DESCR_MAX 129
187 #define SEARCH_DEFAULT 0
188 #define SEARCH_TARGET 1
190 #define SHOW_PROGRESS if (show_progress) printf
192 //int write_bulk(int endpoint, char *message, int length);
193 //int read_bulk(int endpoint, char *buffer, int length);
195 //int find_first_bulk_output_endpoint(struct usb_device *dev);
196 //int find_first_bulk_input_endpoint(struct usb_device *dev);
200 struct usb_device
*dev
;
201 struct usb_dev_handle
*devh
;
203 int DefaultVendor
=0, DefaultProduct
=0, TargetVendor
=0, TargetProduct
=-1, TargetClass
=0;
204 int MessageEndpoint
=0, ResponseEndpoint
=0, ReleaseDelay
=0;
205 int targetDeviceCount
=0;
206 int devnum
=-1, busnum
=-1;
209 char DetachStorageOnly
=0, HuaweiMode
=0, SierraMode
=0, SonyMode
=0, GCTMode
=0, KobilMode
=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 {"need-response", no_argument
, 0, 'n'},
247 {"reset-usb", no_argument
, 0, 'R'},
248 {"config-file", required_argument
, 0, 'c'},
249 {"verbose", no_argument
, 0, 'W'},
250 {"quiet", no_argument
, 0, 'Q'},
251 {"sysmode", no_argument
, 0, 'D'},
252 {"no-inquire", no_argument
, 0, 'I'},
253 {"check-success", required_argument
, 0, 's'},
254 {"interface", required_argument
, 0, 'i'},
255 {"configuration", required_argument
, 0, 'u'},
256 {"altsetting", required_argument
, 0, 'a'},
261 void readConfigFile(const char *configFilename
)
263 if (verbose
) printf("\nReading config file: %s\n", configFilename
);
264 ParseParamHex(configFilename
, TargetVendor
);
265 ParseParamHex(configFilename
, TargetProduct
);
266 ParseParamString(configFilename
, TargetProductList
);
267 ParseParamHex(configFilename
, TargetClass
);
268 ParseParamHex(configFilename
, DefaultVendor
);
269 ParseParamHex(configFilename
, DefaultProduct
);
270 ParseParamBool(configFilename
, DetachStorageOnly
);
271 ParseParamBool(configFilename
, HuaweiMode
);
272 ParseParamBool(configFilename
, SierraMode
);
273 ParseParamBool(configFilename
, SonyMode
);
274 ParseParamBool(configFilename
, GCTMode
);
275 ParseParamBool(configFilename
, KobilMode
);
276 ParseParamBool(configFilename
, NoDriverLoading
);
277 ParseParamHex(configFilename
, MessageEndpoint
);
278 ParseParamString(configFilename
, MessageContent
);
279 ParseParamString(configFilename
, MessageContent2
);
280 ParseParamString(configFilename
, MessageContent3
);
281 ParseParamInt(configFilename
, ReleaseDelay
);
282 ParseParamHex(configFilename
, NeedResponse
);
283 ParseParamHex(configFilename
, ResponseEndpoint
);
284 ParseParamHex(configFilename
, ResetUSB
);
285 ParseParamHex(configFilename
, InquireDevice
);
286 ParseParamInt(configFilename
, CheckSuccess
);
287 ParseParamHex(configFilename
, Interface
);
288 ParseParamHex(configFilename
, Configuration
);
289 ParseParamHex(configFilename
, AltSetting
);
291 /* TargetProductList has priority over TargetProduct */
292 if (TargetProduct
!= -1 && TargetProductList
[0] != '\0') {
294 SHOW_PROGRESS("Warning: TargetProductList overrides TargetProduct!\n");
304 printf ("DefaultVendor= 0x%04x\n", DefaultVendor
);
306 printf ("DefaultVendor= not set\n");
307 if ( DefaultProduct
)
308 printf ("DefaultProduct= 0x%04x\n", DefaultProduct
);
310 printf ("DefaultProduct= not set\n");
312 printf ("TargetVendor= 0x%04x\n", TargetVendor
);
314 printf ("TargetVendor= not set\n");
315 if ( TargetProduct
> -1 )
316 printf ("TargetProduct= 0x%04x\n", TargetProduct
);
318 printf ("TargetProduct= not set\n");
320 printf ("TargetClass= 0x%02x\n", TargetClass
);
322 printf ("TargetClass= not set\n");
323 printf ("TargetProductList=\"%s\"\n", TargetProductList
);
324 printf ("\nDetachStorageOnly=%i\n", (int)DetachStorageOnly
);
325 printf ("HuaweiMode=%i\n", (int)HuaweiMode
);
326 printf ("SierraMode=%i\n", (int)SierraMode
);
327 printf ("SonyMode=%i\n", (int)SonyMode
);
328 printf ("GCTMode=%i\n", (int)GCTMode
);
329 printf ("KobilMode=%i\n", (int)KobilMode
);
330 if ( MessageEndpoint
)
331 printf ("MessageEndpoint=0x%02x\n", MessageEndpoint
);
333 printf ("MessageEndpoint= not set\n");
334 printf ("MessageContent=\"%s\"\n", MessageContent
);
335 if ( strlen(MessageContent2
) )
336 printf ("MessageContent2=\"%s\"\n", MessageContent2
);
337 if ( strlen(MessageContent3
) )
338 printf ("MessageContent3=\"%s\"\n", MessageContent3
);
339 printf ("NeedResponse=%i\n", (int)NeedResponse
);
340 if ( ResponseEndpoint
)
341 printf ("ResponseEndpoint=0x%02x\n", ResponseEndpoint
);
343 printf ("ResponseEndpoint= not set\n");
344 printf ("Interface=0x%02x\n", Interface
);
345 if ( Configuration
> 0 )
346 printf ("Configuration=0x%02x\n", Configuration
);
347 if ( AltSetting
> -1 )
348 printf ("AltSetting=0x%02x\n", AltSetting
);
350 printf ("\nInquireDevice enabled (default)\n");
352 printf ("\nInquireDevice disabled\n");
354 printf ("Success check enabled, max. wait time %d seconds\n", CheckSuccess
);
356 printf ("Success check disabled\n");
358 printf ("System integration mode enabled\n");
360 printf ("System integration mode disabled\n");
365 int readArguments(int argc
, char **argv
)
367 int c
, option_index
= 0, count
=0;
377 c
= getopt_long (argc
, argv
, "heWQDndHSOGTRIv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:",
378 long_options
, &option_index
);
380 /* Detect the end of the options. */
386 case 'R': ResetUSB
= 1; break;
387 case 'v': DefaultVendor
= strtol(optarg
, NULL
, 16); break;
388 case 'p': DefaultProduct
= strtol(optarg
, NULL
, 16); break;
389 case 'V': TargetVendor
= strtol(optarg
, NULL
, 16); break;
390 case 'P': TargetProduct
= strtol(optarg
, NULL
, 16); break;
391 case 'C': TargetClass
= strtol(optarg
, NULL
, 16); break;
392 case 'm': MessageEndpoint
= strtol(optarg
, NULL
, 16); break;
393 case 'M': strcpy(MessageContent
, optarg
); break;
394 case '2': strcpy(MessageContent2
, optarg
); break;
395 case '3': strcpy(MessageContent3
, optarg
); break;
396 case 'w': ReleaseDelay
= strtol(optarg
, NULL
, 10); count
--; break;
397 case 'n': NeedResponse
= 1; break;
398 case 'r': ResponseEndpoint
= strtol(optarg
, NULL
, 16); break;
399 case 'd': DetachStorageOnly
= 1; break;
400 case 'H': HuaweiMode
= 1; break;
401 case 'S': SierraMode
= 1; break;
402 case 'O': SonyMode
= 1; break;
403 case 'G': GCTMode
= 1; break;
404 case 'T': KobilMode
= 1; break;
405 case 'c': readConfigFile(optarg
); break;
406 case 'W': verbose
= 1; show_progress
= 1; count
--; break;
407 case 'Q': show_progress
= 0; verbose
= 0; count
--; break;
408 case 'D': sysmode
= 1; count
--; break;
409 case 's': CheckSuccess
= strtol(optarg
, NULL
, 10); count
--; break;
410 case 'I': InquireDevice
= 0; break;
412 case 'i': Interface
= strtol(optarg
, NULL
, 16); break;
413 case 'u': Configuration
= strtol(optarg
, NULL
, 16); break;
414 case 'a': AltSetting
= strtol(optarg
, NULL
, 16); break;
426 default: /* Unsupported - error message has already been printed */
437 int main(int argc
, char **argv
)
439 int numDefaults
=0, specialMode
=0, sonySuccess
=0;
440 int currentConfig
=0, defaultClass
=0, interfaceClass
=0;
442 /* Make sure we have empty strings even if not set by config */
443 TargetProductList
[0] = '\0';
444 MessageContent
[0] = '\0';
445 MessageContent2
[0] = '\0';
446 MessageContent3
[0] = '\0';
449 signal(SIGTERM
, release_usb_device
);
451 * Parameter parsing, USB preparation/diagnosis, plausibility checks
454 /* Check command arguments, use params instead of config file when given */
455 switch (readArguments(argc
, argv
)) {
456 case 0: /* no argument or -W, -q or -s */
458 default: /* one or more arguments except -W, -q or -s */
459 if (!config_read
) /* if arguments contain -c, the config file was already processed */
460 if (verbose
) printf("Taking all parameters from the command line\n\n");
469 /* libusb initialization */
478 /* Plausibility checks. The default IDs are mandatory */
479 if (!(DefaultVendor
&& DefaultProduct
)) {
480 SHOW_PROGRESS("No default vendor/product ID given. Aborting.\n\n");
483 if (strlen(MessageContent
)) {
484 if (strlen(MessageContent
) % 2 != 0) {
485 fprintf(stderr
, "Error: MessageContent hex string has uneven length. Aborting.\n\n");
488 if ( hexstr2bin(MessageContent
, ByteString
, strlen(MessageContent
)/2) == -1) {
489 fprintf(stderr
, "Error: MessageContent %s\n is not a hex string. Aborting.\n\n", MessageContent
);
496 if (CheckSuccess
&& !(TargetVendor
|| TargetProduct
> -1 || TargetProductList
[0] != '\0') && !TargetClass
)
497 printf("Note: target parameter missing; success check limited\n");
499 /* Count existing target devices, remember for success check */
500 if (TargetVendor
|| TargetClass
) {
501 SHOW_PROGRESS("Looking for target devices ...\n");
502 search_devices(&targetDeviceCount
, TargetVendor
, TargetProduct
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
503 if (targetDeviceCount
) {
504 SHOW_PROGRESS(" Found devices in target mode or class (%d)\n", targetDeviceCount
);
506 SHOW_PROGRESS(" No devices in target mode or class found\n");
509 /* Count default devices, get the last one found */
510 SHOW_PROGRESS("Looking for default devices ...\n");
511 dev
= search_devices(&numDefaults
, DefaultVendor
, DefaultProduct
, "\0", TargetClass
, Configuration
, SEARCH_DEFAULT
);
513 SHOW_PROGRESS(" Found devices in default mode, class or configuration (%d)\n", numDefaults
);
515 SHOW_PROGRESS(" No devices in default mode found. Nothing to do. Bye.\n\n");
519 devnum
= get_devnum(dev
);
520 busnum
= get_busnum(dev
);
521 SHOW_PROGRESS("Accessing device %03d on bus %03d ...\n", devnum
, busnum
);
522 devh
= usb_open(dev
);
524 SHOW_PROGRESS(" No default device found. Is it connected? Bye.\n\n");
528 /* Get current configuration of default device */
529 currentConfig
= get_current_configuration(devh
);
531 /* Get class of default device/interface */
533 defaultClass
= dev
->descriptor
.bDeviceClass
;
534 interfaceClass
= get_interface0_class(dev
, currentConfig
);
536 struct libusb_device_descriptor descriptor
;
537 libusb_get_device_descriptor(dev
, &descriptor
);
538 defaultClass
= descriptor
.bDeviceClass
;
539 struct libusb_config_descriptor
*config
;
540 libusb_get_config_descriptor(dev
, 0, &config
);
541 interfaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
542 libusb_free_config_descriptor(config
);
544 if (interfaceClass
== -1) {
545 fprintf(stderr
, "Error: getting the interface class failed. Aborting.\n\n");
549 if (defaultClass
== 0)
550 defaultClass
= interfaceClass
;
552 if (interfaceClass
== 8 && defaultClass
!= 8) {
553 /* Weird device with default class other than 0 and differing interface class */
554 SHOW_PROGRESS("Ambiguous Class/InterfaceClass: 0x%02x/0x08\n", defaultClass
);
558 /* Check or get endpoints */
559 if (strlen(MessageContent
) || InquireDevice
) {
560 if (!MessageEndpoint
)
561 MessageEndpoint
= find_first_bulk_output_endpoint(dev
);
562 if (!MessageEndpoint
) {
563 fprintf(stderr
,"Error: message endpoint not given or found. Aborting.\n\n");
566 if (!ResponseEndpoint
)
567 ResponseEndpoint
= find_first_bulk_input_endpoint(dev
);
568 if (!ResponseEndpoint
) {
569 fprintf(stderr
,"Error: response endpoint not given or found. Aborting.\n\n");
572 SHOW_PROGRESS("Using endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
, ResponseEndpoint
);
575 if (MessageEndpoint
&& ResponseEndpoint
) {
576 SHOW_PROGRESS("Using endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint
, ResponseEndpoint
);
578 if (InquireDevice
&& defaultClass
== 0x08) {
579 SHOW_PROGRESS("Endpoints not found, skipping SCSI inquiry\n");
583 if (InquireDevice
&& show_progress
) {
584 if (defaultClass
== 0x08) {
585 SHOW_PROGRESS("Inquiring device details; driver will be detached ...\n");
587 if (deviceInquire() >= 0)
590 SHOW_PROGRESS("Not a storage device, skipping SCSI inquiry\n");
595 printf("\nUSB description data (for identification)\n");
596 printf("-------------------------\n");
597 printf("Manufacturer: %s\n", imanufact
);
598 printf(" Product: %s\n", iproduct
);
599 printf(" Serial No.: %s\n", iserial
);
600 printf("-------------------------\n");
603 /* Some scenarios are exclusive, so check for unwanted combinations */
604 specialMode
= DetachStorageOnly
+ HuaweiMode
+ SierraMode
+ SonyMode
+ KobilMode
;
605 if ( specialMode
> 1 ) {
606 SHOW_PROGRESS("Invalid mode combination. Check your configuration. Aborting.\n\n");
610 if ( !specialMode
&& !strlen(MessageContent
) && AltSetting
== -1 && Configuration
== 0 )
611 SHOW_PROGRESS("Warning: no switching method given.\n");
614 * The switching actions
618 openlog("usb_modeswitch", 0, LOG_SYSLOG
);
619 syslog(LOG_NOTICE
, "switching %04x:%04x (%s: %s)", DefaultVendor
, DefaultProduct
, imanufact
, iproduct
);
622 if (DetachStorageOnly
) {
623 SHOW_PROGRESS("Only detaching storage driver for switching ...\n");
624 if (InquireDevice
== 2) {
625 SHOW_PROGRESS(" Any driver was already detached for inquiry\n");
627 ret
= detachDriver();
629 SHOW_PROGRESS(" You may want to remove the storage driver manually\n");
649 SHOW_PROGRESS("Note: ignoring CheckSuccess. Separate checks for Sony mode\n");
650 CheckSuccess
= 0; /* separate and implied success control */
651 sonySuccess
= switchSonyMode();
654 if (strlen(MessageContent
) && MessageEndpoint
) {
655 if (specialMode
== 0) {
656 if (InquireDevice
!= 2)
660 SHOW_PROGRESS("Warning: ignoring MessageContent. Can't combine with special mode\n");
663 if (Configuration
!= 0) {
664 if (currentConfig
!= Configuration
) {
665 if (switchConfiguration()) {
666 currentConfig
= get_current_configuration(devh
);
667 if (currentConfig
== Configuration
) {
668 SHOW_PROGRESS("The configuration was set successfully\n");
670 SHOW_PROGRESS("Setting the configuration failed\n");
674 SHOW_PROGRESS("Target configuration %d already active. Doing nothing\n", currentConfig
);
678 if (AltSetting
!= -1) {
682 /* No "removal" check if these are set */
683 if ((Configuration
!= 0 || AltSetting
!= -1) && !ResetUSB
) {
695 if (checkSuccess()) {
700 if (TargetProduct
< 1)
701 printf("ok:no_data\n");
703 printf("ok:%04x:%04x\n", TargetVendor
, TargetProduct
);
712 syslog(LOG_NOTICE
, "switched S.E. MD400 to modem mode");
713 printf("ok:\n"); /* ACM device, no driver action */
715 SHOW_PROGRESS("-> device should be stable now. Bye.\n\n");
719 SHOW_PROGRESS("-> switching was probably not completed. Bye.\n\n");
722 SHOW_PROGRESS("-> Run lsusb to note any changes. Bye.\n\n");
733 /* Get descriptor strings if available (identification details) */
734 void deviceDescription ()
738 memset (imanufact
, ' ', DESCR_MAX
);
739 memset (iproduct
, ' ', DESCR_MAX
);
740 memset (iserial
, ' ', DESCR_MAX
);
743 int iManufacturer
= dev
->descriptor
.iManufacturer
;
744 int iProduct
= dev
->descriptor
.iProduct
;
745 int iSerialNumber
= dev
->descriptor
.iSerialNumber
;
747 struct libusb_device_descriptor descriptor
;
748 libusb_get_device_descriptor(dev
, &descriptor
);
750 int iManufacturer
= descriptor
.iManufacturer
;
751 int iProduct
= descriptor
.iProduct
;
752 int iSerialNumber
= descriptor
.iSerialNumber
;
756 ret
= usb_get_string_simple(devh
, iManufacturer
, imanufact
, DESCR_MAX
);
758 fprintf(stderr
, "Error: could not get description string \"manufacturer\"\n");
760 strcpy(imanufact
, "not provided");
761 c
= strstr(imanufact
, " ");
763 memset((void*)c
, '\0', 1);
766 ret
= usb_get_string_simple(devh
, iProduct
, iproduct
, DESCR_MAX
);
768 fprintf(stderr
, "Error: could not get description string \"product\"\n");
770 strcpy(iproduct
, "not provided");
771 c
= strstr(iproduct
, " ");
773 memset((void*)c
, '\0', 1);
776 ret
= usb_get_string_simple(devh
, iSerialNumber
, iserial
, DESCR_MAX
);
778 fprintf(stderr
, "Error: could not get description string \"serial number\"\n");
780 strcpy(iserial
, "not provided");
781 c
= strstr(iserial
, " ");
783 memset((void*)c
, '\0', 1);
787 /* Print result of SCSI command INQUIRY (identification details) */
790 const unsigned char inquire_msg
[] = {
791 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
792 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
793 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
800 command
= malloc(31);
801 if (command
== NULL
) {
806 memcpy(command
, inquire_msg
, sizeof (inquire_msg
));
808 ret
= usb_claim_interface(devh
, Interface
);
810 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping device inquiry\n", ret
);
813 usb_clear_halt(devh
, MessageEndpoint
);
815 ret
= usb_bulk_write(devh
, MessageEndpoint
, (char *)command
, 31, 0);
817 SHOW_PROGRESS(" Could not send INQUIRY message (error %d)\n", ret
);
821 ret
= usb_bulk_read(devh
, ResponseEndpoint
, data
, 36, 0);
823 SHOW_PROGRESS(" Could not get INQUIRY response (error %d)\n", ret
);
827 i
= usb_bulk_read(devh
, ResponseEndpoint
, command
, 13, 0);
829 printf("\nSCSI inquiry data (for identification)\n");
830 printf("-------------------------\n");
832 printf(" Vendor String: ");
833 for (i
= 8; i
< 16; i
++) printf("%c",data
[i
]);
836 printf(" Model String: ");
837 for (i
= 16; i
< 32; i
++) printf("%c",data
[i
]);
840 printf("Revision String: ");
841 for (i
= 32; i
< 36; i
++) printf("%c",data
[i
]);
843 printf("\n-------------------------\n");
846 if (strlen(MessageContent
) == 0)
847 usb_clear_halt(devh
, MessageEndpoint
);
848 usb_release_interface(devh
, Interface
);
860 printf("Resetting usb device ");
866 success
= usb_reset(devh
);
867 if ( ((bpoint
% 10) == 0) && show_progress
) {
874 } while (success
< 0);
877 SHOW_PROGRESS("\n Reset failed. Can be ignored if device switched OK.\n");
879 SHOW_PROGRESS("\n OK, device was reset\n");
883 int switchSendMessage ()
887 /* May be activated in future versions */
888 // if (MessageContent2[0] != '\0' || MessageContent3[0] != '\0')
891 SHOW_PROGRESS("Setting up communication with interface %d ...\n", Interface
);
892 if (InquireDevice
!= 2) {
893 ret
= usb_claim_interface(devh
, Interface
);
895 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping message sending\n", ret
);
899 usb_clear_halt(devh
, MessageEndpoint
);
900 SHOW_PROGRESS("Using endpoint 0x%02x for message sending ...\n", MessageEndpoint
);
904 if ( sendMessage(MessageContent
, 1) )
908 SHOW_PROGRESS("Reading the response to the message (CSW) ...\n");
909 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
914 if (strlen(MessageContent2
)) {
915 if ( sendMessage(MessageContent2
, 2) )
919 SHOW_PROGRESS("Reading the response to message 2 ...\n");
920 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
926 if (strlen(MessageContent3
)) {
927 if ( sendMessage(MessageContent3
, 3) )
930 SHOW_PROGRESS("Reading the response to message 3 ...\n");
931 ret
= read_bulk(ResponseEndpoint
, ByteString
, 13);
937 SHOW_PROGRESS("Resetting response endpoint 0x%02x\n", ResponseEndpoint
);
938 ret
= usb_clear_halt(devh
, ResponseEndpoint
);
940 SHOW_PROGRESS(" Error resetting endpoint: %d\n", ret
);
941 SHOW_PROGRESS("Resetting message endpoint 0x%02x\n", MessageEndpoint
);
942 ret
= usb_clear_halt(devh
, MessageEndpoint
);
944 SHOW_PROGRESS(" Error resetting endpoint: %d\n", ret
);
947 SHOW_PROGRESS("Blocking the interface for %d ms before releasing ...\n", ReleaseDelay
);
948 usleep(ReleaseDelay
*1000);
950 ret
= usb_release_interface(devh
, Interface
);
956 SHOW_PROGRESS(" Device is gone, skipping any further commands\n");
962 #define SWITCH_CONFIG_MAXTRIES 5
964 int switchConfiguration ()
966 int count
= SWITCH_CONFIG_MAXTRIES
;
969 SHOW_PROGRESS("Changing configuration to %i ...\n", Configuration
);
970 while (((ret
= usb_set_configuration(devh
, Configuration
)) < 0) && --count
) {
971 SHOW_PROGRESS(" Device is busy, trying to detach kernel driver\n");
975 SHOW_PROGRESS(" OK, configuration set\n");
978 SHOW_PROGRESS(" Setting the configuration returned error %d. Trying to continue\n", ret
);
983 int switchAltSetting ()
987 SHOW_PROGRESS("Changing to alt setting %i ...\n", AltSetting
);
988 ret
= usb_claim_interface(devh
, Interface
);
990 ret
= usb_set_altinterface(devh
, AltSetting
);
992 ret
= libusb_set_interface_alt_setting(devh
, Interface
, AltSetting
);
994 usb_release_interface(devh
, Interface
);
996 SHOW_PROGRESS(" Changing to alt setting returned error %d. Trying to continue\n", ret
);
999 SHOW_PROGRESS(" OK, changed to alt setting\n");
1005 void switchHuaweiMode ()
1009 SHOW_PROGRESS("Sending Huawei control message ...\n");
1010 ret
= usb_control_msg(devh
, USB_TYPE_STANDARD
| USB_RECIP_DEVICE
, USB_REQ_SET_FEATURE
, 00000001, 0, buffer
, 0, 1000);
1012 fprintf(stderr
, "Error: sending Huawei control message failed (error %d). Aborting.\n\n", ret
);
1015 SHOW_PROGRESS(" OK, Huawei control message sent\n");
1019 void switchSierraMode ()
1023 SHOW_PROGRESS("Trying to send Sierra control message\n");
1024 ret
= usb_control_msg(devh
, 0x40, 0x0b, 00000001, 0, buffer
, 0, 1000);
1026 fprintf(stderr
, "Error: sending Sierra control message failed (error %d). Aborting.\n\n", ret
);
1029 SHOW_PROGRESS(" OK, Sierra control message sent\n");
1033 void switchGCTMode ()
1037 ret
= usb_claim_interface(devh
, Interface
);
1039 SHOW_PROGRESS(" Could not claim interface (error %d). Skipping GCT sequence \n", ret
);
1043 SHOW_PROGRESS("Sending GCT control message 1 ...\n");
1044 ret
= usb_control_msg(devh
, 0xa1, 0xa0, 0, Interface
, buffer
, 1, 1000);
1045 SHOW_PROGRESS("Sending GCT control message 2 ...\n");
1046 ret
= usb_control_msg(devh
, 0xa1, 0xfe, 0, Interface
, buffer
, 1, 1000);
1047 SHOW_PROGRESS(" OK, GCT control messages sent\n");
1048 usb_release_interface(devh
, Interface
);
1052 int switchKobilMode() {
1055 SHOW_PROGRESS("Sending Kobil control message ...\n");
1056 ret
= usb_control_msg(devh
, USB_TYPE_VENDOR
| USB_RECIP_DEVICE
| USB_ENDPOINT_IN
, 0x88, 0, 0, buffer
, 8, 1000);
1058 fprintf(stderr
, "Error: sending Kobil control message failed (error %d). Aborting.\n\n", ret
);
1061 SHOW_PROGRESS(" OK, Kobil control message sent\n");
1066 int switchSonyMode ()
1072 printf("Note: CheckSuccess pointless with Sony mode, disabling\n");
1076 SHOW_PROGRESS("Trying to send Sony control message\n");
1077 ret
= usb_control_msg(devh
, 0xc0, 0x11, 2, 0, buffer
, 3, 100);
1079 fprintf(stderr
, "Error: sending Sony control message failed (error %d). Aborting.\n\n", ret
);
1082 SHOW_PROGRESS(" OK, control message sent, waiting for device to return ...\n");
1087 /* Now waiting for the device to reappear */
1092 while ( dev
== 0 && i
< 30 ) {
1096 dev
= search_devices(&found
, DefaultVendor
, DefaultProduct
, "\0", TargetClass
, 0, SEARCH_TARGET
);
1101 if (show_progress
) {
1107 SHOW_PROGRESS("\n After %d seconds:",i
);
1109 SHOW_PROGRESS(" device came back, proceeding\n");
1110 devh
= usb_open( dev
);
1112 fprintf(stderr
, "Error: could not get handle on device\n");
1116 SHOW_PROGRESS(" device still gone, cancelling\n");
1121 SHOW_PROGRESS("Sending Sony control message again ...\n");
1122 ret
= usb_control_msg(devh
, 0xc0, 0x11, 2, 0, buffer
, 3, 100);
1124 fprintf(stderr
, "Error: sending Sony control message (2) failed (error %d)\n", ret
);
1127 SHOW_PROGRESS(" OK, control message sent\n");
1131 /* Detach driver either as the main action or as preparation for other
1138 #ifndef LIBUSB_HAS_GET_DRIVER_NP
1139 printf(" Cant't do driver detection and detaching on this platform.\n");
1143 SHOW_PROGRESS("Looking for active driver ...\n");
1144 ret
= usb_get_driver_np(devh
, Interface
, buffer
, BUF_SIZE
);
1146 SHOW_PROGRESS(" No driver found. Either detached before or never attached\n");
1149 SHOW_PROGRESS(" OK, driver found (\"%s\")\n", buffer
);
1150 if (DetachStorageOnly
&& strcmp(buffer
,"usb-storage")) {
1151 SHOW_PROGRESS(" Warning: driver is not usb-storage\n");
1154 #ifndef LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
1155 SHOW_PROGRESS(" Can't do driver detaching on this platform\n");
1160 ret
= usb_detach_kernel_driver_np(devh
, Interface
);
1162 SHOW_PROGRESS(" OK, driver \"%s\" detached\n", buffer
);
1164 SHOW_PROGRESS(" Driver \"%s\" detach failed with error %d. Trying to continue\n", buffer
, ret
);
1169 int sendMessage(char* message
, int count
)
1171 int message_length
, ret
;
1173 if (strlen(message
) % 2 != 0) {
1174 fprintf(stderr
, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count
);
1177 message_length
= strlen(message
) / 2;
1178 if ( hexstr2bin(message
, ByteString
, message_length
) == -1) {
1179 fprintf(stderr
, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", count
, MessageContent
);
1182 SHOW_PROGRESS("Trying to send message %d to endpoint 0x%02x ...\n", count
, MessageEndpoint
);
1184 ret
= write_bulk(MessageEndpoint
, ByteString
, message_length
);
1195 int newTargetCount
, success
=0;
1197 SHOW_PROGRESS("\nChecking for mode switch (max. %d times, once per second) ...\n", CheckSuccess
);
1200 /* if target ID is not given but target class is, assign default as target;
1201 * it will be needed for sysmode output
1203 if (!TargetVendor
&& TargetClass
) {
1204 TargetVendor
= DefaultVendor
;
1205 TargetProduct
= DefaultProduct
;
1208 if (devh
) // devh is 0 if device vanished during command transmission
1209 for (i
=0; i
< CheckSuccess
; i
++) {
1211 /* Test if default device still can be accessed; positive result does
1212 * not necessarily mean failure
1214 SHOW_PROGRESS(" Waiting for original device to vanish ...\n");
1216 ret
= usb_claim_interface(devh
, Interface
);
1217 usb_release_interface(devh
, Interface
);
1219 SHOW_PROGRESS(" Original device can't be accessed anymore. Good.\n");
1220 if (i
== CheckSuccess
-1)
1221 SHOW_PROGRESS(" If you want target checking, increase 'CheckSuccess' value.\n");
1226 if (i
== CheckSuccess
-1) {
1227 SHOW_PROGRESS(" Original device still present after the timeout\n\nMode switch most likely failed. Bye.\n\n");
1233 if ( TargetVendor
&& (TargetProduct
> -1 || TargetProductList
[0] != '\0') ) {
1235 /* Recount target devices (compare with previous count) if target data is given.
1236 * Target device on the same bus with higher device number is returned,
1237 * description is read for syslog message
1239 for (i
=i
; i
< CheckSuccess
; i
++) {
1240 SHOW_PROGRESS(" Searching for target devices ...\n");
1241 ret
= usb_find_busses();
1243 ret
= usb_find_devices();
1245 SHOW_PROGRESS("Error: libusb1 bug, no more searching, try to work around\n");
1249 dev
= search_devices(&newTargetCount
, TargetVendor
, TargetProduct
, TargetProductList
, TargetClass
, 0, SEARCH_TARGET
);
1250 if (dev
&& (newTargetCount
> targetDeviceCount
)) {
1251 printf("\nFound target device, now opening\n");
1252 devh
= usb_open(dev
);
1253 deviceDescription();
1257 printf("\nFound target device %03d on bus %03d\n", \
1258 get_devnum(dev
), get_busnum(dev
));
1259 printf("\nTarget device description data\n");
1260 printf("-------------------------\n");
1261 printf("Manufacturer: %s\n", imanufact
);
1262 printf(" Product: %s\n", iproduct
);
1263 printf(" Serial No.: %s\n", iserial
);
1264 printf("-------------------------\n");
1266 SHOW_PROGRESS(" Found correct target device\n\nMode switch succeeded. Bye.\n\n");
1270 if (i
== CheckSuccess
-1) {
1271 SHOW_PROGRESS(" No new devices in target mode or class found\n\nMode switch has failed. Bye.\n\n");
1276 /* No target data given, rely on the vanished device */
1278 SHOW_PROGRESS(" (For a better success check provide target IDs or class)\n");
1279 SHOW_PROGRESS(" Original device vanished after switching\n\nMode switch most likely succeeded. Bye.\n\n");
1286 syslog(LOG_NOTICE
, "switched to new device, but hit libusb1 bug");
1292 syslog(LOG_NOTICE
, "switched to %04x:%04x (%s: %s)", TargetVendor
, TargetProduct
, imanufact
, iproduct
);
1297 syslog(LOG_NOTICE
, "device seems to have switched");
1309 int write_bulk(int endpoint
, char *message
, int length
)
1312 ret
= usb_bulk_write(devh
, endpoint
, message
, length
, 3000);
1314 SHOW_PROGRESS(" OK, message successfully sent\n");
1317 SHOW_PROGRESS(" Device seems to have vanished right after sending. Good.\n");
1319 SHOW_PROGRESS(" Sending the message returned error %d. Trying to continue\n", ret
);
1324 int read_bulk(int endpoint
, char *buffer
, int length
)
1327 ret
= usb_bulk_read(devh
, endpoint
, buffer
, length
, 3000);
1328 usb_bulk_read(devh
, endpoint
, buffer
, 13, 100);
1330 SHOW_PROGRESS(" OK, response successfully read (%d bytes).\n", ret
);
1333 SHOW_PROGRESS(" Device seems to have vanished after reading. Good.\n");
1335 SHOW_PROGRESS(" Response reading got error %d, can probably be ignored\n", ret
);
1340 void release_usb_device(int dummy
) {
1341 SHOW_PROGRESS("Program cancelled by system. Bye.\n\n");
1343 usb_release_interface(devh
, Interface
);
1353 /* Iterates over busses and devices, counts the ones with the given
1354 * ID/class and returns the last one of them
1356 struct usb_device
* search_devices( int *numFound
, int vendor
, int product
, char* productList
, int targetClass
, int configuration
, int mode
)
1359 struct usb_bus
*bus
;
1361 char *listcopy
=NULL
, *token
, buffer
[2];
1363 struct usb_device
* right_dev
= NULL
;
1364 struct usb_dev_handle
*testdevh
;
1366 /* only target class given, target vendor and product assumed unchanged */
1367 if ( targetClass
&& !(vendor
|| product
) ) {
1368 vendor
= DefaultVendor
;
1369 product
= DefaultProduct
;
1374 if (!vendor
|| (!product
&& productList
== '\0') )
1377 if (productList
!= '\0')
1378 listcopy
= malloc(strlen(productList
)+1);
1381 for (bus
= usb_get_busses(); bus
; bus
= bus
->next
) {
1382 struct usb_device
*dev
;
1383 for (dev
= bus
->devices
; dev
; dev
= dev
->next
) {
1385 struct libusb_device
**devs
;
1388 if (libusb_get_device_list( ctx
, &devs
) < 0){
1389 perror ("failed to access USB");
1393 while ( (dev
= devs
[i
++]) != NULL
) {
1396 int idVendor
= dev
->descriptor
.idVendor
;
1397 int idProduct
= dev
->descriptor
.idProduct
;
1399 struct libusb_device_descriptor descriptor
;
1400 libusb_get_device_descriptor(dev
, &descriptor
);
1401 int idVendor
= descriptor
.idVendor
;
1402 int idProduct
= descriptor
.idProduct
;
1405 printf (" searching devices, found USB ID %04x:%04x\n", idVendor
, idProduct
);
1406 if (idVendor
!= vendor
)
1409 printf (" found matching vendor ID\n");
1410 // product list given
1411 if ( strlen(productList
) ) {
1412 strcpy(listcopy
, productList
);
1413 token
= strtok(listcopy
, ",");
1414 while (token
!= NULL
) {
1415 if (strlen(token
) != 4) {
1416 SHOW_PROGRESS("Error: entry in product ID list has wrong length: %s. Ignoring\n", token
);
1419 if ( hexstr2bin(token
, buffer
, strlen(token
)/2) == -1) {
1420 SHOW_PROGRESS("Error: entry in product ID list is not a hex string: %s. Ignoring\n", token
);
1424 product
+= (unsigned char)buffer
[0];
1426 product
+= (unsigned char)buffer
[1];
1427 if (product
== idProduct
) {
1429 printf (" found matching product ID from list\n");
1434 if (get_devnum(dev
) >= devnum
&& get_busnum(dev
) == busnum
) {
1436 TargetProduct
= idProduct
;
1442 token
= strtok(NULL
, ",");
1444 /* Product ID is given */
1446 if (product
== idProduct
) {
1448 printf (" found matching product ID\n");
1449 if (targetClass
== 0 && configuration
== 0) {
1453 printf (" adding device\n");
1455 if (targetClass
!= 0) {
1457 devClass
= dev
->descriptor
.bDeviceClass
;
1458 int ifaceClass
= dev
->config
[0].interface
[0].altsetting
[0].bInterfaceClass
;
1460 struct libusb_device_descriptor descriptor
;
1461 libusb_get_device_descriptor(dev
, &descriptor
);
1462 devClass
= descriptor
.bDeviceClass
;
1463 struct libusb_config_descriptor
*config
;
1464 libusb_get_config_descriptor(dev
, 0, &config
);
1465 int ifaceClass
= config
->interface
[0].altsetting
[0].bInterfaceClass
;
1466 libusb_free_config_descriptor(config
);
1469 devClass
= ifaceClass
;
1471 /* Check for some quirky devices */
1472 if (devClass
!= ifaceClass
)
1473 devClass
= ifaceClass
;
1474 if (devClass
== targetClass
) {
1476 printf (" target class %02x matching\n", targetClass
);
1477 if (mode
== SEARCH_TARGET
) {
1481 printf (" adding device\n");
1484 printf (" not adding device\n");
1487 printf (" target class %02x not matching\n", targetClass
);
1488 if (mode
== SEARCH_DEFAULT
) {
1492 printf (" adding device\n");
1496 // check configuration (only if no target class given)
1497 testdevh
= usb_open(dev
);
1498 int testconfig
= get_current_configuration(testdevh
);
1499 if (testconfig
!= configuration
) {
1501 printf (" device configuration %d not matching parameter\n", testconfig
);
1505 printf (" adding device\n");
1508 printf (" not adding device, target configuration already set\n");
1511 /* hack: if busnum has other than init value, we are called from
1512 * successCheck() and do probe for plausible new devnum/busnum
1515 if (get_devnum(dev
) < devnum
|| get_busnum(dev
) != busnum
) {
1517 printf (" busnum/devnum indicates an unrelated device\n");
1525 if (productList
!= NULL
)
1531 #define USB_DIR_OUT 0x00
1532 #define USB_DIR_IN 0x80
1534 /* Autodetect bulk endpoints (ab) */
1536 int find_first_bulk_output_endpoint(struct usb_device
*dev
)
1540 struct usb_interface_descriptor
*alt
= &(dev
->config
[0].interface
[0].altsetting
[0]);
1541 struct usb_endpoint_descriptor
*ep
;
1543 struct libusb_config_descriptor
*config
;
1544 libusb_get_config_descriptor(dev
, 0, &config
);
1545 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1546 const struct usb_endpoint_descriptor
*ep
;
1549 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1550 ep
=&(alt
->endpoint
[i
]);
1551 if( ( (ep
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
) &&
1552 ( (ep
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_OUT
) ) {
1553 return ep
->bEndpointAddress
;
1557 libusb_free_config_descriptor(config
);
1564 int find_first_bulk_input_endpoint(struct usb_device
*dev
)
1568 struct usb_interface_descriptor
*alt
= &(dev
->config
[0].interface
[0].altsetting
[0]);
1569 struct usb_endpoint_descriptor
*ep
;
1571 struct libusb_config_descriptor
*config
;
1572 libusb_get_config_descriptor(dev
, 0, &config
);
1573 const struct libusb_interface_descriptor
*alt
= &(config
[0].interface
[0].altsetting
[0]);
1574 const struct usb_endpoint_descriptor
*ep
;
1576 for(i
=0;i
< alt
->bNumEndpoints
;i
++) {
1577 ep
=&(alt
->endpoint
[i
]);
1578 if( ( (ep
->bmAttributes
& USB_ENDPOINT_TYPE_MASK
) == USB_ENDPOINT_TYPE_BULK
) &&
1579 ( (ep
->bEndpointAddress
& USB_ENDPOINT_DIR_MASK
) == USB_DIR_IN
) ) {
1580 return ep
->bEndpointAddress
;
1584 libusb_free_config_descriptor(config
);
1590 int get_current_configuration(struct usb_dev_handle
* devh
)
1594 SHOW_PROGRESS("Getting the current device configuration ...\n");
1595 ret
= usb_control_msg(devh
, USB_DIR_IN
+ USB_TYPE_STANDARD
+ USB_RECIP_DEVICE
, USB_REQ_GET_CONFIGURATION
, 0, 0, buffer
, 1, 1000);
1597 fprintf(stderr
, "Error: getting the current configuration failed (error %d). Aborting.\n\n", ret
);
1600 SHOW_PROGRESS(" OK, got current device configuration (%d)\n", buffer
[0]);
1607 int get_interface0_class(struct usb_device
*dev
, int devconfig
)
1610 for (i
=0; i
<dev
->descriptor
.bNumConfigurations
; i
++)
1611 if (dev
->config
[i
].bConfigurationValue
== devconfig
)
1612 return dev
->config
[i
].interface
[0].altsetting
[0].bInterfaceClass
;
1618 /* Parameter parsing */
1620 char* ReadParseParam(const char* FileName
, char *VariableName
)
1622 static char Str
[LINE_DIM
];
1623 char *VarName
, *Comment
=NULL
, *Equal
=NULL
;
1624 char *FirstQuote
, *LastQuote
, *P1
, *P2
;
1625 int Line
=0, Len
=0, Pos
=0;
1626 FILE *file
=fopen(FileName
, "r");
1629 fprintf(stderr
, "Error: Could not find file %s\n\n", FileName
);
1633 while (fgets(Str
, LINE_DIM
-1, file
) != NULL
) {
1636 if (Len
==0) goto Next
;
1637 if (Str
[Len
-1]=='\n' or Str
[Len
-1]=='\r') Str
[--Len
]='\0';
1638 Equal
= strchr (Str
, '='); // search for equal sign
1639 Pos
= strcspn (Str
, ";#!"); // search for comment
1640 Comment
= (Pos
==Len
) ? NULL
: Str
+Pos
;
1641 if (Equal
==NULL
or ( Comment
!=NULL
and Comment
<=Equal
)) goto Next
; // Only comment
1643 if (Comment
!=NULL
) *Comment
='\0';
1646 FirstQuote
=strchr (Equal
, '"'); // search for double quote char
1647 LastQuote
=strrchr (Equal
, '"');
1648 if (FirstQuote
!=NULL
) {
1649 if (LastQuote
==NULL
) {
1650 fprintf(stderr
, "Error reading parameter file %s line %d - Missing end quote.\n", FileName
, Line
);
1653 *FirstQuote
=*LastQuote
='\0';
1657 // removes leading/trailing spaces
1658 Pos
=strspn (Str
, " \t");
1659 if (Pos
==strlen(Str
)) {
1660 fprintf(stderr
, "Error reading parameter file %s line %d - Missing variable name.\n", FileName
, Line
);
1661 goto Next
; // No function name
1663 while ((P1
=strrchr(Str
, ' '))!=NULL
or (P2
=strrchr(Str
, '\t'))!=NULL
)
1664 if (P1
!=NULL
) *P1
='\0';
1665 else if (P2
!=NULL
) *P2
='\0';
1668 Pos
=strspn (Equal
, " \t");
1669 if (Pos
==strlen(Equal
)) {
1670 fprintf(stderr
, "Error reading parameter file %s line %d - Missing value.\n", FileName
, Line
);
1671 goto Next
; // No function name
1675 if (strcmp(VarName
, VariableName
)==0) { // Found it
1689 if (c
>= '0' && c
<= '9')
1691 if (c
>= 'a' && c
<= 'f')
1692 return c
- 'a' + 10;
1693 if (c
>= 'A' && c
<= 'F')
1694 return c
- 'A' + 10;
1699 int hex2byte(const char *hex
)
1702 a
= hex2num(*hex
++);
1705 b
= hex2num(*hex
++);
1708 return (a
<< 4) | b
;
1711 int hexstr2bin(const char *hex
, char *buffer
, int len
)
1715 const char *ipos
= hex
;
1716 char *opos
= buffer
;
1718 for (i
= 0; i
< len
; i
++) {
1730 char* version
= VERSION
;
1731 printf("\n * usb_modeswitch: handle USB devices with multiple modes\n");
1732 printf(" * Version %s (C) Josua Dietze 2010\n", version
);
1734 printf(" * Based on libusb0 (0.1.12 and above)\n\n");
1736 printf(" * Based on libusb10 (1.0.1 and above)\n\n");
1738 printf(" ! PLEASE REPORT NEW CONFIGURATIONS !\n\n");
1743 printf ("Usage: usb_modeswitch [-hvpVPmMrdHn] [-c filename]\n\n");
1744 printf (" -h, --help this help\n");
1745 printf (" -e, --version print version information and exit\n");
1746 printf (" -v, --default-vendor NUM vendor ID of original mode (mandatory)\n");
1747 printf (" -p, --default-product NUM product ID of original mode (mandatory)\n");
1748 printf (" -V, --target-vendor NUM target mode vendor ID (optional)\n");
1749 printf (" -P, --target-product NUM target mode product ID (optional)\n");
1750 printf (" -C, --target-class NUM target mode device class (optional)\n");
1751 printf (" -m, --message-endpoint NUM direct the message transfer there (optional)\n");
1752 printf (" -M, --message-content <msg> message to send (hex number as string)\n");
1753 printf (" -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n");
1754 printf (" -n, --need-response read response to the message transfer (CSW)\n");
1755 printf (" -r, --response-endpoint NUM read response from there (optional)\n");
1756 printf (" -d, --detach-only detach the active driver, no further action\n");
1757 printf (" -H, --huawei-mode apply a special procedure\n");
1758 printf (" -S, --sierra-mode apply a special procedure\n");
1759 printf (" -O, --sony-mode apply a special procedure\n");
1760 printf (" -G, --gct-mode apply a special procedure\n");
1761 printf (" -T, --kobil-mode apply a special procedure\n");
1762 printf (" -R, --reset-usb reset the device after all other actions\n");
1763 printf (" -Q, --quiet don't show progress or error messages\n");
1764 printf (" -W, --verbose print all settings and debug output\n");
1765 printf (" -D, --sysmode specific result and syslog message\n");
1766 printf (" -s, --success NUM check switching result after NUM secs\n");
1767 printf (" -I, --no-inquire do not get SCSI attributes (default on)\n\n");
1768 printf (" -c, --config-file <filename> load configuration from file\n\n");
1769 printf (" -i, --interface NUM select initial USB interface (default 0)\n");
1770 printf (" -u, --configuration NUM select USB configuration\n");
1771 printf (" -a, --altsetting NUM select alternative USB interface setting\n\n");