The 'linusb' is one of the most used open source library for work with usb devices. It allow to make the basic usb data transfers operation in a little bit easier way compared to standard system calls. Here a short tutorial regarding how to use asynchronous bulk transfer.
Asynchronous transfer allow to launch the transfer command and return immediately, a callback function will be called once the data will be transfer/received completely. Using such transfer mode is quite simple, let's go to see a practical example. At first we have to initialize libusb library and look for the USB device we want to communicate to. Usually device is referred using the two values called Vendor ID and Product ID. The first is a unique number "assigned" to each hardware device producer and the second is a number reporting the device type and model.
libusb_device_handle *dev_handle = NULL;
libusb_device **list;
size_t count, i; // Initialize library
libusb_init(NULL); // Get list of USB devices currently connected
count = libusb_get_device_list(NULL, &list); for(i = 0; i < count; i++)
{
struct libusb_device_descriptor desc; libusb_get_device_descriptor(list[i], &desc); // Is our device?
if(desc.idVendor == 0x1234 && desc.idProduct == 0x5678)
{
// Open USB device and get handle
libusb_open(list[i], &dev_handle);
break;
}
} libusb_free_device_list(list, 1);
Now we have the handle to the USB device we want to communicate. The steps to performs an asynchronous bulk transfer are basically two, first prepare the structure with all the data for "instruct" USB controller to make request operation and then submit the data for start the transfer. Please note that the transfer direction (IN or OUT) is determined by the USB endpoint type we want to communicate to/from. An USB device usually provide some connections called Endpoint for allow data transfer between host and device. An Endpoint is usually marked as IN and OUT where, please note, in/out direction are from host point of view. This mean an endpoint marked as IN, for example, transfer data from device to host (usually the PC where the USB device is connected). Once clarified this point we can move to see the asynchronous transfer procedure as follow:
struct libusb_transfer *xfr;
unsigned char *data;
const unsigned int size = 1024; data = malloc(size);
xfr = libusb_alloc_transfer(0); libusb_fill_bulk_transfer(xfr,
dev_handle,
0x82, // Endpoint ID
data,
size,
callbackUSBTransferComplete,
NULL,
5000
); if(libusb_submit_transfer(xfr) < 0)
{
// Error
libusb_free_transfer(xfr);
free(data);
}
Detailed explanation about each params used can be found at official documentation here. In this example we prepare for a bulk transfer from the device using endpoint 0x82. Data size to transfer are 1024 bytes and timeout is 5000 milliseconds. callbackUSBTransferComplete is the name of the function automatically called when the transfer will be completed. Please note here the function will be called also in case of errors. It's necessary to check params returned  as follow:
void callbackUSBTransferComplete(struct libusb_transfer *xfr)
{
switch(xfr->status)
{
case LIBUSB_TRANSFER_COMPLETED:
// Success here, data transfered are inside
// xfr->buffer
// and the length is
// xfr->actual_length
break;
case LIBUSB_TRANSFER_CANCELLED:
case LIBUSB_TRANSFER_NO_DEVICE:
case LIBUSB_TRANSFER_TIMED_OUT:
case LIBUSB_TRANSFER_ERROR:
case LIBUSB_TRANSFER_STALL:
case LIBUSB_TRANSFER_OVERFLOW:
// Various type of errors here
break;
}
}
Now the transfer code seem complete. However an additional step have to be made. What is not very clear here (at least it wasn't clear for me in the past) is that the "internal USB engine" who make the transfer and automatically call the callback function is not in a separate thread working in parallel but, for have it working as expected, need to be "keep alive" by continuously calling the function libusb_handle_events as follow:
while(1)
{
if(libusb_handle_events(NULL) != LIBUSB_SUCCESS) break;
}
As you can note this is an infinite loop with minimum of error check used just for example purpose. In case you need to manage additional error conditions and provide some way to exit from loop if your software require it. This small snippet is only to explain that if you don't continuously call the libusb_handle_events function your callback function will never be called also if the USB transfer was completed (and this can result in many hours lost insearch for the problem... ^_^).

转-Asynchronous bulk transfer using libusb的更多相关文章

  1. libusb 源码阅读

    libusb_init(NULL), 如果传入一个NULL, 则libusb 内部会有一个 usbi_default_context 变量在内部保存上下文. 这样以后调用 libusb 函数时可以不指 ...

  2. bulkTransfer通讯必须注意的问题:bulk buffer size(16K)

    Android USB host与HID使用bulkTransfer通讯接收和发送的数据长度不会超过16384,这个问题困扰了我很长一段时间,终于发现问题所在,不是出在我的程序设计,也不是硬件的发送/ ...

  3. C#开发usb通知之bulk传输

    usb通信分为4种传输方式,下位机通信协议用的是块传输,也就是bulk传输,C#下实现的usb通信使用的是开源的LibUsbDotNet,主要的就是需要在C#中添加LibUsbDotNet.dll引用 ...

  4. redis.conf配置详细解析

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => 1000 bytes # 1kb ...

  5. redis配置详解

    ##redis配置详解 # Redis configuration file example. # # Note that in order to read the configuration fil ...

  6. redis.conf配置详细翻译解析

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => 1000 bytes # 1kb ...

  7. Redis 配置文件

    # Redis configuration file example. # # Note that in order to read the configuration file, Redis mus ...

  8. Redis 配置文件详解

    # Redis 配置文件 # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写)## 1k => 1000 bytes# 1kb => ...

  9. Redis基本配置

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位, # 通常的格式就是 1k 5gb 4m 等酱紫: # # 1k => 1000 bytes # 1kb ...

随机推荐

  1. P5157 [USACO18DEC]The Cow Gathering

    首先考虑怎么check一个点是否能被最后一个删除. 可以这么建图,以这个点建有根树,边全部向上指,再加上剩下的有向边. 很明显,这里的一条边的定义就变成了只有删去这个点,才可以删去它指向的点. 因此, ...

  2. 5月21 汽车查询及批量删除----php方法

    ---恢复内容开始--- 这个与之前不同是在php中实现了页面的查询,引用AJAX实现批量删除及弹窗的显示 作业要求: 页面显示数据代码: <!DOCTYPE html PUBLIC " ...

  3. csu oj 1343 Long Long

    Description 现在有两个单调递增序列,第一个序列有N个整数,第二个序列有M个整数,现在你可以从第一个序列中选一个数x,然后从第二个序列中选一个数y,那么有多少种情况满足x+y<=K呢? ...

  4. Oracle DB 使用子查询来解决查询

    • 定义子查询 • 描述子查询可以解决的问题类型 • 列出子查询的类型 • 编写单行和多行子查询   • 子查询:类型.语法和准则 • 单行子查询: – 子查询中的组函数 – 带有子查询的HAVING ...

  5. PostgreSQL&PostGIS完全安装

    检查PostGIS.PostgreSQL.GEOS.GDAL.PROJ等各软件的版本依赖关系 http://trac.osgeo.org/postgis/wiki/UsersWikiPostgreSQ ...

  6. python中RabbitMQ的使用(工作队列)

    消息可以理解为任务,消息发送者可以看成任务派送者(sender),消息接收者可以看成工作者(worker). 当工作者接收到一个任务,还没完任务时分配者又发一个任务,此时需要多个工作者来共同处理这些任 ...

  7. Mysql可重复读原理

    mysql可重复读现象及原理分析 InnoDB---可重复读隔离级别的底层实现原理 概念 可重复读的实现 Repeatable Read(可重复读):一个事务在执行过程中可以看到其他事务已经提交的新插 ...

  8. virtualenv 运行python 解决依赖冲突问题 尤其是django那种蛋疼的版本问题

    Create a python virtual environment and install python dependencies. cd evalai virtualenv venv sourc ...

  9. IDA 逆向工程 反汇编使用

    IDA pro 7.0版本 from:freebuf 用到的工具有IDA pro 7.0  ,被反汇编的是百度云(BaiduNetdisk_5.6.1.2.exe). 首先,IDA pro的长相如下: ...

  10. 小程序证书申请FAQ

    1. 帮别人开发小程序, 先把你的微信号加到成员里, 并给予开发者权限,体验者权限,登录,数据分析,开发管理,开发设置 2. 需要https, 不能用windows2003,必须2008以上,用IIS ...