This repository has been archived on 2025-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
libUSB_upper/usbhandler.cpp
2025-05-14 21:36:17 +08:00

301 lines
9.8 KiB
C++

#include "usbhandler.h"
UsbHandler::UsbHandler(QObject *parent) : QObject(parent), context(nullptr), deviceList(nullptr), deviceCount(0), handle(nullptr)
{
// Initialize libusb context
if (libusb_init(&context) < 0) {
emit errorOccurred("Failed to initialize libusb.");
}
}
UsbHandler::~UsbHandler()
{
if (handle) {
libusb_close(handle);
}
if (deviceList) {
libusb_free_device_list(deviceList, 1);
}
libusb_exit(context);
}
bool UsbHandler::initialize()
{
// Initialize the libusb context and check for errors
if (libusb_init(&context) < 0) {
emit errorOccurred("Failed to initialize libusb.");
return false;
}
return true;
}
void UsbHandler::listDevices()
{
// Retrieve the list of connected USB devices
deviceCount = libusb_get_device_list(context, &deviceList);
if (deviceCount < 0) {
emit errorOccurred("Failed to get USB device list.");
return;
}else{
productList = new QMap<int,QString>[deviceCount];
}
for (ssize_t i = 0; i < deviceCount; ++i) {
productList->insert(i,printDeviceInfo(deviceList[i]));
// Optionally add more detailed device information here
}
emit productListUpdate(productList);
}
bool UsbHandler::openDevice(int deviceIndex)
{
if (deviceIndex < 0 || deviceIndex >= deviceCount) {
emit errorOccurred("Invalid device index.");
return false;
}
// Open the selected device
libusb_device_handle *devHandle;
int status = libusb_open(deviceList[deviceIndex], &devHandle);
if (status < 0) {
emit errorOccurred("Failed to open USB device.");
return false;
}
// Store the device handle for further operations
handle = devHandle;
LOG_DEBUG("open deviceindex %d success",deviceIndex);
return true;
}
bool UsbHandler::sendControlTransfer(uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, uint8_t *data, uint16_t length)
{
if (handle == nullptr) {
emit errorOccurred("No device handle.");
return false;
}
int status = libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, length, 1000);
if (status < 0) {
emit errorOccurred("Control transfer failed.");
return false;
}
return true;
}
bool UsbHandler::sendBulkTransfer(uint8_t endpoint, uint8_t *data, int length)
{
if (handle == nullptr) {
emit errorOccurred("No device handle.");
return false;
}
int actualLength;
int status = libusb_bulk_transfer(handle, endpoint, data, length, &actualLength, 1000);
if (status < 0) {
emit errorOccurred("Bulk transfer failed.");
return false;
}
return true;
}
//主要用在数据读,从设备到主机
// bool UsbHandler::sendInterruptTransfer(uint8_t endpoint, uint8_t *data, int length)
// {
// if (handle == nullptr) {
// emit errorOccurred("No device handle.");
// return false;
// }
// int actualLength;
// int status = libusb_interrupt_transfer(handle, endpoint, data, length, &actualLength, 1000);
// if (status < 0) {
// emit errorOccurred("Interrupt transfer failed.");
// return false;
// }
// return true;
// }
bool UsbHandler::sendAsyncTransfer(uint8_t endpoint, uint8_t *data, int length)
{
if (handle == nullptr) {
emit errorOccurred("No device handle.");
return false;
}
// 1. 创建 libusb_transfer 对象
libusb_transfer *transfer = libusb_alloc_transfer(0); // 0 表示默认的最大传输包大小
if (transfer == nullptr) {
emit errorOccurred("Failed to allocate transfer.");
return false;
}
// 2. 设置传输类型和参数
if (endpoint & LIBUSB_ENDPOINT_IN) { // 如果是输入端点 (IN)
libusb_fill_bulk_transfer(transfer, handle, endpoint, data, length,
[](libusb_transfer *transfer) {
// 回调函数,当传输完成时调用
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
LOG_DEBUG("Async Transfer completed successfully.");
} else {
LOG_ERROR("Async Transfer failed with status:0x%x",transfer->status);
}
libusb_free_transfer(transfer); // 释放传输资源
}, nullptr, 0);
} else { // 如果是输出端点 (OUT)
libusb_fill_bulk_transfer(transfer, handle, endpoint, data, length,
[](libusb_transfer *transfer) {
// 回调函数,当传输完成时调用
if (transfer->status == LIBUSB_TRANSFER_COMPLETED) {
LOG_DEBUG("Async Transfer completed successfully.");
} else {
LOG_ERROR("Async Transfer failed with status:0x%x",transfer->status);
}
libusb_free_transfer(transfer); // 释放传输资源
}, nullptr, 0);
}
// 3. 提交传输
int status = libusb_submit_transfer(transfer);
if (status < 0) {
emit errorOccurred("Failed to submit async transfer.");
libusb_free_transfer(transfer);
return false;
}
libusb_handle_events(context); // 确保事件循环能处理异步传输
return true;
}
QString UsbHandler::printDeviceInfo(libusb_device *device)
{
libusb_device_descriptor desc;
QString tmp={};
if (libusb_get_device_descriptor(device, &desc) == 0) {
tmp= "Vendor ID: 0x"+QString::number(desc.idVendor,16)+",Product ID: 0x"+QString::number(desc.idProduct,16);
LOG_DEBUG("Vendor ID: 0x%x, Product ID: 0x%x", desc.idVendor, desc.idProduct);
} else {
LOG_ERROR("Failed to retrieve device descriptor.");
}
return tmp;
}
void UsbHandler::listInterfaces(int deviceIndex) {
if (deviceIndex < 0 || deviceIndex >= deviceCount) {
emit errorOccurred("无效的设备索引");
return;
}
libusb_device *device = deviceList[deviceIndex];
libusb_config_descriptor *config = nullptr;
if (libusb_get_active_config_descriptor(device, &config) != 0) {
emit errorOccurred("获取配置描述符失败");
return;
}
LOG_DEBUG("接口总数: %d",config->bNumInterfaces);
interfaceList = new QMap<int,QString>[config->bNumInterfaces];
for (int i = 0; i < config->bNumInterfaces; ++i) {
const libusb_interface &interface = config->interface[i];
QString tmp;
for (int j = 0; j < interface.num_altsetting; ++j) {
const libusb_interface_descriptor &alt = interface.altsetting[j];
tmp += QString("Interface #[%1]: %2, Class: %3, SubClass: %4, Protocol: %5")
.arg(i)
.arg(alt.bInterfaceNumber)
.arg(alt.bInterfaceClass)
.arg(alt.bInterfaceSubClass)
.arg(alt.bInterfaceProtocol);
}
interfaceList->insert(i, tmp);
}
libusb_free_config_descriptor(config);
emit interfaceListUpdate(interfaceList);
}
void UsbHandler::listInterfaceEndpoints(int deviceIndex, int interfaceNumber) {
LOG_DEBUG("devivceIdx is %d,interfaceiIdx is %d",deviceIndex,interfaceNumber);
if (deviceIndex < 0 || deviceIndex >= deviceCount) {
qDebug() << "无效的设备索引";
return;
}
libusb_device *device = deviceList[deviceIndex];
libusb_config_descriptor *config = nullptr;
if (libusb_get_active_config_descriptor(device, &config) != 0) {
qDebug() << "获取配置描述符失败";
return;
}
if (interfaceNumber < 0 || interfaceNumber >= config->bNumInterfaces) {
qDebug() << "无效的接口编号";
libusb_free_config_descriptor(config);
return;
}
const libusb_interface &interface = config->interface[interfaceNumber];
if (interface.num_altsetting < 1) {
qDebug() << "接口无 altsetting";
libusb_free_config_descriptor(config);
return;
}
endPointList = new QMap<int, QString>;
for(int j=0;j<interface.num_altsetting;j++){
const libusb_interface_descriptor &alt = interface.altsetting[j];
for (int k = 0; k < alt.bNumEndpoints; ++k) {
const libusb_endpoint_descriptor &ep = alt.endpoint[k];
QString epTypeStr;
switch (ep.bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) {
case LIBUSB_TRANSFER_TYPE_CONTROL: epTypeStr = "Control"; break;
case LIBUSB_TRANSFER_TYPE_ISOCHRONOUS: epTypeStr = "Isochronous"; break;
case LIBUSB_TRANSFER_TYPE_BULK: epTypeStr = "Bulk"; break;
case LIBUSB_TRANSFER_TYPE_INTERRUPT: epTypeStr = "Interrupt"; break;
default: epTypeStr = "Unknown"; break;
}
QString direction = (ep.bEndpointAddress & LIBUSB_ENDPOINT_IN) ? "IN" : "OUT";
QString info= QString("Endpoint 0x%1 (%2, %3), MaxPacketSize: %4")
.arg(ep.bEndpointAddress, 2, 16, QChar('0'))
.arg(direction)
.arg(epTypeStr)
.arg(ep.wMaxPacketSize);
endPointList->insert(k, info);
}
}
libusb_free_config_descriptor(config);
emit endPointListUpdate(endPointList);
}
bool UsbHandler::closeDevice() {
if (handle) {
libusb_close(handle);
handle = nullptr;
LOG_DEBUG("设备关闭成功");
return true;
} else {
LOG_DEBUG("无打开的设备");
return false;
}
}