[PATCH v2 4/4] hid: Implement HidP_GetLinkCollectionNodes.

Aric Stewart aric at codeweavers.com
Wed Feb 12 10:00:48 CST 2020


Signed-off-by: Aric Stewart <aric at codeweavers.com>

On 2/11/20 12:13 PM, Rémi Bernon wrote:
> Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
> ---
>   dlls/hid/hidp.c                | 24 ++++++++++++++++++++---
>   dlls/hid/tests/device.c        |  7 -------
>   dlls/hidclass.sys/descriptor.c | 36 +++++++++++++++++++++++++++++-----
>   include/wine/hid.h             | 13 ++++++++++++
>   4 files changed, 65 insertions(+), 15 deletions(-)
> 
> diff --git a/dlls/hid/hidp.c b/dlls/hid/hidp.c
> index e0513af7fba..817e021fe4e 100644
> --- a/dlls/hid/hidp.c
> +++ b/dlls/hid/hidp.c
> @@ -931,9 +931,27 @@ NTSTATUS WINAPI HidP_GetData(HIDP_REPORT_TYPE ReportType, HIDP_DATA *DataList, U
>   NTSTATUS WINAPI HidP_GetLinkCollectionNodes(HIDP_LINK_COLLECTION_NODE *LinkCollectionNode,
>       ULONG *LinkCollectionNodeLength, PHIDP_PREPARSED_DATA PreparsedData)
>   {
> -    FIXME("stub (%p, %p, %p)\n", LinkCollectionNode, LinkCollectionNodeLength, PreparsedData);
> +    WINE_HIDP_PREPARSED_DATA *data = (WINE_HIDP_PREPARSED_DATA*)PreparsedData;
> +    WINE_HID_LINK_COLLECTION_NODE *nodes = HID_NODES(data);
> +    ULONG i;
>   
> -    *LinkCollectionNodeLength = 0;
> +    TRACE("(%p, %p, %p)\n", LinkCollectionNode, LinkCollectionNodeLength, PreparsedData);
>   
> -    return STATUS_NOT_IMPLEMENTED;
> +    if (*LinkCollectionNodeLength < data->caps.NumberLinkCollectionNodes)
> +        return HIDP_STATUS_BUFFER_TOO_SMALL;
> +
> +    for (i = 0; i < data->caps.NumberLinkCollectionNodes; ++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;
> +    }
> +    *LinkCollectionNodeLength = data->caps.NumberLinkCollectionNodes;
> +
> +    return HIDP_STATUS_SUCCESS;
>   }
> diff --git a/dlls/hid/tests/device.c b/dlls/hid/tests/device.c
> index b3e959d2594..24c307704fe 100644
> --- a/dlls/hid/tests/device.c
> +++ b/dlls/hid/tests/device.c
> @@ -51,17 +51,14 @@ static void test_device_info(HANDLE device)
>       trace("Found device %s (%02x, %02x)\n", wine_dbgstr_w(device_name), Caps.UsagePage, Caps.Usage);
>   
>       trace("LinkCollectionNodes: (%d)\n", Caps.NumberLinkCollectionNodes);
> -    todo_wine
>       ok(Caps.NumberLinkCollectionNodes > 0, "Expected at least one link collection\n");
>   
>       nodes_count = 0;
>       status = HidP_GetLinkCollectionNodes(nodes, &nodes_count, ppd);
> -    todo_wine
>       ok(status == HIDP_STATUS_BUFFER_TOO_SMALL, "HidP_GetLinkCollectionNodes succeeded:%x\n", status);
>   
>       nodes_count = ARRAY_SIZE(nodes);
>       status = HidP_GetLinkCollectionNodes(nodes, &nodes_count, ppd);
> -    todo_wine
>       ok(status == HIDP_STATUS_SUCCESS, "HidP_GetLinkCollectionNodes failed:%x\n", status);
>   
>       for (i = 0; i < nodes_count; ++i)
> @@ -74,13 +71,9 @@ static void test_device_info(HANDLE device)
>                 nodes[i].CollectionType, nodes[i].IsAlias, nodes[i].UserContext);
>       }
>   
> -    todo_wine
>       ok(nodes_count > 0, "Unexpected number of link collection nodes:%u.\n", nodes_count);
> -    todo_wine
>       ok(nodes[0].LinkUsagePage == Caps.UsagePage, "Unexpected top collection usage page:%x\n", nodes[0].LinkUsagePage);
> -    todo_wine
>       ok(nodes[0].LinkUsage == Caps.Usage, "Unexpected top collection usage:%x\n", nodes[0].LinkUsage);
> -    todo_wine
>       ok(nodes[0].CollectionType == 1, "Unexpected top collection type:%x\n", nodes[0].CollectionType);
>   
>       rc = HidD_FreePreparsedData(ppd);
> diff --git a/dlls/hidclass.sys/descriptor.c b/dlls/hidclass.sys/descriptor.c
> index af1679d23b0..876369ad701 100644
> --- a/dlls/hidclass.sys/descriptor.c
> +++ b/dlls/hidclass.sys/descriptor.c
> @@ -835,12 +835,14 @@ static void create_preparse_ctx(const struct collection *base, struct preparse_c
>           create_preparse_ctx(c, ctx);
>   }
>   
> -static void preparse_collection(const struct collection *base,
> +static void preparse_collection(const struct collection *root, const struct collection *base,
>           WINE_HIDP_PREPARSED_DATA *data, struct preparse_ctx *ctx)
>   {
>       WINE_HID_ELEMENT *elem = HID_ELEMS(data);
> +    WINE_HID_LINK_COLLECTION_NODE *nodes = HID_NODES(data);
>       struct feature *f;
>       struct collection *c;
> +    struct list *entry;
>   
>       LIST_FOR_EACH_ENTRY(f, &base->features, struct feature, entry)
>       {
> @@ -885,11 +887,29 @@ static void preparse_collection(const struct collection *base,
>           }
>       }
>   
> +    if (root != base)
> +    {
> +        nodes[base->index].LinkUsagePage = base->caps.UsagePage;
> +        nodes[base->index].LinkUsage = base->caps.u.NotRange.Usage;
> +        nodes[base->index].Parent = base->parent == root ? 0 : base->parent->index;
> +        nodes[base->index].CollectionType = base->type;
> +        nodes[base->index].IsAlias = 0;
> +
> +        if ((entry = list_head(&base->collections)))
> +            nodes[base->index].FirstChild = LIST_ENTRY(entry, struct collection, entry)->index;
> +    }
> +
>       LIST_FOR_EACH_ENTRY(c, &base->collections, struct collection, entry)
> -        preparse_collection(c, data, ctx);
> +    {
> +        preparse_collection(root, c, data, ctx);
> +
> +        if ((entry = list_next(&base->collections, &c->entry)))
> +            nodes[c->index].NextSibling = LIST_ENTRY(entry, struct collection, entry)->index;
> +        if (root != base) nodes[base->index].NumberOfChildren++;
> +    }
>   }
>   
> -static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_collection)
> +static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_collection, unsigned int node_count)
>   {
>       WINE_HIDP_PREPARSED_DATA *data;
>       unsigned int report_count;
> @@ -897,6 +917,7 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_coll
>   
>       struct preparse_ctx ctx;
>       unsigned int element_off;
> +    unsigned int nodes_offset;
>   
>       memset(&ctx, 0, sizeof(ctx));
>       create_preparse_ctx(base_collection, &ctx);
> @@ -906,14 +927,19 @@ static WINE_HIDP_PREPARSED_DATA* build_PreparseData(struct collection *base_coll
>       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 += node_count * sizeof(WINE_HID_LINK_COLLECTION_NODE);
> +
>       data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
>       data->magic = HID_MAGIC;
>       data->dwSize = size;
>       data->caps.Usage = base_collection->caps.u.NotRange.Usage;
>       data->caps.UsagePage = base_collection->caps.UsagePage;
> +    data->caps.NumberLinkCollectionNodes = node_count;
>       data->elementOffset = element_off;
> +    data->nodesOffset = nodes_offset;
>   
> -    preparse_collection(base_collection, data, &ctx);
> +    preparse_collection(base_collection, base_collection, data, &ctx);
>       return data;
>   }
>   
> @@ -981,7 +1007,7 @@ WINE_HIDP_PREPARSED_DATA* ParseDescriptor(BYTE *descriptor, unsigned int length)
>           }
>       }
>   
> -    data = build_PreparseData(base);
> +    data = build_PreparseData(base, cidx);
>       debug_print_preparsed(data);
>       free_collection(base);
>   
> diff --git a/include/wine/hid.h b/include/wine/hid.h
> index 319105d286e..857dcae18fe 100644
> --- a/include/wine/hid.h
> +++ b/include/wine/hid.h
> @@ -48,6 +48,17 @@ 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;
> @@ -55,6 +66,7 @@ typedef struct __WINE_HIDP_PREPARSED_DATA
>       HIDP_CAPS caps;
>   
>       DWORD elementOffset;
> +    DWORD nodesOffset;
>       DWORD reportCount[3];
>       BYTE reportIdx[3][256];
>   
> @@ -65,5 +77,6 @@ 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))
>   
>   #endif /* __WINE_PARSE_H */
> 



More information about the wine-devel mailing list