当前位置:   article > 正文

C语言调用libusb访问USB驱动

libusb

目录

一、环境搭建

1. 下载库文件

2. 解压

3. 配置VS工程

3.1 头文件的配置

3.2 静态库文件的处理

3.3 配置运行时库

二、生成自定义设备的驱动

1. 禁用Windows驱动程序强制签名

2. 设备描述符的设计

3. 设备枚举

4. 如何为自己的设备安装WinUSB驱动

三、测试

1. 测试代码

2. 小结


一、环境搭建

开发环境:win10/64位、VS2019企业版(Microsoft Visual Studio Enterprise 2019)

1. 下载库文件

先不关心源码,直接下载库文件,然后配置VS2019引用库文件即可。libusb-1.0.20下载地址:

https://udomain.dl.sourceforge.net/project/libusb/libusb-1.0/libusb-1.0.20/libusb-1.0.20.7z

2. 解压

解压之后,需要关注这两个个目录:

3. 配置VS工程

新建工程:略。如下,新建一个C工程,命名为test_for_usb。

 接下来要配置这个工程使用库(xxx.lib)文件。

3.1 头文件的配置

(1) 将解压目录里面的libusb.h拷贝到当前工程目录下

(2) 配置附加包含目录

添加libusb.h的路径(实际上就是当前工程的路径) 到“附加包含目录中”。

工程右键--->属性--->C/C++--->常规--->附加包含目录。最后单击“应用”按钮结束配置。

(3)将头文件添加到工程中

头文件--->添加--->现有项--->选择libusb.h

3.2 静态库文件的处理

(1)库文件的拷贝

对于64位的系统,选择MS64目录。将libusb-1.0.20\MS64\dll\下的libusb-1.0.lib文件复制到当前工程目录下:

(2)将libusb-1.0.lib添加到“附加依赖项”。

右键工程--->配置属性--->链接器--->输入--->附加依赖项。最后单击“确定”和“应用”结束配置。

(3)将libusb-1.0.lib所在目录添加到“附加库目录”

libusb-1.0.lib所在目录实际上就是当前工程所在目录。

右键工程--->配置属性--->链接器--->常规--->附加库目录。最后单击“确定”和“应用”结束配置。

3.3 配置运行时库

使用静态版本的libusb库,那么就要把“运行时库”设置为“多线程DLL(/MD)”。

右键工程--->配置属性--->C/C++--->代码生成--->运行库。最后单击“确定”和“应用”结束配置。

 注意:以上的所有配置,包括库文件的选择,都是针对64位平台(X64)的。

二、生成自定义设备的驱动

1. 禁用Windows驱动程序强制签名

如果不禁用Windows驱动程序强制签名,在安装自定义的驱动时,可能会碰到这个问题:

“System policy has been modified to reject unsigned drivers”,如下图。

 禁用驱动程序强制签名即可。以win10为例,解决过程:Win10怎么禁用驱动程序强制签名-百度经验 (baidu.com)

2. 设备描述符的设计

针对环境搭建,设计了一个简单的USB设备。设备实现Bulk传输,除控制传输端点0外,还有Bulk-IN1和Bulk-OUT2两个数据传输端点。把PID和VID都设计为0x10e6,设备描述符中的设备类、子类和协议都设置为0, 接口描述符中对应的三个字段都设置为0xff,表示这是一个自定义的设备(不使用MSC协议)。

附:设备描述符

---===>Device Information<===---

ConnectionStatus:                  
Current Config Value:              0x01  -> Device Bus Speed: High
Device Address:                    0x07
Open Pipes:                           2

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0200 = 0x200 max bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0200 = 0x200 max bytes
bInterval:                         0x00

          ===>Device Descriptor<===
bLength:                           0x12
bDescriptorType:                   0x01
bcdUSB:                          0x0200
bDeviceClass:                      0x00  -> This is an Interface Class Defined Device
bDeviceSubClass:                   0x00
bDeviceProtocol:                   0x00

bMaxPacketSize0:                   0x40 = (64) Bytes
idVendor:                        0x10E6 
idProduct:                       0x10E6

bcdDevice:                       0x0100
iManufacturer:                     0x00
iProduct:                          0x00
iSerialNumber:                     0x00
bNumConfigurations:                0x01

          ===>Configuration Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x02
wTotalLength:                    0x0020  -> Validated
bNumInterfaces:                    0x01
bConfigurationValue:               0x01
iConfiguration:                    0x00
bmAttributes:                      0x80  -> Bus Powered
MaxPower:                          0x96 = 300 mA

          ===>Interface Descriptor<===
bLength:                           0x09
bDescriptorType:                   0x04
bInterfaceNumber:                  0x00
bAlternateSetting:                 0x00
bNumEndpoints:                     0x02
bInterfaceClass:                   0xFF  -> Vendor Specific Device
bInterfaceSubClass:                0xFF
*!*CAUTION:    This appears to be an invalid bInterfaceSubClass
bInterfaceProtocol:                0xFF
*!*WARNING:  must be set to PC_PROTOCOL_UNDEFINED 0 for this class
iInterface:                        0x00
*!*ERROR:  0xFF is the prerelease USB Video Class ID

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x81  -> Direction: IN - EndpointID: 1
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0200 = 0x200 max bytes
bInterval:                         0x00

          ===>Endpoint Descriptor<===
bLength:                           0x07
bDescriptorType:                   0x05
bEndpointAddress:                  0x02  -> Direction: OUT - EndpointID: 2
bmAttributes:                      0x02  -> Bulk Transfer Type
wMaxPacketSize:                  0x0200 = 0x200 max bytes
bInterval:                         0x00
 

3. 设备枚举

USB设备插入PC,控制传输枚举阶段结束,设备管理器出现“未知设备”。

这个设备比较简单,设备端只需要处理几条控制传输指令(bulk传输指令可以不理会,事实上由于描述符有几个字段设置的原因,HOST也不会下发相关的SCSI指令)即可。如下:

4. 如何为自己的设备安装WinUSB驱动

需要下载Zadig,Zadig是一个Windows平台上专门用于安装USB相关驱动的小软件,下载后解压即可。连接如下:

https://udomain.dl.sourceforge.net/project/libusb-win32/libusb-win32-releases/1.2.6.0/libusb-win32-bin-1.2.6.0.zip

复制后,打开浏览器即可自动下载,如下图:

 解压之后,在bin目录下有可执行文件inf-wizard.exe

 选择自己这个未知的设备:

 注意:对应设备描述符中的VID和PID

厂商名称和设备名称可以自由填写

 找个目录保存生成的xxx.inf文件之后,开始安装驱动。

安装中

安装成功:

 驱动安装成功后,再查看设备管理器,设备驱动就正常了:

接下来libusb就可以访问设备了。

三、测试

1. 测试代码

main.c

#include <stdio.h>

#include "libusb.h"

int main(void)

{

    int res;

    struct libusb_device_handle* usb_handle = NULL;

    struct libusb_device* usb_dev = NULL;

    struct libusb_device_descriptor dev_desc;

    libusb_init(NULL);

    usb_handle = libusb_open_device_with_vid_pid(NULL, 0x10e6, 0x10e6);

    if (usb_handle != NULL) {

        usb_dev = libusb_get_device(usb_handle);

        if (usb_dev != NULL) {

            //get device descriptor

            res = libusb_get_device_descriptor(usb_dev, &dev_desc);

            if (res == 0) {

                printf("get device desc success\n");

                printf("bLength:0x%02x\n", dev_desc.bLength);

                printf("bDescriptorType:0x%02x\n", dev_desc.bDescriptorType);

                printf("bcdUSB:0x%04x\n", dev_desc.bcdUSB);

                printf("bDeviceClass:0x%02x\n", dev_desc.bDeviceClass);

            } else {

                printf("fail to get device desc\n");

                libusb_close(usb_handle);

            }

        }

    } else {

        printf("can not find device:0x1010\n");

    }

    libusb_exit(NULL);

    return 0;

}

运行如下:

程序可以访问USB驱动,并获取相关设备信息。接下来要实现数据的读写。

2. 小结

(1)配置VS,使用到的资源文件是libusb.h和libusb-1.0.lib

(2)整个环境搭建,会使用到这两个资源包

(3)关于驱动程序的编写和测试要有USB设备的配合。

关于libusb的详细API介绍和使用例程,官网Spec链接为:

libusb: libusb-1.0 API Reference

下一篇:实现Bulk数据双向传输。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/2023面试高手/article/detail/711481
推荐阅读
相关标签
  

闽ICP备14008679号