Open rainit2006 opened 7 years ago
HIDクラスでは、レポートと呼ばれる単位でデータを転送する レポートの中にどのような情報がどのように並んでいるかは、レポートディスクリプタによって定義 レポートディスクリプタは、他のディスクリプタと構造が全く違う HIDディスクリプタに続いて送られ、可変長。 レポートディスクリプタのサイズはHIDディスクリプタのwDescriptorLengthで定義
HID インターフェースでは、Input、Output、Featureの3タイプのレポートをデバイスとホストの間で転送し ます。
レポートディスクリプタはデバイスに関する情報を提供するまとまり(アイテム)から構成される アイテムはショートアイテムとロングアイテムの2種類 item type には「Main」「Global」「Local」の 3 種類があり、Main item type(リポートディスクリプタ内 のデータフィールドを定義もしくはグループ化に使用)は 5 種類、Global item type(データを記述に使用) は12 種類、Local item type(特性を定義に使用)は 10 種類の item tag があります。
アイテムの形式 すべてのアイテムは1バイトのプレフィックスを持つ。 アイテムは「data」、「item tag」、「item type」と「itemSize」の 4 種類から構成されます。
パース時の動作 メインアイテムがでてくると新しいレポート構造が一時状態テーブルに割り当てられる。 グローバルアイテムはメインアイテムが出てきても一時状態テーブルに残る。 ローカルアイテムはメインアイテムが出てきたら一時状態テーブルから消える。
Open the target Device 目的是获得目标Device的句柄
流程:
2, SetupDiGetClassDevs: 利用GUID取得所有HID Devices信息集合
returns a handle to a device information set that contains requested device information elements for a local computer. 从GUID取得devices信息。
另外:リモートコンピュータ上のデバイスに関するデバイス情報セットを取得するには、SetupDiGetClassDevsEx関数を使います。
3, SetupDiEnumDeviceInfo: 枚举取得每个HID Device信息(SP_DEVINFO_DATA 结构体),利用index循环取得 returns a SP_DEVINFO_DATA structure that specifies a device information element in a device information set. 根据index参数取得相应的device信息。
4, 从SP_DEVINFO_DATA structure里获得HardwareID(HID)。具体实现: SetupDiGetDeviceRegistryProperty: retrieves a specified Plug and Play device property. 第三个参数里指定“SPDRP_HARDWAREID”时刻获得HardwareID。 HardwareID内容类似:"HID\VID_054C&PID_0872&MI_01&Col04"
5, 将HaredwareID和目标HardwareID进行比较,判断当前取得的Device是否是TargetDevice。 如果找到TargetDevice则往下执行。
6,取出目标Device的Path信息(变量名: strDevicePath)。具体实现用到下面两个接口。 (1)SetupDiEnumDeviceInterfaces 判断能否取得Interface以及Interface的size (2)SetupDiGetDeviceInterfaceDetail: returns details about a device interface. 其中的output 之一DeviceInterfaceDetailData里包含了path信息。
7, 取得句柄 hDeviceHandle = CreateFile(strDevicePath, GENERIC_READ | GENERIC_WRITE/0/, FILE_SHARE_READ | FILE_SHARE_WRITE, (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, 0, NULL );
8, SetupDiDestroyDeviceInfoList
向目标Device(HID设备)发送command 方法:HidD_SetFeature
//Example
UCHAR buffer[BUFFER_LENGETH] = {0};
buffer[0] = 0x01;
buffer[1] = 0x0F;
buffer[2] = 0x5B;
bRet = HidD_SetFeature(m_hDeviceHandle, buffer, BUFFER_LENGETH);
取得Device状态 根据需要,先HidD_SetFeature, 然后HidD_GetFeature。
其他常用函数: SetupDiGetDeviceInstanceId 可以获得DeviceID
设定设备的有效/无效 的处理流程:
SetupDiGetClassDevs ⇒ デバイス情報セットの取得
SetupDiEnumDeviceInfo ⇒ デバイスの列挙
列挙中に
CM_Get_DevNode_Status ⇒ デバイスの状態(有効or無効)を取得
SetupDiGetDeviceRegistryProperty ⇒ デバイス名を取得
取得したりして、制御対象のデバイスを探します。
SetupDiSetClassInstallParams ⇒ デバイスの有効/無効化
SetupDiChangeState ⇒ 変更を反映
SetupDiDestroyDeviceInfoList ⇒ デバイス情報セットを解放
DeviceIOControl 指定されたデバイスドライバへ制御コードを直接送信し、対応するデバイスに対応する動作をさせます。 用来控制我们指定设备的输入输出操作,使设备按照我们发的指令去工作。 应用场景: 如获取硬件设备信息、与硬件设备通信(读写数据)等
For most types of device, the application can use the standard MicrosoftWin32 API function DeviceIoControl. On the driver side, an application’s call to DeviceIoControl turns into an I/O request packet (IRP) with the major function code IRP_MJ_DEVICE_CONTROL. But,with several specific types of device, however, an application isn’t supposed to (or can’t) use DeviceIoControl to talk to a driver.
BOOL DeviceIoControl(
HANDLE hDevice, // デバイス、ファイル、ディレクトリいずれかのハンドル
DWORD dwIoControlCode, // 実行する動作の制御コード
LPVOID lpInBuffer, // 入力データを供給するバッファへのポインタ
DWORD nInBufferSize, // 入力バッファのバイト単位のサイズ
LPVOID lpOutBuffer, // 出力データを受け取るバッファへのポインタ
DWORD nOutBufferSize, // 出力バッファのバイト単位のサイズ
LPDWORD lpBytesReturned, // バイト数を受け取る変数へのポインタ
LPOVERLAPPED lpOverlapped // 非同期動作を表す構造体へのポインタ
);
这里的hDevice必须来自CreateFile函数的返回值。
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
参数:要打开的文件名,访问权限,共享模式,安全属性,文件存在与不存在时的文件创建模式,文件属性设定(隐藏、只读、压缩、指定为系统文件等),文件副本句柄。
要说明的是第一个参数lpFileName,是设备的名称或者是和设备关连的驱动的名称,一般用\\.\DeviceName的形式,比如要打开逻辑驱动盘A就用\\.\a,也可以用\\.\PhysicalDevice0,\\.\PhsycalDebive1来指定物理驱动器,\\.\PhysicalDevice0表示本机的物理驱动器0(一般是主硬盘),从而来获取硬盘的序列号、模块名、扇区数、磁头数等相关信息
注意: DeviceIOControl函数的输入参数dwIoControlCode 表示 控制设备的指令 微软已经定义好了很多种操作,在winioctl.h文件中,但最终都是通过CTL_CODE宏来实现的,其实这就是一种通信协议。 For lists of supported control codes, see the following topics: • Communications Control Codes • Device Management Control Codes • Directory Management Control Codes • Disk Management Control Codes • File Management Control Codes • Power Management Control Codes • Volume Management Control Codes
如果某些设备没有支持这些generic指令,则无法通过DeviceIOControl函数对设备操作。
涉及到显卡,声卡的功能对应,则直接调用各个厂家(Intel, Nvidia等)提供的API
Device Management的函数一览 (SetupDixxxxx系列): https://msdn.microsoft.com/ja-jp/library/cc429159.aspx Device入出力 (DeviceIOControl) https://msdn.microsoft.com/ja-jp/library/cc392652.aspx
Collection Capability The capability of a collection is defined by its usage, reports, link collections, and controls. To obtain a summary of a collection's capability, a user-mode application or kernel-mode driver calls HidP_GetCaps to obtain a HIDP_CAPS structure. https://msdn.microsoft.com/windows/hardware/drivers/hid/collection-capability
HID drivers Human Interface Devices (or HID). Typically, these are devices that humans use to directly control the operation of computer systems. The definition of HID started as a device class over USB. Today, HID devices include: alphanumeric displays, barcode readers, volume controls on speakers/headsets, auxiliary displays, sensors, and MRI’s (yes, in hospitals). In addition, many hardware vendors use HID for their proprietary devices. https://msdn.microsoft.com/zh-cn/windows/hardware/drivers/hid/index
Today, HID has a standard protocol over multiple transports, and the following transports are supported natively in Windows 8 for HID: •USB •Bluetooth •Bluetooth LE •I²C https://msdn.microsoft.com/zh-cn/windows/hardware/drivers/hid/introduction-to-hid-concepts