DualSense controller's report descriptor comes with a 1 bit vendor specific (Usage Page & Usage) element repeated through 'report count'.
Those were correctly interpreted as non-ranged buttons (exposed as button caps with appropriate usage values) but their size was incorrectly assumed to be 1 ignoring the 'report count'.
Because of that the InputReportByteLength is miscalculated as 63 instead of 64. If the buffer passed to HidD_GetInputReport() is allocated using that value the call will fail with ERROR_INSUFFICIENT_BUFFER.
This change fixes the above and cleans up the code a bit so the size for each case is calculated directly from the count and size instead of using the values that were derived from them.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com --- dlls/hidclass.sys/descriptor.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 56e4da4ad10..c02988494fd 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -698,6 +698,10 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems }
wine_element->valueStartBit = wine_report->bitSize; + + wine_element->bitCount = (feature->caps.BitSize * feature->caps.ReportCount); + wine_report->bitSize += wine_element->bitCount; + if (feature->caps.BitSize == 1) { wine_element->ElementType = ButtonElement; @@ -713,8 +717,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems wine_element->caps.button.IsAbsolute = feature->IsAbsolute; if (wine_element->caps.button.IsRange) { - wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1; - wine_report->bitSize += wine_element->bitCount; wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin; wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax; wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin; @@ -727,8 +729,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems } else { - wine_report->bitSize++; - wine_element->bitCount = 1; wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage; wine_element->caps.button.u.NotRange.Reserved1 = feature->caps.u.NotRange.Usage; wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex; @@ -756,8 +756,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems wine_element->caps.value.HasNull = feature->HasNull; wine_element->caps.value.BitSize = feature->caps.BitSize; wine_element->caps.value.ReportCount = feature->caps.ReportCount; - wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount); - wine_report->bitSize += wine_element->bitCount; wine_element->caps.value.UnitsExp = feature->caps.UnitsExp; wine_element->caps.value.Units = feature->caps.Units; wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;
Signed-off-by: Aric Stewart aric@codeweavers.com
On 1/21/21 10:11 AM, Arkadiusz Hiler wrote:
DualSense controller's report descriptor comes with a 1 bit vendor specific (Usage Page & Usage) element repeated through 'report count'.
Those were correctly interpreted as non-ranged buttons (exposed as button caps with appropriate usage values) but their size was incorrectly assumed to be 1 ignoring the 'report count'.
Because of that the InputReportByteLength is miscalculated as 63 instead of 64. If the buffer passed to HidD_GetInputReport() is allocated using that value the call will fail with ERROR_INSUFFICIENT_BUFFER.
This change fixes the above and cleans up the code a bit so the size for each case is calculated directly from the count and size instead of using the values that were derived from them.
Signed-off-by: Arkadiusz Hiler ahiler@codeweavers.com
dlls/hidclass.sys/descriptor.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c index 56e4da4ad10..c02988494fd 100644 --- a/dlls/hidclass.sys/descriptor.c +++ b/dlls/hidclass.sys/descriptor.c @@ -698,6 +698,10 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems }
wine_element->valueStartBit = wine_report->bitSize;
- wine_element->bitCount = (feature->caps.BitSize * feature->caps.ReportCount);
- wine_report->bitSize += wine_element->bitCount;
if (feature->caps.BitSize == 1) { wine_element->ElementType = ButtonElement;
@@ -713,8 +717,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems wine_element->caps.button.IsAbsolute = feature->IsAbsolute; if (wine_element->caps.button.IsRange) {
wine_element->bitCount = (feature->caps.u.Range.UsageMax - feature->caps.u.Range.UsageMin) + 1;
wine_report->bitSize += wine_element->bitCount; wine_element->caps.button.u.Range.UsageMin = feature->caps.u.Range.UsageMin; wine_element->caps.button.u.Range.UsageMax = feature->caps.u.Range.UsageMax; wine_element->caps.button.u.Range.StringMin = feature->caps.u.Range.StringMin;
@@ -727,8 +729,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems } else {
wine_report->bitSize++;
wine_element->bitCount = 1; wine_element->caps.button.u.NotRange.Usage = feature->caps.u.NotRange.Usage; wine_element->caps.button.u.NotRange.Reserved1 = feature->caps.u.NotRange.Usage; wine_element->caps.button.u.NotRange.StringIndex = feature->caps.u.NotRange.StringIndex;
@@ -756,8 +756,6 @@ static void build_elements(WINE_HID_REPORT *wine_report, WINE_HID_ELEMENT *elems wine_element->caps.value.HasNull = feature->HasNull; wine_element->caps.value.BitSize = feature->caps.BitSize; wine_element->caps.value.ReportCount = feature->caps.ReportCount;
wine_element->bitCount = (feature->caps.BitSize * wine_element->caps.value.ReportCount);
wine_report->bitSize += wine_element->bitCount; wine_element->caps.value.UnitsExp = feature->caps.UnitsExp; wine_element->caps.value.Units = feature->caps.Units; wine_element->caps.value.LogicalMin = feature->caps.LogicalMin;