diff options
author | Pete Batard <pbatard@gmail.com> | 2010-01-14 01:23:19 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-01-14 01:23:19 +0000 |
commit | 434caf7c49b819f94035643862814a0e86112ec4 (patch) | |
tree | 70278cf7fd9ad4deca05f32e3144c9f2a33ae98a /examples | |
parent | 368130bd31efbb97d709882ded63de870974d3e4 (diff) | |
download | libusb-434caf7c49b819f94035643862814a0e86112ec4.tar.gz |
svn r37:
- windows_set_interface_altsetting (untested)
- windows_set_configuration (untested)
- updated xusb.c test program, with comprehensive XBox Controller test and
preparation for bulk transfers test on Mass Storage device
Diffstat (limited to 'examples')
-rw-r--r-- | examples/xusb.c | 224 |
1 files changed, 166 insertions, 58 deletions
diff --git a/examples/xusb.c b/examples/xusb.c index 8614e2f..6ea99f7 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -3,7 +3,7 @@ * based on lsusb, copyright (C) 2007 Daniel Drake <dsd@gentoo.org> * * This test program tries to access an USB device through WinUSB. - * To access your device, change VID/PID. + * To access your device, modify this source and add your VID/PID. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,65 +23,111 @@ #include <stdio.h> #include <sys/types.h> #include <inttypes.h> +#include <string.h> +#include "../config.h" #include <libusb/libusb.h> +#ifdef OS_WINDOWS +#include <windows.h> +#define msleep(msecs) Sleep(msecs) +#ifdef interface
+#undef interface
+#endif +#else +#include <unistd.h> +#define msleep(msecs) usleep(1000*msecs) +#endif + #define perr(...) fprintf(stderr, __VA_ARGS__) #define ERR_EXIT(errcode) do { perr(" libusb error: %d\n", errcode); return -1; } while (0) #define CALL_CHECK(fcall) do { r=fcall; if (r < 0) ERR_EXIT(r); } while (0); +#define B(x) (((x)!=0)?1:0) + +// HID Class-Specific Requests values. See section 7.2 of the HID specifications +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#define HID_REPORT_TYPE_INPUT 0x01 +#define HID_REPORT_TYPE_OUTPUT 0x02 +#define HID_REPORT_TYPE_FEATURE 0x03 + +// Mass Storage Requests values. See section 3 of the Bulk-Only Mass Storage Class specifications +#define BOMS_RESET 0xFF +#define BOMS_GET_MAX_LUN 0xFE + +enum test_type { + USE_XBOX, + USE_KEY, + USE_JTAG, +} test_mode; +uint16_t VID, PID; + +// The XBOX Controller is really a HID device that got its HID Report Descriptors +// removed by Microsoft. +// Input/Output reports described at http://euc.jp/periphs/xbox-controller.ja.html +int display_xbox_status(libusb_device_handle *handle) +{ + int r; + uint8_t input_report[20]; + printf("Retrieving XBox Input Report...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_GET_REPORT, (HID_REPORT_TYPE_INPUT<<8)|0x00, 0, input_report, 20, 1000)); + printf("D-pad: %02X\n", input_report[2]&0x0F); + printf("Start:%d, Back:%d, Left Stick Press:%d, Right Stick Press:%d\n", B(input_report[2]&0x10), B(input_report[2]&0x20), + B(input_report[2]&0x40), B(input_report[2]&0x80)); + // A, B, X, Y, Black, White are pressure sensitive + printf("A:%d, B:%d, X:%d, Y:%d, White:%d, Black:%d\n", input_report[4], input_report[5], + input_report[6], input_report[7], input_report[9], input_report[8]); + printf("Left Trigger: %d, Right Trigger: %d\n", input_report[10], input_report[11]); + printf("Left Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[13]<<8)|input_report[12]), + (int16_t)((input_report[15]<<8)|input_report[14])); + printf("Right Analog (X,Y): (%d,%d)\n", (int16_t)((input_report[17]<<8)|input_report[16]), + (int16_t)((input_report[19]<<8)|input_report[18])); + return 0; +} -//#define USE_MOUSE -//#define USE_XBOX -#define USE_JTAG - -#ifdef USE_MOUSE -// Logitech optical mouse -#define VID 0x046D -#define PID 0xC03E -#endif +int set_xbox_actuators(libusb_device_handle *handle, uint8_t left, uint8_t right) +{ + int r; + uint8_t output_report[6]; -#ifdef USE_XBOX -// Microsoft XBox Controller -#define VID 0x045E -#define PID 0x0289 -#endif + printf("Writing XBox Controller Output Report...\n"); -#ifdef USE_KEY -// 2 GB Usb key -#define VID 0x0204 -#define PID 0x6025 -#endif + memset(output_report, 0, 6); + output_report[1] = 6; + output_report[3] = left; + output_report[5] = right; -#ifdef USE_JTAG -// OLIMEX ARM-USB-TINY, 2 channel composite device -#define VID 0x15BA -#define PID 0x0004 -#endif + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + HID_SET_REPORT, (HID_REPORT_TYPE_OUTPUT<<8)|0x00, 0, output_report, 6, 1000)); + return 0; +} -static void print_devs(libusb_device **devs) +// Mass Storage device to test bulk transfers (/!\ destructive test /!\) +int test_mass_storage(libusb_device_handle *handle) { - libusb_device *dev; - int i = 0; - - while ((dev = devs[i++]) != NULL) { - struct libusb_device_descriptor desc; - int r = libusb_get_device_descriptor(dev, &desc); - if (r < 0) { - perr("failed to get device descriptor\n"); - return; - } - - printf("%04x:%04x (bus %d, device %d)\n", - desc.idVendor, desc.idProduct, - libusb_get_bus_number(dev), libusb_get_device_address(dev)); - } + int r; + unsigned char lun; + printf("Sending Mass Storage Reset...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_OUT|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + BOMS_RESET, 0, 0, NULL, 0, 1000)); + printf("Getting Max LUN...\n"); + CALL_CHECK(libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE, + BOMS_GET_MAX_LUN, 0, 0, &lun, 1, 1000)); + printf(" Max LUN = %d\n", lun); + return 0; } int test_device(uint16_t vid, uint16_t pid) { libusb_device_handle *handle; - int r; - int iface = 1; + libusb_device *dev; + int i, j, r; + int iface = 0; printf("Opening device...\n"); handle = libusb_open_device_with_vid_pid(NULL, vid, pid); @@ -91,6 +137,8 @@ int test_device(uint16_t vid, uint16_t pid) return -1; } + dev = libusb_get_device(handle); + printf("Claiming interface %d...\n", iface); r = libusb_claim_interface(handle, iface); if (r != LIBUSB_SUCCESS) { @@ -101,10 +149,48 @@ int test_device(uint16_t vid, uint16_t pid) CALL_CHECK(libusb_claim_interface(handle, iface)); } - char string[128]; - printf("Retieving string descriptor...\n"); - CALL_CHECK(libusb_get_string_descriptor_ascii(handle, 3, string, 128)); - printf("Got string: \"%s\"\n", string); + struct libusb_device_descriptor dev_desc; + printf("reading device descriptor...\n"); + CALL_CHECK(libusb_get_device_descriptor(dev, &dev_desc)); + printf("length = %d\n", dev_desc.bLength); + printf("device class = %d\n", dev_desc.bDeviceClass); + printf("ser num = %d\n", dev_desc.iSerialNumber); + printf("VID:PID %04X:%04X\n", dev_desc.idVendor, dev_desc.idProduct); + printf("bcdDevice = %04X\n", dev_desc.bcdDevice); + printf("iMan:iProd:iSer %d:%d:%d\n", dev_desc.iManufacturer, dev_desc.iProduct, dev_desc.iSerialNumber); + printf("num confs = %d\n", dev_desc.bNumConfigurations); + + struct libusb_config_descriptor *conf_desc; + printf("reading configuration descriptor...\n"); + CALL_CHECK(libusb_get_config_descriptor(dev, 0, &conf_desc)); + printf("num interfaces = %d\n", conf_desc->bNumInterfaces); + for (i=0; i<conf_desc->bNumInterfaces; i++) { + for (j=0; j<conf_desc->interface[i].num_altsetting; j++) { + printf("interface[%d].altsetting[%d]: num endpoints = %d\n", + i, j, conf_desc->interface[i].altsetting[j].bNumEndpoints); + printf(" Class.SubClass.Protocol: %02X.%02X.%02X\n", + conf_desc->interface[i].altsetting[j].bInterfaceClass, + conf_desc->interface[i].altsetting[j].bInterfaceSubClass, + conf_desc->interface[i].altsetting[j].bInterfaceProtocol); + } + } + libusb_free_config_descriptor(conf_desc); + + if (test_mode == USE_XBOX) { + CALL_CHECK(display_xbox_status(handle)); + CALL_CHECK(set_xbox_actuators(handle, 128, 222)); + msleep(2000); + CALL_CHECK(set_xbox_actuators(handle, 0, 0)); + } else { + char string[128]; + printf("Retieving string descriptor...\n"); + CALL_CHECK(libusb_get_string_descriptor_ascii(handle, 2, string, 128)); + printf("Got string: \"%s\"\n", string); + } + + if (test_mode = USE_KEY) { + CALL_CHECK(test_mass_storage(handle)); + } printf("Releasing interface...\n"); CALL_CHECK(libusb_release_interface(handle, iface)); @@ -115,26 +201,48 @@ int test_device(uint16_t vid, uint16_t pid) return 0; } -int main(void) +int main(int argc, char** argv) { - libusb_device **devs; int r; - ssize_t cnt; + + // Default test = Microsoft XBox Controller Type S + VID = 0x045E; + PID = 0x0289; + test_mode = USE_XBOX; + + if (argc == 2) { + if ((argv[1][0] != '-') || (argv[1][1] == 'h')) { + printf("usage: %s [-h] [-j] [-k] [-x]\n", argv[0]); + printf(" -h: display usage\n"); + printf(" -j: test OLIMEX ARM-USB-TINY JTAG, 2 channel composite device\n"); + printf(" -k: test Generic 2 GB USB Key\n"); + printf(" -x: test Microsoft XBox Controller Type S\n"); + return 0; + } + switch(argv[1][1]) { + case 'j': + // OLIMEX ARM-USB-TINY JTAG, 2 channel composite device + VID = 0x15BA; + PID = 0x0004; + test_mode = USE_JTAG; + break; + case 'k': + // Generic 2 GB USB Key (SCSI Transparent/Bulk Only) + VID = 0x0204; + PID = 0x6025; + test_mode = USE_KEY; + break; + default: + break; + } + } r = libusb_init(NULL); if (r < 0) return r; -/* - cnt = libusb_get_device_list(NULL, &devs); - if (cnt < 0) - return (int) cnt; -*/ -// print_devs(devs); test_device(VID, PID); -// libusb_free_device_list(devs, 1); - libusb_exit(NULL); return 0; } |