//可以查看按游戏手柄按钮时的情况.
//USB接口的游戏手柄
//编译环境:Windows 2000 server+VC++ 6.0+Win2K DDK
#include <stdio.h>
#include <windows.h>
#include <setupapi.h>
#include <tchar.h>
extern "C"
{
#include <hidsdi.h>
}
void main()
{
GUID HidGuid;
// 查找本系统中HID类的GUID标识
HidD_GetHidGuid(&HidGuid);
_tprintf("系统中HID类的GUID标识为:%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n",
HidGuid.Data1,HidGuid.Data2 ,HidGuid.Data3 ,
HidGuid.Data4[0],HidGuid.Data4[1],HidGuid.Data4[2],
HidGuid.Data4[3],HidGuid.Data4[4],HidGuid.Data4[5],
HidGuid.Data4[6],HidGuid.Data4[7]);
// 准备查找符合HID规范的USB设备
HDEVINFO hDevInfo = SetupDiGetClassDevs(&HidGuid,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
if (hDevInfo == INVALID_HANDLE_VALUE)
{
_tprintf("符合HID规范的USB设备发生错误\n");
return;
}
_tprintf("正在查找可用的USB设备...\n");
DWORD MemberIndex = 0;
SP_DEVICE_INTERFACE_DATA DeviceInterfaceData;
BOOL bSuccess = FALSE;
DeviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
do
{
bSuccess = SetupDiEnumDeviceInterfaces(hDevInfo,
NULL,
&HidGuid,
MemberIndex,
&DeviceInterfaceData);
if ((!bSuccess) && (GetLastError() == ERROR_NO_MORE_ITEMS))
{
if(MemberIndex == 0)
_tprintf("抱歉,未找到可用的USB设备!\n");
else
_tprintf("没有更多的可用的USB设备!\n");
SetupDiDestroyDeviceInfoList(hDevInfo);
return;
}
_tprintf("找到了一个USB设备:\n");
//若找到了一个USB设备,则获取该设备的细节信息
PSP_DEVICE_INTERFACE_DETAIL_DATA pDeviceInterfaceDetailData;
DWORD Length = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&DeviceInterfaceData,
NULL,
0,
&Length,
NULL);
pDeviceInterfaceDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
pDeviceInterfaceDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA); //MUST BE!!!
if (!SetupDiGetDeviceInterfaceDetail(hDevInfo,
&DeviceInterfaceData,
pDeviceInterfaceDetailData,
Length,
NULL,
NULL))
_tprintf("查找路径设备时出错!\n");
else
_tprintf("设备路径:%s\n",pDeviceInterfaceDetailData->DevicePath );
//打开设备句柄
HANDLE hDeviceHandle = CreateFile(pDeviceInterfaceDetailData->DevicePath ,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if (hDeviceHandle == INVALID_HANDLE_VALUE)
_tprintf("打开设备路径出错!\n");
else
{
HIDD_ATTRIBUTES Attributes;
HidD_GetAttributes(hDeviceHandle,&Attributes);
//将有关该设备的标识显示出来
_tprintf("供应商ID\t:0X%04X\n",Attributes.VendorID);
_tprintf("产品ID\t:0X%04X\n",Attributes.ProductID);
_tprintf("产品版本号:0X%04X\n",Attributes.VersionNumber);
WCHAR mString[256];
TCHAR Buffer[256];
HidD_GetManufacturerString(hDeviceHandle,mString,sizeof(mString));
if (wcstombs(Buffer,mString,256) == -1) // fail
Buffer[0] = NULL;
_tprintf("生产商:\t%s\n",Buffer);
HidD_GetProductString(hDeviceHandle,mString,sizeof(mString));
if (wcstombs(Buffer,mString,256) == -1)
Buffer[0] = NULL;
_tprintf("产品名称:\t%s\n",Buffer);
// 通信:
PHIDP_PREPARSED_DATA pHidpPreparsedData;
HIDP_CAPS hidPCaps;
if (!HidD_GetPreparsedData(hDeviceHandle,&pHidpPreparsedData))
{
_tprintf("获取 HID PREPARED DATA 失败!\n");
return;
}
NTSTATUS status = HidP_GetCaps(pHidpPreparsedData,&hidPCaps);
if (status == HIDP_STATUS_SUCCESS)
{
_tprintf("CAP信息如下:\n");
_tprintf(" InputReportByteLength %d\n", hidPCaps.InputReportByteLength);
_tprintf(" OutputReportByteLength %d\n", hidPCaps.OutputReportByteLength);
}
DWORD nReadBytes = 0;
BYTE *pInputReport = new BYTE[hidPCaps.InputReportByteLength];
memset(pInputReport,0,hidPCaps.InputReportByteLength);
do
{
ReadFile(hDeviceHandle,pInputReport,hidPCaps.InputReportByteLength,&nReadBytes,NULL);
if (hidPCaps.InputReportByteLength == nReadBytes)
{
for(unsigned int i=0; i<(nReadBytes-1);i++)
_tprintf("%02x-",pInputReport[i]);
_tprintf("%02x\r",pInputReport[nReadBytes-1]);
}
if (pInputReport[nReadBytes-2] == 0x20) //break the loop when pressing a specific key
{
_tprintf("\n");
break;
}
Sleep(10);
}while(hidPCaps.InputReportByteLength == nReadBytes);
//释放句柄资源
CloseHandle(hDeviceHandle);
}
MemberIndex++;
}while(bSuccess);
SetupDiDestroyDeviceInfoList(hDevInfo);
}