关键词: libusb, bulk批量传输, 上位机软件.
公司的一个项目中负责USB驱动SDK设计, 做一个USB上位机软件, 要求使用的传输方式是bulk传输. 以前从没接触过这方面的东西, 可以说完全是个外行, 到现在为止搞了将近一个月, 总算出来了那么一点成果. 在这里, 总结分享一下.
~>USB上位机程序的编写
1.下载libusb-win32的项目源码(libusb-win32-bin-1.2.6.0), 里面包含.lib库和.h头文件, 以及inf-wizard.exe和testlibusb-win.exe.
- 在PC端插上USB设备后, 运行inf-wizard.exe, 即可自动生成.inf 驱动文件, 不用自己编写驱动, 就可完成驱动的安装.
- 运行testlibusb-win.exe, 即可查看设备的信息, 包括: VID/PID,以及各种描述符, 端点地址Endpoint Address, 最大包的大小MaxPacketSize.
- 程序代码中加入 : #include "lusb0_usb.h" 以及 #pragma comment(lib, "libusb.lib") //即可调用libusb的函数
- 函数的调用过程.
1) 调用 void usb_init(void); 进行初始化
2) 调用usb_find_busses、usb_find_devices和usb_get_busses这三个函数,获得已找到的USB总线序列;然后通过链表遍历所有的USB设备,根据已知的要打开USB设备的ID(VID/PID),找到相应的USB设备.
3) 调用usb_open函数打开该USB设备
4) usb_set_configuration(m_dev_handle, 1) //设置配置
intint usb_claim_interface(usb_dev_handle *dev, int interface);
注册与操作系统通信的接口,这个函数必须被调用,因为只有注册接口,才能做相应的操作。
5)与USB设备进行通信。使用函数
int usb_bulk_write(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);//批量写入
int usb_bulk_read(usb_dev_handle *dev, int ep, char *bytes, int size, int timeout);//批量读取
从USB设备读取(接收)数据或向其写入(发送)数据。
6) int usb_release_interface(usb_dev_handle *dev, int interface);
注销被usb_claim_interface函数调用后的接口,释放资源,和usb_claim_interface对应使用。
8) int usb_close(usb_dev_handle *dev);
与usb_open相对应,关闭设备,是必须调用的, 返回0成功,<0 失败。
附上最简单的win32控制台程序的代码:(配合Bus Hound运行起来更直观).
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "conio.h"
#include "lusb0_usb.h"
#pragma comment(lib, "libusb.lib")
#define m_dev_VID 0x1483 /* Vendor ID of the m_dev */
#define m_dev_PID 0x5751 /* Product ID of the m_dev */
#define EP1_OUT_SIZE 63 //可根据设备修改大小
#define EP1_IN_SIZE 63
int main(int argc, char *argv[])
{
struct usb_device * m_dev = NULL;
struct usb_dev_handle *m_dev_handle;
char str[64];
memset(str,0,sizeof(str));
usb_init();
usb_find_busses();
usb_find_devices();
struct usb_bus *bus;
for(bus = usb_get_busses(); bus; bus = bus->next)
{
struct usb_device *dev;
for(dev = bus->devices; dev; dev = dev->next)
{
if(dev->descriptor.idVendor == m_dev_VID && dev->descriptor.idProduct == m_dev_PID)
m_dev=dev;
}
}
if(!m_dev)
{
printf("m_dev not found\n");
return 1;
}
m_dev_handle = usb_open(m_dev);
if(!m_dev_handle)
{
printf("Could not open m_dev\n");
return 1;
}
printf("设备打开成功!\n");
if(usb_set_configuration(m_dev_handle, 1) < 0)
{
printf("Could not set configuration\n");
usb_close(m_dev_handle);
return 1;
}
if(usb_claim_interface(m_dev_handle, 0) < 0) //claim_interface 0 注册与操作系统通信的接口 0
{
printf("Could not claim interface\n");
usb_close(m_dev_handle);
return 1;
}
//-----获取端点的地址-----------------------------
int ep = m_dev->config->interface->altsetting->endpoint->bEndpointAddress;
int EP_IN = 0;
int EP_OUT = 0;
if (ep > 0x0f)
{
EP_IN = ep;
EP_OUT = ep - 0x80;
}
else
{
EP_OUT = ep;
EP_IN = ep + 0x80;
}
printf("EP_IN: 0x%02x , EP_OUT: 0x%02x \n", EP_IN, EP_OUT);
//------------------------------------------------------------
char WriteTestData[2048] = {0};
char ReadTestData[2048] = {0};
for(int i = 0; i< 2048; i++)
{
WriteTestData[i] = i;
}
//端点1写入数据
int ret;
ret = usb_bulk_write(m_dev_handle, EP_OUT, WriteTestData, EP1_OUT_SIZE, 500);
if(ret != EP1_OUT_SIZE)
{
printf("端点1写入数据失败! %d\n", ret);
return 1;
}
else
{
printf("端点1写入数据成功!\n");
}
//端点1读取数据
ret = usb_bulk_read(m_dev_handle, EP_IN, ReadTestData, EP1_IN_SIZE, 500);
if(ret != EP1_IN_SIZE)
{
printf("端点1读取数据失败! %d\n", ret);
return 1;
}
else
{
printf("端点1读取数据成功!\n");
for (int i = 0; i < EP1_IN_SIZE; i++)
{
printf("%02X ", ReadTestData[i]);
if(((i + 1) % 16) == 0)
{
printf("\n");
}
}
printf("\n");
}
/**************************************************************************/
usb_release_interface(m_dev_handle, 0); //注销接口,释放资源,和usb_claim_interface搭配使用。
usb_close(m_dev_handle);
printf("\n设备关闭\n");
return 0;
}
附上:我用VC++编写的上位机测试Demo.
https://download.youkuaiyun.com/download/huihong_vitality/9797105