HID descriptor parsing issue when the HID report includes short items with bSize = 3
Reported by
vpalatin@chromium.org,
Nov 3 2017
|
||
Issue descriptionChrome Version: OS: all ? What steps will reproduce the problem? (1) Attach LG UltraFine 4K Display (2) In a Chrome.extension, open its HID device (available on its USB interface with VID:PID 043e:9a40) (3) read 'maxFeatureReportSize' in HidDeviceInfo What is the expected result? maxFeatureReportSize is equal to 6 and the screen answers 6-byte (including the current brightness in the 4 first) when using chrome.hid.receiveFeatureReport(connectionId, 0, callback) What happens instead? maxFeatureReportSize is equal to 2 and the USB transfer triggered by chrome.hid.receiveFeatureReport() fails. The chrome://device-log shows "Failed to get feature report: Value too large for defined data type (75)" Meaning that in Chrome, the ioctl(fd_.get(), HIDIOCGFEATURE(buffer->size()), buffer->data()) returns EOVERFLOW. On this chromebook, looking at the kernel, this likely means that the actual USB transfer fails due to a 'babble' of the USB device. so, it might be because we ask for 2 bytes and the screen tries to return more (which is not compliant with USB spec too ...). internal discussion is on https://goo.gl/oc11wc, summary here: The HID report descriptor of the screen is the following: 0x05, 0x80, // Usage Page (Monitor Pages) 0x09, 0x01, // Usage (0x01) 0xA1, 0x01, // Collection (Application) 0x06, 0x82, 0x00, // Usage Page (Monitor Pages) 0x09, 0x10, // Usage (0x10) 0x15, 0x04, // Logical Minimum (4) 0x26, 0x1C, 0x02, // Logical Maximum (540) 0x67, 0xE1, 0x00, 0x00, 0x01, // Unit (System: SI Linear, Luminous Intensity: Candela) 0x55, 0x0E, // Unit Exponent (-2) 0x75, 0x20, // Report Size (32) 0x95, 0x01, // Report Count (1) 0xB1, 0x42, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State,Non-volatile) 0x06, 0x82, 0x00, // Usage Page (Monitor Pages) 0x09, 0x10, // Usage (0x10) 0x67, 0xE1, 0x00, 0x00, 0x01, // Unit (System: SI Linear, Luminous Intensity: Candela) 0x55, 0x0E, // Unit Exponent (-2) 0x75, 0x20, // Report Size (32) 0x95, 0x01, // Report Count (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x05, 0x0F, // Usage Page (PID Page) 0x09, 0x50, // Usage (0x50) 0x66, 0x10, 0x01, // Unit (Length: Centimeter, Mass: Gram) 0x55, 0x0D, // Unit Exponent (-3) 0x75, 0x10, // Report Size (16) 0xB1, 0x42, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State,Non-volatile) 0xC0, // End Collection When I run it through device/hid/hid_report_descriptor_unittest.cc, I'm getting: actual_max_input_report_size == 0 actual_max_output_report_size == 0 actual_max_feature_report_size == 2 while I would have expected (by reading the report descriptor): actual_max_input_report_size == 4 actual_max_output_report_size == 0 actual_max_feature_report_size == 6 When tracing the unittest execution, it's getting lost on 0x67, 0xE1, 0x00, 0x00, 0x01, The tag starting with 0x67 is a 'short item' for the HID spec (with bTag == 6 aka Unit, bType == 1 aka Global, bSize == 3) But the trick is that according to the HID 1.1 spec: bSize == 3 means that *4* bytes are following (see picture of the spec attached) Trying the following fix: --- a/device/hid/hid_report_descriptor_item.cc +++ b/device/hid/hid_report_descriptor_item.cc @@ -37,7 +37,7 @@ HidReportDescriptorItem::HidReportDescriptorItem( if (size >= 2) payload_size_ = bytes[1]; } else { - payload_size_ = header->size; + payload_size_ = header->size == 0x3 ? 4 : header->size; DCHECK(payload_size_ <= sizeof(shortData_)); if (GetHeaderSize() + payload_size() <= size) memcpy(&shortData_, &bytes[GetHeaderSize()], payload_size()); I'm getting the expected: actual_max_input_report_size == 4 actual_max_output_report_size == 0 actual_max_feature_report_size == 6
,
Nov 4 2017
The following revision refers to this bug: https://chromium.googlesource.com/chromium/src.git/+/1838f300d3a3051c30402dd2beeb168b84ab3b59 commit 1838f300d3a3051c30402dd2beeb168b84ab3b59 Author: Vincent Palatin <vpalatin@chromium.org> Date: Sat Nov 04 09:43:53 2017 Fix HID report parsing for short items with bSize == 3 In the USB Device Class Definition for Human Interface Devices (HID) specification, the section '6.2.2.2 Short Items' defines the size of the 'short' tag payload as follow: bSize Numeric expression specifying size of data: 0 = 0 bytes 1 = 1 byte 2 = 2 bytes 3 = 4 bytes The current code was assuming that the size in bytes was equal to the bSize value. For a bSize value of 3, it was using only 3 bytes, starting the next tag one byte too early and messing up the parsing of the remaining descriptor (as shown in the bug linked below). The monitor report descriptor in the unittest has been updated to cover this case. The updated unittest was failing before the fix and passing afterwards. BUG= 781221 TESTS=run device_unittests (HidReportDescriptorTest) R=reillyg@chromium.org Change-Id: I8dc33070d5d1a45317c1b38520f01ceef79c6994 Reviewed-on: https://chromium-review.googlesource.com/753327 Reviewed-by: Reilly Grant <reillyg@chromium.org> Commit-Queue: Vincent Palatin <vpalatin@chromium.org> Cr-Commit-Position: refs/heads/master@{#514040} [modify] https://crrev.com/1838f300d3a3051c30402dd2beeb168b84ab3b59/device/hid/hid_report_descriptor_item.cc [modify] https://crrev.com/1838f300d3a3051c30402dd2beeb168b84ab3b59/device/hid/test_report_descriptors.cc
,
Nov 5 2017
|
||
►
Sign in to add a comment |
||
Comment 1 by vpalatin@chromium.org
, Nov 3 2017