Get the HID descriptor from the already retrieved configuration info instead of

always calling the device and requesting it. If no HID descriptor is found in
the configuration we fall back to retrieving it manually and if that fails we
fall back to a dummy report descriptor length. In the most usual case this will
save one unnecessary USB control request.

Incidentally this also fixes the absolute pointing device under VirtualBox. VBox
stalled the retrieval of the HID descriptor. That alone wasn't so problematic as
in this case we just fell back to the dummy report descriptor length which
would've been large enough. But VBox also times out the next request after the
stall, which in this case was the retrieval of the report descriptor, hence no
HIDDevice could be created.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@42019 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Lotz 2011-06-07 18:17:08 +00:00
parent 8a480e5d69
commit 7802e2dd2c

View File

@ -60,31 +60,55 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config,
}
if (!hasFixedDescriptor) {
// 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;
// Conforming device, find the HID descriptor and get the report
// descriptor from the device.
usb_hid_descriptor *hidDescriptor = NULL;
const usb_interface_info *interfaceInfo
= config->interface[interfaceIndex].active;
for (size_t i = 0; i < interfaceInfo->generic_count; i++) {
const usb_generic_descriptor &generic
= interfaceInfo->generic[i]->generic;
if (generic.descriptor_type == B_USB_HID_DESCRIPTOR_HID) {
hidDescriptor = (usb_hid_descriptor *)&generic;
descriptorLength
= hidDescriptor->descriptor_info[0].descriptor_length;
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 (hidDescriptor == NULL) {
TRACE_ALWAYS("didn't find a HID descriptor in the configuration, "
"trying to retrieve manually\n");
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 */
descriptorLength = sizeof(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;
}
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);
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 */
TRACE_ALWAYS("failed to get HID descriptor, trying with a "
"fallback report descriptor length of %lu\n",
descriptorLength);
}
free(hidDescriptor);
}
reportDescriptor = (uint8 *)malloc(descriptorLength);
if (reportDescriptor == NULL) {
@ -93,7 +117,7 @@ HIDDevice::HIDDevice(usb_device device, const usb_configuration_info *config,
return;
}
result = gUSBModule->send_request(device,
status_t result = gUSBModule->send_request(device,
USB_REQTYPE_INTERFACE_IN | USB_REQTYPE_STANDARD,
USB_REQUEST_GET_DESCRIPTOR,
B_USB_HID_DESCRIPTOR_REPORT << 8, interfaceIndex, descriptorLength,