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
This commit is contained in:
Michael Lotz 2011-03-17 22:21:55 +00:00
parent 02845142e3
commit 6339610f44
2 changed files with 95 additions and 41 deletions

View File

@ -11,6 +11,7 @@
#include "HIDDevice.h"
#include "HIDReport.h"
#include "ProtocolHandler.h"
#include "QuirkyDevices.h"
#include <usb/USB_hid.h>
@ -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;

View File

@ -0,0 +1,27 @@
/*
* Copyright 2011 Michael Lotz <mmlr@mlotz.ch>
* 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