summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPete Batard <pbatard@gmail.com>2010-01-23 23:28:55 +0000
committerPete Batard <pbatard@gmail.com>2010-01-23 23:28:55 +0000
commit628bd43bc24319f82a6ca63265b55adce438c9b5 (patch)
treea45f752fdc0d9b3cc034bc437dbcc7dcf20ef819
parent6b34ff4ed72e3c52b4c927946b4fb0a233c24044 (diff)
downloadlibusb-628bd43bc24319f82a6ca63265b55adce438c9b5.tar.gz
r105: added MS Sidewinder HID test in xusb.c + minor changes/improvements
-rw-r--r--examples/xusb.c90
-rw-r--r--libusb/os/windows_usb.c12
-rw-r--r--libusb/os/windows_usb.h2
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)