hid: Build link collection nodes in HidP_GetLinkCollectionNodes.

Signed-off-by: Rémi Bernon <rbernon@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Rémi Bernon 2021-06-28 09:22:00 +02:00 committed by Alexandre Julliard
parent b860281d32
commit 37009031bb
3 changed files with 30 additions and 57 deletions

View file

@ -721,33 +721,37 @@ NTSTATUS WINAPI HidP_GetData( HIDP_REPORT_TYPE report_type, HIDP_DATA *data, ULO
return HIDP_STATUS_SUCCESS;
}
NTSTATUS WINAPI HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE *LinkCollectionNode,
ULONG *LinkCollectionNodeLength, PHIDP_PREPARSED_DATA PreparsedData)
NTSTATUS WINAPI HidP_GetLinkCollectionNodes( HIDP_LINK_COLLECTION_NODE *nodes, ULONG *nodes_len, PHIDP_PREPARSED_DATA preparsed_data )
{
WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
WINE_HID_LINK_COLLECTION_NODE *nodes = HID_NODES(data);
ULONG i;
WINE_HIDP_PREPARSED_DATA *preparsed = (WINE_HIDP_PREPARSED_DATA *)preparsed_data;
struct hid_value_caps *caps = HID_COLLECTION_VALUE_CAPS( preparsed );
ULONG i, count, capacity = *nodes_len;
TRACE("(%p, %p, %p)\n", LinkCollectionNode, LinkCollectionNodeLength, PreparsedData);
TRACE( "nodes %p, nodes_len %p, preparsed_data %p.\n", nodes, nodes_len, preparsed_data );
if (data->magic != HID_MAGIC)
return HIDP_STATUS_INVALID_PREPARSED_DATA;
if (preparsed->magic != HID_MAGIC) return HIDP_STATUS_INVALID_PREPARSED_DATA;
if (*LinkCollectionNodeLength < data->caps.NumberLinkCollectionNodes)
return HIDP_STATUS_BUFFER_TOO_SMALL;
if (capacity < preparsed->caps.NumberLinkCollectionNodes) return HIDP_STATUS_BUFFER_TOO_SMALL;
count = *nodes_len = preparsed->caps.NumberLinkCollectionNodes;
for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i)
for (i = 0; i < count; ++i)
{
LinkCollectionNode[i].LinkUsage = nodes[i].LinkUsage;
LinkCollectionNode[i].LinkUsagePage = nodes[i].LinkUsagePage;
LinkCollectionNode[i].Parent = nodes[i].Parent;
LinkCollectionNode[i].NumberOfChildren = nodes[i].NumberOfChildren;
LinkCollectionNode[i].NextSibling = nodes[i].NextSibling;
LinkCollectionNode[i].FirstChild = nodes[i].FirstChild;
LinkCollectionNode[i].CollectionType = nodes[i].CollectionType;
LinkCollectionNode[i].IsAlias = nodes[i].IsAlias;
nodes[i].LinkUsagePage = caps[i].usage_page;
nodes[i].LinkUsage = caps[i].usage_min;
nodes[i].Parent = caps[i].link_collection;
nodes[i].CollectionType = caps[i].bit_field;
nodes[i].IsAlias = 0;
nodes[i].FirstChild = 0;
nodes[i].NextSibling = 0;
nodes[i].NumberOfChildren = 0;
if (i > 0)
{
nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild;
nodes[nodes[i].Parent].FirstChild = i;
nodes[nodes[i].Parent].NumberOfChildren++;
}
}
*LinkCollectionNodeLength = data->caps.NumberLinkCollectionNodes;
return HIDP_STATUS_SUCCESS;
}

View file

@ -834,7 +834,6 @@ static void preparse_collection(const struct collection *root, const struct coll
static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_collection,
struct hid_parser_state *state )
{
WINE_HID_LINK_COLLECTION_NODE *nodes;
WINE_HIDP_PREPARSED_DATA *data;
struct hid_value_caps *caps;
unsigned int report_count;
@ -843,7 +842,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
struct preparse_ctx ctx;
unsigned int element_off;
unsigned int nodes_offset;
memset(&ctx, 0, sizeof(ctx));
create_preparse_ctx(base_collection, &ctx);
@ -853,10 +851,8 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
element_off = FIELD_OFFSET(WINE_HIDP_PREPARSED_DATA, reports[report_count]);
size = element_off + (ctx.elem_count * sizeof(WINE_HID_ELEMENT));
nodes_offset = size;
size += state->caps.NumberLinkCollectionNodes * sizeof(WINE_HID_LINK_COLLECTION_NODE);
caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps + state->caps.NumberFeatureValueCaps;
caps_len = state->caps.NumberInputValueCaps + state->caps.NumberOutputValueCaps +
state->caps.NumberFeatureValueCaps + state->caps.NumberLinkCollectionNodes;
caps_off = size;
size += caps_len * sizeof(*caps);
@ -866,7 +862,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
data->caps = state->caps;
data->new_caps = state->caps;
data->elementOffset = element_off;
data->nodesOffset = nodes_offset;
data->value_caps_offset = caps_off;
data->value_caps_count[HidP_Input] = state->caps.NumberInputValueCaps;
@ -878,23 +873,6 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
data->caps.NumberFeatureValueCaps = data->caps.NumberFeatureButtonCaps = data->caps.NumberFeatureDataIndices = 0;
preparse_collection(base_collection, base_collection, data, &ctx);
nodes = HID_NODES( data );
for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++i)
{
nodes[i].LinkUsagePage = state->collections[i].usage_page;
nodes[i].LinkUsage = state->collections[i].usage_min;
nodes[i].Parent = state->collections[i].link_collection;
nodes[i].CollectionType = state->collections[i].bit_field;
nodes[i].IsAlias = 0;
if (i > 0)
{
nodes[i].NextSibling = nodes[nodes[i].Parent].FirstChild;
nodes[nodes[i].Parent].FirstChild = i;
nodes[nodes[i].Parent].NumberOfChildren++;
}
}
/* fixup value vs button vs filler counts */
caps = HID_INPUT_VALUE_CAPS( data );
@ -929,6 +907,9 @@ static WINE_HIDP_PREPARSED_DATA *build_preparsed_data( struct collection *base_c
data->new_caps.NumberFeatureButtonCaps = button;
data->new_caps.NumberFeatureValueCaps -= filler + button;
caps = HID_COLLECTION_VALUE_CAPS( data );
memcpy( caps, state->collections, data->new_caps.NumberLinkCollectionNodes * sizeof(*caps) );
return data;
}

View file

@ -81,17 +81,6 @@ typedef struct __WINE_HID_REPORT
DWORD elementIdx;
} WINE_HID_REPORT;
typedef struct __WINE_HID_LINK_COLLECTION_NODE {
USAGE LinkUsage;
USAGE LinkUsagePage;
USHORT Parent;
USHORT NumberOfChildren;
USHORT NextSibling;
USHORT FirstChild;
BYTE CollectionType;
BYTE IsAlias;
} WINE_HID_LINK_COLLECTION_NODE;
typedef struct __WINE_HIDP_PREPARSED_DATA
{
DWORD magic;
@ -100,7 +89,6 @@ typedef struct __WINE_HIDP_PREPARSED_DATA
HIDP_CAPS new_caps;
DWORD elementOffset;
DWORD nodesOffset;
DWORD reportCount[3];
BYTE reportIdx[3][256];
@ -113,10 +101,10 @@ typedef struct __WINE_HIDP_PREPARSED_DATA
#define HID_OUTPUT_REPORTS(d) ((d)->reports + (d)->reportCount[0])
#define HID_FEATURE_REPORTS(d) ((d)->reports + (d)->reportCount[0] + (d)->reportCount[1])
#define HID_ELEMS(d) ((WINE_HID_ELEMENT*)((BYTE*)(d) + (d)->elementOffset))
#define HID_NODES(d) ((WINE_HID_LINK_COLLECTION_NODE*)((BYTE*)(d) + (d)->nodesOffset))
#define HID_INPUT_VALUE_CAPS(d) ((struct hid_value_caps*)((char *)(d) + (d)->value_caps_offset))
#define HID_OUTPUT_VALUE_CAPS(d) (HID_INPUT_VALUE_CAPS(d) + (d)->value_caps_count[0])
#define HID_FEATURE_VALUE_CAPS(d) (HID_OUTPUT_VALUE_CAPS(d) + (d)->value_caps_count[1])
#define HID_COLLECTION_VALUE_CAPS(d) (HID_FEATURE_VALUE_CAPS(d) + (d)->value_caps_count[2])
#endif /* __WINE_PARSE_H */