#include #include "hiddev.h" #include HIDDev::HIDDev() : dev_handle(nullptr), ctx(nullptr), connected(false) { libusb_init(&ctx); #if USB_HOT_PLUG_SUPPORT libusb_hotplug_callback_handle handle_attach; int rc = libusb_hotplug_register_callback(ctx, static_cast( LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT), LIBUSB_HOTPLUG_NO_FLAGS, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY, hotplug_callback, this, &handle_attach); if (rc != LIBUSB_SUCCESS) { std::cout << "Error registering callback for attach event." << std::endl; libusb_exit(ctx); } std::cout << "[INFO] HIDDev using hot plug driver." << std::endl; #endif // 启动事件处理线程 usbThread = std::thread(&HIDDev::usbEventHandling, this); } HIDDev::~HIDDev() { // 通知线程结束 stopThread = true; if (usbThread.joinable()) { usbThread.join(); } closeDevice(); libusb_exit(ctx); } bool HIDDev::openDevice(int vendor_id, int product_id) { vendorId = vendor_id; productId = product_id; dev_handle = libusb_open_device_with_vid_pid(ctx, vendor_id, product_id); if (!dev_handle) { std::cerr << "Cannot open device\n"; connected = false; return false; } if (libusb_kernel_driver_active(dev_handle, 0) == 1) { // find out if kernel driver is attached printf("Kernel Driver Active\n"); if (libusb_detach_kernel_driver(dev_handle, 0) == 0) // detach it printf("Kernel Driver Detached!\n"); } if (libusb_claim_interface(dev_handle, 0) < 0) { std::cerr << "Cannot claim interface\n"; closeDevice(); return false; } connected = true; return true; } #if USB_HOT_PLUG_SUPPORT int LIBUSB_CALL HIDDev::hotplug_callback(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data) { HIDDev *self = static_cast(user_data); libusb_device_descriptor desc; if (libusb_get_device_descriptor(device, &desc) == 0) { if(self->vendorId != desc.idVendor || self->productId != desc.iProduct){ return 0; } std::cout << "Device Event: VendorID=" << desc.idVendor << ", ProductID=" << desc.idProduct << std::endl; } if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED) { self->devArrived = true; std::cout << "Device arrived." << std::endl; } else if (event == LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT) { self->connected = false; std::cout << "Device disconnected." << std::endl; } std::cout << "Device event." << std::endl; return 0; } #endif void HIDDev::closeDevice() { if (dev_handle) { libusb_release_interface(dev_handle, 0); libusb_close(dev_handle); dev_handle = nullptr; } connected = false; } int HIDDev::read(unsigned char *data, int length) { if (!connected) { return -1; } int actual_length; int res = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_IN | 1, data, length, &actual_length, 0); if (res == 0) { return actual_length; } else { if (res == LIBUSB_ERROR_NO_DEVICE) { std::cout << "Device not connected error...\n"; connected = false; reconnectFlag = true; } return -1; } } int HIDDev::write(const unsigned char *data, int length) { if (!connected) { return -1; } int actual_length; int res = libusb_bulk_transfer(dev_handle, LIBUSB_ENDPOINT_OUT | 1, const_cast(data), length, &actual_length, 0); if (res == 0) { return actual_length; } else { if (res == LIBUSB_ERROR_NO_DEVICE) { connected = false; reconnectFlag = true; } return -1; } } void HIDDev::usbEventHandling() { int completed = 0; while (!stopThread) { #if USB_HOT_PLUG_SUPPORT libusb_handle_events_completed(ctx, &completed); // 也可以加入一些线程休眠来减少CPU使用率 std::this_thread::sleep_for(std::chrono::milliseconds(100)); if(devArrived == true){ std::cout << "[INFO] Hotplug mode, Device reconnected ...\n"; tryReconnect(); devArrived = false; } #else std::this_thread::sleep_for(std::chrono::milliseconds(1000)); // 如果设备未连接,定期尝试连接设备 if(reconnectFlag && !connected){ std::cout << "[INFO] Query mode,Device disconnected, try to connect.\n"; reconnectFlag = !tryReconnect(); } #endif } std::cout << "[INFO] HIDDev event thread exit...\n"; } bool HIDDev::isConnected() { return connected; } bool HIDDev::tryReconnect() { return openDevice(this->vendorId, this->productId); }