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