summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKari Oikarinen <kari.oikarinen@qt.io>2017-03-14 14:46:09 +0200
committerKari Oikarinen <kari.oikarinen@qt.io>2017-05-02 11:53:34 +0000
commitcac1d51ed38a3aa2db7d61fee3ab3245ab99f588 (patch)
tree85c858d780cb3e2ba44c2777266ef84e7fb94469
parentd96efc1a528f38c1da6830eadd9d096a49495d08 (diff)
Reset network configuration when cable is unplugged
Read USB function filesystem events from the control endpoint and react to events related to disconnecting by calling the network configuration script to reset. This means that when the cable is plugged in, network is always in a reset state and a stale IP according to the previous configuration won't be returned. Task-number: QTBUG-59450 Change-Id: I4ae77c6a9283941802d7b04b3588dbbb81b7c266 Reviewed-by: Samuli Piippo <samuli.piippo@qt.io>
-rw-r--r--qdbd/qdbd.pro2
-rw-r--r--qdbd/usb-gadget/usbgadget.cpp21
-rw-r--r--qdbd/usb-gadget/usbgadget.h4
-rw-r--r--qdbd/usb-gadget/usbgadgetcontrol.cpp105
-rw-r--r--qdbd/usb-gadget/usbgadgetcontrol.h42
5 files changed, 174 insertions, 0 deletions
diff --git a/qdbd/qdbd.pro b/qdbd/qdbd.pro
index c4b573a..de83872 100644
--- a/qdbd/qdbd.pro
+++ b/qdbd/qdbd.pro
@@ -21,6 +21,7 @@ SOURCES += \
networkconfigurationexecutor.cpp \
server.cpp \
usb-gadget/usbgadget.cpp \
+ usb-gadget/usbgadgetcontrol.cpp \
usb-gadget/usbgadgetreader.cpp \
usb-gadget/usbgadgetwriter.cpp \
@@ -33,6 +34,7 @@ HEADERS += \
networkconfigurationexecutor.h \
server.h \
usb-gadget/usbgadget.h \
+ usb-gadget/usbgadgetcontrol.h \
usb-gadget/usbgadgetreader.h \
usb-gadget/usbgadgetwriter.h \
diff --git a/qdbd/usb-gadget/usbgadget.cpp b/qdbd/usb-gadget/usbgadget.cpp
index af5eca2..dd56a7e 100644
--- a/qdbd/usb-gadget/usbgadget.cpp
+++ b/qdbd/usb-gadget/usbgadget.cpp
@@ -23,6 +23,7 @@
#include "configuration.h"
#include "libqdb/make_unique.h"
#include "libqdb/qdbconstants.h"
+#include "usb-gadget/usbgadgetcontrol.h"
#include "usb-gadget/usbgadgetreader.h"
#include "usb-gadget/usbgadgetwriter.h"
@@ -113,8 +114,10 @@ UsbGadget::UsbGadget()
: m_controlEndpoint(Configuration::functionFsDir() + "/ep0"),
m_outEndpoint(Configuration::functionFsDir() + "/ep1"),
m_inEndpoint(Configuration::functionFsDir() + "/ep2"),
+ m_controlThread{nullptr},
m_readThread{nullptr},
m_writeThread{nullptr},
+ m_control{nullptr},
m_reader{nullptr},
m_writer{nullptr},
m_reads{}
@@ -124,6 +127,10 @@ UsbGadget::UsbGadget()
UsbGadget::~UsbGadget()
{
+ if (m_controlThread) {
+ m_controlThread->terminate();
+ m_controlThread->wait();
+ }
if (m_readThread) {
m_readThread->terminate();
m_readThread->wait();
@@ -168,6 +175,7 @@ bool UsbGadget::open(QIODevice::OpenMode mode)
}
qCDebug(usbC) << "Initialized function fs";
+ startControlThread();
startReadThread();
startWriteThread();
@@ -204,6 +212,19 @@ void UsbGadget::dataRead(QByteArray data)
emit readyRead();
}
+void UsbGadget::startControlThread()
+{
+ m_control = make_unique<UsbGadgetControl>(&m_controlEndpoint);
+ m_controlThread = make_unique<QThread>();
+
+ connect(m_controlThread.get(), &QThread::started,
+ m_control.get(), &UsbGadgetControl::monitor);
+
+ m_control->moveToThread(m_controlThread.get());
+ m_controlThread->setObjectName("UsbGadgetControl");
+ m_controlThread->start();
+}
+
void UsbGadget::startReadThread()
{
m_reader = make_unique<UsbGadgetReader>(&m_outEndpoint);
diff --git a/qdbd/usb-gadget/usbgadget.h b/qdbd/usb-gadget/usbgadget.h
index 9765523..f72b925 100644
--- a/qdbd/usb-gadget/usbgadget.h
+++ b/qdbd/usb-gadget/usbgadget.h
@@ -21,6 +21,7 @@
#ifndef USBGADGET_H
#define USBGADGET_H
+class UsbGadgetControl;
class UsbGadgetReader;
class UsbGadgetWriter;
@@ -56,6 +57,7 @@ private slots:
private:
bool openControlEndpoint();
+ void startControlThread();
void startReadThread();
void startWriteThread();
@@ -64,8 +66,10 @@ private:
// gadget and in means from gadget to host.
QFile m_outEndpoint;
QFile m_inEndpoint;
+ std::unique_ptr<QThread> m_controlThread;
std::unique_ptr<QThread> m_readThread;
std::unique_ptr<QThread> m_writeThread;
+ std::unique_ptr<UsbGadgetControl> m_control;
std::unique_ptr<UsbGadgetReader> m_reader;
std::unique_ptr<UsbGadgetWriter> m_writer;
QQueue<QByteArray> m_reads;
diff --git a/qdbd/usb-gadget/usbgadgetcontrol.cpp b/qdbd/usb-gadget/usbgadgetcontrol.cpp
new file mode 100644
index 0000000..235c266
--- /dev/null
+++ b/qdbd/usb-gadget/usbgadgetcontrol.cpp
@@ -0,0 +1,105 @@
+/******************************************************************************
+**
+** Copyright (C) 2017 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 "usbgadgetcontrol.h"
+
+#include "configuration.h"
+#include "libqdb/protocol/protocol.h"
+#include "libqdb/protocol/qdbmessage.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qloggingcategory.h>
+#include <QtCore/qprocess.h>
+#include <QtCore/qtimer.h>
+
+#include <linux/usb/functionfs.h>
+
+Q_DECLARE_LOGGING_CATEGORY(usbC);
+
+namespace {
+
+QString eventTypeName(usb_functionfs_event_type eventType)
+{
+ switch (eventType)
+ {
+ case FUNCTIONFS_BIND:
+ return QLatin1String("FUNCTIONFS_BIND");
+ case FUNCTIONFS_UNBIND:
+ return QLatin1String("FUNCTIONFS_UNBIND");
+ case FUNCTIONFS_ENABLE:
+ return QLatin1String("FUNCTIONFS_ENABLE");
+ case FUNCTIONFS_DISABLE:
+ return QLatin1String("FUNCTIONFS_DISABLE");
+ case FUNCTIONFS_SETUP:
+ return QLatin1String("FUNCTIONFS_SETUP");
+ case FUNCTIONFS_SUSPEND:
+ return QLatin1String("FUNCTIONFS_SUSPEND");
+ case FUNCTIONFS_RESUME:
+ return QLatin1String("FUNCTIONFS_RESUME");
+ }
+ return QLatin1String("(unknown)");
+}
+
+} // anonymous namespace
+
+UsbGadgetControl::UsbGadgetControl(QFile *controlEndpoint)
+ : m_controlEndpoint{controlEndpoint}
+{
+
+}
+
+void UsbGadgetControl::monitor()
+{
+ if (!m_controlEndpoint->isOpen()) {
+ qCCritical(usbC) << "Tried to read FFS events from a closed endpoint";
+ return;
+ }
+
+ QTimer::singleShot(0, this, &UsbGadgetControl::monitor);
+
+ const auto eventSize = sizeof(usb_functionfs_event);
+
+ QByteArray buffer{eventSize, '\0'};
+ int count = m_controlEndpoint->read(buffer.data(), buffer.size());
+ if (count == -1) {
+ qCWarning(usbC) << "Could not read FFS event from control endpoint";
+ return;
+ } else if (count < buffer.size()) {
+ qCWarning(usbC) << "Could only read" << count << "out of" << buffer.size()
+ << "byte event from control endpoint";
+ return;
+ }
+
+ const auto *event = reinterpret_cast<usb_functionfs_event *>(buffer.data());
+ const auto eventType = static_cast<usb_functionfs_event_type>(event->type);
+ qCDebug(usbC) << "USB FFS event:" << eventTypeName(eventType);
+ if (eventType == FUNCTIONFS_DISABLE || eventType == FUNCTIONFS_SUSPEND) {
+ QProcess process;
+ process.start(Configuration::networkScript(), QStringList{"--reset"});
+ process.waitForFinished();
+ if (process.exitCode() != 0) {
+ qCWarning(usbC) << "Using script" << Configuration::networkScript()
+ << "to reset the network configuration failed";
+ return;
+ }
+ qCDebug(usbC) << "Reset the network configuration";
+ }
+}
diff --git a/qdbd/usb-gadget/usbgadgetcontrol.h b/qdbd/usb-gadget/usbgadgetcontrol.h
new file mode 100644
index 0000000..07a3895
--- /dev/null
+++ b/qdbd/usb-gadget/usbgadgetcontrol.h
@@ -0,0 +1,42 @@
+/******************************************************************************
+**
+** Copyright (C) 2017 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 USBGADGETCONTROL_H
+#define USBGADGETCONTROL_H
+
+#include <QtCore/qobject.h>
+QT_BEGIN_NAMESPACE
+class QFile;
+QT_END_NAMESPACE
+
+class UsbGadgetControl : public QObject
+{
+ Q_OBJECT
+public:
+ UsbGadgetControl(QFile *controlEndpoint);
+
+public slots:
+ void monitor();
+
+private:
+ QFile *m_controlEndpoint;
+};
+
+#endif // USBGADGETCONTROL_H