win7基于libusb在QT中实现USB通讯

第一次写这种文章,不清晰的地方请帮忙指出
QT环境准备
引言
PC环境:window7
网上很多QT的USB访问,使用的是MCVS的环境,我一番使用下来遇到很多问题,
使用C#写USB驱动需要用到LIBUSBDONET这个库,但是这个库需要手动使用内部的工具生成驱动上位机才能访问到,但是我的是标准的HID设备且每次使用都需要安装一下驱动不太适合,所以改用QT使用libusb这个库来绕开这一步直接访问我的HID设备。
做的过程中发现libusb也分好几种方法,像hidapi这个库虽然很方便,但是在WIN7系统上,hid_write方法总是会失败而hid_read正常,查了很久的资料也找不到解决问题的方法。
Libusb0.h这个库也是需要手动用inf-wizard.exe生成驱动之后上位机才能识别,且此工具会更改USB设备的枚举,我的设备正常枚举是这样
在这里插入图片描述

经过inf-wizard.exe生成后,HID这个接口消失,卸载了好几遍驱动才恢复回来。
环境介绍
最后选用libusb1.0这个库
配套的头文件是libusb.h
win7基于libusb在QT中实现USB通讯_第1张图片

QT使用的环境是5.15.2MinGw32bit,MinGw实际上就是GCC编译,所以对应使用后缀.a的lib
win7基于libusb在QT中实现USB通讯_第2张图片

PS:如果使用MCVS的编译器,记得选用liusb-1.0.lib的静态库,最好是32位的。

在QT中导入LIBUSB
我这边的QT是需要ui界面的,所以新建了一个标准的mainwindow的工程,文件结构是
1.放置了需要引用的.a文件和.h文件
2.QT的工程文件
win7基于libusb在QT中实现USB通讯_第3张图片

打开对应的.pro文件,导入libUSB的库,是通过路径索引的方法,导入的方法很多,还是推荐直接填写路径的方法,因为-L的方法有时候会出错,看个人选用。

这种导入.h的方法就不需要在Headers文件中再次导入我们的libusb.h文件直接在代码中
#Include”libusb.h”就可以了,如图所示。
win7基于libusb在QT中实现USB通讯_第4张图片

QT代码部分
USB初始化
1.初始化
在窗口生成的时候,放入USB初始化的语句,若初始化成功,则res变量值为0,这一步如果出现函数解析错误的报错,就需要检查当前libusb库是否跟编译对应,或者将libusb重新生成一遍。

然后对应在窗口关闭时销毁USB

#include "ui_mainwindow.h"
#include "libusb.h"
#include "self_config.h"

#include 
#include 
#include 
#include 
#include 
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    int res;
    res=libusb_init(NULL);
    ui->setupUi(this);
}

MainWindow::~MainWindow()
{
    libusb_exit(NULL);
    delete ui;
}

USB打印设备
打印所有USB设备,这一步可以检查上位机是否能访问到现在PC上接入的USB设备,如果就要检查是否使用到libusb0.h这种库,因为网上搜索libusb也会搜索到libusb0.h这种库,但是库里面函数名和使用的方法也不一样,几率不是很大,可以用BUS HOUND多多检查。

int find_all_of_devices(void)
{
     
    libusb_device **devs;
    ssize_t cnt;
    cnt = libusb_get_device_list(NULL, &devs);
    print_dev(devs);

}

void print_dev(libusb_device **devs)
{
     
    libusb_device *dev;
        int i = 0, j = 0;
        uint8_t path[8];

        while ((dev = devs[i++]) != NULL)
        {
     
            struct libusb_device_descriptor desc;
            int r = libusb_get_device_descriptor(dev, &desc);
            if (r < 0) {
     
                qDebug("failed to get device descriptor");
                return;
            }
        //main_show->ui->textBrowser->setText("aaaa");
#if 1
            qDebug("%04x:%04x (bus %d, device %d)",
                desc.idVendor, desc.idProduct,
                libusb_get_bus_number(dev), libusb_get_device_address(dev));

            r = libusb_get_port_numbers(dev, path, sizeof(path));
            if (r > 0) {
     
                qDebug(" path: %d", path[0]);
                for (j = 1; j < r; j++)
                    qDebug(".%d", path[j]);
            }
#endif
        }

}

Usb读写设备
测试设备介绍:
此次用测试的设备是一块新塘的板子,接入PC后枚举后可以看到有一个HID接口
在这里插入图片描述

使用libusb_open_device_with_vid_pid方法来访问我们指定的设备

void test_my_usb_devices(int vid,int pid)
{
     
    libusb_device_handle *handle;
    libusb_device *dev;
    int bus;

    struct libusb_config_descriptor *conf_desc;
    const struct libusb_endpoint_descriptor *endpoint;
    uint8_t endpoint_in = 0, endpoint_out = 0;
    int endpoint_num, nb_ifaces, altesetting = -1;
    struct libusb_ss_endpoint_companion_descriptor *ep_comp = NULL;

    uint8_t buf[63]={
     0};
    int i;
    int res;
    int size=0;

    /*打开设备*/
    handle = libusb_open_device_with_vid_pid(NULL, vid, pid);
    if (handle == NULL)
        qDebug("open devices failed");


    dev = libusb_get_device(handle);
    bus = libusb_get_bus_number(dev);
    libusb_get_config_descriptor(dev, 0, &conf_desc);
    nb_ifaces = conf_desc->bNumInterfaces;
    qDebug()<<nb_ifaces;

读取设备读、写端点

  if(nb_ifaces>0)
    {
     
        altesetting=conf_desc->interface[0].num_altsetting;
        if(altesetting>0)
        {
     
            endpoint_num=conf_desc->interface[0].altsetting[0].bNumEndpoints;
            if(endpoint_num>0)
            {
     
                for(i=0;i<endpoint_num;i++)
                {
     
                    endpoint= &conf_desc->interface[0].altsetting[0].endpoint[i];
                    if ((endpoint->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) & (LIBUSB_TRANSFER_TYPE_BULK | LIBUSB_TRANSFER_TYPE_INTERRUPT)) {
     
                        if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
     
                            if (!endpoint_in)
                                endpoint_in = endpoint->bEndpointAddress;
                        }
                        else {
     
                            if (!endpoint_out)
                                endpoint_out = endpoint->bEndpointAddress;
                        }
                    }
                }
            }
            else
                qDebug("endpoint num error");
        }
        else
        {
     
            qDebug("altsetting error");
        }

    }
    else
        qDebug("interface found error");

    /*释放配置描述符*/
    libusb_free_config_descriptor(conf_desc);
    /*卸载驱动内核*/
    libusb_set_auto_detach_kernel_driver(handle, 1);
    /*为指定的设备申请接口*/
    res=libusb_claim_interface(handle, 0);
    res<0?qDebug("claim interface error"):qDebug("claim interface success");

USB读写操作

 while (1)
    {
     
        memset(&buf[0], 0, 63);

        qDebug("Testing interrupt read using endpoint %02X...\n", endpoint_in);
        res = libusb_interrupt_transfer(handle, endpoint_in, buf, 64, &size, 1000);
        if (res >= 0) {
     
            qDebug("read ok:");
            for (uint8_t i = 0; i < 64; i++)
            {
     
                qDebug("%02x ", buf[i]);
            }

        }
        else {
     
            qDebug("   %s\n", libusb_strerror((enum libusb_error)res));
        }

        buf[0] = 0x12;
        buf[1] = 0x13;
        buf[2] = 0x14;
        buf[3] = 0x15;
        qDebug("\nTesting interrupt write using endpoint %02X...\n", endpoint_out);
        res = libusb_interrupt_transfer(handle, endpoint_out, buf, 63, &size, 1000);
        //r = libusb_interrupt_transfer(handle, endpoint_out, report_buffer, 64, &size, 1000);
        //r = libusb_interrupt_transfer(handle, endpoint_out, report_buffer, 65, &size, 1000);

        if (res >= 0) {
     
            qDebug("write ok\n");
        }
        else {
     
            qDebug("   %s\n", libusb_strerror((enum libusb_error)res));
        }
        Sleep(1000);
    }

}

最后我在按钮点击事件中调用,PID和VID可以通过BUS HOUND查看确定一下

void MainWindow::on_btn1_open_clicked()
{
     
    find_all_of_devices();
    test_my_usb_devices(0x248a,0x1239);
}

你可能感兴趣的:(QT,USB,qt,usb,window)