libusb win32简介以及应用
1.libusb win32 作用以及安装步骤。
LibUSB-Win32是一个用于Windows操作系统(Win98SE、WinME、Win2k和WinXP、Vista、Win7等)上的通用USB设备驱动程序。该驱动程序允许使用者在不写任何一行核心驱动程序代码的情况下,可以访问Windows系统上的任意一个USB设备,具有以下特点:
能够与任意一个已安装的USB设备进行通信
可被用作自己开发的USB设备的驱动程序
支持批量和中断传输
支持USB规范中定义的所有标准设备请求
支持USB设备制造商的自定义请求
libusb-win32-bin-1.2.6.0驱动安装方法
本驱动是Windows系统下(包含主流的Windows XP, Windows7)下的驱动,官方网址为,http://sourceforge.net/apps/trac/libusb-win32/wiki,里面也可以找到libusb-win32的overview.
2.libusb win32编译环境以及在Windows操作系统使用libusb
编译工具:
VS2010:用来编译libusb-win32的动态链接库、相关工具和DEMO程序的。
WINDDK:来编译usb驱动,即生成libusb0.sys文件。
源码下载:http://sourceforge.net/projects/libusb-win32/files/
inf-wizard——设备驱动安装信息文件生成向导。此向导可以扫描计算机上的USB设备,并可以获取你选择的设备的VID及PID生成inf文件。
install-filter——filter驱动安装。filterdriver 是驱动的高层境界,杀毒软件,防火墙,笔记本的多功能按键等等都会用到。
libusb-dll——动态链接库,生成libusb0.dll。接下来会说的libusb core函数就封装在这里面。同时生成了libusb0.lib文件,供程序链接,实现libusb0.dll的装载。
libusb-sys——USB驱动,生成驱动文件libusb0.sys。注意它是makefile项目。
testbulk——libusb-win32的简单案列传送“hello world!”。
testlibusb——实现libusb-win32驱动的设备的遍历并打印一部分设备描述信息。
testlibusb-win——WINFORM版的testlibusb。
在编译完工程后,在libusb-sys生成目录下没有libusb0.sys文件。(libusb-sys是靠WINDDK来编译链接生成的)
所以需要查看libusb-sys的项目属性页,在[配置属性]的栏里,查看“生成命令行”,查看目录下的make.cfg文件
; DefaultWinDDKdirectory(s) Adjust these values to match your environment
; (REQUIRED)
WINDDK_BASE=Z:\WinDDK
WINDDK_DIR=!WINDDK_BASE!\7600.16385.0\
;
; (optional)
WINDDK_W2K_DIR=!WINDDK_BASE!\6001.18002\ //
修改成我们自定义WINDDK安装路径eg.
; DefaultWinDDKdirectory(s) Adjust these values to match your environment
; (REQUIRED)
WINDDK_BASE=D:\WinDDK
WINDDK_DIR=!WINDDK_BASE!\7600.16385.1\
然后再VS2010上重新编译libusb-sys.
3.API函数介绍
在libusb0.1中,函数有两种返回值,一种为usb_open函数返回打开的设备句柄handle,第二种为int型,当返回值大于等于0时表示成功,返回值小于0表示失败
报告错误代码在WDK crt_errno.h文件中标准的错误代码和一些MinGW的说明如下:
#define EPERM 1 /* Operation not permitted */
#define ENOENT 2 /* No entry, ENOFILE, no such file ordirectory */
#define ESRCH 3 /* No such process */
#define EINTR 4 /* Interrupted function call */
#define EIO 5 /* Input/output error */
#define ENXIO 6 /* No such device or address */
#define E2BIG 7 /* Arg list too long */
#define ENOEXEC 8 /* Exec format error */
#define EBADF 9 /* Bad file descriptor */
#define ECHILD 10 /* No child processes */
#define EAGAIN 11 /* Resource temporarily unavailable */
#define ENOMEM 12 /* Not enough space */
#define EACCES 13 /* Permission denied */
#define EFAULT 14 /* Bad address */
#define EBUSY 16 /* strerror reports "Resourcedevice" */
#define EEXIST 17 /* File exists */
#define EXDEV 18 /* Improper link (cross-device link?) */
#define ENODEV 19 /* No such device */
#define ENOTDIR 20 /* Not a directory */
#define EISDIR 21 /* Is a directory */
#define EINVAL 22 /* Invalid argument */
#define ENFILE 23 /* Too many open files in system */
#define EMFILE 24 /* Too many open files */
#define ENOTTY 25 /* Inappropriate I/O control operation*/
#define EFBIG 27 /* File too large */
#define ENOSPC 28 /* No space left on device */
#define ESPIPE 29 /* Invalid seek (seek on a pipe?) */
#define EROFS 30 /* Read-only file system */
#define EMLINK 31 /* Too many links */
#define EPIPE 32 /* Broken pipe */
#define EDOM 33 /* Domain error (math functions) */
#define ERANGE 34 /* Result too large (possibly toosmall) */
#define EDEADLK 36 /* Resource deadlock avoided */
#define ENAMETOOLONG 38 /* Filename too long */
#define ENOLCK 39 /* No locks available */
#define ENOSYS 40 /* Function not implemented */
#define ENOTEMPTY 41 /* Directory not empty */
III.Functions
1.Core
void usb_init(void);
初始化libusb,usb_init设置了一些内部结构体。usb_init必须在libusb的其他功能函数之前被调用。
int usb_find_busses(void);
寻找系统中的所有的usb总线,返回自上次调用此函数以来发生的更改次数(已删除新总线和总线的总数)。
int usb_find_devices(void);
该函数会扫描在每条usb总线上的所有设备,并且必须在usb_find_busses()函数后调用,返回自上次调用此函数依赖法伤的变化次数(所有的新设备和被移除的设备)。
struct usb_bus *usb_get_busses(void);
这是为那些支持C调用约定的语言实现的,并且可以使用共享库,但是不要支持C全局变量, 返回全局变量usb_busses的值。
void usb_set_debug(int level);
该函数设置调试信息的信息级别,设置为4就可以得到信息的调试信息。
0 LOG_OFF, 1 LOG_ERROR, 2 LOG_WARNING, 3 LOG_INFO, 4LOG_DEBUG
2. Device operations:
该组函数主要是与设备相关的操作,如打开、关闭设备等一些usb标准的操作:设置配置、 alternate settings、clearing halts和重启设备等。同时也会提供操作系统级的操作,如声明和释放接口。
usb_dev_handle *usb_open(struct *usb_device dev);
打开一个usb设备,打开设备成功会返回一个句柄,以后的程序就可以通过该句柄来进行设备的通信。
int usb_close(usb_dev_handle *dev);
关闭usb设备
返回0:关闭设备成功
小于0:关闭设备失败
int usb_set_configuration(usb_dev_handle *dev, intconfiguration);
根据配置描述符bConfigurationValue来配置使能usb设备。
返回0:设置成功
小于0:设置失败
int usb_set_altinterface(usb_dev_handle *dev, intalternate);
设置当前接口的一个可选择的setting
int usb_resetep(usb_dev_handle *dev, unsigned int ep);
重置指定地址bEndpointAddress端点所有的状态
int usb_clear_halt(usb_dev_handle *dev, unsigned intep);
清除指定地址halt状态端点。
int usb_reset(usb_dev_handle *dev);
通过想下行端口发送一个RESET来重启连接该PORT的特定的设备 (会造成重新枚举的动作)
返回0:reset成功
小于0:reset失败
调用usb_reset设备重启后,设备会重新进行枚举成一个新设备并打开一个新句柄。
int usb_claim_interface(usb_dev_handle *dev, intinterface);
声明一个有操作系统相关的接口,接口的参数在描述符里的bInterfaceNumber字段里指定。
注意:在进行与该接口相关的操作之前,usb_claim_interface必须被首先调用(like usb_set_altinterface,usb_bulk_write, etc).。
返回值:
EBUSY :接口是不可用的
ENOMEM:没有足够的内存可用
int usb_release_interface(usb_dev_handle *dev, intinterface);
释放先前usb_claim_interface声明的接口
3. Control Transfers
该组函数的主要功能是允许应用程序可以给默认的控制管道发送消息。
int usb_control_msg(usb_dev_handle *dev, intrequesttype, int request, int value, int index, char *bytes, int size, inttimeout);
给设备发送一个控制消息
int usb_get_string(usb_dev_handle *dev, int index, intlangid, char *buf, size_t buflen);
通过index和langid从一个usb设备中获取字符串描述符,并返回buf中的字节数。
int usb_get_string_simple(usb_dev_handle *dev, intindex, char *buf, size_t buflen);
该函数是对usb_get_string()的封装,从设备重新获取设备描述符并将其转换成C语言格式的ASCII。
usb_get_descriptor()
通过设备默认的控制管道向设备重新获取设备描述符。
usb_get_descriptor_by_endpoint()
从端点识别的控制管道去获取设备描述符。
4. Bulk Transfers
该组函数允许应用程序通过批量传输管道向设备发送信息
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);
向一个批量传输端点向设备读取数据
5. Interrupt Transfers
该组函数允许应用程序通过中断传输管道向设备发送和接受数据。
int usb_interrupt_write(usb_dev_handle *dev, int ep, char*bytes, int size, int timeout);
向一个中断端点写数据。该函数会向指定的端点发起一个中断写请求。
int usb_interrupt_read(usb_dev_handle *dev, int ep, char*bytes, int size, int timeout);
向一个中断端点写数据。该函数会向指定的端点发起一个中断读请求。
6. Asynchronous API and Isochronous Transfer
libusb-win32通过异步API支持异步传输。libusb-win32异步传输API也支持其他的传输类型:控制传输、中断传输、批量传输等。
int usb_isochronous_setup_async(usb_dev_handle *dev, void **context, unsigned char ep, int pktsize);
为端点ep分配一个异步传输请求。
int usb_bulk_setup_async(usb_dev_handle *dev, void**context, unsigned char ep);
int usb_bulk_setup_async(usb_dev_handle *dev, void **context,unsigned char ep);
int usb_submit_async(void *context, char *bytes, intsize);
int usb_reap_async(void *context, int timeout);等待请求完成,返回读写成功的字节数或者失败的返回值。
int usb_reap_async_nocancel(void *context, inttimeout);
int usb_cancel_async(void *context);取消
int usb_free_async(void **context);
4.块传输例程
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "conio.h"
#include "lusb0_usb.h"
#pragma comment(lib, "libusb.lib")
#define m_dev_VID<spanstyle="white-space:pre;"> </span>0x1483 /* Vendor ID of the m_dev */
#define m_dev_PID<spanstyle="white-space:pre;"> </span>0x5751 /* Product ID of the m_dev */
#define EP1_OUT_SIZE 63<spanstyle="white-space:pre;"> </span> //可根据设备修改大小
#define EP1_IN_SIZE 63
int main(int argc, char *argv[])
{
structusb_device * m_dev = NULL;
structusb_dev_handle *m_dev_handle;
charstr[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("Couldnot 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("Couldnot 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);
//------------------------------------------------------------
charWriteTestData[2048] = {0};
charReadTestData[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;
}