读写USB设备出错,WriteFile、ReadFile失败,高手请帮忙!急!

xingkong1985 2009-07-09 02:00:47
最近在做USB设备的通信程序,芯片厂家已提供驱动,在通信程序中,我已经成功枚举出连接在PC机上所有USB设备,并且可以正确获得设备句柄,CreateFile是成功的(独占设备除外)。但是在对句柄进行ReadFile和WriteFile读写操作时,总是不成功,用GetLastError检查,返回值是87,参数错误,无论我怎么修改,参照MSDN,都不成功,希望高手能帮忙。感激不尽啊!
...全文
2169 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
luckyboy1979 2010-08-20
  • 打赏
  • 举报
回复
//编译环境: Borland C++ Builder 6.0, Windows Server 2003 DDK
//运行环境: Win98/2000/XP/2003
//下面是访问 USB 口必备的函数:
#include <vcl.h>
#include <dir.h>
#include <setupapi.h>
#include "C:/WINDDK/3790/inc/ddk/w2k/usbdi.h"
#include "C:/WINDDK/3790/inc/ddk/w2k/devioctl.h"
#include <initguid.h>
//---------------------------------------------------------------------------
// 下面必须为驱动程序的 GUID 值, 这里我乱写的数
DEFINE_GUID(USB_DRIVER_GUID, 0x12345678,0xabcd,0x1122,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0x00);
//---------------------------------------------------------------------------
HANDLE OpenOneDevice(HDEVINFO hDvcInfo, PSP_INTERFACE_DEVICE_DATA DvcInfoData, char *sDevNameBuf)
{
HANDLE hOut = INVALID_HANDLE_VALUE;
ULONG iReqLen = 0;
SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, NULL, 0, &iReqLen, NULL);
ULONG iDevDataLen = iReqLen; //sizeof(SP_FNCLASS_DEVICE_DATA) + 512;
PSP_INTERFACE_DEVICE_DETAIL_DATA pDevData = (PSP_INTERFACE_DEVICE_DETAIL_DATA)malloc(iDevDataLen);
pDevData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
if(SetupDiGetInterfaceDeviceDetail(hDvcInfo, DvcInfoData, pDevData, iDevDataLen, &iReqLen, NULL))
{
strcpy(sDevNameBuf, pDevData->DevicePath);
hOut = CreateFile(pDevData->DevicePath, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
}
free(pDevData);
return hOut;
}
//---------------------------------------------------------------------------
HANDLE OpenUsbDevice(const GUID *pGuid, char *sDevNameBuf)
{
HANDLE hOut = INVALID_HANDLE_VALUE;
HDEVINFO hDevInfo = SetupDiGetClassDevs(pGuid, NULL, NULL, DIGCF_PRESENT|DIGCF_INTERFACEDEVICE);
SP_INTERFACE_DEVICE_DATA deviceInfoData;
deviceInfoData.cbSize = sizeof (SP_INTERFACE_DEVICE_DATA);
ULONG nGuessCount = MAXLONG;
for(ULONG iDevIndex=0; iDevIndex<nGuessCount; iDevIndex++)
{
if(SetupDiEnumDeviceInterfaces(hDevInfo, 0, pGuid, iDevIndex, &deviceInfoData))
{
if((hOut=OpenOneDevice(hDevInfo, &deviceInfoData, sDevNameBuf)) != INVALID_HANDLE_VALUE)
break;
}
else if(GetLastError() == ERROR_NO_MORE_ITEMS) //No more items
{
break;
}
}
SetupDiDestroyDeviceInfoList(hDevInfo);
return hOut;
}
//---------------------------------------------------------------------------
bool GetUsbDeviceFileName(const GUID *pGuid, char *sDevNameBuf)
{
HANDLE hDev = OpenUsbDevice(pGuid, sDevNameBuf);
if(hDev != INVALID_HANDLE_VALUE)
{
CloseHandle(hDev);
return true;
}
return false;
}
//---------------------------------------------------------------------------
HANDLE OpenMyDevice()
{
char DeviceName[MAXPATH] = "";
return OpenUsbDevice(&USB_DRIVER_GUID, DeviceName);
}
//---------------------------------------------------------------------------
HANDLE OpenMyDevPipe(const char *PipeName)
{
char DeviceName[MAXPATH] = "";
if(GetUsbDeviceFileName(&USB_DRIVER_GUID, DeviceName))
{
strcat(DeviceName,"\\");
strcat(DeviceName,PipeName);
return CreateFile(DeviceName, GENERIC_WRITE|GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
}
return INVALID_HANDLE_VALUE;
}
//---------------------------------------------------------------------------

有了上面的函数就可以访问 USB 口了:
//打开 USB 口读写, 由驱动程序的 Pipe 名确定
HANDLE hPipe = OpenMyDevPipe("MyPipe1"); //驱动程序里面的 Pipe 名, 对应访问某个端点的 I/O, 这里我乱写的, 需要与驱动一致
if(hPipe != INVALID_HANDLE_VALUE) //打开 Pipe 成功
{
ReadFile(hPipe, Buffer, BufSize, &nBytesRead, NULL); //从 hPipe 里读取数据到 Buffer 里
//WriteFile(hPipe, Buffer, BytesToWrite, &nBytesWritten, NULL); //把 Buffer 里面的 BytesToWrite 字节写入 hPipe
CloseHandle(hPipe);
}
//使用 DeviceIoControl 访问 USB 设备
HANDLE hDevice = OpenMyDevice();
if(hDevice != INVALID_HANDLE_VALUE) //打开设备成功
{
//这些 DeviceIoControl 功能都是由设备定义的, 具体看设备和驱动的资料
if(DeviceIoControl(hDevice, IOCTL_READ_xxxx, &IOBlock, sizeof(IOBLOCK), &c, 1, &nBytes, NULL))
{
//成功
}
CloseHandle(hDevice);
}

这也是我看到的,不知道是否有帮助
snowwood 2010-07-30
  • 打赏
  • 举报
回复
我也遇到了同样的问题,有谁知道请回复一下呗
yylooker2008 2010-06-13
  • 打赏
  • 举报
回复
mark;
krpol2005 2009-11-16
  • 打赏
  • 举报
回复
lz问题解决了没有?
我也出现了和你一样的问题
西山小月 2009-07-10
  • 打赏
  • 举报
回复
用DeviceIoControl
xingkong1985 2009-07-10
  • 打赏
  • 举报
回复
那么用DeviceIoControl应该怎么做呢?是直接用它读取和写入数据,还是用它打开pipe后再读写?
marrco2005 2009-07-09
  • 打赏
  • 举报
回复
mark
xingkong1985 2009-07-09
  • 打赏
  • 举报
回复
我发送数据想改用DeviceIoControl,也不行,总是说请求无效!
char ReceiveNum[512];
DWORD ReceiveNumSize=sizeof(ReceiveNum);
ULONG bytesreturned;

HANDLE handle;
handle=hCom[1];
bret=DeviceIoControl(handle,
IOCTL_SEND_BUFFERED_PACKETS,
ReceiveNum,
ReceiveNumSize,
NULL,
0,
&bytesreturned,
NULL);

CString test;
int error;
error=GetLastError();
test.Format("%d",error);
if (bret)
{
MessageBox("写入成功!");
}
else
{
MessageBox("写入失败!");
MessageBox(test);
}


请各位高手帮帮忙。
xingkong1985 2009-07-09
  • 打赏
  • 举报
回复
#define IOCTL_SEND_BUFFERED_PACKETS CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD,0x839, METHOD_BUFFERED,FILE_READ_DATA)
GUID Deviceguid = {0xa5dcbf10, 0x6530, 0x11d2, 0x90, 0x1f, 0x00, 0xc0, 0x4f, 0xb9, 0x51, 0xed};
HANDLE hCom[11];
BOOL bret=FALSE;
CString ShowMessage;
ShowMessage.Empty();
ShowMessage = _T("开始查找USB设备......\r\nUSB类的GUID标识为:\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);
ShowMessage+= _T("a5dcbf10-6530-11d2-901f-00c04fb951ed\r\n\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

LPGUID pInterfaceGuid = &Deviceguid;

HDEVINFO hDeviceInfo = SetupDiGetClassDevs(pInterfaceGuid,
NULL,
NULL,
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);

if (hDeviceInfo==INVALID_HANDLE_VALUE)
{
MessageBox("设备信息不可用!");
}
/* CString test;
test.Format("%d",hDeviceInfo);
MessageBox(test);*/

ShowMessage += _T("正在查找可用的USB设备...\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

SP_DEVICE_INTERFACE_DATA spDevInterData;
memset(&spDevInterData, 0x00, sizeof(SP_DEVICE_INTERFACE_DATA));
spDevInterData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);

DWORD nIndex = 0;

ShowMessage += _T("查找USB设备接口...\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

while(TRUE)
{
bret=SetupDiEnumDeviceInterfaces( hDeviceInfo,
NULL,
pInterfaceGuid,
nIndex,
&spDevInterData);

if ((!bret)&&(GetLastError()==ERROR_NO_MORE_ITEMS))
{
if (nIndex==0)
{
AfxMessageBox(_T("未找到可用的设备!"));
return;
}

else
{
ShowMessage += _T("\r\n目前没有更多可用的设备!");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);
SetupDiDestroyDeviceInfoList(hDeviceInfo);
return;
}

}

ShowMessage += _T("\r\n找到一个USB设备!\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

ShowMessage += _T("读取设备路径名......\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

DWORD Length=0;

bret = SetupDiGetDeviceInterfaceDetail(
hDeviceInfo,
&spDevInterData,
NULL,
0,
&Length,
NULL);

if (!bret)
{
if (ERROR_INSUFFICIENT_BUFFER != GetLastError())
{
ShowMessage += _T("计算所需长度......\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);
}
}

PSP_DEVICE_INTERFACE_DETAIL_DATA pstDetailData;

pstDetailData = NULL;
pstDetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, Length);

if(NULL == pstDetailData)
{
MessageBox("HeapAlloc Memory Failed");

if (!SetupDiDestroyDeviceInfoList(hDeviceInfo))
{
MessageBox("SetupDiDestroyDeviceInfoList Error!");
}

return;
}

pstDetailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

//SP_DEVINFO_DATA infodata;
//infodata.cbSize=sizeof(SP_DEVINFO_DATA);

bret = SetupDiGetDeviceInterfaceDetail(
hDeviceInfo,
&spDevInterData,
pstDetailData,
Length,
&Length,
NULL);

if (!bret)
{
MessageBox("查找路径时出错!");
return;
}

vDevicePath=pstDetailData->DevicePath;

CString strshow;
strshow.Empty();
strshow.Format("可以通过路径:\r\n%s\r\n访问设备\r\n",vDevicePath);
ShowMessage += strshow;
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

ShowMessage += _T("打开设备接口......\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

hCom[nIndex] = CreateFile(pstDetailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);

Comnumber.Empty();

if (hCom[nIndex]==INVALID_HANDLE_VALUE)
{
MessageBox("打开通信端口失败!");
ShowMessage += _T("句柄号———hCom[");
Comnumber.Format("%d",nIndex);
ShowMessage = ShowMessage+Comnumber+_T("]\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);
goto next;
}
else
{
MessageBox("打开通信端口成功!");
ShowMessage +=_T("句柄号———hCom[");
Comnumber.Format("%d",nIndex);
ShowMessage = ShowMessage+Comnumber+_T("]\r\n");
SetDlgItemText(IDC_EDIT_SHOW,ShowMessage);

CString test;
test.Format("%d",hCom[nIndex]);
MessageBox(test);
goto read;
}

read:
{
DWORD BufferSize=512;
DWORD NumberRead=0;
char* Buffer;
Buffer= new char[512];
while (bret=ReadFile(hCom[nIndex],Buffer,BufferSize,&NumberRead,NULL))
{
if (bret)
{
MessageBox("读取成功!");
}
else
{
MessageBox("读取失败!");//总是失败,用GetLastError来看,返回87.
}
}

}
next:
if (NULL != pstDetailData)
{
HeapFree(GetProcessHeap(), 0, pstDetailData);
pstDetailData = NULL;
}
nIndex++;
}
kondykuang 2009-07-09
  • 打赏
  • 举报
回复
在网上找找 相关的程序 看看别人是这么写的·
wangk 2009-07-09
  • 打赏
  • 举报
回复
厂家没有提供通讯规范吗?
要发多大Buffer,哪些位要特殊标记,等等……
还是要厂家要求support吧。
一条晚起的虫 2009-07-09
  • 打赏
  • 举报
回复
//请贴出代码

2,643

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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