From 779911e97e435b7837c36ea95614778e243db503 Mon Sep 17 00:00:00 2001 From: Moritz Martinius Date: Sat, 26 Aug 2023 13:16:09 +0200 Subject: [PATCH] Re-implemented USB device enumeration with new structure --- src/P700Driver.cpp | 76 ------------------------- src/libusbwrap/LibUsbTypes.hpp | 2 + src/libusbwrap/UsbDevice.cpp | 39 +++++++++---- src/libusbwrap/UsbDevice.hpp | 13 ++++- src/libusbwrap/UsbDeviceFactory.cpp | 27 ++++++++- src/libusbwrap/UsbDeviceFactory.hpp | 3 + src/libusbwrap/interface/IUsbDevice.hpp | 11 ++-- src/main.cpp | 3 - 8 files changed, 76 insertions(+), 98 deletions(-) delete mode 100644 src/P700Driver.cpp diff --git a/src/P700Driver.cpp b/src/P700Driver.cpp deleted file mode 100644 index 5a8bdc8..0000000 --- a/src/P700Driver.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include "P700Driver.hpp" - -#include - -#include -#include - -namespace ptprnt::driver { - -P700Driver::P700Driver(std::shared_ptr usbDriver, uint16_t usbDevVendor, uint16_t usbProductId) - : mUsbDriver{std::move(usbDriver)}, - mUsbDev{.vendorId = usbDevVendor, .productId = usbProductId} - -{ - spdlog::debug("P700Driver constructing"); - if (!init()) { - spdlog::error("Could not find any P700 Printers."); - } else { - spdlog::info("Found P700 Printer :-)."); - } -} - -P700Driver::~P700Driver() { - spdlog::debug("P700Driver destructing"); -} - -driver::info P700Driver::getInfo() { - return mInfo; -} - -bool P700Driver::open() { - auto maybeUsbDev = mUsbDriver->open(mUsbDev); - if (!maybeUsbDev.has_value()) { - spdlog::error("Can't open P700 printer"); - return false; - } - mUsbDev = maybeUsbDev.value(); - return true; -} - -bool P700Driver::close() { - if (!mUsbDriver->close(mUsbDev)) { - return false; - } - return true; -} - -bool P700Driver::command() { - return false; -} - -bool P700Driver::init() { - auto devs = mUsbDriver->getDevices(); - - if (!devs.has_value()) { - spdlog::error("No USB devices found"); - return false; - } - - // TODO: There is the possibility, that two printers with the same ID are connected - // We have to take that into account - auto devIt = std::find_if(devs.value().begin(), devs.value().end(), [=](auto dev) { - return mUsbDev.vendorId == dev.vendorId && mUsbDev.productId == dev.productId; - }); - - if (devIt == devs.value().end()) { - spdlog::error("No device with {0:04X}:{1:04X}", mUsbDev.vendorId, mUsbDev.productId); - return false; - } - - mUsbDev = *devIt; - - return true; -} - -} // namespace ptprnt::driver \ No newline at end of file diff --git a/src/libusbwrap/LibUsbTypes.hpp b/src/libusbwrap/LibUsbTypes.hpp index a1ff0ff..be13763 100644 --- a/src/libusbwrap/LibUsbTypes.hpp +++ b/src/libusbwrap/LibUsbTypes.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "libusb.h" namespace libusbwrap { diff --git a/src/libusbwrap/UsbDevice.cpp b/src/libusbwrap/UsbDevice.cpp index b66958c..3cc2965 100644 --- a/src/libusbwrap/UsbDevice.cpp +++ b/src/libusbwrap/UsbDevice.cpp @@ -1,35 +1,52 @@ #include "libusbwrap/UsbDevice.hpp" +#include + +#include "libusb.h" #include "libusbwrap/interface/IUsbDevice.hpp" namespace libusbwrap { -UsbDevice::UsbDevice() {} +UsbDevice::UsbDevice(libusb_context* ctx, libusb_device* dev) : mLibusbCtx(ctx), mLibusbDev(dev) { + if (mLibusbCtx == nullptr || mLibusbDev == nullptr) { + throw std::invalid_argument("ctx or device are nullptr"); + } -UsbDevice::~UsbDevice() {} - -Error UsbDevice::open() { - return Error::SUCCESS; + libusb_get_device_descriptor(dev, &mLibusbDevDesc); } -void UsbDevice::close() {} +UsbDevice::~UsbDevice() { + // only free the device, not the context, which is shared between every device + // the UsbDeviceFactory will take care of that + if (mIsOpen) { + close(); + } +} + +Error UsbDevice::open() { + return static_cast(libusb_open(mLibusbDev, &mLibusbDevHandle)); +} + +void UsbDevice::close() { + libusb_close(mLibusbDevHandle); +} const uint16_t UsbDevice::getVid() { - return 0x0000; + return mLibusbDevDesc.idVendor; } const uint16_t UsbDevice::getPid() { - return 0x0000; + return mLibusbDevDesc.idProduct; } const device::Speed UsbDevice::getSpeed() { - return device::Speed::FULL; + return static_cast(libusb_get_device_speed(mLibusbDev)); } const uint8_t UsbDevice::getBusNumber() { - return 0; + return libusb_get_bus_number(mLibusbDev); } const uint8_t UsbDevice::getPortNumber() { - return 0; + return libusb_get_port_number(mLibusbDev); } } // namespace libusbwrap \ No newline at end of file diff --git a/src/libusbwrap/UsbDevice.hpp b/src/libusbwrap/UsbDevice.hpp index 8b763c7..a26cd7d 100644 --- a/src/libusbwrap/UsbDevice.hpp +++ b/src/libusbwrap/UsbDevice.hpp @@ -1,11 +1,15 @@ #pragma once +#include +#include + +#include "libusb.h" #include "libusbwrap/interface/IUsbDevice.hpp" namespace libusbwrap { class UsbDevice : public IUsbDevice { public: - UsbDevice(); + UsbDevice(libusb_context* ctx, libusb_device* dev); ~UsbDevice(); // delete copy ctor and assignment @@ -21,5 +25,12 @@ class UsbDevice : public IUsbDevice { const device::Speed getSpeed() override; const uint8_t getBusNumber() override; const uint8_t getPortNumber() override; + + private: + libusb_context* mLibusbCtx{nullptr}; + libusb_device* mLibusbDev{nullptr}; + libusb_device_handle* mLibusbDevHandle{nullptr}; + libusb_device_descriptor mLibusbDevDesc; + std::atomic mIsOpen = false; }; } // namespace libusbwrap \ No newline at end of file diff --git a/src/libusbwrap/UsbDeviceFactory.cpp b/src/libusbwrap/UsbDeviceFactory.cpp index 74e7dc5..63f7002 100644 --- a/src/libusbwrap/UsbDeviceFactory.cpp +++ b/src/libusbwrap/UsbDeviceFactory.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "libusb.h" #include "libusbwrap/UsbDevice.hpp" @@ -18,12 +19,12 @@ UsbDeviceFactory::~UsbDeviceFactory() { std::vector> UsbDeviceFactory::findAllDevices() { refreshDeviceList(); - return std::vector>({std::make_shared()}); + return buildMaskedDeviceVector(0x0, 0x0, 0x0, 0x0); } std::vector> UsbDeviceFactory::findDevices(uint16_t vid, uint16_t pid) { refreshDeviceList(); - return std::vector>({std::make_shared()}); + return buildMaskedDeviceVector(0xffff, 0xffff, vid, pid); } int UsbDeviceFactory::refreshDeviceList() { @@ -39,6 +40,28 @@ int UsbDeviceFactory::refreshDeviceList() { return ret; } +std::vector> UsbDeviceFactory::buildMaskedDeviceVector(uint16_t vidMask, + uint16_t pidMask, + uint16_t vid, + uint16_t pid) { + std::vector> matchedDevices; + // see libusb/examples/listdevs.c + int i = 0; + libusb_device* currDev = nullptr; + while ((currDev = mLibusbDeviceList[i++]) != nullptr) { + struct libusb_device_descriptor currDevDesc; + int ret = libusb_get_device_descriptor(currDev, &currDevDesc); + if (ret < 0) { + continue; + } + if (((currDevDesc.idVendor & vidMask) == vid) && + ((currDevDesc.idProduct & pidMask) == pid)) { + matchedDevices.push_back(std::make_shared(mLibusbCtx, currDev)); + } + } + return matchedDevices; +} + bool UsbDeviceFactory::init() { auto err = libusb_init(&mLibusbCtx); diff --git a/src/libusbwrap/UsbDeviceFactory.hpp b/src/libusbwrap/UsbDeviceFactory.hpp index 282a06c..1f502db 100644 --- a/src/libusbwrap/UsbDeviceFactory.hpp +++ b/src/libusbwrap/UsbDeviceFactory.hpp @@ -32,6 +32,9 @@ class UsbDeviceFactory : public IUsbDeviceFactory { private: // methods int refreshDeviceList(); + std::vector> buildMaskedDeviceVector(uint16_t vidMask, + uint16_t pidMask, uint16_t vid, + uint16_t pid); // members libusb_context* mLibusbCtx{nullptr}; libusb_device** mLibusbDeviceList; diff --git a/src/libusbwrap/interface/IUsbDevice.hpp b/src/libusbwrap/interface/IUsbDevice.hpp index 0f9d238..0291cd5 100644 --- a/src/libusbwrap/interface/IUsbDevice.hpp +++ b/src/libusbwrap/interface/IUsbDevice.hpp @@ -3,6 +3,7 @@ #include #include +#include #include "libusb.h" #include "libusbwrap/LibUsbTypes.hpp" @@ -25,10 +26,10 @@ class IUsbDevice { virtual void close() = 0; // getters - const virtual uint16_t getVid() = 0; - const virtual uint16_t getPid() = 0; - const virtual device::Speed getSpeed() = 0; - const virtual uint8_t getBusNumber() = 0; - const virtual uint8_t getPortNumber() = 0; + virtual const uint16_t getVid() = 0; + virtual const uint16_t getPid() = 0; + virtual const device::Speed getSpeed() = 0; + virtual const uint8_t getBusNumber() = 0; + virtual const uint8_t getPortNumber() = 0; }; } // namespace libusbwrap \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 1cbaff1..7d20249 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,9 +25,6 @@ int main(int argc, char** argv) { auto usbDevs = usbFactory.findAllDevices(); for (auto usbDev : usbDevs) { - auto vid = usbDev->getVid(); - auto pid = usbDev->getPid(); - spdlog::info("UsbDev {}:{}", vid, pid); auto foundPrinterIt = std::find_if(compatiblePrinters.begin(), compatiblePrinters.end(), [usbDev](const std::shared_ptr& printer) {