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

一. 提示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. Quartz.Net 官方教程 Tutorial 1/3(Jobs 和 Trigger)

    根据官网说明 类型 概述 IScheduler 调度类核心接口 IJob 独立实现业务逻辑需要继承的任务接口 IJobDetail 给任务接口定义实例的任务说明类接口 ITrigger 触发器,设置何 ...

  2. 【分析笔记】SiliconLabs EFR32BG22 Bluetooth Mesh SensorClient 源码分析

    硬件环境: SLTB010A(BRD4184A Rev A02 / EFR32BG22C224F512IM40) 软件环境: SimplicityStudio5/gecko_sdk_3.2.3 分析工 ...

  3. 同类型芯片资源对比-CH32x芯片快速应用说明

    CH32Fx 系列芯片是基于 Cortex-M3 内核设计的微控制器,所以与大部分 ARM 工具和软件兼容. 此外,其外设和硬件设计兼容市场上一些主流微控制器,并在性能和功能上有所增强, 方便用户快速 ...

  4. Pytest插件pytest-repeat重复执行

    Pytest插件pytest-repeat重复执行 安装 pip install pytest-repeat doc https://pypi.org/project/pytest-repeat/ h ...

  5. 【学习日志】MySQL分表与索引的关系

    什么情况下需要分表呢?分表又能解决什么问题呢? 一般情况下分表的直接原因是数据量太大了,比如一张表一共只有1w条数据,确实没必要分表.为什么数据量大了就需要分表呢?首先得看看数量量过大后会带来什么问题 ...

  6. 元数据库 information_schema.tables

    转  https://www.cnblogs.com/ssslinppp/p/6178636.html 1.information_schema数据库 对于mysql和Infobright等数据库,i ...

  7. Google_MapReduce中文版

    笔者最近在看MIT6.824的lab1,实验内容是实现一个简易的MapReduce.本篇文章是MapReduce论文的中文翻译. @Author:Akai-yuan @更新时间:2023/2/13 摘 ...

  8. 真正“搞”懂HTTPS协议18之TLS特性解析

    上一篇,我们讲了TLS的握手过程,我们参照的版本其实是TLS1.2.这个协议是2008年的老协议了,虽然它的价值不言而喻,但是毕竟年纪大了,不太能跟得上时代了.所以,经历了诸多磨难的TLS1.3在20 ...

  9. SpringMVC的表单组件、国际化

    spring mvc 的表单标签库 1.Student实体类 package com.southwind.POJO; import lombok.Data; @Data public class St ...

  10. ctf 菜鸟杯

    web签到 首先最里面的是ctfshow-QQ群:,而他需要进行cookie传参,因此我们需要在cookie传入CTFshow-QQ群=a,然后就要以POST方式传入a的值,我们传入a=b,而b是以G ...