C# USB通信

无常名 2011-01-22 10:52:53
我现在有一个USB接口的硬件设备,已经安装驱动。谁能提供一个利用系统API与USB接口通讯的简单的例子?非常感谢~!
...全文
3442 28 打赏 收藏 转发到动态 举报
写回复
用AI写文章
28 条回复
切换为时间正序
请发表友善的回复…
发表回复
落奇 2012-01-11
  • 打赏
  • 举报
回复
我怎么看不到最佳回复啊
铜臂阿铁木 2012-01-04
  • 打赏
  • 举报
回复
……我是来看楼主ID的
无常名 2011-01-25
  • 打赏
  • 举报
回复
感谢大家 的帮助。特别是骏马。。。
无常名 2011-01-24
  • 打赏
  • 举报
回复
没有更高一点的手啊?
无常名 2011-01-24
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 doubleu2005 的回复:]
如果知道usb设备读写的endpoint和pipe就可使用CreateFile,WriteFile,ReadFile来操作usb设备了
[/Quote]
能具体讲一下吗?实在是不知道从哪入手啊~!
mjp1234airen4385 2011-01-24
  • 打赏
  • 举报
回复
mjp1234airen4385 2011-01-24
  • 打赏
  • 举报
回复
网上都有现成的二代证阅读器的标准代码?
另外,二代证阅读器的两个阅读数据的函数是国家公安部提供的标准函数,不是厂家的函数。
一般情况下,就是厂家也是调用这两个动态库里的函数的。
一个dll是从设备读取数据的,另一个dll是解密图片的。
如果你不使用这些动态库,即使你读取出信息,也不能解析图片,图片的解析是国家的加密算法,
如果你私自破解,理论上是违法的。
doubleu2005 2011-01-23
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 zongbao516 的回复:]

引用 13 楼 lovesongforever 的回复:
引用 11 楼 zongbao516 的回复:
我的设备是一台身份证阅读器。谢谢


你用的是那个厂家的设备。

你和USB通信的目的是什么?

厂家给的API应该完全让你使用设备了。

呃,通信当然是读设备返回的数据了。那我全部的希望都寄托在厂家那里?
[/Quote]
应该是的,还有一个方法在我上面发的例子里也有了就是“使用 DeviceIoControl 访问 USB 设备”,可是你必须知道"IOCTL_READ_xxxx"-控制码,这个也是在驱动里面定义的,因此你不知道底层的接口是开发不了的。
无常名 2011-01-22
  • 打赏
  • 举报
回复
自己顶一下~!
无常名 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 lovesongforever 的回复:]
引用 11 楼 zongbao516 的回复:
我的设备是一台身份证阅读器。谢谢


你用的是那个厂家的设备。

你和USB通信的目的是什么?

厂家给的API应该完全让你使用设备了。
[/Quote]
呃,通信当然是读设备返回的数据了。那我全部的希望都寄托在厂家那里?
garfieldzf 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 zongbao516 的回复:]
我的设备是一台身份证阅读器。谢谢
[/Quote]

你用的是那个厂家的设备。

你和USB通信的目的是什么?

厂家给的API应该完全让你使用设备了。
doubleu2005 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 zongbao516 的回复:]

8楼那个方法是C语言是吧?实在有点看不懂。
[/Quote]
是C++的,那个可以慢慢研究,关键是概念,看了就知道endpoint和pipe的意义和作用了,再结合实际。其实没什么看不懂的,API都是一样的。无非就是找到句柄,这句柄里要包含读写的pipe号,这样就可以像操作文件一样操作usb设备了,但pipe是硬件底层的东西,如果驱动的提供方不给说明的话,不好搞的。
无常名 2011-01-22
  • 打赏
  • 举报
回复
我的设备是一台身份证阅读器。谢谢
无常名 2011-01-22
  • 打赏
  • 举报
回复
8楼那个方法是C语言是吧?实在有点看不懂。
足球中国 2011-01-22
  • 打赏
  • 举报
回复
看一下。你的usb驱动。
如果你的usb设备不支持一问一答的形式。那只能是文件式的读写了。
doubleu2005 2011-01-22
  • 打赏
  • 举报
回复
这个是最接近实用的例子,我就是研究的这个,最后因为没有供应商给出的usb的pipe而终止了,但方法绝对是对的!
#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);


USB 设备、USB 驱动、USB 应用程序

1.USB 设备硬件部分
a.这个硬件的标识是用的 Vender ID 和 Product ID, 即“厂家标识”和“产品标识”
b.这个硬件规定了各个 End Point (端点) 的性质, 读/写 及 类型 (Control/Interrupt/Bulk/Isochronous)
c.这个硬件的固件里面有 DeviceIoControl 的实现部分, 规定了这个函数的具体参数和动作
2.USB 设备驱动
①硬件接口
a.需要识别 Vender ID 和 Product ID
b.对每个 EndPoint 的每个 I/O 分配一个 Pipe, 并且起一个名字作为软件接口
c.做 DeviceIoControl 的接口
②软件接口
a.GUID, 驱动程序的标识, 每个驱动程序使用不同的 GUID, GUID 是识别驱动的, 与硬件无关 (驱动程序升级版本 GUID 不能修改)
b.硬件接口里面的 b: Pipe 名字是软件接口, 这个 Pipe 名字纯粹由驱动定义的, 和硬件无关, 升级驱动不能改 Pipe 的名字
c.硬件接口里面的 c 的各个参数也是软件的接口, 这些参数是由硬件带来的, 不是驱动规定的, 当然也可以在驱动里面转义, 隐藏设备的真实情况
③这个驱动程序是用 WinDDK 编译的, 可以用文本编辑器或其他开发工具的编辑器编程序代码, 然后调用 WinDDK 编译

3.读写 USB 口的程序
①与驱动的接口
a.利用驱动程序里面的 GUID 找出设备的文件名, 用 CreateFile 函数打开设备。我前面的程序里面的 OpenUsbDevice 就是这个作用
b.通过 a.得到的设备文件名和驱动程序里面的 Pipe 名打开 Pipe, 访问这个 Pipe 对应的 USB 端点 (读写数据)
c.使用 a.的 CreateFile 得到的句柄, 通过 DeviceIoControl 实现设备规定的动作
②有关需要的资料
a.Vender ID, Product ID 和 GUID 一般在驱动程序的 .inf 文件里面能看到, 如果找不到就需要和厂家联系
b.Pipe 的名字是驱动程序规定的, 需要有驱动程序的资料才能知道
c.DeviceIoControl 的参数需要有驱动程序的资料或者硬件资料才能知道
③这个程序一般用 C/C++ 直接编写, 如果使用其他语言(VB/PB等)需要调用 C/C++ 编的 DLL


其他相关内容:

USB 驱动程序可以到注册表里面找到:
"HKEY_LOCAL_MACHINE\\SYSTEM\\ControlSet001\\Enum\\USB\\Vid_厂家标识&Pid_产品标识\\驱动程序"

里面的 ClassGUID 就是驱动程序的 GUID 标识, 例如 {36FC9E60-C465-11CF-8056-444553540000}
相当于程序的: DEFINE_GUID(USB_DRIVER_GUID, 0x36FC9E60,0xC465,0x11CF,0x80,0x56,0x44,0x45,0x53,0x54,0x00,0x00);
另外在这个注册表键里面还可找到有关设备的其他描述, 例如 DeviceDesc = "USB Mass Storage Device" 等
无常名 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 doubleu2005 的回复:]
如果知道usb设备读写的endpoint和pipe就可使用CreateFile,WriteFile,ReadFile来操作usb设备了
[/Quote]
这两个是什么啊
无常名 2011-01-22
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wuyq11 的回复:]
http://topic.csdn.net/u/20090705/22/88b44fc7-cd12-49f8-aab9-34ce1bb93eb7.html
[/Quote]
这个看过啊~!
doubleu2005 2011-01-22
  • 打赏
  • 举报
回复
如果知道usb设备读写的endpoint和pipe就可使用CreateFile,WriteFile,ReadFile来操作usb设备了
邋遢的土豆 2011-01-22
  • 打赏
  • 举报
回复
http://blog.csdn.net/Dream_Realise/archive/2009/07/23/4375145.aspx

这个
加载更多回复(2)

110,567

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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