hid: Implement HidP_SetScaledUsageValue.
The function seems to actually do overflows and rounding errors. Signed-off-by: Rémi Bernon <rbernon@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
3b40a03267
commit
74b7845ff0
5 changed files with 138 additions and 8 deletions
|
@ -35,7 +35,7 @@
|
|||
@ stdcall HidP_MaxDataListLength(long ptr)
|
||||
@ stdcall HidP_MaxUsageListLength(long long ptr)
|
||||
@ stub HidP_SetData
|
||||
@ stub HidP_SetScaledUsageValue
|
||||
@ stdcall HidP_SetScaledUsageValue(long long long long long ptr ptr long)
|
||||
@ stdcall HidP_SetUsageValue(long long long long long ptr ptr long)
|
||||
@ stdcall HidP_SetUsageValueArray(long long long long ptr long ptr ptr long)
|
||||
@ stdcall HidP_SetUsages(long long long ptr ptr ptr ptr long)
|
||||
|
|
|
@ -380,6 +380,53 @@ ULONG WINAPI HidP_MaxUsageListLength( HIDP_REPORT_TYPE report_type, USAGE usage_
|
|||
return count;
|
||||
}
|
||||
|
||||
static NTSTATUS set_scaled_usage_value( const struct hid_value_caps *caps, void *user )
|
||||
{
|
||||
ULONG bit_count = caps->bit_size * caps->report_count;
|
||||
struct usage_value_params *params = user;
|
||||
LONG value, log_range, phy_range;
|
||||
|
||||
if (caps->logical_min > caps->logical_max) return HIDP_STATUS_BAD_LOG_PHY_VALUES;
|
||||
if (caps->physical_min > caps->physical_max) return HIDP_STATUS_BAD_LOG_PHY_VALUES;
|
||||
|
||||
if ((bit_count + 7) / 8 > sizeof(value)) return HIDP_STATUS_BUFFER_TOO_SMALL;
|
||||
if (sizeof(LONG) > params->value_len) return HIDP_STATUS_BUFFER_TOO_SMALL;
|
||||
value = *(LONG *)params->value_buf;
|
||||
|
||||
if (caps->physical_min || caps->physical_max)
|
||||
{
|
||||
/* testing shows that this is what the function does, including all
|
||||
* the overflows and rounding errors... */
|
||||
log_range = (caps->logical_max - caps->logical_min + 1) / 2;
|
||||
phy_range = (caps->physical_max - caps->physical_min + 1) / 2;
|
||||
value = value - caps->physical_min;
|
||||
value = (log_range * value) / phy_range;
|
||||
value = caps->logical_min + value;
|
||||
}
|
||||
|
||||
copy_bits( params->report_buf, (unsigned char *)&value, bit_count, caps->start_bit );
|
||||
|
||||
return HIDP_STATUS_NULL;
|
||||
}
|
||||
|
||||
NTSTATUS WINAPI HidP_SetScaledUsageValue( 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 )
|
||||
{
|
||||
struct usage_value_params params = {.value_buf = &value, .value_len = sizeof(value), .report_buf = report_buf};
|
||||
struct hid_preparsed_data *preparsed = (struct hid_preparsed_data *)preparsed_data;
|
||||
struct caps_filter filter = {.values = TRUE, .usage_page = usage_page, .collection = collection, .usage = usage };
|
||||
USHORT count = 1;
|
||||
|
||||
TRACE( "report_type %d, usage_page %x, collection %d, usage %x, value %d, preparsed_data %p, report_buf %p, report_len %u.\n",
|
||||
report_type, usage_page, collection, usage, value, preparsed_data, report_buf, report_len );
|
||||
|
||||
if (!report_len) return HIDP_STATUS_INVALID_REPORT_LENGTH;
|
||||
|
||||
filter.report_id = report_buf[0];
|
||||
return enum_value_caps( preparsed, report_type, report_len, &filter, set_scaled_usage_value, ¶ms, &count );
|
||||
}
|
||||
|
||||
static NTSTATUS set_usage_value( const struct hid_value_caps *caps, void *user )
|
||||
{
|
||||
struct usage_value_params *params = user;
|
||||
|
|
|
@ -356,6 +356,16 @@ static NTSTATUS WINAPI driver_internal_ioctl(DEVICE_OBJECT *device, IRP *irp)
|
|||
/* reset global items */
|
||||
UNIT(1, 0), /* None */
|
||||
UNIT_EXPONENT(1, 0),
|
||||
|
||||
USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
|
||||
USAGE(1, HID_USAGE_GENERIC_Z),
|
||||
LOGICAL_MINIMUM(4, 0x0000),
|
||||
LOGICAL_MAXIMUM(4, 0x7fff),
|
||||
PHYSICAL_MINIMUM(4, 0xfff90000),
|
||||
PHYSICAL_MAXIMUM(4, 0x0003ffff),
|
||||
REPORT_SIZE(1, 32),
|
||||
REPORT_COUNT(1, 1),
|
||||
FEATURE(1, Data|Var|Abs),
|
||||
END_COLLECTION,
|
||||
|
||||
USAGE_PAGE(1, HID_USAGE_PAGE_GENERIC),
|
||||
|
|
|
@ -1686,14 +1686,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
|||
.UsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.InputReportByteLength = 26,
|
||||
.OutputReportByteLength = 3,
|
||||
.FeatureReportByteLength = 18,
|
||||
.FeatureReportByteLength = 22,
|
||||
.NumberLinkCollectionNodes = 10,
|
||||
.NumberInputButtonCaps = 17,
|
||||
.NumberInputValueCaps = 7,
|
||||
.NumberInputDataIndices = 47,
|
||||
.NumberFeatureButtonCaps = 1,
|
||||
.NumberFeatureValueCaps = 5,
|
||||
.NumberFeatureDataIndices = 7,
|
||||
.NumberFeatureValueCaps = 6,
|
||||
.NumberFeatureDataIndices = 8,
|
||||
},
|
||||
/* with report id */
|
||||
{
|
||||
|
@ -1701,14 +1701,14 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
|||
.UsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.InputReportByteLength = 25,
|
||||
.OutputReportByteLength = 2,
|
||||
.FeatureReportByteLength = 17,
|
||||
.FeatureReportByteLength = 21,
|
||||
.NumberLinkCollectionNodes = 10,
|
||||
.NumberInputButtonCaps = 17,
|
||||
.NumberInputValueCaps = 7,
|
||||
.NumberInputDataIndices = 47,
|
||||
.NumberFeatureButtonCaps = 1,
|
||||
.NumberFeatureValueCaps = 5,
|
||||
.NumberFeatureDataIndices = 7,
|
||||
.NumberFeatureValueCaps = 6,
|
||||
.NumberFeatureDataIndices = 8,
|
||||
},
|
||||
};
|
||||
const HIDP_BUTTON_CAPS expect_button_caps[] =
|
||||
|
@ -2182,6 +2182,10 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
|||
(LONG *)&value, preparsed_data, report, caps.InputReportByteLength);
|
||||
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);
|
||||
status = HidP_SetScaledUsageValue(HidP_Input, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_RY,
|
||||
0, preparsed_data, report, caps.InputReportByteLength);
|
||||
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);
|
||||
|
||||
value = HidP_MaxUsageListLength(HidP_Feature + 1, 0, preparsed_data);
|
||||
ok(value == 0, "HidP_MaxUsageListLength(HidP_Feature + 1, 0) returned %d, expected %d\n", value, 0);
|
||||
|
@ -2311,7 +2315,7 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
|||
value = HidP_MaxDataListLength(HidP_Output, preparsed_data);
|
||||
ok(value == 0, "HidP_MaxDataListLength(HidP_Output) returned %d, expected %d\n", value, 0);
|
||||
value = HidP_MaxDataListLength(HidP_Feature, preparsed_data);
|
||||
ok(value == 13, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 13);
|
||||
ok(value == 14, "HidP_MaxDataListLength(HidP_Feature) returned %d, expected %d\n", value, 14);
|
||||
|
||||
value = 1;
|
||||
status = HidP_GetData(HidP_Input, data, &value, preparsed_data, report, caps.InputReportByteLength);
|
||||
|
@ -2474,6 +2478,74 @@ static void test_hidp(HANDLE file, HANDLE async_file, int report_id, BOOL polled
|
|||
ok(!memcmp(buffer, buffer + 16, 16), "unexpected report value\n");
|
||||
|
||||
|
||||
value = 0x7fffffff;
|
||||
status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status);
|
||||
value = 0xdeadbeef;
|
||||
status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
(LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_VALUE_OUT_OF_RANGE, "HidP_GetScaledUsageValue returned %#x\n", status);
|
||||
ok(value == 0, "got value %x, expected %#x\n", value, 0);
|
||||
value = 0xdeadbeef;
|
||||
status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status);
|
||||
ok(value == 0x7fffffff, "got value %x, expected %#x\n", value, 0x7fffffff);
|
||||
|
||||
value = 0x7fff;
|
||||
status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status);
|
||||
value = 0xdeadbeef;
|
||||
status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
(LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status);
|
||||
ok(value == 0x0003ffff, "got value %x, expected %#x\n", value, 0x0003ffff);
|
||||
|
||||
value = 0;
|
||||
status = HidP_SetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetUsageValue returned %#x\n", status);
|
||||
value = 0xdeadbeef;
|
||||
status = HidP_GetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
(LONG *)&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetScaledUsageValue returned %#x\n", status);
|
||||
ok(value == 0xfff90000, "got value %x, expected %#x\n", value, 0xfff90000);
|
||||
status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
0x1000, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status);
|
||||
value = 0;
|
||||
status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status);
|
||||
ok(value == 0xfffff518, "got value %x, expected %#x\n", value, 0xfffff518);
|
||||
status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
0, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status);
|
||||
value = 0;
|
||||
status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status);
|
||||
ok(value == 0xfffff45e, "got value %x, expected %#x\n", value, 0xfffff45e);
|
||||
status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
0xdead, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status);
|
||||
value = 0;
|
||||
status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status);
|
||||
ok(value == 0xfffffe7d, "got value %x, expected %#x\n", value, 0xfffffe7d);
|
||||
status = HidP_SetScaledUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
0xbeef, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_SetScaledUsageValue returned %#x\n", status);
|
||||
value = 0;
|
||||
status = HidP_GetUsageValue(HidP_Feature, HID_USAGE_PAGE_GENERIC, 0, HID_USAGE_GENERIC_Z,
|
||||
&value, preparsed_data, report, caps.FeatureReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_GetUsageValue returned %#x\n", status);
|
||||
ok(value == 0xfffffd0b, "got value %x, expected %#x\n", value, 0xfffffd0b);
|
||||
|
||||
|
||||
memset(report, 0xcd, sizeof(report));
|
||||
status = HidP_InitializeReportForID(HidP_Input, report_id, preparsed_data, report, caps.InputReportByteLength);
|
||||
ok(status == HIDP_STATUS_SUCCESS, "HidP_InitializeReportForID returned %#x\n", status);
|
||||
|
|
|
@ -202,6 +202,7 @@ NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS
|
|||
NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR ReportID, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||
ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData);
|
||||
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_SetScaledUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, LONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||
NTSTATUS WINAPI HidP_SetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, ULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, CHAR *Report, ULONG ReportLength);
|
||||
NTSTATUS WINAPI HidP_SetUsageValueArray( HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
|
||||
USAGE Usage, PCHAR UsageValue, USHORT UsageValueByteLength,
|
||||
|
|
Loading…
Add table
Reference in a new issue