一 识别设备
要和自己的HID设备通信,第一步当然是找到设备.找到设备的原理很简单,我们把读到的设备信息与实际设备的信息相比较,就可以知道是否读到了正确的设备. 在USB设备中,设备描述符里的信息可以唯一的标识不同的USB设备. 我们一般用
idVendor idProduct bcdDevice
这三个信息识别一个USB设备. 这三个信息都是设备描述符里的属性. 所以我们的上位机程序可以把读到的上述三个信息与实际设备的相比较,从而确定是否正确的连接到了设备. 实际设备的设备描述符在设备的固件程序中可以找得到,如果你没有固件程序的源码,也可以通过一些工具软件读出来设备的描述符信息,比如USB View就是一个很好用的工具.
知道了识别设备的原理,就可以通过DDK里相关的API接口去实现了.
HidD_GetAttributes函数可以获取到上面的属性信息, 它的定义如下:
BOOLEAN HidD_GetAttributes(
IN HANDLE HidDeviceObject,
OUT PHIDD_ATTRIBUTES Attributes
);
第二个参数是一个指向HIDD_ATTRIBUTES结构体的指针, 这个结构体的定义如下:
typedef struct _HIDD_ATTRIBUTES {
ULONG Size;
USHORT VendorID;
USHORT ProductID;
USHORT VersionNumber;
} HIDD_ATTRIBUTES
所以,这个函数可以从设备中读到我们想要的信息. 但是,函数还有一个入口参数, HidDeviceObject,这是一个指向设备的句柄,所以在调用HidD_GetAttributes前,先要调用CreateFile函数返回一个有效的设备操作句柄. 有了这个句柄才能与设备进行正常的通信.
CreateFile的第一个参数要求提供一个设备名,这里我们要提供一个完整的设备路径名,否则将返回无效的句柄. 这个路径名是操作系统在识别到设备后分配给设备的, 可以通过DDK里的接口SetupDiGetDeviceInterfaceDetail来获取到, 这个函数的定义如下:
SetupDiGetDeviceInterfaceDetailW(
__in HDEVINFO DeviceInfoSet,
__in PSP_DEVICE_INTERFACE_DATA DeviceInterfaceData,
__out_bcount_opt(DeviceInterfaceDetailDataSize) PSP_DEVICE_INTERFACE_DETAIL_DATA_W DeviceInterfaceDetailData,
__in DWORD DeviceInterfaceDetailDataSize,
__out_opt PDWORD RequiredSize,
__out_opt PSP_DEVINFO_DATA Devic