diff options
author | Pete Batard <pbatard@gmail.com> | 2010-01-23 23:28:55 +0000 |
---|---|---|
committer | Pete Batard <pbatard@gmail.com> | 2010-01-23 23:28:55 +0000 |
commit | 628bd43bc24319f82a6ca63265b55adce438c9b5 (patch) | |
tree | a45f752fdc0d9b3cc034bc437dbcc7dcf20ef819 | |
parent | 6b34ff4ed72e3c52b4c927946b4fb0a233c24044 (diff) | |
download | libusb-628bd43bc24319f82a6ca63265b55adce438c9b5.tar.gz |
r105: added MS Sidewinder HID test in xusb.c + minor changes/improvements
-rw-r--r-- | examples/xusb.c | 90 | ||||
-rw-r--r-- | libusb/os/windows_usb.c | 12 | ||||
-rw-r--r-- | libusb/os/windows_usb.h | 2 |
3 files changed, 91 insertions, 13 deletions
diff --git a/examples/xusb.c b/examples/xusb.c index adad6ce..05a4610 100644 --- a/examples/xusb.c +++ b/examples/xusb.c @@ -117,6 +117,7 @@ enum test_type { USE_KEY, USE_JTAG, USE_HID, + USE_SIDEWINDER, } test_mode; uint16_t VID, PID; @@ -335,6 +336,52 @@ int test_mass_storage(libusb_device_handle *handle) return 0; } +// Plantronics (HID) +int display_plantronics_status(libusb_device_handle *handle) +{ + int r; + uint8_t input_report[2]; + printf("Reading Plantronics Input Report...\n"); + r = 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, 2, 5000); + if (r >= 0) { + printf(" OK\n"); + } else { + switch(r) { + case LIBUSB_ERROR_TIMEOUT: + printf(" Timeout! Please make sure you press the mute button within the 5 seconds allocated...\n"); + break; + default: + printf(" Error: %d\n", r); + break; + } + } + return 0; +} + +// SideWinder (HID) +int display_sidewinder_status(libusb_device_handle *handle) +{ + int r; + uint8_t input_report[6]; + printf("Reading SideWinder Input Report.\n"); + r = 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, 6, 5000); + if (r >= 0) { + printf(" OK\n"); + } else { + switch(r) { + case LIBUSB_ERROR_TIMEOUT: + printf(" Timeout! Please make sure you use the joystick within the 5 seconds allocated...\n\n"); + break; + default: + printf(" Error: %d\n", r); + break; + } + } + return 0; +} + int test_device(uint16_t vid, uint16_t pid) { libusb_device_handle *handle; @@ -342,9 +389,10 @@ int test_device(uint16_t vid, uint16_t pid) struct libusb_config_descriptor *conf_desc; const struct libusb_endpoint_descriptor *endpoint; int i, j, k, r; - int iface, nb_ifaces; + int iface, nb_ifaces, nb_strings; int test_scsi = 0; struct libusb_device_descriptor dev_desc; + char string[128]; printf("Opening device...\n"); handle = libusb_open_device_with_vid_pid(NULL, vid, pid); @@ -394,6 +442,8 @@ int test_device(uint16_t vid, uint16_t pid) } libusb_free_config_descriptor(conf_desc); + // On Windows, autoclaim will sort things out +#ifndef OS_WINDOWS for (iface = 0; iface < nb_ifaces; iface++) { printf("Claiming interface %d...\n", iface); @@ -410,17 +460,34 @@ int test_device(uint16_t vid, uint16_t pid) } } } +#endif - if (test_mode == USE_XBOX) { + r = libusb_get_string_descriptor(handle, 0, 0, string, 128); + if (r > 0) { + nb_strings = string[0]; + printf("Retrieving string descriptors...\n"); + for (i=1; i<nb_strings; i++) { + if (libusb_get_string_descriptor_ascii(handle, i, string, 128) >= 0) { + printf("string (%d/%d): \"%s\"\n", i, nb_strings-1, string); + } + } + } + + switch(test_mode) { + case 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); + break; + case USE_SIDEWINDER: + display_sidewinder_status(handle); + break; + case USE_HID: + display_plantronics_status(handle); + break; + default: + break; } if (test_scsi) { @@ -449,11 +516,12 @@ int main(int argc, char** argv) if (argc == 2) { if ((argv[1][0] != '-') || (argv[1][1] == 'h')) { - printf("usage: %s [-h] [-i] [-j] [-k] [-l] [-x]\n", argv[0]); + printf("usage: %s [-h] [-i] [-j] [-k] [-l] [-s] [-x]\n", argv[0]); printf(" -h: display usage\n"); printf(" -i: test IBM HID Optical Mouse\n"); printf(" -j: test OLIMEX ARM-USB-TINY JTAG, 2 channel composite device\n"); printf(" -k: test Generic 2 GB USB Key\n"); + printf(" -s: test Microsoft Sidwinder Precision Pro\n"); printf(" -x: test Microsoft XBox Controller Type S (default)\n"); return 0; } @@ -482,6 +550,12 @@ int main(int argc, char** argv) PID = 0x0CA1; test_mode = USE_HID; break; + case 's': + // Microsoft Sidewinder Precision Pro Joystick - 1 HID interface + VID = 0x045E; + PID = 0x0008; + test_mode = USE_SIDEWINDER; + break; default: break; } diff --git a/libusb/os/windows_usb.c b/libusb/os/windows_usb.c index 3c8b7f6..9f38fbc 100644 --- a/libusb/os/windows_usb.c +++ b/libusb/os/windows_usb.c @@ -2774,14 +2774,16 @@ static int _hid_get_report(struct hid_device_priv* dev, HANDLE hid_handle, int i *size += 1; // Use ReadFile instead of HidD_GetInputReport for async I/O + // NB: HidD_GetInputReport returns the last Input Report read whereas ReadFile + // waits for input to be generated => in case your HID device requires human + // action to generate a report, it may wait indefinitely + // TODO: give users a choice? if (!ReadFile(hid_handle, buf, *size, NULL, overlapped)) { - if(GetLastError() != ERROR_IO_PENDING) { - usbi_dbg("READFILE FAILED"); + if (GetLastError() != ERROR_IO_PENDING) { + usbi_dbg("Failed to Read HID Input Report: %s", windows_error_str(0)); return LIBUSB_ERROR_IO; } - usbi_dbg("IO_PENDING"); } else { - usbi_dbg("IO_SYNC"); return LIBUSB_COMPLETED; } @@ -2803,6 +2805,7 @@ static int _hid_set_report(struct hid_device_priv* dev, HANDLE hid_handle, int i // Une WriteFile instead of HidD_SetOutputReport for async I/O if (!WriteFile(hid_handle, buf, *size, NULL, overlapped)) { if (GetLastError() != ERROR_IO_PENDING) { + usbi_dbg("Failed to Write HID Output Report: %s", windows_error_str(0)); return LIBUSB_ERROR_IO; } } else { @@ -2936,6 +2939,7 @@ static int hid_open(struct libusb_device_handle *dev_handle) && (priv->usb_interface[i].apib->id == USB_API_HID) ) { hid_handle = CreateFileA(priv->usb_interface[i].path, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL); + usbi_dbg("hid_handle = %p", hid_handle); /* * http://www.lvr.com/hidfaq.htm: Why do I receive "Access denied" when attempting to access my HID? * "Windows 2000 and later have exclusive read/write access to HIDs that are configured as a system diff --git a/libusb/os/windows_usb.h b/libusb/os/windows_usb.h index 58fc9b2..582605f 100644 --- a/libusb/os/windows_usb.h +++ b/libusb/os/windows_usb.h @@ -83,7 +83,7 @@ inline void upperize(char* str) { // Handle code for HID interface that have been claimed ("dibs") #define INTERFACE_CLAIMED ((HANDLE)0xD1B5) // Additional return code for HID operations that completed synchronously -#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) +#define LIBUSB_COMPLETED (LIBUSB_SUCCESS + 1) #define wchar_to_utf8_ms(wstr, str, strlen) WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, strlen, NULL, NULL) |