Libusb测试USB device(2)
因为测试的比较混乱,我就按照我的问题导向来描述我的过程吧
一. 提示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)的更多相关文章
- 基于libUSB的USB设备固件更新程序(下载数据)(转)
源:基于libUSB的USB设备固件更新程序(下载数据) 本文紧接上一篇日志:基于libUSB-Win32的USB设备固件更新程序(前言),相关背景以及起因等,此处不再赘述,如感兴趣请移步. libU ...
- USB device & USB controller & USB passthrough
目录 USB device USB controller Linux 相关命令 Python 相关库 Libvirt USB passthrough 参考资料 近期往 openstack 里倒腾 US ...
- 【转载】How to Reset USB Device in Linux
USB devices are anywhere nowadays, even many embedded devices replace the traditional serial devices ...
- libusb获取usb设备的idVendor(vid),idProduct(pid),以及Serial Number
发表于2015/6/23 21:55:11 4594人阅读 最近在做关于usb设备的项目,用到了libusb,发现关于这个的函数库的介绍,讲解很少,下面仅仅是简单展示一些基本的使用方法,以备后用. ...
- 痞子衡嵌入式:可通过USB Device Path来唯一指定i.MXRT设备进行ROM/Flashloader通信
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是通过USB Device Path来唯一指定i.MXRT设备进行ROM/Flashloader通信. i.MXRT系列高性能微控制器从2 ...
- Install Slax on USB device (Slax U 盘安装)
Slax is a modern, portable, small and fast Linux operating system with a modular approach and outsta ...
- 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 ...
- USB Device Finder
http://www.velleman.eu/images/tmp/usbfind.c #ifdef __cplusplus extern "C" { #endif #includ ...
- 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 ...
- usb host和usb device
S3C2440的数据手册将USB功能分为两章--usb host和usb device.具体什么意思呢? usb host: 微处理器作为usb主设备,可以挂接U盘之类的从属设备. usb devic ...
随机推荐
- 读Java8函数式编程笔记07_设计和架构的原则
1. SOLID原则 1.1. 开发良好面向对象程序的准则 1.2. Liskov substitution里氏替换 1.3. Interface segregation接口隔离 1.4. Singl ...
- 2211-11Flask入门教程
本篇记录来自Flask入门教程 准备工作 在通过这本书学习 Flask 开发前,我假设你已经了解了 Python 和 HTML 的基础知识.如果还没有,那么可以先从下面这些在线资源入手: <使用 ...
- 复制内容到剪切板通用的js方法
复制内容到剪切板通用的js方法 /** * 复制内容到剪切板 * @param text 要复制的内容 */ function Clipboard(text) { if (navigator.clip ...
- vue + element-ui + qrcodejs2 实现二维码生成
1.在所在项目下安装插件 npm i qrcodejs2 2.在需要生成二维码的页面引入qrcodejs import QRCode from 'qrcodejs2' 3.使用 <el-butt ...
- Symbol详解
Symbol Symbol是es6引入的一个新的原始数据类型,是一个独一无二的值. 目前为止,js的数据类型有以下几种: 数据类型 说明 undefined undefined null null b ...
- JZOJ 3527.迷宫花坛(garden)
题面 思路 考场想到 \(tarjan\) 缩点 然而忘了缩点怎么打 于是甩了个暴力 改题时学了个圆方树 发现挺好用 于是······注意重边 \(Code\) #include<cstdio& ...
- Linux centos 代替方案: Rocky Linux (centos作者)
官网: Rocky Linux
- Cobalt Strike 之:提权
郑重声明: 本笔记编写目的只用于安全知识提升,并与更多人共享安全知识,切勿使用笔记中的技术进行违法活动,利用笔记中的技术造成的后果与作者本人无关.倡导维护网络安全人人有责,共同维护网络文明和谐. Co ...
- js中的for循环,循环次数会多出一次。当循环到最后一个的时候,循环还会继续,并且此时i就变成remove?
for (i in points) 改成 for(var i = 0; i < points,length; i++)
- ABP微服务系列学习-搭建自己的微服务结构(三)
上一篇我们基础服务初步搭建完毕,接下来我们整一下认证和网关. 搭建认证服务 认证服务的话,ABP CLI生成的所有模板都包括了一个AuthServer.我们直接生成模板然后微调一下就可以直接用了. a ...