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:
parent
02845142e3
commit
6339610f44
@ -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;
|
||||
|
27
src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h
Normal file
27
src/add-ons/kernel/drivers/input/usb_hid/QuirkyDevices.h
Normal 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
|
Loading…
Reference in New Issue
Block a user