From 1a8ff526eb750c6629c03c694c07be8d0bebffe2 Mon Sep 17 00:00:00 2001 From: Kari Oikarinen Date: Mon, 29 Aug 2016 12:10:11 +0300 Subject: Handle multiple USB devices Add a new qdb subcommand "devices". It lists the USB devices that are available and have a QDB interface. Their serial numbers are retrieved from the USB interface description. All the other commands now use --device option to decide which device to connect to. libusb_context is managed in a separate singleton, because managing its lifetime between the DeviceManager and UsbConnection would be awkward otherwise. The library-wide initialization is anyway meant to happen just once and the deinitialization just before quitting the executable. Task-number: QTBUG-54405 Change-Id: I8dd4f759e2e0906e0b9d121eb9f1221ee4de55ca Reviewed-by: Samuli Piippo --- client/client.pro | 4 +- client/main.cpp | 83 ++++++++++++++++++------ client/networkmanagercontrol.cpp | 5 +- libqdb/libqdb.pro | 9 ++- libqdb/protocol/protocol.h | 2 +- libqdb/usb/devicemanagement.cpp | 136 +++++++++++++++++++++++++++++++++++++++ libqdb/usb/devicemanagement.h | 30 +++++++++ libqdb/usb/libusbcontext.cpp | 51 +++++++++++++++ libqdb/usb/usbcommon.h | 37 +++++++++++ libqdb/usb/usbconnection.cpp | 94 ++++----------------------- libqdb/usb/usbconnection.h | 11 ++-- libqdb/usb/usbdevice.h | 60 +++++++++++++++++ tests/servicetest.cpp | 3 +- tests/streamtest.cpp | 5 +- 14 files changed, 415 insertions(+), 115 deletions(-) create mode 100644 libqdb/usb/devicemanagement.cpp create mode 100644 libqdb/usb/devicemanagement.h create mode 100644 libqdb/usb/libusbcontext.cpp create mode 100644 libqdb/usb/usbcommon.h create mode 100644 libqdb/usb/usbdevice.h diff --git a/client/client.pro b/client/client.pro index 3ea5839..0bae2f4 100644 --- a/client/client.pro +++ b/client/client.pro @@ -17,7 +17,7 @@ HEADERS += \ handshakeservice.h \ networkmanagercontrol.h \ processservice.h \ - service.h + service.h \ SOURCES += \ connection.cpp \ @@ -28,7 +28,7 @@ SOURCES += \ main.cpp \ networkmanagercontrol.cpp \ processservice.cpp \ - service.cpp + service.cpp \ INCLUDEPATH += $$PWD/../libqdb diff --git a/client/main.cpp b/client/main.cpp index cbef27c..91ab3e6 100644 --- a/client/main.cpp +++ b/client/main.cpp @@ -18,6 +18,7 @@ ** $QT_END_LICENSE$ ** ******************************************************************************/ +#include "../libqdb/usb/devicemanagement.h" #include "../libqdb/usb/usbconnection.h" #include "../libqdb/protocol/qdbtransport.h" #include "connection.h" @@ -32,9 +33,12 @@ #include #include #include +#include #include #include +#include + void setupFilePullService(Connection *connection, const QString &sourcePath, const QString &sinkPath) { auto *service = new FilePullService{connection}; @@ -43,11 +47,11 @@ void setupFilePullService(Connection *connection, const QString &sourcePath, con service, &QObject::deleteLater); QObject::connect(service, &FilePullService::pulled, []() { - qDebug() << "File pull finished."; + std::cout << "File pull finished.\n"; QCoreApplication::quit(); }); QObject::connect(service, &FilePullService::error, []() { - qDebug() << "Error while pulling file."; + std::cerr << "Error while pulling file.\n"; QCoreApplication::exit(1); }); QObject::connect(service, &Service::initialized, [=]() { @@ -65,11 +69,11 @@ void setupFilePushService(Connection *connection, const QString &sourcePath, con service, &QObject::deleteLater); QObject::connect(service, &FilePushService::pushed, []() { - qDebug() << "File transfer finished."; + std::cout << "File transfer finished.\n"; QCoreApplication::quit(); }); QObject::connect(service, &FilePushService::error, []() { - qDebug() << "Error while pushing file."; + std::cerr << "Error while pushing file.\n"; QCoreApplication::exit(1); }); QObject::connect(service, &Service::initialized, [=]() { @@ -87,18 +91,21 @@ void setupProcessService(Connection *connection, const QString &processName, con service, &QObject::deleteLater); QObject::connect(service, &ProcessService::executed, [](int exitCode, QProcess::ExitStatus exitStatus, QString output) { - qDebug() << "Process run, exit code:" << exitCode << exitStatus << output; + std::printf("Process run, exit code %d (%s):\n%s", + exitCode, + exitStatus == QProcess::NormalExit ? "NormalExit" : "CrashExit", + qUtf8Printable(output)); QTimer::singleShot(1, []() { QCoreApplication::quit(); }); }); QObject::connect(service, &ProcessService::executionError, [](QProcess::ProcessError error) { - qDebug() << "Process not run, error:" << error; + std::cerr << "Process not run, error: " << error << std::endl; QTimer::singleShot(1, []() {QCoreApplication::exit(1); }); }); QObject::connect(service, &ProcessService::started, []() { - qDebug() << "Process started"; + std::cout << "Process started.\n"; }); QObject::connect(service, &ProcessService::readyRead, [=]() { - qDebug() << "Process output:" << service->read(); + std::cout << "Process output: " << qUtf8Printable(service->read()) << std::endl; }); QObject::connect(service, &Service::initialized, [=]() { service->execute(processName, arguments); @@ -176,11 +183,12 @@ int main(int argc, char *argv[]) QCommandLineParser parser; parser.addHelpOption(); - parser.addOption({{"d","debug-transport"}, "Print each message that is sent."}); + parser.addOption({"debug-transport", "Print each message that is sent."}); parser.addOption({"debug-connection", "Show enqueued messages"}); + parser.addOption({{"d", "device"}, "Run the command on . Device is specified with a substring of the device serial number.", "device"}); parser.addPositionalArgument("command", "Subcommand of qdb to run. Possible commands are: " - "run, push, pull"); + "run, push, pull, devices, handshake, network"); parser.process(app); QString filterRules; @@ -190,9 +198,53 @@ int main(int argc, char *argv[]) filterRules.append("connection=false\n"); QLoggingCategory::setFilterRules(filterRules); - Connection connection{new QdbTransport{new UsbConnection{}}}; + const QStringList arguments = parser.positionalArguments(); + if (arguments.size() < 1) + parser.showHelp(1); + const QString command = arguments[0]; + + const auto devices = listUsbDevices(); + if (devices.empty()) { + std::cerr << "No QDB devices found.\n"; + return 1; + } + + if (command == "devices") { + std::cout << "USB devices:\n"; + for (const auto &device : devices) { + std::cout << " " << qUtf8Printable(device.serial) << std::endl; + } + return 0; + } + + std::vector matchingDevices; + if (parser.isSet("device")) { + QRegularExpression regexp{parser.value("device")}; + + std::copy_if(devices.begin(), devices.end(), std::back_inserter(matchingDevices), [&](const UsbDevice &device) { + return regexp.match(device.serial).hasMatch(); + }); + } else { + matchingDevices = devices; + } + + if (matchingDevices.size() == 0) { + std::cerr << "No device matching \"" << qUtf8Printable(parser.value("device")) << "\" found.\n"; + return 1; + } + if (matchingDevices.size() > 1) { + std::cerr << "Device \"" << qUtf8Printable(parser.value("device")) + << "\" could mean any of the following devices:\n"; + for (const auto &device : devices) + std::cout << " " << qUtf8Printable(device.serial) << std::endl; + return 1; + } + UsbDevice targetDevice = matchingDevices[0]; + qDebug() << "Executing commands for" << targetDevice.serial; + + Connection connection{new QdbTransport{new UsbConnection{targetDevice}}}; if (!connection.initialize()) { - qDebug() << "could not initialize Connection"; + std::cerr << "Could not initialize connection to \"" << qUtf8Printable(targetDevice.serial) << "\".\n"; return 1; } @@ -204,11 +256,6 @@ int main(int argc, char *argv[]) connection.connect(); qDebug() << "initialized connection"; - QStringList arguments = parser.positionalArguments(); - if (arguments.size() < 1) - return 0; - - QString command = arguments[0]; if (command == "run") { Q_ASSERT(arguments.size() >= 2); setupProcessService(&connection, arguments[1], arguments.mid(2)); @@ -230,7 +277,7 @@ int main(int argc, char *argv[]) } else if (command == "handshake") { setupHandshakeService(&connection); } else { - qDebug() << "Unrecognized command:" << command; + std::cerr << "Unrecognized command: " << qUtf8Printable(command) << std::endl; return 1; } diff --git a/client/networkmanagercontrol.cpp b/client/networkmanagercontrol.cpp index ed0fff0..09edae5 100644 --- a/client/networkmanagercontrol.cpp +++ b/client/networkmanagercontrol.cpp @@ -296,8 +296,9 @@ QVariant NetworkManagerControl::findNetworkDeviceByMac(const QString &macAddress QVariant macResult = wiredDeviceInterface.property("HwAddress"); if (!macResult.isValid()) { const auto error = wiredDeviceInterface.lastError(); - // Non-wired devices result in InvalidArgs due to no MAC address and need not be warned about - if (error.type() != QDBusError::InvalidArgs) + // Non-wired devices result into errors due to no MAC address and need not be warned about. + // For some reason the error type in this case can be either UnknownInterface or InvalidArgs. + if (error.type() != QDBusError::UnknownInterface && error.type() != QDBusError::InvalidArgs) qWarning() << "Could not fetch hw address for" << device.path() << error; continue; } diff --git a/libqdb/libqdb.pro b/libqdb/libqdb.pro index ec5fadf..eeacb7e 100644 --- a/libqdb/libqdb.pro +++ b/libqdb/libqdb.pro @@ -15,18 +15,21 @@ DEFINES += LIBQDB_LIBRARY SOURCES += \ abstractconnection.cpp \ + interruptsignalhandler.cpp \ protocol/qdbmessage.cpp \ protocol/qdbtransport.cpp \ stream.cpp \ streampacket.cpp \ + usb/devicemanagement.cpp \ + usb/libusbcontext.cpp \ usb/usbconnection.cpp \ usb/usbconnectionreader.cpp \ - interruptsignalhandler.cpp \ HEADERS += \ abstractconnection.h \ filepullcommon.h \ filepushcommon.h \ + interruptsignalhandler.h \ libqdb_global.h \ processcommon.h \ protocol/protocol.h \ @@ -35,9 +38,11 @@ HEADERS += \ protocol/services.h \ stream.h \ streampacket.h \ + usb/devicemanagement.h \ + usb/usbcommon.h \ usb/usbconnection.h \ usb/usbconnectionreader.h \ - interruptsignalhandler.h \ + usb/usbdevice.h \ unix { target.path = $$[QT_INSTALL_LIBS] diff --git a/libqdb/protocol/protocol.h b/libqdb/protocol/protocol.h index 42a3081..c0ae09b 100644 --- a/libqdb/protocol/protocol.h +++ b/libqdb/protocol/protocol.h @@ -21,7 +21,7 @@ #ifndef PROTOCOL_H #define PROTOCOL_H -#include +#include const uint8_t qdbUsbClassId = 0xff; const uint8_t qdbUsbSubclassId = 0x52; diff --git a/libqdb/usb/devicemanagement.cpp b/libqdb/usb/devicemanagement.cpp new file mode 100644 index 0000000..3f67cd6 --- /dev/null +++ b/libqdb/usb/devicemanagement.cpp @@ -0,0 +1,136 @@ +/****************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Debug Bridge. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ +#include "devicemanagement.h" +#include "protocol/protocol.h" +#include "usbcommon.h" +#include "usbconnection.h" +#include "../utils/scopeguard.h" + +#include + +#include + +bool isQdbInterface(const libusb_interface &interface) +{ + const libusb_interface_descriptor *descriptor = &interface.altsetting[0]; + return descriptor->bInterfaceClass == qdbUsbClassId && descriptor->bInterfaceSubClass == qdbUsbSubclassId; +} + +std::pair findQdbInterface(libusb_device *device) +{ + libusb_config_descriptor *config; + const int ret = libusb_get_active_config_descriptor(device, &config); + if (ret) { + qCritical() << "Could not get config descriptor" << libusb_error_name(ret); + return std::make_pair(false, UsbInterfaceInfo{}); + } + ScopeGuard configGuard = [&]() { + libusb_free_config_descriptor(config); + }; + + const auto last = config->interface + config->bNumInterfaces; + const auto qdbInterface = std::find_if(config->interface, last, isQdbInterface); + if (qdbInterface == last) { + return std::make_pair(false, UsbInterfaceInfo{});; + } + + const int inEndpointIndex = 1; + const int outEndpointIndex = 0; + + const libusb_interface_descriptor *interface = &qdbInterface->altsetting[0]; + const auto interfaceNumber = interface->bInterfaceNumber; + const auto inAddress = interface->endpoint[inEndpointIndex].bEndpointAddress; + const auto outAddress = interface->endpoint[outEndpointIndex].bEndpointAddress; + const UsbInterfaceInfo info{interfaceNumber, inAddress, outAddress}; + return std::make_pair(true, info); +} + +QString getSerialNumber(libusb_device *device, libusb_device_handle *handle) +{ + QString serial{"???"}; + + libusb_device_descriptor desc; + int ret = libusb_get_device_descriptor(device, &desc); + if (ret) { + qCritical() << "Could not get device descriptor" << libusb_error_name(ret); + return serial; + } + auto serialIndex = desc.iSerialNumber; + + const uint16_t englishUsLangId = 0x409; + const int bufferSize = 255; // USB string descriptor size field is a single byte + unsigned char buffer[bufferSize]; + int length = libusb_get_string_descriptor(handle, serialIndex, englishUsLangId, buffer, bufferSize); + if (length <= 0) { + qWarning() << "Could not get string descriptor of serial number:" << libusb_error_name(length); + return serial; + } + // length is the length in bytes and UTF-16 characters consist of two bytes + Q_ASSERT(length % 2 == 0); + serial = QString::fromUtf16(reinterpret_cast(buffer), length / 2); + return serial; +} + +std::vector listUsbDevices() +{ + if (!libUsbContext()) { + qDebug() << "Not initialized libusb in DeviceManager"; + return std::vector{}; + } + + libusb_device **devicesParam; + ssize_t deviceCount = libusb_get_device_list(libUsbContext(), &devicesParam); + std::shared_ptr devices{devicesParam, + [](libusb_device **pointer) { + libusb_free_device_list(pointer, 1); + }}; + + if (deviceCount < 0) { + qCritical() << "USB devices could not be listed:" << libusb_error_name(deviceCount); + return std::vector{}; + } + + std::vector qdbDevices; + for (int i = 0; i < deviceCount; ++i) { + libusb_device *device = devices.get()[i]; + + const auto interfaceResult = findQdbInterface(device); + if (!interfaceResult.first) { + // No QDB interface found, not a QDB device + continue; + } + + libusb_device_handle *handle; + int ret = libusb_open(device, &handle); + if (ret) { + qDebug() << "Could not open USB device for checking serial number:" << libusb_error_name(ret); + continue; + } + ScopeGuard deviceGuard = [=]() { + libusb_close(handle); + }; + const auto serial = getSerialNumber(device, handle); + + const UsbDevice usbDevice{serial, LibUsbDevice{devices, i}, interfaceResult.second}; + qdbDevices.push_back(usbDevice); + } + return qdbDevices; +} diff --git a/libqdb/usb/devicemanagement.h b/libqdb/usb/devicemanagement.h new file mode 100644 index 0000000..52ac688 --- /dev/null +++ b/libqdb/usb/devicemanagement.h @@ -0,0 +1,30 @@ +/****************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Debug Bridge. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ +#ifndef DEVICEMANAGER_H +#define DEVICEMANAGER_H + +#include "usbdevice.h" + +#include + +std::vector listUsbDevices(); + +#endif // DEVICEMANAGER_H diff --git a/libqdb/usb/libusbcontext.cpp b/libqdb/usb/libusbcontext.cpp new file mode 100644 index 0000000..6976e4e --- /dev/null +++ b/libqdb/usb/libusbcontext.cpp @@ -0,0 +1,51 @@ +/****************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Debug Bridge. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ +#include "usbcommon.h" + +#include + +#include + +struct LibUsbContext +{ + LibUsbContext() + : context{nullptr} + { + int ret = libusb_init(&context); + if (ret) { + qCritical("Could not initialize libusb"); + } + } + + ~LibUsbContext() + { + if (context) + libusb_exit(context); + } + + libusb_context* context; +}; + +libusb_context *libUsbContext() +{ + static LibUsbContext context; + return context.context; +} diff --git a/libqdb/usb/usbcommon.h b/libqdb/usb/usbcommon.h new file mode 100644 index 0000000..4a6d024 --- /dev/null +++ b/libqdb/usb/usbcommon.h @@ -0,0 +1,37 @@ +/****************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Debug Bridge. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ +#ifndef USBCOMMON_H +#define USBCOMMON_H + +#include + +struct libusb_context; + +libusb_context *libUsbContext(); + +struct UsbInterfaceInfo +{ + uint8_t number; + uint8_t inAddress; + uint8_t outAddress; +}; + +#endif // USBCOMMON_H diff --git a/libqdb/usb/usbconnection.cpp b/libqdb/usb/usbconnection.cpp index 7564f3e..2a3bf92 100644 --- a/libqdb/usb/usbconnection.cpp +++ b/libqdb/usb/usbconnection.cpp @@ -23,6 +23,7 @@ #include "../utils/make_unique.h" #include "../utils/scopeguard.h" #include "protocol/protocol.h" +#include "usbcommon.h" #include "usbconnectionreader.h" #include @@ -30,23 +31,10 @@ #include -static const uint16_t vendorID = 0x18d1; // Google Inc. -static const uint16_t productID = 0x0d02; // Celkon A88 -static const int inEndpointIndex = 1; -static const int outEndpointIndex = 0; - -bool isQdbInterface(const libusb_interface &interface) -{ - const libusb_interface_descriptor *descriptor = &interface.altsetting[0]; - return descriptor->bInterfaceClass == qdbUsbClassId && descriptor->bInterfaceSubClass == qdbUsbSubclassId; -} - -UsbConnection::UsbConnection() - : m_context(nullptr), - m_handle(nullptr), - m_interfaceNumber(0), - m_inAddress(0), - m_outAddress(0), +UsbConnection::UsbConnection(const UsbDevice &device) + : m_device{device.usbDevice}, + m_handle{nullptr}, + m_interfaceInfo(device.interfaceInfo), // uniform initialization with {} fails with GCC 4.9 m_readThread{nullptr}, m_reader{nullptr}, m_reads{} @@ -60,11 +48,9 @@ UsbConnection::~UsbConnection() m_readThread->wait(); } if (m_handle) { - libusb_release_interface(m_handle, m_interfaceNumber); + libusb_release_interface(m_handle, m_interfaceInfo.number); libusb_close(m_handle); } - if (m_context) - libusb_exit(m_context); } bool UsbConnection::open(OpenMode mode) @@ -72,48 +58,8 @@ bool UsbConnection::open(OpenMode mode) Q_ASSERT(mode == (QIODevice::ReadWrite | QIODevice::Unbuffered)); QIODevice::open(mode); - libusb_device *found = NULL; - - int ret = libusb_init(&m_context); - if (ret) { - qDebug("cannot init libusb: %s\n", libusb_error_name(ret)); - return false; - } - - libusb_device **devices; - ssize_t deviceCount = libusb_get_device_list(m_context, &devices); - ScopeGuard deviceListGuard = [&]() { - libusb_free_device_list(devices, 1); - }; - - if (deviceCount <= 0) { - qDebug("no devices found\n"); - return false; - } - - for (int i = 0; i < deviceCount; ++i) { - libusb_device *device = devices[i]; - struct libusb_device_descriptor desc; - ret = libusb_get_device_descriptor(device, &desc); - if (ret) { - qDebug("unable to get device descriptor: %s\n", - libusb_error_name(ret)); - return false; - } - if (desc.idVendor == vendorID && desc.idProduct == productID) { - qDebug("found QDB device"); - found = device; - break; - } - } - - if (!found) { - qDebug("no QDB devices found\n"); - return false; - } - libusb_config_descriptor *config; - ret = libusb_get_active_config_descriptor(found, &config); + int ret = libusb_get_active_config_descriptor(m_device.pointer(), &config); if (ret) { qDebug("could not get config descriptor: %s\n", libusb_error_name(ret)); @@ -123,21 +69,7 @@ bool UsbConnection::open(OpenMode mode) libusb_free_config_descriptor(config); }; - auto last = config->interface + config->bNumInterfaces; - auto qdbInterface = std::find_if(config->interface, last, isQdbInterface); - if (qdbInterface == last) { - qDebug("no QDB interface found in device"); - return false; - } - - const libusb_interface_descriptor *interface = &qdbInterface->altsetting[0]; - m_interfaceNumber = interface->bInterfaceNumber; - m_inAddress = interface->endpoint[inEndpointIndex].bEndpointAddress; - m_outAddress = interface->endpoint[outEndpointIndex].bEndpointAddress; - - qDebug("interface %d is a qdb interface", m_interfaceNumber); - - ret = libusb_open(found, &m_handle); + ret = libusb_open(m_device.pointer(), &m_handle); if (ret) { qDebug("cannot open device: %s\n", libusb_error_name(ret)); return false; @@ -145,14 +77,14 @@ bool UsbConnection::open(OpenMode mode) libusb_set_auto_detach_kernel_driver(m_handle, 1); - ret = libusb_claim_interface(m_handle, m_interfaceNumber); + ret = libusb_claim_interface(m_handle, m_interfaceInfo.number); if (ret) { qDebug("cannot claim interface: %s", libusb_error_name(ret)); return false; } - qDebug("claimed interface %d", m_interfaceNumber); + qDebug("claimed interface %d", m_interfaceInfo.number); - startReader(m_handle, m_inAddress); + startReader(m_handle, m_interfaceInfo.inAddress); return true; } @@ -176,7 +108,7 @@ qint64 UsbConnection::writeData(const char *data, qint64 maxSize) int size = maxSize > qdbHeaderSize ? qdbHeaderSize : maxSize; int transferred = 0; - int ret = libusb_bulk_transfer(m_handle, m_outAddress, (unsigned char*)data, size, &transferred, 0); + int ret = libusb_bulk_transfer(m_handle, m_interfaceInfo.outAddress, (unsigned char*)data, size, &transferred, 0); if (ret) { qDebug() << "writeData error:" << libusb_error_name(ret); return -1; @@ -186,7 +118,7 @@ qint64 UsbConnection::writeData(const char *data, qint64 maxSize) if (size < maxSize) { int rest = maxSize - size; - int ret = libusb_bulk_transfer(m_handle, m_outAddress, (unsigned char*)data + size, rest, &transferred, 0); + int ret = libusb_bulk_transfer(m_handle, m_interfaceInfo.outAddress, (unsigned char*)data + size, rest, &transferred, 0); if (ret) { qDebug() << "writeData error:" << libusb_error_name(ret); return -1; diff --git a/libqdb/usb/usbconnection.h b/libqdb/usb/usbconnection.h index 87c10d5..e050557 100644 --- a/libqdb/usb/usbconnection.h +++ b/libqdb/usb/usbconnection.h @@ -22,6 +22,7 @@ #define USBMANAGER_H #include "libqdb_global.h" +#include "usbdevice.h" class UsbConnectionReader; @@ -34,14 +35,14 @@ QT_END_NAMESPACE #include -struct libusb_context; +struct libusb_device; struct libusb_device_handle; class LIBQDBSHARED_EXPORT UsbConnection : public QIODevice { Q_OBJECT public: - UsbConnection(); + UsbConnection(const UsbDevice &device); ~UsbConnection(); bool open(QIODevice::OpenMode mode) override; @@ -56,11 +57,9 @@ private slots: private: void startReader(libusb_device_handle *handle, uint8_t inAddress); - libusb_context *m_context; + LibUsbDevice m_device; libusb_device_handle *m_handle; - uint8_t m_interfaceNumber; - uint8_t m_inAddress; - uint8_t m_outAddress; + UsbInterfaceInfo m_interfaceInfo; std::unique_ptr m_readThread; std::unique_ptr m_reader; QQueue m_reads; diff --git a/libqdb/usb/usbdevice.h b/libqdb/usb/usbdevice.h new file mode 100644 index 0000000..5e8c1a9 --- /dev/null +++ b/libqdb/usb/usbdevice.h @@ -0,0 +1,60 @@ +/****************************************************************************** +** +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the Qt Debug Bridge. +** +** $QT_BEGIN_LICENSE:COMM$ +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** $QT_END_LICENSE$ +** +******************************************************************************/ +#ifndef USBDEVICE_H +#define USBDEVICE_H + +#include "usbcommon.h" + +#include + +#include +#include + +struct libusb_device; + +class LibUsbDevice { +public: + LibUsbDevice(std::shared_ptr devices, int index) + : m_deviceList{devices}, + m_index{index} + + { + } + + libusb_device *pointer() + { + return m_deviceList.get()[m_index]; + } + +private: + std::shared_ptr m_deviceList; + int m_index; + +}; + +struct UsbDevice +{ + QString serial; + LibUsbDevice usbDevice; + UsbInterfaceInfo interfaceInfo; +}; + +#endif // USBDEVICE_H diff --git a/tests/servicetest.cpp b/tests/servicetest.cpp index c87d429..099a49f 100644 --- a/tests/servicetest.cpp +++ b/tests/servicetest.cpp @@ -24,6 +24,7 @@ #include "../client/processservice.h" #include "../client/echoservice.h" #include "../utils/make_unique.h" +#include "usb/devicemanagement.h" #include "usb/usbconnection.h" #include "protocol/qdbtransport.h" #include "protocol/services.h" @@ -39,7 +40,7 @@ const int testTimeout = 500; // in milliseconds struct ConnectionContext { ConnectionContext() - : connection{new QdbTransport{new UsbConnection{}}} + : connection{new QdbTransport{new UsbConnection{listUsbDevices()[0]}}} { QVERIFY(connection.initialize()); diff --git a/tests/streamtest.cpp b/tests/streamtest.cpp index df0c814..0d33d10 100644 --- a/tests/streamtest.cpp +++ b/tests/streamtest.cpp @@ -19,6 +19,7 @@ ** ******************************************************************************/ #include "../utils/make_unique.h" +#include "usb/devicemanagement.h" #include "usb/usbconnection.h" #include "protocol/protocol.h" #include "protocol/qdbmessage.h" @@ -44,7 +45,7 @@ public: public slots: void run() { - m_transport = make_unique(new UsbConnection{}); + m_transport = make_unique(new UsbConnection{listUsbDevices()[0]}); if (m_transport->open()) { qDebug() << "opened transport"; connect(m_transport.get(), &QdbTransport::messageAvailable, this, &TestCase::testPhases); @@ -209,7 +210,7 @@ public slots: { switch (m_phase) { case 0: { - QdbMessage cnxn{QdbMessage::Connect, 0, 0}; + QdbMessage cnxn{QdbMessage::Connect, 0, 0, m_versionBuffer}; QVERIFY(m_transport->send(cnxn)); break; } -- cgit v1.2.3