HID(Human Interface Device)
即人机接口设备,是指能够通过USB、PS/2等接口进行传输的输入和输出设备,如键盘、鼠标、游戏手柄、扫描仪等。
一、HID设备通讯协议
HID设备通讯协议有两种,分别是HID Boot Protocol和HID Report Protocol。其中HID Boot Protocol是一种通用协议,可用于交换所有HID设备的数据,但是它不支持多个并发数据输入输出;而HID Report Protocol是一种自定义协议,不同的HID设备可以使用不同格式的报告描述符和报告协议来进行数据传输,并支持多个并发数据输入输出。 HID Boot Protocol的报告描述符如下所示:
// HID Boot Protocol Report Descriptor
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x02, // Usage (Mouse)
0xA1, 0x01, // Collection (Application)
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (01)
0x29, 0x03, // Usage Maximum (03)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x95, 0x03, // Report Count (3)
0x75, 0x01, // Report Size (1)
0x81, 0x02, // Input (Data,Var,Abs)
0x95, 0x01, // Report Count (1)
0x75, 0x05, // Report Size (5)
0x81, 0x01, // Input (Cnst,Ary,Abs)
0x05, 0x01, // Usage Page (Generic Desktop)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x81, // Logical Minimum (-127)
0x25, 0x7F, // Logical Maximum (127)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x06, // Input (Data,Var,Rel)
0xC0, // End Collection
0xC0 // End Collection
而HID Report Protocol的报告描述符,则是根据HID设备的具体情况而定,下面以鼠标为例,列出其报告描述符:
// Mouse HID Report Descriptor
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x02, // USAGE (Mouse)
0xA1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xA1, 0x00, // COLLECTION (Physical)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x01, // INPUT (Constant)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xC0, // END_COLLECTION
0xC0 // END_COLLECTION
二、HID设备驱动程序
HID设备需要特定的驱动程序才能被计算机识别和使用。通常情况下,Windows操作系统内置了很多常见的HID设备驱动程序,可直接使用。而对于某些不常见的HID设备,则需要手动安装其对应的驱动程序。
三、HID设备数据传输
HID设备的数据传输主要是通过输入报告和输出报告进行的。 输入报告是指从HID设备向计算机发送数据的报告,一般用于传输HID设备的输入信号,如键盘的按键、鼠标的位置等信息。输出报告则是指从计算机向HID设备发送数据的报告,一般用于传输HID设备的输出信号,如LED灯的亮度和颜色等信息。 下面是一个使用WINAPI函数来进行HID设备输入输出的例子:
// WinHidIO.c - Windows HID I/O test program
#include <tchar.h>
#include <windows.h>
#include <stdio.h>
const UINT32 g_OutReportSize = 16;
const UINT32 g_InReportSize = 16;
HANDLE g_hDev = NULL;
BYTE g_OutBuf[g_OutReportSize];
BYTE g_InBuf[g_InReportSize];
BOOL OpenDevice()
{
GUID guid;
HDEVINFO hdevInfo;
SP_DEVICE_INTERFACE_DATA ifaceData;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData;
// Get the HID GUID class
if (!SetupDiClassGuidsFromName(TEXT("HIDClass"), &guid, 1, NULL))
return FALSE;
// Get devices matching HID GUID class
hdevInfo = SetupDiGetClassDevs(&guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hdevInfo == INVALID_HANDLE_VALUE)
return FALSE;
// Enumerate all devices
ifaceData.cbSize = sizeof(ifaceData);
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH);
detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
for (DWORD i = 0; SetupDiEnumDeviceInterfaces(hdevInfo, NULL, &guid, i, &ifaceData); ++i)
{
DWORD dwSize = 0;
BOOL bRet = SetupDiGetDeviceInterfaceDetail(hdevInfo, &ifaceData, detailData, sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA) + MAX_PATH, &dwSize, NULL);
if (bRet)
{
// Open HID device with read/write access
g_hDev = CreateFile(detailData->DevicePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (g_hDev != INVALID_HANDLE_VALUE)
{
// Set feature report
HIDD_ATTRIBUTES attr;
HidD_GetAttributes(g_hDev, &attr);
printf("Found HID device (vid=%04X, pid=%04X)\n", attr.VendorID, attr.ProductID);
// Write output report
bRet = HidD_SetOutputReport(g_hDev, g_OutBuf, g_OutReportSize);
if (bRet)
{
// Read input report
memset(g_InBuf, 0, g_InReportSize);
bRet = HidD_GetInputReport(g_hDev, g_InBuf, g_InReportSize);
if (bRet)
{
// Process input report data
for (UINT32 j = 0; j < g_InReportSize; ++j)
printf("InBuf[%d] = %02X\n", j, g_InBuf[j]);
}
}
CloseHandle(g_hDev);
g_hDev = NULL;
}
}
}
free(detailData);
SetupDiDestroyDeviceInfoList(hdevInfo);
return TRUE;
}
int main()
{
// Fill output report buffer
memset(g_OutBuf, 0, g_OutReportSize);
g_OutBuf[0] = 0x01;
// Open HID device and perform I/O operations
if (OpenDevice())
printf("Test completed successfully\n");
return 0;
}
四、HID设备应用场景
HID设备可以广泛应用于各种交互式设备上,如电脑、手机、平板等。下面是一些常见的应用场景:
1.键盘和鼠标
键盘和鼠标是最常见的HID设备之一,可以用于输入文字、控制光标等操作。
2.游戏手柄和方向盘
游戏手柄和方向盘是常见的游戏控制器,可以实现游戏中的各种操作,如移动、跳跃、射击等。
3.触摸屏
触摸屏可以用于移动设备上的交互,如点击、滑动、缩放等操作。
4.扫描仪
扫描仪可以用于将文档或图片数字化,便于存储和传输。
5.电视遥控器
电视遥控器可以通过HID设备来实现对电视的遥控操作,包括调节音量、切换频道等。
五、总结
HID设备是一种重要的人机接口设备,其通讯协议、驱动程序、数据传输等方面都需要进行详细的了解和应用。常见的HID设备包括键盘、鼠标、游戏手柄、触摸屏、扫描仪、电视遥控器等。通过对HID设备的应用,可以实现各种交互性设备操作,方便用户的使用。