forked from Mirrors/wine-wine
hid: Implement HidP_GetUsageValueArray.
Games like Risk of Rain 2 need this with certain controllers. Signed-off-by: Gabriel Ivăncescu <gabrielopcode@gmail.com> Signed-off-by: Aric Stewart <aric@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
3b27222aa2
commit
ec88633912
|
@ -27,7 +27,7 @@
|
||||||
@ stdcall HidP_GetSpecificButtonCaps(long long long long ptr ptr ptr)
|
@ stdcall HidP_GetSpecificButtonCaps(long long long long ptr ptr ptr)
|
||||||
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
|
@ stdcall HidP_GetSpecificValueCaps(long long long long ptr ptr ptr)
|
||||||
@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
|
@ stdcall HidP_GetUsageValue(long long long long ptr ptr ptr long)
|
||||||
@ stub HidP_GetUsageValueArray
|
@ stdcall HidP_GetUsageValueArray(long long long long ptr long ptr ptr long)
|
||||||
@ stdcall HidP_GetUsages(long long long ptr ptr ptr ptr long)
|
@ stdcall HidP_GetUsages(long long long ptr ptr ptr ptr long)
|
||||||
@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
|
@ stdcall HidP_GetUsagesEx(long long ptr ptr ptr ptr long)
|
||||||
@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
|
@ stdcall HidP_GetValueCaps(long ptr ptr ptr)
|
||||||
|
|
|
@ -117,6 +117,46 @@ static NTSTATUS set_report_data(BYTE *report, INT reportLength, INT startBit, IN
|
||||||
return HIDP_STATUS_SUCCESS;
|
return HIDP_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NTSTATUS get_report_data_array(BYTE *report, UINT reportLength, UINT startBit, UINT elemSize,
|
||||||
|
UINT numElements, PCHAR values, UINT valuesSize)
|
||||||
|
{
|
||||||
|
BYTE byte, *end, *p = report + startBit / 8;
|
||||||
|
ULONG size = elemSize * numElements;
|
||||||
|
ULONG m, bit_index = startBit % 8;
|
||||||
|
BYTE *data = (BYTE*)values;
|
||||||
|
|
||||||
|
if ((startBit + size) / 8 > reportLength)
|
||||||
|
return HIDP_STATUS_INVALID_REPORT_LENGTH;
|
||||||
|
|
||||||
|
if (valuesSize < (size + 7) / 8)
|
||||||
|
return HIDP_STATUS_BUFFER_TOO_SMALL;
|
||||||
|
|
||||||
|
end = report + (startBit + size + 7) / 8;
|
||||||
|
|
||||||
|
data--;
|
||||||
|
byte = *p++;
|
||||||
|
while (p != end)
|
||||||
|
{
|
||||||
|
*(++data) = byte >> bit_index;
|
||||||
|
byte = *p++;
|
||||||
|
*data |= byte << (8 - bit_index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Handle the end and mask out bits beyond */
|
||||||
|
m = (startBit + size) % 8;
|
||||||
|
m = m ? m : 8;
|
||||||
|
|
||||||
|
if (m > bit_index)
|
||||||
|
*(++data) = (byte >> bit_index) & ((1 << (m - bit_index)) - 1);
|
||||||
|
else
|
||||||
|
*data &= (1 << (m + 8 - bit_index)) - 1;
|
||||||
|
|
||||||
|
if (++data < (BYTE*)values + valuesSize)
|
||||||
|
memset(data, 0, (BYTE*)values + valuesSize - data);
|
||||||
|
|
||||||
|
return HIDP_STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps,
|
NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAPS ButtonCaps,
|
||||||
PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
PUSHORT ButtonCapsLength, PHIDP_PREPARSED_DATA PreparsedData)
|
||||||
|
@ -325,6 +365,31 @@ NTSTATUS WINAPI HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NTSTATUS WINAPI HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
|
||||||
|
USAGE Usage, PCHAR UsageValue, USHORT UsageValueByteLength,
|
||||||
|
PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength)
|
||||||
|
{
|
||||||
|
WINE_HID_ELEMENT element;
|
||||||
|
NTSTATUS rc;
|
||||||
|
|
||||||
|
TRACE("(%i, %x, %i, %i, %p, %u, %p, %p, %i)\n", ReportType, UsagePage, LinkCollection, Usage, UsageValue,
|
||||||
|
UsageValueByteLength, PreparsedData, Report, ReportLength);
|
||||||
|
|
||||||
|
rc = find_usage(ReportType, UsagePage, LinkCollection, Usage, PreparsedData, Report, ValueElement, &element);
|
||||||
|
|
||||||
|
if (rc == HIDP_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
if (element.caps.value.IsRange || element.caps.value.ReportCount <= 1 || !element.bitCount)
|
||||||
|
return HIDP_STATUS_NOT_VALUE_ARRAY;
|
||||||
|
|
||||||
|
return get_report_data_array((BYTE*)Report, ReportLength, element.valueStartBit, element.bitCount,
|
||||||
|
element.caps.value.ReportCount, UsageValue, UsageValueByteLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
|
NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection,
|
||||||
PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData,
|
PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData,
|
||||||
PCHAR Report, ULONG ReportLength)
|
PCHAR Report, ULONG ReportLength)
|
||||||
|
|
|
@ -253,11 +253,38 @@ static void process_data(HIDP_CAPS Caps, PHIDP_PREPARSED_DATA ppd, CHAR *data, D
|
||||||
trace("\tValues:\n");
|
trace("\tValues:\n");
|
||||||
for (i = 0; i < length; i++)
|
for (i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
status = HidP_GetUsageValue(HidP_Input, values[i].UsagePage, 0,
|
ok(values[i].ReportCount, "Zero ReportCount for [%i,%i]\n", values[i].UsagePage, values[i].NotRange.Usage);
|
||||||
values[i].Range.UsageMin, &value, ppd, data, data_length);
|
if (values[i].IsRange || values[i].ReportCount <= 1)
|
||||||
ok(status == HIDP_STATUS_SUCCESS, "Failed to get value [%i,%i] (%x)\n",
|
{
|
||||||
values[i].UsagePage, values[i].Range.UsageMin, status);
|
status = HidP_GetUsageValue(HidP_Input, values[i].UsagePage, 0,
|
||||||
trace("[%02x, %02x]: %u\n",values[i].UsagePage, values[i].Range.UsageMin, value);
|
values[i].Range.UsageMin, &value, ppd, data, data_length);
|
||||||
|
ok(status == HIDP_STATUS_SUCCESS, "Failed to get value [%i,%i] (%x)\n",
|
||||||
|
values[i].UsagePage, values[i].Range.UsageMin, status);
|
||||||
|
trace("[%02x, %02x]: %u\n", values[i].UsagePage, values[i].Range.UsageMin, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
USHORT k, array_size = (values[i].BitSize * values[i].ReportCount + 7) / 8;
|
||||||
|
PCHAR array = HeapAlloc(GetProcessHeap(), 0, array_size);
|
||||||
|
char *dump = HeapAlloc(GetProcessHeap(), 0, array_size * 3 + 1);
|
||||||
|
|
||||||
|
status = HidP_GetUsageValueArray(HidP_Input, values[i].UsagePage, 0,
|
||||||
|
values[i].NotRange.Usage, array, array_size, ppd, data, data_length);
|
||||||
|
ok(status == HIDP_STATUS_SUCCESS, "Failed to get value array [%i,%i] (%x)\n",
|
||||||
|
values[i].UsagePage, values[i].NotRange.Usage, status);
|
||||||
|
dump[0] = 0;
|
||||||
|
for (k = 0; k < array_size; k++)
|
||||||
|
{
|
||||||
|
char bytestr[5];
|
||||||
|
sprintf(bytestr, " %02x", (BYTE)array[k]);
|
||||||
|
strcat(dump, bytestr);
|
||||||
|
}
|
||||||
|
trace("[%02x, %02x] element bit size %u num elements %u:%s\n", values[i].UsagePage,
|
||||||
|
values[i].NotRange.Usage, values[i].BitSize, values[i].ReportCount, dump);
|
||||||
|
|
||||||
|
HeapFree(GetProcessHeap(), 0, dump);
|
||||||
|
HeapFree(GetProcessHeap(), 0, array);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HeapFree(GetProcessHeap(), 0, values);
|
HeapFree(GetProcessHeap(), 0, values);
|
||||||
|
|
|
@ -195,6 +195,7 @@ NTSTATUS WINAPI HidP_GetButtonCaps(HIDP_REPORT_TYPE ReportType, PHIDP_BUTTON_CAP
|
||||||
NTSTATUS WINAPI HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities);
|
NTSTATUS WINAPI HidP_GetCaps(PHIDP_PREPARSED_DATA PreparsedData, PHIDP_CAPS Capabilities);
|
||||||
NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
NTSTATUS WINAPI HidP_GetUsages(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, PUSAGE UsageList, PULONG UsageLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||||
NTSTATUS WINAPI HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
NTSTATUS WINAPI HidP_GetUsageValue(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PULONG UsageValue, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||||
|
NTSTATUS WINAPI HidP_GetUsageValueArray(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, USHORT LinkCollection, USAGE Usage, PCHAR UsageValue, USHORT UsageValueByteLength, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
||||||
NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
|
NTSTATUS WINAPI HidP_GetValueCaps(HIDP_REPORT_TYPE ReportType, PHIDP_VALUE_CAPS ValueCaps, PUSHORT ValueCapsLength, PHIDP_PREPARSED_DATA PreparsedData);
|
||||||
NTSTATUS WINAPI HidP_InitializeReportForID(HIDP_REPORT_TYPE ReportType, UCHAR ReportID, PHIDP_PREPARSED_DATA PreparsedData, PCHAR Report, ULONG ReportLength);
|
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);
|
ULONG WINAPI HidP_MaxUsageListLength(HIDP_REPORT_TYPE ReportType, USAGE UsagePage, PHIDP_PREPARSED_DATA PreparsedData);
|
||||||
|
|
Loading…
Reference in New Issue