New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 781221 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner: ----
Closed: Nov 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux , Chrome
Pri: 1
Type: Bug



Sign in to add a comment

HID descriptor parsing issue when the HID report includes short items with bSize = 3

Reported by vpalatin@chromium.org, Nov 3 2017

Issue description

Chrome 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

 
HID_short_items.png
44.4 KB View Download
I have sent a Chromium CL with the fix above:
https://chromium-review.googlesource.com/c/chromium/src/+/753327 
Project Member

Comment 2 by bugdroid1@chromium.org, 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

Status: Fixed (was: Untriaged)

Sign in to add a comment