USB不能打开请各位看看错在哪里
我写的用来打开US旧的device是可以打开可以使用的,但是新的却不可以,我知道新的机器的vid,pid都改变了,但是我已经将所有的代码里的vid ,pid改成新的了。打开程序每次运行到SetupDiEnumDeviceInterfaces里面返回的strtInterfaceData.Flags=SPINT_ACTIVE,说明device已经在启用了。但是旧机器却没有这种情况这是怎么回事呢?跟硬件有关?
下面是代码:
BOOL CUSBCalcDlg::UsbOpenDriver(HANDLE *hDevice)
{
// TODO: Add your control notification handler code here
#ifdef Debug_mode
MessageBox(_T("start the usbopendriver "),NULL, NULL);
#endif
HDEVINFO hDevInfo = SetupDiGetClassDevs(&guidHID,NULL,0, //取得HID资讯的结构阵列//失败了.
DIGCF_PRESENT|DIGCF_INTERFACEDEVICE );
if(hDevInfo == INVALID_HANDLE_VALUE) //没有设备连接
{
#ifdef Debug_mode
MessageBox(_T("can not find the device"),NULL, NULL);
#endif
return FALSE;
}
SP_DEVICE_INTERFACE_DATA strtInterfaceData;
strtInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
DWORD index = 0;
CString temp;
BOOL findFlag = FALSE;
int i = 0;
while(1) // 查找人体学输入设备类USB,直到查完或已经查到为止
{
//枚举每一个设备
if(!SetupDiEnumDeviceInterfaces(hDevInfo,
NULL,
&guidHID,
i,
&strtInterfaceData))
{
#ifdef Debug_mode
MessageBox((LPCTSTR)strtInterfaceData.Flags,NULL, NULL);
#endif
break;
}
//strtInterfaceData.Flags = SPINT_DEFAULT;
i++;
if(strtInterfaceData.Flags == SPINT_ACTIVE )
{
//调用两次SetupDiGetDeviceInterfaceDetail()
//第一次调用,虽然返回值出错,但获得DeviceInterfaceDetailDataSize数值的大小,存在strSize中
//第二次调用,函数执行正常,可以获得PSP_DEVICE_INTERFACE_DETAIL_DATA结构
//通过两次调用,获得设备的路径名称。
#ifdef Debug_mode
MessageBox(_T("stuck here in the second call"),NULL, NULL);
#endif
DWORD strSize = 0, requiesize = 0;
SetupDiGetDeviceInterfaceDetail(hDevInfo, &strtInterfaceData, NULL, 0, &strSize, NULL);
requiesize = strSize;
PSP_DEVICE_INTERFACE_DETAIL_DATA strtDetailData;
strtDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(requiesize);
strtDetailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
SP_DEVINFO_DATA infodata;
infodata.cbSize = sizeof(SP_DEVINFO_DATA);
if(!SetupDiGetDeviceInterfaceDetail(hDevInfo,
&strtInterfaceData,
strtDetailData,
strSize,
&requiesize,
NULL))
{
#ifdef Debug_mode
MessageBox(_T("stuck here in the scecond SetupDiGetDeviceInterfacDetail call"),NULL, NULL);
#endif
free(strtDetailData);
break;
}
CString str;
str = strtDetailData -> DevicePath;
str.MakeLower();
if(str.Find(_T("vid_c251&pid_1301")) == -1) //是否是我们所需的设备
{
#ifdef Debug_mode
MessageBox(_T("can not find the device"),NULL, NULL);
#endif
continue;
}
*hDevice = CreateFile(strtDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL); //取得设备的句柄
if(*hDevice == INVALID_HANDLE_VALUE)
{
#ifdef Debug_mode
MessageBox(NULL, _T("could not get the device handle "), NULL);
#endif
free(strtDetailData); //释放资源
continue;
}
free(strtDetailData); //释放资源
/////////////////////////////////////////////////////////////////////////
/////读取硬件信息,判断是否是我们的设备
DWORD BytesReturned;
BYTE deviceDescriptor[50];
if(!DeviceIoControl(*hDevice,
IOCTL_USBKBD_GET_DEVICE_DESCRIPTOR,
NULL,
0, // Input
deviceDescriptor,
sizeof(deviceDescriptor), // Output
&BytesReturned, NULL))
{
#ifdef Debug_mode
MessageBox(NULL, _T("could not get the device descriptor"), NULL);
#endif
// Could not get deveice descriptor
CloseHandle(*hDevice);
continue;
}
if((deviceDescriptor[0x0C] != 0x02) || (deviceDescriptor[0x0D] != 0x01))
{
CloseHandle(*hDevice);
continue;
}
////////读取硬件信息完
////////////////////////////////////////////////////////////////////////////
findFlag = TRUE;
break;
}
}
SetupDiDestroyDeviceInfoList(hDevInfo); //释放由SetupDiGetClassDevs()产生的资源
if(findFlag == FALSE)
{
return FALSE;
}
else
{
if(calc_OpenDevice(*hDevice))
return TRUE;
else
return FALSE;
} //打开设备就返回true,反之,返回false
#ifdef Debug_mode
MessageBox(_T("function finished "),NULL, NULL);
#endif
return TRUE;
}
还是是不是有可能guid不对?但是也不可能那~
我用的guid:
GUID guidHID1= {0x4D1E55B2, 0xF16F, 0x11CF, {0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30}};
[解决办法]
没时间看~太长了~给你我的代码吧~
BOOL OpenDevice(CString byDevPathName)
{
hWriteHandle=INVALID_HANDLE_VALUE;
m_DevPathName = byDevPathName;
MyDevFound=TRUE;
//那么就是我们要找的设备,分别使用读写方式打开之,并保存其句柄
//并且选择为异步访问方式。
//读方式打开设备
hReadHandle=CreateFile(byDevPathName,
GENERIC_READ,
FILE_SHARE_READ
[解决办法]
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL
[解决办法]
FILE_FLAG_OVERLAPPED,
NULL);
if(hReadHandle==INVALID_HANDLE_VALUE)
return FALSE;
hWriteHandle=CreateFile(m_DevPathName,
GENERIC_WRITE,
FILE_SHARE_READ
[解决办法]
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL
[解决办法]
FILE_FLAG_OVERLAPPED,
NULL);
if(hWriteHandle==INVALID_HANDLE_VALUE)
return FALSE;
DataInSending=FALSE; //可以发送数据
//手动触发事件,让读报告线程恢复运行。因为在这之前并没有调用
//读数据的函数,也就不会引起事件的产生,所以需要先手动触发一
//次事件,让读报告线程恢复运行。
SetEvent(ReadOverlapped.hEvent);
//显示设备的状态。
return TRUE;
}
SearchDevice(CString &byDevPathName)
{
GUID HidGuid;
HDEVINFO hDevInfoSet;
DWORD MemberIndex;
SP_DEVICE_INTERFACE_DATA DevInterfaceData;
BOOL Result;
DWORD RequiredSize;
PSP_DEVICE_INTERFACE_DETAIL_DATApDevDetailData;
HANDLE hDevHandle;
HIDD_ATTRIBUTES DevAttributes;
HIDP_CAPS Caps;
//初始化读、写句柄为无效句柄。
DevInterfaceData.cbSize=sizeof(DevInterfaceData);
DevAttributes.Size=sizeof(DevAttributes);
HidD_GetHidGuid(&HidGuid);
hDevInfoSet=SetupDiGetClassDevs(&HidGuid,
NULL,
NULL,
DIGCF_DEVICEINTERFACE
[解决办法]
DIGCF_PRESENT);
MemberIndex=0;
while(1)
{
Result=SetupDiEnumDeviceInterfaces(hDevInfoSet,
NULL,
&HidGuid,
MemberIndex,
&DevInterfaceData);
if(Result==FALSE)
break;
MemberIndex++;
Result=SetupDiGetDeviceInterfaceDetail(hDevInfoSet,
&DevInterfaceData,
NULL,
NULL,
&RequiredSize,
NULL);
pDevDetailData=(PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(RequiredSize);
if(pDevDetailData==NULL) //如果内存不足,则直接返回。
{
SetupDiDestroyDeviceInfoList(hDevInfoSet);
return FALSE;
}
//并设置pDevDetailData的cbSize为结构体的大小(注意只是结构体大小,
//不包括后面缓冲区)。
pDevDetailData->cbSize=sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
//然后再次调用SetupDiGetDeviceInterfaceDetail函数来获取设备的
//详细信息。这次调用设置使用的缓冲区以及缓冲区大小。
Result=SetupDiGetDeviceInterfaceDetail(hDevInfoSet,
&DevInterfaceData,
pDevDetailData,
RequiredSize,
NULL,
NULL);
//将设备路径复制出来,然后销毁刚刚申请的内存。
byDevPathName=pDevDetailData->DevicePath;
free(pDevDetailData);
//如果调用失败,则查找下一个设备。
if(Result==FALSE)
continue;
//如果调用成功,则使用不带读写访问的CreateFile函数
//来获取设备的属性,包括VID、PID、版本号等。
//对于一些独占设备(例如USB键盘),使用读访问方式是无法打开的,
//而使用不带读写访问的格式才可以打开这些设备,从而获取设备的属性。
hDevHandle=CreateFile(byDevPathName,
NULL,
FILE_SHARE_READ
[解决办法]
FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//如果打开成功,则获取设备属性。
if(hDevHandle!=INVALID_HANDLE_VALUE)
{
//获取设备的属性并保存在DevAttributes结构体中
Result=HidD_GetAttributes(hDevHandle,&DevAttributes);
PHIDP_PREPARSED_DATA PreparsedData;
HidD_GetPreparsedData(hDevHandle,&PreparsedData);
HidP_GetCaps (PreparsedData,&Caps);
//关闭刚刚打开的设备
CloseHandle(hDevHandle);
//获取失败,查找下一个
if(Result==FALSE)
continue;
if(DevAttributes.VersionNumber == 0x0200
&& Caps.UsagePage == 0xFFB1
&& Caps.Usage == 1
&& Caps.InputReportByteLength == 8
&& Caps.OutputReportByteLength == 8)
{
Result=TRUE; //设置设备已经找到
break;
}
}
else
continue;
}
SetupDiDestroyDeviceInfoList(hDevInfoSet);
return Result;
}