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