From 6339610f44c98bf70526ab1f27a82fd141381518 Mon Sep 17 00:00:00 2001 From: Michael Lotz Date: Thu, 17 Mar 2011 22:21:55 +0000 Subject: [PATCH] Add a way to override report descriptors with fixed ones based on vendor and product id. Currently the list only has an example entry. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@41017 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../drivers/input/usb_hid/HIDDevice.cpp | 109 +++++++++++------- .../drivers/input/usb_hid/QuirkyDevices.h | 27 +++++ 2 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h diff --git a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp index b883014a36..d4cf3e426a 100644 --- a/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp +++ b/src/add-ons/kernel/drivers/input/usb_hid/HIDDevice.cpp @@ -11,6 +11,7 @@ #include "HIDDevice.h" #include "HIDReport.h" #include "ProtocolHandler.h" +#include "QuirkyDevices.h" #include @@ -36,55 +37,78 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, fProtocolHandlerCount(0), fProtocolHandlers(NULL) { - // read HID descriptor - size_t descriptorLength = sizeof(usb_hid_descriptor); - usb_hid_descriptor *hidDescriptor - = (usb_hid_descriptor *)malloc(descriptorLength); - if (hidDescriptor == NULL) { - TRACE_ALWAYS("failed to allocate buffer for hid descriptor\n"); - fStatus = B_NO_MEMORY; - return; + uint8 *reportDescriptor = NULL; + size_t descriptorLength = 0; + bool isQuirky = false; + + const usb_device_descriptor *deviceDescriptor + = gUSBModule->get_device_descriptor(device); + + // check for quirky devices first and don't bother in that case + for (int32 i = 0; i < sQuirkyDeviceCount; i++) { + usb_hid_quirky_device &quirky = sQuirkyDevices[i]; + if (deviceDescriptor->vendor_id == quirky.vendor_id + && deviceDescriptor->product_id == quirky.product_id) { + reportDescriptor = (uint8 *)quirky.fixed_descriptor; + descriptorLength = quirky.descriptor_length; + isQuirky = true; + break; + } } - status_t result = gUSBModule->send_request(device, - USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD, - USB_REQUEST_GET_DESCRIPTOR, - B_USB_HID_DESCRIPTOR_HID << 8, interfaceIndex, descriptorLength, - hidDescriptor, &descriptorLength); + if (!isQuirky) { + // conforming device, read HID and report descriptors + descriptorLength = sizeof(usb_hid_descriptor); + usb_hid_descriptor *hidDescriptor + = (usb_hid_descriptor *)malloc(descriptorLength); + if (hidDescriptor == NULL) { + TRACE_ALWAYS("failed to allocate buffer for hid descriptor\n"); + fStatus = B_NO_MEMORY; + return; + } - TRACE("get hid descriptor: result: 0x%08lx; length: %lu\n", result, - descriptorLength); - if (result == B_OK) - descriptorLength = hidDescriptor->descriptor_info[0].descriptor_length; - else - descriptorLength = 256; /* XXX */ - free(hidDescriptor); + status_t result = gUSBModule->send_request(device, + USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD, + USB_REQUEST_GET_DESCRIPTOR, + B_USB_HID_DESCRIPTOR_HID << 8, interfaceIndex, descriptorLength, + hidDescriptor, &descriptorLength); - uint8 *reportDescriptor = (uint8 *)malloc(descriptorLength); - if (reportDescriptor == NULL) { - TRACE_ALWAYS("failed to allocate buffer for report descriptor\n"); - fStatus = B_NO_MEMORY; - return; - } + TRACE("get hid descriptor: result: 0x%08lx; length: %lu\n", result, + descriptorLength); + if (result == B_OK) { + descriptorLength + = hidDescriptor->descriptor_info[0].descriptor_length; + } else + descriptorLength = 256; /* XXX */ - result = gUSBModule->send_request(device, - USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD, - USB_REQUEST_GET_DESCRIPTOR, - B_USB_HID_DESCRIPTOR_REPORT << 8, interfaceIndex, descriptorLength, - reportDescriptor, &descriptorLength); + free(hidDescriptor); - TRACE("get report descriptor: result: 0x%08lx; length: %lu\n", result, - descriptorLength); - if (result != B_OK) { - TRACE_ALWAYS("failed tot get report descriptor\n"); - free(reportDescriptor); - return; + reportDescriptor = (uint8 *)malloc(descriptorLength); + if (reportDescriptor == NULL) { + TRACE_ALWAYS("failed to allocate buffer for report descriptor\n"); + fStatus = B_NO_MEMORY; + return; + } + + result = gUSBModule->send_request(device, + USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD, + USB_REQUEST_GET_DESCRIPTOR, + B_USB_HID_DESCRIPTOR_REPORT << 8, interfaceIndex, descriptorLength, + reportDescriptor, &descriptorLength); + + TRACE("get report descriptor: result: 0x%08lx; length: %lu\n", result, + descriptorLength); + if (result != B_OK) { + TRACE_ALWAYS("failed tot get report descriptor\n"); + free(reportDescriptor); + return; + } + } else { + TRACE_ALWAYS("found quirky device, using patched descriptor\n"); } #if 1 // save report descriptor for troubleshooting - const usb_device_descriptor *deviceDescriptor - = gUSBModule->get_device_descriptor(device); char outputFile[128]; sprintf(outputFile, "/tmp/usb_hid_report_descriptor_%04x_%04x_%lu.bin", deviceDescriptor->vendor_id, deviceDescriptor->product_id, @@ -96,8 +120,11 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config, } #endif - result = fParser.ParseReportDescriptor(reportDescriptor, descriptorLength); - free(reportDescriptor); + status_t result = fParser.ParseReportDescriptor(reportDescriptor, + descriptorLength); + if (!isQuirky) + free(reportDescriptor); + if (result != B_OK) { TRACE_ALWAYS("parsing the report descriptor failed\n"); fStatus = result; diff --git a/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h new file mode 100644 index 0000000000..fe7c251b85 --- /dev/null +++ b/src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h @@ -0,0 +1,27 @@ +/* + * Copyright 2011 Michael Lotz + * Distributed under the terms of the MIT license. + */ +#ifndef USB_HID_QUIRKY_DEVICES +#define USB_HID_QUIRKY_DEVICES + +static uint8 sDescriptorExample[] = { 0x00, 0x00 }; + +struct usb_hid_quirky_device { + uint16 vendor_id; + uint16 product_id; + size_t descriptor_length; + const uint8 * fixed_descriptor; +}; + +#define ADD_QUIRKY_DEVICE(vendorID, productID, descriptor) \ + { vendorID, productID, sizeof(descriptor), descriptor } + +static usb_hid_quirky_device sQuirkyDevices[] = { + ADD_QUIRKY_DEVICE(0xffff, 0xffff, sDescriptorExample) +}; + +static int32 sQuirkyDeviceCount + = sizeof(sQuirkyDevices) / sizeof(sQuirkyDevices[0]); + +#endif // USB_HID_QUIRKY_DEVICES