1 /*
2 Mode switching tool for controlling mode of 'multi-state' USB devices
3 Version 2.6.0, 2019/11/28
4
5 Copyright (C) 2007 - 2019 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)
8
9 Major contributions:
10
11 Command line parsing, decent usage/config output/handling, bugfixes and advanced
12 options added by:
13 Joakim Wennergren
14
15 TargetClass parameter implementation to support new Option devices/firmware:
16 Paul Hardwick (http://www.pharscape.org)
17
18 Created with initial help from:
19 "usbsnoop2libusb.pl" by Timo Lindfors (http://iki.fi/lindi/usb/usbsnoop2libusb.pl)
20
21 Config file parsing code borrowed from:
22 Guillaume Dargaud (http://www.gdargaud.net/Hack/SourceCode.html)
23
24 Hexstr2bin function borrowed from:
25 Jouni Malinen (http://hostap.epitest.fi/wpa_supplicant, from "common.c")
26
27 Other contributions: see README
28
29 Device information contributors are named in the "device_reference.txt" file. See
30 homepage.
31
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.
36
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:
41
42 http://www.gnu.org/licenses/gpl.txt
43
44 */
45
46 /* Recommended tab size: 4 */
47
48 #define VERSION "2.6.0"
49
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>
58
59 #include "usb_modeswitch.h"
60
61
62 // Little helpers
63
usb_bulk_io(struct libusb_device_handle * handle,int ep,unsigned char * bytes,int size,int timeout)64 int usb_bulk_io(struct libusb_device_handle *handle, int ep, unsigned char *bytes,
65 int size, int timeout)
66 {
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);
72
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;
77
78 return r;
79 }
80
81
usb_interrupt_io(libusb_device_handle * handle,int ep,unsigned char * bytes,int size,int timeout)82 static int usb_interrupt_io(libusb_device_handle *handle, int ep, unsigned char *bytes,
83 int size, int timeout)
84 {
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);
90
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;
95
96 return (r);
97 }
98
99
100 #define LINE_DIM 1024
101 #define MSG_DIM 11
102 #define MAXLINES 50
103 #define BUF_SIZE 4096
104 #define DESCR_MAX 129
105
106 #define SEARCH_DEFAULT 0
107 #define SEARCH_TARGET 1
108 #define SEARCH_BUSDEV 2
109
110 #define SWITCH_CONFIG_MAXTRIES 5
111
112 #define SHOW_PROGRESS if (show_progress) fprintf
113
114 char *TempPP=NULL;
115
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;
120
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;
125
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
142 #define HUAWEIALT_MODE 0x00008000
143
144
145 int PantechMode=0;
146 char verbose=0, show_progress=1, ResetUSB=0, CheckSuccess=0, config_read=0;
147 char NoDriverLoading=0, sysmode=0, mbim=0;
148 char StandardEject=0;
149
150 char MessageContent[LINE_DIM];
151 char MessageContent2[LINE_DIM];
152 char MessageContent3[LINE_DIM];
153 char TargetProductList[LINE_DIM];
154 char DefaultProductList[5];
155 unsigned char ByteString[LINE_DIM/2];
156 unsigned char buffer[BUF_SIZE];
157 char **Messages = NULL;
158
159 FILE *output;
160
161
162 /* Settable interface, altsetting (for debugging mostly) and configuration */
163 int Interface = -1, Configuration = 0, AltSetting = -1;
164
165
166 static struct option long_options[] = {
167 {"help", no_argument, 0, 'h'},
168 {"version", no_argument, 0, 'e'},
169 {"default-vendor", required_argument, 0, 'v'},
170 {"default-product", required_argument, 0, 'p'},
171 {"target-vendor", required_argument, 0, 'V'},
172 {"target-product", required_argument, 0, 'P'},
173 {"target-class", required_argument, 0, 'C'},
174 {"message-endpoint", required_argument, 0, 'm'},
175 {"message-content", required_argument, 0, 'M'},
176 {"message-content2", required_argument, 0, '2'},
177 {"message-content3", required_argument, 0, '3'},
178 {"release-delay", required_argument, 0, 'w'},
179 {"response-endpoint", required_argument, 0, 'r'},
180 {"bus-num", required_argument, 0, 'b'},
181 {"device-num", required_argument, 0, 'g'},
182 {"detach-only", no_argument, 0, 'd'},
183 {"huawei-mode", no_argument, 0, 'H'},
184 {"huawei-new-mode", no_argument, 0, 'J'},
185 {"huawei-alt-mode", no_argument, 0, 'X'},
186 {"sierra-mode", no_argument, 0, 'S'},
187 {"sony-mode", no_argument, 0, 'O'},
188 {"qisda-mode", no_argument, 0, 'B'},
189 {"quanta-mode", no_argument, 0, 'E'},
190 {"kobil-mode", no_argument, 0, 'T'},
191 {"gct-mode", no_argument, 0, 'G'},
192 {"sequans-mode", no_argument, 0, 'N'},
193 {"mobileaction-mode", no_argument, 0, 'A'},
194 {"cisco-mode", no_argument, 0, 'L'},
195 {"blackberry-mode", no_argument, 0, 'Z'},
196 {"option-mode", no_argument, 0, 'U'},
197 {"pantech-mode", required_argument, 0, 'F'},
198 {"std-eject", no_argument, 0, 'K'},
199 {"need-response", no_argument, 0, 'n'},
200 {"reset-usb", no_argument, 0, 'R'},
201 {"config-file", required_argument, 0, 'c'},
202 {"verbose", no_argument, 0, 'W'},
203 {"quiet", no_argument, 0, 'Q'},
204 {"sysmode", no_argument, 0, 'D'},
205 {"inquire", no_argument, 0, 'I'},
206 {"stdinput", no_argument, 0, 't'},
207 {"find-mbim", no_argument, 0, 'j'},
208 {"long-config", required_argument, 0, 'f'},
209 {"check-success", required_argument, 0, 's'},
210 {"interface", required_argument, 0, 'i'},
211 {"configuration", required_argument, 0, 'u'},
212 {"altsetting", required_argument, 0, 'a'},
213 {0, 0, 0, 0}
214 };
215
216
readConfigFile(const char * configFilename)217 void readConfigFile(const char *configFilename)
218 {
219 ParseParamHex(configFilename, TargetVendor);
220 ParseParamHex(configFilename, TargetProduct);
221 ParseParamString(configFilename, TargetProductList);
222 ParseParamHex(configFilename, TargetClass);
223 ParseParamHex(configFilename, DefaultVendor);
224 ParseParamHex(configFilename, DefaultProduct);
225 ParseParamBoolMap(configFilename, DetachStorageOnly, ModeMap, DETACHONLY_MODE);
226 ParseParamBoolMap(configFilename, HuaweiMode, ModeMap, HUAWEI_MODE);
227 ParseParamBoolMap(configFilename, HuaweiNewMode, ModeMap, HUAWEINEW_MODE);
228 ParseParamBoolMap(configFilename, HuaweiAltMode, ModeMap, HUAWEIALT_MODE);
229 ParseParamBoolMap(configFilename, SierraMode, ModeMap, SIERRA_MODE);
230 ParseParamBoolMap(configFilename, SonyMode, ModeMap, SONY_MODE);
231 ParseParamBoolMap(configFilename, GCTMode, ModeMap, GCT_MODE);
232 ParseParamBoolMap(configFilename, KobilMode, ModeMap, KOBIL_MODE);
233 ParseParamBoolMap(configFilename, SequansMode, ModeMap, SEQUANS_MODE);
234 ParseParamBoolMap(configFilename, MobileActionMode, ModeMap, MOBILEACTION_MODE);
235 ParseParamBoolMap(configFilename, CiscoMode, ModeMap, CISCO_MODE);
236 ParseParamBoolMap(configFilename, QisdaMode, ModeMap, QISDA_MODE);
237 ParseParamBoolMap(configFilename, QuantaMode, ModeMap, QUANTA_MODE);
238 ParseParamBoolMap(configFilename, OptionMode, ModeMap, OPTION_MODE);
239 ParseParamBoolMap(configFilename, BlackberryMode, ModeMap, BLACKBERRY_MODE);
240 ParseParamInt(configFilename, PantechMode);
241 if (PantechMode)
242 ModeMap |= PANTECH_MODE;
243 ParseParamBool(configFilename, StandardEject);
244 ParseParamBool(configFilename, NoDriverLoading);
245 ParseParamHex(configFilename, MessageEndpoint);
246 ParseParamString(configFilename, MessageContent);
247 ParseParamString(configFilename, MessageContent2);
248 ParseParamString(configFilename, MessageContent3);
249 ParseParamInt(configFilename, ReleaseDelay);
250 ParseParamHex(configFilename, ResponseEndpoint);
251 ParseParamHex(configFilename, ResetUSB);
252 ParseParamInt(configFilename, CheckSuccess);
253 ParseParamHex(configFilename, Interface);
254 ParseParamHex(configFilename, Configuration);
255 ParseParamHex(configFilename, AltSetting);
256
257 /* TargetProductList has priority over TargetProduct */
258 if (TargetProduct != -1 && TargetProductList[0] != '\0') {
259 TargetProduct = -1;
260 SHOW_PROGRESS(output,"Warning: TargetProductList overrides TargetProduct!\n");
261 }
262
263 config_read = 1;
264 }
265
266
printConfig()267 void printConfig()
268 {
269 if ( DefaultVendor )
270 fprintf (output,"DefaultVendor= 0x%04x\n", DefaultVendor);
271 if ( DefaultProduct )
272 fprintf (output,"DefaultProduct= 0x%04x\n", DefaultProduct);
273 if ( TargetVendor )
274 fprintf (output,"TargetVendor= 0x%04x\n", TargetVendor);
275 if ( TargetProduct > -1 )
276 fprintf (output,"TargetProduct= 0x%04x\n", TargetProduct);
277 if ( TargetClass )
278 fprintf (output,"TargetClass= 0x%02x\n", TargetClass);
279 if ( strlen(TargetProductList) )
280 fprintf (output,"TargetProductList=\"%s\"\n", TargetProductList);
281 if (StandardEject)
282 fprintf (output,"\nStandardEject=1\n");
283 if (ModeMap & DETACHONLY_MODE)
284 fprintf (output,"\nDetachStorageOnly=1\n");
285 if (ModeMap & HUAWEI_MODE)
286 fprintf (output,"HuaweiMode=1\n");
287 if (ModeMap & HUAWEINEW_MODE)
288 fprintf (output,"HuaweiNewMode=1\n");
289 if (ModeMap & HUAWEIALT_MODE)
290 fprintf (output,"HuaweiAltMode=1\n");
291 if (ModeMap & SIERRA_MODE)
292 fprintf (output,"SierraMode=1\n");
293 if (ModeMap & SONY_MODE)
294 fprintf (output,"SonyMode=1\n");
295 if (ModeMap & QISDA_MODE)
296 fprintf (output,"QisdaMode=1\n");
297 if (ModeMap & QUANTA_MODE)
298 fprintf (output,"QuantaMode=1\n");
299 if (ModeMap & GCT_MODE)
300 fprintf (output,"GCTMode=1\n");
301 if (ModeMap & KOBIL_MODE)
302 fprintf (output,"KobilMode=1\n");
303 if (ModeMap & SEQUANS_MODE)
304 fprintf (output,"SequansMode=1\n");
305 if (ModeMap & MOBILEACTION_MODE)
306 fprintf (output,"MobileActionMode=1\n");
307 if (ModeMap & CISCO_MODE)
308 fprintf (output,"CiscoMode=1\n");
309 if (ModeMap & BLACKBERRY_MODE)
310 fprintf (output,"BlackberryMode=1\n");
311 if (ModeMap & OPTION_MODE)
312 fprintf (output,"OptionMode=1\n");
313 if (ModeMap & PANTECH_MODE)
314 fprintf (output,"PantechMode=1\n");
315 if ( MessageEndpoint )
316 fprintf (output,"MessageEndpoint=0x%02x\n", MessageEndpoint);
317 if ( strlen(MessageContent) )
318 fprintf (output,"MessageContent=\"%s\"\n", MessageContent);
319 if ( strlen(MessageContent2) )
320 fprintf (output,"MessageContent2=\"%s\"\n", MessageContent2);
321 if ( strlen(MessageContent3) )
322 fprintf (output,"MessageContent3=\"%s\"\n", MessageContent3);
323 if ( ResponseEndpoint )
324 fprintf (output,"ResponseEndpoint=0x%02x\n", ResponseEndpoint);
325 if ( Interface > -1 )
326 fprintf (output,"Interface=0x%02x\n", Interface);
327 if ( Configuration > 0 )
328 fprintf (output,"Configuration=0x%02x\n", Configuration);
329 if ( AltSetting > -1 )
330 fprintf (output,"AltSetting=0x%02x\n", AltSetting);
331 if ( CheckSuccess )
332 fprintf (output,"Success check enabled, max. wait time %d seconds\n", CheckSuccess);
333 if ( sysmode )
334 fprintf (output,"System integration mode enabled\n");
335 }
336
337
readArguments(int argc,char ** argv)338 int readArguments(int argc, char **argv)
339 {
340 int c, option_index = 0, count=0;
341 char *longConfig = NULL;
342 if (argc==1)
343 {
344 printHelp();
345 printVersion();
346 exit(1);
347 }
348
349 while (1)
350 {
351 c = getopt_long (argc, argv, "hejWQDndKHJSOBEGTNALZUXF:RItv:p:V:P:C:m:M:2:3:w:r:c:i:u:a:s:f:b:g:",
352 long_options, &option_index);
353
354 /* Detect the end of the options. */
355 if (c == -1)
356 break;
357 count++;
358 switch (c)
359 {
360 case 'R': ResetUSB = 1; break;
361 case 'v': DefaultVendor = strtol(optarg, NULL, 16); break;
362 case 'p': DefaultProduct = strtol(optarg, NULL, 16); break;
363 case 'V': TargetVendor = strtol(optarg, NULL, 16); break;
364 case 'P': TargetProduct = strtol(optarg, NULL, 16); break;
365 case 'C': TargetClass = strtol(optarg, NULL, 16); break;
366 case 'm': MessageEndpoint = strtol(optarg, NULL, 16); break;
367 case 'M': strncpy(MessageContent, optarg, LINE_DIM); break;
368 case '2': strncpy(MessageContent2, optarg, LINE_DIM); break;
369 case '3': strncpy(MessageContent3, optarg, LINE_DIM); break;
370 case 'w': ReleaseDelay = strtol(optarg, NULL, 10); break;
371 case 'n': break;
372 case 'r': ResponseEndpoint = strtol(optarg, NULL, 16); break;
373 case 'K': StandardEject = 1; break;
374 case 'd': ModeMap = ModeMap + DETACHONLY_MODE; break;
375 case 'H': ModeMap = ModeMap + HUAWEI_MODE; break;
376 case 'J': ModeMap = ModeMap + HUAWEINEW_MODE; break;
377 case 'X': ModeMap = ModeMap + HUAWEIALT_MODE; break;
378 case 'S': ModeMap = ModeMap + SIERRA_MODE; break;
379 case 'O': ModeMap = ModeMap + SONY_MODE; break;; break;
380 case 'B': ModeMap = ModeMap + QISDA_MODE; break;
381 case 'E': ModeMap = ModeMap + QUANTA_MODE; break;
382 case 'G': ModeMap = ModeMap + GCT_MODE; break;
383 case 'T': ModeMap = ModeMap + KOBIL_MODE; break;
384 case 'N': ModeMap = ModeMap + SEQUANS_MODE; break;
385 case 'A': ModeMap = ModeMap + MOBILEACTION_MODE; break;
386 case 'L': ModeMap = ModeMap + CISCO_MODE; break;
387 case 'Z': ModeMap = ModeMap + BLACKBERRY_MODE; break;
388 case 'U': ModeMap = ModeMap + OPTION_MODE; break;
389 case 'F': ModeMap = ModeMap + PANTECH_MODE;
390 PantechMode = strtol(optarg, NULL, 10); break;
391 case 'c': readConfigFile(optarg); break;
392 case 't': readConfigFile("stdin"); break;
393 case 'W': verbose = 1; show_progress = 1; count--; break;
394 case 'Q': show_progress = 0; verbose = 0; count--; break;
395 case 'D': sysmode = 1; count--; break;
396 case 's': CheckSuccess = strtol(optarg, NULL, 10); count--; break;
397 case 'I': break;
398 case 'b': busnum = strtol(optarg, NULL, 10); break;
399 case 'g': devnum = strtol(optarg, NULL, 10); break;
400
401 case 'i': Interface = strtol(optarg, NULL, 16); break;
402 case 'u': Configuration = strtol(optarg, NULL, 16); break;
403 case 'a': AltSetting = strtol(optarg, NULL, 16); break;
404 case 'j': mbim = 1; break;
405
406 case 'f':
407 longConfig = malloc(strlen(optarg)+5);
408 strcpy(longConfig,"##\n");
409 strcat(longConfig,optarg);
410 strcat(longConfig,"\n");
411 readConfigFile(longConfig);
412 free(longConfig);
413 break;
414
415 case 'e':
416 printVersion();
417 exit(0);
418 break;
419 case 'h':
420 printVersion();
421 printHelp();
422 exit(0);
423 break;
424
425 default: /* Unsupported - error message has already been printed */
426 fprintf (output,"\n");
427 printHelp();
428 exit(1);
429 }
430 }
431 return count;
432 }
433
434
main(int argc,char ** argv)435 int main(int argc, char **argv)
436 {
437 int ret=0, numDefaults=0, sonySuccess=0, i;
438 int defaultClass=0, interfaceClass=0, currentConfigVal=0;
439 struct libusb_device_descriptor descriptor;
440 enum libusb_error libusbError;
441
442 /* Make sure we have empty strings even if not set by config */
443 TargetProductList[0] = '\0';
444 MessageContent[0] = '\0';
445 MessageContent2[0] = '\0';
446 MessageContent3[0] = '\0';
447 DefaultProductList[0] = '\0';
448
449 /* Useful for debugging during boot */
450 // output=fopen("/dev/console", "w");
451 output=stdout;
452
453 signal(SIGTERM, release_usb_device);
454
455 /*
456 * Parameter parsing, USB preparation/diagnosis, plausibility checks
457 */
458
459 /* Check command arguments, use params instead of config file when given */
460 switch (readArguments(argc, argv)) {
461 case 0: /* no argument or -W, -q or -s */
462 break;
463 default: /* one or more arguments except -W, -q or -s */
464 if (!config_read) /* if arguments contain -c, the config file was already processed */
465 if (verbose) fprintf(output,"Take all parameters from the command line\n\n");
466 }
467
468 if (verbose) {
469 printVersion();
470 printConfig();
471 fprintf(output,"\n");
472 }
473
474 /* Some validty checks. The default IDs are mandatory */
475 if (!(DefaultVendor && DefaultProduct)) {
476 SHOW_PROGRESS(output,"No default vendor/product ID given. Abort\n\n");
477 exit(1);
478 }
479
480 if (strlen(MessageContent)) {
481 if (strlen(MessageContent) % 2 != 0) {
482 fprintf(stderr, "MessageContent hex string has uneven length. Abort\n\n");
483 exit(1);
484 }
485 if ( hexstr2bin(MessageContent, ByteString, strlen(MessageContent)/2) == -1) {
486 fprintf(stderr, "MessageContent %s\n is not a hex string. Abort\n\n",
487 MessageContent);
488
489 exit(1);
490 }
491 }
492
493 if (devnum == -1) {
494 searchMode = SEARCH_DEFAULT;
495 } else {
496 SHOW_PROGRESS(output,"Use given bus/device number: %03d/%03d ...\n", busnum, devnum);
497 searchMode = SEARCH_BUSDEV;
498 }
499
500 if (show_progress)
501 if (CheckSuccess && !(TargetVendor || TargetProduct > -1 || TargetProductList[0] != '\0')
502 && !TargetClass)
503
504 fprintf(output,"Note: No target parameter given; success check limited\n");
505
506 if (TargetProduct > -1 && TargetProductList[0] == '\0') {
507 sprintf(TargetProductList,"%04x",TargetProduct);
508 TargetProduct = -1;
509 }
510
511 /* libusb initialization */
512 if ((libusbError = libusb_init(&ctx)) != LIBUSB_SUCCESS) {
513 fprintf(stderr, "Error: Failed to initialize libusb. %s (%d)\n\n",
514 libusb_error_name(libusbError), libusbError);
515 exit(1);
516 }
517
518 if (verbose)
519 libusb_set_debug(ctx, 3);
520
521 if (mbim) {
522 printf("%d\n", findMBIMConfig(DefaultVendor, DefaultProduct, searchMode) );
523 exit(0);
524 }
525
526 /* Count existing target devices, remember for success check */
527 if (searchMode != SEARCH_BUSDEV && (TargetVendor || TargetClass)) {
528 SHOW_PROGRESS(output,"Look for target devices ...\n");
529 search_devices(&targetDeviceCount, TargetVendor, TargetProductList, TargetClass, 0,
530 SEARCH_TARGET);
531
532 if (targetDeviceCount) {
533 SHOW_PROGRESS(output," Found devices in target mode or class (%d)\n", targetDeviceCount);
534 } else
535 SHOW_PROGRESS(output," No devices in target mode or class found\n");
536 }
537
538 /* Count default devices, get the last one found */
539 SHOW_PROGRESS(output,"Look for default devices ...\n");
540
541 sprintf(DefaultProductList,"%04x",DefaultProduct);
542 dev = search_devices(&numDefaults, DefaultVendor, DefaultProductList, TargetClass,
543 Configuration, searchMode);
544
545 if (numDefaults) {
546 SHOW_PROGRESS(output," Found devices in default mode (%d)\n", numDefaults);
547 } else {
548 SHOW_PROGRESS(output," No devices in default mode found. Nothing to do. Bye!\n\n");
549 close_all();
550 exit(0);
551 }
552
553 if (dev == NULL) {
554 SHOW_PROGRESS(output," No bus/device match. Is device connected? Abort\n\n");
555 close_all();
556 exit(0);
557 } else {
558 if (devnum == -1) {
559 devnum = libusb_get_device_address(dev);
560 busnum = libusb_get_bus_number(dev);
561 SHOW_PROGRESS(output,"Access device %03d on bus %03d\n", devnum, busnum);
562 }
563 libusb_open(dev, &devh);
564 if (devh == NULL) {
565 SHOW_PROGRESS(output,"Error opening the device. Abort\n\n");
566 abortExit();
567 }
568 }
569
570 /* Get current configuration of default device, note value if Configuration
571 * parameter is set. Also sets active_config
572 */
573 currentConfigVal = get_current_config_value(dev);
574 if (Configuration > -1) {
575 SHOW_PROGRESS(output,"Current configuration number is %d\n", currentConfigVal);
576 } else
577 currentConfigVal = 0;
578
579 libusb_get_device_descriptor(dev, &descriptor);
580 defaultClass = descriptor.bDeviceClass;
581 if (Interface == -1)
582 Interface = active_config->interface[0].altsetting[0].bInterfaceNumber;
583 SHOW_PROGRESS(output,"Use interface number %d\n", Interface);
584
585 /* Get class of default device/interface */
586 interfaceClass = get_interface_class();
587
588 if (interfaceClass == -1) {
589 fprintf(stderr, "Error: Could not get class of interface %d. Does it exist? Abort\n\n",Interface);
590 abortExit();
591 } else {
592 SHOW_PROGRESS(output," with class %d\n", interfaceClass);
593 }
594
595 if (defaultClass == 0 || defaultClass == 0xef)
596 defaultClass = interfaceClass;
597 else
598 if (interfaceClass == LIBUSB_CLASS_MASS_STORAGE && defaultClass != LIBUSB_CLASS_MASS_STORAGE
599 && defaultClass != LIBUSB_CLASS_VENDOR_SPEC) {
600
601 /* Unexpected default class combined with differing interface class */
602 SHOW_PROGRESS(output,"Bogus Class/InterfaceClass: 0x%02x/0x08\n", defaultClass);
603 defaultClass = 8;
604 }
605
606 if ((strlen(MessageContent) && strncmp("55534243",MessageContent,8) == 0)
607 || StandardEject || ModeMap & HUAWEINEW_MODE || ModeMap & HUAWEIALT_MODE
608 || ModeMap & CISCO_MODE || ModeMap & OPTION_MODE)
609 if (defaultClass != 8) {
610 fprintf(stderr, "Error: can't use storage command in MessageContent with interface %d; "
611 "interface class is %d, expected 8. Abort\n\n", Interface, defaultClass);
612 abortExit();
613 }
614
615 /* Check or get endpoints and alloc message list if needed*/
616 if (strlen(MessageContent) || StandardEject || ModeMap & CISCO_MODE
617 || ModeMap & HUAWEINEW_MODE || ModeMap & HUAWEIALT_MODE
618 || ModeMap & OPTION_MODE) {
619
620 Messages = (char**) calloc(MSG_DIM, sizeof(char*));
621 for (i = 0; i < MSG_DIM; i++) {
622 Messages[i] = (char*) calloc(LINE_DIM, sizeof(char));
623 Messages[i][0] = '\0';
624 }
625
626 if (!MessageEndpoint)
627 MessageEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_OUT);
628 if (!ResponseEndpoint)
629 ResponseEndpoint = find_first_bulk_endpoint(LIBUSB_ENDPOINT_IN);
630 if (!MessageEndpoint) {
631 fprintf(stderr,"Error: message endpoint not given or found. Abort\n\n");
632 abortExit();
633 }
634 if (!ResponseEndpoint) {
635 fprintf(stderr,"Error: response endpoint not given or found. Abort\n\n");
636 abortExit();
637 }
638 SHOW_PROGRESS(output,"Use endpoints 0x%02x (out) and 0x%02x (in)\n", MessageEndpoint,
639 ResponseEndpoint);
640
641 }
642
643 if (verbose) {
644 fprintf(output,"\nUSB description data (for identification)\n");
645 deviceDescription();
646 }
647
648 /* Special modes are exclusive, so check for illegal combinations.
649 * More than one bit set?
650 */
651 if ( ModeMap & (ModeMap-1) ) {
652 fprintf(output,"Multiple special modes selected; check configuration. Abort\n\n");
653 abortExit();
654 }
655
656 if ((strlen(MessageContent) || StandardEject) && ModeMap ) {
657 MessageContent[0] = '\0';
658 StandardEject = 0;
659 fprintf(output,"Warning: MessageContent/StandardEject ignored; can't combine with special mode\n");
660 }
661
662 if (StandardEject && (strlen(MessageContent2) || strlen(MessageContent3))) {
663 fprintf(output,"Warning: MessageContent2/3 ignored; only one allowed with StandardEject\n");
664 }
665
666 if ( !ModeMap && !strlen(MessageContent) && AltSetting == -1 && !Configuration && !StandardEject )
667 SHOW_PROGRESS(output,"Warning: no switching method given. See documentation\n");
668
669 /*
670 * The switching actions
671 */
672
673 if (sysmode) {
674 openlog("usb_modeswitch", 0, LOG_SYSLOG);
675 syslog(LOG_NOTICE, "switch device %04x:%04x on %03d/%03d", DefaultVendor, DefaultProduct,
676 busnum, devnum);
677
678 }
679
680 if (ModeMap & DETACHONLY_MODE) {
681 SHOW_PROGRESS(output,"Detach storage driver as switching method ...\n");
682 ret = detachDrivers();
683 if (ret == 2)
684 SHOW_PROGRESS(output," You may want to remove the storage driver manually\n");
685 }
686
687 if(ModeMap & HUAWEI_MODE) {
688 switchHuaweiMode();
689 }
690 if(ModeMap & SIERRA_MODE) {
691 switchSierraMode();
692 }
693 if(ModeMap & GCT_MODE) {
694 detachDrivers();
695 switchGCTMode();
696 }
697 if(ModeMap & QISDA_MODE) {
698 switchQisdaMode();
699 }
700 if(ModeMap & KOBIL_MODE) {
701 detachDrivers();
702 switchKobilMode();
703 }
704 if(ModeMap & QUANTA_MODE) {
705 switchQuantaMode();
706 }
707 if(ModeMap & SEQUANS_MODE) {
708 switchSequansMode();
709 }
710 if(ModeMap & MOBILEACTION_MODE) {
711 switchActionMode();
712 }
713 if(ModeMap & CISCO_MODE) {
714 detachDrivers();
715 switchCiscoMode();
716 }
717 if(ModeMap & BLACKBERRY_MODE) {
718 detachDrivers();
719 switchBlackberryMode();
720 }
721 if(ModeMap & PANTECH_MODE) {
722 detachDrivers();
723 if (PantechMode > 1)
724 switchPantechMode();
725 else
726 SHOW_PROGRESS(output,"Waiting for auto-switch of Pantech modem ...\n");
727 }
728 if(ModeMap & SONY_MODE) {
729 if (CheckSuccess)
730 SHOW_PROGRESS(output,"Note: CheckSuccess ignored; Sony mode does separate checks\n");
731 CheckSuccess = 0; /* separate and implied success control */
732 sonySuccess = switchSonyMode();
733 }
734
735 if (StandardEject) {
736 SHOW_PROGRESS(output,"Sending standard EJECT sequence\n");
737 detachDrivers();
738
739 strcpy(Messages[0],"5553424387654321000000000000061e000000000000000000000000000000");
740 strcpy(Messages[1],"5553424397654321000000000000061b000000020000000000000000000000");
741 strcpy(Messages[2],"5553424387654321000000000001061e000000000000000000000000000000");
742 strcpy(Messages[3],"5553424397654321000000000001061b000000020000000000000000000000");
743 if (MessageContent[0] != '\0')
744 strcpy(Messages[4], MessageContent);
745
746 switchSendMessage();
747 } else if (ModeMap & HUAWEINEW_MODE) {
748 SHOW_PROGRESS(output,"Using standard Huawei switching message\n");
749 detachDrivers();
750 strcpy(Messages[0],"55534243123456780000000000000011062000000101000100000000000000");
751 switchSendMessage();
752 } else if (ModeMap & HUAWEIALT_MODE) {
753 SHOW_PROGRESS(output,"Using alternative Huawei switching message\n");
754 detachDrivers();
755 strcpy(Messages[0],"55534243123456780000000000000011063000000000010000000000000000");
756 switchSendMessage();
757 } else if (ModeMap & OPTION_MODE) {
758 SHOW_PROGRESS(output,"Using standard Option switching message\n");
759 detachDrivers();
760 strcpy(Messages[0],"55534243123456780000000000000601000000000000000000000000000000");
761 switchSendMessage();
762 } else if (strlen(MessageContent)) {
763 detachDrivers();
764 strcpy(Messages[0],MessageContent);
765 if (MessageContent2[0] != '\0')
766 strcpy(Messages[1], MessageContent2);
767 if (MessageContent3[0] != '\0')
768 strcpy(Messages[2], MessageContent3);
769 switchSendMessage();
770 }
771
772 if (Configuration > 0) {
773 if (currentConfigVal != Configuration) {
774 if (switchConfiguration()) {
775 currentConfigVal = get_current_config_value(dev);
776 if (currentConfigVal == Configuration) {
777 SHOW_PROGRESS(output,"The configuration was set successfully\n");
778 } else {
779 SHOW_PROGRESS(output,"Changing the configuration has failed\n");
780 }
781 }
782 } else {
783 SHOW_PROGRESS(output,"Target configuration %d already active. Nothing to do. Bye!\n\n", currentConfigVal);
784 close_all();
785 exit(0);
786 }
787 }
788
789 if (AltSetting != -1) {
790 switchAltSetting();
791 }
792
793 /* No "removal" check if these are set */
794 if ((Configuration > 0 || AltSetting > -1) && !ResetUSB) {
795 libusb_close(devh);
796 devh = NULL;
797 }
798
799 if (ResetUSB) {
800 resetUSB();
801 devh = NULL;
802 }
803
804 if (searchMode == SEARCH_BUSDEV && sysmode) {
805 printf("ok:busdev\n");
806 close_all();
807 exit(0);
808 }
809
810 if (CheckSuccess) {
811 if (checkSuccess()) {
812 if (sysmode) {
813 if (NoDriverLoading)
814 printf("ok:\n");
815 else
816 if (TargetProduct < 1)
817 printf("ok:no_data\n");
818 else
819 printf("ok:%04x:%04x\n", TargetVendor, TargetProduct);
820 }
821 } else
822 if (sysmode)
823 printf("fail:\n");
824 } else {
825 if (ModeMap & SONY_MODE)
826 if (sonySuccess) {
827 if (sysmode) {
828 syslog(LOG_NOTICE, "switched S.E. MD400 to modem mode");
829 printf("ok:\n"); /* ACM device, no driver action */
830 }
831 SHOW_PROGRESS(output,"-> device should be stable now. Bye!\n\n");
832 } else {
833 if (sysmode)
834 printf("fail:\n");
835 SHOW_PROGRESS(output,"-> switching was probably not completed. Bye!\n\n");
836 }
837 else
838 SHOW_PROGRESS(output,"-> Run lsusb to note any changes. Bye!\n\n");
839 }
840 close_all();
841 exit(0);
842 }
843
844
845 /* Get descriptor strings if available (identification details) */
deviceDescription()846 void deviceDescription ()
847 {
848 char imanufact[DESCR_MAX], iproduct[DESCR_MAX], iserial[DESCR_MAX];
849 int ret=0;
850 char* c;
851 memset (imanufact, ' ', DESCR_MAX);
852 memset (iproduct, ' ', DESCR_MAX);
853 memset (iserial, ' ', DESCR_MAX);
854
855 struct libusb_device_descriptor descriptor;
856 libusb_get_device_descriptor(dev, &descriptor);
857
858 int iManufacturer = descriptor.iManufacturer;
859 int iProduct = descriptor.iProduct;
860 int iSerialNumber = descriptor.iSerialNumber;
861
862 if (iManufacturer) {
863 ret = libusb_get_string_descriptor_ascii(devh, iManufacturer, (unsigned char *)imanufact, DESCR_MAX);
864 if (ret < 0) {
865 fprintf(stderr, "Error: could not get description string \"manufacturer\"\n");
866 strcpy(imanufact, "read error");
867 }
868 } else
869 strcpy(imanufact, "not provided");
870 c = strstr(imanufact, " ");
871 if (c)
872 memset((void*)c, '\0', 1);
873
874 if (iProduct) {
875 ret = libusb_get_string_descriptor_ascii(devh, iProduct, (unsigned char *)iproduct, DESCR_MAX);
876 if (ret < 0) {
877 fprintf(stderr, "Error: could not get description string \"product\"\n");
878 strcpy(iproduct, "read error");
879 }
880 } else
881 strcpy(iproduct, "not provided");
882 c = strstr(iproduct, " ");
883 if (c)
884 memset((void*)c, '\0', 1);
885
886 if (iSerialNumber) {
887 ret = libusb_get_string_descriptor_ascii(devh, iSerialNumber, (unsigned char *)iserial, DESCR_MAX);
888 if (ret < 0) {
889 fprintf(stderr, "Error: could not get description string \"serial number\"\n");
890 strcpy(iserial, "read error");
891 }
892 } else
893 strcpy(iserial, "not provided");
894 c = strstr(iserial, " ");
895 if (c)
896 memset((void*)c, '\0', 1);
897 fprintf(output,"-------------------------\n");
898 fprintf(output,"Manufacturer: %s\n", imanufact);
899 fprintf(output," Product: %s\n", iproduct);
900 fprintf(output," Serial No.: %s\n", iserial);
901 fprintf(output,"-------------------------\n");
902 }
903
904
905 /* Auxiliary function used by the wrapper */
findMBIMConfig(int vendor,int product,int mode)906 int findMBIMConfig(int vendor, int product, int mode)
907 {
908 struct libusb_device **devs;
909 int resultConfig=0;
910 int i=0, j;
911
912 if (libusb_get_device_list(ctx, &devs) < 0) {
913 perror("Libusb could not access USB. Abort");
914 return 0;
915 }
916
917 SHOW_PROGRESS(output,"Search USB devices ...\n");
918 while ((dev = devs[i++]) != NULL) {
919 struct libusb_device_descriptor descriptor;
920 libusb_get_device_descriptor(dev, &descriptor);
921
922 if (mode == SEARCH_BUSDEV) {
923 if ((libusb_get_bus_number(dev) != busnum) ||
924 (libusb_get_device_address(dev) != devnum)) {
925 continue;
926 } else {
927 if (descriptor.idVendor != vendor)
928 continue;
929 if (product != descriptor.idProduct)
930 continue;
931 }
932 }
933 SHOW_PROGRESS(output,"Found device, search for MBIM configuration...\n");
934
935 // No check if there is only one configuration
936 if (descriptor.bNumConfigurations < 2)
937 return -1;
938
939 // Checking all interfaces of all configurations
940 for (j=0; j<descriptor.bNumConfigurations; j++) {
941 struct libusb_config_descriptor *config;
942
943 libusb_get_config_descriptor(dev, j, &config);
944 resultConfig = config->bConfigurationValue;
945 for (i=0; i<config->bNumInterfaces; i++) {
946 if ( config->interface[i].altsetting[0].bInterfaceClass == 2 )
947 if ( config->interface[i].altsetting[0].bInterfaceSubClass == 0x0e ) {
948 // found MBIM interface in this configuration
949 libusb_free_config_descriptor(config);
950 return resultConfig;
951 }
952 }
953 libusb_free_config_descriptor(config);
954 }
955 return -1;
956 }
957 return 0;
958 }
959
960
resetUSB()961 void resetUSB ()
962 {
963 int success;
964 int bpoint = 0;
965
966 if (!devh) {
967 fprintf(output,"Device handle empty, skip USB reset\n");
968 return;
969 }
970 if (show_progress) {
971 fprintf(output,"Reset USB device ");
972 fflush(output);
973 }
974 sleep( 1 );
975 do {
976 success = libusb_reset_device(devh);
977 if ( ((bpoint % 10) == 0) && show_progress ) {
978 fprintf(output,".");
979 fflush(output);
980 }
981 bpoint++;
982 if (bpoint > 100) {
983 SHOW_PROGRESS(output," Reset USB device failed with error %d", success);
984 fprintf(stderr,"Reset USB device failed with error %d", success);
985 success = 1;
986 }
987 } while (success < 0);
988
989 if ( success == 0 )
990 SHOW_PROGRESS(output,"\n Device was reset\n");
991 }
992
993
switchSendMessage()994 int switchSendMessage ()
995 {
996 const char* cmdHead = "55534243";
997 int ret, i;
998 int retries = 1;
999 /* char* msg[3];
1000 msg[0] = MessageContent;
1001 msg[1] = MessageContent2;
1002 msg[2] = MessageContent3;
1003 */
1004 SHOW_PROGRESS(output,"Set up interface %d\n", Interface);
1005 ret = libusb_claim_interface(devh, Interface);
1006 if (ret != 0) {
1007 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip message sending\n", ret);
1008 return 0;
1009 }
1010
1011 SHOW_PROGRESS(output,"Use endpoint 0x%02x for message sending ...\n", MessageEndpoint);
1012 if (show_progress)
1013 fflush(stdout);
1014
1015 retry:
1016 for (i=0; i<MSG_DIM; i++) {
1017 if ( strlen(Messages[i]) == 0)
1018 break;
1019
1020 if ( sendMessage(Messages[i], i+1) )
1021 goto skip;
1022
1023 if ( strstr(Messages[i],cmdHead) != NULL ) {
1024 // UFI command
1025 SHOW_PROGRESS(output,"Read the response to message %d (CSW) ...\n", i+1);
1026 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1027 if (ret >= 0) {
1028 SHOW_PROGRESS(output,", status %d",ByteString[12]);
1029 }
1030 } /* else {
1031 // Other bulk transfer
1032 SHOW_PROGRESS(output,"Read the response to message %d ...\n", i+1);
1033 ret = read_bulk(ResponseEndpoint, ByteString, strlen(Messages[i])/2 );
1034 }*/
1035 SHOW_PROGRESS(output,"\n");
1036 if (ret == LIBUSB_TRANSFER_STALL && retries--) {
1037 SHOW_PROGRESS(output,"Endpoint stalled. Resetting ...\n");
1038 libusb_clear_halt(devh, MessageEndpoint);
1039 goto retry;
1040 }
1041 if (ret < 0)
1042 goto skip;
1043 }
1044
1045 SHOW_PROGRESS(output,"Reset response endpoint 0x%02x\n", ResponseEndpoint);
1046 ret = libusb_clear_halt(devh, ResponseEndpoint);
1047 if (ret)
1048 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1049 SHOW_PROGRESS(output,"Reset message endpoint 0x%02x\n", MessageEndpoint);
1050 ret = libusb_clear_halt(devh, MessageEndpoint);
1051 if (ret)
1052 SHOW_PROGRESS(output," Could not reset endpoint (probably harmless): %d\n", ret);
1053 usleep(50000);
1054
1055 if (ReleaseDelay) {
1056 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1057 usleep(ReleaseDelay*1000);
1058 }
1059 ret = libusb_release_interface(devh, Interface);
1060 if (ret)
1061 goto skip;
1062 return 1;
1063
1064 skip:
1065 SHOW_PROGRESS(output," Device is gone, skip any further commands\n");
1066 libusb_close(devh);
1067 devh = NULL;
1068 return 2;
1069 }
1070
1071
switchConfiguration()1072 int switchConfiguration ()
1073 {
1074 int ret;
1075
1076 SHOW_PROGRESS(output,"Change configuration to %i ...\n", Configuration);
1077 detachDrivers();
1078 // ret = libusb_set_configuration(devh, -1);
1079 ret = libusb_set_configuration(devh, 0);
1080 if (ret < 0) {
1081 SHOW_PROGRESS(output," Resetting the configuration failed (error %d). Try to continue\n", ret);
1082 } else {
1083 SHOW_PROGRESS(output," Configuration was reset\n");
1084 }
1085 /* Empirically tested wait period, improves reliability of configuration change */
1086 usleep(100000);
1087 ret = libusb_set_configuration(devh, Configuration);
1088 if (ret < 0) {
1089 SHOW_PROGRESS(output," Changing the configuration failed (error %d). Try to continue\n", ret);
1090 return 0;
1091 } else {
1092 SHOW_PROGRESS(output," OK, configuration set\n");
1093 return 1;
1094 }
1095 }
1096
1097
switchAltSetting()1098 int switchAltSetting ()
1099 {
1100 int ret;
1101 SHOW_PROGRESS(output,"Change to alt setting %i ...\n", AltSetting);
1102 ret = libusb_claim_interface(devh, Interface);
1103 if (ret < 0) {
1104 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip AltSetting\n", ret);
1105 return 0;
1106 }
1107 ret = libusb_set_interface_alt_setting(devh, Interface, AltSetting);
1108 libusb_release_interface(devh, Interface);
1109 if (ret < 0) {
1110 SHOW_PROGRESS(output," Change to alt setting returned error %d. Try to continue\n", ret);
1111 return 0;
1112 } else
1113 return 1;
1114 }
1115
1116
switchHuaweiMode()1117 void switchHuaweiMode ()
1118 {
1119 int ret;
1120 SHOW_PROGRESS(output,"Send old Huawei control message ...\n");
1121 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1122 LIBUSB_REQUEST_SET_FEATURE, 00000001, 0, buffer, 0, 1000);
1123
1124 if (ret != 0) {
1125 fprintf(stderr, "Error: Huawei control message failed (error %d). Abort\n\n", ret);
1126 exit(0);
1127 }
1128 }
1129
1130
switchSierraMode()1131 void switchSierraMode ()
1132 {
1133 int ret;
1134 SHOW_PROGRESS(output,"Send Sierra control message\n");
1135 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1136 LIBUSB_REQUEST_SET_INTERFACE, 00000001, 0, buffer, 0, 1000);
1137 if (ret == LIBUSB_ERROR_PIPE) {
1138 SHOW_PROGRESS(output," communication with device stopped. May have switched modes anyway\n");
1139 return;
1140 }
1141 if (ret < 0) {
1142 fprintf(stderr, "Error: Sierra control message failed (error %d). Abort\n\n", ret);
1143 exit(0);
1144 }
1145 }
1146
1147
switchGCTMode()1148 void switchGCTMode ()
1149 {
1150 int ret;
1151 ret = libusb_claim_interface(devh, Interface);
1152 if (ret != 0) {
1153 SHOW_PROGRESS(output," Could not claim interface (error %d). Skip GCT sequence\n", ret);
1154 return;
1155 }
1156 SHOW_PROGRESS(output,"Send GCT control message 1 ...\n type (should be 161/0xA1): %d",
1157 LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN);
1158
1159 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
1160 0xa0, 0, Interface, buffer, 1, 1000);
1161
1162 if (ret < 0) {
1163 SHOW_PROGRESS(output," GCT control message 1 failed (error %d), continue anyway ...\n", ret);
1164 }
1165 SHOW_PROGRESS(output,"Send GCT control message 2 ...\n");
1166 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_IN,
1167 0xfe, 0, Interface, buffer, 1, 1000);
1168
1169 if (ret < 0) {
1170 SHOW_PROGRESS(output," GCT control message 2 failed (error %d). Abort\n\n", ret);
1171 }
1172 libusb_release_interface(devh, Interface);
1173 if (ret < 0)
1174 exit(0);
1175 }
1176
1177
switchKobilMode()1178 void switchKobilMode() {
1179 int ret;
1180 SHOW_PROGRESS(output,"Send Kobil control message ...\n");
1181 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1182 0x88, 0, 0, buffer, 8, 1000);
1183
1184 if (ret < 0) {
1185 fprintf(stderr, "Error: Kobil control message failed (error %d). Abort\n\n", ret);
1186 exit(0);
1187 }
1188 }
1189
1190
switchQisdaMode()1191 void switchQisdaMode () {
1192 int ret;
1193 SHOW_PROGRESS(output,"Sending Qisda control message ...\n");
1194 memcpy(buffer, "\x05\x8c\x04\x08\xa0\xee\x20\x00\x5c\x01\x04\x08\x98\xcd\xea\xbf", 16);
1195 ret = libusb_control_transfer(devh, 0x40, 0x04, 0, 0, buffer, 16, 1000);
1196 if (ret < 0) {
1197 fprintf(stderr, "Error: Qisda control message failed (error %d). Abort\n\n", ret);
1198 exit(0);
1199 }
1200 }
1201
1202
switchQuantaMode()1203 void switchQuantaMode() {
1204 int ret;
1205 SHOW_PROGRESS(output,"Send Quanta control message ...\n");
1206 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1207 0xff, 0, 0, buffer, 0, 1000);
1208
1209 if (ret < 0) {
1210 SHOW_PROGRESS(output,"Error: Quanta control message failed (error %d). Abort\n\n", ret);
1211 exit(0);
1212 }
1213 }
1214
1215
switchBlackberryMode()1216 void switchBlackberryMode ()
1217 {
1218 int ret;
1219 SHOW_PROGRESS(output,"Send Blackberry control message 1 ...\n");
1220 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1221 0xb1, 0x0000, 0, buffer, 8, 1000);
1222
1223 if (ret != 8) {
1224 fprintf(stderr, "Error: Blackberry control message 1 failed (result %d)\n", ret);
1225 }
1226 SHOW_PROGRESS(output,"Send Blackberry control message 2 ...\n");
1227 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_IN,
1228 0xa9, 0x000e, 0, buffer, 2, 1000);
1229
1230 if (ret != 2) {
1231 fprintf(stderr, "Error: Blackberry control message 2 failed (result %d). Abort\n\n", ret);
1232 exit(0);
1233 }
1234 }
1235
1236
switchPantechMode()1237 void switchPantechMode()
1238 {
1239 int ret;
1240 SHOW_PROGRESS(output,"Send Pantech control message, wValue %d ...\n", PantechMode);
1241 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE | LIBUSB_ENDPOINT_OUT,
1242 0x70, PantechMode, 0, buffer, 0, 1000);
1243
1244 if (ret < 0) {
1245 SHOW_PROGRESS(output," Error: Pantech control message failed (error %d). Abort\n\n", ret);
1246 exit(0);
1247 }
1248 }
1249
1250
1251 #define EP_OUT 0x02
1252 #define EP_IN 0x81
1253 #define SIZE 0x08
1254
1255 #define MOBILE_ACTION_READLOOP1 63
1256 #define MOBILE_ACTION_READLOOP2 73
1257
1258 /* The code here is statically derived from sniffing (and confirmed working).
1259 * However, I bet it could be simplified significantly.
1260 */
1261
switchActionMode()1262 void switchActionMode ()
1263 {
1264 int ret, i;
1265 SHOW_PROGRESS(output,"Send MobileAction control sequence ...\n");
1266 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1267 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
1268 0x09, 0x0300, 0, buffer, SIZE, 1000);
1269
1270 memcpy(buffer, "\xb0\x04\x00\x00\x02\x90\x26\x86", SIZE);
1271 libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_CLASS | LIBUSB_RECIPIENT_INTERFACE | LIBUSB_ENDPOINT_OUT,
1272 0x09, 0x0300, 0, buffer, SIZE, 1000);
1273
1274 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1275 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1276 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1277 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1278 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1279 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1280 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1281 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1282 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1283 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1284 for (i=0; i < MOBILE_ACTION_READLOOP1; i++) {
1285 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1286 }
1287 memcpy(buffer, "\x37\x01\xfe\xdb\xc1\x33\x1f\x83", SIZE);
1288 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1289 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1290 memcpy(buffer, "\x37\x0e\xb5\x9d\x3b\x8a\x91\x51", SIZE);
1291 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1292 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1293 memcpy(buffer, "\x34\x87\xba\x0d\xfc\x8a\x91\x51", SIZE);
1294 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1295 for (i=0; i < MOBILE_ACTION_READLOOP2; i++) {
1296 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1297 }
1298 memcpy(buffer, "\x33\x04\xfe\x00\xf4\x6c\x1f\xf0", SIZE);
1299 usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1300 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1301 memcpy(buffer, "\x32\x07\xfe\xf0\x29\xb9\x3a\xf0", SIZE);
1302 ret = usb_interrupt_io(devh, EP_OUT, buffer, SIZE, 1000);
1303 usb_interrupt_io(devh, EP_IN, buffer, SIZE, 1000);
1304 if (ret < 0) {
1305 SHOW_PROGRESS(output," MobileAction control sequence did not complete\n"
1306 " Last error was %d\n",ret);
1307 } else {
1308 SHOW_PROGRESS(output," MobileAction control sequence complete\n");
1309 }
1310 }
1311
1312
1313 #define SQN_SET_DEVICE_MODE_REQUEST 0x0b
1314 #define SQN_GET_DEVICE_MODE_REQUEST 0x0a
1315
1316 #define SQN_DEFAULT_DEVICE_MODE 0x00
1317 #define SQN_MASS_STORAGE_MODE 0x01
1318 #define SQN_CUSTOM_DEVICE_MODE 0x02
1319
switchSequansMode()1320 void switchSequansMode()
1321 {
1322
1323 int ret;
1324 SHOW_PROGRESS(output,"Send Sequans control message\n");
1325 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1326 | LIBUSB_ENDPOINT_OUT, SQN_SET_DEVICE_MODE_REQUEST, SQN_CUSTOM_DEVICE_MODE,
1327 0, buffer, 0, 1000);
1328
1329 if (ret < 0) {
1330 fprintf(stderr, "Error: Sequans request failed (error %d). Abort\n\n", ret);
1331 exit(0);
1332 }
1333 }
1334
1335
switchCiscoMode()1336 void switchCiscoMode()
1337 {
1338 int ret, i, j;
1339
1340 strcpy(Messages[0],"55534243f83bcd810002000080000afd000000030000000100000000000000");
1341 strcpy(Messages[1],"55534243984300820002000080000afd000000070000000100000000000000");
1342 strcpy(Messages[2],"55534243984300820000000000000afd000100071000000000000000000000");
1343 strcpy(Messages[3],"55534243984300820002000080000afd000200230000000100000000000000");
1344 strcpy(Messages[4],"55534243984300820000000000000afd000300238200000000000000000000");
1345 strcpy(Messages[5],"55534243984300820002000080000afd000200260000000100000000000000");
1346 strcpy(Messages[6],"55534243984300820000000000000afd00030026c800000000000000000000");
1347 strcpy(Messages[7],"55534243d84c04820002000080000afd000010730000000100000000000000");
1348 strcpy(Messages[8],"55534243d84c04820002000080000afd000200240000000100000000000000");
1349 strcpy(Messages[9],"55534243d84c04820000000000000afd000300241300000000000000000000");
1350 strcpy(Messages[10],"55534243d84c04820000000000000afd000110732400000000000000000000");
1351
1352 SHOW_PROGRESS(output,"Set up Cisco interface %d\n", Interface);
1353 ret = libusb_claim_interface(devh, Interface);
1354 if (ret < 0) {
1355 SHOW_PROGRESS(output," Could not claim interface (error %d). Abort\n", ret);
1356 abortExit();
1357 }
1358 if (show_progress)
1359 fflush(output);
1360
1361 // ret = read_bulk(ResponseEndpoint, ByteString, 13);
1362 // SHOW_PROGRESS(output," Extra response (CSW) read, result %d\n",ret);
1363
1364 for (i=0; i<11; i++) {
1365 if ( sendMessage(Messages[i], i+1) )
1366 goto skip;
1367
1368 for (j=1; j<4; j++) {
1369
1370 SHOW_PROGRESS(output," Read the CSW for bulk message %d (attempt %d) ...\n",i+1,j);
1371 ret = read_bulk(ResponseEndpoint, ByteString, 13);
1372 SHOW_PROGRESS(output,"\n");
1373
1374 if (ret < 0)
1375 goto skip;
1376 if (ret == 13)
1377 break;
1378 }
1379 }
1380 libusb_clear_halt(devh, MessageEndpoint);
1381 libusb_clear_halt(devh, ResponseEndpoint);
1382
1383 ReleaseDelay = 2000;
1384 SHOW_PROGRESS(output,"Wait for %d ms before releasing interface ...\n", ReleaseDelay);
1385 usleep(ReleaseDelay*1000);
1386
1387 ret = libusb_release_interface(devh, Interface);
1388 if (ret < 0)
1389 goto skip;
1390 return;
1391
1392 skip:
1393 SHOW_PROGRESS(output,"Device returned error %d, skip further commands\n", ret);
1394 libusb_close(devh);
1395 devh = NULL;
1396 }
1397
1398
switchSonyMode()1399 int switchSonyMode ()
1400 {
1401 int ret, i, found;
1402 detachDrivers();
1403
1404 if (CheckSuccess) {
1405 CheckSuccess = 0;
1406 }
1407
1408 SHOW_PROGRESS(output,"Send Sony control message\n");
1409 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1410 | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100);
1411
1412 if (ret < 0) {
1413 fprintf(stderr, "Error: Sony control message failed (error %d). Abort\n\n", ret);
1414 exit(0);
1415 } else
1416 SHOW_PROGRESS(output," OK, control message sent, wait for device to return ...\n");
1417
1418 libusb_close(devh);
1419 devh = NULL;
1420
1421 /* Now waiting for the device to reappear */
1422 devnum=-1;
1423 busnum=-1;
1424 i=0;
1425 dev = 0;
1426 while ( dev == 0 && i < 30 ) {
1427 if ( i > 5 ) {
1428 dev = search_devices(&found, DefaultVendor, DefaultProductList, TargetClass,
1429 0, SEARCH_TARGET);
1430 }
1431 if ( dev != 0 )
1432 break;
1433 sleep(1);
1434 if (show_progress) {
1435 fprintf(output,"#");
1436 fflush(stdout);
1437 }
1438 i++;
1439 }
1440 SHOW_PROGRESS(output,"\n After %d seconds:",i);
1441 if ( dev ) {
1442 SHOW_PROGRESS(output," device came back, proceed\n");
1443 libusb_open(dev, &devh);
1444 if (devh == 0) {
1445 fprintf(stderr, "Error: could not get handle on device\n");
1446 return 0;
1447 }
1448 } else {
1449 SHOW_PROGRESS(output," device still gone, abort\n");
1450 return 0;
1451 }
1452 sleep(1);
1453
1454 SHOW_PROGRESS(output,"Send Sony control message again ...\n");
1455 ret = libusb_control_transfer(devh, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE
1456 | LIBUSB_ENDPOINT_IN, 0x11, 2, 0, buffer, 3, 100);
1457
1458 if (ret < 0) {
1459 fprintf(stderr, "Error: Sony control message (2) failed (error %d)\n", ret);
1460 return 0;
1461 }
1462 SHOW_PROGRESS(output," OK, control message sent\n");
1463 return 1;
1464 }
1465
1466
1467 /* Detach driver
1468 */
detachDrivers()1469 int detachDrivers()
1470 {
1471 int i, ret;
1472 SHOW_PROGRESS(output,"Looking for active drivers ...\n");
1473 ret = libusb_kernel_driver_active(devh, 0);
1474 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1475 fprintf(output," Can't do driver detection on this platform.\n");
1476 return 2;
1477 }
1478
1479 struct libusb_config_descriptor *config;
1480 libusb_get_active_config_descriptor(dev, &config);
1481
1482 for (i=0; i<config->bNumInterfaces; i++) {
1483 ret = libusb_kernel_driver_active(devh, i);
1484 if (ret < 0) {
1485 SHOW_PROGRESS(output," Failed to check driver status for interface %d (error %d)\n Try to continue\n",i,ret);
1486 continue;
1487 }
1488 if (ret) {
1489 ret = libusb_detach_kernel_driver(devh, i);
1490 if (ret == LIBUSB_ERROR_NOT_SUPPORTED) {
1491 fprintf(output," Can't do driver detaching on this platform.\n");
1492 return 2;
1493 }
1494 if (ret == 0) {
1495 SHOW_PROGRESS(output," OK, driver detached\n");
1496 } else {
1497 SHOW_PROGRESS(output," Driver detach failed for interface %d (error %d).\n Try to continue\n",i,ret);
1498 continue;
1499 }
1500 }
1501 }
1502 libusb_free_config_descriptor(config);
1503 return 1;
1504 }
1505
1506
sendMessage(char * message,int count)1507 int sendMessage(char* message, int count)
1508 {
1509 int ret, message_length;
1510
1511 if (strlen(message) % 2 != 0) {
1512 fprintf(stderr, "Error: MessageContent %d hex string has uneven length. Skipping ...\n", count);
1513 return 1;
1514 }
1515 message_length = strlen(message) / 2;
1516 if ( hexstr2bin(message, ByteString, message_length) == -1) {
1517 fprintf(stderr, "Error: MessageContent %d %s\n is not a hex string. Skipping ...\n",
1518 count, MessageContent);
1519
1520 return 1;
1521 }
1522 SHOW_PROGRESS(output,"Trying to send message %d to endpoint 0x%02x ...\n", count, MessageEndpoint);
1523 fflush(output);
1524 ret = write_bulk(MessageEndpoint, ByteString, message_length);
1525 if (ret == LIBUSB_ERROR_NO_DEVICE)
1526 return 1;
1527
1528 return 0;
1529 }
1530
1531
checkSuccess()1532 int checkSuccess()
1533 {
1534 int ret, i;
1535 int newTargetCount, success=0;
1536
1537 SHOW_PROGRESS(output,"\nCheck for mode switch (max. %d times, once per second) ...\n", CheckSuccess);
1538 sleep(1);
1539
1540 /* If target parameters are given, don't check for vanished device
1541 * Changed for Cisco AM10 where a new device is added while the install
1542 * storage device stays active
1543 */
1544 if ((TargetVendor || TargetClass) && devh) {
1545 libusb_close(devh);
1546 devh = NULL;
1547 }
1548
1549 /* if target ID is not given but target class is, assign default as target;
1550 * it will be needed for sysmode output
1551 */
1552 if (!TargetVendor && TargetClass) {
1553 TargetVendor = DefaultVendor;
1554 TargetProduct = DefaultProduct;
1555 }
1556
1557 /* devh is 0 if device vanished during command transmission or if target params were given
1558 */
1559 if (devh)
1560 for (i=0; i < CheckSuccess; i++) {
1561
1562 /* Test if default device still can be accessed; positive result does
1563 * not necessarily mean failure
1564 */
1565 SHOW_PROGRESS(output," Wait for original device to vanish ...\n");
1566
1567 ret = libusb_claim_interface(devh, Interface);
1568 libusb_release_interface(devh, Interface);
1569 if (ret < 0) {
1570 SHOW_PROGRESS(output," Original device can't be accessed anymore. Good.\n");
1571 libusb_close(devh);
1572 devh = NULL;
1573 break;
1574 }
1575 if (i == CheckSuccess-1) {
1576 SHOW_PROGRESS(output," Original device still present after the timeout\n\n"
1577 "Mode switch most likely failed. Bye!\n\n");
1578 } else
1579 sleep(1);
1580 }
1581
1582 if ( TargetVendor && (TargetProduct > -1 || TargetProductList[0] != '\0') ) {
1583
1584 /* Recount target devices (compare with previous count) if target data is given.
1585 * Target device on the same bus with higher device number is returned,
1586 * description is read for syslog message
1587 */
1588 // Wait counter passed on from previous loop
1589 for (i=i; i < CheckSuccess; i++) {
1590 SHOW_PROGRESS(output," Search for target devices ...\n");
1591 dev = search_devices(&newTargetCount, TargetVendor, TargetProductList,
1592 TargetClass, 0, SEARCH_TARGET);
1593
1594 if (dev && (newTargetCount > targetDeviceCount)) {
1595 if (verbose) {
1596 libusb_open(dev, &devh);
1597 fprintf(output,"\nFound target device %03d on bus %03d\n",
1598 libusb_get_device_address(dev), libusb_get_bus_number(dev));
1599
1600 fprintf(output,"\nTarget device description data\n");
1601 deviceDescription();
1602 libusb_close(devh);
1603 devh = NULL;
1604 }
1605 SHOW_PROGRESS(output," Found correct target device\n\n"
1606 "Mode switch succeeded. Bye!\n\n");
1607
1608 success = 2;
1609 break;
1610 }
1611 if (i == CheckSuccess-1) {
1612 SHOW_PROGRESS(output," No new devices in target mode or class found\n\n"
1613 "Mode switch has failed. Bye!\n\n");
1614 } else
1615 sleep(1);
1616 }
1617 } else
1618 /* No target data given, rely on the vanished device */
1619 if (!devh) {
1620 SHOW_PROGRESS(output," (For a better success check provide target IDs or class)\n");
1621 SHOW_PROGRESS(output," Original device vanished after switching\n\n"
1622 "Mode switch most likely succeeded. Bye!\n\n");
1623 success = 1;
1624 }
1625
1626 switch (success) {
1627 case 2:
1628 if (sysmode)
1629 syslog(LOG_NOTICE, "switched to %04x:%04x on %03d/%03d", TargetVendor,
1630 TargetProduct, busnum, devnum);
1631
1632 success = 1;
1633 break;
1634 case 1:
1635 if (sysmode)
1636 syslog(LOG_NOTICE, "device seems to have switched");
1637 default:
1638 ;
1639 }
1640 if (sysmode)
1641 closelog();
1642
1643 return success;
1644
1645 }
1646
1647
write_bulk(int endpoint,unsigned char * message,int length)1648 int write_bulk(int endpoint, unsigned char *message, int length)
1649 {
1650 int ret = usb_bulk_io(devh, endpoint, message, length, 3000);
1651 if (ret >= 0 ) {
1652 SHOW_PROGRESS(output," OK, message successfully sent\n");
1653 } else
1654 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1655 SHOW_PROGRESS(output," Device seems to have vanished right after sending. Good.\n");
1656 } else
1657 SHOW_PROGRESS(output," Sending the message returned error %d. Try to continue\n", ret);
1658 return ret;
1659 }
1660
1661
read_bulk(int endpoint,unsigned char * buffer,int length)1662 int read_bulk(int endpoint, unsigned char *buffer, int length)
1663 {
1664 int ret = usb_bulk_io(devh, endpoint, buffer, length, 3000);
1665 if (ret >= 0 ) {
1666 SHOW_PROGRESS(output," Response successfully read (%d bytes)", ret);
1667 } else
1668 if (ret == LIBUSB_ERROR_NO_DEVICE) {
1669 SHOW_PROGRESS(output," Device seems to have vanished after reading. Good.");
1670 } else
1671 SHOW_PROGRESS(output," Response reading failed (error %d)", ret);
1672 return ret;
1673 }
1674
1675
release_usb_device(int placeholder)1676 void release_usb_device(int __attribute__((unused)) placeholder)
1677 {
1678 SHOW_PROGRESS(output,"Program cancelled by system. Bye!\n\n");
1679 if (devh)
1680 libusb_release_interface(devh, Interface);
1681 close_all();
1682 exit(0);
1683 }
1684
1685
1686 /* Iterates over buses and devices, counts the ones which match the given
1687 * parameters and returns the last one of them
1688 */
search_devices(int * numFound,int vendor,char * productList,int targetClass,int configuration,int mode)1689 struct libusb_device* search_devices( int *numFound, int vendor, char* productList,
1690 int targetClass, int configuration, int mode)
1691 {
1692 char *listcopy=NULL, *token;
1693 unsigned char buffer[2];
1694 int devClass, product;
1695 struct libusb_device* right_dev = NULL;
1696 struct libusb_device **devs;
1697 int i=0;
1698
1699 /* only target class given, target vendor and product assumed unchanged */
1700 if ( targetClass && !(vendor || strlen(productList)) ) {
1701 vendor = DefaultVendor;
1702 productList = DefaultProductList;
1703 }
1704 *numFound = 0;
1705
1706 /* Validity check */
1707 if (!vendor || *productList == '\0')
1708 return NULL;
1709
1710 if (libusb_get_device_list(ctx, &devs) < 0) {
1711 perror("Libusb failed to get USB access!");
1712 return 0;
1713 }
1714
1715 listcopy = malloc(strlen(productList)+1);
1716
1717 while ((dev = devs[i++]) != NULL) {
1718 struct libusb_device_descriptor descriptor;
1719 libusb_get_device_descriptor(dev, &descriptor);
1720
1721 if (mode == SEARCH_BUSDEV) {
1722 if ((libusb_get_bus_number(dev) != busnum) ||
1723 (libusb_get_device_address(dev) != devnum))
1724 continue;
1725 else
1726 SHOW_PROGRESS(output," bus/device number matched\n");
1727 }
1728
1729 if (verbose)
1730 fprintf (output," found USB ID %04x:%04x\n",
1731 descriptor.idVendor, descriptor.idProduct);
1732 if (descriptor.idVendor != vendor)
1733 continue;
1734 if (verbose)
1735 fprintf (output," vendor ID matched\n");
1736
1737 strcpy(listcopy, productList);
1738 token = strtok(listcopy, ",");
1739 while (token != NULL) {
1740 if (strlen(token) != 4) {
1741 SHOW_PROGRESS(output,"Error: entry in product ID list has wrong length: %s. "
1742 "Ignored\n", token);
1743
1744 goto NextToken;
1745 }
1746 if ( hexstr2bin(token, buffer, strlen(token)/2) == -1) {
1747 SHOW_PROGRESS(output,"Error: entry in product ID list is not a hex string: %s. "
1748 "Ignored\n", token);
1749
1750 goto NextToken;
1751 }
1752 product = 0;
1753 product += (unsigned char)buffer[0];
1754 product <<= 8;
1755 product += (unsigned char)buffer[1];
1756 if (product == descriptor.idProduct) {
1757 if (verbose)
1758 fprintf(output," product ID matched\n");
1759
1760 if (targetClass != 0) {
1761 /* TargetClass is set, check class of first interface */
1762 struct libusb_device_descriptor descriptor;
1763 libusb_get_device_descriptor(dev, &descriptor);
1764 devClass = descriptor.bDeviceClass;
1765 struct libusb_config_descriptor *config;
1766 libusb_get_config_descriptor(dev, 0, &config);
1767 int ifaceClass = config->interface[0].altsetting[0].bInterfaceClass;
1768 libusb_free_config_descriptor(config);
1769 if (devClass == 0)
1770 devClass = ifaceClass;
1771 else
1772 /* Check for some quirky devices */
1773 if (devClass != ifaceClass)
1774 devClass = ifaceClass;
1775 if (devClass == targetClass) {
1776 if (verbose)
1777 fprintf (output," target class %02x matches\n", targetClass);
1778 if (mode == SEARCH_TARGET) {
1779 (*numFound)++;
1780 right_dev = dev;
1781 if (verbose)
1782 fprintf (output," count device\n");
1783 } else
1784 if (verbose)
1785 fprintf (output," device not counted, target class reached\n");
1786 } else {
1787 if (verbose)
1788 fprintf (output," device class %02x not matching target\n", devClass);
1789 if (mode == SEARCH_DEFAULT || mode == SEARCH_BUSDEV) {
1790 (*numFound)++;
1791 right_dev = dev;
1792 if (verbose)
1793 fprintf (output," count device\n");
1794 }
1795 }
1796 } else {
1797 /* Neither TargetClass nor Configuration are set */
1798 (*numFound)++;
1799 right_dev = dev;
1800 if (mode == SEARCH_BUSDEV)
1801 break;
1802 }
1803 }
1804
1805 NextToken:
1806 token = strtok(NULL, ",");
1807 }
1808 }
1809 if (listcopy != NULL)
1810 free(listcopy);
1811 return right_dev;
1812 }
1813
1814
1815 /* Autodetect bulk endpoints (ab) */
1816
find_first_bulk_endpoint(int direction)1817 int find_first_bulk_endpoint(int direction)
1818 {
1819 int i, j;
1820 const struct libusb_interface_descriptor *alt;
1821 const struct libusb_endpoint_descriptor *ep;
1822
1823 for (j=0; j < active_config->bNumInterfaces; j++) {
1824 alt = &(active_config->interface[j].altsetting[0]);
1825 if (alt->bInterfaceNumber == Interface) {
1826 for (i=0; i < alt->bNumEndpoints; i++) {
1827 ep = &(alt->endpoint[i]);
1828 if ( ( (ep->bmAttributes & LIBUSB_ENDPOINT_ADDRESS_MASK) == LIBUSB_TRANSFER_TYPE_BULK)
1829 && ( (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == direction ) ) {
1830
1831 return ep->bEndpointAddress;
1832 }
1833 }
1834 }
1835 }
1836 return 0;
1837 }
1838
1839
get_current_config_value()1840 int get_current_config_value()
1841 {
1842 SHOW_PROGRESS(output,"Get the current device configuration ...\n");
1843 if (active_config != NULL) {
1844 libusb_free_config_descriptor(active_config);
1845 active_config = NULL;
1846 }
1847 int ret = libusb_get_active_config_descriptor(dev, &active_config);
1848 if (ret < 0) {
1849 SHOW_PROGRESS(output," Determining the active configuration failed (error %d). Abort\n", ret);
1850 abortExit();
1851 }
1852 return active_config->bConfigurationValue;
1853 }
1854
1855
get_interface_class()1856 int get_interface_class()
1857 {
1858 int i;
1859 for (i=0; i < active_config->bNumInterfaces; i++) {
1860 if (active_config->interface[i].altsetting[0].bInterfaceNumber == Interface)
1861 return active_config->interface[i].altsetting[0].bInterfaceClass;
1862 }
1863 return -1;
1864 }
1865
1866
1867 /* Parameter parsing */
1868
ReadParseParam(const char * FileName,char * VariableName)1869 char* ReadParseParam(const char* FileName, char *VariableName)
1870 {
1871 static int numLines = 0;
1872 static char* ConfigBuffer[MAXLINES];
1873 char *VarName, *Comment=NULL, *Equal=NULL;
1874 char *FirstQuote, *LastQuote, *P1, *P2;
1875 int Line=0;
1876 unsigned Len=0, Pos=0;
1877 static char Str[LINE_DIM];
1878 char *token, *configPos;
1879 FILE *file = NULL;
1880
1881 // Reading and storing input during the first call
1882 if (numLines==0) {
1883 if (strncmp(FileName,"##",2) == 0) {
1884 if (verbose) fprintf(output,"\nRead long config from command line\n");
1885 // "Embedded" configuration data
1886 configPos = (char*)FileName;
1887 token = strtok(configPos, "\n");
1888 strncpy(Str,token,LINE_DIM-1);
1889 } else {
1890 if (strcmp(FileName, "stdin")==0) {
1891 if (verbose) fprintf(output,"\nRead long config from stdin\n");
1892 file = stdin;
1893 } else {
1894 if (verbose) fprintf(output,"\nRead config file: %s\n", FileName);
1895 file=fopen(FileName, "r");
1896 }
1897 if (file==NULL) {
1898 fprintf(stderr, "Error: Could not find file %s. Abort\n\n", FileName);
1899 abortExit();
1900 } else {
1901 token = fgets(Str, LINE_DIM-1, file);
1902 }
1903 }
1904 while (token != NULL && numLines < MAXLINES) {
1905 Len=strlen(Str);
1906 if (Len==0)
1907 goto NextLine;
1908 if (Str[Len-1]=='\n' or Str[Len-1]=='\r')
1909 Str[--Len]='\0';
1910 Equal = strchr (Str, '='); // search for equal sign
1911 Pos = strcspn (Str, ";#!"); // search for comment
1912 Comment = (Pos==Len) ? NULL : Str+Pos;
1913 if (Equal==NULL or ( Comment!=NULL and Comment<=Equal))
1914 goto NextLine; // Comment or irrelevant, don't save
1915 Len=strlen(Str)+1;
1916 ConfigBuffer[numLines] = malloc(Len*sizeof(char));
1917 strcpy(ConfigBuffer[numLines],Str);
1918 numLines++;
1919 NextLine:
1920 if (file == NULL) {
1921 token = strtok(NULL, "\n");
1922 if (token != NULL)
1923 strncpy(Str,token,LINE_DIM-1);
1924 } else
1925 token = fgets(Str, LINE_DIM-1, file);
1926 }
1927 if (file != NULL)
1928 fclose(file);
1929 }
1930
1931 // Now checking for parameters
1932 Line=0;
1933 while (Line < numLines) {
1934 strcpy(Str,ConfigBuffer[Line]);
1935 Equal = strchr (Str, '='); // search for equal sign
1936 *Equal++ = '\0';
1937
1938 // String
1939 FirstQuote=strchr (Equal, '"'); // search for double quote char
1940 LastQuote=strrchr (Equal, '"');
1941 if (FirstQuote!=NULL) {
1942 if (LastQuote==NULL) {
1943 fprintf(stderr, "Error reading parameters from file %s - "
1944 "Missing end quote:\n%s\n", FileName, Str);
1945
1946 goto Next;
1947 }
1948 *FirstQuote=*LastQuote='\0';
1949 Equal=FirstQuote+1;
1950 }
1951
1952 // removes leading/trailing spaces
1953 Pos=strspn (Str, " \t");
1954 if (Pos==strlen(Str)) {
1955 fprintf(stderr, "Error reading parameters from file %s - "
1956 "Missing variable name:\n%s\n", FileName, Str);
1957
1958 goto Next;
1959 }
1960 while ((P1=strrchr(Str, ' '))!=NULL or (P2=strrchr(Str, '\t'))!=NULL)
1961 if (P1!=NULL) *P1='\0';
1962 else if (P2!=NULL) *P2='\0';
1963 VarName=Str+Pos;
1964
1965 Pos=strspn (Equal, " \t");
1966 if (Pos==strlen(Equal)) {
1967 fprintf(stderr, "Error reading parameter from file %s - "
1968 "Missing value:\n%s\n", FileName, Str);
1969
1970 goto Next;
1971 }
1972 Equal+=Pos;
1973
1974 if (strcmp(VarName, VariableName)==0) { // Found it
1975 return Equal;
1976 }
1977 Next:
1978 Line++;
1979 }
1980
1981 return NULL;
1982 }
1983
1984
hex2num(char c)1985 int hex2num(char c)
1986 {
1987 if (c >= '0' && c <= '9')
1988 return c - '0';
1989 if (c >= 'a' && c <= 'f')
1990 return c - 'a' + 10;
1991 if (c >= 'A' && c <= 'F')
1992 return c - 'A' + 10;
1993 return -1;
1994 }
1995
1996
hex2byte(const char * hex)1997 int hex2byte(const char *hex)
1998 {
1999 int a, b;
2000 a = hex2num(*hex++);
2001 if (a < 0)
2002 return -1;
2003 b = hex2num(*hex++);
2004 if (b < 0)
2005 return -1;
2006 return (a << 4) | b;
2007 }
2008
2009
hexstr2bin(const char * hex,unsigned char * buffer,int len)2010 int hexstr2bin(const char *hex, unsigned char *buffer, int len)
2011 {
2012 int i;
2013 int a;
2014 const char *ipos = hex;
2015 unsigned char *opos = buffer;
2016
2017 for (i = 0; i < len; i++) {
2018 a = hex2byte(ipos);
2019 if (a < 0)
2020 return -1;
2021 *opos++ = (unsigned char) a;
2022 ipos += 2;
2023 }
2024 return 0;
2025 }
2026
2027
close_all()2028 void close_all()
2029 {
2030 int i;
2031 if (Messages) {
2032 for ( i = 0; i < MSG_DIM; i++ ) {
2033 free(Messages[i]);
2034 }
2035 free(Messages);
2036 }
2037 if (active_config)
2038 libusb_free_config_descriptor(active_config);
2039 if (devh)
2040 libusb_close(devh);
2041 // libusb_exit will crash on Raspbian 7, crude protection
2042 #ifndef __ARMEL__
2043 if (ctx)
2044 libusb_exit(NULL);
2045 #endif
2046 if (sysmode)
2047 closelog();
2048 }
2049
2050
abortExit()2051 void abortExit()
2052 {
2053 fflush(output);
2054 fflush(stderr);
2055 close_all();
2056 exit(1);
2057 }
2058
2059
printVersion()2060 void printVersion()
2061 {
2062 char* version = VERSION;
2063 fprintf(output,"\n * usb_modeswitch: handle USB devices with multiple modes\n"
2064 " * Version %s (C) Josua Dietze 2017\n"
2065 " * Based on libusb1/libusbx\n\n"
2066 " ! PLEASE REPORT NEW CONFIGURATIONS !\n\n", version);
2067 }
2068
2069
printHelp()2070 void printHelp()
2071 {
2072 fprintf(output,"\nUsage: usb_modeswitch [<params>] [-c filename]\n\n"
2073 " -h, --help this help\n"
2074 " -e, --version print version information and exit\n"
2075 " -j, --find-mbim return config no. with MBIM interface, exit\n\n"
2076 " -v, --default-vendor NUM vendor ID of original mode (mandatory)\n"
2077 " -p, --default-product NUM product ID of original mode (mandatory)\n"
2078 " -V, --target-vendor NUM target mode vendor ID (optional)\n"
2079 " -P, --target-product NUM target mode product ID (optional)\n"
2080 " -C, --target-class NUM target mode device class (optional)\n"
2081 " -b, --bus-num NUM system bus number of device (for hard ID)\n"
2082 " -g, --device-num NUM system device number (for hard ID)\n"
2083 " -m, --message-endpoint NUM direct the message transfer there (optional)\n"
2084 " -M, --message-content <msg> message to send (hex number as string)\n"
2085 " -2, --message-content2 <msg>\n"
2086 " -3, --message-content3 <msg> additional messages to send if needed\n"
2087 " -w, --release-delay <msecs> wait a while before releasing the interface\n"
2088 " -n, --need-response obsolete, no effect (always on)\n"
2089 " -r, --response-endpoint NUM read response from there (optional)\n"
2090 " -K, --std-eject send standard EJECT sequence\n"
2091 " -d, --detach-only detach the active driver, no further action\n"
2092 " -H, --huawei-mode apply a special procedure\n"
2093 " -J, --huawei-new-mode apply a special procedure\n"
2094 " -X, --huawei-alt-mode apply a special procedure\n"
2095 " -S, --sierra-mode apply a special procedure\n"
2096 " -O, --sony-mode apply a special procedure\n"
2097 " -G, --gct-mode apply a special procedure\n"
2098 " -N, --sequans-mode apply a special procedure\n"
2099 " -A, --mobileaction-mode apply a special procedure\n"
2100 " -T, --kobil-mode apply a special procedure\n"
2101 " -L, --cisco-mode apply a special procedure\n"
2102 " -B, --qisda-mode apply a special procedure\n"
2103 " -E, --quanta-mode apply a special procedure\n"
2104 " -F, --pantech-mode NUM apply a special procedure, pass NUM through\n"
2105 " -Z, --blackberry-mode apply a special procedure\n"
2106 " -U, --option-mode apply a special procedure\n"
2107 " -R, --reset-usb reset the device after all other actions\n"
2108 " -Q, --quiet don't show progress or error messages\n"
2109 " -W, --verbose print all settings and debug output\n"
2110 " -D, --sysmode specific result and syslog message\n"
2111 " -s, --check-success <seconds> check switching result, with timeout\n"
2112 " -I, --inquire obsolete, no effect\n\n"
2113 " -c, --config-file <filename> load long configuration from file\n\n"
2114 " -t, --stdinput read long configuration from stdin\n\n"
2115 " -f, --long-config <text> get long configuration from string\n\n"
2116 " -i, --interface NUM select initial USB interface (default 0)\n"
2117 " -u, --configuration NUM select USB configuration\n"
2118 " -a, --altsetting NUM select alternative USB interface setting\n\n");
2119 }
2120