Readfile失败,错误代码1,这是肿么回事?

hfut_cy 2014-07-29 09:35:53
想做一个C++实现通过USB读取键盘发送的数据,即通过Readfile的同步通信模式,在执行到Readfile语句前程序阻塞,此时键盘再通过敲击给程序发送数据,程序读取键盘发送的数据存在buffer中。但是代码执行SetupDiGetClassDevs,SetupDiEnumDeviceInterfaces,两次SetupDiGetDeviceInterfaceDetail,createfile都正常,但执行到Readfile时却出现问题,始终没有想要的效果,大家觉得有什么问题啊。源代码如下:

int main()
{
ULONG Required;
//定义strUsbPath 设备路径
CString strUsbPath;
//定义一个GUID的结构体HidGuid来保存HID设备的接口类GUID。
GUID GUID_DEVINTERFACE_USB_DEVICE = {0xA5DCBF10,0x6530,0x11D2,0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED};
GUID HidGuid;
//定义一个DEVINFO的句柄hDevInfoSet来保存获取到的设备信息集合句柄。
HDEVINFO hDevInfoSet;
//DevInfoData,用来保存设备的驱动接口信息
SP_DEVICE_INTERFACE_DATA DevInfoData;
//定义一个BOOL变量,保存函数调用是否返回成功
BOOL Result;
//定义一个RequiredSize的变量,用来接收需要保存详细信息的缓冲长度。
DWORD RequiredSize;
//定义一个指向设备详细信息的结构体指针。
PSP_DEVICE_INTERFACE_DETAIL_DATA pDevDetailData;
//定义一个用来保存打开设备的句柄。
HANDLE DevHandle;
//定义一个HIDD_ATTRIBUTES的结构体变量,保存设备的属性。
HIDD_ATTRIBUTES DevAttributes;

//对DevInfoData结构体的cbSize初始化为结构体大小
DevInfoData.cbSize=sizeof(DevInfoData);

//调用HidD_GetHidGuid函数获取HID设备的GUID,并保存在HidGuid中。
HidD_GetHidGuid(&HidGuid);

hDevInfoSet=SetupDiGetClassDevs((LPGUID)&GUID_DEVINTERFACE_USB_DEVICE,NULL,NULL,DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
if (hDevInfoSet == INVALID_HANDLE_VALUE)
{
cout<<"没有找到正在使用的设备"<<endl;
SetupDiDestroyDeviceInfoList(hDevInfoSet);
}

int MemberIndex=0;

while(1)
{
cout<<"开始枚举第"<<MemberIndex+1<<"个设备"<<endl;
//调用SetupDiEnumDeviceInterfaces在设备信息集合中获取编号为MemberIndex的设备信息。
Result=SetupDiEnumDeviceInterfaces(hDevInfoSet,NULL,&GUID_DEVINTERFACE_USB_DEVICE,MemberIndex,&DevInfoData);
MemberIndex++;


if(Result==FALSE){cout<<"获取设备信息失败"<<endl;break;}

Result=SetupDiGetDeviceInterfaceDetail(hDevInfoSet,&DevInfoData,NULL,0,&RequiredSize,NULL);
if (Result==FALSE)
{
cout<<"第一次获取设备细节失败,错误代码为"<<GetLastError()<<endl;
}

//然后,分配一个大小为RequiredSize缓冲区,用来保存设备详细信息。
pDevDetailData=(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);

if(pDevDetailData==NULL) //如果内存不足,则直接返回。
{
//TRACE("内存不足!");
cout<<"内存不足"<<endl;
SetupDiDestroyDeviceInfoList(hDevInfoSet);
return FALSE;
}

//并设置pDevDetailData的cbSize为结构体的大小(注意只是结构体大小,不包括后面缓冲区)
pDevDetailData->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

//然后再次调用SetupDiGetDeviceInterfaceDetail函数来获取设备的详细信息。这次调用设置使用的缓冲区以及缓冲区大小。
Result=SetupDiGetDeviceInterfaceDetail(hDevInfoSet,&DevInfoData,pDevDetailData,RequiredSize,&Required,NULL);
//如果调用失败,则查找下一个设备。
if(Result==FALSE) {cout<<"第二次获取设备细节失败"<<endl;continue;}

//将设备路径复制出来,然后销毁刚刚申请的内存。
CString m_strDevicePath;//=pDevDetailData->DevicePath;
cout<<"格式化前设备路径"<<m_strDevicePath<<endl;
m_strDevicePath.Format(_T("%s"),pDevDetailData->DevicePath);
cout<<"设备路径为"<<m_strDevicePath<<endl;
free(pDevDetailData);

DevHandle=CreateFile(m_strDevicePath,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)NULL,OPEN_EXISTING,0,NULL);
if(DevHandle == INVALID_HANDLE_VALUE)
{
cout<<"创建设备句柄失败,失败代码为 "<< GetLastError()<<endl;
}

//如果打开成功,则获取设备属性。
if(DevHandle!=INVALID_HANDLE_VALUE)
{
cout<<"创建设备句柄成功"<<endl;
//获取设备的属性并保存在DevAttributes结构体中
Result=HidD_GetAttributes(DevHandle,&DevAttributes);

//获取失败,查找下一个
if(Result==FALSE)
{
//关闭刚刚打开的设备
cout<<"获取设备HID属性失败,关闭该句柄,继续枚举下一设备,错误代码为 "<<GetLastError()<<endl;
CloseHandle(DevHandle);
DevHandle=NULL;
}
else cout<<DevAttributes.ProductID<<"||"<<DevAttributes.Size<<"||"<<DevAttributes.VendorID<<"||"<<DevAttributes.VersionNumber<<endl;
}
char buf[1024];DWORD len = 0;
bool res = ReadFile(DevHandle,buf,1024,&len,NULL);
if(!res)
{
cout<<"读取设备失败,关闭该句柄,失败代码为 "<<GetLastError()<<endl;
CloseHandle(DevHandle);
}
cout<<endl;
}
return 0;

}
...全文
576 11 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
e421970083 2017-02-16
  • 打赏
  • 举报
回复
同求这个问题,请问楼主解决了么?
wesley 2014-08-01
  • 打赏
  • 举报
回复
什么时候CSDN可以邀请回答问题了?这个问题我不会啊!
hfut_cy 2014-08-01
  • 打赏
  • 举报
回复
引用 9 楼 cumtgao 的回复:
什么时候CSDN可以邀请回答问题了?这个问题我不会啊!
哈,第一次发帖就又这个功能哈。
hfut_cy 2014-07-31
  • 打赏
  • 举报
回复
引用 7 楼 Huntercao 的回复:
[quote=引用 6 楼 hfut_cy 的回复:] 如果是驱动的问题,那用方法GET_STD_HANDLE方法可以获取键盘的句柄,然后通过Readfile读取键盘输入的数据啊。
我的意思是你可以获得键盘设备的句柄。但是键盘的驱动程序堆栈里面没有一个程序来响应由Readfile发起的IRP_MJ_READ请求。键盘驱动程序可能只处理HID_READ_REPORT类别的IOCTL来返回数据。[/quote] 哦,我大概了解到了,我再试试。
曹大夯 2014-07-30
  • 打赏
  • 举报
回复
引用 6 楼 hfut_cy 的回复:
如果是驱动的问题,那用方法GET_STD_HANDLE方法可以获取键盘的句柄,然后通过Readfile读取键盘输入的数据啊。
我的意思是你可以获得键盘设备的句柄。但是键盘的驱动程序堆栈里面没有一个程序来响应由Readfile发起的IRP_MJ_READ请求。键盘驱动程序可能只处理HID_READ_REPORT类别的IOCTL来返回数据。
hfut_cy 2014-07-30
  • 打赏
  • 举报
回复
引用 5 楼 Huntercao 的回复:
[quote=引用 4 楼 hfut_cy 的回复:] [quote=引用 2 楼 Huntercao 的回复:] HID设备的数据是有专门的HID API去访问的。 参考:Obtaining HID Reports by User-Mode Applications 可以看看WDK例子HClient sample application
好像上面也说可以用Readfile进行数据的读取。[/quote] 你说的很对。理论上来说Readfile应该可以。 Readfile不能正确返回的原因可能是键盘的驱动队列里面,没有驱动来响应你的这个ReadFile对应的IRP_MJ_READ请求。 如果你调试对应的HID MiniDriver你可能就会知道,该MiniDriver可能只支持Read Report/Read Feature之类的IRP/IOCTL请求。[/quote] 如果是驱动的问题,那用方法GET_STD_HANDLE方法可以获取键盘的句柄,然后通过Readfile读取键盘输入的数据啊。
曹大夯 2014-07-29
  • 打赏
  • 举报
回复
HID设备的数据是有专门的HID API去访问的。 参考:Obtaining HID Reports by User-Mode Applications 可以看看WDK例子HClient sample application
袁保康 2014-07-29
  • 打赏
  • 举报
回复
CSDN也可以邀请回答问题了?只不过很遗憾这个问题我不会,我只有过来加加人气了。
曹大夯 2014-07-29
  • 打赏
  • 举报
回复
引用 4 楼 hfut_cy 的回复:
[quote=引用 2 楼 Huntercao 的回复:] HID设备的数据是有专门的HID API去访问的。 参考:Obtaining HID Reports by User-Mode Applications 可以看看WDK例子HClient sample application
好像上面也说可以用Readfile进行数据的读取。[/quote] 你说的很对。理论上来说Readfile应该可以。 Readfile不能正确返回的原因可能是键盘的驱动队列里面,没有驱动来响应你的这个ReadFile对应的IRP_MJ_READ请求。 如果你调试对应的HID MiniDriver你可能就会知道,该MiniDriver可能只支持Read Report/Read Feature之类的IRP/IOCTL请求。
hfut_cy 2014-07-29
  • 打赏
  • 举报
回复
引用 2 楼 Huntercao 的回复:
HID设备的数据是有专门的HID API去访问的。 参考:Obtaining HID Reports by User-Mode Applications 可以看看WDK例子HClient sample application
好像上面也说可以用Readfile进行数据的读取。
hfut_cy 2014-07-29
  • 打赏
  • 举报
回复
引用 2 楼 Huntercao 的回复:
HID设备的数据是有专门的HID API去访问的。 参考:Obtaining HID Reports by User-Mode Applications 可以看看WDK例子HClient sample application
引用 1 楼 kangear 的回复:
CSDN也可以邀请回答问题了?只不过很遗憾这个问题我不会,我只有过来加加人气了。
哦,可以邀请回答的,发帖的时候点下就可以了。

21,615

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧