From 38d863f1f70a35850e983f4ecb4ae3feae84fff1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?R=C3=A9mi=20Bernon?= Date: Fri, 25 Jun 2021 10:06:52 +0200 Subject: [PATCH] hid: Rewrite HidP_GetScaledUsageValue using enum_value_caps. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: RĂ©mi Bernon Signed-off-by: Alexandre Julliard --- dlls/hid/hidp.c | 137 ++++++++++--------------------------- dlls/ntoskrnl.exe/tests/ntoskrnl.c | 4 -- 2 files changed, 36 insertions(+), 105 deletions(-) diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c index 948f0c7c4dc..59f18276b38 100644 --- a/dlls/hid/hidp.c +++ b/dlls/hid/hidp.c @@ -217,70 +217,6 @@ NTSTATUS WINAPI HidP_GetCaps( PHIDP_PREPARSED_DATA preparsed_data, HIDP_CAPS *ca return HIDP_STATUS_SUCCESS; } -static NTSTATUS find_usage(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, - USAGE Usage, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, - USHORT bit_size, WINE_HID_ELEMENT *element) -{ - PWINE_HIDP_PREPARSED_DATA data = (PWINE_HIDP_PREPARSED_DATA)PreparsedData; - WINE_HID_ELEMENT *elems = HID_ELEMS(data); - WINE_HID_REPORT *report = NULL; - USHORT v_count = 0, r_count = 0; - int i; - - TRACE("(%i, %x, %i, %i, %p, %p)\n", ReportType, UsagePage, LinkCollection, Usage, - PreparsedData, Report); - - if (data->magic != HID_MAGIC) - return HIDP_STATUS_INVALID_PREPARSED_DATA; - switch(ReportType) - { - case HidP_Input: - v_count = data->caps.NumberInputValueCaps; - break; - case HidP_Output: - v_count = data->caps.NumberOutputValueCaps; - break; - case HidP_Feature: - v_count = data->caps.NumberFeatureValueCaps; - break; - default: - return HIDP_STATUS_INVALID_REPORT_TYPE; - } - r_count = data->reportCount[ReportType]; - report = &data->reports[data->reportIdx[ReportType][(BYTE)Report[0]]]; - - if (!r_count || !v_count) - return HIDP_STATUS_USAGE_NOT_FOUND; - - if (report->reportID && report->reportID != Report[0]) - return HIDP_STATUS_REPORT_DOES_NOT_EXIST; - - for (i = 0; i < report->elementCount; i++) - { - HIDP_VALUE_CAPS *value = &elems[report->elementIdx + i].caps; - - if ((elems[report->elementIdx + i].caps.BitSize == 1) != (bit_size == 1) || - value->UsagePage != UsagePage) - continue; - - if (value->IsRange && value->Range.UsageMin <= Usage && Usage <= value->Range.UsageMax) - { - *element = elems[report->elementIdx + i]; - element->valueStartBit += value->BitSize * (Usage - value->Range.UsageMin); - element->bitCount = elems[report->elementIdx + i].caps.BitSize; - return HIDP_STATUS_SUCCESS; - } - else if (value->NotRange.Usage == Usage) - { - *element = elems[report->elementIdx + i]; - element->bitCount = elems[report->elementIdx + i].caps.BitSize; - return HIDP_STATUS_SUCCESS; - } - } - - return HIDP_STATUS_USAGE_NOT_FOUND; -} - struct usage_value_params { void *value_buf; @@ -288,53 +224,52 @@ struct usage_value_params void *report_buf; }; -static LONG sign_extend(ULONG value, const WINE_HID_ELEMENT *element) +static LONG sign_extend( ULONG value, const struct hid_value_caps *caps ) { - UINT bit_count = element->bitCount; - - if ((value & (1 << (bit_count - 1))) - && element->caps.BitSize != 1 - && element->caps.LogicalMin < 0) - { - value -= (1 << bit_count); - } - return value; + UINT sign = 1 << (caps->bit_size - 1); + if (sign <= 1 || caps->logical_min >= 0) return value; + return value - ((value & sign) << 1); } -static LONG logical_to_physical(LONG value, const WINE_HID_ELEMENT *element) +static NTSTATUS get_scaled_usage_value( const struct hid_value_caps *caps, void *user ) { - if (element->caps.PhysicalMin || element->caps.PhysicalMax) - { - value = (((ULONGLONG)(value - element->caps.LogicalMin) - * (element->caps.PhysicalMax - element->caps.PhysicalMin)) - / (element->caps.LogicalMax - element->caps.LogicalMin)) - + element->caps.PhysicalMin; - } - return value; + struct usage_value_params *params = user; + ULONG unsigned_value = 0, bit_count = caps->bit_size * caps->report_count; + LONG signed_value, *value = params->value_buf; + + if ((bit_count + 7) / 8 > sizeof(unsigned_value)) return HIDP_STATUS_BUFFER_TOO_SMALL; + if (sizeof(LONG) > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL; + copy_bits( (unsigned char *)&unsigned_value, params->report_buf, bit_count, -caps->start_bit ); + signed_value = sign_extend( unsigned_value, caps ); + + if (caps->logical_min > caps->logical_max || caps->physical_min > caps->physical_max) + return HIDP_STATUS_BAD_LOG_PHY_VALUES; + if (caps->logical_min > signed_value || caps->logical_max < signed_value) + return HIDP_STATUS_VALUE_OUT_OF_RANGE; + + if (!caps->physical_min && !caps->physical_max) *value = signed_value; + else *value = caps->physical_min + MulDiv( signed_value - caps->logical_min, caps->physical_max - caps->physical_min, + caps->logical_max - caps->logical_min ); + return HIDP_STATUS_NULL; } -NTSTATUS WINAPI HidP_GetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, - USHORT LinkCollection, USAGE Usage, PLONG UsageValue, - PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength) +NTSTATUS WINAPI HidP_GetScaledUsageValue( HIDP_REPORT_TYPE report_type, USAGE usage_page, USHORT collection, + USAGE usage, LONG *value, PHIDP_PREPARSED_DATA preparsed_data, + char *report_buf, ULONG report_len ) { - NTSTATUS rc; - WINE_HID_ELEMENT element; - TRACE("(%i, %x, %i, %i, %p, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, Usage, UsageValue, - PreparsedData, Report, ReportLength); + struct usage_value_params params = {.value_buf = value, .value_len = sizeof(*value), .report_buf = report_buf}; + WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data; + struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage }; + USHORT count = 1; - rc = find_usage(ReportType, UsagePage, LinkCollection, Usage, PreparsedData, Report, 0, &element); + TRACE( "report_type %d, usage_page %x, collection %d, usage %x, value %p, preparsed_data %p, report_buf %p, report_len %u.\n", + report_type, usage_page, collection, usage, value, preparsed_data, report_buf, report_len ); - if (rc == HIDP_STATUS_SUCCESS) - { - ULONG rawValue; - rc = get_report_data((BYTE*)Report, ReportLength, - element.valueStartBit, element.bitCount, &rawValue); - if (rc != HIDP_STATUS_SUCCESS) - return rc; - *UsageValue = logical_to_physical(sign_extend(rawValue, &element), &element); - } + *value = 0; + if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH; - return rc; + filter.report_id = report_buf[0]; + return enum_value_caps( preparsed, report_type, report_len, &filter, get_scaled_usage_value, ¶ms, &count ); } static NTSTATUS get_usage_value( const struct hid_value_caps *caps, void *user ) diff --git a/dlls/ntoskrnl.exe/tests/ntoskrnl.c b/dlls/ntoskrnl.exe/tests/ntoskrnl.c index b29660d4773..432bc168259 100644 --- a/dlls/ntoskrnl.exe/tests/ntoskrnl.c +++ b/dlls/ntoskrnl.exe/tests/ntoskrnl.c @@ -2085,9 +2085,7 @@ static void test_hidp(HANDLE file, int report_id) value = 0xdeadbeef; status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); - todo_wine ok(status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status); - todo_wine ok(value == 0, "got value %x, expected %#x\n", value, 0); value = 0xdeadbeef; status = HidP_GetUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, @@ -2103,7 +2101,6 @@ static void test_hidp(HANDLE file, int report_id) status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z, (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status); - todo_wine ok(value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff); value = 0; @@ -2133,7 +2130,6 @@ static void test_hidp(HANDLE file, int report_id) value = 0xdeadbeef; status = HidP_GetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY, (LONG *)&value, preparsed_data, report, caps.InputReportByteLength); - todo_wine ok(status == HIDP_STATUS_BAD_LOG_PHY_VALUES, "HidP_GetScaledUsageValue returned %#x\n", status); ok(value == 0, "got value %x, expected %#x\n", value, 0); -- 2.11.4.GIT