/* ptrnt - print labels on linux Copyright (C) 2023 Moritz Martinius This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "libusbwrap/UsbDevice.hpp" #include #include #include "libusb.h" #include "libusbwrap/LibUsbTypes.hpp" #include "libusbwrap/interface/IUsbDevice.hpp" namespace libusbwrap { 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"); } libusb_get_device_descriptor(dev, &mLibusbDevDesc); } 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(); } } bool UsbDevice::open() { int openStatus = libusb_open(mLibusbDev, &mLibusbDevHandle); if (openStatus != 0) { mLastError = static_cast(openStatus); return false; } return true; } void UsbDevice::close() { libusb_close(mLibusbDevHandle); } bool UsbDevice::detachKernelDriver(int interfaceNo) { // TODO: cover the other status codes that can be returned int kernelDriverStatus = libusb_kernel_driver_active(mLibusbDevHandle, interfaceNo); if (kernelDriverStatus == 1) { // kernel driver is active, we have to detach to continue... int detachStatus = libusb_detach_kernel_driver(mLibusbDevHandle, interfaceNo); if (detachStatus != 0) { mLastError = static_cast(detachStatus); return false; } } return true; } bool UsbDevice::claimInterface(int interfaceNo) { // TODO: cover the other status codes that can be returned int claimInterfaceStatus = libusb_claim_interface(mLibusbDevHandle, interfaceNo); if (claimInterfaceStatus != 0) { mLastError = static_cast(claimInterfaceStatus); return false; } return true; } bool UsbDevice::releaseInterface(int interfaceNo) { int releaseInterfaceStatus = libusb_release_interface(mLibusbDevHandle, interfaceNo); if (releaseInterfaceStatus != 0) { mLastError = static_cast(releaseInterfaceStatus); return false; } return true; } bool UsbDevice::bulkTransfer(uint8_t endpoint, std::vector& data, int* tx, unsigned int timeout) { // TODO: implement error handling for incomplete transactions (tx length != data length) int bulkTransferStatus = 0; bulkTransferStatus = libusb_bulk_transfer(mLibusbDevHandle, endpoint, data.data(), data.size(), tx, timeout); if (bulkTransferStatus != 0) { mLastError = static_cast(bulkTransferStatus); return false; } return true; } const uint16_t UsbDevice::getVid() { return mLibusbDevDesc.idVendor; } const uint16_t UsbDevice::getPid() { return mLibusbDevDesc.idProduct; } const device::Speed UsbDevice::getSpeed() { return static_cast(libusb_get_device_speed(mLibusbDev)); } const uint8_t UsbDevice::getBusNumber() { return libusb_get_bus_number(mLibusbDev); } const uint8_t UsbDevice::getPortNumber() { return libusb_get_port_number(mLibusbDev); } const Error UsbDevice::getLastError() { return mLastError; } const std::string UsbDevice::getLastErrorString() { return std::string(libusb_error_name(static_cast(mLastError))); } } // namespace libusbwrap