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

334 lines
11 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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);
LOG_DEBUG("status is %d",status);
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,int interfaceNum)
{
int status;
if (handle == nullptr) {
emit errorOccurred("No device handle.");
return false;
}
// 获取接口权限可选部分系统如Linux必须
if (libusb_kernel_driver_active(handle, interfaceNum)) {
libusb_detach_kernel_driver(handle, interfaceNum);
}
status = libusb_claim_interface(handle, interfaceNum);
if (status < 0) {
LOG_ERROR("Failed to claim interface: %d",interfaceNum);
return false;
}
int actualLength;
status = libusb_bulk_transfer(handle, endpoint, data, length, &actualLength, 1000);
if (status < 0) {
emit errorOccurred("Bulk transfer failed.");
libusb_release_interface(handle, interfaceNum);
return false;
}
libusb_release_interface(handle, interfaceNum);
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,int interfaceNum)
{
int status;
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;
}
// 获取接口权限可选部分系统如Linux必须
if (libusb_kernel_driver_active(handle, interfaceNum)) {
libusb_detach_kernel_driver(handle, interfaceNum);
}
status = libusb_claim_interface(handle, interfaceNum);
if (status < 0) {
LOG_ERROR("Failed to claim interface: %d",interfaceNum);
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. 提交传输
status = libusb_submit_transfer(transfer);
if (status < 0) {
emit errorOccurred("Failed to submit async transfer.");
libusb_free_transfer(transfer);
libusb_release_interface(handle, interfaceNum);
return false;
}
libusb_release_interface(handle, interfaceNum);
// 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;
}
}