Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / usbmodeswitch / usb_modeswitch.c
blob30b96aee47c7a7a2f205910b5a080df6e5358205
1 /*
2 Mode switching tool for controlling flip flop (multiple device) USB gear
3 Version 2.0.1, 2013/09/03
5 Copyright (C) 2007 - 2013 Josua Dietze (mail to "usb_admin" at the domain
6 of the home page; or write a personal message through the forum to "Josh".
7 NO SUPPORT VIA E-MAIL - please use the forum for that)
9 Major contributions:
11 Command line parsing, decent usage/config output/handling, bugfixes and advanced
12 options added by:
13 Joakim Wennergren
15 TargetClass parameter implementation to support new Option devices/firmware:
16 Paul Hardwick (http://www.pharscape.org)
18 Created with initial help from:
19 "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl)
21 Config file parsing stuff borrowed from:
22 Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
24 Hexstr2bin function borrowed from:
25 Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
27 Other contributions: see README
29 Device information contributors are named in the "device_reference.txt" file. See
30 homepage.
32 This program is free software; you can redistribute it and/or modify
33 it under the terms of the GNU General Public License as published by
34 the Free Software Foundation; either version 2 of the License, or
35 (at your option) any later version.
37 This program is distributed in the hope that it will be useful,
38 but WITHOUT ANY WARRANTY; without even the implied warranty of
39 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
40 GNU General Public License for more details:
42 http://www.gnu.org/licenses/gpl.txt
46 /* Recommended tab size: 4 */
48 #define VERSION "2.0.1"
50 #include <stdio.h>
51 #include <stdlib.h>
52 #include <string.h>
53 #include <signal.h>
54 #include <ctype.h>
55 #include <getopt.h>
56 #include <syslog.h>
57 #include <unistd.h>
59 #include "usb_modeswitch.h"
62 /* libusb 1.0 wrappers */
64 int usb_bulk_io(struct libusb_device_handle *handle, int ep, char *bytes,
65 int size, int timeout)
67 int actual_length;
68 int r;
69 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
70 r = libusb_bulk_transfer(handle, ep & 0xff, (unsigned char *)bytes, size,
71 &actual_length, timeout);
73 /* if we timed out but did transfer some data, report as successful short
74 * read. FIXME: is this how libusb-0.1 works? */
75 if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0))
76 return actual_length;
78 return r;
81 static int usb_interrupt_io(libusb_device_handle *handle, int ep, char *bytes,
82 int size, int timeout)
84 int actual_length;
85 int r;
86 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
87 r = libusb_interrupt_transfer(handle, ep & 0xff, (unsigned char *)bytes, size,
88 &actual_length, timeout);
90 /* if we timed out but did transfer some data, report as successful short
91 * read. FIXME: is this how libusb-0.1 works? */
92 if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0))
93 return actual_length;
95 return (r);
99 #define LINE_DIM 1024
100 #define MAXLINES 50
101 #define BUF_SIZE 4096
102 #define DESCR_MAX 129
104 #define SEARCH_DEFAULT 0
105 #define SEARCH_TARGET 1
106 #define SEARCH_BUSDEV 2
108 #define SWITCH_CONFIG_MAXTRIES 5
110 #define SHOW_PROGRESS if (show_progress) fprintf
112 char *TempPP=NULL;
114 static struct libusb_context *ctx = NULL;
115 static struct libusb_device *dev;
116 static struct libusb_device_handle *devh;
118 int DefaultVendor=0, DefaultProduct=0, TargetVendor=0, TargetProduct=-1, TargetClass=0;
119 int MessageEndpoint=0, ResponseEndpoint=0, ReleaseDelay=0;
120 int targetDeviceCount=0, searchMode;
121 int devnum=-1, busnum=-1;
122 int ret;
124 unsigned int ModeMap = 0;
125 #define DETACHONLY_MODE 0x00000001
126 #define HUAWEI_MODE 0x00000002
127 #define SIERRA_MODE 0x00000004
128 #define SONY_MODE 0x00000008
129 #define GCT_MODE 0x00000010
130 #define KOBIL_MODE 0x00000020
131 #define SEQUANS_MODE 0x00000040
132 #define MOBILEACTION_MODE 0x00000080
133 #define CISCO_MODE 0x00000100
134 #define QISDA_MODE 0x00000200
135 #define QUANTA_MODE 0x00000400
136 #define BLACKBERRY_MODE 0x00000800
137 #define PANTECH_MODE 0x00001000
139 char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0;
140 char NeedResponse=0, NoDriverLoading=0, InquireDevice=1, sysmode=0, mbim=0;
142 char imanufact[DESCR_MAX], iproduct[DESCR_MAX], iserial[DESCR_MAX];
144 char MessageContent[LINE_DIM];
145 char MessageContent2[LINE_DIM];
146 char MessageContent3[LINE_DIM];
147 char TargetProductList[LINE_DIM];
148 char DefaultProductList[5];
149 char ByteString[LINE_DIM/2];
150 char buffer[BUF_SIZE];
152 FILE *output;
155 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
156 int Interface = -1, Configuration = 0, AltSetting = -1;
159 static struct option long_options[] = {
160 {"help", no_argument, 0, 'h'},
161 {"version", no_argument, 0, 'e'},
162 {"default-vendor", required_argument, 0, 'v'},
163 {"default-product", required_argument, 0, 'p'},
164 {"target-vendor", required_argument, 0, 'V'},
165 {"target-product", required_argument, 0, 'P'},
166 {"target-class", required_argument, 0, 'C'},
167 {"message-endpoint", required_argument, 0, 'm'},
168 {"message-content", required_argument, 0, 'M'},
169 {"message-content2", required_argument, 0, '2'},
170 {"message-content3", required_argument, 0, '3'},
171 {"release-delay", required_argument, 0, 'w'},
172 {"response-endpoint", required_argument, 0, 'r'},
173 {"bus-num", required_argument, 0, 'b'},
174 {"device-num", required_argument, 0, 'g'},
175 {"detach-only", no_argument, 0, 'd'},
176 {"huawei-mode", no_argument, 0, 'H'},
177 {"sierra-mode", no_argument, 0, 'S'},
178 {"sony-mode", no_argument, 0, 'O'},
179 {"qisda-mode", no_argument, 0, 'B'},
180 {"quanta-mode", no_argument, 0, 'E'},
181 {"kobil-mode", no_argument, 0, 'T'},
182 {"gct-mode", no_argument, 0, 'G'},
183 {"sequans-mode", no_argument, 0, 'N'},
184 {"mobileaction-mode", no_argument, 0, 'A'},
185 {"cisco-mode", no_argument, 0, 'L'},
186 {"blackberry-mode", no_argument, 0, 'Z'},
187 {"pantech-mode", no_argument, 0, 'F'},
188 {"need-response", no_argument, 0, 'n'},
189 {"reset-usb", no_argument, 0, 'R'},
190 {"config-file", required_argument, 0, 'c'},
191 {"verbose", no_argument, 0, 'W'},
192 {"quiet", no_argument, 0, 'Q'},
193 {"sysmode", no_argument, 0, 'D'},
194 {"no-inquire", no_argument, 0, 'I'},
195 {"stdinput", no_argument, 0, 't'},
196 {"find-mbim", no_argument, 0, 'j'},
197 {"long-config", required_argument, 0, 'f'},
198 {"check-success", required_argument, 0, 's'},
199 {"interface", required_argument, 0, 'i'},
200 {"configuration", required_argument, 0, 'u'},
201 {"altsetting", required_argument, 0, 'a'},
202 {0, 0, 0, 0}
206 void readConfigFile(const char *configFilename)
208 ParseParamHex(configFilename, TargetVendor);
209 ParseParamHex(configFilename, TargetProduct);
210 ParseParamString(configFilename, TargetProductList);
211 ParseParamHex(configFilename, TargetClass);
212 ParseParamHex(configFilename, DefaultVendor);
213 ParseParamHex(configFilename, DefaultProduct);
214 ParseParamBoolMap(configFilename, DetachStorageOnly, ModeMap, DETACHONLY_MODE);
215 ParseParamBoolMap(configFilename, HuaweiMode, ModeMap, HUAWEI_MODE);
216 ParseParamBoolMap(configFilename, SierraMode, ModeMap, SIERRA_MODE);
217 ParseParamBoolMap(configFilename, SonyMode, ModeMap, SONY_MODE);
218 ParseParamBoolMap(configFilename, GCTMode, ModeMap, GCT_MODE);
219 ParseParamBoolMap(configFilename, KobilMode, ModeMap, KOBIL_MODE);
220 ParseParamBoolMap(configFilename, SequansMode, ModeMap, SEQUANS_MODE);
221 ParseParamBoolMap(configFilename, MobileActionMode, ModeMap, MOBILEACTION_MODE);
222 ParseParamBoolMap(configFilename, CiscoMode, ModeMap, CISCO_MODE);
223 ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE);
224 ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE);
225 ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE);
226 ParseParamBoolMap(configFilename, PantechMode, ModeMap, PANTECH_MODE);
227 ParseParamBool(configFilename, NoDriverLoading);
228 ParseParamHex(configFilename, MessageEndpoint);
229 ParseParamString(configFilename, MessageContent);
230 ParseParamString(configFilename, MessageContent2);
231 ParseParamString(configFilename, MessageContent3);
232 ParseParamInt(configFilename, ReleaseDelay);
233 ParseParamHex(configFilename, NeedResponse);
234 ParseParamHex(configFilename, ResponseEndpoint);
235 ParseParamHex(configFilename, ResetUSB);
236 ParseParamHex(configFilename, InquireDevice);
237 ParseParamInt(configFilename, CheckSuccess);
238 ParseParamHex(configFilename, Interface);
239 ParseParamHex(configFilename, Configuration);
240 ParseParamHex(configFilename, AltSetting);
242 /* TargetProductList has priority over TargetProduct */
243 if (TargetProduct != -1 && TargetProductList[0] != '\0') {
244 TargetProduct = -1;
245 SHOW_PROGRESS(output,"Warning: TargetProductList overrides TargetProduct!\n");
248 config_read = 1;
252 void printConfig()
254 if ( DefaultVendor )
255 fprintf (output,"DefaultVendor= 0x%04x\n", DefaultVendor);
256 if ( DefaultProduct )
257 fprintf (output,"DefaultProduct= 0x%04x\n", DefaultProduct);
258 if ( TargetVendor )
259 fprintf (output,"TargetVendor= 0x%04x\n", TargetVendor);
260 if ( TargetProduct > -1 )
261 fprintf (output,"TargetProduct= 0x%04x\n", TargetProduct);
262 if ( TargetClass )
263 fprintf (output,"TargetClass= 0x%02x\n", TargetClass);
264 if ( strlen(TargetProductList) )
265 fprintf (output,"TargetProductList=\"%s\"\n", TargetProductList);
266 if (ModeMap & DETACHONLY_MODE)
267 fprintf (output,"\nDetachStorageOnly=1\n");
268 if (ModeMap & HUAWEI_MODE)
269 fprintf (output,"HuaweiMode=1\n");
270 if (ModeMap & SIERRA_MODE)
271 fprintf (output,"SierraMode=1\n");
272 if (ModeMap & SONY_MODE)
273 fprintf (output,"SonyMode=1\n");
274 if (ModeMap & QISDA_MODE)
275 fprintf (output,"QisdaMode=1\n");
276 if (ModeMap & QUANTA_MODE)
277 fprintf (output,"QuantaMode=1\n");
278 if (ModeMap & GCT_MODE)
279 fprintf (output,"GCTMode=1\n");
280 if (ModeMap & KOBIL_MODE)
281 fprintf (output,"KobilMode=1\n");
282 if (ModeMap & SEQUANS_MODE)
283 fprintf (output,"SequansMode=1\n");
284 if (ModeMap & MOBILEACTION_MODE)
285 fprintf (output,"MobileActionMode=1\n");
286 if (ModeMap & CISCO_MODE)
287 fprintf (output,"CiscoMode=1\n");
288 if (ModeMap & BLACKBERRY_MODE)
289 fprintf (output,"BlackberryMode=1\n");
290 if (ModeMap & PANTECH_MODE)
291 fprintf (output,"PantechMode=1\n");
292 if ( MessageEndpoint )
293 fprintf (output,"MessageEndpoint=0x%02x\n", MessageEndpoint);
294 if ( strlen(MessageContent) )
295 fprintf (output,"MessageContent=\"%s\"\n", MessageContent);
296 if ( strlen(MessageContent2) )
297 fprintf (output,"MessageContent2=\"%s\"\n", MessageContent2);
298 if ( strlen(MessageContent3) )
299 fprintf (output,"MessageContent3=\"%s\"\n", MessageContent3);
300 fprintf (output,"NeedResponse=%i\n", (int)NeedResponse);
301 if ( ResponseEndpoint )
302 fprintf (output,"ResponseEndpoint=0x%02x\n", ResponseEndpoint);
303 if ( Interface > -1 )
304 fprintf (output,"Interface=0x%02x\n", Interface);
305 if ( Configuration > 0 )
306 fprintf (output,"Configuration=0x%02x\n", Configuration);
307 if ( AltSetting > -1 )
308 fprintf (output,"AltSetting=0x%02x\n", AltSetting);
309 if ( InquireDevice )
310 fprintf (output,"\nInquireDevice enabled (default)\n");
311 else
312 fprintf (output,"\nInquireDevice disabled\n");
313 if ( CheckSuccess )
314 fprintf (output,"Success check enabled, max. wait time %d seconds\n", CheckSuccess);
315 if ( sysmode )
316 fprintf (output,"System integration mode enabled\n");
320 int readArguments(int argc, char **argv)
322 int c, option_index = 0, count=0;
323 char *longConfig = NULL;
324 if (argc==1)
326 printHelp();
327 printVersion();
328 exit(1);
331 while (1)
333 c = getopt_long (argc, argv, "hejWQDndHSOBEGTNALZFRItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
334 long_options, &option_index);
336 /* Detect the end of the options. */
337 if (c == -1)
338 break;
339 count++;
340 switch (c)
342 case 'R': ResetUSB = 1; break;
343 case 'v': DefaultVendor = strtol(optarg, NULL, 16); break;
344 case 'p': DefaultProduct = strtol(optarg, NULL, 16); break;
345 case 'V': TargetVendor = strtol(optarg, NULL, 16); break;
346 case 'P': TargetProduct = strtol(optarg, NULL, 16); break;
347 case 'C': TargetClass = strtol(optarg, NULL, 16); break;
348 case 'm': MessageEndpoint = strtol(optarg, NULL, 16); break;
349 case 'M': strncpy(MessageContent, optarg, LINE_DIM); break;
350 case '2': strncpy(MessageContent2, optarg, LINE_DIM); break;
351 case '3': strncpy(MessageContent3, optarg, LINE_DIM); break;
352 case 'w': ReleaseDelay = strtol(optarg, NULL, 10); break;
353 case 'n': NeedResponse = 1; break;
354 case 'r': ResponseEndpoint = strtol(optarg, NULL, 16); break;
355 case 'd': ModeMap = ModeMap + DETACHONLY_MODE; break;
356 case 'H': ModeMap = ModeMap + HUAWEI_MODE; break;
357 case 'S': ModeMap = ModeMap + SIERRA_MODE; break;
358 case 'O': ModeMap = ModeMap + SONY_MODE; break;; break;
359 case 'B': ModeMap = ModeMap + QISDA_MODE; break;
360 case 'E': ModeMap = ModeMap + QUANTA_MODE; break;
361 case 'G': ModeMap = ModeMap + GCT_MODE; break;
362 case 'T': ModeMap = ModeMap + KOBIL_MODE; break;
363 case 'N': ModeMap = ModeMap + SEQUANS_MODE; break;
364 case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break;
365 case 'L': ModeMap = ModeMap + CISCO_MODE; break;
366 case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break;
367 case 'F': ModeMap = ModeMap + PANTECH_MODE; break;
368 case 'c': readConfigFile(optarg); break;
369 case 't': readConfigFile("stdin"); break;
370 case 'W': verbose = 1; show_progress = 1; count--; break;
371 case 'Q': show_progress = 0; verbose = 0; count--; break;
372 case 'D': sysmode = 1; InquireDevice = 0; count--; break;
373 case 's': CheckSuccess = strtol(optarg, NULL, 10); count--; break;
374 case 'I': InquireDevice = 0; break;
375 case 'b': busnum = strtol(optarg, NULL, 10); break;
376 case 'g': devnum = strtol(optarg, NULL, 10); break;
378 case 'i': Interface = strtol(optarg, NULL, 16); break;
379 case 'u': Configuration = strtol(optarg, NULL, 16); break;
380 case 'a': AltSetting = strtol(optarg, NULL, 16); break;
381 case 'j': mbim = 1; break;
383 case 'f':
384 longConfig = malloc(strlen(optarg)+5);
385 strcpy(longConfig,"##\n");
386 strcat(longConfig,optarg);
387 strcat(longConfig,"\n");
388 readConfigFile(longConfig);
389 free(longConfig);
390 break;
392 case 'e':
393 printVersion();
394 exit(0);
395 break;
396 case 'h':
397 printVersion();
398 printHelp();
399 exit(0);
400 break;
402 default: /* Unsupported - error message has already been printed */
403 fprintf (output,"\n");
404 printHelp();
405 exit(1);
409 return count;
413 int main(int argc, char **argv)
415 int numDefaults=0, sonySuccess=0;
416 int currentConfig=0, defaultClass=0, interfaceClass=0;
417 struct libusb_device_descriptor descriptor;
418 struct libusb_config_descriptor *config;
421 /* Make sure we have empty strings even if not set by config */
422 TargetProductList[0] = '\0';
423 MessageContent[0] = '\0';
424 MessageContent2[0] = '\0';
425 MessageContent3[0] = '\0';
426 DefaultProductList[0] = '\0';
428 /* Useful for debugging during boot */
429 // output=fopen("/dev/console", "w");
430 output=stdout;
432 signal(SIGTERM, release_usb_device);
435 * Parameter parsing, USB preparation/diagnosis, plausibility checks
438 /* Check command arguments, use params instead of config file when given */
439 switch (readArguments(argc, argv)) {
440 case 0: /* no argument or -W, -q or -s */
441 break;
442 default: /* one or more arguments except -W, -q or -s */
443 if (!config_read) /* if arguments contain -c, the config file was already processed */
444 if (verbose) fprintf(output,"Take all parameters from the command line\n\n");
447 if (verbose) {
448 printVersion();
449 printConfig();
450 fprintf(output,"\n");
453 /* Some sanity checks. The default IDs are mandatory */
454 if (!(DefaultVendor && DefaultProduct)) {
455 SHOW_PROGRESS(output,"No default vendor/product ID given. Abort\n\n");
456 exit(1);
459 if (strlen(MessageContent)) {
460 if (strlen(MessageContent) % 2 != 0) {
461 fprintf(stderr, "Error: MessageContent hex string has uneven length. Abort\n\n");
462 exit(1);
464 if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) {
465 fprintf(stderr, "Error: MessageContent %s\n is not a hex string. Abort\n\n", MessageContent);
466 exit(1);
470 if (devnum == -1) {
471 searchMode = SEARCH_DEFAULT;
472 } else {
473 SHOW_PROGRESS(output,"Use given bus/device number: %03d/%03d ...\n", busnum, devnum);
474 searchMode = SEARCH_BUSDEV;
477 if (show_progress)
478 if (CheckSuccess && !(TargetVendor || TargetProduct > -1 || TargetProductList[0] != '\0') && !TargetClass)
479 fprintf(output,"Note: No target parameter given; success check limited\n");
481 if (TargetProduct > -1 && TargetProductList[0] == '\0') {
482 sprintf(TargetProductList,"%04x",TargetProduct);
483 TargetProduct = -1;
486 /* libusb initialization */
487 libusb_init(&ctx);
489 if (verbose)
490 libusb_set_debug(ctx, 3);
492 if (mbim) {
493 printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) );
494 exit(0);
497 /* Count existing target devices, remember for success check */
498 if (searchMode != SEARCH_BUSDEV && (TargetVendor || TargetClass)) {
499 SHOW_PROGRESS(output,"Look for target devices ...\n");
500 search_devices(&targetDeviceCount, TargetVendor, TargetProductList, TargetClass, 0, SEARCH_TARGET);
501 if (targetDeviceCount) {
502 SHOW_PROGRESS(output," Found devices in target mode or class (%d)\n", targetDeviceCount);
503 } else
504 SHOW_PROGRESS(output," No devices in target mode or class found\n");
507 /* Count default devices, get the last one found */
508 SHOW_PROGRESS(output,"Look for default devices ...\n");
510 sprintf(DefaultProductList,"%04x",DefaultProduct);
511 dev = search_devices(&numDefaults, DefaultVendor, DefaultProductList, TargetClass, Configuration, searchMode);
512 if (numDefaults) {
513 SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults);
514 } else {
515 SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n");
516 exit(0);
518 if (dev == NULL) {
519 SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n");
520 exit(0);
521 } else {
522 if (devnum == -1) {
523 devnum = libusb_get_device_address(dev);
524 busnum = libusb_get_bus_number(dev);
525 SHOW_PROGRESS(output,"Access device %03d on bus %03d\n", devnum, busnum);
527 libusb_open(dev, &devh);
528 if (devh == NULL) {
529 SHOW_PROGRESS(output,"Error opening the device. Abort\n\n");
530 exit(1);
534 /* Get current configuration of default device
535 * A configuration value of -1 helps with quirky devices which have
536 * trouble determining the current configuration. We are just using the
537 * current config branch then.
538 * This affects only single-configuration devices so it's no problem.
539 * The dispatcher is using this always if no change of configuration
540 * is required for switching
542 if (Configuration > -1)
543 currentConfig = get_current_configuration(devh);
544 else {
545 SHOW_PROGRESS(output,"Skip the check for the current configuration\n");
546 currentConfig = 0;
549 libusb_get_device_descriptor(dev, &descriptor);
550 defaultClass = descriptor.bDeviceClass;
551 libusb_get_config_descriptor(dev, 0, &config);
552 if (Interface == -1)
553 Interface = config->interface[0].altsetting[0].bInterfaceNumber;
554 SHOW_PROGRESS(output,"Use interface number %d\n", Interface);
556 /* Get class of default device/interface */
557 interfaceClass = get_interface_class(config, Interface);
558 libusb_free_config_descriptor(config);
559 if (interfaceClass == -1) {
560 fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
561 exit(1);
564 if (defaultClass == 0)
565 defaultClass = interfaceClass;
566 else
567 if (interfaceClass == 8 && defaultClass != 8) {
568 /* Weird device with default class other than 0 and differing interface class */
569 SHOW_PROGRESS(output,"Ambiguous Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
570 defaultClass = 8;
573 if (strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0)
574 if (defaultClass != 8) {
575 fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n"
576 " interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
577 exit(1);
580 /* Check or get endpoints */
581 if (strlen(MessageContent) || InquireDevice || ModeMap & CISCO_MODE) {
582 if (!MessageEndpoint)
583 MessageEndpoint = find_first_bulk_output_endpoint(dev);
584 if (!MessageEndpoint) {
585 fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n");
586 exit(1);
588 if (!ResponseEndpoint)
589 ResponseEndpoint = find_first_bulk_input_endpoint(dev);
590 if (!ResponseEndpoint) {
591 fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n");
592 exit(1);
594 SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint, ResponseEndpoint);
597 if (InquireDevice && show_progress) {
598 if (defaultClass == 0x08) {
599 SHOW_PROGRESS(output,"Inquire device details; driver will be detached ...\n");
600 detachDriver();
601 if (deviceInquire() >= 0)
602 InquireDevice = 2;
603 } else
604 SHOW_PROGRESS(output,"Not a storage device, skip SCSI inquiry\n");
607 deviceDescription();
608 if (show_progress) {
609 fprintf(output,"\nUSB description data (for identification)\n");
610 fprintf(output,"-------------------------\n");
611 fprintf(output,"Manufacturer: %s\n", imanufact);
612 fprintf(output," Product: %s\n", iproduct);
613 fprintf(output," Serial No.: %s\n", iserial);
614 fprintf(output,"-------------------------\n");
617 /* Special modes are exclusive, so check for illegal combinations.
618 * More than one bit set?
620 if ( ModeMap & (ModeMap-1) ) {
621 fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n");
622 exit(1);
625 if (strlen(MessageContent) && ModeMap ) {
626 MessageContent[0] = '\0';
627 SHOW_PROGRESS(output,"Warning: MessageContent ignored; can't combine with special mode\n");
630 if ( !ModeMap && !strlen(MessageContent) && AltSetting == -1 && Configuration == 0 )
631 SHOW_PROGRESS(output,"Warning: no switching method given. See documentation\n");
634 * The switching actions
637 if (sysmode) {
638 openlog("usb_modeswitch", 0, LOG_SYSLOG);
639 syslog(LOG_NOTICE, "switch device %04x:%04x on %03d/%03d", DefaultVendor, DefaultProduct, busnum, devnum);
642 if (ModeMap & DETACHONLY_MODE) {
643 SHOW_PROGRESS(output,"Detach storage driver as switching method ...\n");
644 if (InquireDevice == 2) {
645 SHOW_PROGRESS(output," Any driver was already detached for inquiry. Do nothing\n");
646 } else {
647 ret = detachDriver();
648 if (ret == 2)
649 SHOW_PROGRESS(output," You may want to remove the storage driver manually\n");
653 if(ModeMap & HUAWEI_MODE) {
654 switchHuaweiMode();
656 if(ModeMap & SIERRA_MODE) {
657 switchSierraMode();
659 if(ModeMap & GCT_MODE) {
660 detachDriver();
661 switchGCTMode();
663 if(ModeMap & QISDA_MODE) {
664 switchQisdaMode();
666 if(ModeMap & KOBIL_MODE) {
667 detachDriver();
668 switchKobilMode();
670 if(ModeMap & QUANTA_MODE) {
671 switchQuantaMode();
673 if(ModeMap & SEQUANS_MODE) {
674 switchSequansMode();
676 if(ModeMap & MOBILEACTION_MODE) {
677 switchActionMode();
679 if(ModeMap & CISCO_MODE) {
680 detachDriver();
681 switchCiscoMode();
683 if(ModeMap & BLACKBERRY_MODE) {
684 detachDriver();
685 switchBlackberryMode();
687 if(ModeMap & PANTECH_MODE) {
688 detachDriver();
689 switchPantechMode();
691 if(ModeMap & SONY_MODE) {
692 if (CheckSuccess)
693 SHOW_PROGRESS(output,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
694 CheckSuccess = 0; /* separate and implied success control */
695 sonySuccess = switchSonyMode();
698 if (strlen(MessageContent) && MessageEndpoint) {
699 if (InquireDevice != 2)
700 detachDriver();
701 switchSendMessage();
704 if (Configuration > 0) {
705 if (currentConfig != Configuration) {
706 if (switchConfiguration()) {
707 currentConfig = get_current_configuration(devh);
708 if (currentConfig == Configuration) {
709 SHOW_PROGRESS(output,"The configuration was set successfully\n");
710 } else {
711 SHOW_PROGRESS(output,"Changing the configuration has failed\n");
714 } else {
715 SHOW_PROGRESS(output,"Target configuration %d found. Do nothing\n", currentConfig);
719 if (AltSetting != -1) {
720 switchAltSetting();
723 /* No "removal" check if these are set */
724 if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) {
725 libusb_close(devh);
726 devh = 0;
729 if (ResetUSB) {
730 resetUSB();
731 devh = 0;
734 if (CheckSuccess) {
735 if (searchMode == SEARCH_BUSDEV && sysmode) {
736 SHOW_PROGRESS(output,"Bus/dev search active, refer success check to wrapper. Bye!\n\n");
737 printf("ok:busdev\n");
738 goto CLOSING;
740 if (checkSuccess()) {
741 if (sysmode) {
742 if (NoDriverLoading)
743 printf("ok:\n");
744 else
745 if (TargetProduct < 1)
746 printf("ok:no_data\n");
747 else
748 printf("ok:%04x:%04x\n", TargetVendor, TargetProduct);
750 } else
751 if (sysmode)
752 printf("fail:\n");
753 } else {
754 if (ModeMap & SONY_MODE)
755 if (sonySuccess) {
756 if (sysmode) {
757 syslog(LOG_NOTICE, "switched S.E. MD400 to modem mode");
758 printf("ok:\n"); /* ACM device, no driver action */
760 SHOW_PROGRESS(output,"-> device should be stable now. Bye!\n\n");
761 } else {
762 if (sysmode)
763 printf("fail:\n");
764 SHOW_PROGRESS(output,"-> switching was probably not completed. Bye!\n\n");
766 else
767 SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n");
769 CLOSING:
770 if (sysmode)
771 closelog();
772 if (devh)
773 libusb_close(devh);
774 exit(0);
778 /* Get descriptor strings if available (identification details) */
779 void deviceDescription ()
781 char* c;
782 memset (imanufact, ' ', DESCR_MAX);
783 memset (iproduct, ' ', DESCR_MAX);
784 memset (iserial, ' ', DESCR_MAX);
786 struct libusb_device_descriptor descriptor;
787 libusb_get_device_descriptor(dev, &descriptor);
789 int iManufacturer = descriptor.iManufacturer;
790 int iProduct = descriptor.iProduct;
791 int iSerialNumber = descriptor.iSerialNumber;
793 if (iManufacturer) {
794 ret = libusb_get_string_descriptor_ascii(devh, iManufacturer, (unsigned char *)imanufact, DESCR_MAX);
795 if (ret < 0)
796 fprintf(stderr, "Error: could not get description string \"manufacturer\"\n");
797 } else
798 strcpy(imanufact, "not provided");
799 c = strstr(imanufact, " ");
800 if (c)
801 memset((void*)c, '\0', 1);
803 if (iProduct) {
804 ret = libusb_get_string_descriptor_ascii(devh, iProduct, (unsigned char *)iproduct, DESCR_MAX);
805 if (ret < 0)
806 fprintf(stderr, "Error: could not get description string \"product\"\n");
807 } else
808 strcpy(iproduct, "not provided");
809 c = strstr(iproduct, " ");
810 if (c)
811 memset((void*)c, '\0', 1);
813 if (iSerialNumber) {
814 ret = libusb_get_string_descriptor_ascii(devh, iSerialNumber, (unsigned char *)iserial, DESCR_MAX);
815 if (ret < 0)
816 fprintf(stderr, "Error: could not get description string \"serial number\"\n");
817 } else
818 strcpy(iserial, "not provided");
819 c = strstr(iserial, " ");
820 if (c)
821 memset((void*)c, '\0', 1);
825 /* Print result of SCSI command INQUIRY (identification details) */
826 int deviceInquire ()
828 const unsigned char inquire_msg[] = {
829 0x55, 0x53, 0x42, 0x43, 0x12, 0x34, 0x56, 0x78,
830 0x24, 0x00, 0x00, 0x00, 0x80, 0x00, 0x06, 0x12,
831 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
834 char *command;
835 char data[36];
836 int i;
838 command = malloc(31);
839 if (command == NULL) {
840 ret = 1;
841 goto out;
844 memcpy(command, inquire_msg, sizeof (inquire_msg));
846 ret = libusb_claim_interface(devh, Interface);
847 if (ret != 0) {
848 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip device inquiry\n", ret);
849 goto out;
851 libusb_clear_halt(devh, MessageEndpoint);
853 ret = usb_bulk_io(devh, MessageEndpoint, (char *)command, 31, 0);
854 if (ret < 0) {
855 SHOW_PROGRESS(output," INQUIRY message failed (error %d)\n", ret);
856 goto out;
859 ret = usb_bulk_io(devh, ResponseEndpoint, data, 36, 0);
860 if (ret < 0) {
861 SHOW_PROGRESS(output," INQUIRY response failed (error %d)\n", ret);
862 goto out;
865 i = usb_bulk_io(devh, ResponseEndpoint, command, 13, 0);
867 fprintf(output,"\nSCSI inquiry data (for identification)\n");
868 fprintf(output,"-------------------------\n");
870 fprintf(output," Vendor String: ");
871 for (i = 8; i < 16; i++) printf("%c",data[i]);
872 fprintf(output,"\n");
874 fprintf(output," Model String: ");
875 for (i = 16; i < 32; i++) printf("%c",data[i]);
876 fprintf(output,"\n");
878 fprintf(output,"Revision String: ");
879 for (i = 32; i < 36; i++) printf("%c",data[i]);
881 fprintf(output,"\n-------------------------\n");
883 out:
884 if (strlen(MessageContent) == 0)
885 libusb_clear_halt(devh, MessageEndpoint);
886 libusb_release_interface(devh, Interface);
887 free(command);
888 return ret;
892 int findMBIMConfig(int vendor, int product, int mode)
894 struct libusb_device **devs;
895 int resultConfig=0;
896 int i=0, j;
898 if (libusb_get_device_list(ctx, &devs) < 0) {
899 perror("Libusb could not access USB. Abort");
900 return 0;
903 SHOW_PROGRESS(output,"Search USB devices ...\n");
904 while ((dev = devs[i++]) != NULL) {
905 struct libusb_device_descriptor descriptor;
906 libusb_get_device_descriptor(dev, &descriptor);
908 if (mode == SEARCH_BUSDEV) {
909 if ((libusb_get_bus_number(dev) != busnum) ||
910 (libusb_get_device_address(dev) != devnum)) {
911 continue;
912 } else {
913 if (descriptor.idVendor != vendor)
914 continue;
915 if (product != descriptor.idProduct)
916 continue;
919 SHOW_PROGRESS(output,"Found device, search for MBIM configuration...\n");
921 // No check if there is only one configuration
922 if (descriptor.bNumConfigurations < 2)
923 return -1;
925 // Checking all interfaces of all configurations
926 for (j=0; j<descriptor.bNumConfigurations; j++) {
927 struct libusb_config_descriptor *config;
929 libusb_get_config_descriptor(dev, j, &config);
930 resultConfig = config->bConfigurationValue;
931 for (i=0; i<config->bNumInterfaces; i++) {
932 if ( config->interface[i].altsetting[0].bInterfaceClass == 2 )
933 if ( config->interface[i].altsetting[0].bInterfaceSubClass == 0x0e ) {
934 // found MBIM interface in this configuration
935 libusb_free_config_descriptor(config);
936 return resultConfig;
939 libusb_free_config_descriptor(config);
941 return -1;
943 return 0;
946 void resetUSB ()
948 int success;
949 int bpoint = 0;
951 if (show_progress) {
952 fprintf(output,"Reset USB device ");
953 fflush(stdout);
955 sleep( 1 );
956 do {
957 success = libusb_reset_device(devh);
958 if ( ((bpoint % 10) == 0) && show_progress ) {
959 fprintf(output,".");
960 fflush(stdout);
962 bpoint++;
963 if (bpoint > 100)
964 success = 1;
965 } while (success < 0);
967 if ( success ) {
968 SHOW_PROGRESS(output,"\n Device reset failed.\n");
969 } else
970 SHOW_PROGRESS(output,"\n Device was reset\n");
974 int switchSendMessage ()
976 const char* cmdHead = "55534243";
977 int ret, i;
978 char* msg[3];
979 msg[0] = MessageContent;
980 msg[1] = MessageContent2;
981 msg[2] = MessageContent3;
983 /* May be activated in future versions */
984 // if (MessageContent2[0] != '\0' || MessageContent3[0] != '\0')
985 // NeedResponse = 1;
987 SHOW_PROGRESS(output,"Set up interface %d\n", Interface);
988 if (InquireDevice != 2) {
989 ret = libusb_claim_interface(devh, Interface);
990 if (ret != 0) {
991 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret);
992 return 0;
995 libusb_clear_halt(devh, MessageEndpoint);
996 SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint);
997 if (show_progress)
998 fflush(stdout);
1000 for (i=0; i<3; i++) {
1001 if ( strlen(msg[i]) == 0)
1002 continue;
1004 if ( sendMessage(msg[i], i+1) )
1005 goto skip;
1007 if (NeedResponse) {
1008 if ( strstr(msg[i],cmdHead) != NULL ) {
1009 // UFI command
1010 SHOW_PROGRESS(output,"Read the response to message %d (CSW) ...\n", i+1);
1011 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1012 } else {
1013 // Other bulk transfer
1014 SHOW_PROGRESS(output,"Read the response to message %d ...\n", i+1);
1015 ret = read_bulk(ResponseEndpoint, ByteString, strlen(msg[i])/2 );
1017 if (ret < 0)
1018 goto skip;
1022 SHOW_PROGRESS(output,"Reset response endpoint 0x%02x\n", ResponseEndpoint);
1023 ret = libusb_clear_halt(devh, ResponseEndpoint);
1024 if (ret)
1025 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1026 SHOW_PROGRESS(output,"Reset message endpoint 0x%02x\n", MessageEndpoint);
1027 ret = libusb_clear_halt(devh, MessageEndpoint);
1028 if (ret)
1029 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1030 usleep(50000);
1032 if (ReleaseDelay) {
1033 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1034 usleep(ReleaseDelay*1000);
1036 ret = libusb_release_interface(devh, Interface);
1037 if (ret)
1038 goto skip;
1039 return 1;
1041 skip:
1042 SHOW_PROGRESS(output," Device is gone, skip any further commands\n");
1043 libusb_close(devh);
1044 devh = 0;
1045 return 2;
1049 int switchConfiguration ()
1051 int count = SWITCH_CONFIG_MAXTRIES;
1053 SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration);
1054 while (((ret = libusb_set_configuration(devh, Configuration)) < 0) && --count) {
1055 SHOW_PROGRESS(output," Device is busy, try to detach kernel driver\n");
1056 detachDriver();
1058 if (ret < 0 ) {
1059 SHOW_PROGRESS(output," Changing the configuration failed (error %d). Try to continue\n", ret);
1060 return 0;
1061 } else {
1062 SHOW_PROGRESS(output," OK, configuration set\n");
1063 return 1;
1067 int switchAltSetting ()
1070 SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting);
1071 ret = libusb_claim_interface(devh, Interface);
1072 ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting);
1073 libusb_release_interface(devh, Interface);
1074 if (ret < 0) {
1075 SHOW_PROGRESS(output," Change to alt setting returned error %d. Try to continue\n", ret);
1076 return 0;
1077 } else
1078 return 1;
1082 void switchHuaweiMode ()
1085 SHOW_PROGRESS(output,"Send old Huawei control message ...\n");
1086 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE, \
1087 LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, (unsigned char *)buffer, 0, 1000);
1088 if (ret != 0) {
1089 fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret);
1090 exit(1);
1095 void switchSierraMode ()
1097 SHOW_PROGRESS(output,"Send Sierra control message\n");
1098 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR, 0x0b, 00000001, 0, (unsigned char *)buffer, 0, 1000);
1099 if (ret == LIBUSB_ERROR_PIPE) {
1100 SHOW_PROGRESS(output," communication with device stopped. May have switched modes anyway\n");
1101 return;
1103 if (ret < 0) {
1104 fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret);
1105 exit(1);
1110 void switchGCTMode ()
1112 ret = libusb_claim_interface(devh, Interface);
1113 if (ret != 0) {
1114 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret);
1115 return;
1117 SHOW_PROGRESS(output,"Send GCT control message 1 ...\n");
1118 ret = libusb_control_transfer(devh, 0xa1, 0xa0, 0, Interface, (unsigned char *)buffer, 1, 1000);
1119 if (ret < 0) {
1120 SHOW_PROGRESS(output," GCT control message 1 failed (error %d), continue anyway ...\n", ret);
1122 SHOW_PROGRESS(output,"Send GCT control message 2 ...\n");
1123 ret = libusb_control_transfer(devh, 0xa1, 0xfe, 0, Interface, (unsigned char *)buffer, 1, 1000);
1124 if (ret < 0) {
1125 SHOW_PROGRESS(output," GCT control message 2 failed (error %d). Abort\n\n", ret);
1127 libusb_release_interface(devh, Interface);
1128 if (ret < 0)
1129 exit(1);
1133 void switchKobilMode() {
1134 SHOW_PROGRESS(output,"Send Kobil control message ...\n");
1135 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1136 0x88, 0, 0, (unsigned char *)buffer, 8, 1000);
1137 if (ret < 0) {
1138 fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret);
1139 exit(1);
1144 void switchQisdaMode () {
1145 SHOW_PROGRESS(output,"Sending Qisda control message ...\n");
1146 memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1147 ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, (unsigned char *)buffer, 16, 1000);
1148 if (ret < 0) {
1149 fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret);
1150 exit(1);
1155 void switchQuantaMode() {
1156 SHOW_PROGRESS(output,"Send Quanta control message ...\n");
1157 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1158 0xff, 0, 0, (unsigned char *)buffer, 0, 1000);
1159 if (ret < 0) {
1160 SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret);
1161 exit(1);
1166 void switchBlackberryMode ()
1168 SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n");
1169 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1170 0xb1, 0x0000, 0, (unsigned char *)buffer, 8, 1000);
1171 if (ret != 8) {
1172 fprintf(stderr, "Error: Blackberry control message 1 failed (result %d)\n", ret);
1174 SHOW_PROGRESS(output,"Send Blackberry control message 2 ...\n");
1175 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1176 0xa9, 0x000e, 0, (unsigned char *)buffer, 2, 1000);
1177 if (ret != 2) {
1178 fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret);
1179 exit(1);
1184 void switchPantechMode()
1186 SHOW_PROGRESS(output,"Send Pantech control message ...\n");
1187 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, 0x70, 2, 0, (unsigned char *)buffer, 0, 1000);
1188 if (ret < 0) {
1189 SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret);
1190 exit(1);
1195 #define EP_OUT 0x02
1196 #define EP_IN 0x81
1197 #define SIZE 0x08
1199 #define MOBILE_ACTION_READLOOP1 63
1200 #define MOBILE_ACTION_READLOOP2 73
1202 /* If anyone can test the MobileAction cable - I bet this
1203 * function (which is confirmed working) can be greatly
1204 * simplified ...
1207 void switchActionMode ()
1209 int i;
1210 SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n");
1211 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1212 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS + LIBUSB_RECIPIENT_INTERFACE, 0x09, 0x0300, 0, (unsigned char *)buffer, SIZE, 1000);
1213 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1214 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS + LIBUSB_RECIPIENT_INTERFACE, 0x09, 0x0300, 0, (unsigned char *)buffer, SIZE, 1000);
1215 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1216 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1217 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1218 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1219 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1220 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1221 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1222 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1223 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1224 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1225 for (i=0; i < MOBILE_ACTION_READLOOP1; i++) {
1226 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1228 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1229 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1230 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1231 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1232 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1233 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1234 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1235 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1236 for (i=0; i < MOBILE_ACTION_READLOOP2; i++) {
1237 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1239 memcpy(buffer, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE);
1240 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1241 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1242 memcpy(buffer, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE);
1243 ret = usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1244 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1245 if (ret < 0) {
1246 SHOW_PROGRESS(output," MobileAction control sequence did not complete\n Last error was %d\n",ret);
1247 } else {
1248 SHOW_PROGRESS(output," MobileAction control sequence complete\n");
1253 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1254 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1256 #define SQN_DEFAULT_DEVICE_MODE 0x00
1257 #define SQN_MASS_STORAGE_MODE 0x01
1258 #define SQN_CUSTOM_DEVICE_MODE 0x02
1260 void switchSequansMode() {
1262 SHOW_PROGRESS(output,"Send Sequans control message\n");
1263 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE, 0, (unsigned char *)buffer, 0, 1000);
1264 if (ret < 0) {
1265 fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret);
1266 exit(1);
1270 void switchCiscoMode() {
1271 int i;
1272 char* msg[11];
1274 msg[0] = "55534243f83bcd810002000080000afd000000030000000100000000000000";
1275 msg[1] = "55534243984300820002000080000afd000000070000000100000000000000";
1276 msg[2] = "55534243984300820000000000000afd000100071000000000000000000000";
1277 msg[3] = "55534243984300820002000080000afd000200230000000100000000000000";
1278 msg[4] = "55534243984300820000000000000afd000300238200000000000000000000";
1279 msg[5] = "55534243984300820002000080000afd000200260000000100000000000000";
1280 msg[6] = "55534243984300820000000000000afd00030026c800000000000000000000";
1281 msg[7] = "55534243d84c04820002000080000afd000010730000000100000000000000";
1282 msg[8] = "55534243d84c04820002000080000afd000200240000000100000000000000";
1283 msg[9] = "55534243d84c04820000000000000afd000300241300000000000000000000";
1284 msg[10] = "55534243d84c04820000000000000afd000110732400000000000000000000";
1286 SHOW_PROGRESS(output,"Set up Cisco interface %d\n", Interface);
1287 ret = libusb_claim_interface(devh, Interface);
1288 if (ret < 0) {
1289 SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret);
1290 exit(1);
1292 // libusb_clear_halt(devh, MessageEndpoint);
1293 if (show_progress)
1294 fflush(output);
1296 for (i=0; i<11; i++) {
1297 if ( sendMessage(msg[i], i+1) )
1298 goto skip;
1300 SHOW_PROGRESS(output," Read the response (CSW) to bulk message %d ...\n",i+1);
1301 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1302 if (ret < 0)
1303 goto skip;
1306 if (ReleaseDelay) {
1307 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1308 usleep(ReleaseDelay*1000);
1310 ret = libusb_release_interface(devh, Interface);
1311 if (ret < 0)
1312 goto skip;
1313 return;
1315 skip:
1316 SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret);
1317 libusb_close(devh);
1318 devh = 0;
1322 int switchSonyMode ()
1324 int i, found;
1325 detachDriver();
1327 if (CheckSuccess) {
1328 CheckSuccess = 0;
1331 SHOW_PROGRESS(output,"Send Sony control message\n");
1332 ret = libusb_control_transfer(devh, 0xc0, 0x11, 2, 0, (unsigned char *)buffer, 3, 100);
1333 if (ret < 0) {
1334 fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret);
1335 exit(1);
1336 } else
1337 SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n");
1339 libusb_close(devh);
1340 devh = 0;
1342 /* Now waiting for the device to reappear */
1343 devnum=-1;
1344 busnum=-1;
1345 i=0;
1346 dev = 0;
1347 while ( dev == 0 && i < 30 ) {
1348 if ( i > 5 ) {
1349 dev = search_devices(&found, DefaultVendor, DefaultProductList, TargetClass, 0, SEARCH_TARGET);
1351 if ( dev != 0 )
1352 break;
1353 sleep(1);
1354 if (show_progress) {
1355 fprintf(output,"#");
1356 fflush(stdout);
1358 i++;
1360 SHOW_PROGRESS(output,"\n After %d seconds:",i);
1361 if ( dev ) {
1362 SHOW_PROGRESS(output," device came back, proceed\n");
1363 libusb_open(dev, &devh);
1364 if (devh == 0) {
1365 fprintf(stderr, "Error: could not get handle on device\n");
1366 return 0;
1368 } else {
1369 SHOW_PROGRESS(output," device still gone, abort\n");
1370 return 0;
1372 sleep(1);
1374 SHOW_PROGRESS(output,"Send Sony control message again ...\n");
1375 ret = libusb_control_transfer(devh, 0xc0, 0x11, 2, 0, (unsigned char *)buffer, 3, 100);
1376 if (ret < 0) {
1377 fprintf(stderr, "Error: Sony control message (2) failed (error %d)\n", ret);
1378 return 0;
1380 SHOW_PROGRESS(output," OK, control message sent\n");
1381 return 1;
1385 /* Detach driver
1387 int detachDriver()
1390 SHOW_PROGRESS(output,"Looking for active driver ...\n");
1391 ret = libusb_kernel_driver_active(devh, 0);
1392 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1393 fprintf(output," Can't do driver detection on this platform.\n");
1394 return 2;
1396 if (ret < 0) {
1397 fprintf(output," Driver check failed with error %d. Try to continue\n", ret);
1398 return 2;
1400 if (ret == 0) {
1401 SHOW_PROGRESS(output," No active driver found. Detached before or never attached\n");
1402 return 1;
1405 ret = libusb_detach_kernel_driver(devh, Interface);
1406 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1407 fprintf(output," Can't do driver detaching on this platform.\n");
1408 return 2;
1410 if (ret == 0) {
1411 SHOW_PROGRESS(output," OK, driver detached\n");
1412 } else
1413 SHOW_PROGRESS(output," Driver detach failed (error %d). Try to continue\n", ret);
1414 return 1;
1418 int sendMessage(char* message, int count)
1420 int message_length;
1422 if (strlen(message) % 2 != 0) {
1423 fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count);
1424 return 1;
1426 message_length = strlen(message) / 2;
1427 if ( hexstr2bin(message, ByteString, message_length) == -1) {
1428 fprintf(stderr, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n", count, MessageContent);
1429 return 1;
1431 SHOW_PROGRESS(output,"Trying to send message %d to endpoint 0x%02x ...\n", count, MessageEndpoint);
1432 fflush(output);
1433 ret = write_bulk(MessageEndpoint, ByteString, message_length);
1434 if (ret == LIBUSB_ERROR_NO_DEVICE)
1435 return 1;
1437 return 0;
1441 int checkSuccess()
1443 int i=0;
1444 int newTargetCount, success=0;
1446 SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess);
1447 sleep(1);
1449 /* If target parameters are given, don't check for vanished device
1450 * Changed for Cisco AM10 where a new device is added while the install
1451 * storage device stays active
1453 if ((TargetVendor || TargetClass) && devh) {
1454 libusb_close(devh);
1455 devh = 0;
1458 /* if target ID is not given but target class is, assign default as target;
1459 * it will be needed for sysmode output
1461 if (!TargetVendor && TargetClass) {
1462 TargetVendor = DefaultVendor;
1463 TargetProduct = DefaultProduct;
1466 /* devh is 0 if device vanished during command transmission or if target params were given
1468 if (devh)
1469 for (i=0; i < CheckSuccess; i++) {
1471 /* Test if default device still can be accessed; positive result does
1472 * not necessarily mean failure
1474 SHOW_PROGRESS(output," Wait for original device to vanish ...\n");
1476 ret = libusb_claim_interface(devh, Interface);
1477 libusb_release_interface(devh, Interface);
1478 if (ret < 0) {
1479 SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n");
1480 libusb_close(devh);
1481 devh = 0;
1482 break;
1484 if (i == CheckSuccess-1) {
1485 SHOW_PROGRESS(output," Original device still present after the timeout\n\nMode switch most likely failed. Bye!\n\n");
1486 } else
1487 sleep(1);
1490 if ( TargetVendor && (TargetProduct > -1 || TargetProductList[0] != '\0') ) {
1492 /* Recount target devices (compare with previous count) if target data is given.
1493 * Target device on the same bus with higher device number is returned,
1494 * description is read for syslog message
1496 for (i=i; i < CheckSuccess; i++) {
1497 SHOW_PROGRESS(output," Search for target devices ...\n");
1498 dev = search_devices(&newTargetCount, TargetVendor, TargetProductList, TargetClass, 0, SEARCH_TARGET);
1499 if (dev && (newTargetCount > targetDeviceCount)) {
1500 fprintf(output,"\nFound target device, open it\n");
1501 libusb_open(dev, &devh);
1502 deviceDescription();
1503 libusb_close(devh);
1504 devh = 0;
1505 if (verbose) {
1506 fprintf(output,"\nFound target device %03d on bus %03d\n", \
1507 libusb_get_device_address(dev), libusb_get_bus_number(dev));
1508 fprintf(output,"\nTarget device description data\n");
1509 fprintf(output,"-------------------------\n");
1510 fprintf(output,"Manufacturer: %s\n", imanufact);
1511 fprintf(output," Product: %s\n", iproduct);
1512 fprintf(output," Serial No.: %s\n", iserial);
1513 fprintf(output,"-------------------------\n");
1515 SHOW_PROGRESS(output," Found correct target device\n\nMode switch succeeded. Bye!\n\n");
1516 success = 2;
1517 break;
1519 if (i == CheckSuccess-1) {
1520 SHOW_PROGRESS(output," No new devices in target mode or class found\n\nMode switch has failed. Bye!\n\n");
1521 } else
1522 sleep(1);
1524 } else
1525 /* No target data given, rely on the vanished device */
1526 if (!devh) {
1527 SHOW_PROGRESS(output," (For a better success check provide target IDs or class)\n");
1528 SHOW_PROGRESS(output," Original device vanished after switching\n\nMode switch most likely succeeded. Bye!\n\n");
1529 success = 1;
1532 switch (success) {
1533 case 3:
1534 if (sysmode)
1535 syslog(LOG_NOTICE, "switched to new device, but hit libusb1 bug");
1536 TargetProduct = -1;
1537 success = 1;
1538 break;
1539 case 2:
1540 if (sysmode)
1541 syslog(LOG_NOTICE, "switched to %04x:%04x on %03d/%03d", TargetVendor, TargetProduct, busnum, devnum);
1542 success = 1;
1543 break;
1544 case 1:
1545 if (sysmode)
1546 syslog(LOG_NOTICE, "device seems to have switched");
1547 default:
1550 if (sysmode)
1551 closelog();
1553 return success;
1558 int write_bulk(int endpoint, char *message, int length)
1560 ret = usb_bulk_io(devh, endpoint, message, length, 3000);
1561 if (ret >= 0 ) {
1562 SHOW_PROGRESS(output," OK, message successfully sent\n");
1563 } else
1564 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1565 SHOW_PROGRESS(output," Device seems to have vanished right after sending. Good.\n");
1566 } else
1567 SHOW_PROGRESS(output," Sending the message returned error %d. Try to continue\n", ret);
1568 return ret;
1572 int read_bulk(int endpoint, char *buffer, int length)
1574 ret = usb_bulk_io(devh, endpoint, buffer, length, 3000);
1575 usb_bulk_io(devh, endpoint, buffer, 13, 100);
1576 if (ret >= 0 ) {
1577 SHOW_PROGRESS(output," Response successfully read (%d bytes).\n", ret);
1578 } else
1579 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1580 SHOW_PROGRESS(output," Device seems to have vanished after reading. Good.\n");
1581 } else
1582 SHOW_PROGRESS(output," Response reading failed (error %d)\n", ret);
1583 return ret;
1587 void release_usb_device(int __attribute__((unused)) dummy) {
1588 SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n");
1589 if (devh) {
1590 libusb_release_interface(devh, Interface);
1591 libusb_close(devh);
1593 if (sysmode)
1594 closelog();
1595 exit(0);
1600 /* Iterates over busses and devices, counts the ones which match the given
1601 * parameters and returns the last one of them
1603 struct libusb_device* search_devices( int *numFound, int vendor, char* productList, int targetClass, int configuration, int mode)
1605 char *listcopy=NULL, *token, buffer[2];
1606 int devClass, product;
1607 struct libusb_device* right_dev = NULL;
1608 struct libusb_device_handle *testdevh;
1609 struct libusb_device **devs;
1610 int i=0;
1612 /* only target class given, target vendor and product assumed unchanged */
1613 if ( targetClass && !(vendor || strlen(productList)) ) {
1614 vendor = DefaultVendor;
1615 productList = DefaultProductList;
1617 *numFound = 0;
1619 /* Sanity check */
1620 if (!vendor || productList == '\0')
1621 return NULL;
1623 listcopy = malloc(strlen(productList)+1);
1625 if (libusb_get_device_list(ctx, &devs) < 0) {
1626 perror("Libusb failed to get USB access!");
1627 return 0;
1630 while ((dev = devs[i++]) != NULL) {
1631 struct libusb_device_descriptor descriptor;
1632 libusb_get_device_descriptor(dev, &descriptor);
1634 if (mode == SEARCH_BUSDEV) {
1635 if ((libusb_get_bus_number(dev) != busnum) ||
1636 (libusb_get_device_address(dev) != devnum))
1637 continue;
1638 else
1639 SHOW_PROGRESS(output," bus/device number matched\n");
1642 if (verbose)
1643 fprintf (output," found USB ID %04x:%04x\n",
1644 descriptor.idVendor, descriptor.idProduct);
1645 if (descriptor.idVendor != vendor)
1646 continue;
1647 if (verbose)
1648 fprintf (output," vendor ID matched\n");
1650 strcpy(listcopy, productList);
1651 token = strtok(listcopy, ",");
1652 while (token != NULL) {
1653 if (strlen(token) != 4) {
1654 SHOW_PROGRESS(output,"Error: entry in product ID list has wrong length: %s. Ignored\n", token);
1655 goto NextToken;
1657 if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) {
1658 SHOW_PROGRESS(output,"Error: entry in product ID list is not a hex string: %s. Ignored\n", token);
1659 goto NextToken;
1661 product = 0;
1662 product += (unsigned char)buffer[0];
1663 product <<= 8;
1664 product += (unsigned char)buffer[1];
1665 if (product == descriptor.idProduct) {
1666 SHOW_PROGRESS(output," product ID matched\n");
1668 if (targetClass != 0) {
1669 // TargetClass is set, check class of first interface
1670 struct libusb_device_descriptor descriptor;
1671 libusb_get_device_descriptor(dev, &descriptor);
1672 devClass = descriptor.bDeviceClass;
1673 struct libusb_config_descriptor *config;
1674 libusb_get_config_descriptor(dev, 0, &config);
1675 int ifaceClass = config->interface[0].altsetting[0].bInterfaceClass;
1676 libusb_free_config_descriptor(config);
1677 if (devClass == 0)
1678 devClass = ifaceClass;
1679 else
1680 /* Check for some quirky devices */
1681 if (devClass != ifaceClass)
1682 devClass = ifaceClass;
1683 if (devClass == targetClass) {
1684 if (verbose)
1685 fprintf (output," target class %02x matches\n", targetClass);
1686 if (mode == SEARCH_TARGET) {
1687 (*numFound)++;
1688 right_dev = dev;
1689 if (verbose)
1690 fprintf (output," count device\n");
1691 } else
1692 if (verbose)
1693 fprintf (output," device not counted, target class reached\n");
1694 } else {
1695 if (verbose)
1696 fprintf (output," device class %02x not matching target\n", devClass);
1697 if (mode == SEARCH_DEFAULT || mode == SEARCH_BUSDEV) {
1698 (*numFound)++;
1699 right_dev = dev;
1700 if (verbose)
1701 fprintf (output," count device\n");
1704 } else if (configuration > 0) {
1705 // Configuration is set, check device configuration
1706 libusb_open(dev, &testdevh);
1707 int testconfig = get_current_configuration(testdevh);
1708 if (testconfig != configuration) {
1709 if (verbose)
1710 fprintf (output," device configuration %d not matching target\n", testconfig);
1711 (*numFound)++;
1712 right_dev = dev;
1713 if (verbose)
1714 fprintf (output," count device\n");
1715 } else
1716 if (verbose)
1717 fprintf (output," device not counted, target configuration reached\n");
1718 } else {
1719 // Neither TargetClass nor Configuration are set
1720 (*numFound)++;
1721 right_dev = dev;
1722 if (mode == SEARCH_BUSDEV)
1723 break;
1727 NextToken:
1728 token = strtok(NULL, ",");
1731 if (listcopy != NULL)
1732 free(listcopy);
1733 return right_dev;
1737 #define USB_DIR_OUT 0x00
1738 #define USB_DIR_IN 0x80
1740 /* Autodetect bulk endpoints (ab) */
1742 int find_first_bulk_output_endpoint(struct libusb_device *dev)
1744 int i;
1745 struct libusb_config_descriptor *config;
1746 libusb_get_config_descriptor(dev, 0, &config);
1747 const struct libusb_interface_descriptor *alt = &(config[0].interface[0].altsetting[0]);
1748 const struct libusb_endpoint_descriptor *ep;
1750 for(i=0;i < alt->bNumEndpoints;i++) {
1751 ep=&(alt->endpoint[i]);
1752 if( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK) &&
1753 ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == USB_DIR_OUT ) ) {
1754 return ep->bEndpointAddress;
1757 libusb_free_config_descriptor(config);
1758 return 0;
1762 int find_first_bulk_input_endpoint(struct libusb_device *dev)
1764 int i;
1765 struct libusb_config_descriptor *config;
1766 libusb_get_config_descriptor(dev, 0, &config);
1767 const struct libusb_interface_descriptor *alt = &(config[0].interface[0].altsetting[0]);
1768 const struct libusb_endpoint_descriptor *ep;
1769 for(i=0;i < alt->bNumEndpoints;i++) {
1770 ep=&(alt->endpoint[i]);
1771 if( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK) &&
1772 ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == USB_DIR_IN ) ) {
1773 return ep->bEndpointAddress;
1776 libusb_free_config_descriptor(config);
1777 return 0;
1780 int get_current_configuration(struct libusb_device_handle* devh)
1782 SHOW_PROGRESS(output,"Get the current device configuration ...\n");
1783 ret = libusb_control_transfer(devh, USB_DIR_IN + LIBUSB_REQUEST_TYPE_STANDARD + LIBUSB_RECIPIENT_DEVICE, LIBUSB_REQUEST_GET_CONFIGURATION, 0, 0, (unsigned char *)buffer, 1, 1000);
1784 if (ret < 0) {
1785 // There are quirky devices which fail to respond properly to this command
1786 fprintf(stderr, "Error getting the current configuration (error %d). Assume configuration 1\n", ret);
1787 if (Configuration) {
1788 fprintf(stderr, " No configuration setting possible for this device.\n");
1789 Configuration = 0;
1791 return 1;
1792 } else {
1793 SHOW_PROGRESS(output," OK, got current device configuration (%d)\n", buffer[0]);
1794 return buffer[0];
1798 int get_interface_class(struct libusb_config_descriptor *cfg, int ifcNumber)
1800 int i;
1801 for (i=0; i<cfg->bNumInterfaces; i++) {
1802 // SHOW_PROGRESS(output,"Test: looking at ifc %d, class is %d\n",i,cfg->interface[i].altsetting[0].bInterfaceClass);
1803 if (cfg->interface[i].altsetting[0].bInterfaceNumber == ifcNumber)
1804 return cfg->interface[i].altsetting[0].bInterfaceClass;
1806 return -1;
1809 /* Parameter parsing */
1811 char* ReadParseParam(const char* FileName, char *VariableName)
1813 static int numLines = 0;
1814 static char* ConfigBuffer[MAXLINES];
1815 char *VarName, *Comment=NULL, *Equal=NULL;
1816 char *FirstQuote, *LastQuote, *P1, *P2;
1817 int Line=0;
1818 unsigned Len=0, Pos=0;
1819 char Str[LINE_DIM], *token, *configPos;
1820 FILE *file = NULL;
1822 // Reading and storing input during the first call
1823 if (numLines==0) {
1824 if (strncmp(FileName,"##",2) == 0) {
1825 if (verbose) fprintf(output,"\nRead long config from command line\n");
1826 // "Embedded" configuration data
1827 configPos = (char*)FileName;
1828 token = strtok(configPos, "\n");
1829 strncpy(Str,token,LINE_DIM-1);
1830 } else {
1831 if (strcmp(FileName, "stdin")==0) {
1832 if (verbose) fprintf(output,"\nRead long config from stdin\n");
1833 file = stdin;
1834 } else {
1835 if (verbose) fprintf(output,"\nRead config file: %s\n", FileName);
1836 file=fopen(FileName, "r");
1838 if (file==NULL) {
1839 fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName);
1840 exit(1);
1841 } else {
1842 token = fgets(Str, LINE_DIM-1, file);
1845 while (token != NULL && numLines < MAXLINES) {
1846 // Line++;
1847 Len=strlen(Str);
1848 if (Len==0)
1849 goto NextLine;
1850 if (Str[Len-1]=='\n' or Str[Len-1]=='\r')
1851 Str[--Len]='\0';
1852 Equal = strchr (Str, '='); // search for equal sign
1853 Pos = strcspn (Str, ";#!"); // search for comment
1854 Comment = (Pos==Len) ? NULL : Str+Pos;
1855 if (Equal==NULL or ( Comment!=NULL and Comment<=Equal))
1856 goto NextLine; // Comment or irrelevant, don't save
1857 Len=strlen(Str)+1;
1858 ConfigBuffer[numLines] = malloc(Len*sizeof(char));
1859 strcpy(ConfigBuffer[numLines],Str);
1860 numLines++;
1861 NextLine:
1862 if (file == NULL) {
1863 token = strtok(NULL, "\n");
1864 if (token != NULL)
1865 strncpy(Str,token,LINE_DIM-1);
1866 } else
1867 token = fgets(Str, LINE_DIM-1, file);
1869 if (file != NULL)
1870 fclose(file);
1873 // Now checking for parameters
1874 Line=0;
1875 while (Line < numLines) {
1876 strcpy(Str,ConfigBuffer[Line]);
1877 Equal = strchr (Str, '='); // search for equal sign
1878 *Equal++ = '\0';
1880 // String
1881 FirstQuote=strchr (Equal, '"'); // search for double quote char
1882 LastQuote=strrchr (Equal, '"');
1883 if (FirstQuote!=NULL) {
1884 if (LastQuote==NULL) {
1885 fprintf(stderr, "Error reading parameters from file %s - Missing end quote:\n%s\n", FileName, Str);
1886 goto Next;
1888 *FirstQuote=*LastQuote='\0';
1889 Equal=FirstQuote+1;
1892 // removes leading/trailing spaces
1893 Pos=strspn (Str, " \t");
1894 if (Pos==strlen(Str)) {
1895 fprintf(stderr, "Error reading parameters from file %s - Missing variable name:\n%s\n", FileName, Str);
1896 goto Next;
1898 while ((P1=strrchr(Str, ' '))!=NULL or (P2=strrchr(Str, '\t'))!=NULL)
1899 if (P1!=NULL) *P1='\0';
1900 else if (P2!=NULL) *P2='\0';
1901 VarName=Str+Pos;
1903 Pos=strspn (Equal, " \t");
1904 if (Pos==strlen(Equal)) {
1905 fprintf(stderr, "Error reading parameter from file %s - Missing value:\n%s\n", FileName, Str);
1906 goto Next;
1908 Equal+=Pos;
1910 if (strcmp(VarName, VariableName)==0) { // Found it
1911 return Equal;
1913 Next:
1914 Line++;
1917 return NULL;
1921 int hex2num(char c)
1923 if (c >= '0' && c <= '9')
1924 return c - '0';
1925 if (c >= 'a' && c <= 'f')
1926 return c - 'a' + 10;
1927 if (c >= 'A' && c <= 'F')
1928 return c - 'A' + 10;
1929 return -1;
1933 int hex2byte(const char *hex)
1935 int a, b;
1936 a = hex2num(*hex++);
1937 if (a < 0)
1938 return -1;
1939 b = hex2num(*hex++);
1940 if (b < 0)
1941 return -1;
1942 return (a << 4) | b;
1945 int hexstr2bin(const char *hex, char *buffer, int len)
1947 int i;
1948 int a;
1949 const char *ipos = hex;
1950 char *opos = buffer;
1952 for (i = 0; i < len; i++) {
1953 a = hex2byte(ipos);
1954 if (a < 0)
1955 return -1;
1956 *opos++ = a;
1957 ipos += 2;
1959 return 0;
1962 void printVersion()
1964 char* version = VERSION;
1965 fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
1966 " * Version %s (C) Josua Dietze 2013\n"
1967 " * Based on libusb1/libusbx\n\n"
1968 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version);
1971 void printHelp()
1973 fprintf(output,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
1974 " -h, --help this help\n"
1975 " -e, --version print version information and exit\n"
1976 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
1977 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
1978 " -p, --default-product NUM product ID of original mode (mandatory)\n"
1979 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
1980 " -P, --target-product NUM target mode product ID (optional)\n"
1981 " -C, --target-class NUM target mode device class (optional)\n"
1982 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
1983 " -g, --device-num NUM system device number (for hard ID)\n"
1984 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
1985 " -M, --message-content <msg> message to send (hex number as string)\n"
1986 " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n"
1987 " -n, --need-response read response to the message transfer (CSW)\n"
1988 " -r, --response-endpoint NUM read response from there (optional)\n"
1989 " -d, --detach-only detach the active driver, no further action\n"
1990 " -H, --huawei-mode apply a special procedure\n"
1991 " -S, --sierra-mode apply a special procedure\n"
1992 " -O, --sony-mode apply a special procedure\n"
1993 " -G, --gct-mode apply a special procedure\n"
1994 " -N, --sequans-mode apply a special procedure\n"
1995 " -A, --mobileaction-mode apply a special procedure\n"
1996 " -T, --kobil-mode apply a special procedure\n"
1997 " -L, --cisco-mode apply a special procedure\n"
1998 " -B, --qisda-mode apply a special procedure\n"
1999 " -E, --quanta-mode apply a special procedure\n"
2000 " -R, --reset-usb reset the device after all other actions\n"
2001 " -Q, --quiet don't show progress or error messages\n"
2002 " -W, --verbose print all settings and debug output\n"
2003 " -D, --sysmode specific result and syslog message\n"
2004 " -s, --success <seconds> switching result check with timeout\n"
2005 " -I, --no-inquire do not get SCSI attributes (default on)\n\n"
2006 " -c, --config-file <filename> load long configuration from file\n\n"
2007 " -t, --stdinput read long configuration from stdin\n\n"
2008 " -f, --long-config <text> get long configuration from string\n\n"
2009 " -i, --interface NUM select initial USB interface (default 0)\n"
2010 " -u, --configuration NUM select USB configuration\n"
2011 " -a, --altsetting NUM select alternative USB interface setting\n\n");