Windows动态库hid.dll
+ -

HIDP_DEVICE_DESC和HIDP_COLLECTION_DESC、HIDP_REPORT_IDS关系注释

2022-05-14 244 0

在说明Hid.dll的导出函数Hid.dll导出函数HidD_GetPreparsedData,其实会涉及到Hidparser.sys中比较重要的两个结构体,就是HIDP_COLLECTION_DESC和HIDP_REPORT_IDS。
这两个结构体的定义如下:

typedef struct _HIDP_COLLECTION_DESC
{
    USAGE  UsagePage;
    USAGE  Usage;
    UCHAR  CollectionNumber;
    UCHAR  Reserved[15];
    USHORT InputLength;
    USHORT OutputLength;
    USHORT FeatureLength;
    USHORT PreparsedDataLength;
    PHIDP_PREPARSED_DATA PreparsedData;
}HIDP_COLLECTION_DESC, * PHIDP_COLLECTION_DESC;
typedef struct _HIDP_REPORT_IDS
{
    UCHAR  ReportID;
    UCHAR  CollectionNumber;
    USHORT InputLength;
    USHORT OutputLength;
    USHORT FeatureLength;
}HIDP_REPORT_IDS, * PHIDP_REPORT_IDS;

可以看到,其中HIDP_COLLECTION_DESC用于描述一个HID功能设备报告描述符的基本信息,另一个HIDP_REPORT_IDS和其类似,信息更加简化些,并且一个HID报告描述符解析出的HIDP_COLLECTION_DESC和HIDP_REPORT_IDS的数量应该是相同的,都是CollectionCount。
我们在HidD_GetPreparsedData一节看到其中的部分代码,这里我们再加其更加详细的初始化代码,在reactos的hidparser中如下:

NTSTATUS
NTAPI
HidParser_GetCollectionDescription(
    IN PHID_PARSER Parser,
    IN PHIDP_REPORT_DESCRIPTOR ReportDesc,
    IN ULONG DescLength,
    IN POOL_TYPE PoolType,
    OUT PHIDP_DEVICE_DESC DeviceDescription)
{
    HIDPARSER_STATUS ParserStatus;
    ULONG CollectionCount;
    ULONG Index;
    PVOID ParserContext;

    //
    // first parse the report descriptor
    //
    ParserStatus = HidParser_ParseReportDescriptor(Parser, ReportDesc, DescLength, &ParserContext);
    if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
    {
        //
        // failed to parse report descriptor
        //
        Parser->Debug("[HIDPARSER] Failed to parse report descriptor with %x\n", ParserStatus);
        return ParserStatus;
    }

    //
    // get collection count
    //
    CollectionCount = HidParser_NumberOfTopCollections(ParserContext);
    if (CollectionCount == 0)
    {
        //
        // no top level collections found
        //
        ASSERT(FALSE);
        return STATUS_NO_DATA_DETECTED;
    }

    //
    // zero description
    //
    Parser->Zero(DeviceDescription, sizeof(HIDP_DEVICE_DESC));

    //
    // allocate collection
    //
    DeviceDescription->CollectionDesc = (PHIDP_COLLECTION_DESC)Parser->Alloc(sizeof(HIDP_COLLECTION_DESC) * CollectionCount);
    if (!DeviceDescription->CollectionDesc)
    {
        //
        // no memory
        //
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    //
    // allocate report description
    //
    DeviceDescription->ReportIDs = (PHIDP_REPORT_IDS)Parser->Alloc(sizeof(HIDP_REPORT_IDS) * CollectionCount);
    if (!DeviceDescription->ReportIDs)
    {
        //
        // no memory
        //
        Parser->Free(DeviceDescription->CollectionDesc);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    for(Index = 0; Index < CollectionCount; Index++)
    {
        //
        // set preparsed data length
        //
        DeviceDescription->CollectionDesc[Index].PreparsedDataLength = HidParser_GetContextSize(Parser, ParserContext, Index);
        ParserStatus = HidParser_BuildContext(Parser, ParserContext, Index, DeviceDescription->CollectionDesc[Index].PreparsedDataLength, (PVOID*)&DeviceDescription->CollectionDesc[Index].PreparsedData);
        if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
        {
            //
            // no memory
            //
            Parser->Free(DeviceDescription->CollectionDesc);
            Parser->Free(DeviceDescription->ReportIDs);
            return ParserStatus;
        }

        //
        // init report description
        //
        DeviceDescription->ReportIDs[Index].CollectionNumber = Index + 1;
        DeviceDescription->ReportIDs[Index].ReportID = Index; //FIXME
        DeviceDescription->ReportIDs[Index].InputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT);
        DeviceDescription->ReportIDs[Index].OutputLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT);
        DeviceDescription->ReportIDs[Index].FeatureLength = HidParser_GetReportLength((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE);


        DeviceDescription->ReportIDs[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) ? 1 : 0);
        DeviceDescription->ReportIDs[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) ? 1 : 0);
        DeviceDescription->ReportIDs[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) ? 1 : 0);


        //
        // init collection description
        //
        DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1;

        //
        // get collection usage page
        //
        ParserStatus = HidParser_GetCollectionUsagePage((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, &DeviceDescription->CollectionDesc[Index].Usage, &DeviceDescription->CollectionDesc[Index].UsagePage);
        if (ParserStatus != HIDPARSER_STATUS_SUCCESS)
        {
            // collection not found
            Parser->Free(DeviceDescription->CollectionDesc);
            Parser->Free(DeviceDescription->ReportIDs);
            return ParserStatus;
        }

        //
        // windows seems to prepend the report id, regardless if it is required
        //
        DeviceDescription->CollectionDesc[Index].CollectionNumber = Index + 1;
        DeviceDescription->CollectionDesc[Index].InputLength = DeviceDescription->ReportIDs[Index].InputLength;
        DeviceDescription->CollectionDesc[Index].OutputLength = DeviceDescription->ReportIDs[Index].OutputLength;
        DeviceDescription->CollectionDesc[Index].FeatureLength = DeviceDescription->ReportIDs[Index].FeatureLength;

        DeviceDescription->CollectionDesc[Index].InputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_INPUT) == FALSE ? 1 : 0);
        DeviceDescription->CollectionDesc[Index].OutputLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_OUTPUT) == FALSE ? 1 : 0);
        DeviceDescription->CollectionDesc[Index].FeatureLength += (HidParser_UsesReportId((PVOID)DeviceDescription->CollectionDesc[Index].PreparsedData, HID_REPORT_TYPE_FEATURE) == FALSE ? 1 : 0);


    }

    //
    // store collection & report count
    //
    DeviceDescription->CollectionDescLength = CollectionCount;
    DeviceDescription->ReportIDsLength = CollectionCount;

    //
    // done
    //
    return STATUS_SUCCESS;
}

这里还涉及一个结构体HIDP_DEVICE_DESC,其结构体定义如下:

typedef struct _HIDP_DEVICE_DESC
{
    PHIDP_COLLECTION_DESC CollectionDesc;
    ULONG                 CollectionDescLength;
    PHIDP_REPORT_IDS      ReportIDs;
    ULONG                 ReportIDsLength;
    HIDP_GETCOLDESC_DBG   Dbg;
}HIDP_DEVICE_DESC, * PHIDP_DEVICE_DESC;

它们之间的关系如下:
HIDP_DEVICE_DESC和HIDP_COLLECTION_DESC、HIDP_REPORT_ID

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

HIDP_DEVICE_DESCHIDP_COLLECTION_DESCHIDP_REPORT_IDS关系注释
在说明Hid.dll的导出函数Hid.dll导出函数HidD_GetPreparsedData,其实会涉及到Hidparser.sys中比较重要的两个结构体,就是HIDP_COLLECTION_DESCHIDP_REPORT_IDS。这两个结构体的定义如下:typedef struct _HID......
HID_PARSER_CONTEXT解析报告描述符生成的COLLECTION树形结构
通过前面的代码,我们简单的说明了一下HIDP_DEVICE_DESCHIDP_COLLECTION_DESCHIDP_REPORT_IDS关系:其实我们在分析其代码的时候,都是通过ParserContext来实现的,这个指针的定义实质上为:typedef struct{ // ......
关注公众号
  • HID人机交互
  • Linux&USB
  • UAC音频
  • TYPE-C
  • USB规范
  • USB大容量存储
  • USB百科
  • USB周边
  • UVC摄像头
  • Windows系统USB
  • 音视频博客
  • 取消
    感谢您的支持,我会继续努力的!
    扫码支持
    扫码打赏,你说多少就多少

    打开支付宝扫一扫,即可进行扫码打赏哦

    您的支持,是我们前进的动力!