HID触摸屏报告描述符应用层解析分析代码
			 2022-06-06
			  本文链接为:http://www.usbzh.com/article/detail-1047.html ,欢迎转载,转载请附上本文链接。
	
			
			
			
			
		
			这一段时间狠狠地研究了HID报告描述符,虽然尚未达到炉火纯青的地步,不过经过自己深入的研究,还是对HID的报告描述符以及Windows系统对HID报告描述符的解析和处理有了更深一层的理解,同时也增进了自己对IRP等Windows驱动编程的技术提高。
其实以前做了触摸屏驱动,包括现在虚拟出来的。不过当我们在进行数据传递时,一般是需要数据格式的转换,这我们只需要按实际的数据结构转换就行了,其实这个还好话。不过有一个比较麻烦的地方就是不同的厂商定义的坐标系的范围是不同的,所以在应用层进行数据结构转换时,时常有一些硬编码或者查表来进行按比例转换。
今天,刚好又要搞这个东西,自己干脆自己在应用层搞一个,通过在驱动层将HID报告描述符的内容获取到应用层,然后在应用层进行解析,获取其X,Y的最大逻辑值。
触摸屏的在定义XY的最大逻辑值LOCAL_USAGE(X)和LOCAL_USAGE(Y)时,使用的USAGE_PAGE为PAGE_GENDRIC_DESKTOP_CONTROLS,这时获取全局项ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM的值。
其实这里的代码相对简单,不过更好帮我们理解HID报告描述符的全局项,主项、局部项等概念。
不支持LONG项
代码如下:
#define ITEM_TYPE_MAIN                        0x0
#define ITEM_TYPE_GLOBAL                    0x1
#define ITEM_TYPE_LOCAL                        0x2
#define ITEM_TYPE_LONG                        0x3
#define ITEM_TAG_GLOBAL_USAGE_PAGE            0x0
#define ITEM_TAG_GLOBAL_LOGICAL_MINIMUM        0x1
#define ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM        0x2
#define ITEM_TAG_LOCAL_USAGE                0x0
#define PAGE_GENDRIC_DESKTOP_CONTROLS 0x01
#define USAGE_X 0x30
#define USAGE_Y 0x31
BOOL  GetLogicalMax(PUCHAR pData, ULONG nLen, PULONG pXMax, PULONG pYMax)
{
#pragma pack(1)
    typedef struct
    {
        UCHAR Size : 2;
        UCHAR Type : 2;
        UCHAR Tag : 4;
    }ITEM_PREFIX, * PITEM_PREFIX;
    typedef struct
    {
        ITEM_PREFIX Prefix;
        union
        {
            UCHAR UData8[4];
            CHAR  SData8[4];
            USHORT UData16[2];
            SHORT SData16[2];
            ULONG UData32;
            LONG SData32;
        }Data;
    }SHORT_ITEM, * PSHORT_ITEM;
#pragma pack()
    static UCHAR ItemSize[4] = { 0, 1, 2, 4 };
    PUCHAR CurrentOffset = pData;
    ULONG Data = 0;
    ULONG UsagePage;
    ULONG Usage;
    ULONG xMax = 0, yMax = 0;
    do
    {
        PITEM_PREFIX CurrentItem = (PITEM_PREFIX)CurrentOffset;
        UCHAR CurrentItemSize = ItemSize[CurrentItem->Size];
        if (CurrentItem->Type == ITEM_TYPE_LONG)
        {
            return FALSE;
        }
        PSHORT_ITEM CurrentShortItem = (PSHORT_ITEM)CurrentItem;
        if (CurrentItemSize == 1)
            Data = CurrentShortItem->Data.UData8[0];
        else if (CurrentItemSize == 2)
            Data = CurrentShortItem->Data.UData16[0];
        else if (CurrentItemSize == 4)
            Data = CurrentShortItem->Data.UData32;
        if (CurrentItem->Type == ITEM_TYPE_GLOBAL)
        {
            if (CurrentItem->Tag == ITEM_TAG_GLOBAL_USAGE_PAGE)
            {
                UsagePage = Data;
            }
            else if (CurrentItem->Tag == ITEM_TAG_GLOBAL_LOGICAL_MAXIMUM)
            {
                if (UsagePage == PAGE_GENDRIC_DESKTOP_CONTROLS && Usage == USAGE_X)
                {
                    xMax = Data;
                }
                else if (UsagePage == PAGE_GENDRIC_DESKTOP_CONTROLS && Usage == USAGE_Y)
                {
                    yMax = Data;
                }
                //    printf("LogicalMax=%d\n", Data);
            }
            else if (CurrentItem->Tag == ITEM_TAG_GLOBAL_LOGICAL_MINIMUM)
            {
                //printf("LogicalMin=%d\n", Data);
            }
        }
        else if (CurrentItem->Type == ITEM_TYPE_LOCAL)
        {
            if (CurrentItem->Tag == ITEM_TAG_LOCAL_USAGE)
            {
                Usage = Data;
            }
        }
        CurrentOffset += CurrentItemSize + sizeof(ITEM_PREFIX);
    } while (CurrentOffset < (pData + nLen));
    if (xMax == 0 || yMax == 0)
    {
        return FALSE;
    }
    if (pXMax != NULL)
    {
        *pXMax = xMax;
    }
    if (pYMax != NULL)
    {
        *pYMax = yMax;
    }
    return TRUE;
}
HID人机交互QQ群:564808376   
UAC音频QQ群:218581009   
UVC相机QQ群:331552032   
BOT&UASP大容量存储QQ群:258159197   
STC-USB单片机QQ群:315457461   
USB技术交流QQ群2:580684376   
USB技术交流QQ群:952873936    
		 HID开发笔记
			HID开发笔记
			




