Implement open() and close() for Usb class, added a lot of TODO's

This commit is contained in:
2022-11-13 21:28:28 +01:00
parent f09e4ab5c8
commit 38906dafef
11 changed files with 103 additions and 30 deletions

11
.vscode/settings.json vendored
View File

@@ -1,9 +1,7 @@
{ {
"clangd.arguments": [ "-log=verbose", "C_Cpp.codeAnalysis.clangTidy.args":[
"-pretty", "-extra-arg=-std=c++17"
"--background-index", ],
"--compile-commands-dir=${workspaceFolder}/builddir"
],
"files.associations": { "files.associations": {
"cctype": "cpp", "cctype": "cpp",
"clocale": "cpp", "clocale": "cpp",
@@ -82,6 +80,7 @@
"any": "cpp", "any": "cpp",
"regex": "cpp", "regex": "cpp",
"future": "cpp", "future": "cpp",
"charconv": "cpp" "charconv": "cpp",
"*.ipp": "cpp"
} }
} }

View File

@@ -7,6 +7,8 @@ namespace ptprnt::driver {
struct info { struct info {
std::string name{""}; std::string name{""};
std::string version{""}; std::string version{""};
uint32_t busNo{0};
uint32_t flags{0};
}; };
} // namespace ptprnt::driver } // namespace ptprnt::driver

View File

@@ -12,6 +12,8 @@ class IUsb {
virtual ~IUsb() = default; virtual ~IUsb() = default;
virtual std::optional<std::vector<UsbDevice>> getDevices() = 0; virtual std::optional<std::vector<UsbDevice>> getDevices() = 0;
virtual std::optional<UsbDevice> open(UsbDevice) = 0;
virtual bool close(UsbDevice) = 0;
}; };
} // namespace ptprnt::driver } // namespace ptprnt::driver

View File

@@ -23,6 +23,7 @@ class P700Driver : public IDriver {
private: private:
std::shared_ptr<Usb> mUsbDriver{0}; std::shared_ptr<Usb> mUsbDriver{0};
UsbDevice mUsbDev{0}; UsbDevice mUsbDev{0};
driver::info mInfo{};
bool init(); bool init();
}; };

View File

@@ -10,7 +10,7 @@ namespace ptprnt::printer {
class P700Printer : public IPrinter { class P700Printer : public IPrinter {
public: public:
P700Printer(std::unique_ptr<driver::P700Driver> driver); P700Printer(std::shared_ptr<driver::P700Driver> driver);
~P700Printer() override; ~P700Printer() override;
printer::info getInfo() override; printer::info getInfo() override;
@@ -19,7 +19,7 @@ class P700Printer : public IPrinter {
private: private:
static info mPrinterInfo; static info mPrinterInfo;
std::unique_ptr<driver::P700Driver> mDriver; std::shared_ptr<driver::P700Driver> mDriver;
}; };
} // namespace ptprnt::printer } // namespace ptprnt::printer

View File

@@ -1,8 +1,6 @@
#include "IUsb.hpp" #include "IUsb.hpp"
#include "UsbTypes.hpp" #include "UsbTypes.hpp"
#include <libusb-1.0/libusb.h>
#pragma once #pragma once
namespace ptprnt::driver { namespace ptprnt::driver {
@@ -13,9 +11,12 @@ class Usb : public IUsb {
~Usb() override; ~Usb() override;
std::optional<std::vector<UsbDevice>> getDevices() override; std::optional<std::vector<UsbDevice>> getDevices() override;
std::optional<UsbDevice> open(UsbDevice) override;
bool close(UsbDevice) override;
private: private:
// TODO: This should be a std::map with handles & locking on access
std::vector<UsbDevice> mDevices{}; std::vector<UsbDevice> mDevices{};
}; };
} // namespace ptprnt::driver } // namespace ptprnt::driver

View File

@@ -8,7 +8,7 @@ namespace ptprnt::driver {
struct UsbDevice { struct UsbDevice {
uint16_t vendorId{0}; uint16_t vendorId{0};
uint16_t productId{0}; uint16_t productId{0};
libusb_device* dev{nullptr}; libusb_device* device{nullptr};
libusb_device_handle* hndl{nullptr}; libusb_device_handle* hndl{nullptr};
}; };

View File

@@ -26,15 +26,24 @@ P700Driver::~P700Driver() {
} }
driver::info P700Driver::getInfo() { driver::info P700Driver::getInfo() {
return driver::info{}; return mInfo;
} }
bool P700Driver::open() { 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() { bool P700Driver::close() {
return false; if(!mUsbDriver->close(mUsbDev)) {
return false;
}
return true;
} }
bool P700Driver::command() { bool P700Driver::command() {
@@ -49,6 +58,8 @@ bool P700Driver::init() {
return false; 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 = auto devIt =
std::find_if(devs.value().begin(), devs.value().end(), [=](auto dev) { std::find_if(devs.value().begin(), devs.value().end(), [=](auto dev) {
return mUsbDev.vendorId == dev.vendorId && return mUsbDev.vendorId == dev.vendorId &&

View File

@@ -5,8 +5,9 @@
namespace ptprnt::printer { namespace ptprnt::printer {
P700Printer::P700Printer(std::unique_ptr<driver::P700Driver> driver) { P700Printer::P700Printer(std::shared_ptr<driver::P700Driver> driver) {
if (!driver->open()) { mDriver = std::move(driver);
if (!mDriver->open()) {
throw std::invalid_argument("Could not open driver!"); throw std::invalid_argument("Could not open driver!");
} }
} }

View File

@@ -17,31 +17,87 @@ Usb::~Usb() {
} }
std::optional<std::vector<UsbDevice>> Usb::getDevices() { std::optional<std::vector<UsbDevice>> Usb::getDevices() {
libusb_device** devs; // TODO: wrap libUsbDevs in a smart pointer with custom destructor
libusb_device* dev; // calling libusb_free_device_list
struct libusb_device_descriptor desc; libusb_device** libUsbDevs;
int r, i = 0; libusb_device* libUsbDev;
struct libusb_device_descriptor libUsbDesc;
int ret, i = 0;
mDevices.clear(); 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; 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"); spdlog::error("failed to open device");
libusb_free_device_list(devs, 1); libusb_free_device_list(libUsbDevs, 1);
return std::nullopt; return std::nullopt;
} }
newDev.vendorId = desc.idVendor; newDev.vendorId = libUsbDesc.idVendor;
newDev.productId = desc.idProduct; newDev.productId = libUsbDesc.idProduct;
newDev.device = libUsbDev;
newDev.hndl =
nullptr; // handle is only available after we opened the dev
mDevices.push_back(newDev); mDevices.push_back(newDev);
} }
libusb_free_device_list(libUsbDevs, 1);
return mDevices; return mDevices;
} }
std::optional<UsbDevice> 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 } // namespace ptprnt::driver

View File

@@ -25,8 +25,8 @@ int main(int argc, char** argv) {
return -1; return -1;
} }
auto driver = std::make_unique<driver::P700Driver>(usb); auto driver = std::make_shared<driver::P700Driver>(usb);
//auto printer = std::make_unique<printer::P700Printer>(std::move(driver)); auto printer = std::make_unique<printer::P700Printer>(std::move(driver));
//printer::info info = printer->getInfo(); //printer::info info = printer->getInfo();
return 0; return 0;