C 使用异步I/O的Libusb争用条件
我正在使用libusb与配置为USB设备的飞利浦ISP1362进行通信。我能够使用同步I/O成功地环回数据,没有任何问题。出于某种原因,在使用异步I/O时,似乎存在竞争条件 我正在使用背对背的输入输出传输传输64字节的数据包。有时,当我运行我的程序时,libusb抛出超时错误,一些环回数据丢失。当使用我的Beagle 12分析USB总线时,我可以看到OUT-IN事务在应该(OUT-IN-OUT-IN-IN-IN)的情况下是无序的(即OUT-OUT-IN-TIMEOUT) 更新回调函数中的传输出现无序,这很奇怪,因为它们与总线分析器上的实际情况不一致 示例1:(输入-输出-输入-输出) 示例2:(OUT-IN-IN-OUT) 以下是分析仪的屏幕截图: 代码如下:C 使用异步I/O的Libusb争用条件,c,libusb,C,Libusb,我正在使用libusb与配置为USB设备的飞利浦ISP1362进行通信。我能够使用同步I/O成功地环回数据,没有任何问题。出于某种原因,在使用异步I/O时,似乎存在竞争条件 我正在使用背对背的输入输出传输传输64字节的数据包。有时,当我运行我的程序时,libusb抛出超时错误,一些环回数据丢失。当使用我的Beagle 12分析USB总线时,我可以看到OUT-IN事务在应该(OUT-IN-OUT-IN-IN-IN)的情况下是无序的(即OUT-OUT-IN-TIMEOUT) 更新回调函数中的传输出现
#include <stdlib.h>
#include <stdio.h>
#include <libusb-1.0/libusb.h>
/* Specify VENDOR_ID and PRODUCT_ID for device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define EP_SIZE 64 // bytes
#define TRANSFERS 4 // number of transfers
#define BYTES EP_SIZE*TRANSFERS
#define TIMEOUT 3*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *devh = NULL;
/* use a global variable to keep the context */
static struct libusb_context *usb_context = NULL;
/* count variable */
int count = 0;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in = 0x82;
static int ep_out = 0x01;
void xfr_cb(struct libusb_transfer *transfer )
{
int *completed = transfer->user_data;
/* callback - This is called after the transfer has been received by libusb */
fprintf(stderr, "xfr_cb(): count %d, status = %d, endpoint = %x, actual_length = %d, completed = %d\n",
count,
transfer->status,
transfer->endpoint,
transfer->actual_length,
*completed);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
{
/* Error! */
fprintf(stderr, "Error: %s\n", libusb_error_name((int)transfer->status));
}
if (count == TRANSFERS-1)
*completed = 1;
count++;
}
int main(int argc, char **argv)
{
int ep_addr;
int completed = 0;
unsigned char *buf;
size_t length = 64;
int n;
int i;
int rc;
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!devh)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* allocate memory */
buf = malloc(length);
/* start with OUT transfer */
ep_addr = ep_out;
/* queue up alternating OUT-IN transfers */
for (i = 0; i < TRANSFERS; i++)
{
/* fill the buffer with incrementing data */
for (n = 0; n < EP_SIZE; n++)
{
buf[n] = i+n;
}
/* Set up the transfer object */
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, devh, ep_addr, buf, EP_SIZE, xfr_cb, &completed, TIMEOUT); /* callback data = &completed */
/* Submit the transfer object */
libusb_submit_transfer(transfer);
fprintf(stderr, "main(): submitting transfer %d, endpoint %x\n", i, ep_addr);
/* alternate writing and reading for loopback */
ep_addr = (ep_addr == ep_out) ? ep_in : ep_out;
}
/* Handle Events */
while (!completed)
{
rc = libusb_handle_events_completed(NULL, &completed);
if (rc < 0)
{
if (rc == LIBUSB_ERROR_INTERRUPTED)
continue;
fprintf(stderr, "Transfer Error: %s", libusb_error_name(rc));
continue;
}
}
fprintf(stderr, "completed\n");
/* Release the interface */
libusb_release_interface(devh, 0);
/* Close the device handle */
if (devh)
libusb_close(devh);
out:
if (devh)
{
libusb_close(devh);
}
libusb_exit(NULL);
return rc;
}
我真的不明白为什么循环会导致基于文档和示例的竞争条件。实际上,在一个libusb示例(sam3u_benchmark.c)中建议对多个传输进行排队,并在下面的.pdf中演示(使用循环)
请参阅异步I/O部分:
根据我的理解,使用libusb_handle_events_completed(NULL,&completed)应该可以解决同步问题。我是不是误解了什么?
请参阅来自多个线程的libusb_handle_events()
-“这就是为什么libusb-1.0.9引入了新的libusb_handle_events_timeout_completed()和libusb_handle_events_completed()函数,它们在获得锁后为您执行完成检查:”
如果是这样的话,他们需要的是如何使用API的清晰示例
我可以添加更多的事件检查,但这里似乎不太对劲
更新3:见接受答案。更新:见接受答案 下面是一个使用同步I/O的示例。我在使用异步I/O使事务按预期顺序进行时遇到了很多麻烦。我认为这是由于@Gene提到的传输相互竞争造成的 我对libusbapi的主要抱怨是缺少示例来说明正确的使用。API会让人相信异步事务是按照它们“提交”的顺序放置在总线上的,从我收集的信息来看,这是不正确的。此功能适用于提交具有所有相同数据包令牌(即OUT或IN)的事务 以下代码适用于大批量传输 使用同步I/O
#include <stdlib.h>
#include <stdio.h>
#include <libusb-1.0/libusb.h>
/* Change VENDOR_ID and PRODUCT_ID depending on device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define BYTES 1024*768*3 // bytes
#define EP_SIZE 64 // bytes
#define TIMEOUT 5*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *devh = NULL;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in_addr = 0x82;
static int ep_out_addr = 0x01;
int write_chars(unsigned char * data, int length)
{
/* To send a char to the device simply initiate a bulk_transfer to the Endpoint
* with the address ep_out_addr.
*/
int actual_length;
int rc = libusb_bulk_transfer(devh, ep_out_addr, data, length, &actual_length, TIMEOUT);
if (rc < 0)
{
fprintf(stderr, "Error while sending char: %d\n", rc);
return -1;
}
return actual_length;
}
int read_chars(unsigned char * data, int length)
{
/* To receive characters from the device initiate a bulk_transfer to the Entpoint
* with address ep_in_addr
*/
int actual_length;
int rc = libusb_bulk_transfer(devh, ep_in_addr, data, length, &actual_length, TIMEOUT);
if (rc == LIBUSB_ERROR_TIMEOUT)
{
printf("timeout (%d)\n", actual_length);
return -1;
}
else if (rc < 0)
{
fprintf(stderr, "Error while waiting for char: %d\n", rc);
return -1;
}
return actual_length;
}
int main(int argc, char **argv)
{
int rc;
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!devh)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* We can now start sending or receiving data to the device */
unsigned char buf[BYTES];
unsigned char rbuf[EP_SIZE];
int len;
int n;
int l;
int res;
// fill buffer
for (n = 0; n < BYTES; n++)
{
buf[n] = 0x00+n;
}
// loopback data, write-read
for (l = 0; l < BYTES/EP_SIZE; l++)
{
len = write_chars(buf+l*EP_SIZE, EP_SIZE);
len = read_chars(rbuf, EP_SIZE);
res = memcmp(rbuf, buf+l*EP_SIZE, sizeof(rbuf));
if (res != 0)
fprintf(stderr, "Miscompare: block %d\n", l);
}
libusb_release_interface(devh, 0);
out:
if (devh)
{
libusb_close(devh);
}
libusb_exit(NULL);
return rc;
}
#包括
#包括
#包括
/*根据设备更改供应商ID和产品ID*/
#定义供应商标识0x0471
#定义产品标识0x3630
/*定义要传输的字节数*/
#定义字节1024*768*3//字节
#定义EP_大小64//字节
#定义超时5*1000//毫秒
/*使用全局变量保留设备句柄*/
静态结构libusb\u设备\u句柄*devh=NULL;
/*端点地址是硬编码的。您应该使用libusb-v来查找
*与设备相对应的值
*/
静态int ep_in_addr=0x82;
静态int ep_out_addr=0x01;
int write_chars(无符号字符*数据,int长度)
{
/*要向设备发送字符,只需启动到端点的大容量传输
*地址为ep_out_addr。
*/
int实际长度;
int rc=libusb批量传输(devh、ep out地址、数据、长度和实际长度、超时);
if(rc<0)
{
fprintf(stderr,“发送字符时出错:%d\n”,rc);
返回-1;
}
返回实际长度;
}
整数读取字符(无符号字符*数据,整数长度)
{
/*要从设备接收字符,请启动到入口点的批量传输
*地址为ep_in_addr
*/
int实际长度;
int rc=libusb批量传输(devh、ep输入地址、数据、长度和实际长度、超时);
如果(rc==LIBUSB\u错误\u超时)
{
printf(“超时(%d)\n”,实际长度);
返回-1;
}
else if(rc<0)
{
fprintf(stderr,“等待字符时出错:%d\n”,rc);
返回-1;
}
返回实际长度;
}
int main(int argc,字符**argv)
{
int rc;
/*初始化libusb*/
rc=libusb_init(NULL);
if(rc<0)
{
fprintf(stderr,“初始化libusb时出错:%s\n”,libusb_错误_名称(rc));
出口(1);
}
/*将调试输出设置为最大级别*/
libusb_设置_调试(NULL,3);
/*查找特定设备并打开它*/
devh=libusb\u open\u设备\u,带\u vid\u pid(空,供应商ID,产品ID);
如果(!devh)
{
fprintf(stderr,“错误查找USB设备\n”);
出去;
}
/*我们现在可以开始向设备发送或接收数据*/
无符号字符buf[字节];
无符号字符rbuf[EP_SIZE];
内伦;
int n;
int l;
国际关系;
//填充缓冲区
用于(n=0;n
同时使用异步和同步(即OUT异步提交,IN同步提交)
#包括
#包括
#包括
#包括
/*指定设备的供应商ID和产品ID*/
#定义供应商标识0x0471
#定义产品标识0x3630
/*定义要传输的字节数*/
#定义EP_大小64//字节
#定义传输1024*768*3/EP\U大小//传输数量
#定义字节EP_大小*传输
#定义超时15*1000//毫秒
/*使用全局变量保留设备句柄*/
静态结构libusb\u设备\u句柄*
#include <stdlib.h>
#include <stdio.h>
#include <libusb-1.0/libusb.h>
/* Specify VENDOR_ID and PRODUCT_ID for device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define EP_SIZE 64 // bytes
#define TRANSFERS 4 // number of transfers
#define BYTES EP_SIZE*TRANSFERS
#define TIMEOUT 3*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *devh = NULL;
/* use a global variable to keep the context */
static struct libusb_context *usb_context = NULL;
/* count variable */
int count = 0;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in = 0x82;
static int ep_out = 0x01;
void xfr_cb(struct libusb_transfer *transfer )
{
int *completed = transfer->user_data;
/* callback - This is called after the transfer has been received by libusb */
fprintf(stderr, "xfr_cb(): count %d, status = %d, endpoint = %x, actual_length = %d, completed = %d\n",
count,
transfer->status,
transfer->endpoint,
transfer->actual_length,
*completed);
if (transfer->status != LIBUSB_TRANSFER_COMPLETED)
{
/* Error! */
fprintf(stderr, "Error: %s\n", libusb_error_name((int)transfer->status));
}
if (count == TRANSFERS-1)
*completed = 1;
count++;
}
int main(int argc, char **argv)
{
int ep_addr;
int completed = 0;
unsigned char *buf;
size_t length = 64;
int n;
int i;
int rc;
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!devh)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* allocate memory */
buf = malloc(length);
/* start with OUT transfer */
ep_addr = ep_out;
/* queue up alternating OUT-IN transfers */
for (i = 0; i < TRANSFERS; i++)
{
/* fill the buffer with incrementing data */
for (n = 0; n < EP_SIZE; n++)
{
buf[n] = i+n;
}
/* Set up the transfer object */
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, devh, ep_addr, buf, EP_SIZE, xfr_cb, &completed, TIMEOUT); /* callback data = &completed */
/* Submit the transfer object */
libusb_submit_transfer(transfer);
fprintf(stderr, "main(): submitting transfer %d, endpoint %x\n", i, ep_addr);
/* alternate writing and reading for loopback */
ep_addr = (ep_addr == ep_out) ? ep_in : ep_out;
}
/* Handle Events */
while (!completed)
{
rc = libusb_handle_events_completed(NULL, &completed);
if (rc < 0)
{
if (rc == LIBUSB_ERROR_INTERRUPTED)
continue;
fprintf(stderr, "Transfer Error: %s", libusb_error_name(rc));
continue;
}
}
fprintf(stderr, "completed\n");
/* Release the interface */
libusb_release_interface(devh, 0);
/* Close the device handle */
if (devh)
libusb_close(devh);
out:
if (devh)
{
libusb_close(devh);
}
libusb_exit(NULL);
return rc;
}
static void LIBUSB_CALL xfr_cb(struct libusb_transfer *transfer )
{
int *completed = transfer->user_data;
unsigned char *wbuf, *rbuf;
size_t length = 64;
fprintf(stderr, "xfr_cb(): status = %d, endpoint = %x, actual_length = %d\n",
transfer->status,
transfer->endpoint,
transfer->actual_length);
*completed = 1;
}
int main(int argc, char **argv)
{
const struct libusb_version *version;
int ep_addr;
int completed = 0;
unsigned char *buf, *wbuf1, *wbuf2, *rbuf1, *rbuf2;
size_t length = 64;
int n;
int m;
int i;
int rc;
/* Get libusb version */
version = libusb_get_version();
fprintf(stderr, "libusb version: %d.%d.%d.%d\n", version->major, version->minor, version->micro, version->nano);
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!handle)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* claim interface */
rc = libusb_claim_interface(handle, 0);
if (rc < 0)
{
fprintf(stderr, "Error claiming interface.\n");
goto out;
}
/* allocate memory */
wbuf1 = malloc(length);
wbuf2 = malloc(length);
rbuf1 = malloc(length);
rbuf2 = malloc(length);
/* fill the buffer with incrementing data */
for (n = 0; n < EP_SIZE; n++)
wbuf1[n] = n;
for (m = 0; m < EP_SIZE; m++)
wbuf2[m] = m+1;
struct libusb_transfer *transfer1;
struct libusb_transfer *transfer2;
struct libusb_transfer *transfer3;
struct libusb_transfer *transfer4;
/* Set up the transfer object */
transfer1 = libusb_alloc_transfer(0);
transfer2 = libusb_alloc_transfer(0);
transfer3 = libusb_alloc_transfer(0);
transfer4 = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer1, handle, ep_out, wbuf1, EP_SIZE, xfr_cb, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer2, handle, ep_in, rbuf1, EP_SIZE, xfr_cb, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer3, handle, ep_out, wbuf2, EP_SIZE, xfr_cb, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer4, handle, ep_in, rbuf2, EP_SIZE, xfr_cb, &completed, TIMEOUT); /* callback data = &completed */
/* Submit the transfers */
libusb_submit_transfer(transfer1);
libusb_submit_transfer(transfer2);
libusb_submit_transfer(transfer3);
libusb_submit_transfer(transfer4);
/* Handle Events */
while (!completed)
{
rc = libusb_handle_events_completed(NULL, &completed);
if (rc != LIBUSB_SUCCESS)
{
fprintf(stderr, "Transfer Error: %s\n", libusb_error_name(rc));
break;
}
}
fprintf(stderr, "completed\n");
//* Release the interface */
libusb_release_interface(handle, 0);
/* Close the device handle */
if (handle)
libusb_close(handle);
out:
if (handle)
{
libusb_close(handle);
}
libusb_exit(NULL);
return rc;
}
libusb_fill_bulk_transfer(transfer1, handle, ep_out, wbuf1, EP_SIZE, NULL, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer2, handle, ep_in, rbuf1, EP_SIZE, NULL, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer3, handle, ep_out, wbuf2, EP_SIZE, NULL, NULL, TIMEOUT);
libusb_fill_bulk_transfer(transfer4, handle, ep_in, rbuf2, EP_SIZE, xfr_cb, &completed, TIMEOUT); /* callback data = &completed */
#include <stdlib.h>
#include <stdio.h>
#include <libusb-1.0/libusb.h>
/* Change VENDOR_ID and PRODUCT_ID depending on device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define BYTES 1024*768*3 // bytes
#define EP_SIZE 64 // bytes
#define TIMEOUT 5*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *devh = NULL;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in_addr = 0x82;
static int ep_out_addr = 0x01;
int write_chars(unsigned char * data, int length)
{
/* To send a char to the device simply initiate a bulk_transfer to the Endpoint
* with the address ep_out_addr.
*/
int actual_length;
int rc = libusb_bulk_transfer(devh, ep_out_addr, data, length, &actual_length, TIMEOUT);
if (rc < 0)
{
fprintf(stderr, "Error while sending char: %d\n", rc);
return -1;
}
return actual_length;
}
int read_chars(unsigned char * data, int length)
{
/* To receive characters from the device initiate a bulk_transfer to the Entpoint
* with address ep_in_addr
*/
int actual_length;
int rc = libusb_bulk_transfer(devh, ep_in_addr, data, length, &actual_length, TIMEOUT);
if (rc == LIBUSB_ERROR_TIMEOUT)
{
printf("timeout (%d)\n", actual_length);
return -1;
}
else if (rc < 0)
{
fprintf(stderr, "Error while waiting for char: %d\n", rc);
return -1;
}
return actual_length;
}
int main(int argc, char **argv)
{
int rc;
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
devh = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!devh)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* We can now start sending or receiving data to the device */
unsigned char buf[BYTES];
unsigned char rbuf[EP_SIZE];
int len;
int n;
int l;
int res;
// fill buffer
for (n = 0; n < BYTES; n++)
{
buf[n] = 0x00+n;
}
// loopback data, write-read
for (l = 0; l < BYTES/EP_SIZE; l++)
{
len = write_chars(buf+l*EP_SIZE, EP_SIZE);
len = read_chars(rbuf, EP_SIZE);
res = memcmp(rbuf, buf+l*EP_SIZE, sizeof(rbuf));
if (res != 0)
fprintf(stderr, "Miscompare: block %d\n", l);
}
libusb_release_interface(devh, 0);
out:
if (devh)
{
libusb_close(devh);
}
libusb_exit(NULL);
return rc;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include </usr/include/libusb-1.0/libusb.h>
/* Specify VENDOR_ID and PRODUCT_ID for device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define EP_SIZE 64 // bytes
#define TRANSFERS 1024*768*3/EP_SIZE // number of transfers
#define BYTES EP_SIZE*TRANSFERS
#define TIMEOUT 15*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *handle = NULL;
/* count variable */
unsigned int count_out = 0;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in = 0x82;
static int ep_out = 0x01;
unsigned char rbuf[EP_SIZE*TRANSFERS];
unsigned char wbuf[EP_SIZE*TRANSFERS];
static void LIBUSB_CALL xfr_cb_out(struct libusb_transfer *transfer )
{
memcpy(wbuf+count_out*EP_SIZE, transfer->buffer, EP_SIZE);
count_out++;
}
int main(int argc, char **argv)
{
const struct libusb_version *version;
unsigned char *buf, *rbuf_tmp;
size_t length = 64;
int n;
int i;
int rc;
/* Get libusb version */
version = libusb_get_version();
fprintf(stderr, "libusb version: %d.%d.%d.%d\n", version->major, version->minor, version->micro, version->nano);
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!handle)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* claim interface */
rc = libusb_claim_interface(handle, 0);
if (rc < 0)
{
fprintf(stderr, "Error claiming interface.\n");
goto out;
}
/* allocate memory */
buf = malloc(length*TRANSFERS);
/* fill the buffer with incrementing data */
for (n = 0; n < EP_SIZE*TRANSFERS; n++)
{
buf[n] = n;
}
/* allocate memory */
rbuf_tmp = malloc(length);
/* set up alternating OUT-IN transfers */
for (i = 0; i < TRANSFERS; i++)
{
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, ep_out, buf+i, EP_SIZE, xfr_cb_out, NULL, TIMEOUT);
libusb_submit_transfer(transfer);
int actual_length;
int rc = libusb_bulk_transfer(handle, ep_in, rbuf_tmp, EP_SIZE, &actual_length, TIMEOUT);
if (rc != LIBUSB_SUCCESS)
{
fprintf(stderr, "Transfer Error: %s\n", libusb_error_name(rc));
break;
}
memcpy(rbuf+i*EP_SIZE, rbuf_tmp, EP_SIZE);
}
fprintf(stderr, "completed\n");
int res;
res = memcmp(rbuf, wbuf, sizeof(wbuf));
if (res != 0)
fprintf(stderr, "miscompare\n");
//* Release the interface */
libusb_release_interface(handle, 0);
/* Close the device handle */
if (handle)
libusb_close(handle);
out:
if (handle)
{
libusb_close(handle);
}
libusb_exit(NULL);
return rc;
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include </usr/include/libusb-1.0/libusb.h>
/* Specify VENDOR_ID and PRODUCT_ID for device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define EP_SIZE 64 // bytes
#define TRANSFERS 1024*768*3/EP_SIZE // number of transfers
#define TIMEOUT 10*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *handle = NULL;
/* count variables */
unsigned int count = 0;
unsigned int count_in = 0;
unsigned int count_out = 0;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in = 0x82;
static int ep_out = 0x01;
/* Write and Read buffers */
unsigned char wbuf[EP_SIZE*TRANSFERS];
unsigned char wbuf_tmp[EP_SIZE*TRANSFERS];
unsigned char rbuf[EP_SIZE*TRANSFERS];
unsigned char rbuf_tmp[EP_SIZE*TRANSFERS];
static void LIBUSB_CALL xfr_cb_out(struct libusb_transfer *transfer )
{
memcpy(wbuf+count_out*EP_SIZE, transfer->buffer, EP_SIZE);
}
static void LIBUSB_CALL xfr_cb_in(struct libusb_transfer *transfer )
{
int *completed = transfer->user_data;
memcpy(rbuf+count_in*EP_SIZE, transfer->buffer, EP_SIZE);
count_in++; // one transfer complete
if (count_in < TRANSFERS)
*completed = 1;
}
int main(int argc, char **argv)
{
const struct libusb_version *version;
int completed = 0;
size_t length = 64;
int n;
int m;
int rc;
/* Get libusb version */
version = libusb_get_version();
fprintf(stderr, "libusb version: %d.%d.%d.%d\n", version->major, version->minor, version->micro, version->nano);
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!handle)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* claim interface */
rc = libusb_claim_interface(handle, 0);
if (rc < 0)
{
fprintf(stderr, "Error claiming interface.\n");
goto out;
}
/* fill the buffer with incrementing data */
for (n = 0; n < TRANSFERS; n++)
{
for (m = 0; m < EP_SIZE; m++)
{
wbuf_tmp[m+n*EP_SIZE] = m+n;
}
}
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, ep_out, wbuf_tmp, EP_SIZE*TRANSFERS, xfr_cb_out, NULL, TIMEOUT);
libusb_submit_transfer(transfer);
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, ep_in, rbuf_tmp, EP_SIZE*TRANSFERS, xfr_cb_in, &completed, TIMEOUT);
libusb_submit_transfer(transfer);
/* Handle Events */
while (!completed)
{
rc = libusb_handle_events_completed(NULL, &completed);
if (rc != LIBUSB_SUCCESS)
{
fprintf(stderr, "Transfer Error: %s\n", libusb_error_name(rc));
break;
}
}
fprintf(stderr, "completed\n");
int res;
res = memcmp(rbuf, wbuf, sizeof(wbuf));
if (res != 0)
fprintf(stderr, "miscompare\n");
else
fprintf(stderr, "success\n");
//* Release the interface */
libusb_release_interface(handle, 0);
/* Close the device handle */
if (handle)
libusb_close(handle);
out:
if (handle)
{
libusb_close(handle);
}
libusb_exit(NULL);
return rc;
}
include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include </usr/include/libusb-1.0/libusb.h>
/* Specify VENDOR_ID and PRODUCT_ID for device */
#define VENDOR_ID 0x0471
#define PRODUCT_ID 0x3630
/* Define number of bytes to transfer */
#define EP_SIZE 64 // bytes
#define TRANSFERS 1024*768*3/EP_SIZE // number of transfers
#define TIMEOUT 10*1000 // milliseconds
/* Use a global variable to keep the device handle */
static struct libusb_device_handle *handle = NULL;
/* count variables */
unsigned int count = 0;
unsigned int count_in = 0;
unsigned int count_out = 0;
/* The Endpoint addresses are hard-coded. You should use libusb -v to find
* the values corresponding to device
*/
static int ep_in = 0x82;
static int ep_out = 0x01;
/* Write and Read buffers */
unsigned char wbuf[EP_SIZE*TRANSFERS];
unsigned char *wbuf_tmp;
unsigned char rbuf[EP_SIZE*TRANSFERS];
unsigned char rbuf_tmp[EP_SIZE*TRANSFERS];
static void LIBUSB_CALL xfr_cb_out(struct libusb_transfer *transfer )
{
memcpy(wbuf+count_out*EP_SIZE, transfer->buffer, EP_SIZE);
count_out++; // one transfer complete
if (count_out < TRANSFERS)
{
transfer->buffer = ++wbuf_tmp;
libusb_submit_transfer(transfer);
}
}
static void LIBUSB_CALL xfr_cb_in(struct libusb_transfer *transfer )
{
int *completed = transfer->user_data;
memcpy(rbuf+count_in*EP_SIZE, transfer->buffer, EP_SIZE);
count_in++; // one transfer complete
if (count_in < TRANSFERS)
libusb_submit_transfer(transfer);
else
*completed = 1;
}
int main(int argc, char **argv)
{
const struct libusb_version *version;
int completed = 0;
size_t length = 64;
int n;
int rc;
/* Get libusb version */
version = libusb_get_version();
fprintf(stderr, "libusb version: %d.%d.%d.%d\n", version->major, version->minor, version->micro, version->nano);
/* Initialize libusb */
rc = libusb_init(NULL);
if (rc < 0)
{
fprintf(stderr, "Error Initializing libusb: %s\n", libusb_error_name(rc));
exit(1);
}
/* Set debugging output to max level */
libusb_set_debug(NULL, 3);
/* Look for a specific device and open it */
handle = libusb_open_device_with_vid_pid(NULL, VENDOR_ID, PRODUCT_ID);
if (!handle)
{
fprintf(stderr, "Error finding USB device\n");
goto out;
}
/* claim interface */
rc = libusb_claim_interface(handle, 0);
if (rc < 0)
{
fprintf(stderr, "Error claiming interface.\n");
goto out;
}
/* allocate memory */
wbuf_tmp = malloc(length*TRANSFERS);
/* fill the buffer with incrementing data */
for (n = 0; n < EP_SIZE*TRANSFERS; n++)
{
wbuf_tmp[n] = n;
}
struct libusb_transfer *transfer;
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, ep_out, wbuf_tmp, EP_SIZE, xfr_cb_out, NULL, TIMEOUT);
libusb_submit_transfer(transfer);
transfer = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer, handle, ep_in, rbuf_tmp, EP_SIZE, xfr_cb_in, &completed, TIMEOUT);
libusb_submit_transfer(transfer);
/* Handle Events */
while (!completed)
{
rc = libusb_handle_events_completed(NULL, &completed);
if (rc != LIBUSB_SUCCESS)
{
fprintf(stderr, "Transfer Error: %s\n", libusb_error_name(rc));
break;
}
}
fprintf(stderr, "completed\n");
int res;
res = memcmp(rbuf, wbuf, sizeof(wbuf));
if (res != 0)
fprintf(stderr, "miscompare\n");
else
fprintf(stderr, "success\n");
//* Release the interface */
libusb_release_interface(handle, 0);
/* Close the device handle */
if (handle)
libusb_close(handle);
out:
if (handle)
{
libusb_close(handle);
}
libusb_exit(NULL);
return rc;
}