本文是<实战解析 USB HID 协议>和<实战解析 USB HID 协议 2>的扩展篇. 不过这次将目光转移到应用了I2C HID协议的设备.1. 硬件部分在单片机/嵌入式应用场景中, 设备间通信只需SCL/SDA 2根信号线; 而HID over I2C协议还额外需要一根INT中断信号. 当I2C Slaver有数据时, 如触摸Pad, 会触发INT信号 (Assert INT#). Host收到中断后才会发起I2C事务(直至此时Host才使能SCL信号, 再通过SDA信号读取数据). 由于这个特性, HID over I2C信号在逻辑分析仪中的输出会呈现一定的规律性: SCL/SDA仅在INT# Assert期间变化; 在INT# De-Assert期间无变化, 这种特性使得波形比较清澈(这样设计可能也是为了省电):
由Acute解析的HID Over I2C波形
常见的I2C HID设备有I2C Touch Pad和I2C Touch Panel, 正好我手边有台带FocalTech I2C Touch Pad的二手笔记本且Touch Pad PCB上有INT/SCL/SDA这些信号的丝印, 方便接转接板. 本文的内容将基于此笔记本展开.
FocalTech I2C Pad PCB
2.固件部分硬件部分的准备完成, 再看看固件/OS部分. HID over I2C协议获取HID Report Descriptor的过程有点绕. OS需要从ACPI中获得HID Descriptor Register. OS通过HID Descriptor Register去Touch Pad中读取HID Descriptor. 注意, 目前读到的是HID Descriptor, 其结构如下:typedef struct _HIDDescriptor
uint16 wHIDDescLength;
uint16 bcdVersion;
uint16 wReportDescriptorLength;
uint16 wReportDescriptorRegister;
uint16 wInputRegister;
uint16 wMaxInputLength;
uint16 wOutputRegister;
uint16 wMaxOutputLength;
uint16 wCommandRegister;
uint16 wDataRegister;
uint16 wVendorID;
uint16 wProductID;
uint16 wVersionID;
uint32 Reserved;
}HIDDescriptor;OS再从HIDDescriptor->wReportDescriptorRegister获得Report Descriptor Register地址, 最终通过该地址获得HID Report Descriptor. 该过程的示意图如下:
另外OS从HIDDescriptor->wCommandRegister获得Command Register, 该寄存器用于Host向Slave发出如SetPower/RESET请求. 2.1. SetPower/RESETOS在读取HID Descriptor后, 在进一步读取HID Report Descriptor前, 还需要对HID Over I2C设备依次执行2个动作SetPower和RESET
这2个命令都是OS通过向HIDDescriptor->wCommandRegister(在本文中是0x22)指定的寄存器写入2 BYTE的Command实现.
命令
HOST向wCommandRegister写入的2 BYTE数值
备注
SET_POWER
BYTE0=0x08, BYTE1=0x00
SET_POWER=On, 让设备开始工作
RESET
BYTE0=0x01, BYTE1=0x00
1.Slave重置自身;
2.重置完成后Assert INT#
3.Host发现INT# Assert后发起I2CRead事务
4.Slave持续向Host返回0x00 0x00作为重置成功的标志
5.Host读取完毕后, Slave将De-Assert INT#
附注, 如果RESET流程执行失败, Windows设备管理器中的I2C 设备会出现黄色感叹号.
2.2. 获取I2C Slave Address和HID Descriptor Register Address HID over I2C协议本质上依然是I2C协议和HID协议. 对于I2C协议, 固件需要向主机提供I2C Slave Address; 而对于HID协议, 固件需要向Host提供HID Descriptor Register. Host获得Descriptor Register后, 再通过I2C 协议(Repeat Start事务)从Pad固件中获得 HID Descriptor. 这种关系就像C语言里的指针: HID Descriptor Register就像HID Descriptor类型的指针, 通过该指针获取HID Descriptor结构体变量.
获取方式
备注
I2C Slaver Address
OS enable ACPI以后, 由Method(_INI)设定, OS通过Method(_CRS)获取
字面意思, 就是Slave设备地址, 在本文中就是I2C Touch Pad Slave地址.
HID Descriptor Register
OS enable ACPI以后, 由Method(_INI)设定, OS通过Method(_DSW)获取
HID over I2C协议中最重要的部分. 由厂商提供, 固件设定的16bit地址. Method(_DSW)中获得HID Descriptor Register, 再从Register中获得HID Descriptor.
作为Pad厂商和主机厂商以外的读者, 可以通过RW dump整个ACPI Table获得这2个信息(本文使用的ACPI Dump文件参见附录):a. 首先查看设备管理器, 定位I2C Touch Pad的Bios Device Name:
b. 根据Bios Devic
...(已截断)
---
来源: 看雪论坛
原文链接: https://bbs.kanxue.com/thread-289800.htm
[原创] 实战解析I2C HID协议----以I2C Touch Pad为例
77 浏览
5 回复
很棒的分享!不过有几处_DSM写成DSW了吧
AmnesiaSoly
很棒的分享!不过有几处_DSM写成DSW了吧
确实,感谢指出
很棒的分享!不过有几处_DSM写成DSW了吧
确实,感谢指出
确实,还是你眼尖发现了,谢谢
帖主你好,不知道为什么没有权限私信,我想问下我用STM32模拟触摸板通信主机已经识别到touchpad成功了,但是为什么发送移动数据报告成功了 鼠标却没有反应呢?
mb_vhtnulms
帖主你好,不知道为什么没有权限私信,我想问下我用STM32模拟触摸板通信主机已经识别到touchpad成功了,但是为什么发送移动数据报告成功了 鼠标却没有反应呢?
你用逻辑分析仪的hid over iic看下通信过程,正常吗
帖主你好,不知道为什么没有权限私信,我想问下我用STM32模拟触摸板通信主机已经识别到touchpad成功了,但是为什么发送移动数据报告成功了 鼠标却没有反应呢?
你用逻辑分析仪的hid over iic看下通信过程,正常吗