前面我们已经完成了控制传输部分的开发,现在继续进行端点相关的传输部分开发。先实现接口和端点信息的解析,以便用户选择某个接口下的某个端点进行收发。
参考libusb_get_active_config_descriptor()获取描述符信息,然后进行解析,注意使用完需要调用libusb_free_config_descriptor释放资源。
使用变量s_interface_num记录接口数,一个接口下的不同alt接口算不同的接口。
定义结构体 usbddev_interface_info_st记录接口和端点信息。
定义全局数组 s_interface_info记录接口和端点信息,最大可记录MAX_INTERFACE 个接口
每个接口最大MAX_ENDPOINTS 个端点。
Usbdev.c提供数据结构如下:
int s_interface_num = 0; /* 打开的设备的接口数 */
/**
* 记录接口信息结构体
*/
typedef struct
{
int interfacenumber;
int alternateSetting;
int numendpoints;
struct libusb_endpoint_descriptor endpoints[MAX_ENDPOINTS];
} usbddev_interface_info_st;
usbddev_interface_info_st s_interface_info[MAX_INTERFACE];
Usbdev.c提供获取接口和端点信息接口实现如下
int usbdev_update_interface_endpoint_list(void)
{
struct libusb_config_descriptor * config;
struct libusb_interface * interface;
struct libusb_interface_descriptor* altsetting;
struct libusb_endpoint_descriptor * endpoint;
if(s_opened_dev != NULL)
{
memset(&s_interface_info,0,sizeof(s_interface_info));
if(0 == libusb_get_active_config_descriptor(s_opened_dev,&config))
{
s_interface_num = 0;
if(config != NULL)
{
interface = config->interface;
for(int i=0; i< config->bNumInterfaces; i++)
{
for(int j=0; j
{
altsetting = interface[i].altsetting;
s_interface_info[s_interface_num].interfacenumber = altsetting[j].bInterfaceNumber;
s_interface_info[s_interface_num].alternateSetting = altsetting[j].bAlternateSetting;
s_interface_info[s_interface_num].numendpoints = altsetting[j].bNumEndpoints;
for(int k=0; k
{
endpoint = altsetting[j].endpoint;
s_interface_info[s_interface_num].endpoints[k] = endpoint[k];
}
s_interface_num++;
}
}
libusb_free_config_descriptor(config);
}
}
else
{
return -2;
}
}
else
{
return -1;
}
return 0;
}
Usbdev.c提供以下接口获取接口数和接口的id
int usbdev_get_interface_num(void)
{
return s_interface_num;
}
int usbdev_get_in_interface_id(int itf_index, int* interface, int* altsetting)
{
if(itf_index >= s_interface_num)
{
return -1;
}
*interface = s_interface_info[itf_index].interfacenumber;
*altsetting = s_interface_info[itf_index].alternateSetting;
return 0;
}
Usbdev.c提供以下信息获取指定接口的端点数和端点信息
int usbdev_get_endpoint_num(int itf_index)
{
if(itf_index >= s_interface_num)
{
return -1;
}
return s_interface_info[itf_index].numendpoints;
}
int usbdev_get_endpoint_info(int itf_index, int ep_index, int* address, int* type, int* mps)
{
struct libusb_endpoint_descriptor* endpoint;
if(itf_index >= s_interface_num)
{
return -1;
}
if(ep_index >= s_interface_info[itf_index].numendpoints)
{
return -1;
}
endpoint = s_interface_info[itf_index].endpoints;
*address = endpoint[ep_index].bEndpointAddress;
*type = endpoint[ep_index].bmAttributes;
*mps = endpoint[ep_index].wMaxPacketSize;
return 0;
}
Usbdev.h中声明接口
int usbdev_update_interface_endpoint_list(void);
int usbdev_get_interface_num(void);
int usbdev_get_in_interface_id(int itf_index, int* interface, int* altsetting);
int usbdev_get_endpoint_num(int itf_index);
int usbdev_get_endpoint_info(int itf_index, int ep_index, int* address, int* type, int* mps);
打开设备时,接口下拉框中显示接口信息,关闭设备时清除接口显示
打开按钮的处理函数下添加
void MainWindow::on_pushButton_clicked()
{
int index = ui->comboBox->currentIndex();
if(index < 0)
{
return;
}
if(0 == usbdev_get_openstatus())
{
printf("to open dev %d\r\n",index);
if(0 == usbdev_open(index))
{
ui->pushButton->setText("关闭");
/* 这里更新显示接口下拉框的内容 */
ui->comboBox_3->clear();
ui->comboBox_4->clear();
ui->comboBox_2->clear();
ui->comboBox_5->clear();
usbdev_update_interface_endpoint_list(); /* 更新接口和端点信息 */
int int_num = usbdev_get_interface_num();
int itf_id;
int alt_id;
for(int i = 0; i
{
if(0 == usbdev_get_in_interface_id(i,&itf_id,&alt_id))
{
QString itfstr= QString::number(i)+":"+QString::number(itf_id)+":"+QString::number(alt_id);
ui->comboBox_3->addItems(QStringList(itfstr));
ui->comboBox_4->addItems(QStringList(itfstr));
}
}
}
}
else
{
usbdev_close();
ui->pushButton->setText("打开");
/* 这里清除显示接口下拉框的内容 */
ui->comboBox_3->clear();
ui->comboBox_4->clear();
ui->comboBox_2->clear();
ui->comboBox_5->clear();
}
}
右键点击ui界面的下拉框->转为槽
添加activated事件处理函数
void MainWindow::on_comboBox_3_activated(int index)
{
}
实现如下
void MainWindow::on_comboBox_3_activated(int index)
{
int epnum = usbdev_get_endpoint_num(index);
ui->comboBox_2->clear();
for(int i=0; i< epnum; i++)
{
int address;
int type;
int mps;
if(0 == usbdev_get_endpoint_info(index, i, &address, &type, &mps))
{
QString epstr= QString::number(i)+":"+
QString("%1").arg(address & 0xFF, 2, 16, QLatin1Char('0'))+":"+
QString("%1").arg(mps & 0xFF, 2, 16, QLatin1Char('0'))+":";
switch(type & 0x03)
{
case 0:
epstr = epstr + "CTRL";
break;
case 1:
epstr = epstr + "ISOC";
break;
case 2:
epstr = epstr + "BULK";
break;
case 3:
epstr = epstr + "INT";
break;
}
ui->comboBox_2->addItems(QStringList(epstr));
}
}
}
同样的接收区添加
void MainWindow::on_comboBox_4_activated(int index)
{
}
实现如下
void MainWindow::on_comboBox_4_activated(int index)
{
int epnum = usbdev_get_endpoint_num(index);
ui->comboBox_5->clear();
for(int i=0; i< epnum; i++)
{
int address;
int type;
int mps;
if(0 == usbdev_get_endpoint_info(index, i, &address, &type, &mps))
{
QString epstr= QString::number(i)+":"+
QString("%1").arg(address & 0xFF, 2, 16, QLatin1Char('0'))+":"+
QString("%1").arg(mps & 0xFF, 2, 16, QLatin1Char('0'))+":";
switch(type & 0x03)
{
case 0:
epstr = epstr + "CTRL";
break;
case 1:
epstr = epstr + "ISOC";
break;
case 2:
epstr = epstr + "BULK";
break;
case 3:
epstr = epstr + "INT";
break;
}
ui->comboBox_5->addItems(QStringList(epstr));
}
}
}
打开设备接口显示
关闭设备接口清除显示
显示信息和UsbTreeView看到的美剧信息一致,0:0接口下面3个端点
以上完成了接口和端点信息的解析,后面就可以选择端点,进行对应的传输了。