usb_modeswitch ver. 2.4.0 with data package 2016-06-12
[tomato.git] / release / src / router / usbmodeswitch / usb_modeswitch.c
blob64998449089cbdae279df90b7144af01412034b7
1 /*
2 Mode switching tool for controlling mode of 'multi-state' USB devices
3 Version 2.4.0, 2016/06/12
5 Copyright (C) 2007 - 2016 Josua Dietze (mail to "usb_admin" at the domain
6 of the home page; or write a personal message through the forum to "Josh".
7 NO SUPPORT VIA E-MAIL - please use the forum for that)
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 code borrowed from:
22 Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
24 Hexstr2bin function borrowed from:
25 Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
27 Other contributions: see README
29 Device information contributors are named in the "device_reference.txt" file. See
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.4.0"
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 // Little helpers
64 int usb_bulk_io(struct libusb_device_handle *handle, int ep, unsigned 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, 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;
82 static int usb_interrupt_io(libusb_device_handle *handle, int ep, unsigned char *bytes,
83 int size, int timeout)
85 int actual_length;
86 int r;
87 // usbi_dbg("endpoint %x size %d timeout %d", ep, size, timeout);
88 r = libusb_interrupt_transfer(handle, ep & 0xff, bytes, size,
89 &actual_length, timeout);
91 /* if we timed out but did transfer some data, report as successful short
92 * read. FIXME: is this how libusb-0.1 works? */
93 if (r == 0 || (r == LIBUSB_ERROR_TIMEOUT && actual_length > 0))
94 return actual_length;
96 return (r);
100 #define LINE_DIM 1024
101 #define MSG_DIM 11
102 #define MAXLINES 50
103 #define BUF_SIZE 4096
104 #define DESCR_MAX 129
106 #define SEARCH_DEFAULT 0
107 #define SEARCH_TARGET 1
108 #define SEARCH_BUSDEV 2
110 #define SWITCH_CONFIG_MAXTRIES 5
112 #define SHOW_PROGRESS if (show_progress) fprintf
114 char *TempPP=NULL;
116 static struct libusb_context *ctx = NULL;
117 static struct libusb_device *dev = NULL;
118 static struct libusb_device_handle *devh = NULL;
119 static struct libusb_config_descriptor *active_config = NULL;
121 int DefaultVendor=0, DefaultProduct=0, TargetVendor=0, TargetProduct=-1, TargetClass=0;
122 int MessageEndpoint=0, ResponseEndpoint=0, ReleaseDelay=0;
123 int targetDeviceCount=0, searchMode;
124 int devnum=-1, busnum=-1;
126 unsigned int ModeMap = 0;
127 #define DETACHONLY_MODE 0x00000001
128 #define HUAWEI_MODE 0x00000002
129 #define SIERRA_MODE 0x00000004
130 #define SONY_MODE 0x00000008
131 #define GCT_MODE 0x00000010
132 #define KOBIL_MODE 0x00000020
133 #define SEQUANS_MODE 0x00000040
134 #define MOBILEACTION_MODE 0x00000080
135 #define CISCO_MODE 0x00000100
136 #define QISDA_MODE 0x00000200
137 #define QUANTA_MODE 0x00000400
138 #define BLACKBERRY_MODE 0x00000800
139 #define PANTECH_MODE 0x00001000
140 #define HUAWEINEW_MODE 0x00002000
141 #define OPTION_MODE 0x00004000
144 int PantechMode=0;
145 char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0;
146 char NoDriverLoading=0, sysmode=0, mbim=0;
147 char StandardEject=0;
149 char MessageContent[LINE_DIM];
150 char MessageContent2[LINE_DIM];
151 char MessageContent3[LINE_DIM];
152 char TargetProductList[LINE_DIM];
153 char DefaultProductList[5];
154 unsigned char ByteString[LINE_DIM/2];
155 unsigned char buffer[BUF_SIZE];
156 char **Messages = NULL;
158 FILE *output;
161 /* Settable Interface and Configuration (for debugging mostly) (jmw) */
162 int Interface = -1, Configuration = 0, AltSetting = -1;
165 static struct option long_options[] = {
166 {"help", no_argument, 0, 'h'},
167 {"version", no_argument, 0, 'e'},
168 {"default-vendor", required_argument, 0, 'v'},
169 {"default-product", required_argument, 0, 'p'},
170 {"target-vendor", required_argument, 0, 'V'},
171 {"target-product", required_argument, 0, 'P'},
172 {"target-class", required_argument, 0, 'C'},
173 {"message-endpoint", required_argument, 0, 'm'},
174 {"message-content", required_argument, 0, 'M'},
175 {"message-content2", required_argument, 0, '2'},
176 {"message-content3", required_argument, 0, '3'},
177 {"release-delay", required_argument, 0, 'w'},
178 {"response-endpoint", required_argument, 0, 'r'},
179 {"bus-num", required_argument, 0, 'b'},
180 {"device-num", required_argument, 0, 'g'},
181 {"detach-only", no_argument, 0, 'd'},
182 {"huawei-mode", no_argument, 0, 'H'},
183 {"huawei-new-mode", no_argument, 0, 'J'},
184 {"sierra-mode", no_argument, 0, 'S'},
185 {"sony-mode", no_argument, 0, 'O'},
186 {"qisda-mode", no_argument, 0, 'B'},
187 {"quanta-mode", no_argument, 0, 'E'},
188 {"kobil-mode", no_argument, 0, 'T'},
189 {"gct-mode", no_argument, 0, 'G'},
190 {"sequans-mode", no_argument, 0, 'N'},
191 {"mobileaction-mode", no_argument, 0, 'A'},
192 {"cisco-mode", no_argument, 0, 'L'},
193 {"blackberry-mode", no_argument, 0, 'Z'},
194 {"option-mode", no_argument, 0, 'U'},
195 {"pantech-mode", required_argument, 0, 'F'},
196 {"std-eject", no_argument, 0, 'K'},
197 {"need-response", no_argument, 0, 'n'},
198 {"reset-usb", no_argument, 0, 'R'},
199 {"config-file", required_argument, 0, 'c'},
200 {"verbose", no_argument, 0, 'W'},
201 {"quiet", no_argument, 0, 'Q'},
202 {"sysmode", no_argument, 0, 'D'},
203 {"inquire", no_argument, 0, 'I'},
204 {"stdinput", no_argument, 0, 't'},
205 {"find-mbim", no_argument, 0, 'j'},
206 {"long-config", required_argument, 0, 'f'},
207 {"check-success", required_argument, 0, 's'},
208 {"interface", required_argument, 0, 'i'},
209 {"configuration", required_argument, 0, 'u'},
210 {"altsetting", required_argument, 0, 'a'},
211 {0, 0, 0, 0}
215 void readConfigFile(const char *configFilename)
217 ParseParamHex(configFilename, TargetVendor);
218 ParseParamHex(configFilename, TargetProduct);
219 ParseParamString(configFilename, TargetProductList);
220 ParseParamHex(configFilename, TargetClass);
221 ParseParamHex(configFilename, DefaultVendor);
222 ParseParamHex(configFilename, DefaultProduct);
223 ParseParamBoolMap(configFilename, DetachStorageOnly, ModeMap, DETACHONLY_MODE);
224 ParseParamBoolMap(configFilename, HuaweiMode, ModeMap, HUAWEI_MODE);
225 ParseParamBoolMap(configFilename, HuaweiNewMode, ModeMap, HUAWEINEW_MODE);
226 ParseParamBoolMap(configFilename, SierraMode, ModeMap, SIERRA_MODE);
227 ParseParamBoolMap(configFilename, SonyMode, ModeMap, SONY_MODE);
228 ParseParamBoolMap(configFilename, GCTMode, ModeMap, GCT_MODE);
229 ParseParamBoolMap(configFilename, KobilMode, ModeMap, KOBIL_MODE);
230 ParseParamBoolMap(configFilename, SequansMode, ModeMap, SEQUANS_MODE);
231 ParseParamBoolMap(configFilename, MobileActionMode, ModeMap, MOBILEACTION_MODE);
232 ParseParamBoolMap(configFilename, CiscoMode, ModeMap, CISCO_MODE);
233 ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE);
234 ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE);
235 ParseParamBoolMap(configFilename, OptionMode, ModeMap, OPTION_MODE);
236 ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE);
237 ParseParamInt(configFilename, PantechMode);
238 if (PantechMode)
239 ModeMap |= PANTECH_MODE;
240 ParseParamBool(configFilename, StandardEject);
241 ParseParamBool(configFilename, NoDriverLoading);
242 ParseParamHex(configFilename, MessageEndpoint);
243 ParseParamString(configFilename, MessageContent);
244 ParseParamString(configFilename, MessageContent2);
245 ParseParamString(configFilename, MessageContent3);
246 ParseParamInt(configFilename, ReleaseDelay);
247 ParseParamHex(configFilename, ResponseEndpoint);
248 ParseParamHex(configFilename, ResetUSB);
249 ParseParamInt(configFilename, CheckSuccess);
250 ParseParamHex(configFilename, Interface);
251 ParseParamHex(configFilename, Configuration);
252 ParseParamHex(configFilename, AltSetting);
254 /* TargetProductList has priority over TargetProduct */
255 if (TargetProduct != -1 && TargetProductList[0] != '\0') {
256 TargetProduct = -1;
257 SHOW_PROGRESS(output,"Warning: TargetProductList overrides TargetProduct!\n");
260 config_read = 1;
264 void printConfig()
266 if ( DefaultVendor )
267 fprintf (output,"DefaultVendor= 0x%04x\n", DefaultVendor);
268 if ( DefaultProduct )
269 fprintf (output,"DefaultProduct= 0x%04x\n", DefaultProduct);
270 if ( TargetVendor )
271 fprintf (output,"TargetVendor= 0x%04x\n", TargetVendor);
272 if ( TargetProduct > -1 )
273 fprintf (output,"TargetProduct= 0x%04x\n", TargetProduct);
274 if ( TargetClass )
275 fprintf (output,"TargetClass= 0x%02x\n", TargetClass);
276 if ( strlen(TargetProductList) )
277 fprintf (output,"TargetProductList=\"%s\"\n", TargetProductList);
278 if (StandardEject)
279 fprintf (output,"\nStandardEject=1\n");
280 if (ModeMap & DETACHONLY_MODE)
281 fprintf (output,"\nDetachStorageOnly=1\n");
282 if (ModeMap & HUAWEI_MODE)
283 fprintf (output,"HuaweiMode=1\n");
284 if (ModeMap & HUAWEINEW_MODE)
285 fprintf (output,"HuaweiNewMode=1\n");
286 if (ModeMap & SIERRA_MODE)
287 fprintf (output,"SierraMode=1\n");
288 if (ModeMap & SONY_MODE)
289 fprintf (output,"SonyMode=1\n");
290 if (ModeMap & QISDA_MODE)
291 fprintf (output,"QisdaMode=1\n");
292 if (ModeMap & QUANTA_MODE)
293 fprintf (output,"QuantaMode=1\n");
294 if (ModeMap & GCT_MODE)
295 fprintf (output,"GCTMode=1\n");
296 if (ModeMap & KOBIL_MODE)
297 fprintf (output,"KobilMode=1\n");
298 if (ModeMap & SEQUANS_MODE)
299 fprintf (output,"SequansMode=1\n");
300 if (ModeMap & MOBILEACTION_MODE)
301 fprintf (output,"MobileActionMode=1\n");
302 if (ModeMap & CISCO_MODE)
303 fprintf (output,"CiscoMode=1\n");
304 if (ModeMap & BLACKBERRY_MODE)
305 fprintf (output,"BlackberryMode=1\n");
306 if (ModeMap & OPTION_MODE)
307 fprintf (output,"OptionMode=1\n");
308 if (ModeMap & PANTECH_MODE)
309 fprintf (output,"PantechMode=1\n");
310 if ( MessageEndpoint )
311 fprintf (output,"MessageEndpoint=0x%02x\n", MessageEndpoint);
312 if ( strlen(MessageContent) )
313 fprintf (output,"MessageContent=\"%s\"\n", MessageContent);
314 if ( strlen(MessageContent2) )
315 fprintf (output,"MessageContent2=\"%s\"\n", MessageContent2);
316 if ( strlen(MessageContent3) )
317 fprintf (output,"MessageContent3=\"%s\"\n", MessageContent3);
318 if ( ResponseEndpoint )
319 fprintf (output,"ResponseEndpoint=0x%02x\n", ResponseEndpoint);
320 if ( Interface > -1 )
321 fprintf (output,"Interface=0x%02x\n", Interface);
322 if ( Configuration > 0 )
323 fprintf (output,"Configuration=0x%02x\n", Configuration);
324 if ( AltSetting > -1 )
325 fprintf (output,"AltSetting=0x%02x\n", AltSetting);
326 if ( CheckSuccess )
327 fprintf (output,"Success check enabled, max. wait time %d seconds\n", CheckSuccess);
328 if ( sysmode )
329 fprintf (output,"System integration mode enabled\n");
333 int readArguments(int argc, char **argv)
335 int c, option_index = 0, count=0;
336 char *longConfig = NULL;
337 if (argc==1)
339 printHelp();
340 printVersion();
341 exit(1);
344 while (1)
346 c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZUF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
347 long_options, &option_index);
349 /* Detect the end of the options. */
350 if (c == -1)
351 break;
352 count++;
353 switch (c)
355 case 'R': ResetUSB = 1; break;
356 case 'v': DefaultVendor = strtol(optarg, NULL, 16); break;
357 case 'p': DefaultProduct = strtol(optarg, NULL, 16); break;
358 case 'V': TargetVendor = strtol(optarg, NULL, 16); break;
359 case 'P': TargetProduct = strtol(optarg, NULL, 16); break;
360 case 'C': TargetClass = strtol(optarg, NULL, 16); break;
361 case 'm': MessageEndpoint = strtol(optarg, NULL, 16); break;
362 case 'M': strncpy(MessageContent, optarg, LINE_DIM); break;
363 case '2': strncpy(MessageContent2, optarg, LINE_DIM); break;
364 case '3': strncpy(MessageContent3, optarg, LINE_DIM); break;
365 case 'w': ReleaseDelay = strtol(optarg, NULL, 10); break;
366 case 'n': break;
367 case 'r': ResponseEndpoint = strtol(optarg, NULL, 16); break;
368 case 'K': StandardEject = 1; break;
369 case 'd': ModeMap = ModeMap + DETACHONLY_MODE; break;
370 case 'H': ModeMap = ModeMap + HUAWEI_MODE; break;
371 case 'J': ModeMap = ModeMap + HUAWEINEW_MODE; break;
372 case 'S': ModeMap = ModeMap + SIERRA_MODE; break;
373 case 'O': ModeMap = ModeMap + SONY_MODE; break;; break;
374 case 'B': ModeMap = ModeMap + QISDA_MODE; break;
375 case 'E': ModeMap = ModeMap + QUANTA_MODE; break;
376 case 'G': ModeMap = ModeMap + GCT_MODE; break;
377 case 'T': ModeMap = ModeMap + KOBIL_MODE; break;
378 case 'N': ModeMap = ModeMap + SEQUANS_MODE; break;
379 case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break;
380 case 'L': ModeMap = ModeMap + CISCO_MODE; break;
381 case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break;
382 case 'U': ModeMap = ModeMap + OPTION_MODE; break;
383 case 'F': ModeMap = ModeMap + PANTECH_MODE;
384 PantechMode = strtol(optarg, NULL, 10); break;
385 case 'c': readConfigFile(optarg); break;
386 case 't': readConfigFile("stdin"); break;
387 case 'W': verbose = 1; show_progress = 1; count--; break;
388 case 'Q': show_progress = 0; verbose = 0; count--; break;
389 case 'D': sysmode = 1; count--; break;
390 case 's': CheckSuccess = strtol(optarg, NULL, 10); count--; break;
391 case 'I': break;
392 case 'b': busnum = strtol(optarg, NULL, 10); break;
393 case 'g': devnum = strtol(optarg, NULL, 10); break;
395 case 'i': Interface = strtol(optarg, NULL, 16); break;
396 case 'u': Configuration = strtol(optarg, NULL, 16); break;
397 case 'a': AltSetting = strtol(optarg, NULL, 16); break;
398 case 'j': mbim = 1; break;
400 case 'f':
401 longConfig = malloc(strlen(optarg)+5);
402 strcpy(longConfig,"##\n");
403 strcat(longConfig,optarg);
404 strcat(longConfig,"\n");
405 readConfigFile(longConfig);
406 free(longConfig);
407 break;
409 case 'e':
410 printVersion();
411 exit(0);
412 break;
413 case 'h':
414 printVersion();
415 printHelp();
416 exit(0);
417 break;
419 default: /* Unsupported - error message has already been printed */
420 fprintf (output,"\n");
421 printHelp();
422 exit(1);
425 return count;
429 int main(int argc, char **argv)
431 int ret=0, numDefaults=0, sonySuccess=0, i;
432 int currentConfigVal=0, defaultClass=0, interfaceClass=0;
433 struct libusb_device_descriptor descriptor;
434 enum libusb_error libusbError;
436 /* Make sure we have empty strings even if not set by config */
437 TargetProductList[0] = '\0';
438 MessageContent[0] = '\0';
439 MessageContent2[0] = '\0';
440 MessageContent3[0] = '\0';
441 DefaultProductList[0] = '\0';
443 /* Useful for debugging during boot */
444 // output=fopen("/dev/console", "w");
445 output=stdout;
447 signal(SIGTERM, release_usb_device);
450 * Parameter parsing, USB preparation/diagnosis, plausibility checks
453 /* Check command arguments, use params instead of config file when given */
454 switch (readArguments(argc, argv)) {
455 case 0: /* no argument or -W, -q or -s */
456 break;
457 default: /* one or more arguments except -W, -q or -s */
458 if (!config_read) /* if arguments contain -c, the config file was already processed */
459 if (verbose) fprintf(output,"Take all parameters from the command line\n\n");
462 if (verbose) {
463 printVersion();
464 printConfig();
465 fprintf(output,"\n");
468 /* Some sanity checks. The default IDs are mandatory */
469 if (!(DefaultVendor && DefaultProduct)) {
470 SHOW_PROGRESS(output,"No default vendor/product ID given. Abort\n\n");
471 exit(1);
474 if (strlen(MessageContent)) {
475 if (strlen(MessageContent) % 2 != 0) {
476 fprintf(stderr, "Error: MessageContent hex string has uneven length. Abort\n\n");
477 exit(1);
479 if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) {
480 fprintf(stderr, "Error: MessageContent %s\n is not a hex string. Abort\n\n",
481 MessageContent);
483 exit(1);
487 if (devnum == -1) {
488 searchMode = SEARCH_DEFAULT;
489 } else {
490 SHOW_PROGRESS(output,"Use given bus/device number: %03d/%03d ...\n", busnum, devnum);
491 searchMode = SEARCH_BUSDEV;
494 if (show_progress)
495 if (CheckSuccess && !(TargetVendor || TargetProduct > -1 || TargetProductList[0] != '\0')
496 && !TargetClass)
498 fprintf(output,"Note: No target parameter given; success check limited\n");
500 if (TargetProduct > -1 && TargetProductList[0] == '\0') {
501 sprintf(TargetProductList,"%04x",TargetProduct);
502 TargetProduct = -1;
505 /* libusb initialization */
506 if ((libusbError = libusb_init(&ctx)) != LIBUSB_SUCCESS) {
507 fprintf(stderr, "Error: Failed to initialize libusb. %s (%d)\n\n");
508 exit(1);
511 if (verbose)
512 libusb_set_debug(ctx, 3);
514 if (mbim) {
515 printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) );
516 exit(0);
519 /* Count existing target devices, remember for success check */
520 if (searchMode != SEARCH_BUSDEV && (TargetVendor || TargetClass)) {
521 SHOW_PROGRESS(output,"Look for target devices ...\n");
522 search_devices(&targetDeviceCount, TargetVendor, TargetProductList, TargetClass, 0,
523 SEARCH_TARGET);
525 if (targetDeviceCount) {
526 SHOW_PROGRESS(output," Found devices in target mode or class (%d)\n", targetDeviceCount);
527 } else
528 SHOW_PROGRESS(output," No devices in target mode or class found\n");
531 /* Count default devices, get the last one found */
532 SHOW_PROGRESS(output,"Look for default devices ...\n");
534 sprintf(DefaultProductList,"%04x",DefaultProduct);
535 dev = search_devices(&numDefaults, DefaultVendor, DefaultProductList, TargetClass,
536 Configuration, searchMode);
538 if (numDefaults) {
539 SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults);
540 } else {
541 SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n");
542 close_all();
543 exit(0);
546 if (dev == NULL) {
547 SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n");
548 close_all();
549 exit(0);
550 } else {
551 if (devnum == -1) {
552 devnum = libusb_get_device_address(dev);
553 busnum = libusb_get_bus_number(dev);
554 SHOW_PROGRESS(output,"Access device %03d on bus %03d\n", devnum, busnum);
556 libusb_open(dev, &devh);
557 if (devh == NULL) {
558 SHOW_PROGRESS(output,"Error opening the device. Abort\n\n");
559 abortExit();
563 /* Get current configuration of default device, note value if Configuration
564 * parameter is set. Also sets active_config
566 currentConfigVal = get_current_config_value(dev);
567 if (Configuration > -1) {
568 SHOW_PROGRESS(output,"Current configuration number is %d\n", currentConfigVal);
569 } else
570 currentConfigVal = 0;
572 libusb_get_device_descriptor(dev, &descriptor);
573 defaultClass = descriptor.bDeviceClass;
574 if (Interface == -1)
575 Interface = active_config->interface[0].altsetting[0].bInterfaceNumber;
576 SHOW_PROGRESS(output,"Use interface number %d\n", Interface);
578 /* Get class of default device/interface */
579 interfaceClass = get_interface_class();
581 /* Check or get endpoints and alloc message list if needed*/
582 if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE
583 || ModeMap & HUAWEINEW_MODE || ModeMap & OPTION_MODE) {
585 Messages = (char**) calloc(MSG_DIM, sizeof(char*));
586 for (i = 0; i < MSG_DIM; i++) {
587 Messages[i] = (char*) calloc(LINE_DIM, sizeof(char));
588 Messages[i][0] = '\0';
591 if (!MessageEndpoint)
592 MessageEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT);
593 if (!ResponseEndpoint)
594 ResponseEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN);
595 if (!MessageEndpoint) {
596 fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n");
597 abortExit();
599 if (!ResponseEndpoint) {
600 fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n");
601 abortExit();
603 SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint,
604 ResponseEndpoint);
608 if (interfaceClass == -1) {
609 fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
610 abortExit();
613 if (defaultClass == 0 || defaultClass == 0xef)
614 defaultClass = interfaceClass;
615 else
616 if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE
617 && defaultClass != LIBUSB_CLASS_VENDOR_SPEC) {
619 /* Unexpected default class combined with differing interface class */
620 SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
621 defaultClass = 8;
624 if (strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0)
625 if (defaultClass != 8) {
626 fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d;\n"
627 " interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
628 abortExit();
631 if (show_progress) {
632 fprintf(output,"\nUSB description data (for identification)\n");
633 deviceDescription();
636 /* Special modes are exclusive, so check for illegal combinations.
637 * More than one bit set?
639 if ( ModeMap & (ModeMap-1) ) {
640 fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n");
641 abortExit();
644 if ((strlen(MessageContent) || StandardEject) && ModeMap ) {
645 MessageContent[0] = '\0';
646 StandardEject = 0;
647 fprintf(output,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n");
650 if (StandardEject && (strlen(MessageContent2) || strlen(MessageContent3))) {
651 fprintf(output,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n");
654 if ( !ModeMap && !strlen(MessageContent) && AltSetting == -1 && !Configuration && !StandardEject )
655 SHOW_PROGRESS(output,"Warning: no switching method given. See documentation\n");
658 * The switching actions
661 if (sysmode) {
662 openlog("usb_modeswitch", 0, LOG_SYSLOG);
663 syslog(LOG_NOTICE, "switch device %04x:%04x on %03d/%03d", DefaultVendor, DefaultProduct,
664 busnum, devnum);
668 if (ModeMap & DETACHONLY_MODE) {
669 SHOW_PROGRESS(output,"Detach storage driver as switching method ...\n");
670 ret = detachDriver();
671 if (ret == 2)
672 SHOW_PROGRESS(output," You may want to remove the storage driver manually\n");
675 if(ModeMap & HUAWEI_MODE) {
676 switchHuaweiMode();
678 if(ModeMap & SIERRA_MODE) {
679 switchSierraMode();
681 if(ModeMap & GCT_MODE) {
682 detachDriver();
683 switchGCTMode();
685 if(ModeMap & QISDA_MODE) {
686 switchQisdaMode();
688 if(ModeMap & KOBIL_MODE) {
689 detachDriver();
690 switchKobilMode();
692 if(ModeMap & QUANTA_MODE) {
693 switchQuantaMode();
695 if(ModeMap & SEQUANS_MODE) {
696 switchSequansMode();
698 if(ModeMap & MOBILEACTION_MODE) {
699 switchActionMode();
701 if(ModeMap & CISCO_MODE) {
702 detachDriver();
703 switchCiscoMode();
705 if(ModeMap & BLACKBERRY_MODE) {
706 detachDriver();
707 switchBlackberryMode();
709 if(ModeMap & PANTECH_MODE) {
710 detachDriver();
711 if (PantechMode > 1)
712 switchPantechMode();
713 else
714 SHOW_PROGRESS(output,"Waiting for auto-switch of Pantech modem ...\n");
716 if(ModeMap & SONY_MODE) {
717 if (CheckSuccess)
718 SHOW_PROGRESS(output,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
719 CheckSuccess = 0; /* separate and implied success control */
720 sonySuccess = switchSonyMode();
723 if (StandardEject) {
724 SHOW_PROGRESS(output,"Sending standard EJECT sequence\n");
725 detachDriver();
727 strcpy(Messages[0],"5553424387654321000000000000061e000000000000000000000000000000");
728 strcpy(Messages[1],"5553424397654321000000000000061b000000020000000000000000000000");
729 strcpy(Messages[2],"5553424387654321000000000001061e000000000000000000000000000000");
730 strcpy(Messages[3],"5553424397654321000000000001061b000000020000000000000000000000");
731 if (MessageContent[0] != '\0')
732 strcpy(Messages[4], MessageContent);
734 switchSendMessage();
735 } else if (ModeMap & HUAWEINEW_MODE) {
736 SHOW_PROGRESS(output,"Using standard Huawei switching message\n");
737 detachDriver();
738 strcpy(Messages[0],"55534243123456780000000000000011062000000101000100000000000000");
739 switchSendMessage();
740 } else if (ModeMap & OPTION_MODE) {
741 SHOW_PROGRESS(output,"Using standard Option switching message\n");
742 detachDriver();
743 // strcpy(MessageContent,"55534243123456780100000080000601000000000000000000000000000000");
744 strcpy(Messages[0],"55534243123456780000000000000601000000000000000000000000000000");
745 switchSendMessage();
746 } else if (strlen(MessageContent)) {
747 detachDriver();
748 strcpy(Messages[0],MessageContent);
749 switchSendMessage();
752 if (Configuration > 0) {
753 if (currentConfigVal != Configuration) {
754 if (switchConfiguration()) {
755 currentConfigVal = get_current_config_value(dev);
756 if (currentConfigVal == Configuration) {
757 SHOW_PROGRESS(output,"The configuration was set successfully\n");
758 } else {
759 SHOW_PROGRESS(output,"Changing the configuration has failed\n");
762 } else {
763 SHOW_PROGRESS(output,"Target configuration %d found. Do nothing\n", currentConfigVal);
767 if (AltSetting != -1) {
768 switchAltSetting();
771 /* No "removal" check if these are set */
772 if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) {
773 libusb_close(devh);
774 devh = NULL;
777 if (ResetUSB) {
778 resetUSB();
779 devh = NULL;
782 if (searchMode == SEARCH_BUSDEV && sysmode) {
783 printf("ok:busdev\n");
784 close_all();
785 exit(0);
788 if (CheckSuccess) {
789 if (checkSuccess()) {
790 if (sysmode) {
791 if (NoDriverLoading)
792 printf("ok:\n");
793 else
794 if (TargetProduct < 1)
795 printf("ok:no_data\n");
796 else
797 printf("ok:%04x:%04x\n", TargetVendor, TargetProduct);
799 } else
800 if (sysmode)
801 printf("fail:\n");
802 } else {
803 if (ModeMap & SONY_MODE)
804 if (sonySuccess) {
805 if (sysmode) {
806 syslog(LOG_NOTICE, "switched S.E. MD400 to modem mode");
807 printf("ok:\n"); /* ACM device, no driver action */
809 SHOW_PROGRESS(output,"-> device should be stable now. Bye!\n\n");
810 } else {
811 if (sysmode)
812 printf("fail:\n");
813 SHOW_PROGRESS(output,"-> switching was probably not completed. Bye!\n\n");
815 else
816 SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n");
818 close_all();
819 exit(0);
823 /* Get descriptor strings if available (identification details) */
824 void deviceDescription ()
826 char imanufact[DESCR_MAX], iproduct[DESCR_MAX], iserial[DESCR_MAX];
827 int ret=0;
828 char* c;
829 memset (imanufact, ' ', DESCR_MAX);
830 memset (iproduct, ' ', DESCR_MAX);
831 memset (iserial, ' ', DESCR_MAX);
833 struct libusb_device_descriptor descriptor;
834 libusb_get_device_descriptor(dev, &descriptor);
836 int iManufacturer = descriptor.iManufacturer;
837 int iProduct = descriptor.iProduct;
838 int iSerialNumber = descriptor.iSerialNumber;
840 if (iManufacturer) {
841 ret = libusb_get_string_descriptor_ascii(devh, iManufacturer, (unsigned char *)imanufact, DESCR_MAX);
842 if (ret < 0) {
843 fprintf(stderr, "Error: could not get description string \"manufacturer\"\n");
844 strcpy(imanufact, "read error");
846 } else
847 strcpy(imanufact, "not provided");
848 c = strstr(imanufact, " ");
849 if (c)
850 memset((void*)c, '\0', 1);
852 if (iProduct) {
853 ret = libusb_get_string_descriptor_ascii(devh, iProduct, (unsigned char *)iproduct, DESCR_MAX);
854 if (ret < 0) {
855 fprintf(stderr, "Error: could not get description string \"product\"\n");
856 strcpy(iproduct, "read error");
858 } else
859 strcpy(iproduct, "not provided");
860 c = strstr(iproduct, " ");
861 if (c)
862 memset((void*)c, '\0', 1);
864 if (iSerialNumber) {
865 ret = libusb_get_string_descriptor_ascii(devh, iSerialNumber, (unsigned char *)iserial, DESCR_MAX);
866 if (ret < 0) {
867 fprintf(stderr, "Error: could not get description string \"serial number\"\n");
868 strcpy(iserial, "read error");
870 } else
871 strcpy(iserial, "not provided");
872 c = strstr(iserial, " ");
873 if (c)
874 memset((void*)c, '\0', 1);
875 fprintf(output,"-------------------------\n");
876 fprintf(output,"Manufacturer: %s\n", imanufact);
877 fprintf(output," Product: %s\n", iproduct);
878 fprintf(output," Serial No.: %s\n", iserial);
879 fprintf(output,"-------------------------\n");
883 /* Auxiliary function used by the wrapper */
884 int findMBIMConfig(int vendor, int product, int mode)
886 struct libusb_device **devs;
887 int resultConfig=0;
888 int i=0, j;
890 if (libusb_get_device_list(ctx, &devs) < 0) {
891 perror("Libusb could not access USB. Abort");
892 return 0;
895 SHOW_PROGRESS(output,"Search USB devices ...\n");
896 while ((dev = devs[i++]) != NULL) {
897 struct libusb_device_descriptor descriptor;
898 libusb_get_device_descriptor(dev, &descriptor);
900 if (mode == SEARCH_BUSDEV) {
901 if ((libusb_get_bus_number(dev) != busnum) ||
902 (libusb_get_device_address(dev) != devnum)) {
903 continue;
904 } else {
905 if (descriptor.idVendor != vendor)
906 continue;
907 if (product != descriptor.idProduct)
908 continue;
911 SHOW_PROGRESS(output,"Found device, search for MBIM configuration...\n");
913 // No check if there is only one configuration
914 if (descriptor.bNumConfigurations < 2)
915 return -1;
917 // Checking all interfaces of all configurations
918 for (j=0; j<descriptor.bNumConfigurations; j++) {
919 struct libusb_config_descriptor *config;
921 libusb_get_config_descriptor(dev, j, &config);
922 resultConfig = config->bConfigurationValue;
923 for (i=0; i<config->bNumInterfaces; i++) {
924 if ( config->interface[i].altsetting[0].bInterfaceClass == 2 )
925 if ( config->interface[i].altsetting[0].bInterfaceSubClass == 0x0e ) {
926 // found MBIM interface in this configuration
927 libusb_free_config_descriptor(config);
928 return resultConfig;
931 libusb_free_config_descriptor(config);
933 return -1;
935 return 0;
939 void resetUSB ()
941 int success;
942 int bpoint = 0;
944 if (!devh) {
945 fprintf(output,"Device handle empty, skip USB reset\n");
946 return;
948 if (show_progress) {
949 fprintf(output,"Reset USB device ");
950 fflush(output);
952 sleep( 1 );
953 do {
954 success = libusb_reset_device(devh);
955 if ( ((bpoint % 10) == 0) && show_progress ) {
956 fprintf(output,".");
957 fflush(output);
959 bpoint++;
960 if (bpoint > 100)
961 success = 1;
962 } while (success < 0);
964 if ( success ) {
965 SHOW_PROGRESS(output,"\n Device reset failed.\n");
966 } else
967 SHOW_PROGRESS(output,"\n Device was reset\n");
971 int switchSendMessage ()
973 const char* cmdHead = "55534243";
974 int ret, i;
975 /* char* msg[3];
976 msg[0] = MessageContent;
977 msg[1] = MessageContent2;
978 msg[2] = MessageContent3;
980 SHOW_PROGRESS(output,"Set up interface %d\n", Interface);
981 ret = libusb_claim_interface(devh, Interface);
982 if (ret != 0) {
983 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret);
984 return 0;
986 libusb_clear_halt(devh, MessageEndpoint);
987 SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint);
988 if (show_progress)
989 fflush(stdout);
991 for (i=0; i<MSG_DIM; i++) {
992 if ( strlen(Messages[i]) == 0)
993 break;
995 if ( sendMessage(Messages[i], i+1) )
996 goto skip;
998 if ( strstr(Messages[i],cmdHead) != NULL ) {
999 // UFI command
1000 SHOW_PROGRESS(output,"Read the response to message %d (CSW) ...\n", i+1);
1001 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1002 if (ret >= 0)
1003 SHOW_PROGRESS(output,", status %d",ByteString[12]);
1004 } else {
1005 // Other bulk transfer
1006 SHOW_PROGRESS(output,"Read the response to message %d ...\n", i+1);
1007 ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 );
1009 SHOW_PROGRESS(output,"\n");
1010 if (ret < 0)
1011 goto skip;
1014 SHOW_PROGRESS(output,"Reset response endpoint 0x%02x\n", ResponseEndpoint);
1015 ret = libusb_clear_halt(devh, ResponseEndpoint);
1016 if (ret)
1017 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1018 SHOW_PROGRESS(output,"Reset message endpoint 0x%02x\n", MessageEndpoint);
1019 ret = libusb_clear_halt(devh, MessageEndpoint);
1020 if (ret)
1021 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1022 usleep(50000);
1024 if (ReleaseDelay) {
1025 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1026 usleep(ReleaseDelay*1000);
1028 ret = libusb_release_interface(devh, Interface);
1029 if (ret)
1030 goto skip;
1031 return 1;
1033 skip:
1034 SHOW_PROGRESS(output," Device is gone, skip any further commands\n");
1035 libusb_close(devh);
1036 devh = NULL;
1037 return 2;
1041 int switchConfiguration ()
1043 int ret, count = SWITCH_CONFIG_MAXTRIES;
1045 SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration);
1046 while (((ret = libusb_set_configuration(devh, Configuration)) < 0) && --count) {
1047 SHOW_PROGRESS(output," Device is busy, try to detach kernel driver\n");
1048 detachDriver();
1050 if (ret < 0 ) {
1051 SHOW_PROGRESS(output," Changing the configuration failed (error %d). Try to continue\n", ret);
1052 return 0;
1053 } else {
1054 SHOW_PROGRESS(output," OK, configuration set\n");
1055 return 1;
1060 int switchAltSetting ()
1062 int ret;
1063 SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting);
1064 ret = libusb_claim_interface(devh, Interface);
1065 if (ret < 0) {
1066 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip AltSetting\n", ret);
1067 return 0;
1069 ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting);
1070 libusb_release_interface(devh, Interface);
1071 if (ret < 0) {
1072 SHOW_PROGRESS(output," Change to alt setting returned error %d. Try to continue\n", ret);
1073 return 0;
1074 } else
1075 return 1;
1079 void switchHuaweiMode ()
1081 int ret;
1082 SHOW_PROGRESS(output,"Send old Huawei control message ...\n");
1083 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1084 LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, buffer, 0, 1000);
1086 if (ret != 0) {
1087 fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret);
1088 exit(0);
1093 void switchSierraMode ()
1095 int ret;
1096 SHOW_PROGRESS(output,"Send Sierra control message\n");
1097 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1098 LIBUSB_REQUEST_SET_INTERFACE, 00000001, 0, buffer, 0, 1000);
1099 if (ret == LIBUSB_ERROR_PIPE) {
1100 SHOW_PROGRESS(output," communication with device stopped. May have switched modes anyway\n");
1101 return;
1103 if (ret < 0) {
1104 fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret);
1105 exit(0);
1110 void switchGCTMode ()
1112 int ret;
1113 ret = libusb_claim_interface(devh, Interface);
1114 if (ret != 0) {
1115 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret);
1116 return;
1118 SHOW_PROGRESS(output,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d",
1119 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN);
1121 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
1122 0xa0, 0, Interface, buffer, 1, 1000);
1124 if (ret < 0) {
1125 SHOW_PROGRESS(output," GCT control message 1 failed (error %d), continue anyway ...\n", ret);
1127 SHOW_PROGRESS(output,"Send GCT control message 2 ...\n");
1128 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
1129 0xfe, 0, Interface, buffer, 1, 1000);
1131 if (ret < 0) {
1132 SHOW_PROGRESS(output," GCT control message 2 failed (error %d). Abort\n\n", ret);
1134 libusb_release_interface(devh, Interface);
1135 if (ret < 0)
1136 exit(0);
1140 void switchKobilMode() {
1141 int ret;
1142 SHOW_PROGRESS(output,"Send Kobil control message ...\n");
1143 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1144 0x88, 0, 0, buffer, 8, 1000);
1146 if (ret < 0) {
1147 fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret);
1148 exit(0);
1153 void switchQisdaMode () {
1154 int ret;
1155 SHOW_PROGRESS(output,"Sending Qisda control message ...\n");
1156 memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1157 ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, buffer, 16, 1000);
1158 if (ret < 0) {
1159 fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret);
1160 exit(0);
1165 void switchQuantaMode() {
1166 int ret;
1167 SHOW_PROGRESS(output,"Send Quanta control message ...\n");
1168 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1169 0xff, 0, 0, buffer, 0, 1000);
1171 if (ret < 0) {
1172 SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret);
1173 exit(0);
1178 void switchBlackberryMode ()
1180 int ret;
1181 SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n");
1182 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1183 0xb1, 0x0000, 0, buffer, 8, 1000);
1185 if (ret != 8) {
1186 fprintf(stderr, "Error: Blackberry control message 1 failed (result %d)\n", ret);
1188 SHOW_PROGRESS(output,"Send Blackberry control message 2 ...\n");
1189 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1190 0xa9, 0x000e, 0, buffer, 2, 1000);
1192 if (ret != 2) {
1193 fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret);
1194 exit(0);
1199 void switchPantechMode()
1201 int ret;
1202 SHOW_PROGRESS(output,"Send Pantech control message, wValue %d ...\n", PantechMode);
1203 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1204 0x70, PantechMode, 0, buffer, 0, 1000);
1206 if (ret < 0) {
1207 SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret);
1208 exit(0);
1213 #define EP_OUT 0x02
1214 #define EP_IN 0x81
1215 #define SIZE 0x08
1217 #define MOBILE_ACTION_READLOOP1 63
1218 #define MOBILE_ACTION_READLOOP2 73
1220 /* The code here is statically derived from sniffing (and confirmed working).
1221 * However I bet it could be simplified significantly.
1224 void switchActionMode ()
1226 int ret, i;
1227 SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n");
1228 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1229 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
1230 0x09, 0x0300, 0, buffer, SIZE, 1000);
1232 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1233 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
1234 0x09, 0x0300, 0, buffer, SIZE, 1000);
1236 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1237 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1238 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1239 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1240 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1241 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1242 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1243 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1244 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1245 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1246 for (i=0; i < MOBILE_ACTION_READLOOP1; i++) {
1247 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1249 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1250 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1251 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1252 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1253 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1254 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1255 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1256 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1257 for (i=0; i < MOBILE_ACTION_READLOOP2; i++) {
1258 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1260 memcpy(buffer, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE);
1261 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1262 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1263 memcpy(buffer, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE);
1264 ret = usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1265 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1266 if (ret < 0) {
1267 SHOW_PROGRESS(output," MobileAction control sequence did not complete\n"
1268 " Last error was %d\n",ret);
1269 } else {
1270 SHOW_PROGRESS(output," MobileAction control sequence complete\n");
1275 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1276 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1278 #define SQN_DEFAULT_DEVICE_MODE 0x00
1279 #define SQN_MASS_STORAGE_MODE 0x01
1280 #define SQN_CUSTOM_DEVICE_MODE 0x02
1282 void switchSequansMode()
1285 int ret;
1286 SHOW_PROGRESS(output,"Send Sequans control message\n");
1287 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1288 | LIBUSB_ENDPOINT_OUT, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE,
1289 0, buffer, 0, 1000);
1291 if (ret < 0) {
1292 fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret);
1293 exit(0);
1298 void switchCiscoMode()
1300 int ret, i, j;
1302 strcpy(Messages[0],"55534243f83bcd810002000080000afd000000030000000100000000000000");
1303 strcpy(Messages[1],"55534243984300820002000080000afd000000070000000100000000000000");
1304 strcpy(Messages[2],"55534243984300820000000000000afd000100071000000000000000000000");
1305 strcpy(Messages[3],"55534243984300820002000080000afd000200230000000100000000000000");
1306 strcpy(Messages[4],"55534243984300820000000000000afd000300238200000000000000000000");
1307 strcpy(Messages[5],"55534243984300820002000080000afd000200260000000100000000000000");
1308 strcpy(Messages[6],"55534243984300820000000000000afd00030026c800000000000000000000");
1309 strcpy(Messages[7],"55534243d84c04820002000080000afd000010730000000100000000000000");
1310 strcpy(Messages[8],"55534243d84c04820002000080000afd000200240000000100000000000000");
1311 strcpy(Messages[9],"55534243d84c04820000000000000afd000300241300000000000000000000");
1312 strcpy(Messages[10],"55534243d84c04820000000000000afd000110732400000000000000000000");
1314 SHOW_PROGRESS(output,"Set up Cisco interface %d\n", Interface);
1315 ret = libusb_claim_interface(devh, Interface);
1316 if (ret < 0) {
1317 SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret);
1318 abortExit();
1320 // libusb_clear_halt(devh, MessageEndpoint);
1321 if (show_progress)
1322 fflush(output);
1324 // ret = read_bulk(ResponseEndpoint, ByteString, 13);
1325 // SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret);
1327 for (i=0; i<11; i++) {
1328 if ( sendMessage(Messages[i], i+1) )
1329 goto skip;
1331 for (j=1; j<4; j++) {
1333 SHOW_PROGRESS(output," Read the CSW for bulk message %d (attempt %d) ...\n",i+1,j);
1334 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1335 SHOW_PROGRESS(output,"\n");
1337 if (ret < 0)
1338 goto skip;
1339 if (ret == 13)
1340 break;
1343 libusb_clear_halt(devh, MessageEndpoint);
1344 libusb_clear_halt(devh, ResponseEndpoint);
1346 ReleaseDelay = 2000;
1347 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1348 usleep(ReleaseDelay*1000);
1350 ret = libusb_release_interface(devh, Interface);
1351 if (ret < 0)
1352 goto skip;
1353 return;
1355 skip:
1356 SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret);
1357 libusb_close(devh);
1358 devh = NULL;
1362 int switchSonyMode ()
1364 int ret, i, found;
1365 detachDriver();
1367 if (CheckSuccess) {
1368 CheckSuccess = 0;
1371 SHOW_PROGRESS(output,"Send Sony control message\n");
1372 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1373 | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100);
1375 if (ret < 0) {
1376 fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret);
1377 exit(0);
1378 } else
1379 SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n");
1381 libusb_close(devh);
1382 devh = NULL;
1384 /* Now waiting for the device to reappear */
1385 devnum=-1;
1386 busnum=-1;
1387 i=0;
1388 dev = 0;
1389 while ( dev == 0 && i < 30 ) {
1390 if ( i > 5 ) {
1391 dev = search_devices(&found, DefaultVendor, DefaultProductList, TargetClass,
1392 0, SEARCH_TARGET);
1394 if ( dev != 0 )
1395 break;
1396 sleep(1);
1397 if (show_progress) {
1398 fprintf(output,"#");
1399 fflush(stdout);
1401 i++;
1403 SHOW_PROGRESS(output,"\n After %d seconds:",i);
1404 if ( dev ) {
1405 SHOW_PROGRESS(output," device came back, proceed\n");
1406 libusb_open(dev, &devh);
1407 if (devh == 0) {
1408 fprintf(stderr, "Error: could not get handle on device\n");
1409 return 0;
1411 } else {
1412 SHOW_PROGRESS(output," device still gone, abort\n");
1413 return 0;
1415 sleep(1);
1417 SHOW_PROGRESS(output,"Send Sony control message again ...\n");
1418 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1419 | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100);
1421 if (ret < 0) {
1422 fprintf(stderr, "Error: Sony control message (2) failed (error %d)\n", ret);
1423 return 0;
1425 SHOW_PROGRESS(output," OK, control message sent\n");
1426 return 1;
1430 /* Detach driver
1432 int detachDriver()
1435 int ret;
1436 SHOW_PROGRESS(output,"Looking for active driver ...\n");
1437 ret = libusb_kernel_driver_active(devh, 0);
1438 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1439 fprintf(output," Can't do driver detection on this platform.\n");
1440 return 2;
1442 if (ret < 0) {
1443 fprintf(output," Driver check failed with error %d. Try to continue\n", ret);
1444 return 2;
1446 if (ret == 0) {
1447 SHOW_PROGRESS(output," No active driver found. Detached before or never attached\n");
1448 return 1;
1451 ret = libusb_detach_kernel_driver(devh, Interface);
1452 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1453 fprintf(output," Can't do driver detaching on this platform.\n");
1454 return 2;
1456 if (ret == 0) {
1457 SHOW_PROGRESS(output," OK, driver detached\n");
1458 } else
1459 SHOW_PROGRESS(output," Driver detach failed (error %d). Try to continue\n", ret);
1460 return 1;
1464 int sendMessage(char* message, int count)
1466 int ret, message_length;
1468 if (strlen(message) % 2 != 0) {
1469 fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count);
1470 return 1;
1472 message_length = strlen(message) / 2;
1473 if ( hexstr2bin(message, ByteString, message_length) == -1) {
1474 fprintf(stderr, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n",
1475 count, MessageContent);
1477 return 1;
1479 SHOW_PROGRESS(output,"Trying to send message %d to endpoint 0x%02x ...\n", count, MessageEndpoint);
1480 fflush(output);
1481 ret = write_bulk(MessageEndpoint, ByteString, message_length);
1482 if (ret == LIBUSB_ERROR_NO_DEVICE)
1483 return 1;
1485 return 0;
1489 int checkSuccess()
1491 int ret, i;
1492 int newTargetCount, success=0;
1494 SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess);
1495 sleep(1);
1497 /* If target parameters are given, don't check for vanished device
1498 * Changed for Cisco AM10 where a new device is added while the install
1499 * storage device stays active
1501 if ((TargetVendor || TargetClass) && devh) {
1502 libusb_close(devh);
1503 devh = NULL;
1506 /* if target ID is not given but target class is, assign default as target;
1507 * it will be needed for sysmode output
1509 if (!TargetVendor && TargetClass) {
1510 TargetVendor = DefaultVendor;
1511 TargetProduct = DefaultProduct;
1514 /* devh is 0 if device vanished during command transmission or if target params were given
1516 if (devh)
1517 for (i=0; i < CheckSuccess; i++) {
1519 /* Test if default device still can be accessed; positive result does
1520 * not necessarily mean failure
1522 SHOW_PROGRESS(output," Wait for original device to vanish ...\n");
1524 ret = libusb_claim_interface(devh, Interface);
1525 libusb_release_interface(devh, Interface);
1526 if (ret < 0) {
1527 SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n");
1528 libusb_close(devh);
1529 devh = NULL;
1530 break;
1532 if (i == CheckSuccess-1) {
1533 SHOW_PROGRESS(output," Original device still present after the timeout\n\n"
1534 "Mode switch most likely failed. Bye!\n\n");
1535 } else
1536 sleep(1);
1539 if ( TargetVendor && (TargetProduct > -1 || TargetProductList[0] != '\0') ) {
1541 /* Recount target devices (compare with previous count) if target data is given.
1542 * Target device on the same bus with higher device number is returned,
1543 * description is read for syslog message
1545 for (i=i; i < CheckSuccess; i++) {
1546 SHOW_PROGRESS(output," Search for target devices ...\n");
1547 dev = search_devices(&newTargetCount, TargetVendor, TargetProductList,
1548 TargetClass, 0, SEARCH_TARGET);
1550 if (dev && (newTargetCount > targetDeviceCount)) {
1551 if (verbose) {
1552 libusb_open(dev, &devh);
1553 fprintf(output,"\nFound target device %03d on bus %03d\n",
1554 libusb_get_device_address(dev), libusb_get_bus_number(dev));
1556 fprintf(output,"\nTarget device description data\n");
1557 deviceDescription();
1558 libusb_close(devh);
1559 devh = NULL;
1561 SHOW_PROGRESS(output," Found correct target device\n\n"
1562 "Mode switch succeeded. Bye!\n\n");
1564 success = 2;
1565 break;
1567 if (i == CheckSuccess-1) {
1568 SHOW_PROGRESS(output," No new devices in target mode or class found\n\n"
1569 "Mode switch has failed. Bye!\n\n");
1570 } else
1571 sleep(1);
1573 } else
1574 /* No target data given, rely on the vanished device */
1575 if (!devh) {
1576 SHOW_PROGRESS(output," (For a better success check provide target IDs or class)\n");
1577 SHOW_PROGRESS(output," Original device vanished after switching\n\n"
1578 "Mode switch most likely succeeded. Bye!\n\n");
1579 success = 1;
1582 switch (success) {
1583 case 3:
1584 if (sysmode)
1585 syslog(LOG_NOTICE, "switched to new device, but hit libusb1 bug");
1586 TargetProduct = -1;
1587 success = 1;
1588 break;
1589 case 2:
1590 if (sysmode)
1591 syslog(LOG_NOTICE, "switched to %04x:%04x on %03d/%03d", TargetVendor,
1592 TargetProduct, busnum, devnum);
1594 success = 1;
1595 break;
1596 case 1:
1597 if (sysmode)
1598 syslog(LOG_NOTICE, "device seems to have switched");
1599 default:
1602 if (sysmode)
1603 closelog();
1605 return success;
1610 int write_bulk(int endpoint, unsigned char *message, int length)
1612 int ret = usb_bulk_io(devh, endpoint, message, length, 3000);
1613 if (ret >= 0 ) {
1614 SHOW_PROGRESS(output," OK, message successfully sent\n");
1615 } else
1616 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1617 SHOW_PROGRESS(output," Device seems to have vanished right after sending. Good.\n");
1618 } else
1619 SHOW_PROGRESS(output," Sending the message returned error %d. Try to continue\n", ret);
1620 return ret;
1625 int read_bulk(int endpoint, unsigned char *buffer, int length)
1627 int ret = usb_bulk_io(devh, endpoint, buffer, length, 3000);
1628 if (ret >= 0 ) {
1629 SHOW_PROGRESS(output," Response successfully read (%d bytes)", ret);
1630 } else
1631 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1632 SHOW_PROGRESS(output," Device seems to have vanished after reading. Good.");
1633 } else
1634 SHOW_PROGRESS(output," Response reading failed (error %d)", ret);
1635 return ret;
1640 void release_usb_device(int __attribute__((unused)) dummy)
1642 SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n");
1643 if (devh)
1644 libusb_release_interface(devh, Interface);
1645 close_all();
1646 exit(0);
1651 /* Iterates over busses and devices, counts the ones which match the given
1652 * parameters and returns the last one of them
1654 struct libusb_device* search_devices( int *numFound, int vendor, char* productList,
1655 int targetClass, int configuration, int mode)
1657 char *listcopy=NULL, *token;
1658 unsigned char buffer[2];
1659 int devClass, product;
1660 struct libusb_device* right_dev = NULL;
1661 // struct libusb_device_handle *testdevh;
1662 struct libusb_device **devs;
1663 int i=0;
1665 /* only target class given, target vendor and product assumed unchanged */
1666 if ( targetClass && !(vendor || strlen(productList)) ) {
1667 vendor = DefaultVendor;
1668 productList = DefaultProductList;
1670 *numFound = 0;
1672 /* Sanity check */
1673 if (!vendor || productList == '\0')
1674 return NULL;
1676 listcopy = malloc(strlen(productList)+1);
1678 if (libusb_get_device_list(ctx, &devs) < 0) {
1679 perror("Libusb failed to get USB access!");
1680 return 0;
1683 while ((dev = devs[i++]) != NULL) {
1684 struct libusb_device_descriptor descriptor;
1685 libusb_get_device_descriptor(dev, &descriptor);
1687 if (mode == SEARCH_BUSDEV) {
1688 if ((libusb_get_bus_number(dev) != busnum) ||
1689 (libusb_get_device_address(dev) != devnum))
1690 continue;
1691 else
1692 SHOW_PROGRESS(output," bus/device number matched\n");
1695 if (verbose)
1696 fprintf (output," found USB ID %04x:%04x\n",
1697 descriptor.idVendor, descriptor.idProduct);
1698 if (descriptor.idVendor != vendor)
1699 continue;
1700 if (verbose)
1701 fprintf (output," vendor ID matched\n");
1703 strcpy(listcopy, productList);
1704 token = strtok(listcopy, ",");
1705 while (token != NULL) {
1706 if (strlen(token) != 4) {
1707 SHOW_PROGRESS(output,"Error: entry in product ID list has wrong length: %s. "
1708 "Ignored\n", token);
1710 goto NextToken;
1712 if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) {
1713 SHOW_PROGRESS(output,"Error: entry in product ID list is not a hex string: %s. "
1714 "Ignored\n", token);
1716 goto NextToken;
1718 product = 0;
1719 product += (unsigned char)buffer[0];
1720 product <<= 8;
1721 product += (unsigned char)buffer[1];
1722 if (product == descriptor.idProduct) {
1723 SHOW_PROGRESS(output," product ID matched\n");
1725 if (targetClass != 0) {
1726 // TargetClass is set, check class of first interface
1727 struct libusb_device_descriptor descriptor;
1728 libusb_get_device_descriptor(dev, &descriptor);
1729 devClass = descriptor.bDeviceClass;
1730 struct libusb_config_descriptor *config;
1731 libusb_get_config_descriptor(dev, 0, &config);
1732 int ifaceClass = config->interface[0].altsetting[0].bInterfaceClass;
1733 libusb_free_config_descriptor(config);
1734 if (devClass == 0)
1735 devClass = ifaceClass;
1736 else
1737 /* Check for some quirky devices */
1738 if (devClass != ifaceClass)
1739 devClass = ifaceClass;
1740 if (devClass == targetClass) {
1741 if (verbose)
1742 fprintf (output," target class %02x matches\n", targetClass);
1743 if (mode == SEARCH_TARGET) {
1744 (*numFound)++;
1745 right_dev = dev;
1746 if (verbose)
1747 fprintf (output," count device\n");
1748 } else
1749 if (verbose)
1750 fprintf (output," device not counted, target class reached\n");
1751 } else {
1752 if (verbose)
1753 fprintf (output," device class %02x not matching target\n", devClass);
1754 if (mode == SEARCH_DEFAULT || mode == SEARCH_BUSDEV) {
1755 (*numFound)++;
1756 right_dev = dev;
1757 if (verbose)
1758 fprintf (output," count device\n");
1761 } else if (configuration > 0) {
1762 // Configuration parameter is set, check device configuration
1763 int testconfig = get_current_config_value(dev);
1764 if (testconfig != configuration) {
1765 if (verbose)
1766 fprintf (output," device configuration %d not matching target\n",
1767 testconfig);
1769 (*numFound)++;
1770 right_dev = dev;
1771 if (verbose)
1772 fprintf (output," count device\n");
1773 } else
1774 if (verbose)
1775 fprintf (output," device not counted, target configuration reached\n");
1776 } else {
1777 // Neither TargetClass nor Configuration are set
1778 (*numFound)++;
1779 right_dev = dev;
1780 if (mode == SEARCH_BUSDEV)
1781 break;
1785 NextToken:
1786 token = strtok(NULL, ",");
1789 if (listcopy != NULL)
1790 free(listcopy);
1791 return right_dev;
1795 /* Autodetect bulk endpoints (ab) */
1797 int find_first_bulk_endpoint(int direction)
1799 int i, j;
1800 const struct libusb_interface_descriptor *alt;
1801 const struct libusb_endpoint_descriptor *ep;
1803 for (j=0; j < active_config->bNumInterfaces; j++) {
1804 alt = &(active_config->interface[j].altsetting[0]);
1805 if (alt->bInterfaceNumber == Interface) {
1806 for (i=0; i < alt->bNumEndpoints; i++) {
1807 ep = &(alt->endpoint[i]);
1808 if ( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK)
1809 && ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == direction ) ) {
1811 return ep->bEndpointAddress;
1816 return 0;
1820 int get_current_config_value()
1822 SHOW_PROGRESS(output,"Get the current device configuration ...\n");
1823 if (active_config != NULL) {
1824 libusb_free_config_descriptor(active_config);
1825 active_config = NULL;
1827 int ret = libusb_get_active_config_descriptor(dev, &active_config);
1828 if (ret < 0) {
1829 SHOW_PROGRESS(output," Determining the active configuration failed (error %d). Abort\n", ret);
1830 abortExit();
1832 return active_config->bConfigurationValue;
1836 int get_interface_class()
1838 int i;
1839 for (i=0; i < active_config->bNumInterfaces; i++) {
1840 if (active_config->interface[i].altsetting[0].bInterfaceNumber == Interface)
1841 return active_config->interface[i].altsetting[0].bInterfaceClass;
1843 return -1;
1847 /* Parameter parsing */
1849 char* ReadParseParam(const char* FileName, char *VariableName)
1851 static int numLines = 0;
1852 static char* ConfigBuffer[MAXLINES];
1853 char *VarName, *Comment=NULL, *Equal=NULL;
1854 char *FirstQuote, *LastQuote, *P1, *P2;
1855 int Line=0;
1856 unsigned Len=0, Pos=0;
1857 char Str[LINE_DIM], *token, *configPos;
1858 FILE *file = NULL;
1860 // Reading and storing input during the first call
1861 if (numLines==0) {
1862 if (strncmp(FileName,"##",2) == 0) {
1863 if (verbose) fprintf(output,"\nRead long config from command line\n");
1864 // "Embedded" configuration data
1865 configPos = (char*)FileName;
1866 token = strtok(configPos, "\n");
1867 strncpy(Str,token,LINE_DIM-1);
1868 } else {
1869 if (strcmp(FileName, "stdin")==0) {
1870 if (verbose) fprintf(output,"\nRead long config from stdin\n");
1871 file = stdin;
1872 } else {
1873 if (verbose) fprintf(output,"\nRead config file: %s\n", FileName);
1874 file=fopen(FileName, "r");
1876 if (file==NULL) {
1877 fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName);
1878 abortExit();
1879 } else {
1880 token = fgets(Str, LINE_DIM-1, file);
1883 while (token != NULL && numLines < MAXLINES) {
1884 // Line++;
1885 Len=strlen(Str);
1886 if (Len==0)
1887 goto NextLine;
1888 if (Str[Len-1]=='\n' or Str[Len-1]=='\r')
1889 Str[--Len]='\0';
1890 Equal = strchr (Str, '='); // search for equal sign
1891 Pos = strcspn (Str, ";#!"); // search for comment
1892 Comment = (Pos==Len) ? NULL : Str+Pos;
1893 if (Equal==NULL or ( Comment!=NULL and Comment<=Equal))
1894 goto NextLine; // Comment or irrelevant, don't save
1895 Len=strlen(Str)+1;
1896 ConfigBuffer[numLines] = malloc(Len*sizeof(char));
1897 strcpy(ConfigBuffer[numLines],Str);
1898 numLines++;
1899 NextLine:
1900 if (file == NULL) {
1901 token = strtok(NULL, "\n");
1902 if (token != NULL)
1903 strncpy(Str,token,LINE_DIM-1);
1904 } else
1905 token = fgets(Str, LINE_DIM-1, file);
1907 if (file != NULL)
1908 fclose(file);
1911 // Now checking for parameters
1912 Line=0;
1913 while (Line < numLines) {
1914 strcpy(Str,ConfigBuffer[Line]);
1915 Equal = strchr (Str, '='); // search for equal sign
1916 *Equal++ = '\0';
1918 // String
1919 FirstQuote=strchr (Equal, '"'); // search for double quote char
1920 LastQuote=strrchr (Equal, '"');
1921 if (FirstQuote!=NULL) {
1922 if (LastQuote==NULL) {
1923 fprintf(stderr, "Error reading parameters from file %s - "
1924 "Missing end quote:\n%s\n", FileName, Str);
1926 goto Next;
1928 *FirstQuote=*LastQuote='\0';
1929 Equal=FirstQuote+1;
1932 // removes leading/trailing spaces
1933 Pos=strspn (Str, " \t");
1934 if (Pos==strlen(Str)) {
1935 fprintf(stderr, "Error reading parameters from file %s - "
1936 "Missing variable name:\n%s\n", FileName, Str);
1938 goto Next;
1940 while ((P1=strrchr(Str, ' '))!=NULL or (P2=strrchr(Str, '\t'))!=NULL)
1941 if (P1!=NULL) *P1='\0';
1942 else if (P2!=NULL) *P2='\0';
1943 VarName=Str+Pos;
1945 Pos=strspn (Equal, " \t");
1946 if (Pos==strlen(Equal)) {
1947 fprintf(stderr, "Error reading parameter from file %s - "
1948 "Missing value:\n%s\n", FileName, Str);
1950 goto Next;
1952 Equal+=Pos;
1954 if (strcmp(VarName, VariableName)==0) { // Found it
1955 return Equal;
1957 Next:
1958 Line++;
1961 return NULL;
1965 int hex2num(char c)
1967 if (c >= '0' && c <= '9')
1968 return c - '0';
1969 if (c >= 'a' && c <= 'f')
1970 return c - 'a' + 10;
1971 if (c >= 'A' && c <= 'F')
1972 return c - 'A' + 10;
1973 return -1;
1977 int hex2byte(const char *hex)
1979 int a, b;
1980 a = hex2num(*hex++);
1981 if (a < 0)
1982 return -1;
1983 b = hex2num(*hex++);
1984 if (b < 0)
1985 return -1;
1986 return (a << 4) | b;
1990 int hexstr2bin(const char *hex, unsigned char *buffer, int len)
1992 int i;
1993 int a;
1994 const char *ipos = hex;
1995 unsigned char *opos = buffer;
1997 for (i = 0; i < len; i++) {
1998 a = hex2byte(ipos);
1999 if (a < 0)
2000 return -1;
2001 *opos++ = (unsigned char) a;
2002 ipos += 2;
2004 return 0;
2008 void close_all()
2010 int i;
2011 if (Messages) {
2012 for ( i = 0; i < MSG_DIM; i++ ) {
2013 free(Messages[i]);
2015 free(Messages);
2017 if (active_config)
2018 libusb_free_config_descriptor(active_config);
2019 if (devh)
2020 libusb_close(devh);
2021 // libusb_exit will crash on Raspbian 7, crude protection
2022 #ifndef __ARMEL__
2023 libusb_exit(NULL);
2024 #endif
2025 if (sysmode)
2026 closelog();
2030 void abortExit()
2032 close_all();
2033 exit(1);
2037 void printVersion()
2039 char* version = VERSION;
2040 fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
2041 " * Version %s (C) Josua Dietze 2016\n"
2042 " * Based on libusb1/libusbx\n\n"
2043 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version);
2047 void printHelp()
2049 fprintf(output,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
2050 " -h, --help this help\n"
2051 " -e, --version print version information and exit\n"
2052 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
2053 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
2054 " -p, --default-product NUM product ID of original mode (mandatory)\n"
2055 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
2056 " -P, --target-product NUM target mode product ID (optional)\n"
2057 " -C, --target-class NUM target mode device class (optional)\n"
2058 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
2059 " -g, --device-num NUM system device number (for hard ID)\n"
2060 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
2061 " -M, --message-content <msg> message to send (hex number as string)\n"
2062 " -2 <msg>, -3 <msg> additional messages to send (-n recommended)\n"
2063 " -w, --release-delay NUM wait NUM ms before releasing the interface\n"
2064 " -n, --need-response obsolete, no effect (always on)\n"
2065 " -r, --response-endpoint NUM read response from there (optional)\n"
2066 " -K, --std-eject send standard EJECT sequence\n"
2067 " -d, --detach-only detach the active driver, no further action\n"
2068 " -H, --huawei-mode apply a special procedure\n"
2069 " -J, --huawei-new-mode apply a special procedure\n"
2070 " -S, --sierra-mode apply a special procedure\n"
2071 " -O, --sony-mode apply a special procedure\n"
2072 " -G, --gct-mode apply a special procedure\n"
2073 " -N, --sequans-mode apply a special procedure\n"
2074 " -A, --mobileaction-mode apply a special procedure\n"
2075 " -T, --kobil-mode apply a special procedure\n"
2076 " -L, --cisco-mode apply a special procedure\n"
2077 " -B, --qisda-mode apply a special procedure\n"
2078 " -E, --quanta-mode apply a special procedure\n"
2079 " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n"
2080 " -Z, --blackberry-mode apply a special procedure\n"
2081 " -U, --option-mode apply a special procedure\n"
2082 " -R, --reset-usb reset the device after all other actions\n"
2083 " -Q, --quiet don't show progress or error messages\n"
2084 " -W, --verbose print all settings and debug output\n"
2085 " -D, --sysmode specific result and syslog message\n"
2086 " -s, --success <seconds> switching result check with timeout\n"
2087 " -I, --inquire obsolete, no effect\n\n"
2088 " -c, --config-file <filename> load long configuration from file\n\n"
2089 " -t, --stdinput read long configuration from stdin\n\n"
2090 " -f, --long-config <text> get long configuration from string\n\n"
2091 " -i, --interface NUM select initial USB interface (default 0)\n"
2092 " -u, --configuration NUM select USB configuration\n"
2093 " -a, --altsetting NUM select alternative USB interface setting\n\n");