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

一. 提示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;但是写的时候并不需要;

    最后终于测试成功了

最新文章

  1. DOM基础3
  2. Uploadify在MVC中使用方法案例(一个视图多次上传单张图片)
  3. NFS服务器
  4. Unity3D 将 Unity 嵌入WPF中的一些研究笔记
  5. python增删改查
  6. oracle 自治事物 -- autonomous transaction
  7. SimpleDateFormat的使用
  8. RSA实践指南
  9. Hibernate框架进阶(中篇)之多表关系
  10. CSS3对于盒中容纳不下的内容的显示——overflow属性
  11. sdl的缩放问题
  12. 微信小程序授权获取用户详细信息openid
  13. Map 遍历分析
  14. asp.net 客户端请求到响应的整个过程
  15. sort 快排解决百万级的排序
  16. python数据类型及基本运算符
  17. c++中被忽视的隐藏
  18. 新建本地仓库,同步远程仓场景,出现git branch --set-upstream-to=origin/master master 解决方法
  19. rsync数据备份
  20. springboot项目maven报错 LoggerFactory is not a Logback LoggerContext but Logback is on the classpath. Either remove Logback

热门文章

  1. 结构型模式 - 代理模式Proxy
  2. vue学习笔记(五)---- vue动画
  3. 使用pycharm打开sqlite的问题
  4. 822. 走方格(acwing)
  5. Android IO 框架 Okio 的实现原理,如何检测超时?
  6. 【rust】rsut基础:模块的使用一、mod 关键字、mod.rs 文件的含义等
  7. @EnableDiscoveryClient和@EnableEurekaClient springboot3.x
  8. 【开发宝典】Java并发系列教程(四)
  9. 祝 .NET 20周年生日快乐
  10. [学习笔记]SQL server完全备份指南