diff --git a/.vscode/settings.json b/.vscode/settings.json index 256586b..a54cf27 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,9 +1,7 @@ { - "clangd.arguments": [ "-log=verbose", - "-pretty", - "--background-index", - "--compile-commands-dir=${workspaceFolder}/builddir" - ], + "C_Cpp.codeAnalysis.clangTidy.args":[ + "-extra-arg=-std=c++17" + ], "files.associations": { "cctype": "cpp", "clocale": "cpp", @@ -82,6 +80,7 @@ "any": "cpp", "regex": "cpp", "future": "cpp", - "charconv": "cpp" + "charconv": "cpp", + "*.ipp": "cpp" } } \ No newline at end of file diff --git a/inc/DriverTypes.hpp b/inc/DriverTypes.hpp index aeedf98..abb4ecd 100644 --- a/inc/DriverTypes.hpp +++ b/inc/DriverTypes.hpp @@ -7,6 +7,8 @@ namespace ptprnt::driver { struct info { std::string name{""}; std::string version{""}; + uint32_t busNo{0}; + uint32_t flags{0}; }; } // namespace ptprnt::driver \ No newline at end of file diff --git a/inc/IUsb.hpp b/inc/IUsb.hpp index 3e0d02e..4a8ab6f 100644 --- a/inc/IUsb.hpp +++ b/inc/IUsb.hpp @@ -12,6 +12,8 @@ class IUsb { virtual ~IUsb() = default; virtual std::optional> getDevices() = 0; + virtual std::optional open(UsbDevice) = 0; + virtual bool close(UsbDevice) = 0; }; } // namespace ptprnt::driver \ No newline at end of file diff --git a/inc/P700Driver.hpp b/inc/P700Driver.hpp index 8cd975d..a905c8c 100644 --- a/inc/P700Driver.hpp +++ b/inc/P700Driver.hpp @@ -23,6 +23,7 @@ class P700Driver : public IDriver { private: std::shared_ptr mUsbDriver{0}; UsbDevice mUsbDev{0}; + driver::info mInfo{}; bool init(); }; diff --git a/inc/P700Printer.hpp b/inc/P700Printer.hpp index 16dc082..86c2466 100644 --- a/inc/P700Printer.hpp +++ b/inc/P700Printer.hpp @@ -10,7 +10,7 @@ namespace ptprnt::printer { class P700Printer : public IPrinter { public: - P700Printer(std::unique_ptr driver); + P700Printer(std::shared_ptr driver); ~P700Printer() override; printer::info getInfo() override; @@ -19,7 +19,7 @@ class P700Printer : public IPrinter { private: static info mPrinterInfo; - std::unique_ptr mDriver; + std::shared_ptr mDriver; }; } // namespace ptprnt::printer \ No newline at end of file diff --git a/inc/Usb.hpp b/inc/Usb.hpp index 4ec3074..e8f3709 100644 --- a/inc/Usb.hpp +++ b/inc/Usb.hpp @@ -1,8 +1,6 @@ #include "IUsb.hpp" #include "UsbTypes.hpp" -#include - #pragma once namespace ptprnt::driver { @@ -13,9 +11,12 @@ class Usb : public IUsb { ~Usb() override; std::optional> getDevices() override; + std::optional open(UsbDevice) override; + bool close(UsbDevice) override; private: + // TODO: This should be a std::map with handles & locking on access std::vector mDevices{}; }; -} // namespace ptprnt::driver \ No newline at end of file +} // namespace ptprnt::driver diff --git a/inc/UsbTypes.hpp b/inc/UsbTypes.hpp index e1e4737..24513fd 100644 --- a/inc/UsbTypes.hpp +++ b/inc/UsbTypes.hpp @@ -8,7 +8,7 @@ namespace ptprnt::driver { struct UsbDevice { uint16_t vendorId{0}; uint16_t productId{0}; - libusb_device* dev{nullptr}; + libusb_device* device{nullptr}; libusb_device_handle* hndl{nullptr}; }; diff --git a/src/P700Driver.cpp b/src/P700Driver.cpp index cc4046b..647804d 100644 --- a/src/P700Driver.cpp +++ b/src/P700Driver.cpp @@ -26,15 +26,24 @@ P700Driver::~P700Driver() { } driver::info P700Driver::getInfo() { - return driver::info{}; + return mInfo; } bool P700Driver::open() { - return false; + 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() { - return false; + if(!mUsbDriver->close(mUsbDev)) { + return false; + } + return true; } bool P700Driver::command() { @@ -49,6 +58,8 @@ bool P700Driver::init() { 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 && diff --git a/src/P700Printer.cpp b/src/P700Printer.cpp index fee0054..22914a6 100644 --- a/src/P700Printer.cpp +++ b/src/P700Printer.cpp @@ -5,8 +5,9 @@ namespace ptprnt::printer { -P700Printer::P700Printer(std::unique_ptr driver) { - if (!driver->open()) { +P700Printer::P700Printer(std::shared_ptr driver) { + mDriver = std::move(driver); + if (!mDriver->open()) { throw std::invalid_argument("Could not open driver!"); } } diff --git a/src/Usb.cpp b/src/Usb.cpp index a262410..9bd4f58 100644 --- a/src/Usb.cpp +++ b/src/Usb.cpp @@ -17,31 +17,87 @@ Usb::~Usb() { } std::optional> Usb::getDevices() { - libusb_device** devs; - libusb_device* dev; - struct libusb_device_descriptor desc; - int r, i = 0; + // 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(); - libusb_get_device_list(NULL, &devs); + 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 ((dev = devs[i++]) != NULL) { + while ((libUsbDev = libUsbDevs[i++]) != NULL) { UsbDevice newDev; - if ((r = libusb_get_device_descriptor(dev, &desc)) < 0) { + if ((ret = libusb_get_device_descriptor(libUsbDev, &libUsbDesc)) < 0) { spdlog::error("failed to open device"); - libusb_free_device_list(devs, 1); + libusb_free_device_list(libUsbDevs, 1); return std::nullopt; } - newDev.vendorId = desc.idVendor; - newDev.productId = desc.idProduct; - + 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 \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index ca4dc08..ab5b9b2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -25,8 +25,8 @@ int main(int argc, char** argv) { return -1; } - auto driver = std::make_unique(usb); - //auto printer = std::make_unique(std::move(driver)); + auto driver = std::make_shared(usb); + auto printer = std::make_unique(std::move(driver)); //printer::info info = printer->getInfo(); return 0;