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