| OLD | NEW |
| (Empty) | |
| 1 /* |
| 2 * xusb: Generic USB test program |
| 3 * Copyright © 2009-2012 Pete Batard <pete@akeo.ie> |
| 4 * Contributions to Mass Storage by Alan Stern. |
| 5 * |
| 6 * This library is free software; you can redistribute it and/or |
| 7 * modify it under the terms of the GNU Lesser General Public |
| 8 * License as published by the Free Software Foundation; either |
| 9 * version 2.1 of the License, or (at your option) any later version. |
| 10 * |
| 11 * This library is distributed in the hope that it will be useful, |
| 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 * Lesser General Public License for more details. |
| 15 * |
| 16 * You should have received a copy of the GNU Lesser General Public |
| 17 * License along with this library; if not, write to the Free Software |
| 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| 19 */ |
| 20 |
| 21 #include <stdio.h> |
| 22 #include <stdint.h> |
| 23 #include <stdlib.h> |
| 24 #include <string.h> |
| 25 #include <stdarg.h> |
| 26 |
| 27 #include "libusb.h" |
| 28 |
| 29 #if defined(_WIN32) |
| 30 #define msleep(msecs) Sleep(msecs) |
| 31 #else |
| 32 #include <unistd.h> |
| 33 #define msleep(msecs) usleep(1000*msecs) |
| 34 #endif |
| 35 |
| 36 #if !defined(bool) |
| 37 #define bool int |
| 38 #endif |
| 39 #if !defined(true) |
| 40 #define true (1 == 1) |
| 41 #endif |
| 42 #if !defined(false) |
| 43 #define false (!true) |
| 44 #endif |
| 45 |
| 46 // Future versions of libusbx will use usb_interface instead of interface |
| 47 // in libusb_config_descriptor => catter for that |
| 48 #define usb_interface interface |
| 49 |
| 50 // Global variables |
| 51 bool binary_dump = false; |
| 52 bool extra_info = false; |
| 53 const char* binary_name = NULL; |
| 54 |
| 55 static int perr(char const *format, ...) |
| 56 { |
| 57 va_list args; |
| 58 int r; |
| 59 |
| 60 va_start (args, format); |
| 61 r = vfprintf(stderr, format, args); |
| 62 va_end(args); |
| 63 |
| 64 return r; |
| 65 } |
| 66 |
| 67 #define ERR_EXIT(errcode) do { perr(" %s\n", libusb_strerror((enum libusb_erro
r)errcode)); return -1; } while (0) |
| 68 #define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0); |
| 69 #define B(x) (((x)!=0)?1:0) |
| 70 #define be_to_int32(buf) (((buf)[0]<<24)|((buf)[1]<<16)|((buf)[2]<<8)|(buf)[3]) |
| 71 |
| 72 #define RETRY_MAX 5 |
| 73 #define REQUEST_SENSE_LENGTH 0x12 |
| 74 #define INQUIRY_LENGTH 0x24 |
| 75 #define READ_CAPACITY_LENGTH 0x08 |
| 76 |
| 77 // HID Class-Specific Requests values. See section 7.2 of the HID specifications |
| 78 #define HID_GET_REPORT 0x01 |
| 79 #define HID_GET_IDLE 0x02 |
| 80 #define HID_GET_PROTOCOL 0x03 |
| 81 #define HID_SET_REPORT 0x09 |
| 82 #define HID_SET_IDLE 0x0A |
| 83 #define HID_SET_PROTOCOL 0x0B |
| 84 #define HID_REPORT_TYPE_INPUT 0x01 |
| 85 #define HID_REPORT_TYPE_OUTPUT 0x02 |
| 86 #define HID_REPORT_TYPE_FEATURE 0x03 |
| 87 |
| 88 // Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Cla
ss specifications |
| 89 #define BOMS_RESET 0xFF |
| 90 #define BOMS_GET_MAX_LUN 0xFE |
| 91 |
| 92 // Section 5.1: Command Block Wrapper (CBW) |
| 93 struct command_block_wrapper { |
| 94 uint8_t dCBWSignature[4]; |
| 95 uint32_t dCBWTag; |
| 96 uint32_t dCBWDataTransferLength; |
| 97 uint8_t bmCBWFlags; |
| 98 uint8_t bCBWLUN; |
| 99 uint8_t bCBWCBLength; |
| 100 uint8_t CBWCB[16]; |
| 101 }; |
| 102 |
| 103 // Section 5.2: Command Status Wrapper (CSW) |
| 104 struct command_status_wrapper { |
| 105 uint8_t dCSWSignature[4]; |
| 106 uint32_t dCSWTag; |
| 107 uint32_t dCSWDataResidue; |
| 108 uint8_t bCSWStatus; |
| 109 }; |
| 110 |
| 111 static uint8_t cdb_length[256] = { |
| 112 // 0 1 2 3 4 5 6 7 8 9 A B C D E F |
| 113 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 0 |
| 114 06,06,06,06,06,06,06,06,06,06,06,06,06,06,06,06, // 1 |
| 115 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 2 |
| 116 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 3 |
| 117 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 4 |
| 118 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, // 5 |
| 119 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 6 |
| 120 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // 7 |
| 121 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 8 |
| 122 16,16,16,16,16,16,16,16,16,16,16,16,16,16,16,16, // 9 |
| 123 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // A |
| 124 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, // B |
| 125 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // C |
| 126 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // D |
| 127 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // E |
| 128 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00, // F |
| 129 }; |
| 130 |
| 131 enum test_type { |
| 132 USE_GENERIC, |
| 133 USE_PS3, |
| 134 USE_XBOX, |
| 135 USE_SCSI, |
| 136 USE_HID, |
| 137 } test_mode; |
| 138 uint16_t VID, PID; |
| 139 |
| 140 static void display_buffer_hex(unsigned char *buffer, unsigned size) |
| 141 { |
| 142 unsigned i, j, k; |
| 143 |
| 144 for (i=0; i<size; i+=16) { |
| 145 printf("\n %08x ", i); |
| 146 for(j=0,k=0; k<16; j++,k++) { |
| 147 if (i+j < size) { |
| 148 printf("%02x", buffer[i+j]); |
| 149 } else { |
| 150 printf(" "); |
| 151 } |
| 152 printf(" "); |
| 153 } |
| 154 printf(" "); |
| 155 for(j=0,k=0; k<16; j++,k++) { |
| 156 if (i+j < size) { |
| 157 if ((buffer[i+j] < 32) || (buffer[i+j] > 126)) { |
| 158 printf("."); |
| 159 } else { |
| 160 printf("%c", buffer[i+j]); |
| 161 } |
| 162 } |
| 163 } |
| 164 } |
| 165 printf("\n" ); |
| 166 } |
| 167 |
| 168 static char* uuid_to_string(const uint8_t* uuid) |
| 169 { |
| 170 static char uuid_string[40]; |
| 171 if (uuid == NULL) return NULL; |
| 172 sprintf(uuid_string, "{%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%
02x%02x%02x%02x%02x}", |
| 173 uuid[0], uuid[1], uuid[2], uuid[3], uuid[4], uuid[5], uuid[6], u
uid[7], |
| 174 uuid[8], uuid[9], uuid[10], uuid[11], uuid[12], uuid[13], uuid[1
4], uuid[15]); |
| 175 return uuid_string; |
| 176 } |
| 177 |
| 178 // The PS3 Controller is really a HID device that got its HID Report Descriptors |
| 179 // removed by Sony |
| 180 static int display_ps3_status(libusb_device_handle *handle) |
| 181 { |
| 182 int r; |
| 183 uint8_t input_report[49]; |
| 184 uint8_t master_bt_address[8]; |
| 185 uint8_t device_bt_address[18]; |
| 186 |
| 187 // Get the controller's bluetooth address of its master device |
| 188 CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQ
UEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 189 HID_GET_REPORT, 0x03f5, 0, master_bt_address, sizeof(master_bt_a
ddress), 100)); |
| 190 printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n",
master_bt_address[2], master_bt_address[3], |
| 191 master_bt_address[4], master_bt_address[5], master_bt_address[6]
, master_bt_address[7]); |
| 192 |
| 193 // Get the controller's bluetooth address |
| 194 CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQ
UEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 195 HID_GET_REPORT, 0x03f2, 0, device_bt_address, sizeof(device_bt_a
ddress), 100)); |
| 196 printf("\nMaster's bluetooth address: %02X:%02X:%02X:%02X:%02X:%02X\n",
device_bt_address[4], device_bt_address[5], |
| 197 device_bt_address[6], device_bt_address[7], device_bt_address[8]
, device_bt_address[9]); |
| 198 |
| 199 // Get the status of the controller's buttons via its HID report |
| 200 printf("\nReading PS3 Input Report...\n"); |
| 201 CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQ
UEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 202 HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x01, 0, input_report
, sizeof(input_report), 1000)); |
| 203 switch(input_report[2]){ /** Direction pad plus start, select, an
d joystick buttons */ |
| 204 case 0x01: |
| 205 printf("\tSELECT pressed\n"); |
| 206 break; |
| 207 case 0x02: |
| 208 printf("\tLEFT 3 pressed\n"); |
| 209 break; |
| 210 case 0x04: |
| 211 printf("\tRIGHT 3 pressed\n"); |
| 212 break; |
| 213 case 0x08: |
| 214 printf("\tSTART presed\n"); |
| 215 break; |
| 216 case 0x10: |
| 217 printf("\tUP pressed\n"); |
| 218 break; |
| 219 case 0x20: |
| 220 printf("\tRIGHT pressed\n"); |
| 221 break; |
| 222 case 0x40: |
| 223 printf("\tDOWN pressed\n"); |
| 224 break; |
| 225 case 0x80: |
| 226 printf("\tLEFT pressed\n"); |
| 227 break; |
| 228 } |
| 229 switch(input_report[3]){ /** Shapes plus top right and left butto
ns */ |
| 230 case 0x01: |
| 231 printf("\tLEFT 2 pressed\n"); |
| 232 break; |
| 233 case 0x02: |
| 234 printf("\tRIGHT 2 pressed\n"); |
| 235 break; |
| 236 case 0x04: |
| 237 printf("\tLEFT 1 pressed\n"); |
| 238 break; |
| 239 case 0x08: |
| 240 printf("\tRIGHT 1 presed\n"); |
| 241 break; |
| 242 case 0x10: |
| 243 printf("\tTRIANGLE pressed\n"); |
| 244 break; |
| 245 case 0x20: |
| 246 printf("\tCIRCLE pressed\n"); |
| 247 break; |
| 248 case 0x40: |
| 249 printf("\tCROSS pressed\n"); |
| 250 break; |
| 251 case 0x80: |
| 252 printf("\tSQUARE pressed\n"); |
| 253 break; |
| 254 } |
| 255 printf("\tPS button: %d\n", input_report[4]); |
| 256 printf("\tLeft Analog (X,Y): (%d,%d)\n", input_report[6], input_report[7
]); |
| 257 printf("\tRight Analog (X,Y): (%d,%d)\n", input_report[8], input_report[
9]); |
| 258 printf("\tL2 Value: %d\tR2 Value: %d\n", input_report[18], input_report[
19]); |
| 259 printf("\tL1 Value: %d\tR1 Value: %d\n", input_report[20], input_report[
21]); |
| 260 printf("\tRoll (x axis): %d Yaw (y axis): %d Pitch (z axis) %d\n", |
| 261 //(((input_report[42] + 128) % 256) - 128), |
| 262 (int8_t)(input_report[42]), |
| 263 (int8_t)(input_report[44]), |
| 264 (int8_t)(input_report[46])); |
| 265 printf("\tAcceleration: %d\n\n", (int8_t)(input_report[48])); |
| 266 return 0; |
| 267 } |
| 268 // The XBOX Controller is really a HID device that got its HID Report Descriptor
s |
| 269 // removed by Microsoft. |
| 270 // Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.ht
ml |
| 271 static int display_xbox_status(libusb_device_handle *handle) |
| 272 { |
| 273 int r; |
| 274 uint8_t input_report[20]; |
| 275 printf("\nReading XBox Input Report...\n"); |
| 276 CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQ
UEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 277 HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report
, 20, 1000)); |
| 278 printf(" D-pad: %02X\n", input_report[2]&0x0F); |
| 279 printf(" Start:%d, Back:%d, Left Stick Press:%d, Right Stick Press:%d\
n", B(input_report[2]&0x10), B(input_report[2]&0x20), |
| 280 B(input_report[2]&0x40), B(input_report[2]&0x80)); |
| 281 // A, B, X, Y, Black, White are pressure sensitive |
| 282 printf(" A:%d, B:%d, X:%d, Y:%d, White:%d, Black:%d\n", input_report[4
], input_report[5], |
| 283 input_report[6], input_report[7], input_report[9], input_report[
8]); |
| 284 printf(" Left Trigger: %d, Right Trigger: %d\n", input_report[10], inp
ut_report[11]); |
| 285 printf(" Left Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[13]<<8
)|input_report[12]), |
| 286 (int16_t)((input_report[15]<<8)|input_report[14])); |
| 287 printf(" Right Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[17]<<
8)|input_report[16]), |
| 288 (int16_t)((input_report[19]<<8)|input_report[18])); |
| 289 return 0; |
| 290 } |
| 291 |
| 292 static int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_
t right) |
| 293 { |
| 294 int r; |
| 295 uint8_t output_report[6]; |
| 296 |
| 297 printf("\nWriting XBox Controller Output Report...\n"); |
| 298 |
| 299 memset(output_report, 0, sizeof(output_report)); |
| 300 output_report[1] = sizeof(output_report); |
| 301 output_report[3] = left; |
| 302 output_report[5] = right; |
| 303 |
| 304 CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_RE
QUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 305 HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_repo
rt, 06, 1000)); |
| 306 return 0; |
| 307 } |
| 308 |
| 309 static int send_mass_storage_command(libusb_device_handle *handle, uint8_t endpo
int, uint8_t lun, |
| 310 uint8_t *cdb, uint8_t direction, int data_length, uint32_t *ret_tag) |
| 311 { |
| 312 static uint32_t tag = 1; |
| 313 uint8_t cdb_len; |
| 314 int i, r, size; |
| 315 struct command_block_wrapper cbw; |
| 316 |
| 317 if (cdb == NULL) { |
| 318 return -1; |
| 319 } |
| 320 |
| 321 if (endpoint & LIBUSB_ENDPOINT_IN) { |
| 322 perr("send_mass_storage_command: cannot send command on IN endpo
int\n"); |
| 323 return -1; |
| 324 } |
| 325 |
| 326 cdb_len = cdb_length[cdb[0]]; |
| 327 if ((cdb_len == 0) || (cdb_len > sizeof(cbw.CBWCB))) { |
| 328 perr("send_mass_storage_command: don't know how to handle this c
ommand (%02X, length %d)\n", |
| 329 cdb[0], cdb_len); |
| 330 return -1; |
| 331 } |
| 332 |
| 333 memset(&cbw, 0, sizeof(cbw)); |
| 334 cbw.dCBWSignature[0] = 'U'; |
| 335 cbw.dCBWSignature[1] = 'S'; |
| 336 cbw.dCBWSignature[2] = 'B'; |
| 337 cbw.dCBWSignature[3] = 'C'; |
| 338 *ret_tag = tag; |
| 339 cbw.dCBWTag = tag++; |
| 340 cbw.dCBWDataTransferLength = data_length; |
| 341 cbw.bmCBWFlags = direction; |
| 342 cbw.bCBWLUN = lun; |
| 343 // Subclass is 1 or 6 => cdb_len |
| 344 cbw.bCBWCBLength = cdb_len; |
| 345 memcpy(cbw.CBWCB, cdb, cdb_len); |
| 346 |
| 347 i = 0; |
| 348 do { |
| 349 // The transfer length must always be exactly 31 bytes. |
| 350 r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&cbw,
31, &size, 1000); |
| 351 if (r == LIBUSB_ERROR_PIPE) { |
| 352 libusb_clear_halt(handle, endpoint); |
| 353 } |
| 354 i++; |
| 355 } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX)); |
| 356 if (r != LIBUSB_SUCCESS) { |
| 357 perr(" send_mass_storage_command: %s\n", libusb_strerror((enum
libusb_error)r)); |
| 358 return -1; |
| 359 } |
| 360 |
| 361 printf(" sent %d CDB bytes\n", cdb_len); |
| 362 return 0; |
| 363 } |
| 364 |
| 365 static int get_mass_storage_status(libusb_device_handle *handle, uint8_t endpoin
t, uint32_t expected_tag) |
| 366 { |
| 367 int i, r, size; |
| 368 struct command_status_wrapper csw; |
| 369 |
| 370 // The device is allowed to STALL this transfer. If it does, you have to |
| 371 // clear the stall and try again. |
| 372 i = 0; |
| 373 do { |
| 374 r = libusb_bulk_transfer(handle, endpoint, (unsigned char*)&csw,
13, &size, 1000); |
| 375 if (r == LIBUSB_ERROR_PIPE) { |
| 376 libusb_clear_halt(handle, endpoint); |
| 377 } |
| 378 i++; |
| 379 } while ((r == LIBUSB_ERROR_PIPE) && (i<RETRY_MAX)); |
| 380 if (r != LIBUSB_SUCCESS) { |
| 381 perr(" get_mass_storage_status: %s\n", libusb_strerror((enum l
ibusb_error)r)); |
| 382 return -1; |
| 383 } |
| 384 if (size != 13) { |
| 385 perr(" get_mass_storage_status: received %d bytes (expected 13
)\n", size); |
| 386 return -1; |
| 387 } |
| 388 if (csw.dCSWTag != expected_tag) { |
| 389 perr(" get_mass_storage_status: mismatched tags (expected %08X
, received %08X)\n", |
| 390 expected_tag, csw.dCSWTag); |
| 391 return -1; |
| 392 } |
| 393 // For this test, we ignore the dCSWSignature check for validity... |
| 394 printf(" Mass Storage Status: %02X (%s)\n", csw.bCSWStatus, csw.bCSWSt
atus?"FAILED":"Success"); |
| 395 if (csw.dCSWTag != expected_tag) |
| 396 return -1; |
| 397 if (csw.bCSWStatus) { |
| 398 // REQUEST SENSE is appropriate only if bCSWStatus is 1, meaning
that the |
| 399 // command failed somehow. Larger values (2 in particular) mean
that |
| 400 // the command couldn't be understood. |
| 401 if (csw.bCSWStatus == 1) |
| 402 return -2; // request Get Sense |
| 403 else |
| 404 return -1; |
| 405 } |
| 406 |
| 407 // In theory we also should check dCSWDataResidue. But lots of devices |
| 408 // set it wrongly. |
| 409 return 0; |
| 410 } |
| 411 |
| 412 static void get_sense(libusb_device_handle *handle, uint8_t endpoint_in, uint8_t
endpoint_out) |
| 413 { |
| 414 uint8_t cdb[16]; // SCSI Command Descriptor Block |
| 415 uint8_t sense[18]; |
| 416 uint32_t expected_tag; |
| 417 int size; |
| 418 |
| 419 // Request Sense |
| 420 printf("Request Sense:\n"); |
| 421 memset(sense, 0, sizeof(sense)); |
| 422 memset(cdb, 0, sizeof(cdb)); |
| 423 cdb[0] = 0x03; // Request Sense |
| 424 cdb[4] = REQUEST_SENSE_LENGTH; |
| 425 |
| 426 send_mass_storage_command(handle, endpoint_out, 0, cdb, LIBUSB_ENDPOINT_
IN, REQUEST_SENSE_LENGTH, &expected_tag); |
| 427 libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&sense, REQUES
T_SENSE_LENGTH, &size, 1000); |
| 428 printf(" received %d bytes\n", size); |
| 429 |
| 430 if ((sense[0] != 0x70) && (sense[0] != 0x71)) { |
| 431 perr(" ERROR No sense data\n"); |
| 432 } else { |
| 433 perr(" ERROR Sense: %02X %02X %02X\n", sense[2]&0x0F, sense[12
], sense[13]); |
| 434 } |
| 435 // Strictly speaking, the get_mass_storage_status() call should come |
| 436 // before these perr() lines. If the status is nonzero then we must |
| 437 // assume there's no data in the buffer. For xusb it doesn't matter. |
| 438 get_mass_storage_status(handle, endpoint_in, expected_tag); |
| 439 } |
| 440 |
| 441 // Mass Storage device to test bulk transfers (non destructive test) |
| 442 static int test_mass_storage(libusb_device_handle *handle, uint8_t endpoint_in,
uint8_t endpoint_out) |
| 443 { |
| 444 int r, size; |
| 445 uint8_t lun; |
| 446 uint32_t expected_tag; |
| 447 uint32_t i, max_lba, block_size; |
| 448 double device_size; |
| 449 uint8_t cdb[16]; // SCSI Command Descriptor Block |
| 450 uint8_t buffer[64]; |
| 451 char vid[9], pid[9], rev[5]; |
| 452 unsigned char *data; |
| 453 FILE *fd; |
| 454 |
| 455 printf("Reading Max LUN:\n"); |
| 456 r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TY
PE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 457 BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000); |
| 458 // Some devices send a STALL instead of the actual value. |
| 459 // In such cases we should set lun to 0. |
| 460 if (r == 0) { |
| 461 lun = 0; |
| 462 } else if (r < 0) { |
| 463 perr(" Failed: %s", libusb_strerror((enum libusb_error)r)); |
| 464 } |
| 465 printf(" Max LUN = %d\n", lun); |
| 466 |
| 467 // Send Inquiry |
| 468 printf("Sending Inquiry:\n"); |
| 469 memset(buffer, 0, sizeof(buffer)); |
| 470 memset(cdb, 0, sizeof(cdb)); |
| 471 cdb[0] = 0x12; // Inquiry |
| 472 cdb[4] = INQUIRY_LENGTH; |
| 473 |
| 474 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOIN
T_IN, INQUIRY_LENGTH, &expected_tag); |
| 475 CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&bu
ffer, INQUIRY_LENGTH, &size, 1000)); |
| 476 printf(" received %d bytes\n", size); |
| 477 // The following strings are not zero terminated |
| 478 for (i=0; i<8; i++) { |
| 479 vid[i] = buffer[8+i]; |
| 480 pid[i] = buffer[16+i]; |
| 481 rev[i/2] = buffer[32+i/2]; // instead of another loop |
| 482 } |
| 483 vid[8] = 0; |
| 484 pid[8] = 0; |
| 485 rev[4] = 0; |
| 486 printf(" VID:PID:REV \"%8s\":\"%8s\":\"%4s\"\n", vid, pid, rev); |
| 487 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) { |
| 488 get_sense(handle, endpoint_in, endpoint_out); |
| 489 } |
| 490 |
| 491 // Read capacity |
| 492 printf("Reading Capacity:\n"); |
| 493 memset(buffer, 0, sizeof(buffer)); |
| 494 memset(cdb, 0, sizeof(cdb)); |
| 495 cdb[0] = 0x25; // Read Capacity |
| 496 |
| 497 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOIN
T_IN, READ_CAPACITY_LENGTH, &expected_tag); |
| 498 CALL_CHECK(libusb_bulk_transfer(handle, endpoint_in, (unsigned char*)&bu
ffer, READ_CAPACITY_LENGTH, &size, 1000)); |
| 499 printf(" received %d bytes\n", size); |
| 500 max_lba = be_to_int32(&buffer[0]); |
| 501 block_size = be_to_int32(&buffer[4]); |
| 502 device_size = ((double)(max_lba+1))*block_size/(1024*1024*1024); |
| 503 printf(" Max LBA: %08X, Block Size: %08X (%.2f GB)\n", max_lba, block_
size, device_size); |
| 504 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) { |
| 505 get_sense(handle, endpoint_in, endpoint_out); |
| 506 } |
| 507 |
| 508 data = (unsigned char*) calloc(1, block_size); |
| 509 if (data == NULL) { |
| 510 perr(" unable to allocate data buffer\n"); |
| 511 return -1; |
| 512 } |
| 513 |
| 514 // Send Read |
| 515 printf("Attempting to read %d bytes:\n", block_size); |
| 516 memset(cdb, 0, sizeof(cdb)); |
| 517 |
| 518 cdb[0] = 0x28; // Read(10) |
| 519 cdb[8] = 0x01; // 1 block |
| 520 |
| 521 send_mass_storage_command(handle, endpoint_out, lun, cdb, LIBUSB_ENDPOIN
T_IN, block_size, &expected_tag); |
| 522 libusb_bulk_transfer(handle, endpoint_in, data, block_size, &size, 5000)
; |
| 523 printf(" READ: received %d bytes\n", size); |
| 524 if (get_mass_storage_status(handle, endpoint_in, expected_tag) == -2) { |
| 525 get_sense(handle, endpoint_in, endpoint_out); |
| 526 } else { |
| 527 display_buffer_hex(data, size); |
| 528 if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) { |
| 529 if (fwrite(data, 1, (size_t)size, fd) != (unsigned int)s
ize) { |
| 530 perr(" unable to write binary data\n"); |
| 531 } |
| 532 fclose(fd); |
| 533 } |
| 534 } |
| 535 free(data); |
| 536 |
| 537 return 0; |
| 538 } |
| 539 |
| 540 // HID |
| 541 static int get_hid_record_size(uint8_t *hid_report_descriptor, int size, int typ
e) |
| 542 { |
| 543 uint8_t i, j = 0; |
| 544 uint8_t offset; |
| 545 int record_size[3] = {0, 0, 0}; |
| 546 int nb_bits = 0, nb_items = 0; |
| 547 bool found_record_marker; |
| 548 |
| 549 found_record_marker = false; |
| 550 for (i = hid_report_descriptor[0]+1; i < size; i += offset) { |
| 551 offset = (hid_report_descriptor[i]&0x03) + 1; |
| 552 if (offset == 4) |
| 553 offset = 5; |
| 554 switch (hid_report_descriptor[i] & 0xFC) { |
| 555 case 0x74: // bitsize |
| 556 nb_bits = hid_report_descriptor[i+1]; |
| 557 break; |
| 558 case 0x94: // count |
| 559 nb_items = 0; |
| 560 for (j=1; j<offset; j++) { |
| 561 nb_items = ((uint32_t)hid_report_descriptor[i+j]
) << (8*(j-1)); |
| 562 } |
| 563 break; |
| 564 case 0x80: // input |
| 565 found_record_marker = true; |
| 566 j = 0; |
| 567 break; |
| 568 case 0x90: // output |
| 569 found_record_marker = true; |
| 570 j = 1; |
| 571 break; |
| 572 case 0xb0: // feature |
| 573 found_record_marker = true; |
| 574 j = 2; |
| 575 break; |
| 576 case 0xC0: // end of collection |
| 577 nb_items = 0; |
| 578 nb_bits = 0; |
| 579 break; |
| 580 default: |
| 581 continue; |
| 582 } |
| 583 if (found_record_marker) { |
| 584 found_record_marker = false; |
| 585 record_size[j] += nb_items*nb_bits; |
| 586 } |
| 587 } |
| 588 if ((type < HID_REPORT_TYPE_INPUT) || (type > HID_REPORT_TYPE_FEATURE))
{ |
| 589 return 0; |
| 590 } else { |
| 591 return (record_size[type - HID_REPORT_TYPE_INPUT]+7)/8; |
| 592 } |
| 593 } |
| 594 |
| 595 static int test_hid(libusb_device_handle *handle, uint8_t endpoint_in) |
| 596 { |
| 597 int r, size, descriptor_size; |
| 598 uint8_t hid_report_descriptor[256]; |
| 599 uint8_t *report_buffer; |
| 600 FILE *fd; |
| 601 |
| 602 printf("\nReading HID Report Descriptors:\n"); |
| 603 descriptor_size = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIB
USB_REQUEST_TYPE_STANDARD|LIBUSB_RECIPIENT_INTERFACE, |
| 604 LIBUSB_REQUEST_GET_DESCRIPTOR, LIBUSB_DT_REPORT<<8, 0, hid_repor
t_descriptor, sizeof(hid_report_descriptor), 1000); |
| 605 if (descriptor_size < 0) { |
| 606 printf(" Failed\n"); |
| 607 return -1; |
| 608 } |
| 609 display_buffer_hex(hid_report_descriptor, descriptor_size); |
| 610 if ((binary_dump) && ((fd = fopen(binary_name, "w")) != NULL)) { |
| 611 if (fwrite(hid_report_descriptor, 1, descriptor_size, fd) != des
criptor_size) { |
| 612 printf(" Error writing descriptor to file\n"); |
| 613 } |
| 614 fclose(fd); |
| 615 } |
| 616 |
| 617 size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_R
EPORT_TYPE_FEATURE); |
| 618 if (size <= 0) { |
| 619 printf("\nSkipping Feature Report readout (None detected)\n"); |
| 620 } else { |
| 621 report_buffer = (uint8_t*) calloc(size, 1); |
| 622 if (report_buffer == NULL) { |
| 623 return -1; |
| 624 } |
| 625 |
| 626 printf("\nReading Feature Report (length %d)...\n", size); |
| 627 r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RE
QUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 628 HID_GET_REPORT, (HID_REPORT_TYPE_FEATURE<<8)|0, 0, repor
t_buffer, (uint16_t)size, 5000); |
| 629 if (r >= 0) { |
| 630 display_buffer_hex(report_buffer, size); |
| 631 } else { |
| 632 switch(r) { |
| 633 case LIBUSB_ERROR_NOT_FOUND: |
| 634 printf(" No Feature Report available for this
device\n"); |
| 635 break; |
| 636 case LIBUSB_ERROR_PIPE: |
| 637 printf(" Detected stall - resetting pipe...\n"
); |
| 638 libusb_clear_halt(handle, 0); |
| 639 break; |
| 640 default: |
| 641 printf(" Error: %s\n", libusb_strerror((enum l
ibusb_error)r)); |
| 642 break; |
| 643 } |
| 644 } |
| 645 free(report_buffer); |
| 646 } |
| 647 |
| 648 size = get_hid_record_size(hid_report_descriptor, descriptor_size, HID_R
EPORT_TYPE_INPUT); |
| 649 if (size <= 0) { |
| 650 printf("\nSkipping Input Report readout (None detected)\n"); |
| 651 } else { |
| 652 report_buffer = (uint8_t*) calloc(size, 1); |
| 653 if (report_buffer == NULL) { |
| 654 return -1; |
| 655 } |
| 656 |
| 657 printf("\nReading Input Report (length %d)...\n", size); |
| 658 r = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RE
QUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, |
| 659 HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, repo
rt_buffer, (uint16_t)size, 5000); |
| 660 if (r >= 0) { |
| 661 display_buffer_hex(report_buffer, size); |
| 662 } else { |
| 663 switch(r) { |
| 664 case LIBUSB_ERROR_TIMEOUT: |
| 665 printf(" Timeout! Please make sure you act on
the device within the 5 seconds allocated...\n"); |
| 666 break; |
| 667 case LIBUSB_ERROR_PIPE: |
| 668 printf(" Detected stall - resetting pipe...\n"
); |
| 669 libusb_clear_halt(handle, 0); |
| 670 break; |
| 671 default: |
| 672 printf(" Error: %s\n", libusb_strerror((enum l
ibusb_error)r)); |
| 673 break; |
| 674 } |
| 675 } |
| 676 |
| 677 // Attempt a bulk read from endpoint 0 (this should just return
a raw input report) |
| 678 printf("\nTesting interrupt read using endpoint %02X...\n", endp
oint_in); |
| 679 r = libusb_interrupt_transfer(handle, endpoint_in, report_buffer
, size, &size, 5000); |
| 680 if (r >= 0) { |
| 681 display_buffer_hex(report_buffer, size); |
| 682 } else { |
| 683 printf(" %s\n", libusb_strerror((enum libusb_error)r))
; |
| 684 } |
| 685 |
| 686 free(report_buffer); |
| 687 } |
| 688 return 0; |
| 689 } |
| 690 |
| 691 // Read the MS WinUSB Feature Descriptors, that are used on Windows 8 for automa
ted driver installation |
| 692 static void read_ms_winsub_feature_descriptors(libusb_device_handle *handle, uin
t8_t bRequest, int iface_number) |
| 693 { |
| 694 #define MAX_OS_FD_LENGTH 256 |
| 695 int i, r; |
| 696 uint8_t os_desc[MAX_OS_FD_LENGTH]; |
| 697 uint32_t length; |
| 698 void* le_type_punning_IS_fine; |
| 699 struct { |
| 700 const char* desc; |
| 701 uint8_t recipient; |
| 702 uint16_t index; |
| 703 uint16_t header_size; |
| 704 } os_fd[2] = { |
| 705 {"Extended Compat ID", LIBUSB_RECIPIENT_DEVICE, 0x0004, 0x10}, |
| 706 {"Extended Properties", LIBUSB_RECIPIENT_INTERFACE, 0x0005, 0x0A
} |
| 707 }; |
| 708 |
| 709 if (iface_number < 0) return; |
| 710 |
| 711 for (i=0; i<2; i++) { |
| 712 printf("\nReading %s OS Feature Descriptor (wIndex = 0x%04d):\n"
, os_fd[i].desc, os_fd[i].index); |
| 713 |
| 714 // Read the header part |
| 715 r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN
|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient), |
| 716 bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i
].index, os_desc, os_fd[i].header_size, 1000); |
| 717 if (r < os_fd[i].header_size) { |
| 718 perr(" Failed: %s", (r<0)?libusb_strerror((enum libusb
_error)r):"header size is too small"); |
| 719 return; |
| 720 } |
| 721 le_type_punning_IS_fine = (void*)os_desc; |
| 722 length = *((uint32_t*)le_type_punning_IS_fine); |
| 723 if (length > MAX_OS_FD_LENGTH) { |
| 724 length = MAX_OS_FD_LENGTH; |
| 725 } |
| 726 |
| 727 // Read the full feature descriptor |
| 728 r = libusb_control_transfer(handle, (uint8_t)(LIBUSB_ENDPOINT_IN
|LIBUSB_REQUEST_TYPE_VENDOR|os_fd[i].recipient), |
| 729 bRequest, (uint16_t)(((iface_number)<< 8)|0x00), os_fd[i
].index, os_desc, (uint16_t)length, 1000); |
| 730 if (r < 0) { |
| 731 perr(" Failed: %s", libusb_strerror((enum libusb_error
)r)); |
| 732 return; |
| 733 } else { |
| 734 display_buffer_hex(os_desc, r); |
| 735 } |
| 736 } |
| 737 } |
| 738 |
| 739 static void print_device_cap(struct libusb_bos_dev_capability_descriptor *dev_ca
p) |
| 740 { |
| 741 switch(dev_cap->bDevCapabilityType) { |
| 742 case LIBUSB_BT_USB_2_0_EXTENSION: { |
| 743 struct libusb_usb_2_0_extension_descriptor *usb_2_0_ext = NULL; |
| 744 libusb_get_usb_2_0_extension_descriptor(NULL, dev_cap, &usb_2_0_
ext); |
| 745 if (usb_2_0_ext) { |
| 746 printf(" USB 2.0 extension:\n"); |
| 747 printf(" attributes : %02X\n", usb_2_0_
ext->bmAttributes); |
| 748 libusb_free_usb_2_0_extension_descriptor(usb_2_0_ext); |
| 749 } |
| 750 break; |
| 751 } |
| 752 case LIBUSB_BT_SS_USB_DEVICE_CAPABILITY: { |
| 753 struct libusb_ss_usb_device_capability_descriptor *ss_usb_device
_cap = NULL; |
| 754 libusb_get_ss_usb_device_capability_descriptor(NULL, dev_cap, &s
s_usb_device_cap); |
| 755 if (ss_usb_device_cap) { |
| 756 printf(" USB 3.0 capabilities:\n"); |
| 757 printf(" attributes : %02X\n", ss_usb_d
evice_cap->bmAttributes); |
| 758 printf(" supported speeds : %04X\n", ss_usb_d
evice_cap->wSpeedSupported); |
| 759 printf(" supported functionality: %02X\n", ss_usb_d
evice_cap->bFunctionalitySupport); |
| 760 libusb_free_ss_usb_device_capability_descriptor(ss_usb_d
evice_cap); |
| 761 } |
| 762 break; |
| 763 } |
| 764 case LIBUSB_BT_CONTAINER_ID: { |
| 765 struct libusb_container_id_descriptor *container_id = NULL; |
| 766 libusb_get_container_id_descriptor(NULL, dev_cap, &container_id)
; |
| 767 if (container_id) { |
| 768 printf(" Container ID:\n %s\n", uuid_to_string(c
ontainer_id->ContainerID)); |
| 769 libusb_free_container_id_descriptor(container_id); |
| 770 } |
| 771 break; |
| 772 } |
| 773 default: |
| 774 printf(" Unknown BOS device capability %02x:\n", dev_cap->bDe
vCapabilityType); |
| 775 } |
| 776 } |
| 777 |
| 778 static int test_device(uint16_t vid, uint16_t pid) |
| 779 { |
| 780 libusb_device_handle *handle; |
| 781 libusb_device *dev; |
| 782 uint8_t bus, port_path[8]; |
| 783 struct libusb_bos_descriptor *bos_desc; |
| 784 struct libusb_config_descriptor *conf_desc; |
| 785 const struct libusb_endpoint_descriptor *endpoint; |
| 786 int i, j, k, r; |
| 787 int iface, nb_ifaces, first_iface = -1; |
| 788 struct libusb_device_descriptor dev_desc; |
| 789 const char* speed_name[5] = { "Unknown", "1.5 Mbit/s (USB LowSpeed)", "1
2 Mbit/s (USB FullSpeed)", |
| 790 "480 Mbit/s (USB HighSpeed)", "5000 Mbit/s (USB SuperSpeed)"}; |
| 791 char string[128]; |
| 792 uint8_t string_index[3]; // indexes of the string descriptors |
| 793 uint8_t endpoint_in = 0, endpoint_out = 0; // default IN and OUT en
dpoints |
| 794 |
| 795 printf("Opening device %04X:%04X...\n", vid, pid); |
| 796 handle = libusb_open_device_with_vid_pid(NULL, vid, pid); |
| 797 |
| 798 if (handle == NULL) { |
| 799 perr(" Failed.\n"); |
| 800 return -1; |
| 801 } |
| 802 |
| 803 dev = libusb_get_device(handle); |
| 804 bus = libusb_get_bus_number(dev); |
| 805 if (extra_info) { |
| 806 r = libusb_get_port_numbers(dev, port_path, sizeof(port_path)); |
| 807 if (r > 0) { |
| 808 printf("\nDevice properties:\n"); |
| 809 printf(" bus number: %d\n", bus); |
| 810 printf(" port path: %d", port_path[0]); |
| 811 for (i=1; i<r; i++) { |
| 812 printf("->%d", port_path[i]); |
| 813 } |
| 814 printf(" (from root hub)\n"); |
| 815 } |
| 816 r = libusb_get_device_speed(dev); |
| 817 if ((r<0) || (r>4)) r=0; |
| 818 printf(" speed: %s\n", speed_name[r]); |
| 819 } |
| 820 |
| 821 printf("\nReading device descriptor:\n"); |
| 822 CALL_CHECK(libusb_get_device_descriptor(dev, &dev_desc)); |
| 823 printf(" length: %d\n", dev_desc.bLength); |
| 824 printf(" device class: %d\n", dev_desc.bDeviceClass); |
| 825 printf(" S/N: %d\n", dev_desc.iSerialNumber); |
| 826 printf(" VID:PID: %04X:%04X\n", dev_desc.idVendor, dev_desc.id
Product); |
| 827 printf(" bcdDevice: %04X\n", dev_desc.bcdDevice); |
| 828 printf(" iMan:iProd:iSer: %d:%d:%d\n", dev_desc.iManufacturer, dev_des
c.iProduct, dev_desc.iSerialNumber); |
| 829 printf(" nb confs: %d\n", dev_desc.bNumConfigurations); |
| 830 // Copy the string descriptors for easier parsing |
| 831 string_index[0] = dev_desc.iManufacturer; |
| 832 string_index[1] = dev_desc.iProduct; |
| 833 string_index[2] = dev_desc.iSerialNumber; |
| 834 |
| 835 printf("\nReading BOS descriptor: "); |
| 836 if (libusb_get_bos_descriptor(handle, &bos_desc) == LIBUSB_SUCCESS) { |
| 837 printf("%d caps\n", bos_desc->bNumDeviceCaps); |
| 838 for (i = 0; i < bos_desc->bNumDeviceCaps; i++) |
| 839 print_device_cap(bos_desc->dev_capability[i]); |
| 840 libusb_free_bos_descriptor(bos_desc); |
| 841 } else { |
| 842 printf("no descriptor\n"); |
| 843 } |
| 844 |
| 845 printf("\nReading first configuration descriptor:\n"); |
| 846 CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc)); |
| 847 nb_ifaces = conf_desc->bNumInterfaces; |
| 848 printf(" nb interfaces: %d\n", nb_ifaces); |
| 849 if (nb_ifaces > 0) |
| 850 first_iface = conf_desc->usb_interface[0].altsetting[0].bInterfa
ceNumber; |
| 851 for (i=0; i<nb_ifaces; i++) { |
| 852 printf(" interface[%d]: id = %d\n", i, |
| 853 conf_desc->usb_interface[i].altsetting[0].bInterfaceNumb
er); |
| 854 for (j=0; j<conf_desc->usb_interface[i].num_altsetting; j++) { |
| 855 printf("interface[%d].altsetting[%d]: num endpoints = %d
\n", |
| 856 i, j, conf_desc->usb_interface[i].altsetting[j].
bNumEndpoints); |
| 857 printf(" Class.SubClass.Protocol: %02X.%02X.%02X\n", |
| 858 conf_desc->usb_interface[i].altsetting[j].bInter
faceClass, |
| 859 conf_desc->usb_interface[i].altsetting[j].bInter
faceSubClass, |
| 860 conf_desc->usb_interface[i].altsetting[j].bInter
faceProtocol); |
| 861 if ( (conf_desc->usb_interface[i].altsetting[j].bInterfa
ceClass == LIBUSB_CLASS_MASS_STORAGE) |
| 862 && ( (conf_desc->usb_interface[i].altsetting[j].bInter
faceSubClass == 0x01) |
| 863 || (conf_desc->usb_interface[i].altsetting[j].bInterfa
ceSubClass == 0x06) ) |
| 864 && (conf_desc->usb_interface[i].altsetting[j].bInterfa
ceProtocol == 0x50) ) { |
| 865 // Mass storage devices that can use basic SCSI
commands |
| 866 test_mode = USE_SCSI; |
| 867 } |
| 868 for (k=0; k<conf_desc->usb_interface[i].altsetting[j].bN
umEndpoints; k++) { |
| 869 struct libusb_ss_endpoint_companion_descriptor *
ep_comp = NULL; |
| 870 endpoint = &conf_desc->usb_interface[i].altsetti
ng[j].endpoint[k]; |
| 871 printf(" endpoint[%d].address: %02X\n", k,
endpoint->bEndpointAddress); |
| 872 // Use the first interrupt or bulk IN/OUT endpoi
nts as default for testing |
| 873 if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TY
PE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) { |
| 874 if (endpoint->bEndpointAddress & LIBUSB_
ENDPOINT_IN) { |
| 875 if (!endpoint_in) |
| 876 endpoint_in = endpoint->
bEndpointAddress; |
| 877 } else { |
| 878 if (!endpoint_out) |
| 879 endpoint_out = endpoint-
>bEndpointAddress; |
| 880 } |
| 881 } |
| 882 printf(" max packet size: %04X\n", end
point->wMaxPacketSize); |
| 883 printf(" polling interval: %02X\n", end
point->bInterval); |
| 884 libusb_get_ss_endpoint_companion_descriptor(NULL
, endpoint, &ep_comp); |
| 885 if (ep_comp) { |
| 886 printf(" max burst: %02X
(USB 3.0)\n", ep_comp->bMaxBurst); |
| 887 printf(" bytes per interval: %04X
(USB 3.0)\n", ep_comp->wBytesPerInterval); |
| 888 libusb_free_ss_endpoint_companion_descri
ptor(ep_comp); |
| 889 } |
| 890 } |
| 891 } |
| 892 } |
| 893 libusb_free_config_descriptor(conf_desc); |
| 894 |
| 895 libusb_set_auto_detach_kernel_driver(handle, 1); |
| 896 for (iface = 0; iface < nb_ifaces; iface++) |
| 897 { |
| 898 printf("\nClaiming interface %d...\n", iface); |
| 899 r = libusb_claim_interface(handle, iface); |
| 900 if (r != LIBUSB_SUCCESS) { |
| 901 perr(" Failed.\n"); |
| 902 } |
| 903 } |
| 904 |
| 905 printf("\nReading string descriptors:\n"); |
| 906 for (i=0; i<3; i++) { |
| 907 if (string_index[i] == 0) { |
| 908 continue; |
| 909 } |
| 910 if (libusb_get_string_descriptor_ascii(handle, string_index[i],
(unsigned char*)string, 128) >= 0) { |
| 911 printf(" String (0x%02X): \"%s\"\n", string_index[i],
string); |
| 912 } |
| 913 } |
| 914 // Read the OS String Descriptor |
| 915 if (libusb_get_string_descriptor_ascii(handle, 0xEE, (unsigned char*)str
ing, 128) >= 0) { |
| 916 printf(" String (0x%02X): \"%s\"\n", 0xEE, string); |
| 917 // If this is a Microsoft OS String Descriptor, |
| 918 // attempt to read the WinUSB extended Feature Descriptors |
| 919 if (strncmp(string, "MSFT100", 7) == 0) |
| 920 read_ms_winsub_feature_descriptors(handle, string[7], fi
rst_iface); |
| 921 } |
| 922 |
| 923 switch(test_mode) { |
| 924 case USE_PS3: |
| 925 CALL_CHECK(display_ps3_status(handle)); |
| 926 break; |
| 927 case USE_XBOX: |
| 928 CALL_CHECK(display_xbox_status(handle)); |
| 929 CALL_CHECK(set_xbox_actuators(handle, 128, 222)); |
| 930 msleep(2000); |
| 931 CALL_CHECK(set_xbox_actuators(handle, 0, 0)); |
| 932 break; |
| 933 case USE_HID: |
| 934 test_hid(handle, endpoint_in); |
| 935 break; |
| 936 case USE_SCSI: |
| 937 CALL_CHECK(test_mass_storage(handle, endpoint_in, endpoint_out))
; |
| 938 case USE_GENERIC: |
| 939 break; |
| 940 } |
| 941 |
| 942 printf("\n"); |
| 943 for (iface = 0; iface<nb_ifaces; iface++) { |
| 944 printf("Releasing interface %d...\n", iface); |
| 945 libusb_release_interface(handle, iface); |
| 946 } |
| 947 |
| 948 printf("Closing device...\n"); |
| 949 libusb_close(handle); |
| 950 |
| 951 return 0; |
| 952 } |
| 953 |
| 954 int main(int argc, char** argv) |
| 955 { |
| 956 bool show_help = false; |
| 957 bool debug_mode = false; |
| 958 const struct libusb_version* version; |
| 959 int j, r; |
| 960 size_t i, arglen; |
| 961 unsigned tmp_vid, tmp_pid; |
| 962 uint16_t endian_test = 0xBE00; |
| 963 char* error_lang = NULL; |
| 964 |
| 965 // Default to generic, expecting VID:PID |
| 966 VID = 0; |
| 967 PID = 0; |
| 968 test_mode = USE_GENERIC; |
| 969 |
| 970 if (((uint8_t*)&endian_test)[0] == 0xBE) { |
| 971 printf("Despite their natural superiority for end users, big end
ian\n" |
| 972 "CPUs are not supported with this program, sorry.\n"); |
| 973 return 0; |
| 974 } |
| 975 |
| 976 if (argc >= 2) { |
| 977 for (j = 1; j<argc; j++) { |
| 978 arglen = strlen(argv[j]); |
| 979 if ( ((argv[j][0] == '-') || (argv[j][0] == '/')) |
| 980 && (arglen >= 2) ) { |
| 981 switch(argv[j][1]) { |
| 982 case 'd': |
| 983 debug_mode = true; |
| 984 break; |
| 985 case 'i': |
| 986 extra_info = true; |
| 987 break; |
| 988 case 'b': |
| 989 if ((j+1 >= argc) || (argv[j+1][0] == '-
') || (argv[j+1][0] == '/')) { |
| 990 printf(" Option -b requires a
file name\n"); |
| 991 return 1; |
| 992 } |
| 993 binary_name = argv[++j]; |
| 994 binary_dump = true; |
| 995 break; |
| 996 case 'l': |
| 997 if ((j+1 >= argc) || (argv[j+1][0] == '-
') || (argv[j+1][0] == '/')) { |
| 998 printf(" Option -l requires an
ISO 639-1 language parameter\n"); |
| 999 return 1; |
| 1000 } |
| 1001 error_lang = argv[++j]; |
| 1002 break; |
| 1003 case 'j': |
| 1004 // OLIMEX ARM-USB-TINY JTAG, 2 channel c
omposite device - 2 interfaces |
| 1005 if (!VID && !PID) { |
| 1006 VID = 0x15BA; |
| 1007 PID = 0x0004; |
| 1008 } |
| 1009 break; |
| 1010 case 'k': |
| 1011 // Generic 2 GB USB Key (SCSI Transparen
t/Bulk Only) - 1 interface |
| 1012 if (!VID && !PID) { |
| 1013 VID = 0x0204; |
| 1014 PID = 0x6025; |
| 1015 } |
| 1016 break; |
| 1017 // The following tests will force VID:PID if alr
eady provided |
| 1018 case 'p': |
| 1019 // Sony PS3 Controller - 1 interface |
| 1020 VID = 0x054C; |
| 1021 PID = 0x0268; |
| 1022 test_mode = USE_PS3; |
| 1023 break; |
| 1024 case 's': |
| 1025 // Microsoft Sidewinder Precision Pro Jo
ystick - 1 HID interface |
| 1026 VID = 0x045E; |
| 1027 PID = 0x0008; |
| 1028 test_mode = USE_HID; |
| 1029 break; |
| 1030 case 'x': |
| 1031 // Microsoft XBox Controller Type S - 1
interface |
| 1032 VID = 0x045E; |
| 1033 PID = 0x0289; |
| 1034 test_mode = USE_XBOX; |
| 1035 break; |
| 1036 default: |
| 1037 show_help = true; |
| 1038 break; |
| 1039 } |
| 1040 } else { |
| 1041 for (i=0; i<arglen; i++) { |
| 1042 if (argv[j][i] == ':') |
| 1043 break; |
| 1044 } |
| 1045 if (i != arglen) { |
| 1046 if (sscanf(argv[j], "%x:%x" , &tmp_vid,
&tmp_pid) != 2) { |
| 1047 printf(" Please specify VID &
PID as \"vid:pid\" in hexadecimal format\n"); |
| 1048 return 1; |
| 1049 } |
| 1050 VID = (uint16_t)tmp_vid; |
| 1051 PID = (uint16_t)tmp_pid; |
| 1052 } else { |
| 1053 show_help = true; |
| 1054 } |
| 1055 } |
| 1056 } |
| 1057 } |
| 1058 |
| 1059 if ((show_help) || (argc == 1) || (argc > 7)) { |
| 1060 printf("usage: %s [-h] [-d] [-i] [-k] [-b file] [-l lang] [-j] [
-x] [-s] [-p] [vid:pid]\n", argv[0]); |
| 1061 printf(" -h : display usage\n"); |
| 1062 printf(" -d : enable debug output\n"); |
| 1063 printf(" -i : print topology and speed info\n"); |
| 1064 printf(" -j : test composite FTDI based JTAG device\n"); |
| 1065 printf(" -k : test Mass Storage device\n"); |
| 1066 printf(" -b file : dump Mass Storage data to file 'file'\n"); |
| 1067 printf(" -p : test Sony PS3 SixAxis controller\n"); |
| 1068 printf(" -s : test Microsoft Sidewinder Precision Pro (HI
D)\n"); |
| 1069 printf(" -x : test Microsoft XBox Controller Type S\n"); |
| 1070 printf(" -l lang : language to report errors in (ISO 639-1)\n"
); |
| 1071 printf("If only the vid:pid is provided, xusb attempts to run th
e most appropriate test\n"); |
| 1072 return 0; |
| 1073 } |
| 1074 |
| 1075 version = libusb_get_version(); |
| 1076 printf("Using libusbx v%d.%d.%d.%d\n\n", version->major, version->minor,
version->micro, version->nano); |
| 1077 r = libusb_init(NULL); |
| 1078 if (r < 0) |
| 1079 return r; |
| 1080 |
| 1081 libusb_set_debug(NULL, debug_mode?LIBUSB_LOG_LEVEL_DEBUG:LIBUSB_LOG_LEVE
L_INFO); |
| 1082 if (error_lang != NULL) { |
| 1083 r = libusb_setlocale(error_lang); |
| 1084 if (r < 0) |
| 1085 printf("Invalid or unsupported locale '%s': %s\n", error
_lang, libusb_strerror((enum libusb_error)r)); |
| 1086 } |
| 1087 |
| 1088 test_device(VID, PID); |
| 1089 |
| 1090 libusb_exit(NULL); |
| 1091 |
| 1092 return 0; |
| 1093 } |
| OLD | NEW |