前面已经完成了libusb开发环境和搭建和界面的设计,现在开始就可以进行业务逻辑部分设计了。首先我们需要获取到当前的USB设备信息,然后用户选择对应的设备进行后续的操作。本文先完成获取设备信息这一步,获取到设备后可以通过下拉框进行选择。
考虑到用户可以随时获取设备信息,所以在设备打开前添加一个刷新设备的按钮。
如下在设备这里的horizontal layout中添加一个按钮,layoutstretch改为1,16,4,4.
我们的需求是按刷新设备按键时,设备的下拉框自动更新显示当前的设备信息。
根据以上信息我们需要能获取到设备信息,于是我们来实现对应的接口。
文件-New File..->创建c源文件
指定文件名
点击完成
同样创建一个usbdev.h文件。
我们参考examples/listdevs.c
首先我们需要初始化libusb上下文环境,调用接口libusb_init_context, 而最后需要释放环境,调用libusb_exit.所以我们提供一个初始化和解除初始化的接口,分别在程序开始运行和退出运行时调用。
int usbdev_init(void)
{
int r;
r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
if (r < 0)
{
return r;
}
}
int usbdev_deinit(void)
{
libusb_exit(NULL);
return 0;
}
通过libusb_get_device_list获取设备信息
使用全局变量libusb_device **s_devs;记录设备句柄。
libusb_get_device_list更新上述句柄。
libusb_get_device_descriptor获取描述符信息
libusb_get_port_numbers获取端口信息
将上述获取的信息使用snprintf转为字符串,存储在全局变量
char s_devs_str[MAX_DEVS][MAX_DEVS_STR_LEN];中
提供接口usbdev_get_device_list实现如下
int usbdev_get_device_list(void)
{
ssize_t cnt;
cnt = libusb_get_device_list(NULL, &s_devs);
if (cnt < 0)
{
//libusb_exit(NULL);
return (int) cnt;
}
libusb_device *dev;
int i = 0, j = 0;
uint8_t path[8];
memset(path,0,sizeof(path));
memset(s_devs_str,0,sizeof(s_devs_str));
s_devs_num = 0;
while ((dev = s_devs[i]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
fprintf(stderr, "failed to get device descriptor");
return -1;
}
printf("%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)
{
printf(" path: %d", path[0]);
for (j = 1; j < r; j++)
printf(".%d", path[j]);
}
printf("\n");
snprintf(s_devs_str[i],MAX_DEVS_STR_LEN,"%04x:%04x (bus %d, device %d) path: %d .%d .%d .%d .%d .%d .%d .%d",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev),
path[0],path[1],path[2],path[3],path[4],path[5],path[6],path[7]);
i++;
s_devs_num++;
}
libusb_free_device_list(s_devs, 1);
}
提供接口usbdev_get_device_num获取设备个数
int usbdev_get_device_num(void)
{
return s_devs_num++;
}
提供接口usbdev_get_device_name获取对应设备的字符串信息
char* usbdev_get_device_name(int index)
{
if(index >= s_devs_num)
{
return 0;
}
else
{
return s_devs_str[index];
}
}
完整的usbdev.如下
char s_devs_str[MAX_DEVS][MAX_DEVS_STR_LEN];
libusb_device **s_devs;
int s_devs_num = 0;
int usbdev_init(void)
{
int r;
r = libusb_init_context(/*ctx=*/NULL, /*options=*/NULL, /*num_options=*/0);
if (r < 0)
{
return r;
}
}
int usbdev_deinit(void)
{
libusb_exit(NULL);
return 0;
}
int usbdev_get_device_num(void)
{
return s_devs_num++;
}
char* usbdev_get_device_name(int index)
{
if(index >= s_devs_num)
{
return 0;
}
else
{
return s_devs_str[index];
}
}
int usbdev_get_device_list(void)
{
ssize_t cnt;
cnt = libusb_get_device_list(NULL, &s_devs);
if (cnt < 0)
{
//libusb_exit(NULL);
return (int) cnt;
}
libusb_device *dev;
int i = 0, j = 0;
uint8_t path[8];
memset(path,0,sizeof(path));
memset(s_devs_str,0,sizeof(s_devs_str));
s_devs_num = 0;
while ((dev = s_devs[i]) != NULL)
{
struct libusb_device_descriptor desc;
int r = libusb_get_device_descriptor(dev, &desc);
if (r < 0)
{
fprintf(stderr, "failed to get device descriptor");
return -1;
}
printf("%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)
{
printf(" path: %d", path[0]);
for (j = 1; j < r; j++)
printf(".%d", path[j]);
}
printf("\n");
snprintf(s_devs_str[i],MAX_DEVS_STR_LEN,"%04x:%04x (bus %d, device %d) path: %d .%d .%d .%d .%d .%d .%d .%d",
desc.idVendor, desc.idProduct,
libusb_get_bus_number(dev), libusb_get_device_address(dev),
path[0],path[1],path[2],path[3],path[4],path[5],path[6],path[7]);
i++;
s_devs_num++;
}
libusb_free_device_list(s_devs, 1);
}
完整的usbdev.h如下
extern "C" {
int usbdev_init(void);
int usbdev_deinit(void);
int usbdev_get_device_num(void);
char* usbdev_get_device_name(int index);
int usbdev_get_device_list(void);
}
以上实现了相关的接口,现在开始和UI进行交互,首先在程序运行时要初始化上下文,
程序结束时解除初始化上下文。
mainwindow.cpp中
#include "usbdev.h"
我们在mainwindow的构造函数调用时初始化usb上下文
MainWindow::MainWindow(QWidget *parent)中添加
usbdev_init();
析构时解除初始化usb上下文
MainWindow::~MainWindow()中
usbdev_deinit();
在按键”刷新设备”按钮时调用usbdev_get_device_list刷新设备信息,并通过usbdev_get_device_num获取设备个数,通过usbdev_get_device_name获取设备信息添加到下拉框中。
右键点击ui设计界面的”刷新设备”按钮->转到槽...
点击clicked()方法->确定
mainwindow.cpp中自动添加以下方法
void MainWindow::on_pushButton_8_clicked()
{
}
我们添加实现代码
void MainWindow::on_pushButton_8_clicked()
{
int devsnum = 0;
char* devstr = 0;
usbdev_get_device_list();
devsnum = usbdev_get_device_num();
ui->comboBox->clear();
for(int i=0; i
{
devstr = usbdev_get_device_name(i);
if(devstr == 0)
{
break;
}
else
{
ui->comboBox->addItems(QStringList(devstr));
}
}
}
完整的mainwindow.cpp如下
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
usbdev_init();
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
usbdev_deinit();
delete ui;
}
void MainWindow::on_pushButton_8_clicked()
{
int devsnum = 0;
char* devstr = 0;
usbdev_get_device_list();
devsnum = usbdev_get_device_num();
ui->comboBox->clear();
for(int i=0; i
{
devstr = usbdev_get_device_name(i);
if(devstr == 0)
{
break;
}
else
{
ui->comboBox->addItems(QStringList(devstr));
}
}
}
运行点击刷新设备,获取到设备信息如下
打印如下
以上实现了设备信息的获取,我们下一步继续进行设备的打开与关闭操作。