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. 6.4 操作契约 Operation Contracts

    4.操作契约 Operation Contracts  “用例描述”的补充  强调: 用例中重要的动作,其开始与结束是需要一些约束 4.5 操作契约的后置条件  定义Definition  后 ...

  2. Beautiful Paintings CodeForces - 651B (贪心)

    大意: 给定序列$a$, 可以任意排序, 求最大下标i的个数, 满足$a_i<a_{i+1}$. 这个贪心挺好的, 答案就为n-所有数字出现次数最大值.

  3. oracle数据库中字符乱码

    1.1         88.152 os已安装中文包,以下确认os层面中文是否可以显示 1.2         88.153 os没有安装中文包,以下确认os层面中文无法显示 1.3         ...

  4. Oracle 常用sql整理

    1. 查看当前正在只用的undo段 select s.sid, s.serial#, s.username, r.name, t.STATUS, t.START_TIME, t.USED_UBLK, ...

  5. tf.expand_dims 来增加维度

    主要是因为tflearn官方的例子总是有embeding层,去掉的话要conv1d正常工作,需要加上expand_dims network = input_data(shape=[None, 100] ...

  6. Python获取时间戳

    import datetime as dt dt.datetime.now().microsecond

  7. 把旧系统迁移到.Net Core 2.0 日记 (18) --JWT 认证(Json Web Token)

    我们最常用的认证系统是Cookie认证,通常用一般需要人工登录的系统,用户访问授权范围的url时,会自动Redirect到Account/Login,登录后把认证结果存在cookie里. 系统只要找到 ...

  8. js如何比较两个日期之间相差数(天、时、分、秒)

    首先,我们模拟一个例子 引入js文件 <script type="text/javascript" src="jquery.min.js">< ...

  9. CSS3 的box-shadow进阶之 - 动画篇 - 制作辐射动画

    本篇文章是上一篇讲box-shadow基础知识的延伸,建议先花几分钟阅读那篇文章,点击阅读,再来看这篇. 除了box-shadow属性知识外,制作动画,还需要对CSS3的animation, @key ...

  10. js MDN 查看