HID开发笔记
+ -

HID多ReportId数据长度返回的问题

2022-04-12 733 0

最近搞了一个虚拟的USB HID设备,为了测试各个报告描述符。不过遇到了一个奇怪的问题,以前没有留意,现在分享给大家。

比如在自定义的HID报告描述符中,描述输入的报告内容分别如下:

ReportId 数据长度 总长度
01 16 17
02 60 61

可以看到,当ReportId=0x01时,加上其payload data的16字节,总计17长度。
而当ReportId=0x01时,加上其payload data的60字节,总计61长度。

在Windows应用层,我们通过ReadFile来读取报告内容。
不过在实际的驱动中,发现:

HID输入报告的读取原理

只有驱动正常创建,hidclass类驱动会对该设备下发两个连续的IRP来请求输入报告,无关是否在应用层有打开该设备读取数据。如果固件没有数据返回,这两个IRP处于Pending状态,直到有数据返回或者该IRP被取消掉。
这个问题其实很好理解,由于HID是中断输入请求,为了保证数据的实时性,在驱动中实际是上将从固件中读到的数据放到其缓存队列中的,当应用层的有读数据请求时,会从缓存的数据中取到数据,并返回给应用层,否则就是等待有数据返回,或者上层主动调用CancelIo取消本次请求。

HID输入报告的读取长度

这是我这次遇到的一个奇怪的问题。
就是如果该HID的多个ReportId并且数据长度不一致时,这时主机会使用最长的报告长度来获取据(本人测试的结果,并不一一定准确),当按实际的数据长度返回时,发现应用层返回的还是最大的长度。

如本人对PENDING起的IRP这样处理:

    PIO_STACK_LOCATION IoStack = IoGetCurrentIrpStackLocation(pPendingIrp);
    PURB  Urb = (PURB)IoStack->Parameters.Others.Argument1;
    ULONG length = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength; 
    ULONG copy = min(length, ulInputLength);
    PVOID buffer = Urb->UrbBulkOrInterruptTransfer.TransferBuffer;


    RtlCopyMemory(buffer, pInputReport, copy);
    Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = copy;
    Urb->UrbHeader.Status = USBD_STATUS_SUCCESS;

    pPendingIrp->IoStatus.Information = copy;
    pPendingIrp->IoStatus.Status = STATUS_SUCCESS;
    IoCompleteRequest(pPendingIrp, IO_NO_INCREMENT);

实际在应用层HID返回的长度还是最大长度即实际的请求长度,而本人已经修改了长度

    Urb->UrbBulkOrInterruptTransfer.TransferBufferLength = copy;

这是我一个很迷或的问题,本人在查ReactOS的源代码HidUsb_ReadReportCompletion时,有这么一句:

 //
    // did the reading report succeed / cancelled
    //
    if (NT_SUCCESS(Irp->IoStatus.Status) || Irp->IoStatus.Status == STATUS_CANCELLED || Irp->IoStatus.Status == STATUS_DEVICE_NOT_CONNECTED)
    {
        //
        // store result length
        //
        Irp->IoStatus.Information = Urb->UrbBulkOrInterruptTransfer.TransferBufferLength;

这个应该没问题的啊,其实Windows的源代码也是这样的。不过不知道为什么我这里测试了出一个这样的问题。

纠结了半天,在IRP_MJ_READ转IOCTL_HID_READ_REPORT的完成例程HidClass_ReadCompleteIrp时,发现这样的

    //
    // copy result status
    //
    IrpContext->OriginalIrp->IoStatus.Status = Irp->IoStatus.Status;
    IrpContext->OriginalIrp->IoStatus.Information = Irp->IoStatus.Information;

这个长度是从IOCTL_HID_READ_REPORT的长度传给IRP_MJ_READ的。不过实际在Windows测试却是另不一样的。
至于原因,暂不清楚,这里记一下,后续再分析。
不过数据内容都是对的,。。。

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 篇笔记 写笔记

Windows下枚举系统中所有HID设备
Windows下对任何设备,文件的打开都是通过CreateFile来实现的,不过要打开一个设备得首先知道设备或文件名。由上节可知道,对于HID设备,都会注册一个接口类型为{2ACCFE60-C130-11D2-B082-00A0C91EFB8B}的GUID。我们可以通过Setup系列函数枚举出系统中......
HID 设置协议SetProtocol
SetProtocol用于设置ID设备的协议值。对于USB引导设备,该协议是必须对;对于非引导设备,是可选的。详见:USB请求bmRequestType(1):0x21bRequest(1): SetProtocol,值为0bwValue(2):数据为0表示引导协议,为1表示报告协议。wInd......
HID 设置报告请求SetReport
SetReport请求用于主机向设备发送报告请求。详见:USB请求bmRequestType(1):0x21bRequest(1): SET_REPORT,值为09.wValue(2):高字节报告类型,低字节为报告ID.01:表示输入报告02: 表示输出报告03: 表示特定报告wIndex......
HID 触摸屏的报表描述符
讲道理,这个触摸屏的报告描述符是我从网上搜索的一段代码,这个触摸屏的报告内容本人也进行了测试。测试是通过本站编写的虚拟触摸屏驱动实现的。0x05, 0x0d, // USAGE_PAGE (Digitizers) 0 0x......
HID 简介
 HID(Human Interface Device,人机接口设备)是USB设备中常用的设备类型,是直接与人交互的USB设备,例如键盘、鼠标与游戏杆等。在USB设备中,HID设备的成本较低。另外,HID设备并不一定要有人机交互功能,只要符合HID类别规范的设备都是HID设备。  Wndows操作系......
HID 体系结构
Windows 中的 HID 驱动程序堆栈的体系结构基于名为 hidclass.sys 的类驱动程序。 客户端和传输微型驱动程序从用户模式或内核模式下访问的类驱动程序。HID类驱动程序在系统提供的 HID 类驱动程序是 WDM 功能驱动程序和总线驱动程序 HID 设备安装程序类 (HIDClass)......
HID 报表描述符数字显示实例
USAGE_PAGE (Alphnumeric Display) 05 14USAGE (Alphanumeric Display) 09 01LOGICAL_MINIMUM (0) 15 00 CO......
HID键盘设备数据抓包分析实践
本文使用 Bus Hound 工具对 USB HID 设备数据包进行分析,并结合官方手册及网上文章进行整理。在进行数据分析前,我们先回顾一下USB相关的基础知识。USB描述符USB 主机是通过各种描述符来识别设备的,有设备描述符,接口描述符,端点描述符,字符描述符,报告描述符HID)等。和普通的......
USB复合HID设备报告描述符的区分
在USB规范中,设备的功能是通过接口来承载的,在USB规格书中就是接口描述符。对于一般的设备,一般一个接口就是一个功能,这个功能可以是鼠标,键盘或其它设备类型。当然这个只是对USB简易设备而言的,对于一些USB复杂设备如UVC摄像头,UAC音频等是多接口相互配合来实现其功能的,为了整合这么多接口使......
HID 设备描述符关系
HID设备连接到USB主机后,主机通过发送Get_Descriptor请求读取HID设备的描述符,了解描述符对了解USB设备是至关重要的。HID设备的描述符HID设备除了支持USB设备的5种标准描述符之外,还支持HID设备特有的3种描述符。这些描述符是:USB标准描述符:设备描述符、配置描述符、......
HID描述符
HID描述符的主要作用是用来识别HID通信所使用的额外描述符。下表是HID描述符结构。偏移量字段字节数数值类型说明0bLength1Numeric描述符字节数1bDescriptorType1Constant0x21 = HID描述符2bcdH......
HID报告描述符详解
HID报告描述符和其它描述符不一样,不是具有固定的数据结构,而是由固件开发商根据上报的数据自行组装的。这个组装的原材料是HID规范定义的ITEM。所以说HID报告描述符就像搭积木一样,其最终的数据结构和设计图纸是什么,都是由固件开发商决定的,但是其最终的产品又是由HID规范提供的各个标准积木模块搭......
HID 报表描述符远程控制实例
USAGE_PAGE (Consumer Devices) 05 0CUSAGE (Consumer Control) 09 01COLLECTION (Application) A1 01 ......
USB键盘报告描述符数据格式分析
USB键盘的HID报表描述符的内容参见下表。数据的输入端点为中断方式,当有键盘敲击事件时,会上报数据长度为8字节的数据报告。0x05,0x01,// Global Generic Desktop0x09,0x06,// Local KeyBoard 0xA1,0x01,// Main app col......
HID 报表描述符键盘实例
通过下面的报告描述符的定义,我们根据上面的注释可知,包含一个中断输入报表描述符和一个中断输出报告描述符。其中断输入报告描述符用于USB HID键盘中断输入端点,输出报表描述符用于USB HID键盘中断输出端点。USB HID键盘的中断输入报告对于中断输入端点,数据格式定义如下:BYTE0:该字......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

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

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