社区
Windows SDK/API
帖子详情
使用libusb open device with vid pid返回NULL怎么解决
xxxbit
2015-11-08 12:47:16
在用libusb open device with vid pid时只有HID能够成功,其他U盘硬盘返回NULL,是什么问题?
...全文
531
2
打赏
收藏
使用libusb open device with vid pid返回NULL怎么解决
在用libusb open device with vid pid时只有HID能够成功,其他U盘硬盘返回NULL,是什么问题?
复制链接
扫一扫
分享
转发到动态
举报
写回复
配置赞助广告
用AI写文章
2 条
回复
切换为时间正序
请发表友善的回复…
发表回复
打赏红包
libusb
-1.0.9
libusb
1.0学习(一) 首先声明,这是看到国外论坛上的学习文章后,独立翻译过来作为笔记用,加入部分自我理解,并且全部原创。 介绍:
libusb
是一个开源库,可以帮助开发者在用户空间的层面上与UBS设备进行通讯。如果想了解更多,可以查看他们的主页:http://
libusb
.org/ 在其文档中,建议首先阅读USB2的规格说明:http://www.usb.org/developers/docs/,这可以帮助真正地了解USB是如何工作的。
libusb
的安装: 你可以从官方的主页上获取源代码,并且编译安装。或者
使用
的发行版已经包含了软件包,可以很方便地安装。 如果已经安装完毕,请继续往下 通讯: 设备和客户端之间的通讯是个清楚的概念叫做
使用
管道。每个管道都是一个主机上的一个软件和设备上一个端点的通道。每个端点对于设备来说完成一部分特殊的目标,比如接受命令或者传输数据。一个全速设备最高可以拥有16个端点,然后低速的设备只拥有三个端点。 所有的USB设备当供电时都支持端口0。这个端口是默认的目标管道。当设备连接被检测到后,USBD软件会
使用
端口0来初始化设备,执行普通的(非特殊)配置,并且获得有设备提供的其他端点的信息。端点是以他们的端点数目(取决于设计的时间),总线宽带,访问频率,延迟和处理错误要求为特征区分的。 一旦设备里的端点识别并且配置完毕,管道就产生允许客户端软件与设备进行通讯。跟一个管道产生联系是以对总线的访问和带宽,传输的类型,传输的方向和最大数据负载大小为描述特征的。 USB定义了四种传输方式:控制传输,通常用来传输命令和状态操作;中断传输,通过设备初始化一些来自主机的请求;同步传输,用来传输投递关键事件的数据(比如视频和对话);批量传输,
使用
全部可以用的带宽但不是特定时间的。所有的数传
使用
相同格式的包装,包括控制信息,数据和错误效验区域。 这里有两种管道:消息管道和流管道。控制传输是
使用
消息管道。在消息管道中,在每个包中的数据部分对于USB系统软件是有意义的。 流管道被中断传输,同步传输和批量传输
使用
。在流管道中,在每个包中的数据部分对于USB是没有意义,仅仅在客户端软件和设备间传输。 同步接口: 同步接口允许你
使用
单独一个函数调用一个USB传输。当这个函数调用
返回
时,这个传输也已经完成并且
返回
结果供解析用。这种方式的优点是十分清晰的:你可以通过一个简单的函数调用做任何事。 尽管如此,这个接口还是有它的局限性。你的程序会进入休眠当在
libusb
_bulk_transfer()(当进行批量传输),直到传输完成。假如这需要花费三个小时,你的程序同样需要休眠同样的时间。实现将会在库里面结束,整体线程这期间是无用的。另一个问题是,当一个单独的传输线程结束,这里不存在可能多个端点和多个设备同时地进行I/O操作,除非你借助创造新的线程处理。另外的,当请求被提交后,这里没有机会可能取消传输。 设备和接口: 在
libusb
中,每个USB设备通过
libusb
_
device
和
libusb
_
device
_handle对象操作。
libusb
API 连接一个打开的设备至特定的接口。这意味着如果你在设备上请求多个接口,你必须同样多次打开设备来接受一个
libusb
_dev_handle,对应每个你想进行通讯的接口。不要忘记调用
libusb
_dev_handle。 这些意味着什么?这意味你在设备上操作以前,可以完成请求接口,同样,你可以在完成设备操作前,先释放接口。 每个设备都有自己独属的配置,比如vendor id,product id等。我们
使用
这些设置去发现需求的设备,并且通过这些配置来工作。首先我们写一个函数来查明这些配置并且打印出来,以便我们找到正确的一个;我们基本的操作如下: 1.通过调用
libusb
_init来初始化库,同时创建一个对话; 2.调用
libusb
_get_
device
_list来获得已经连接的设备的队列。这会创建一个
libusb
_
device
的数组,包含了所有连接到系统上的usb设备; 3.循环遍历所有的设备来检查他们的选项; 4.发现其中需要的一个,
使用
libusb
_
open
或者
libusb
_
open
_
device
_with_
vid
_
pid
(当你知道这个设备vendor id和product id)来打开设备; 5.
使用
libusb
_free_
device
_list清除
使用
libusb
_get_
device
_list获得的队列; 6.通过
libusb
_claim_interface请求接口(需要你知道设备的接口数值); 7.操作想得到的I/O; 8.通过
libusb
_release_interface释放设备; 9.通过
libusb
_close将你之前打开的设备关闭; 10.通过
libusb
_exit来关闭对话; PS:英文需要苦练啊,一篇短的教程文章看的结结巴巴的
libusb
1.0学习(二) 接学习一,学习二主要是看例程 ok,现在最简单的想法看看有多少信息包含在你的设备里,程序代码如下 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include
#include <
libusb
.h> using namespace std; void printdev(
libusb
_
device
*dev); //prototype of the function int main() {
libusb
_
device
**devs; //pointer to pointer of
device
, used to retrieve a list of
device
s
libusb
_context *ctx =
NULL
; //a
libusb
session int r; //for return values ssize_t cnt; //holding number of
device
s in list r =
libusb
_init(&ctx;); //initialize a library session if(r < 0) { cout<<"Init Error "<
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation cnt =
libusb
_get_
device
_list(ctx, &devs;); //get the list of
device
s if(cnt < 0) { cout<<"Get
Device
Error"<
Devices in list."<
device ssize_t i; //for iterating through the list for(i = 0; i < cnt; i++) { printdev(devs[i]); //print specs of this
device
}
libusb
_free_
device
_list(devs, 1); //free the list, unref the
device
s in it
libusb
_exit(ctx); //close the session return 0; } void printdev(
libusb
_
device
*dev) {
libusb
_
device
_descriptor desc; int r =
libusb
_get_
device
_descriptor(dev, &desc;); if (r < 0) { cout<<"failed to get
device
descriptor"<
Device Class: "<<(int)desc.b
Device
Class<<" "; cout<<"VendorID: "<
libusb_config_descriptor *config;
libusb
_get_config_descriptor(dev, 0, &config;); cout<<"Interfaces: "<<(int)config->bNumInterfaces<<" ||| "; const
libusb
_interface *inter; const
libusb
_interface_descriptor *interdesc; const
libusb
_endpoint_descriptor *epdesc; for(int i=0; i<(int)config->bNumInterfaces; i++) { inter = &config;->interface[i]; cout<<"Number of alternate settings: "<
num_altsetting<<" | "; for(int j=0; j
num_altsetting; j++) { interdesc = &inter;->altsetting[j]; cout<<"Interface Number: "<<(int)interdesc->bInterfaceNumber<<" | "; cout<<"Number of endpoints: "<<(int)interdesc->bNumEndpoints<<" | "; for(int k=0; k<(int)interdesc->bNumEndpoints; k++) { epdesc = &interdesc;->endpoint[k]; cout<<"Descriptor Type: "<<(int)epdesc->bDescriptorType<<" | "; cout<<"EP Address: "<<(int)epdesc->bEndpointAddress<<" | "; } } } cout<
libusb_free_config_descriptor(config); } 写完之后,编译看看会出现什么。首先运行程序并检查设备,然后连上我自己的设备在执行程序。会发现有新的内容出现,可以根据vendor id和product id发现这正是我自己连上打开的设备。 注意:发现设备(调用
libusb
_get_
device
_list())会
返回
新的内存分配的设备队列。当你完成这个队列的
使用
后必须释放他。
Libusb
同样需要知道当一切完成时清除队列的内容;设备的本身。 为处理这些问题,
libusb
提供了两个单独的条目: 一个释放队列本身的函数 一个针对设备内部的参考计数系统 新的设备由
libusb
_get_
device
_list()函数展示,都拥有一个参考计数1。你可以
使用
libubs_ref_
device
()和
libusb
_unref_
device
()增加或减少参考计数。当一个设备的参考计数为0时,该设备就被销毁 通过以上的信息,打开设备的基本流程可以视为如下步骤: 1.
使用
libusb
_get_
device
_list()发现设备; 2. 选择你想操作的设备,调用
libusb
_
open
(); 3. 在设备队列中unref所有的设备; 4. 释放已经发现的设备队列; 这个次序是十分重要的,在尝试打开设备之前,你不能够unreference设备,因此unreference操作有可能导致设备的销毁。 为了方便起见,
libusb
_free_
device
_list()函数包含一个参数,在释放队列本身前,该参数能够选择性地在队列中unreference所有设备。这包含了以上的步骤3和步骤4。 如果还有需要,可以去
libusb
1’s API(http://
libusb
.sourceforge.net/api-1.0/index.html)文档参考你需要的函数。 好了,现在你可以找到你需要的设备了。现在是打开设备,请求并且执行一个简单的I/O。如果你知道vendor ID和prouct ID,
使用
libusb
_
open
_
device
_with_
vid
_
pid
。 另外需要注意的,如果内核(你的OS)已经连接到这个设备,你将无法请求到它。在这种情况下,你需要调用
libusb
_detach_kernel_drive来从内核中检测设备。如果你想知道内核是否可用的,
使用
libusb
_kernel_drive_active,如果
返回
值为1,对于你的设备内核可以加载驱动。 批量传输 为了在你的设备上
使用
批量传输,你应该获得为你的USB设备获得一个设备句柄,并且你应该知道
使用
哪个端点(从之前设备说明获得)。 关于语法上的信息参考这里(http://
libusb
.sourceforge.net/api-1.0/group__syncio.html#gab8ae853ab492c22d707241dc26c8a805) 这里有个简单的例子包含所有我提到的相关部分: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 #include
#include <
libusb
.h> using namespace std; int main() {
libusb
_
device
**devs; //pointer to pointer of
device
, used to retrieve a list of
device
s
libusb
_
device
_handle *dev_handle; //a
device
handle
libusb
_context *ctx =
NULL
; //a
libusb
session int r; //for return values ssize_t cnt; //holding number of
device
s in list r =
libusb
_init(&ctx;); //initialize the library for the session we just declared if(r < 0) { cout<<"Init Error "<
libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation cnt =
libusb
_get_
device
_list(ctx, &devs;); //get the list of
device
s if(cnt < 0) { cout<<"Get
Device
Error"<
Devices in list."<
libusb_
open
_
device
_with_
vid
_
pid
(ctx, 5118, 7424); //these are vendorID and productID I found for my usb
device
if(dev_handle ==
NULL
) cout<<"Cannot
open
device
"<
Device
Open
ed"<
libusb_free_
device
_list(devs, 1); //free the list, unref the
device
s in it unsigned char *data = new unsigned char[4]; //data to write data[0]='a';data[1]='b';data[2]='c';data[3]='d'; //some dummy values int actual; //used to find out how many bytes were written if(
libusb
_kernel_driver_active(dev_handle, 0) == 1) { //find out if kernel driver is attached cout<<"Kernel Driver Active"<
libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it cout<<"Kernel Driver Detached!"<
libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of
device
(mine had jsut 1) if(r < 0) { cout<<"Cannot Claim Interface"<
"<
libusb_bulk_transfer(dev_handle, (2 |
LIBUSB
_ENDPOINT_OUT), data, 4, &actual;, 0); //my
device
's out endpoint was 2, found with trial- the
device
had 2 endpoints: 2 and 129 if(r == 0 && actual == 4) //we wrote the 4 bytes successfully cout<<"Writing Successful!"<
libusb_release_interface(dev_handle, 0); //release the claimed interface if(r!=0) { cout<<"Cannot Release Interface"<
libusb_close(dev_handle); //close the
device
we
open
ed
libusb
_exit(ctx); //needs to be called to end the delete[] data; //delete the allocated memory for data return 0; } 结尾:这个教程对于这个话题来说是十分简单的介绍,需要时间需联系同步传输,然后移动是异步的,这还有很多需要学习。 希望这些对你的初学有帮助。
Qt5下windows主机的usb上位机开发第三方库文件亲测可用(
libusb
)
windows下开发usb上位机的第三方库文件,亲测可用,由于库本身的原因,是无法支持HID类设备,如果需要开发HID类设备,请查看另一篇文章,HID设备第三方库
基于
libUsb
库实现Hid USB设备通讯
OnInitDialog()下添加如下代码: struct usb_bus *busses, *bus; // usb_dev_handle *handle =
NULL
; //这个需定义为全局变量,在读线程中也许
使用
usb_init(); usb_find_busses(); usb_find_
device
s(); busses = usb_get_busses(); for(bus = busses; bus; bus = bus->next) { struct usb_
device
*dev;
LibUsb
DotNet 例程
这是
使用
LibUsb
DotNet的例程。通过该例程,你可以学会简单的
使用
libusb
来打开和关闭设备,并通过usb来调用读取和写入数据。
安卓开发板
使用
libusb
,遇到了
open
_
device
_with_
vid
_
pid
()错误,但是
libusb
_init()成功
定位为libsub版本问题,本人用的是libsub1.0.23版本时遇到上述问题,后将
libusb
版本更改为1.0.20后
解决
问题,如有朋友遇到类似问题,可以尝试更改
libusb
版本,可能会出现奇效! ...
Windows SDK/API
1,222
社区成员
8,135
社区内容
发帖
与我相关
我的任务
Windows SDK/API
C++ Builder Windows SDK/API
复制链接
扫一扫
分享
社区描述
C++ Builder Windows SDK/API
社区管理员
加入社区
获取链接或二维码
近7日
近30日
至今
加载中
查看更多榜单
社区公告
暂无公告
试试用AI创作助手写篇文章吧
+ 用AI写文章