因为测试的比较混乱,我就按照我的问题导向来描述我的过程吧

一. 提示libusb_context对象为NULL的错误:

  在简化的过程中,我没有加入dev_handler判断为空就进行了具体的工作;

1 if( !dev_handler )
2 libusb_open(dev_obj, &dev_handler);
3 if( dev_handler )
4 // do your job

二. 如果不知道是什么原因(比如说ioctl之类的错误,那么可能是安装错误了驱动:

  我使用了zadig-2.7.exe,来安装:

  如果想要测试HID设备,安装成WinUSB会比较合适;

  如果想要其他的usb设备安装成libusb会比较合适

  如果想要测试等时传输(isoch)则libusbk会更合适一些(虽然我用的是WinUSB好像也可以)

三. 对于Windows中USB的驱动的了解也比较重要:

 1 libusb_bullk_transfer 是libusb提供的函数;
2 do_syun_bulk_transfer 执行具体的工作
3 // 在do_sync_bulk中
4 {
5 alloc_transfer();
6 fill_bulk_transfer();
7 submit_transfer();
8 sync_transfer_wait_for_completion();
9 }
10 // 其中submit又是重点:
11 submit_transfer(){
12 ref_device();
13 mutex_lock & transfer_lock;
14 set_itransfer_obj;
15 add_to_flying_list
16 usbi_backend->submit_transfer()
17 }
18 // 其中ubsi_backend表示的是具体的实现的

四. 对于device发送的Descriptor解析页非常重要:

  其中我认为最重要的就是对断点endpoint descriptor属性的理解 :

  关系这个断电支持什么样的传输方式,已经最多穿多少(对于Isoch来说非常重要)

 1 static void print_endpoint(const struct libusb_endpoint_descriptor* endpoint)
2 {
3 int i, ret;
4 printf("\t\t\tEndpoint:\n");
5 // 可以看出endpoint是OUT(host->device)还是IN(device->host)
6 printf("\t\t\t\tbEndpointAddress: %02xh\n", endpoint->bEndpointAddress);
7 // 可以看出支持的操作:01:中断;02:bulk;03:isoch
8 printf("\t\t\t\tbmAttributes: %02xh\n", endpoint->bmAttributes);
9 printf("\t\t\t\twMaxPacketSize: %u\n", endpoint->wMaxPacketSize);
10 printf("\t\t\t\tTransfer Interval %u\n", endpoint->bInterval);
11 }

五. 关于等时传输isoch(困扰了我最久的一块儿)

  Step1: 根据 微软的官方文档 了解等是传输断点(endpoint)中具体的信息;

获得不连续数据包大小MaximumPacketSize

使用libusb提供的libusb_get_max_iso_packet_size方法就可以了

全速设备:这是1帧发送的数据;

对于高速设备,这个是1微帧发送的字节数;

好像已经固定了:Full是1024;High是3072;Super是45000

确认帧包含多少微帧 根据断点提供的bInterval来计算:2^(Interval-1)
验证

需要连续包个数必须是每个帧数据包数的倍数;

分配结构体

也就是alloc_transfer

指定详细信息 也就是给transfer结构体添加缓冲区数据

    最诡异的就是这个Interval:

    根据Interval就可以计算出来轮询周期Polling Period = 2^(Interval-1); 轮询周期表示每轮询周期个总线间隔才会传输一次;

    所以Interval == 4的时候就和Full Speed差不多;

   Step2:实践:使用等时传输函数:

    首先上代码:

int do_sync_transfer()
{
int endpoint_num;
int test_type;
int interface_num = USB_INTERFACE;
int ret;
int packet_size;
int transfer_length;
int numberOfPackets;
unsigned char* buff;
int temp;
int trans_time; printf("INFO: Enter the test type\n\t0: ISOC IN; 1: ISOC OUT\n");
scanf_s("%d", &test_type);
switch (test_type)
{
case 0:
endpoint_num = ISOC_IN_ENDPOINT;
dir = 1;
break;
case 1:
endpoint_num = ISOC_OUT_ENDPOINT;
dir = 0;
break;
default:printf("ERROR: Wrong test type\n");return;
}
if ((ret = libusb_clear_halt(g_handler, endpoint_num)) < 0)
{
printf("ERROR: clear halt failed\n\tReason: %s\n", libusb_strerror(ret));
return -1;
}
printf("INFO: clear halt succeed\n");
int number0fPacketPerFrame; // new ONE:
// 计算缓冲区大小和长度最重要的地方:
// 根据Interval 计算Polling Period
// 缓冲区大小 = 最大不连续包大小 * 8/ Polling Period
int win_interval = (ISOC_INTERVAL - 1);
int min_buffer_size = MAX_BYTES_PER_INTERVAL * 8 / win_interval; buff = (unsigned char*)malloc(sizeof(unsigned char) * 3072);
int temp_time = min_buffer_size / 16;
for (int i = 0; i < temp_time; i++)
memset(buff + (i * 16), temp_time, 16); libusb_set_debug(NULL, 4); if (endpoint_num == ISOC_OUT_ENDPOINT) {
struct libusb_transfer* xfer;
// 标识发送开始
// 也是很重要的:设置异步的检测状态函数:
// 注意使用detach分离
is_send_over = 0;
pthread_t my_thread;
pthread_create(&my_thread, NULL, handle_isoc_transfer, g_ctx);
pthread_detach(my_thread);
for (trans_time = 0; trans_time < 15; trans_time++) {
printf("TIME: %d\n", trans_time);
printf("Enter Send transfer length:\n");
scanf_s("%d", &transfer_length);
numberOfPackets = ceil(transfer_length / min_buffer_size);
printf("The number of packets is : %d\n", numberOfPackets);
if (numberOfPackets % number0fPacketPerFrame != 0) {
printf("Number of Packet should be a multiple of numberOf packet per frame\n");
return;
}
for (int i = 0; i < numberOfPackets; i++) {
int temp_translen = (transfer_length >= min_buffer_size) ? min_buffer_size : transfer_length;
transfer_length -= temp_translen;
xfer = libusb_alloc_transfer(number0fPacketPerFrame);
if (!xfer) {
printf("ERROR: no memory for transfer\n");
libusb_set_debug(NULL, 0);
return -1;
}
libusb_fill_iso_transfer(xfer, g_handler, endpoint_num,
buff,
transfer_length,
number0fPacketPerFrame,
isoc_callback_send,NULL, 200);
xfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
libusb_set_iso_packet_lengths(xfer, temp_translen);
ret = libusb_submit_transfer(xfer);
if (ret < 0) {
printf("ERROR: submit\n");
libusb_free_transfer(xfer);
libusb_set_debug(NULL, 0);
return -1;
}
Sleep(500);
libusb_free_transfer(xfer);
}
}
is_send_over = 1;
}
else {
int receive_time;
is_receive_over = 0;
pthread_t my_thread;
pthread_create(&my_thread, NULL, handle_isoc_transfer, g_ctx);
pthread_detach(my_thread);
for (trans_time = 0; trans_time < 15; trans_time++) {
printf("TIME: %d\n", trans_time);
printf("Enter Receive Time:\n");
scanf_s("%d", &receive_time);
for (int i = 0; i < receive_time; i++) {
printf("Receive No.%d", i);
if ((ret = libusb_clear_halt(g_handler, endpoint_num)) < 0)
{
printf("ERROR: clear halt failed\n\tReason: %s\n", libusb_strerror(ret));
return -1;
}
printf("INFO: clear halt succeed\n");
struct libusb_transfer* xfer;
libusb_fill_iso_transfer(
xfer,
g_handler,
endpoint_num,
buff,
min_buffer_size,
number0fPacketPerFrame,
isoc_callback_receive,
NULL,
200);
xfer->type = LIBUSB_TRANSFER_TYPE_ISOCHRONOUS;
libusb_set_iso_packet_lengths(xfer, min_buffer_size);
ret = libusb_submit_transfer(xfer);
if (ret < 0) {
printf("ERROR: submit\n");
libusb_free_transfer(xfer);
libusb_set_debug(NULL, 0);
return -1;
}
Sleep(200);
libusb_free_transfer(xfer);
}
}
is_receive_over = 1;
}
libusb_set_debug(NULL, 0);
return 0;
}

    然后对应的异步处理函数代码如下:

 1 static int LIBUSB_CALL usb_arrived_callback(libusb_context*, libusb_device*, libusb_hotplug_event, void*);
2 // leave : left
3 static int LIBUSB_CALL usb_left_callback(libusb_context*, libusb_device*, libusb_hotplug_event, void*);
4 // Just get one handler (default by dev)
5 void get_handle_and_device_by_vandp(uint16_t, uint16_t, libusb_device**, libusb_device_handle**);
6 int print_all_device();
7
8 void* handle_isoc_transfer(void* param) {
9 if (param == NULL) {
10 printf("PARAM Wrong\n");
11 return;
12 }
13 libusb_context* ctx = (libusb_context*)param;
14 while (1) {
15 if (is_send_over == 1) {
16 printf("This time already done");
17 break;
18 }
19 libusb_handle_events(ctx);
20 }
21 }
22
23 static void LIBUSB_CALL isoc_callback_send(struct libusb_transfer* xfer)
24 {
25 printf("INFO : in isoc_callback send\n");
26 if (xfer == NULL)
27 return;
28 printf("INFO : the transfer status is :%d\n", xfer->status);
29 switch(xfer->status)
30 {
31 case LIBUSB_TRANSFER_COMPLETED:
32 printf("INFO: transter complete\nDatas are:\n");
33 printf("The length : %d\n", xfer->actual_length);
34 break;
35 case LIBUSB_TRANSFER_ERROR:
36 printf("ERROR: transfer error\n");
37 break;
38 case LIBUSB_TRANSFER_TIMED_OUT:
39 printf("ERROR: transfer timeout\n");
40 break;
41 case LIBUSB_TRANSFER_CANCELLED:
42 printf("ERROR: transfer is cancelled\n");
43 break;
44 case LIBUSB_TRANSFER_STALL:
45 printf("ERROR: transfer stall\n");
46 break;
47 case LIBUSB_TRANSFER_NO_DEVICE:
48 printf("ERROR: no device detected\n");
49 break;
50 case LIBUSB_TRANSFER_OVERFLOW:
51 printf("ERROR: transfer overflowed\n");
52 break;
53 default:
54 printf("ERROR: UNKNOWN status\n");
55 break;
56 }
57 }
58
59 static void LIBUSB_CALL isoc_callback_receive(struct libusb_transfer* xfer) {
60 if (xfer == NULL)
61 return;
62 printf("INFO: enter : %s and status is : %d\n", __func__, xfer->status);
63 switch (xfer->status)
64 {
65 case LIBUSB_TRANSFER_COMPLETED:
66 printf("INFO: transfer completed\n");
67 break;
68 case LIBUSB_TRANSFER_ERROR:
69 printf("ERROR: transfer error\n");
70 break;
71 case LIBUSB_TRANSFER_TIMED_OUT:
72 printf("ERROR: transfer timeout\n");
73 break;
74 case LIBUSB_TRANSFER_CANCELLED:
75 printf("ERROR: transfer is cancelled\n");
76 break;
77 case LIBUSB_TRANSFER_STALL:
78 printf("ERROR: transfer stall\n");
79 break;
80 case LIBUSB_TRANSFER_NO_DEVICE:
81 printf("ERROR: no device detected\n");
82 break;
83 case LIBUSB_TRANSFER_OVERFLOW:
84 printf("ERROR: transfer overflowed\n");
85 break;
86 default:
87 printf("ERROR: UNKNOWN status\n");
88 break;
89 }
90 }

    总是不确定到底该发送多少个数据才能被接收:

    终于找到了windows_winusb.c中的winusbx_submit_iso_transfer函数:

 1 // For high-speed and SuperSpeed device, the interval is 2**(bInterval-1).
2 if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH)
3 interval = (1 << (pipe_info_ex.Interval - 1));
4 if (transfer->dev_handle->dev->speed >= LIBUSB_SPEED_HIGH) {// Microframes (125us)
5 printf("--------INFO: %d\n", (pipe_info_ex.MaximumBytesPerInterval * 8) / interval);
6 iso_transfer_size_multiple = (pipe_info_ex.MaximumBytesPerInterval * 8) / interval;
7 }
8 else // Normal Frames (1ms)
9 iso_transfer_size_multiple = pipe_info_ex.MaximumBytesPerInterval / interval;
10 if (transfer->length % iso_transfer_size_multiple != 0) {
11 usbi_err(TRANSFER_CTX(transfer), "length of isoch buffer must be a multiple of the MaximumBytesPerInterval * 8 / Interval");
12 return LIBUSB_ERROR_INVALID_PARAM;
13 }

    可见:里面对interval也进行了计算:

    在使用等时传输读的时候需要将buffer的长度设置为size_multiple;但是写的时候并不需要;

    最后终于测试成功了

Libusb测试USB device(2)的更多相关文章

  1. 基于libUSB的USB设备固件更新程序(下载数据)(转)

    源:基于libUSB的USB设备固件更新程序(下载数据) 本文紧接上一篇日志:基于libUSB-Win32的USB设备固件更新程序(前言),相关背景以及起因等,此处不再赘述,如感兴趣请移步. libU ...

  2. USB device & USB controller & USB passthrough

    目录 USB device USB controller Linux 相关命令 Python 相关库 Libvirt USB passthrough 参考资料 近期往 openstack 里倒腾 US ...

  3. 【转载】How to Reset USB Device in Linux

    USB devices are anywhere nowadays, even many embedded devices replace the traditional serial devices ...

  4. libusb获取usb设备的idVendor(vid),idProduct(pid),以及Serial Number

    发表于2015/6/23 21:55:11  4594人阅读 最近在做关于usb设备的项目,用到了libusb,发现关于这个的函数库的介绍,讲解很少,下面仅仅是简单展示一些基本的使用方法,以备后用. ...

  5. 痞子衡嵌入式:可通过USB Device Path来唯一指定i.MXRT设备进行ROM/Flashloader通信

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是通过USB Device Path来唯一指定i.MXRT设备进行ROM/Flashloader通信. i.MXRT系列高性能微控制器从2 ...

  6. Install Slax on USB device (Slax U 盘安装)

    Slax is a modern, portable, small and fast Linux operating system with a modular approach and outsta ...

  7. What is a Windows USB device path and how is it formatted?

    http://community.silabs.com/t5/Interface-Knowledge-Base/Windows-USB-Device-Path/ta-p/114059 Windows ...

  8. USB Device Finder

    http://www.velleman.eu/images/tmp/usbfind.c #ifdef __cplusplus extern "C" { #endif #includ ...

  9. Assigning Host USB device to a Guest VM

    Example Assigning Host USB device to a Guest VM This example is based on qemu-kvm (0.15.0) as instal ...

  10. usb host和usb device

    S3C2440的数据手册将USB功能分为两章--usb host和usb device.具体什么意思呢? usb host: 微处理器作为usb主设备,可以挂接U盘之类的从属设备. usb devic ...

随机推荐

  1. 手把手教你用LOTO虚拟示波器搭建测试系统整机

    虚拟示波器如果用于个人的研发调试工作,主要能体现出它的小巧便携以及功能强大.而它的另一个巨大优势,可集成性可定制性高,则是在我们做项目中搭建测试系统的时候才能更好的体现出来. 通常测试系统要求长时间工 ...

  2. [​DuckDB] 多核算子并行的源码解析

    DuckDB 是近年来颇受关注的OLAP数据库,号称是OLAP领域的SQLite,以精巧简单,性能优异而著称.笔者前段时间在调研Doris的Pipeline的算子并行方案,而DuckDB基于论文< ...

  3. Codeforces Round #849 (Div. 4)

    A. Codeforces Checking 题意 每个案例给一个字符,如果在 "codeforces" 中出现过,输出 YES,否则输出 NO code /** * @autho ...

  4. Vue19 常用指令及自定义指令

    部分转自:https://blog.csdn.net/weixin_58032613/article/details/122759818 1 常用指令 1) v-bind 单向数据绑定 https:/ ...

  5. app实现外部浏览器打开链接

    需求:安卓和IOS开发的混合app.前端使用vue,vant2,安卓使用java,ios使用的object-c.实现效果:点击按钮,下载PDF附件,app跳转到手机外部浏览器,下载附件...... 1 ...

  6. Spring Cloud Config 本地配置

    七:Spring Cloud Config 本地配置 本地文件系统 我们可以将微服务的相关配置文件存储到本地文件中,然后让微服务来读取本地文件. 创建本地文件 Config Server 1.创建模块 ...

  7. 快速上手vue前端存储库、全局状态管理工具pinia

    pinia是什么,为什么我们要使用pinia? pinia是vue全局状态管理工具,类似vueX,用于全局的数据状态存储.修改变更等等 相较于vueX,pinia的使用较为简单,轻量级,上手容易,干掉 ...

  8. 【KAWAKO】audiotsm-使用python对音频进行变速不变调处理

    目录 安装库 导入相关库 定义reader 定义writer 定义WSLOA算法,并运行 官方手册 源码 安装库 pip install audiotsm 导入相关库 import audiotsm ...

  9. Me-and-My-Girlfriend-1

    Me-and-My-Girlfriend-1 目录 Me-and-My-Girlfriend-1 1 信息收集 1.1 端口扫描 1.2 后台目录扫描 1.2.1 目录分析 2 GetShell 2. ...

  10. 基于Python的OpenGL 06 之摄像机

    1. 引言 本文基于Python语言,描述OpenGL的摄像机 前置知识可参考: 基于Python的OpenGL 05 之坐标系统 - 当时明月在曾照彩云归 - 博客园 (cnblogs.com) 笔 ...