#include "Usb.hpp" #include #include #include #include namespace ptprnt::driver { Usb::Usb() { spdlog::debug("Usb constructing"); libusb_init(NULL); } Usb::~Usb() { spdlog::debug("Usb destructing"); } std::optional> Usb::getDevices() { // TODO: wrap libUsbDevs in a smart pointer with custom destructor // calling libusb_free_device_list libusb_device** libUsbDevs; libusb_device* libUsbDev; struct libusb_device_descriptor libUsbDesc; int ret, i = 0; mDevices.clear(); if (0 == (ret = libusb_get_device_list(NULL, &libUsbDevs))) { spdlog::error("Could not find any USB devices: {}", libusb_error_name(ret)); return std::nullopt; } while ((libUsbDev = libUsbDevs[i++]) != NULL) { UsbDevice newDev; if ((ret = libusb_get_device_descriptor(libUsbDev, &libUsbDesc)) < 0) { spdlog::error("failed to open device"); libusb_free_device_list(libUsbDevs, 1); return std::nullopt; } newDev.vendorId = libUsbDesc.idVendor; newDev.productId = libUsbDesc.idProduct; newDev.device = libUsbDev; newDev.hndl = nullptr; // handle is only available after we opened the dev mDevices.push_back(newDev); } libusb_free_device_list(libUsbDevs, 1); return mDevices; } std::optional Usb::open(UsbDevice dev) { libusb_device_handle* libUsbHandle = nullptr; int ret = 0; if ((ret = libusb_open(dev.device, &libUsbHandle) != 0)) { spdlog::error("Could not open device {0:04X}:{1:04X}: {2}", dev.vendorId, dev.productId, libusb_error_name(ret)); return std::nullopt; } // detach the device from the kernel if it is active if ((ret = libusb_kernel_driver_active(libUsbHandle, 0)) == 1) { if ((ret = libusb_detach_kernel_driver(libUsbHandle, 0)) != 0) { spdlog::error( "Could not detach kernel driver for device {0:04X}:{1:04X}: " "{2}", dev.vendorId, dev.productId, libusb_error_name(ret)); return std::nullopt; } } // claim interface if ((ret = libusb_claim_interface(libUsbHandle, 0)) != 0) { spdlog::error( "Could not claim interface {0:04X}:{1:04X}: " "{2}", dev.vendorId, dev.productId, libusb_error_name(ret)); } dev.hndl = libUsbHandle; return dev; } bool Usb::close(UsbDevice dev) { int ret = 0; if(0 != (ret = libusb_release_interface(dev.hndl, 0))) { spdlog::error( "Could not close USB device {0:04X}:{1:04X}: " "{2}", dev.vendorId, dev.productId, libusb_error_name(ret)); } libusb_close(dev.hndl); return true; } } // namespace ptprnt::driver