summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/doc/src/qtee-changelog.qdoc2
-rw-r--r--src/doc/src/qtee-qml-reference.qdoc2
-rw-r--r--src/imports/wifi/pluginmain.cpp30
-rw-r--r--src/imports/wifi/qmldir4
-rw-r--r--src/imports/wifi/qwifiinterface.cpp77
-rw-r--r--src/imports/wifi/qwifimanager.cpp818
-rw-r--r--src/imports/wifi/qwifimanager.h136
-rw-r--r--src/imports/wifi/qwifinetwork.h71
-rw-r--r--src/imports/wifi/wifi.pro34
-rw-r--r--src/src.pro1
-rw-r--r--src/wifi/qwificonfiguration.cpp89
-rw-r--r--src/wifi/qwificonfiguration.h54
-rw-r--r--src/wifi/qwificontroller.cpp461
-rw-r--r--src/wifi/qwificontroller_p.h120
-rw-r--r--src/wifi/qwifidevice.cpp152
-rw-r--r--src/wifi/qwifidevice.h (renamed from src/imports/wifi/qwifiinterface.h)32
-rw-r--r--src/wifi/qwifielinux.cpp (renamed from src/imports/wifi/qwifi_elinux.cpp)113
-rw-r--r--src/wifi/qwifielinux_p.h (renamed from src/imports/wifi/qwifi_elinux.h)10
-rw-r--r--src/wifi/qwifimanager.cpp600
-rw-r--r--src/wifi/qwifimanager.h118
-rw-r--r--src/wifi/qwifimanager_p.h68
-rw-r--r--src/wifi/qwifinetwork.cpp (renamed from src/imports/wifi/qwifinetwork.cpp)41
-rw-r--r--src/wifi/qwifinetwork_p.h66
-rw-r--r--src/wifi/qwifinetworklistmodel.cpp (renamed from src/imports/wifi/qwifinetworklistmodel.cpp)84
-rw-r--r--src/wifi/qwifinetworklistmodel_p.h (renamed from src/imports/wifi/qwifinetworklistmodel.h)29
-rw-r--r--src/wifi/wifi.pro43
-rw-r--r--sync.profile3
27 files changed, 2022 insertions, 1236 deletions
diff --git a/src/doc/src/qtee-changelog.qdoc b/src/doc/src/qtee-changelog.qdoc
index 3c8ab3c..5f18e4c 100644
--- a/src/doc/src/qtee-changelog.qdoc
+++ b/src/doc/src/qtee-changelog.qdoc
@@ -179,7 +179,7 @@
\li Update new content to device without erasing it first on \B2QL
\li All images now contain generally used CA certificates
\li Toolchains updated to support Qt WebEngine
- \li Documentation was added for QML types provided by the \l {WiFi Module}
+ \li Documentation was added for QML types provided by the \l {QtWifi Module}
\li Emulator: Debug logging functionality was added
\li Various documentation improvements
\li \SDK installer error handling was improved
diff --git a/src/doc/src/qtee-qml-reference.qdoc b/src/doc/src/qtee-qml-reference.qdoc
index 7ee86a3..0107e97 100644
--- a/src/doc/src/qtee-qml-reference.qdoc
+++ b/src/doc/src/qtee-qml-reference.qdoc
@@ -31,7 +31,7 @@
\annotatedlist utils-qmltypes
- \section1 WiFi Module
+ \section1 B2Qt Wifi Module
\annotatedlist wifi-qmltypes
*/
diff --git a/src/imports/wifi/pluginmain.cpp b/src/imports/wifi/pluginmain.cpp
index bc72906..f706023 100644
--- a/src/imports/wifi/pluginmain.cpp
+++ b/src/imports/wifi/pluginmain.cpp
@@ -16,15 +16,22 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#include "qwifimanager.h"
-#include "qwifiinterface.h"
+#include <B2QtWifi/QWifiManager>
+#include <B2QtWifi/QWifiDevice>
+#include <B2QtWifi/QWifiConfiguration>
-#include <QtQml/QQmlExtensionPlugin>
-#include <QtQml/qqml.h>
+#include <QtQml>
-static QObject *global_object_wifi(QQmlEngine *, QJSEngine *)
+QT_BEGIN_NAMESPACE
+
+static QObject *globalWifiDevice(QQmlEngine *, QJSEngine *)
{
- return new QWifiInterface;
+ return new QWifiDevice;
+}
+
+static QObject *globalWifiManager(QQmlEngine *, QJSEngine *)
+{
+ return QWifiManager::instance();
}
class QWifiPlugin : public QQmlExtensionPlugin
@@ -35,12 +42,15 @@ class QWifiPlugin : public QQmlExtensionPlugin
public:
virtual void registerTypes(const char *uri)
{
- Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.wifi"));
+ Q_ASSERT(QLatin1String(uri) == QLatin1String("B2Qt.Wifi"));
- qmlRegisterType<QWifiManager>(uri, 0, 1, "WifiManager");
- qmlRegisterType<QWifiNetworkListModel>();
- qmlRegisterSingletonType<QWifiInterface>(uri, 0, 1, "Interface", global_object_wifi);
+ qmlRegisterType<QAbstractListModel>();
+ qmlRegisterSingletonType<QWifiManager>(uri, 1, 0, "WifiManager", globalWifiManager);
+ qmlRegisterSingletonType<QWifiDevice>(uri, 1, 0, "WifiDevice", globalWifiDevice);
+ qmlRegisterType<QWifiConfiguration>(uri, 1, 0, "WifiConfiguration");
}
};
+QT_END_NAMESPACE
+
#include "pluginmain.moc"
diff --git a/src/imports/wifi/qmldir b/src/imports/wifi/qmldir
index d4f65d9..7e99b56 100644
--- a/src/imports/wifi/qmldir
+++ b/src/imports/wifi/qmldir
@@ -1,3 +1,3 @@
-module Qt.labs.wifi
-plugin qwifimodule
+module B2Qt.Wifi
+plugin b2qtwifiplugin
typeinfo plugins.qmltypes
diff --git a/src/imports/wifi/qwifiinterface.cpp b/src/imports/wifi/qwifiinterface.cpp
deleted file mode 100644
index acd7716..0000000
--- a/src/imports/wifi/qwifiinterface.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "qwifiinterface.h"
-
-/*!
- \qmltype Interface
- \inqmlmodule Qt.labs.wifi
- \ingroup wifi-qmltypes
- \brief The Interface element provides the module API.
-
- This element cannot be directly created. It can only be accessed via a namespace import.
-
- \code
- import Qt.labs.wifi 0.1
- import Qt.labs.wifi 0.1 as Wifi
-
- Component.onCompleted: {
- if (Wifi.Interface.wifiSupported()) {
- var component = Qt.createComponent("WifiMenu.qml")
- } else {
- print("WiFi functionality not available on this device.")
- }
- }
- \endcode
-*/
-
-/*!
- \qmlmethod bool Interface::wifiSupported()
-
- Returns true if the device is WiFi capable (provides a WiFi driver), otherwise returns false.
-*/
-
-bool QWifiInterface::wifiSupported() const
-{
-#ifdef Q_OS_ANDROID
- const char *fwpath = 0;
- // reload wifi firmware
- fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
- if (!fwpath) {
- qWarning() << "QWifiInterface: failed to get firmware path";
- return false;
- }
- if (wifi_change_fw_path((const char *)fwpath)) {
- qWarning() << "QWifiInterface: failed to change firmware path";
- return false;
- }
-#endif
- const bool hasInterface = QDir().exists(QStringLiteral("/sys/class/net/wlan0"));
- if (!hasInterface)
- qWarning() << "QWifiInterface: could not find wifi interface in /sys/class/net/";
-#ifdef Q_OS_ANDROID
- if (hasInterface && wifi_load_driver() == 0 && wifi_start_supplicant(0) == 0) {
- return true;
- } else {
- qWarning() << "QWifiInterface: wifi driver is not available";
- return false;
- }
-#else
- return hasInterface;
-#endif
-}
diff --git a/src/imports/wifi/qwifimanager.cpp b/src/imports/wifi/qwifimanager.cpp
deleted file mode 100644
index 2574cd2..0000000
--- a/src/imports/wifi/qwifimanager.cpp
+++ /dev/null
@@ -1,818 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#include "qwifimanager.h"
-#include "qwifiinterface.h"
-
-#include <QtCore>
-#ifdef Q_OS_ANDROID
-#include <hardware_legacy/wifi.h>
-#include <cutils/sockets.h>
-#include <unistd.h>
-#else
-#include <qwifi_elinux.h>
-#endif
-
-static const char SUPPLICANT_SVC[] = "init.svc.wpa_supplicant";
-static const char WIFI_INTERFACE[] = "wifi.interface";
-static const char QT_WIFI_BACKEND[] = "qt.wifi";
-
-static bool QT_WIFI_DEBUG = !qgetenv("QT_WIFI_DEBUG").isEmpty();
-
-const QEvent::Type WIFI_SCAN_RESULTS = (QEvent::Type) (QEvent::User + 2001);
-const QEvent::Type WIFI_CONNECTED = (QEvent::Type) (QEvent::User + 2002);
-const QEvent::Type WIFI_HANDSHAKE_FAILED = (QEvent::Type) (QEvent::User + 2003);
-
-#ifdef Q_OS_ANDROID
-/*
- * Work around API differences between Android versions
- */
-
-static int q_wifi_start_supplicant()
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
- return wifi_start_supplicant();
-#else
- return wifi_start_supplicant(0);
-#endif
-}
-
-static int q_wifi_stop_supplicant()
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
- return wifi_stop_supplicant();
-#else
- return wifi_stop_supplicant(0);
-#endif
-}
-
-static int q_wifi_connect_to_supplicant(const char *ifname)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_connect_to_supplicant(ifname);
-#else
- Q_UNUSED(ifname);
- return wifi_connect_to_supplicant();
-#endif
-}
-
-static void q_wifi_close_supplicant_connection(const char *ifname)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- wifi_close_supplicant_connection(ifname);
-#else
- Q_UNUSED(ifname);
- wifi_close_supplicant_connection();
-#endif
-}
-
-static int q_wifi_wait_for_event(const char *ifname, char *buf, size_t len)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_wait_for_event(ifname, buf, len);
-#else
- Q_UNUSED(ifname);
- return wifi_wait_for_event(buf, len);
-#endif
-}
-
-static int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)
-{
-#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
- return wifi_command(ifname, command, reply, reply_len);
-#else
- Q_UNUSED(ifname);
- return wifi_command(command, reply, reply_len);
-#endif
-}
-
-/*
- * This function is borrowed from /system/core/libnetutils/dhcp_utils.c
- *
- * Wait for a system property to be assigned a specified value.
- * If desired_value is NULL, then just wait for the property to
- * be created with any value. maxwait is the maximum amount of
- * time in seconds to wait before giving up.
- */
-static const int NAP_TIME = 200; // wait for 200ms at a time when polling for property values
-static int wait_for_property(const char *name, const char *desired_value, int maxwait)
-{
- char value[PROPERTY_VALUE_MAX] = {'\0'};
- int maxnaps = (maxwait * 1000) / NAP_TIME;
-
- if (maxnaps < 1) {
- maxnaps = 1;
- }
-
- while (maxnaps-- > 0) {
- usleep(NAP_TIME * 1000);
- if (property_get(name, value, NULL)) {
- if (desired_value == NULL ||
- strcmp(value, desired_value) == 0) {
- return 0;
- }
- }
- }
- return -1; /* failure */
-}
-#endif
-
-class QWifiManagerEvent : public QEvent
-{
-public:
- QWifiManagerEvent(QEvent::Type type, const QByteArray &data = QByteArray())
- : QEvent(type)
- , m_data(data)
- {
- }
-
- QByteArray data() const { return m_data; }
-
-private:
- QByteArray m_data;
-};
-
-class QWifiManagerEventThread : public QThread
-{
-public:
- QWifiManagerEventThread(QWifiManager *manager, const QByteArray &interface)
- : m_manager(manager)
- , m_if(interface)
- {
-
- }
-
- void run() {
- if (QT_WIFI_DEBUG) qDebug("WiFi event thread is running");
- QWifiManagerEvent *event = 0;
- char buffer[2048];
- while (1) {
- int size = q_wifi_wait_for_event(m_if.constData(), buffer, sizeof(buffer) - 1);
- if (size > 0) {
- buffer[size] = 0;
- event = 0;
- if (strstr(buffer, "SCAN-RESULTS")) {
- if (m_manager->exitingEventThread()) {
- if (QT_WIFI_DEBUG) qDebug() << "Exiting WiFi event thread";
- return;
- }
- event = new QWifiManagerEvent(WIFI_SCAN_RESULTS);
- } else if (strstr(buffer, "CONNECTED")) {
- event = new QWifiManagerEvent(WIFI_CONNECTED);
- } else if (strstr(buffer, "Handshake failed")) {
- event = new QWifiManagerEvent(WIFI_HANDSHAKE_FAILED);
- } else if (strstr(buffer, "TERMINATING")) {
- // stop monitoring for events when supplicant is terminating
- return;
- }
- if (event)
- QCoreApplication::postEvent(m_manager, event);
- }
- }
- }
-
- QWifiManager *m_manager;
- QByteArray m_if;
-};
-
-/*!
- \qmlmodule Qt.labs.wifi 0.1
- \title WiFi Module
- \ingroup qtee-qmlmodules
- \brief Controlling wireless network interfaces.
-
- Provides QML types for controlling and accessing information about wireless network interfaces.
-
- The import command for adding these QML types is:
-
- \code
- import Qt.labs.wifi 0.1
- \endcode
-
- If the module is imported into a namespace, some additional methods become available through the
- \l Interface element.
-
- \code
- import Qt.labs.wifi 0.1 as Wifi
- \endcode
-
- \section1 QML Types
-*/
-
-/*!
-
- \qmltype WifiManager
- \inqmlmodule Qt.labs.wifi
- \ingroup wifi-qmltypes
- \brief Provides information about the WiFi backend and available networks.
-
- This element is the main interface to the WiFi functionality.
-
- */
-
-/*!
- \qmlproperty enumeration WifiManager::networkState
-
- This property holds the current state of the network connection.
-
- \list
- \li \e WifiManager.Disconnected - Not connected to any network
- \li \e WifiManager.Authenticating - Verifying password with the network provider
- \li \e WifiManager.HandshakeFailed - Incorrect password provided
- \li \e WifiManager.ObtainingIPAddress - Requesting IP address from DHCP server
- \li \e WifiManager.DhcpRequestFailed - Could not retrieve IP address
- \li \e WifiManager.Connected - Ready to process network requests
- \endlist
-*/
-
-/*!
- \qmlproperty bool WifiManager::backendReady
-
- This property holds whether or not the backend has been successfully initialized.
-
- \code
- WifiManager {
- id: wifiManager
- scanning: backendReady
- }
-
- Button {
- id: wifiOnOffButton
- text: (wifiManager.backendReady) ? "Switch Off" : "Switch On"
- onClicked: {
- if (wifiManager.backendReady) {
- wifiManager.stop()
- } else {
- wifiManager.start()
- }
- }
- }
- \endcode
-*/
-
-/*!
- \qmlproperty bool WifiManager::scanning
-
- This property holds whether or not the backend is scanning for WiFi networks. To
- preserve battery energy, stop scanning for networks once you are done with configuring a network.
-
- Before starting to scan for networks, you need to initialize the WiFi backend.
-
- \sa start
-*/
-
-/*!
- \qmlproperty string WifiManager::connectedSSID
-
- This property holds the network name.
-*/
-
-/*!
- \qmlproperty WifiNetworkListModel WifiManager::networks
-
- This property holds a list of networks that can be sensed by a device. Use the returned
- model as data model in ListView, model is updated every 5 seconds.
-
- WifiNetworkListModel is a simple data model consisting of WifiNetwork objects, accessed with
- the "network" data role. Instances of WifiNetwork cannot be created directly from the QML system.
-
- \code
- WifiManager {
- id: wifiManager
- scanning: backendReady
- Component.onCompleted: start()
- }
-
- Component {
- id: listDelegate
- Rectangle {
- id: delegateBackground
- height: 60
- width: parent.width
- color: "#5C5C5C"
- border.color: "black"
- border.width: 1
-
- Text {
- id: ssidLabel
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.margins: 10
- font.pixelSize: 20
- font.bold: true
- color: "#E6E6E6"
- text: network.ssid
- }
-
- Rectangle {
- width: Math.max(100 + network.signalStrength, 0) / 100 * parent.width;
- height: 20
- radius: 10
- antialiasing: true
- anchors.margins: 20
- anchors.right: parent.right
- anchors.top: parent.top
- color: "#BF8888"
- border.color: "#212126"
- }
- }
- }
-
-
- ListView {
- id: networkView
- anchors.fill: parent
- model: wifiManager.networks
- delegate: listDelegate
- }
- \endcode
-
-*/
-
-/*!
- \qmlmethod void WifiManager::start()
-
- Start an initialization of the WiFi backend.
-
- \sa stop
- */
-
-/*!
- \qmlmethod void WifiManager::stop()
-
- Stop the WiFi backend and shut down all network functionality.
-
- \sa start
- */
-
-/*!
- \qmlmethod void WifiManager::connect(WifiNetwork network, const string passphrase)
-
- Connect to network \a network and use passphrase \a passphrase for authentication.
-
- \sa disconnect, networkState
- */
-
-/*!
- \qmlmethod void WifiManager::disconnect()
-
- Disconnect from currently connected network connection.
-
- \sa connect, networkState
- */
-
-/*!
- \qmlsignal void WifiManager::scanningChanged(bool scanning)
-
- This signal is emitted when device starts or stops to scan for available wifi networks.
-
- \sa scanning
-
-*/
-
-/*!
- \qmlsignal void WifiManager::networkStateChanged(WifiNetwork network)
-
- This signal is emitted whenever changes in a network state occur. Network \a network is the
- the currently active network connection.
-
- \sa networkState
-*/
-
-/*!
- \qmlsignal void WifiManager::backendReadyChanged()
-
- This signal is emitted when backend has been successfully initialized or shut down.
-
- \sa start, stop
-*/
-
-/*!
- \qmlsignal void WifiManager::connectedSSIDChanged(string ssid)
-
- This signal is emitted when the device has connected to or disconnected from a network.
- \a ssid contains the name of the connected network, or an empty string if the network was disconnected.
-
- \sa connect, disconnect
-*/
-
-QWifiManager::QWifiManager()
- : m_networkListModel(this)
- , m_eventThread(0)
- , m_scanTimer(0)
- , m_scanning(false)
-#ifdef Q_OS_ANDROID
- , m_daemonClientSocket(0)
-#endif
- , m_exitingEventThread(false)
- , m_startingUp(true)
- , m_network(0)
-{
- if (!QWifiInterface().wifiSupported())
- // give a warning about API misuse
- qWarning() << "WifiManager may not work as expected on this device. Use the API provided by QtWifi "
- "library to verify if device has support for Wi-Fi before creating an instance of WifiManager!";
-#ifdef Q_OS_ANDROID
- char interface[PROPERTY_VALUE_MAX];
- property_get(WIFI_INTERFACE, interface, NULL);
- m_interface = interface;
-#else
- m_interface = "wlan0"; // use envvar for the interface name?
- m_dhcpRunner = new ProcessRunner(m_interface);
- QObject::connect(m_dhcpRunner, &ProcessRunner::processFinished, this, &QWifiManager::handleDhcpFinished);
-#endif
- qDebug("QWifiManager: using wifi interface: %s", m_interface.constData());
- m_eventThread = new QWifiManagerEventThread(this, m_interface);
-#ifdef Q_OS_ANDROID
- m_daemonClientSocket = new QLocalSocket;
- int qconnFd = socket_local_client("qconnectivity", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
- if (qconnFd != -1) {
- m_daemonClientSocket->setSocketDescriptor(qconnFd);
- QObject::connect(m_daemonClientSocket, SIGNAL(readyRead()), this, SLOT(handleDhcpReply()));
- QObject::connect(m_daemonClientSocket, SIGNAL(connected()), this, SLOT(connectedToDaemon()));
- } else {
- qWarning() << "QWifiManager: failed to connect to qconnectivity socket";
- }
- // check if backend has already been initialized
- char backendStatus[PROPERTY_VALUE_MAX];
- if (property_get(QT_WIFI_BACKEND, backendStatus, NULL)) {
- if (strcmp(backendStatus, "running") == 0) {
- // let it re-connect, in most cases this will see that everything is working properly
- // and will do nothing. Special case is when process has crashed or was killed by a system
- // signal in previous execution, which results in broken connection to a supplicant,
- // connectToBackend will fix it..
- connectToBackend();
- } else if (strcmp(backendStatus, "stopped") == 0) {
- // same here, cleans up the state
- disconnectFromBackend();
- }
- } else {
-#endif
- m_backendReady = false;
- emit backendReadyChanged();
-#ifdef Q_OS_ANDROID
- }
-#endif
-}
-
-QWifiManager::~QWifiManager()
-{
- exitEventThread();
- delete m_eventThread;
-#ifdef Q_OS_ANDROID
- delete m_daemonClientSocket;
-#endif
-}
-
-#ifdef Q_OS_ANDROID
-void QWifiManager::handleDhcpReply()
-{
- if (m_daemonClientSocket->canReadLine()) {
- QByteArray receivedMessage;
- receivedMessage = m_daemonClientSocket->readLine(m_daemonClientSocket->bytesAvailable());
- if (QT_WIFI_DEBUG) qDebug() << "QWifiManager: reply from qconnectivity: " << receivedMessage;
- if (receivedMessage == "success") {
- updateNetworkState(Connected);
- emit connectedSSIDChanged(m_connectedSSID);
- // Store settings of a working wifi connection
- call("SAVE_CONFIG");
- } else if (receivedMessage == "failed") {
- updateNetworkState(DhcpRequestFailed);
- } else {
- qWarning() << "QWifiManager: unknown message: " << receivedMessage;
- }
- }
-}
-
-void QWifiManager::sendDhcpRequest(const QByteArray &request)
-{
- if (QT_WIFI_DEBUG) qDebug() << "QWifiManager: sending request - " << request;
- m_request = request;
- m_request.append("\n");
- m_daemonClientSocket->abort();
- // path where android stores "reserved" sockets
- m_daemonClientSocket->connectToServer(ANDROID_SOCKET_DIR "/qconnectivity");
-}
-
-void QWifiManager::connectedToDaemon()
-{
- m_daemonClientSocket->write(m_request.constData(), m_request.length());
- m_daemonClientSocket->flush();
-}
-#endif
-
-void QWifiManager::handleDhcpFinished()
-{
- // ### TODO - could be that dhcp request fails, how to determine?
- updateNetworkState(Connected);
- call("SAVE_CONFIG");
-}
-
-void QWifiManager::start()
-{
- if (QT_WIFI_DEBUG) qDebug("QWifiManager: connecting to the backend");
- if (m_backendReady)
- return;
- connectToBackend();
-}
-
-void QWifiManager::stop()
-{
- if (QT_WIFI_DEBUG) qDebug("QWifiManager: shutting down");
- if (!m_backendReady)
- return;
- disconnectFromBackend();
-}
-
-void QWifiManager::connectToBackend()
-{
- // ### TODO: maybe it makes sense to move this functions in non-gui thread
-#ifdef Q_OS_ANDROID
- if (!(is_wifi_driver_loaded() || wifi_load_driver() == 0)) {
- qWarning("QWifiManager: failed to load a driver");
- return;
- }
-#else
- QProcess::execute(QStringLiteral("ifup"), QStringList() << m_interface.constData());
-#endif
- if (q_wifi_start_supplicant() != 0) {
- qWarning("QWifiManager: failed to start a supplicant");
- return;
- }
-#ifdef Q_OS_ANDROID
- if (wait_for_property(SUPPLICANT_SVC, "running", 5) < 0) {
- qWarning("QWifiManager: Timed out waiting for supplicant to start");
- return;
- }
-#endif
- if (q_wifi_connect_to_supplicant(m_interface.constData()) == 0) {
- m_backendReady = true;
- emit backendReadyChanged();
-#ifdef Q_OS_ANDROID
- property_set(QT_WIFI_BACKEND, "running");
-#endif
- } else {
- qWarning("QWifiManager: failed to connect to a supplicant");
- return;
- }
- if (QT_WIFI_DEBUG) qDebug("QWifiManager: started successfully");
- m_exitingEventThread = false;
- m_eventThread->start();
- call("SCAN");
-}
-
-void QWifiManager::disconnectFromBackend()
-{
- exitEventThread();
- if (q_wifi_stop_supplicant() < 0)
- qWarning("QWifiManager: failed to stop supplicant");
- q_wifi_close_supplicant_connection(m_interface.constData());
- setScanning(false);
-#ifdef Q_OS_ANDROID
- property_set(QT_WIFI_BACKEND, "stopped");
-#else
- QProcess::execute(QStringLiteral("ifdown"), QStringList() << m_interface.constData());
-#endif
- m_backendReady = false;
- emit backendReadyChanged();
-}
-
-void QWifiManager::exitEventThread()
-{
- if (m_eventThread->isRunning()) {
- m_exitingEventThread = true;
- call("SCAN");
- m_eventThread->wait();
- }
-}
-
-void QWifiManager::setScanning(bool scanning)
-{
- if (!m_backendReady || m_scanning == scanning)
- return;
-
- m_scanning = scanning;
- emit scanningChanged(m_scanning);
-
- if (m_scanning) {
- if (QT_WIFI_DEBUG) qDebug("QWifiManager: scanning");
- call("SCAN");
- m_scanTimer = startTimer(5000); // ### todo - this could be a qml property
- } else {
- if (QT_WIFI_DEBUG) qDebug("QWifiManager: stop scanning");
- killTimer(m_scanTimer);
- }
-}
-
-QByteArray QWifiManager::call(const char *command) const
-{
- char data[2048];
- size_t len = sizeof(data) - 1; // -1: room to add a 0-terminator
- QByteArray cmd;
-#ifdef Q_OS_ANDROID
-#if !(Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 4)
- cmd.append("IFNAME=").append(m_interface).append(" ");
-#endif
-#endif
- cmd.append(command);
- if (q_wifi_command(m_interface.constData(), cmd.constData(), data, &len) < 0) {
- qWarning("QWifiManager: call failed: %s", cmd.constData());
- return QByteArray();
- }
- if (len < sizeof(data))
- data[len] = 0;
- QByteArray result = QByteArray::fromRawData(data, len);
- if (QT_WIFI_DEBUG) qDebug("QWifiManager::call: %s ==>\n%s", cmd.constData(), result.constData());
- return result;
-}
-
-bool QWifiManager::checkedCall(const char *command) const
-{
- return call(command).trimmed().toUpper() == "OK";
-}
-
-void QWifiManager::updateNetworkState(NetworkState state)
-{
- m_state = state;
- if (m_network)
- emit networkStateChanged(m_network);
-}
-
-bool QWifiManager::event(QEvent *e)
-{
- switch ((int) e->type()) {
- case WIFI_SCAN_RESULTS:
- m_networkListModel.parseScanResults(call("SCAN_RESULTS"));
- if (m_startingUp)
- handleConnected();
- return true;
- case WIFI_CONNECTED:
- handleConnected();
- break;
- case WIFI_HANDSHAKE_FAILED:
- updateNetworkState(HandshakeFailed);
- break;
- case QEvent::Timer: {
- int tid = static_cast<QTimerEvent *>(e)->timerId();
- if (tid == m_scanTimer) {
- call("SCAN");
- return true;
- }
- break;
- }
- }
-
- return QObject::event(e);
-}
-
-void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase)
-{
- m_network = network;
- if (network->ssid() == m_connectedSSID) {
- if (QT_WIFI_DEBUG)
- qDebug("QWifiManager::connect(), already connected to %s", network->ssid().constData());
- return;
- }
- updateNetworkState(Authenticating);
- call("DISABLE_NETWORK all");
- if (!m_connectedSSID.isEmpty()) {
- m_connectedSSID.clear();
- emit connectedSSIDChanged(m_connectedSSID);
- }
-
- bool networkKnown = false;
- QByteArray id;
- QByteArray listResult = call("LIST_NETWORKS");
- QList<QByteArray> lines = listResult.split('\n');
- foreach (const QByteArray &line, lines) {
- if (line.contains(network->ssid())) {
- id = line.split('\t').at(0);
- networkKnown = true;
- break;
- }
- }
-
- if (!networkKnown) {
- bool ok;
- id = call("ADD_NETWORK").trimmed();
- id.toInt(&ok);
- if (!ok) {
- qWarning("QWifiManager::connect(), failed to add network");
- return;
- }
- }
- QByteArray setNetworkCommand = QByteArray("SET_NETWORK ") + id;
-
- bool ok = true;
- if (!networkKnown)
- ok = ok && checkedCall(setNetworkCommand + QByteArray(" ssid ") + '"' + network->ssid() + '"');
-
- QByteArray key_mgmt;
- if (network->supportsWPA() || network->supportsWPA2()) {
- ok = ok && checkedCall(setNetworkCommand + QByteArray(" psk ") + '"' + passphrase.toLatin1() + '"');
- key_mgmt = "WPA-PSK";
- } else if (network->supportsWEP()) {
- ok = ok && checkedCall(setNetworkCommand + QByteArray(" wep_key0 ") + '"' + passphrase.toLatin1() + '"');
- ok = ok && checkedCall(setNetworkCommand + QByteArray(" auth_alg OPEN SHARED"));
- key_mgmt = "NONE";
- } else if (!network->supportsWPS() && passphrase.length() == 0) {
- // open network
- key_mgmt = "NONE";
- }
- ok = ok && checkedCall(setNetworkCommand + QByteArray(" key_mgmt ") + key_mgmt);
-
- if (!ok) {
- if (!networkKnown)
- call("REMOVE_NETWORK " + id);
- qWarning("QWifiManager::connect(), failed to set properties on network '%s'", id.constData());
- return;
- }
-
- call(QByteArray("SELECT_NETWORK ") + id);
- call("RECONNECT");
-}
-
-void QWifiManager::disconnect()
-{
- call("DISCONNECT");
-#ifdef Q_OS_ANDROID
- QByteArray req = m_interface;
- sendDhcpRequest(req.append(" disconnect"));
-#endif
- m_connectedSSID.clear();
- updateNetworkState(Disconnected);
- emit connectedSSIDChanged(m_connectedSSID);
-}
-
-void ProcessRunner::run()
-{
- // kill existing udhcpc instance
- QString filePath = QString("/var/run/udhcpc.").append(m_ifc).append(".pid");
- QFile pidFile(filePath);
- if (pidFile.open(QIODevice::ReadOnly)) {
- QByteArray pid = pidFile.readAll();
- pidFile.close();
- QProcess::execute(QStringLiteral("kill"), QStringList() << pid.trimmed().constData());
- } else {
- qWarning() << "QWifiManager - Failed to read" << filePath;
- }
- QStringList args;
- args << QStringLiteral("-R") << QStringLiteral("-n") << QStringLiteral("-p")
- << filePath << QStringLiteral("-i") << m_ifc;
- // start DHCP client
- QProcess::execute(QStringLiteral("udhcpc"), args);
- emit processFinished();
-}
-
-void QWifiManager::handleConnected()
-{
- QList<QByteArray> lists = call("LIST_NETWORKS").split('\n');
- QByteArray connectedNetwork;
- for (int i = 1; i < lists.size(); ++i) {
- if (lists.at(i).toUpper().contains("[CURRENT]")) {
- connectedNetwork = lists.at(i);
- break;
- }
- }
-
- if (connectedNetwork.isEmpty()) {
- if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: not connected to a network...");
- return;
- }
-
- if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: current is %s", connectedNetwork.constData());
-
- QList<QByteArray> info = connectedNetwork.split('\t');
- m_connectedSSID = info.at(1);
-
- if (m_startingUp) {
- m_startingUp = false;
- if (!m_network) {
- int pos = 0; // unused
- m_network = m_networkListModel.networkForSSID(info.at(1), &pos);
- }
- }
-
- updateNetworkState(ObtainingIPAddress);
-#ifdef Q_OS_ANDROID
- QByteArray req = m_interface;
- sendDhcpRequest(req.append(" connect"));
-#else
- m_dhcpRunner->start();
-#endif
-}
diff --git a/src/imports/wifi/qwifimanager.h b/src/imports/wifi/qwifimanager.h
deleted file mode 100644
index 7acc360..0000000
--- a/src/imports/wifi/qwifimanager.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef QWIFIMANAGER_H
-#define QWIFIMANAGER_H
-
-#include <QtCore/QObject>
-#include <QtCore/QThread>
-#include <QtCore/QByteArray>
-
-#ifdef Q_OS_ANDROID
-#include <QtNetwork/QLocalSocket>
-#include <cutils/properties.h>
-#endif
-
-#include "qwifinetworklistmodel.h"
-
-class QWifiManagerEventThread;
-
-class ProcessRunner : public QThread
-{
- Q_OBJECT
-public:
- ProcessRunner(const QByteArray &ifc) : m_ifc(ifc) {}
- void run();
-
-signals:
- void processFinished();
-
-private:
- QByteArray m_ifc;
-};
-
-class QWifiManager : public QObject
-{
- Q_OBJECT
- Q_ENUMS(NetworkState)
- Q_PROPERTY(NetworkState networkState READ networkState NOTIFY networkStateChanged)
- Q_PROPERTY(bool backendReady READ isbackendReady NOTIFY backendReadyChanged)
- Q_PROPERTY(bool scanning READ scanning WRITE setScanning NOTIFY scanningChanged)
- Q_PROPERTY(QString connectedSSID READ connectedSSID NOTIFY connectedSSIDChanged)
- Q_PROPERTY(QWifiNetworkListModel *networks READ networks CONSTANT)
-
-public:
- enum NetworkState {
- Disconnected,
- Authenticating,
- HandshakeFailed,
- ObtainingIPAddress,
- DhcpRequestFailed,
- Connected
- };
-
- QWifiManager();
- ~QWifiManager();
-
- QWifiNetworkListModel *networks() { return &m_networkListModel; }
- QString connectedSSID() const { return m_connectedSSID; }
- bool scanning() const { return m_scanning; }
- void setScanning(bool scanning);
- NetworkState networkState() const { return m_state; }
- bool isbackendReady() const { return m_backendReady; }
- bool exitingEventThread() const { return m_exitingEventThread; }
-
-public slots:
- void start();
- void stop();
- void connect(QWifiNetwork *network, const QString &passphrase);
- void disconnect();
-
-signals:
- void scanningChanged(bool scanning);
- void networkStateChanged(QWifiNetwork *network);
- void backendReadyChanged();
- void connectedSSIDChanged(const QString &ssid);
-
-protected:
- bool event(QEvent *);
- void handleConnected();
- void connectToBackend();
- void disconnectFromBackend();
- void exitEventThread();
-
- QByteArray call(const char *command) const;
- bool checkedCall(const char *command) const;
- void updateNetworkState(NetworkState state);
-
-protected slots:
-#if defined(FORCE_MOC)
- void sendDhcpRequest(const QByteArray &request);
- void connectedToDaemon();
- void handleDhcpReply();
-#endif
- void handleDhcpFinished();
-
-private:
- friend class QWifiManagerEventThread;
- friend class ProcessRunner;
-
- QString m_connectedSSID;
- QWifiNetworkListModel m_networkListModel;
- QWifiManagerEventThread *m_eventThread;
-
- int m_scanTimer;
- bool m_scanning;
- bool m_backendReady;
-
- QByteArray m_interface;
- NetworkState m_state;
-#ifdef Q_OS_ANDROID
- QLocalSocket *m_daemonClientSocket;
-#else
- ProcessRunner *m_dhcpRunner;
-#endif
- QByteArray m_request;
- bool m_exitingEventThread;
- bool m_startingUp;
- QWifiNetwork *m_network;
-};
-
-#endif // QWIFIMANAGER_H
diff --git a/src/imports/wifi/qwifinetwork.h b/src/imports/wifi/qwifinetwork.h
deleted file mode 100644
index 5a92e17..0000000
--- a/src/imports/wifi/qwifinetwork.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Digia Plc
-** All rights reserved.
-** For any questions to Digia, please use the contact form at
-** http://www.qt.io
-**
-** This file is part of Qt Enterprise Embedded.
-**
-** Licensees holding valid Qt Enterprise licenses may use this file in
-** accordance with the Qt Enterprise License Agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and Digia.
-**
-** If you have questions regarding the use of this file, please use
-** the contact form at http://www.qt.io
-**
-****************************************************************************/
-#ifndef QWIFINETWORK_H
-#define QWIFINETWORK_H
-
-#include <QtCore/QByteArray>
-#include <QtCore/QObject>
-
-class QWifiNetwork : public QObject
-{
- Q_OBJECT
-
- Q_PROPERTY(QByteArray bssid READ bssid CONSTANT)
- Q_PROPERTY(QByteArray ssid READ ssid CONSTANT)
- Q_PROPERTY(int signalStrength READ signalStrength NOTIFY signalStrengthChanged)
- Q_PROPERTY(bool supportsWPA2 READ supportsWPA2 CONSTANT)
- Q_PROPERTY(bool supportsWPA READ supportsWPA CONSTANT)
- Q_PROPERTY(bool supportsWEP READ supportsWEP CONSTANT)
- Q_PROPERTY(bool supportsWPS READ supportsWPS CONSTANT)
-
-public:
- QWifiNetwork();
-
- QByteArray bssid() const { return m_bssid; }
- void setBssid(const QByteArray &id) { m_bssid = id; }
-
- QByteArray ssid() const { return m_ssid; }
- void setSsid(const QByteArray &id) { m_ssid = id; }
-
- int signalStrength() const { return m_signalStrength; }
- void setSignalStrength(int strength);
-
- void setOutOfRange(bool outOfRange);
- bool outOfRange() { return m_outOfRange; }
-
- QByteArray flags() const { return m_flags; }
- void setFlags(const QByteArray &f) { m_flags = f; }
- bool supportsWPA2() const { return m_flags.contains("WPA2"); }
- bool supportsWPA() const { return m_flags.contains("WPA"); }
- bool supportsWEP() const { return m_flags.contains("WEP"); }
- bool supportsWPS() const { return m_flags.contains("WPS"); }
-
-signals:
- void signalStrengthChanged(int strength);
-
-private:
- QByteArray m_bssid;
- QByteArray m_ssid;
- int m_signalStrength;
-
- QByteArray m_flags;
- bool m_outOfRange;
-};
-
-#endif // QWIFINETWORK_H
diff --git a/src/imports/wifi/wifi.pro b/src/imports/wifi/wifi.pro
index dabf8cb..b130587 100644
--- a/src/imports/wifi/wifi.pro
+++ b/src/imports/wifi/wifi.pro
@@ -1,34 +1,12 @@
CXX_MODULE = qml
-QT += qml quick network
-TARGET = qwifimodule
-TARGETPATH = Qt/labs/wifi
-IMPORT_VERSION = 0.1
+TARGET = b2qtwifiplugin
+TARGETPATH = B2Qt/Wifi
+IMPORT_VERSION = 1.0
-HEADERS += \
- qwifimanager.h \
- qwifinetwork.h \
- qwifinetworklistmodel.h \
- qwifiinterface.h
+QT += qml b2qtwifi
-SOURCES += \
- pluginmain.cpp \
- qwifimanager.cpp \
- qwifinetwork.cpp \
- qwifinetworklistmodel.cpp \
- qwifiinterface.cpp
+SOURCES += pluginmain.cpp
-android: {
- LIBS += -lhardware_legacy -lcutils
- DEFINES += FORCE_MOC
-} else {
- DEFINES += CONFIG_CTRL_IFACE \
- CONFIG_CTRL_IFACE_UNIX
-
- HEADERS += qwifi_elinux.h
- SOURCES += \
- qwifi_elinux.cpp \
- $$[QT_SYSROOT]/usr/include/wpa-supplicant/wpa_ctrl.c \
- $$[QT_SYSROOT]/usr/include/wpa-supplicant/os_unix.c
-}
+OTHER_FILES += qmldir
load(qml_plugin)
diff --git a/src/src.pro b/src/src.pro
index e8ecbaf..a0e42dd 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -2,6 +2,7 @@ TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS += \
utils \
+ wifi \
imports \
doc \
plugins \
diff --git a/src/wifi/qwificonfiguration.cpp b/src/wifi/qwificonfiguration.cpp
new file mode 100644
index 0000000..f2c859a
--- /dev/null
+++ b/src/wifi/qwificonfiguration.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#include "qwificonfiguration.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWifiConfigurationPrivate
+{
+ Q_DECLARE_PUBLIC(QWifiConfiguration)
+public:
+ QWifiConfigurationPrivate(QWifiConfiguration *config);
+
+ // member variables
+ QWifiConfiguration *const q_ptr;
+ QString m_ssid;
+ QString m_psk;
+ QString m_protocol;
+};
+
+QWifiConfigurationPrivate::QWifiConfigurationPrivate(QWifiConfiguration *config)
+ : q_ptr(config)
+{
+}
+
+
+QWifiConfiguration::QWifiConfiguration(QObject *parent)
+ : QObject(parent)
+ , d_ptr(new QWifiConfigurationPrivate(this))
+{
+}
+
+QWifiConfiguration::~QWifiConfiguration()
+{
+ delete d_ptr;
+}
+
+void QWifiConfiguration::setSsid(const QString &ssid)
+{
+ Q_D(QWifiConfiguration);
+ d->m_ssid = ssid;
+}
+
+QString QWifiConfiguration::ssid() const
+{
+ Q_D(const QWifiConfiguration);
+ return d->m_ssid;
+}
+
+void QWifiConfiguration::setPassphrase(const QString &psk)
+{
+ Q_D(QWifiConfiguration);
+ d->m_psk = psk;
+}
+
+QString QWifiConfiguration::passphrase() const
+{
+ Q_D(const QWifiConfiguration);
+ return d->m_psk;
+}
+
+void QWifiConfiguration::setProtocol(const QString &protocol)
+{
+ Q_D(QWifiConfiguration);
+ d->m_protocol = protocol;
+}
+
+QString QWifiConfiguration::protocol() const
+{
+ Q_D(const QWifiConfiguration);
+ return d->m_protocol;
+}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwificonfiguration.h b/src/wifi/qwificonfiguration.h
new file mode 100644
index 0000000..2253fbb
--- /dev/null
+++ b/src/wifi/qwificonfiguration.h
@@ -0,0 +1,54 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#ifndef QWIFICONFIGURATION_H
+#define QWIFICONFIGURATION_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+class QWifiConfigurationPrivate;
+
+QT_BEGIN_NAMESPACE
+
+class Q_DECL_EXPORT QWifiConfiguration : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QString ssid READ ssid WRITE setSsid)
+ Q_PROPERTY(QString passphrase READ passphrase WRITE setPassphrase)
+ Q_PROPERTY(QString protocol READ protocol WRITE setProtocol)
+public:
+ explicit QWifiConfiguration(QObject *parent = 0);
+ virtual ~QWifiConfiguration();
+
+ void setSsid(const QString &ssid);
+ QString ssid() const;
+ void setPassphrase(const QString &psk);
+ QString passphrase() const;
+ void setProtocol(const QString &protocol);
+ QString protocol() const;
+
+private:
+ Q_DISABLE_COPY(QWifiConfiguration)
+ Q_DECLARE_PRIVATE(QWifiConfiguration)
+ QWifiConfigurationPrivate *const d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFICONFIGURATION_H
diff --git a/src/wifi/qwificontroller.cpp b/src/wifi/qwificontroller.cpp
new file mode 100644
index 0000000..ea49764
--- /dev/null
+++ b/src/wifi/qwificontroller.cpp
@@ -0,0 +1,461 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#include "qwificontroller_p.h"
+#include "qwifimanager_p.h"
+#include "qwifidevice.h"
+
+#include <QtCore/QCoreApplication>
+#include <QtCore/QProcess>
+#include <QtCore/QByteArray>
+#include <QtCore/QFile>
+
+#ifdef Q_OS_ANDROID_NO_SDK
+#include <QtNetwork/QLocalSocket>
+#include <cutils/sockets.h>
+#include <unistd.h>
+#endif
+
+#ifdef Q_OS_ANDROID_NO_SDK
+/*
+ * Work API differences between Android versions
+ */
+int q_wifi_start_supplicant()
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
+ return wifi_start_supplicant();
+#else
+ return wifi_start_supplicant(0);
+#endif
+}
+
+int q_wifi_stop_supplicant()
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 1
+ return wifi_stop_supplicant();
+#else
+ return wifi_stop_supplicant(0);
+#endif
+}
+
+int q_wifi_connect_to_supplicant(const char *ifname)
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
+ return wifi_connect_to_supplicant(ifname);
+#else
+ Q_UNUSED(ifname);
+ return wifi_connect_to_supplicant();
+#endif
+}
+
+void q_wifi_close_supplicant_connection(const char *ifname)
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
+ wifi_close_supplicant_connection(ifname);
+#else
+ Q_UNUSED(ifname);
+ wifi_close_supplicant_connection();
+#endif
+}
+
+int q_wifi_wait_for_event(const char *ifname, char *buf, size_t len)
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
+ return wifi_wait_for_event(ifname, buf, len);
+#else
+ Q_UNUSED(ifname);
+ return wifi_wait_for_event(buf, len);
+#endif
+}
+
+int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len)
+{
+#if Q_ANDROID_VERSION_MAJOR == 4 && (Q_ANDROID_VERSION_MINOR < 4 && Q_ANDROID_VERSION_MINOR >= 1)
+ return wifi_command(ifname, command, reply, reply_len);
+#else
+ Q_UNUSED(ifname);
+ return wifi_command(command, reply, reply_len);
+#endif
+}
+
+/*
+ * This function is borrowed from /system/core/libnetutils/dhcp_utils.c
+ *
+ * Wait for a system property to be assigned a specified value.
+ * If desired_value is NULL, then just wait for the property to
+ * be created with any value. maxwait is the maximum amount of
+ * time in seconds to wait before giving up.
+ */
+const int NAP_TIME = 200; // wait for 200ms at a time when polling for property values
+int wait_for_property(const char *name, const char *desired_value, int maxwait)
+{
+ char value[PROPERTY_VALUE_MAX] = {'\0'};
+ int maxnaps = (maxwait * 1000) / NAP_TIME;
+
+ if (maxnaps < 1) {
+ maxnaps = 1;
+ }
+
+ while (maxnaps-- > 0) {
+ usleep(NAP_TIME * 1000);
+ if (property_get(name, value, NULL)) {
+ if (desired_value == NULL ||
+ strcmp(value, desired_value) == 0) {
+ return 0;
+ }
+ }
+ }
+ return -1; /* failure */
+}
+
+#endif // Q_OS_ANDROID_NO_SDK
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(B2QT_WIFI, "qt.b2qt.wifi")
+
+class QWifiManagerEvent : public QEvent
+{
+public:
+ QWifiManagerEvent(QEvent::Type type, const QByteArray &data = QByteArray())
+ : QEvent(type)
+ , m_data(data)
+ {
+ }
+
+ QByteArray data() const { return m_data; }
+
+private:
+ QByteArray m_data;
+};
+
+class QWifiEventThread : public QThread
+{
+public:
+ QWifiEventThread(QWifiController *controller)
+ : m_controller(controller)
+ {
+ m_interface = QWifiDevice::wifiInterfaceName();
+ }
+
+ void run() {
+ qCDebug(B2QT_WIFI) << "running wifi event thread";
+ QWifiManagerEvent *event = 0;
+ char buffer[2048];
+ forever {
+ int size = q_wifi_wait_for_event(m_interface, buffer, sizeof(buffer) - 1);
+ if (size > 0) {
+ buffer[size] = 0;
+ event = 0;
+ qCDebug(B2QT_WIFI) << "[event]: " << buffer;
+ if (m_controller->isWifiThreadExitRequested()) {
+ qCDebug(B2QT_WIFI) << "exit wifi event thread";
+ return;
+ }
+ if (strstr(buffer, "SCAN-RESULTS")) {
+ event = new QWifiManagerEvent(WIFI_SCAN_RESULTS);
+ } else if (strstr(buffer, "CTRL-EVENT-CONNECTED")) {
+ event = new QWifiManagerEvent(WIFI_CONNECTED);
+ } else if (strstr(buffer, "CTRL-EVENT-DISCONNECTED")) {
+ event = new QWifiManagerEvent(WIFI_DISCONNECTED);
+ } else if (strstr(buffer, "Trying to associate")) {
+ event = new QWifiManagerEvent(WIFI_AUTHENTICATING);
+ } else if (strstr(buffer, "Handshake failed")) {
+ event = new QWifiManagerEvent(WIFI_HANDSHAKE_FAILED);
+ }
+ if (event)
+ QCoreApplication::postEvent(m_controller->wifiManager(), event);
+ }
+ }
+ }
+
+private:
+ QWifiController *m_controller;
+ QByteArray m_interface;
+};
+
+
+QWifiController::QWifiController(QWifiManager *manager, QWifiManagerPrivate *managerPrivate) :
+ m_manager(manager),
+ m_managerPrivate(managerPrivate),
+ m_exitEventThread(false),
+#ifdef Q_OS_ANDROID_NO_SDK
+ m_qcSocket(0),
+#endif
+ m_eventThread(0)
+{
+ m_interface = QWifiDevice::wifiInterfaceName();
+ m_eventThread = new QWifiEventThread(this);
+
+ qRegisterMetaType<QWifiManager::BackendState>("QWifiManager::BackendState");
+#ifdef Q_OS_ANDROID_NO_SDK
+ qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
+#endif
+}
+
+QWifiController::~QWifiController()
+{
+ exitWifiEventThread();
+ delete m_eventThread;
+#ifdef Q_OS_ANDROID_NO_SDK
+ delete m_qcSocket;
+#endif
+}
+
+void QWifiController::allocateOnThisThread()
+{
+#ifdef Q_OS_ANDROID_NO_SDK
+ m_qcSocket = new QLocalSocket;
+ int qcFd = socket_local_client("qconnectivity", ANDROID_SOCKET_NAMESPACE_RESERVED, SOCK_STREAM);
+ if (qcFd != -1) {
+ m_qcSocket->setSocketDescriptor(qcFd);
+ } else {
+ qCWarning(B2QT_WIFI) << "failed to get file descriptor of a qconnectivity socket!";
+ }
+#endif
+}
+
+void QWifiController::run()
+{
+ qCDebug(B2QT_WIFI) << "running wifi backend controller thread";
+ allocateOnThisThread();
+ Method method;
+ forever {
+ m_methodsMutex.lock();
+ if (m_methods.isEmpty())
+ methodCallRequested.wait(&m_methodsMutex);
+ method = m_methods.takeFirst();
+ m_methodsMutex.unlock();
+ switch (method) {
+ case InitializeBackend:
+ initializeBackend();
+ break;
+ case TerminateBackend:
+ terminateBackend();
+ break;
+ case AcquireIPAddress:
+ acquireIPAddress();
+ break;
+ case StopDhcp:
+ stopDhcp();
+ break;
+ case ExitEventLoop:
+ qCDebug(B2QT_WIFI) << "exit wifi backend controller thread";
+ return;
+ }
+ }
+}
+
+void QWifiController::call(Method method)
+{
+ QMutexLocker locker(&m_methodsMutex);
+ m_methods.append(method);
+ methodCallRequested.wakeOne();
+}
+
+void QWifiController::initializeBackend()
+{
+ qCDebug(B2QT_WIFI) << "initializing wifi backend";
+ emit backendStateChanged(QWifiManager::Initializing);
+
+#ifdef Q_OS_ANDROID_NO_SDK
+ qCDebug(B2QT_WIFI) << "initialize driver";
+ if (!(is_wifi_driver_loaded() || wifi_load_driver() == 0)) {
+ qCWarning(B2QT_WIFI) << "failed to load a driver";
+ return;
+ }
+#else
+ qCDebug(B2QT_WIFI) << "run ifconfig (up)";
+ QProcess ifconfig;
+ ifconfig.start(QStringLiteral("ifconfig"), QStringList() << QLatin1String(m_interface) << QStringLiteral("up"));
+ ifconfig.waitForFinished();
+ if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0) {
+ qCWarning(B2QT_WIFI) << "failed to bring up wifi interface!";
+ return;
+ }
+#endif
+ resetSupplicantSocket();
+ startWifiEventThread();
+ qCDebug(B2QT_WIFI) << "wifi backend started successfully";
+ emit backendStateChanged(QWifiManager::Running);
+}
+
+void QWifiController::resetSupplicantSocket() const
+{
+ qCDebug(B2QT_WIFI) << "reset supplicant socket";
+ // close down the previous connection to supplicant if
+ // one exists before re-connecting.
+ if (q_wifi_stop_supplicant() < 0)
+ qCWarning(B2QT_WIFI) << "failed to stop supplicant!";
+ q_wifi_close_supplicant_connection(m_interface);
+ qCDebug(B2QT_WIFI) << "start supplicant";
+ if (q_wifi_start_supplicant() != 0) {
+ qCWarning(B2QT_WIFI) << "failed to start a supplicant!";
+ return;
+ }
+#ifdef Q_OS_ANDROID_NO_SDK
+ if (wait_for_property("init.svc.wpa_supplicant", "running", 5) < 0) {
+ qCWarning(B2QT_WIFI) << "timed out waiting for supplicant to start!";
+ return;
+ }
+#endif
+ qCDebug(B2QT_WIFI) << "connect to supplicant";
+ if (q_wifi_connect_to_supplicant(m_interface) != 0) {
+ qCWarning(B2QT_WIFI) << "failed to connect to a supplicant!";
+ return;
+ }
+}
+
+void QWifiController::terminateBackend()
+{
+ qCDebug(B2QT_WIFI) << "terminating wifi backend";
+ emit backendStateChanged(QWifiManager::Terminating);
+ exitWifiEventThread();
+ if (q_wifi_stop_supplicant() < 0)
+ qCWarning(B2QT_WIFI) << "failed to stop supplicant!";
+ q_wifi_close_supplicant_connection(m_interface);
+#ifndef Q_OS_ANDROID_NO_SDK
+ qCDebug(B2QT_WIFI) << "run ifconfig (down)";
+ QProcess ifconfig;
+ ifconfig.start(QStringLiteral("ifconfig"), QStringList() << QLatin1String(m_interface) << QStringLiteral("down"));
+ ifconfig.waitForFinished();
+ if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0) {
+ qCWarning(B2QT_WIFI) << "failed to bring down wifi interface!";
+ return;
+ }
+#endif
+ stopDhcp();
+ qCDebug(B2QT_WIFI) << "wifi backend stopped successfully";
+ emit backendStateChanged(QWifiManager::NotRunning);
+}
+
+void QWifiController::startWifiEventThread()
+{
+ m_exitEventThread = false;
+ m_eventThread->start();
+}
+
+void QWifiController::exitWifiEventThread()
+{
+ if (m_eventThread->isRunning()) {
+ m_exitEventThread = true;
+ m_managerPrivate->call(QStringLiteral("SCAN"));
+ m_eventThread->wait();
+ }
+}
+
+#ifdef Q_OS_ANDROID_NO_SDK
+bool QWifiController::getQConnectivityReply()
+{
+ bool arrived = false;
+ if (m_qcSocket->canReadLine()) {
+ arrived = true;
+ QByteArray received = m_qcSocket->readLine(m_qcSocket->bytesAvailable());
+ if (received != "success" && received != "failed") {
+ qCWarning(B2QT_WIFI) << "unknown message: " << received;
+ received = "failed";
+ }
+ emit dhcpRequestFinished(QLatin1String(received));
+ }
+ return arrived;
+}
+#else
+void QWifiController::killDhcpProcess(const QString &path) const
+{
+ QFile pidFile(path);
+ if (pidFile.exists()) {
+ pidFile.open(QIODevice::ReadOnly);
+ QByteArray pid = pidFile.readAll();
+ QProcess kill;
+ kill.start(QStringLiteral("kill"), QStringList() << QLatin1String(pid.trimmed()));
+ kill.waitForFinished();
+ if (kill.exitStatus() != QProcess::NormalExit && kill.exitCode() != 0)
+ qCWarning(B2QT_WIFI) << "killing dhcp process failed!";
+ }
+ pidFile.close();
+}
+#endif
+
+void QWifiController::acquireIPAddress()
+{
+ qCDebug(B2QT_WIFI, "acquireIPAddress");
+#ifdef Q_OS_ANDROID_NO_SDK
+ QByteArray request = m_interface + " connect\n";
+ m_qcSocket->abort();
+ m_qcSocket->connectToServer(QStringLiteral(ANDROID_SOCKET_DIR "/qconnectivity"));
+ bool timeout = false;
+ if (m_qcSocket->waitForConnected()) {
+ m_qcSocket->write(request, request.length());
+ m_qcSocket->flush();
+ do {
+ if (m_qcSocket->waitForReadyRead()) {
+ if (getQConnectivityReply())
+ break;
+ } else {
+ timeout = true;
+ qCWarning(B2QT_WIFI) << "waiting a message from qconnectivity timed out!";
+ break;
+ }
+ } while (true);
+ } else {
+ timeout = true;
+ qCWarning(B2QT_WIFI) << "connecting to qconnectivity server socket timed out!";
+ }
+ if (timeout)
+ emit dhcpRequestFinished(QStringLiteral("failed"));
+#else
+ QString filePath = QLatin1String("/var/run/udhcpc." + m_interface + ".pid");
+ killDhcpProcess(filePath);
+ QStringList args;
+ args << QStringLiteral("-R") << QStringLiteral("-n") << QStringLiteral("-p")
+ << filePath << QStringLiteral("-i") << QLatin1String(m_interface);
+
+ QProcess udhcpc;
+ udhcpc.start(QStringLiteral("udhcpc"), args);
+ udhcpc.waitForFinished();
+ if (udhcpc.exitStatus() != QProcess::NormalExit && udhcpc.exitCode() != 0)
+ qCWarning(B2QT_WIFI) << "udhcpc process failed!";
+
+ QString status = QLatin1String("success");
+ if (udhcpc.readAll().contains("No lease"))
+ status = QLatin1String("failed");
+
+ emit dhcpRequestFinished(status);
+#endif
+}
+
+void QWifiController::stopDhcp() const
+{
+ qCDebug(B2QT_WIFI, "stopDhcp");
+#ifdef Q_OS_ANDROID_NO_SDK
+ QByteArray request = m_interface + " disconnect\n";
+ m_qcSocket->abort();
+ m_qcSocket->connectToServer(QStringLiteral(ANDROID_SOCKET_DIR "/qconnectivity"));
+ if (m_qcSocket->waitForConnected()) {
+ m_qcSocket->write(request, request.length());
+ m_qcSocket->flush();
+ } else {
+ qCWarning(B2QT_WIFI) << "connecting to qconnectivity server socket timed out!";
+ }
+#else
+ QString filePath = QLatin1String("/var/run/udhcpc." + m_interface + ".pid");
+ killDhcpProcess(filePath);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwificontroller_p.h b/src/wifi/qwificontroller_p.h
new file mode 100644
index 0000000..230b7c8
--- /dev/null
+++ b/src/wifi/qwificontroller_p.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#ifndef QWIFICONTROLLER_H
+#define QWIFICONTROLLER_H
+
+#include "qwifimanager.h"
+
+#include <QtCore/QEvent>
+#include <QtCore/QVector>
+#include <QtCore/QThread>
+#include <QtCore/QMutex>
+#include <QtCore/QWaitCondition>
+#include <QtCore/QLoggingCategory>
+
+#ifdef Q_OS_ANDROID_NO_SDK
+#include <hardware_legacy/wifi.h>
+#include <cutils/properties.h>
+#else
+#include "qwifielinux_p.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+
+#ifdef Q_OS_ANDROID_NO_SDK
+int q_wifi_start_supplicant();
+int q_wifi_stop_supplicant();
+int q_wifi_connect_to_supplicant(const char *ifname);
+void q_wifi_close_supplicant_connection(const char *ifname);
+int q_wifi_wait_for_event(const char *ifname, char *buf, size_t len);
+int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len);
+int wait_for_property(const char *name, const char *desired_value, int maxwait);
+#endif
+
+const QEvent::Type WIFI_SCAN_RESULTS = (QEvent::Type) (QEvent::User + 2001);
+const QEvent::Type WIFI_CONNECTED = (QEvent::Type) (QEvent::User + 2002);
+const QEvent::Type WIFI_HANDSHAKE_FAILED = (QEvent::Type) (QEvent::User + 2003);
+const QEvent::Type WIFI_AUTHENTICATING = (QEvent::Type) (QEvent::User + 2004);
+const QEvent::Type WIFI_DISCONNECTED = (QEvent::Type) (QEvent::User + 2005);
+
+class QWifiManager;
+class QWifiManagerPrivate;
+class QWifiEventThread;
+#ifdef Q_OS_ANDROID_NO_SDK
+class QLocalSocket;
+#endif
+
+class QWifiController : public QThread
+{
+ Q_OBJECT
+public:
+ enum Method {
+ InitializeBackend,
+ TerminateBackend,
+ AcquireIPAddress,
+ StopDhcp,
+ ExitEventLoop
+ };
+
+ explicit QWifiController(QWifiManager *manager, QWifiManagerPrivate *managerPrivate);
+ ~QWifiController();
+
+ void call(Method method);
+ QWifiManager *wifiManager() const { return m_manager; }
+ bool isWifiThreadExitRequested() const { return m_exitEventThread; }
+ void startWifiEventThread();
+ void acquireIPAddress();
+ void stopDhcp() const;
+ void resetSupplicantSocket() const;
+
+signals:
+ void backendStateChanged(QWifiManager::BackendState backendState);
+ void dhcpRequestFinished(const QString &status);
+
+protected:
+ void run();
+ void initializeBackend();
+ void terminateBackend();
+ void exitWifiEventThread();
+ void allocateOnThisThread();
+#ifdef Q_OS_ANDROID_NO_SDK
+ bool getQConnectivityReply();
+#else
+ void killDhcpProcess(const QString &path) const;
+#endif
+
+private:
+ QWifiManager *m_manager;
+ QWifiManagerPrivate *const m_managerPrivate;
+ bool m_exitEventThread;
+ QByteArray m_interface;
+#ifdef Q_OS_ANDROID_NO_SDK
+ QLocalSocket *m_qcSocket;
+#endif
+ QVector<Method> m_methods;
+ QWifiEventThread *m_eventThread;
+ QMutex m_methodsMutex;
+ QWaitCondition methodCallRequested;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFICONTROLLER_H
diff --git a/src/wifi/qwifidevice.cpp b/src/wifi/qwifidevice.cpp
new file mode 100644
index 0000000..4f100c4
--- /dev/null
+++ b/src/wifi/qwifidevice.cpp
@@ -0,0 +1,152 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#include "qwifidevice.h"
+
+#include <QtCore/QByteArray>
+#include <QtCore/QDir>
+#ifdef Q_OS_ANDROID_NO_SDK
+#include <hardware_legacy/wifi.h>
+#include <cutils/properties.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmltype WifiDevice
+ \inqmlmodule QtWifi
+ \ingroup wifi-qmltypes
+ \brief Represents a physical device
+
+ Use this element to query if a device is WiFi capable before attempting
+ to use functionality of WifiManager.
+
+ \qml
+ import QtWifi 1.0
+
+ GroupBox {
+ id: wifiOptions
+ title: "Wifi"
+ visible: false
+
+ Component.onCompleted: {
+ if (WifiDevice.wifiSupported()) {
+ var component = Qt.createComponent("WifiGroupBox.qml")
+ var wifi = component.createObject(wifiOptions.contentItem)
+ if (wifi)
+ wifiOptions.visible = true
+ } else {
+ print("WiFi functionality not available on this device.")
+ }
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlmethod bool QWifiDevice::wifiSupported()
+
+ Returns true if the device is WiFi capable - WiFi driver and firmware has been
+ successfully loaded by the system, otherwise returns false.
+
+ \sa wifiInterfaceName
+*/
+
+QWifiDevice::QWifiDevice()
+{
+}
+
+QWifiDevice::~QWifiDevice()
+{
+}
+
+bool QWifiDevice::wifiSupported()
+{
+#ifdef Q_OS_ANDROID_NO_SDK
+ const char *fwpath = 0;
+ // reload wifi firmware
+ fwpath = (char *)wifi_get_fw_path(WIFI_GET_FW_PATH_STA);
+ if (!fwpath) {
+ qCWarning(B2QT_WIFI) << "failed to get firmware path";
+ return false;
+ }
+ if (wifi_change_fw_path((const char *)fwpath)) {
+ qCWarning(B2QT_WIFI) << "failed to change firmware path";
+ return false;
+ }
+#endif
+ QByteArray ifc = wifiInterfaceName();
+ bool hasInterface = QDir().exists(QString::fromLatin1("/sys/class/net/" + ifc));
+ if (!hasInterface)
+ qCWarning(B2QT_WIFI) << "could not find wifi interface in \"/sys/class/net/\", "
+ "looking for interface named: " << ifc;
+#ifdef Q_OS_ANDROID_NO_SDK
+ if (hasInterface && wifi_load_driver() == 0) {
+ return true;
+ } else {
+ qCWarning(B2QT_WIFI) << "wifi driver is not available";
+ return false;
+ }
+#else
+ return hasInterface;
+#endif
+}
+
+/*!
+ \fn QByteArray QWifiDevice::wifiInterfaceName()
+
+ Returns WiFi interface name.
+
+ \note On Android WiFi interface name is read from "wifi.interface" system property.
+ On Linux WiFi interface name is read from B2QT_WIFI_INTERFACE environmental variable if
+ it is set. The default interface name is "wlan0" if reading the designated places does not
+ provide an interface name.
+
+ /sa setWifiInterfaceName
+*/
+
+QByteArray QWifiDevice::wifiInterfaceName()
+{
+ QByteArray ifc;
+#ifdef Q_OS_ANDROID_NO_SDK
+ char interface[PROPERTY_VALUE_MAX];
+ property_get("wifi.interface", interface, NULL);
+ ifc = interface[0] == '\0' ? "wlan0" : interface;
+#else
+ ifc = qEnvironmentVariableIsSet("B2QT_WIFI_INTERFACE")
+ ? qgetenv("B2QT_WIFI_INTERFACE") : "wlan0";
+#endif
+ return ifc;
+}
+
+/*!
+ \fn void QWifiDevice::setWifiInterfaceName(const QByteArray &name)
+
+ A conveniece method for settings WiFi interface name.
+*/
+
+void QWifiDevice::setWifiInterfaceName(const QByteArray &name)
+{
+#ifdef Q_OS_ANDROID_NO_SDK
+ property_set("wifi.interface", name);
+#else
+ qputenv("B2QT_WIFI_INTERFACE", name);
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/imports/wifi/qwifiinterface.h b/src/wifi/qwifidevice.h
index 06abd79..80b4891 100644
--- a/src/imports/wifi/qwifiinterface.h
+++ b/src/wifi/qwifidevice.h
@@ -16,25 +16,29 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#ifndef QWIFIINTERFACE_H
-#define QWIFIINTERFACE_H
+#ifndef QWIFIDEVICE_H
+#define QWIFIDEVICE_H
-#include <QtCore/QDir>
-#include <QtCore/QDebug>
-#ifdef Q_OS_ANDROID
-#include <hardware_legacy/wifi.h>
-#include <cutils/properties.h>
-#endif
+#include <QtCore/QObject>
+#include <QtCore/QByteArray>
+#include <QtCore/QLoggingCategory>
-class QWifiInterface : public QObject
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+
+class Q_DECL_EXPORT QWifiDevice : public QObject
{
Q_OBJECT
public:
- explicit QWifiInterface(QObject *parent = 0)
- : QObject(parent) {}
- ~QWifiInterface() {}
+ explicit QWifiDevice();
+ virtual ~QWifiDevice();
- Q_INVOKABLE bool wifiSupported() const;
+ Q_INVOKABLE static bool wifiSupported();
+ static QByteArray wifiInterfaceName();
+ static void setWifiInterfaceName(const QByteArray &name);
};
-#endif // QWIFIHELPERS_H
+QT_END_NAMESPACE
+
+#endif // QWIFIDEVICE_H
diff --git a/src/imports/wifi/qwifi_elinux.cpp b/src/wifi/qwifielinux.cpp
index 32e1aa3..0dc3a39 100644
--- a/src/imports/wifi/qwifi_elinux.cpp
+++ b/src/wifi/qwifielinux.cpp
@@ -16,9 +16,11 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#include "qwifi_elinux.h"
+#include "qwifielinux_p.h"
+#include "qwifidevice.h"
-#include <QtCore/QDebug>
+#include <QtCore/QFile>
+#include <QtCore/QProcess>
#include "wpa-supplicant/wpa_ctrl.h"
@@ -26,18 +28,17 @@
#include <unistd.h>
#include <sys/socket.h>
-static const char SUPP_CONFIG_FILE[] = "/etc/wpa_supplicant.conf";
-static const char IFACE_DIR[] = "/var/run/wpa_supplicant/";
-static const char WIFI[] = "wlan0";
+QT_BEGIN_NAMESPACE
+
+const char SUPP_CONFIG_FILE[] = "/etc/wpa_supplicant.conf";
+const char IFACE_DIR[] = "/var/run/wpa_supplicant/";
+const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
static struct wpa_ctrl *ctrl_conn;
static struct wpa_ctrl *monitor_conn;
// socket pair used to exit from a blocking read
static int exit_sockets[2];
-
-static const char IFNAME[] = "IFNAME=";
-#define IFNAMELEN (sizeof(IFNAME) - 1)
-static const char WPA_EVENT_IGNORE[] = "CTRL-EVENT-IGNORE ";
+QByteArray ctrlInterface;
int wifi_connect_on_socket_path(const char *path);
int wifi_ctrl_recv(char *reply, size_t *reply_len);
@@ -47,30 +48,80 @@ void wifi_close_sockets();
int q_wifi_start_supplicant()
{
- // NOTE: supplicant started when bringing up the wifi interface in
- // QWifiManager::connectToBackend() by:
- // QProcess::execute(QStringLiteral("ifup")
+ // #### TODO - if "/etc/wpa_supplicant/driver.$IFACE" exists, read driver name from there
+ QByteArray ifc = QWifiDevice::wifiInterfaceName();
+ QString driver(QStringLiteral("wext"));
+ QString pidFile = QLatin1String("/var/run/wpa_supplicant." + ifc + ".pid");
+
+ QStringList arg;
+ arg << QStringLiteral("--start") << QStringLiteral("--quiet") << QStringLiteral("--name");
+ arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--startas");
+ arg << QStringLiteral("/usr/sbin/wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
+ arg << QStringLiteral("--") << QStringLiteral("-B") << QStringLiteral("-P") << pidFile;
+ arg << QStringLiteral("-i") << QLatin1String(ifc) << QStringLiteral("-c");
+ arg << QLatin1String(SUPP_CONFIG_FILE) << QStringLiteral("-D") << driver;
+
+ QProcess ssDaemon;
+ ssDaemon.start(QStringLiteral("start-stop-daemon"), arg);
+ ssDaemon.waitForFinished();
+ if (ssDaemon.exitStatus() != QProcess::NormalExit && ssDaemon.exitCode() != 0) {
+ qCWarning(B2QT_WIFI) << "failed to start a supplicant process!";
+ return -1;
+ }
- /* Clear out any stale socket files that might be left over. */
- //wpa_ctrl_cleanup();
- /* Reset sockets used for exiting from hung state */
+ QFile configFile;
+ configFile.setFileName(QLatin1String(SUPP_CONFIG_FILE));
+ if (configFile.exists() && configFile.open(QFile::ReadOnly)) {
+ ctrlInterface.clear();
+ while (!configFile.atEnd()) {
+ QByteArray line = configFile.readLine().trimmed();
+ if (line.startsWith("ctrl_interface")) {
+ ctrlInterface = line.mid(16);
+ break;
+ }
+ }
+ configFile.close();
+ if (!ctrlInterface.isEmpty()) {
+ // if the interface socket exists, then wpa_supplicant was invoked successfully
+ if (!QFile(QLatin1String(ctrlInterface + "/" + ifc)).exists())
+ return -1;
+ } else {
+ qCWarning(B2QT_WIFI) << "ctrl_interface is not set in " << SUPP_CONFIG_FILE;
+ return -1;
+ }
+ } else {
+ qCWarning(B2QT_WIFI) << "could not find/read wpa_supplicant configuration file in" << SUPP_CONFIG_FILE;
+ return -1;
+ }
+ // reset sockets used for exiting from hung state
exit_sockets[0] = exit_sockets[1] = -1;
return 0;
}
int q_wifi_stop_supplicant()
{
- // NOTE: supplicant stopped when bringing down the wifi
- // interface in QWifiManager::disconnectFromBackend() by:
- // QProcess::execute(QStringLiteral("ifdown")
+ QByteArray ifc = QWifiDevice::wifiInterfaceName();
+ QString pidFile = QLatin1String("/var/run/wpa_supplicant." + ifc + ".pid");
+ QStringList arg;
+ arg << QStringLiteral("--stop") << QStringLiteral("--quiet") << QStringLiteral("--name");
+ arg << QStringLiteral("wpa_supplicant") << QStringLiteral("--pidfile") << pidFile;
+ QProcess ssDaemon;
+ ssDaemon.start(QStringLiteral("start-stop-daemon"), arg);
+ ssDaemon.waitForFinished();
+ if (ssDaemon.exitStatus() != QProcess::NormalExit && ssDaemon.exitCode() != 0) {
+ qCWarning(B2QT_WIFI) << "failed to stop a supplicant process!";
+ return -1;
+ }
+
+ QFile::remove(QLatin1String(ctrlInterface + "/" + ifc));
+ QFile::remove(pidFile);
return 0;
}
int q_wifi_connect_to_supplicant(const char *ifname)
{
- Q_UNUSED(ifname);
static char path[4096];
- snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, WIFI);
+ snprintf(path, sizeof(path), "%s/%s", IFACE_DIR, ifname);
return wifi_connect_on_socket_path(path);
}
@@ -79,8 +130,8 @@ int wifi_connect_on_socket_path(const char *path)
// establishes the control and monitor socket connections on the interface
ctrl_conn = wpa_ctrl_open(path);
if (ctrl_conn == NULL) {
- qWarning("Unable to open connection to supplicant on \"%s\": %s",
- path, strerror(errno));
+ qCWarning(B2QT_WIFI, "Unable to open connection to supplicant on \"%s\": %s",
+ path, strerror(errno));
return -1;
}
monitor_conn = wpa_ctrl_open(path);
@@ -130,14 +181,14 @@ int wifi_wait_on_socket(char *buf, size_t buflen)
}
if (result < 0) {
- qWarning("wifi_ctrl_recv failed: %s\n", strerror(errno));
+ qCWarning(B2QT_WIFI, "wifi_ctrl_recv failed: %s", strerror(errno));
return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - recv error");
}
buf[nread] = '\0';
/* Check for EOF on the socket */
if (result == 0 && nread == 0) {
/* Fabricate an event to pass up */
- qWarning("Received EOF on supplicant socket\n");
+ qCWarning(B2QT_WIFI, "Received EOF on supplicant socket");
return snprintf(buf, buflen, WPA_EVENT_TERMINATING " - signal 0 received");
}
/*
@@ -152,7 +203,7 @@ int wifi_wait_on_socket(char *buf, size_t buflen)
* to us, so strip it off.
*/
- if (strncmp(buf, IFNAME, IFNAMELEN) == 0) {
+ if (strncmp(buf, "IFNAME=", (sizeof("IFNAME=") - 1)) == 0) {
match = strchr(buf, ' ');
if (match != NULL) {
if (match[1] == '<') {
@@ -170,11 +221,11 @@ int wifi_wait_on_socket(char *buf, size_t buflen)
if (match != NULL) {
nread -= (match + 1 - buf);
memmove(buf, match + 1, nread + 1);
- //qWarning("supplicant generated event without interface - %s\n", buf);
+ //qCWarning(B2QT_WIFI, "supplicant generated event without interface - %s", buf);
}
} else {
/* let the event go as is! */
- qWarning("supplicant generated event without interface and without message level - %s\n", buf);
+ qCWarning(B2QT_WIFI, "supplicant generated event without interface and without message level - %s", buf);
}
return nread;
@@ -193,7 +244,7 @@ int wifi_ctrl_recv(char *reply, size_t *reply_len)
rfds[1].events |= POLLIN;
res = TEMP_FAILURE_RETRY(poll(rfds, 2, -1));
if (res < 0) {
- qWarning("Error poll = %d", res);
+ qCWarning(B2QT_WIFI, "Error poll = %d", res);
return res;
}
if (rfds[0].revents & POLLIN) {
@@ -210,12 +261,12 @@ int wifi_send_command(const char *cmd, char *reply, size_t *reply_len)
{
int ret;
if (ctrl_conn == NULL) {
- qWarning("Not connected to wpa_supplicant - \"%s\" command dropped.\n", cmd);
+ qCWarning(B2QT_WIFI, "Not connected to wpa_supplicant - \"%s\" command dropped.", cmd);
return -1;
}
ret = wpa_ctrl_request(ctrl_conn, cmd, strlen(cmd), reply, reply_len, NULL);
if (ret == -2) {
- qWarning("'%s' command timed out.\n", cmd);
+ qCWarning(B2QT_WIFI, "'%s' command timed out.", cmd);
/* unblocks the monitor receive socket for termination */
TEMP_FAILURE_RETRY(write(exit_sockets[0], "T", 1));
return -2;
@@ -262,3 +313,5 @@ void wifi_close_sockets()
exit_sockets[1] = -1;
}
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/wifi/qwifi_elinux.h b/src/wifi/qwifielinux_p.h
index a89642f..bef90c3 100644
--- a/src/imports/wifi/qwifi_elinux.h
+++ b/src/wifi/qwifielinux_p.h
@@ -19,9 +19,15 @@
#ifndef LOCAL_WIFI_H
#define LOCAL_WIFI_H
+#include <QtCore/QLoggingCategory>
+
#include <string.h>
-// This API mirrors Android's Wi-Fi libraries interface [1] and implementation, excluding Android OS specific parts.
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+
+// This API mirrors Android's Wi-Fi libraries interface [1] and parts of implementation.
// [1] http://androidxref.com/4.4.2_r2/xref/hardware/libhardware_legacy/include/hardware_legacy/wifi.h
int q_wifi_command(const char *ifname, const char *command, char *reply, size_t *reply_len);
@@ -31,4 +37,6 @@ void q_wifi_close_supplicant_connection(const char *ifname);
int q_wifi_start_supplicant();
int q_wifi_stop_supplicant();
+QT_END_NAMESPACE
+
#endif // LOCAL_WIFI_H
diff --git a/src/wifi/qwifimanager.cpp b/src/wifi/qwifimanager.cpp
new file mode 100644
index 0000000..de35224
--- /dev/null
+++ b/src/wifi/qwifimanager.cpp
@@ -0,0 +1,600 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#include "qwificontroller_p.h"
+#include "qwifinetworklistmodel_p.h"
+#include "qwifinetwork_p.h"
+#include "qwifimanager_p.h"
+#include "qwifidevice.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QProcess>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \qmlmodule QtWifi 1.0
+ \title QtWifi Module
+ \ingroup qtee-qmlmodules
+ \brief A module for managing wireless network connectivity.
+
+ Provides QML types for controlling WiFi networks - handling WiFi backend initialization,
+ retrieving information from nearby WiFi access points, setting up and bringing down WiFi
+ connections, querying DHCP server for IP address.
+
+ The import command for adding these QML types is:
+
+ \code
+ import QtWifi 1.0
+ \endcode
+
+ \section1 API Reference
+*/
+
+/*!
+
+ \qmltype WifiManager
+ \inqmlmodule QtWifi
+ \ingroup wifi-qmltypes
+ \brief Main interface to the WiFi functionality.
+
+ WifiManager is a singleton type that provides information about the WiFi backend and
+ available networks, use it to control the WiFi backend, scan for wireless networks
+ and connect to selected network. WifiManager provides events for backend and network
+ state changes.
+
+ */
+
+/*!
+ \qmlsignal void WifiManager::networkStateChanged(NetworkState networkState)
+
+ This signal is emitted whenever changes in a network state occur. The network name for
+ which the state changes events are send can be obtained from currentSSID.
+
+ \sa networkState
+*/
+
+/*!
+ \qmlsignal void WifiManager::backendStateChanged(BackendState backendState)
+
+ This signal is emitted whenever changes in a backend state occur.
+
+ \sa start, stop
+*/
+
+/*!
+ \qmlsignal void WifiManager::currentSSIDChanged(string currentSSID)
+
+ This signal is emitted when switching between different WiFi networks.
+
+ \sa start, stop
+*/
+
+/*!
+ \qmlsignal void WifiManager::scanningChanged(bool scanning)
+
+ This signal is emitted when device starts or stops to scan for available wifi networks.
+
+ \sa scanning
+
+*/
+
+// must be in the same order as in enum {} definiton
+const char *nsText[] = { "Disconnected", "Authenticating", "HandshakeFailed",
+ "ObtainingIPAddress", "DhcpRequestFailed", "Connected" };
+const char *bsText[] = { "Initializing", "Running", "Terminating", "NotRunning" };
+
+QWifiManagerPrivate::QWifiManagerPrivate(QWifiManager *manager)
+ : q_ptr(manager)
+ , m_networkListModel(new QWifiNetworkListModel())
+ , m_scanTimer(0)
+ , m_scanning(false)
+ , m_interface(QWifiDevice::wifiInterfaceName())
+ , m_backendState(QWifiManager::NotRunning)
+ , m_networkState(QWifiManager::Disconnected)
+ , m_setCurrentSSID(true)
+{
+ qCDebug(B2QT_WIFI) << "using wifi interface: " << m_interface;
+}
+
+QWifiManagerPrivate::~QWifiManagerPrivate()
+{
+ delete m_wifiController;
+ delete m_networkListModel;
+}
+
+QString QWifiManagerPrivate::getConnectedNetwork()
+{
+ QStringList lists = call(QStringLiteral("LIST_NETWORKS")).split('\n');
+ QString connectedNetwork;
+ for (int i = 1; i < lists.size(); ++i) {
+ if (lists.at(i).toUpper().contains(QStringLiteral("[CURRENT]"))) {
+ connectedNetwork = lists.at(i);
+ break;
+ }
+ }
+ return connectedNetwork;
+}
+
+void QWifiManagerPrivate::emitCurrentSSIDChanged()
+{
+ Q_Q(QWifiManager);
+ if (m_previousSSID != m_currentSSID) {
+ qCDebug(B2QT_WIFI) << "current SSID: " << m_previousSSID << " -> " << m_currentSSID;
+ m_previousSSID = m_currentSSID;
+ emit q->currentSSIDChanged(m_currentSSID);
+ }
+}
+
+void QWifiManagerPrivate::setCurrentSSID()
+{
+ qCDebug(B2QT_WIFI, "setCurrentSSID");
+ m_setCurrentSSID = false;
+ QString connectedNetwork = getConnectedNetwork();
+ if (!connectedNetwork.isEmpty()) {
+ QString ssid = connectedNetwork.split('\t').at(1);
+ QWifiNetwork *network = m_networkListModel->networkForSSID(ssid);
+ if (network) {
+ m_currentSSID = network->ssid();
+ emitCurrentSSIDChanged();
+ if (call(QStringLiteral("STATUS")).contains(QStringLiteral("wpa_state=COMPLETED")))
+ updateNetworkState(QWifiManager::Connected);
+ }
+ }
+}
+
+void QWifiManagerPrivate::handleConnected()
+{
+ qCDebug(B2QT_WIFI, "handleConnected");
+ QString connectedNetwork = getConnectedNetwork();
+ if (connectedNetwork.isEmpty())
+ return;
+
+ m_currentSSID = connectedNetwork.split('\t').at(1);
+ qCDebug(B2QT_WIFI) << "connected network: " << m_currentSSID;
+ updateNetworkState(QWifiManager::ObtainingIPAddress);
+ m_wifiController->call(QWifiController::AcquireIPAddress);
+}
+
+void QWifiManagerPrivate::handleDisconneced()
+{
+ updateNetworkState(QWifiManager::Disconnected);
+}
+
+void QWifiManagerPrivate::updateNetworkState(QWifiManager::NetworkState networkState)
+{
+ Q_Q(QWifiManager);
+ qCDebug(B2QT_WIFI, "network state: %s -> %s", nsText[m_networkState], nsText[networkState]);
+ if (m_networkState == networkState)
+ return;
+
+ m_networkState = networkState;
+ emit q->networkStateChanged(m_networkState);
+}
+
+void QWifiManagerPrivate::updateBackendState(QWifiManager::BackendState backendState)
+{
+ Q_Q(QWifiManager);
+ qCDebug(B2QT_WIFI, "backend state: %s -> %s", bsText[m_backendState], bsText[backendState]);
+ if (m_backendState == backendState)
+ return;
+
+ m_backendState = backendState;
+ emit q->backendStateChanged(m_backendState);
+}
+
+void QWifiManagerPrivate::updateWifiState()
+{
+ bool supplicantRunning = false;
+#ifdef Q_OS_ANDROID_NO_SDK
+ char supplicantState[PROPERTY_VALUE_MAX];
+ if (property_get("init.svc.wpa_supplicant", supplicantState, 0)) {
+ if (strcmp(supplicantState, "running") == 0)
+ supplicantRunning = true;
+ }
+#else
+ QProcess ps;
+ ps.start(QStringLiteral("ps"));
+ ps.waitForFinished();
+ if (ps.readAll().contains("wpa_supplicant"))
+ supplicantRunning = true;
+#endif
+ if (supplicantRunning) {
+ m_wifiController->resetSupplicantSocket();
+ m_wifiController->startWifiEventThread();
+ m_backendState = QWifiManager::Running;
+ }
+}
+
+QString QWifiManagerPrivate::call(const QString &command)
+{
+ if (m_backendState != QWifiManager::Running)
+ return QString();
+
+ char data[2048];
+ size_t len = sizeof(data) - 1; // -1: room to add a 0-terminator
+ QString actualCommand = command;
+#ifdef Q_OS_ANDROID_NO_SDK
+#if !(Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR < 4)
+ QString prefix = QLatin1String("IFNAME=" + m_interface + " ");
+ actualCommand.prepend(prefix);
+#endif
+#endif
+ if (q_wifi_command(m_interface, actualCommand.toLatin1(), data, &len) < 0) {
+ qCDebug(B2QT_WIFI) << "call to supplicant failed: " << actualCommand;
+ return QString();
+ }
+ if (len < sizeof(data))
+ data[len] = 0;
+
+ QString result = QLatin1String(data);
+ return result;
+}
+
+bool QWifiManagerPrivate::checkedCall(const QString &command)
+{
+ return call(command).trimmed().toUpper() == QLatin1String("OK");
+}
+
+void QWifiManagerPrivate::updateLastError(const QString &error)
+{
+ Q_Q(QWifiManager);
+ qCWarning(B2QT_WIFI) << error;
+ m_lastError = error;
+ emit q->lastErrorChanged(m_lastError);
+}
+
+
+QWifiManager* QWifiManager::m_instance = 0;
+QWifiManager* QWifiManager::instance()
+{
+ if (!m_instance)
+ m_instance = new QWifiManager();
+ return m_instance;
+}
+
+QWifiManager::QWifiManager()
+ : d_ptr(new QWifiManagerPrivate(this))
+{
+ Q_D(QWifiManager);
+
+ if (!QWifiDevice::wifiSupported())
+ qCWarning(B2QT_WIFI) << "WifiManager may not work as expected on this device. Use the API provided by QtWifi "
+ "library to verify if device has support for Wi-Fi before creating an instance of wifi manager!";
+
+ d->m_wifiController = new QWifiController(this, d_ptr);
+ QObject::connect(d->m_wifiController, &QWifiController::backendStateChanged,
+ this, &QWifiManager::handleBackendStateChanged);
+ QObject::connect(d->m_wifiController, &QWifiController::dhcpRequestFinished,
+ this, &QWifiManager::handleDhcpRequestFinished);
+ d->m_wifiController->start();
+
+ d->updateWifiState();
+}
+
+QWifiManager::~QWifiManager()
+{
+ Q_D(QWifiManager);
+ d->m_wifiController->call(QWifiController::ExitEventLoop);
+ d->m_wifiController->wait();
+ delete d_ptr;
+}
+
+/*!
+ \qmlproperty WifiNetworkListModel WifiManager::networks
+ \readonly
+
+ This property holds a list of networks that can be sensed by a device. Use the returned
+ model as data model in ListView, model is updated every 5 seconds.
+
+ WifiNetworkListModel is a simple data model consisting of WifiNetwork objects, accessed with
+ the "network" data role name. Instances of WifiNetwork cannot be created directly from the QML system.
+
+*/
+
+QAbstractListModel *QWifiManager::networks() const
+{
+ Q_D(const QWifiManager);
+ return d->m_networkListModel;
+}
+
+/*!
+ \qmlproperty string WifiManager::currentSSID
+ \readonly
+
+ This property holds the network name for which the networkState changes events are sent or
+ or an empty string when there is no active network.
+*/
+
+QString QWifiManager::currentSSID() const
+{
+ Q_D(const QWifiManager);
+ return d->m_currentSSID;
+}
+
+/*!
+ \qmlproperty enumeration WifiManager::networkState
+ \readonly
+
+ This property holds the current state of the network connection.
+
+ \list
+ \li \e WifiManager.Disconnected - Not connected to any network
+ \li \e WifiManager.Authenticating - Verifying password with the network provider
+ \li \e WifiManager.HandshakeFailed - Incorrect password provided
+ \li \e WifiManager.ObtainingIPAddress - Requesting IP address from DHCP server
+ \li \e WifiManager.DhcpRequestFailed - Could not retrieve IP address
+ \li \e WifiManager.Connected - Ready to process network requests
+ \endlist
+*/
+
+QWifiManager::NetworkState QWifiManager::networkState() const
+{
+ Q_D(const QWifiManager);
+ return d->m_networkState;
+}
+
+/*!
+ \qmlproperty enumeration WifiManager::backendState
+ \readonly
+
+ This property holds the current state of the WiFi backend.
+
+ \list
+ \li \e WifiManager.Initializing - Wireless supplicant is starting up
+ \li \e WifiManager.Running - Supplicant is initialized and ready to process commands
+ \li \e WifiManager.Terminating - Shutting down wireless supplicant
+ \li \e WifiManager.NotRunning - Wireless supplicant process is not running
+ \endlist
+*/
+
+QWifiManager::BackendState QWifiManager::backendState() const
+{
+ Q_D(const QWifiManager);
+ return d->m_backendState;
+}
+
+/*!
+ \qmlmethod void WifiManager::start()
+
+ Start the WiFi backend. This function returns immediately, the backendState
+ change events are delivered asynchronously.
+
+ \sa stop, backendState
+ */
+
+void QWifiManager::start()
+{
+ Q_D(QWifiManager);
+ d->m_wifiController->call(QWifiController::InitializeBackend);
+}
+
+/*!
+ \qmlmethod void WifiManager::stop()
+
+ Stop the WiFi backend and if connected to any network shut down network connection.
+ This function returns immediately, the backendState change events are delivered asynchronously.
+
+ \sa start, backendState
+ */
+
+void QWifiManager::stop()
+{
+ Q_D(QWifiManager);
+ d->m_wifiController->call(QWifiController::TerminateBackend);
+}
+
+void QWifiManager::handleBackendStateChanged(BackendState backendState)
+{
+ Q_D(QWifiManager);
+ switch (backendState) {
+ case Running:
+ d->m_setCurrentSSID = true;
+ break;
+ case NotRunning:
+ d->updateNetworkState(Disconnected);
+ break;
+ default:
+ break;
+ }
+ d->updateBackendState(backendState);
+}
+
+void QWifiManager::handleDhcpRequestFinished(const QString &status)
+{
+ Q_D(QWifiManager);
+ qCDebug(B2QT_WIFI) << "handleDhcpRequestFinished: " << status << " for " << d->m_currentSSID;
+ if (status == QLatin1String("success")) {
+ d->emitCurrentSSIDChanged();
+ d->updateNetworkState(Connected);
+ d->call(QStringLiteral("SAVE_CONFIG"));
+ } else {
+ d->updateNetworkState(DhcpRequestFailed);
+ }
+}
+
+void QWifiManager::setScanning(bool scanning)
+{
+ Q_D(QWifiManager);
+ if (d->m_scanning == scanning)
+ return;
+
+ d->m_scanning = scanning;
+ emit scanningChanged(d->m_scanning);
+ if (d->m_scanning) {
+ d->call(QStringLiteral("SCAN"));
+ // ### TODO android has property for this - wifi.supplicant_scan_interval
+ d->m_scanTimer = startTimer(5000);
+ } else {
+ killTimer(d->m_scanTimer);
+ }
+}
+
+/*!
+ \qmlproperty bool WifiManager::scanning
+
+ This property holds whether or not the backend is scanning for WiFi networks. To
+ preserve battery energy, set this property to false when scanning is not required.
+
+ Before starting to scan for networks, you need to initialize the WiFi backend.
+
+ \sa start
+*/
+
+bool QWifiManager::scanning() const
+{
+ Q_D(const QWifiManager);
+ return d->m_scanning;
+}
+
+QString QWifiManager::lastError() const
+{
+ Q_D(const QWifiManager);
+ return d->m_lastError;
+}
+
+bool QWifiManager::event(QEvent *event)
+{
+ Q_D(QWifiManager);
+ switch ((int) event->type()) {
+ case WIFI_SCAN_RESULTS:
+ d->m_networkListModel->parseScanResults(d->call(QStringLiteral("SCAN_RESULTS")));
+ if (d->m_setCurrentSSID || d->m_currentSSID.isEmpty())
+ d->setCurrentSSID();
+ return true;
+ case WIFI_CONNECTED:
+ d->handleConnected();
+ return true;
+ case WIFI_DISCONNECTED:
+ d->handleDisconneced();
+ return true;
+ case WIFI_AUTHENTICATING:
+ d->updateNetworkState(Authenticating);
+ d->emitCurrentSSIDChanged();
+ return true;
+ case WIFI_HANDSHAKE_FAILED:
+ d->updateNetworkState(HandshakeFailed);
+ return true;
+ case QEvent::Timer: {
+ int tid = static_cast<QTimerEvent *>(event)->timerId();
+ if (tid == d->m_scanTimer) {
+ d->call(QStringLiteral("SCAN"));
+ return true;
+ }
+ break;
+ }
+ }
+ return QObject::event(event);
+}
+
+
+/*!
+ \qmlmethod void WifiManager::connect(WifiNetwork network, string passphrase)
+
+ Connect to network \a network and use passphrase \a passphrase for authentication.
+
+ \sa disconnect, networkState
+ */
+
+bool QWifiManager::connect(QWifiConfiguration *config)
+{
+ Q_D(QWifiManager);
+ if (d->m_backendState != Running) {
+ qCWarning(B2QT_WIFI) << "start wifi backend before calling connect() !";
+ return false;
+ }
+
+ d->call(QStringLiteral("DISABLE_NETWORK all"));
+
+ d->m_currentSSID = config->ssid();
+ bool networkKnown = false;
+ QString id;
+ QString listResult = d->call(QStringLiteral("LIST_NETWORKS"));
+ QStringList lines = listResult.split('\n');
+ foreach (const QString &line, lines) {
+ if (line.contains(d->m_currentSSID)) {
+ id = line.split('\t').at(0);
+ networkKnown = true;
+ break;
+ }
+ }
+
+ if (!networkKnown) {
+ bool ok;
+ id = d->call(QStringLiteral("ADD_NETWORK")).trimmed();
+ id.toInt(&ok);
+ if (!ok) {
+ d->updateLastError(QStringLiteral("failed to add network!"));
+ return false;
+ }
+ }
+
+ bool ok = true;
+ QChar q = QLatin1Char('"');
+ QString setNetworkCommand = QLatin1String("SET_NETWORK ") + id;
+ if (!networkKnown) {
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" ssid ") + q + d->m_currentSSID + q);
+ }
+
+ QString key_mgmt;
+ QString protocol = config->protocol().toUpper();
+ QString psk = config->passphrase();
+ // ref: http://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
+ if (protocol.isEmpty() || protocol.contains(QStringLiteral("WPA"))) {
+ // ### todo - password length has limits (see IEEE 802.11), we need to check
+ // for those limits here. Supplicant gives only a meaningless "fail" message.
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" psk ") + q + psk + q);
+ key_mgmt = QLatin1String("WPA-PSK");
+ } else if (protocol.contains(QStringLiteral("WEP"))) {
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" wep_key0 ") + q + psk + q);
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" auth_alg OPEN SHARED"));
+ key_mgmt = QLatin1String("NONE");
+ } else if (protocol.contains(QStringLiteral("WPS")) && psk.length() == 0) {
+ // open network
+ key_mgmt = QLatin1String("NONE");
+ }
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" key_mgmt ") + key_mgmt);
+ if (!ok) {
+ if (!networkKnown)
+ d->call(QLatin1String("REMOVE_NETWORK ") + id);
+ d->updateLastError(QLatin1String("failed to set properties on network: ") + id);
+ return false;
+ }
+
+ d->call(QLatin1String("SELECT_NETWORK ") + id);
+ d->call(QStringLiteral("RECONNECT"));
+
+ return true;
+}
+
+/*!
+ \qmlmethod void WifiManager::disconnect()
+
+ Disconnect from currently connected network connection.
+
+ \sa connect, networkState
+*/
+
+void QWifiManager::disconnect()
+{
+ Q_D(QWifiManager);
+ d->call(QStringLiteral("DISCONNECT"));
+ d->m_wifiController->call(QWifiController::StopDhcp);
+}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwifimanager.h b/src/wifi/qwifimanager.h
new file mode 100644
index 0000000..cd55f4d
--- /dev/null
+++ b/src/wifi/qwifimanager.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#ifndef QWIFIMANAGER_H
+#define QWIFIMANAGER_H
+
+#include "qwificonfiguration.h"
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
+#include <QtCore/QLoggingCategory>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+
+class QWifiManagerPrivate;
+class QAbstractListModel;
+class QWifiController;
+class QWifiNetworkListModel;
+
+class Q_DECL_EXPORT QWifiManager : public QObject
+{
+ Q_OBJECT
+ Q_ENUMS(NetworkState)
+ Q_ENUMS(BackendState)
+ Q_PROPERTY(NetworkState networkState READ networkState NOTIFY networkStateChanged)
+ Q_PROPERTY(BackendState backendState READ backendState NOTIFY backendStateChanged)
+ Q_PROPERTY(bool scanning READ scanning WRITE setScanning NOTIFY scanningChanged)
+ Q_PROPERTY(QString currentSSID READ currentSSID NOTIFY currentSSIDChanged)
+ Q_PROPERTY(QString lastError READ lastError NOTIFY lastErrorChanged)
+ Q_PROPERTY(QAbstractListModel *networks READ networks CONSTANT)
+public:
+ enum NetworkState {
+ Disconnected,
+ Authenticating,
+ HandshakeFailed,
+ ObtainingIPAddress,
+ DhcpRequestFailed,
+ Connected
+ };
+
+ enum BackendState {
+ Initializing,
+ Running,
+ Terminating,
+ NotRunning
+ };
+
+ enum Roles {
+ SSIDRole = Qt::UserRole + 1,
+ BSSIDRole = Qt::UserRole + 2,
+ SignalRole = Qt::UserRole + 3,
+ WPARole = Qt::UserRole + 4,
+ WPA2Role = Qt::UserRole + 5,
+ WEPRole = Qt::UserRole + 6,
+ WPSRole = Qt::UserRole + 7
+ };
+
+ static QWifiManager *instance();
+ virtual ~QWifiManager();
+
+ QAbstractListModel *networks() const;
+ QString currentSSID() const;
+ bool scanning() const;
+ void setScanning(bool scanning);
+ NetworkState networkState() const;
+ BackendState backendState() const;
+ QString lastError() const;
+
+public slots:
+ void start();
+ void stop();
+ bool connect(QWifiConfiguration *config);
+ void disconnect();
+
+signals:
+ void scanningChanged(bool scanning);
+ void networkStateChanged(NetworkState networkState);
+ void backendStateChanged(BackendState backendState);
+ void currentSSIDChanged(const QString &currentSSID);
+ void lastErrorChanged(const QString &error);
+
+protected:
+ bool event(QEvent *event);
+
+private slots:
+ void handleBackendStateChanged(BackendState backendState);
+ void handleDhcpRequestFinished(const QString &status);
+
+private:
+ QWifiManager();
+ static QWifiManager* m_instance;
+ friend class QWifiController;
+ Q_DISABLE_COPY(QWifiManager)
+ Q_DECLARE_PRIVATE(QWifiManager)
+ QWifiManagerPrivate *const d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFIMANAGER_H
diff --git a/src/wifi/qwifimanager_p.h b/src/wifi/qwifimanager_p.h
new file mode 100644
index 0000000..ef8a0da
--- /dev/null
+++ b/src/wifi/qwifimanager_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#ifndef QWIFIMANAGER_P_H
+#define QWIFIMANAGER_P_H
+
+#include "qwifimanager.h"
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QWifiManagerPrivate
+{
+ Q_DECLARE_PUBLIC(QWifiManager)
+public:
+ QWifiManagerPrivate(QWifiManager *manager);
+ virtual ~QWifiManagerPrivate();
+
+ // methods
+ QString getConnectedNetwork();
+ void setCurrentSSID();
+ void emitCurrentSSIDChanged();
+ void handleConnected();
+ void handleDisconneced();
+
+ void updateNetworkState(QWifiManager::NetworkState networkState);
+ void updateBackendState(QWifiManager::BackendState backendState);
+ void updateWifiState();
+
+ QString call(const QString &command);
+ bool checkedCall(const QString &command);
+ void updateLastError(const QString &error);
+
+ // member variables
+ QWifiManager *const q_ptr;
+ QWifiController *m_wifiController;
+ QWifiNetworkListModel *m_networkListModel;
+
+ int m_scanTimer;
+ bool m_scanning;
+ QByteArray m_interface;
+ QWifiManager::BackendState m_backendState;
+ QWifiManager::NetworkState m_networkState;
+ bool m_setCurrentSSID;
+ QString m_currentSSID;
+ QString m_previousSSID;
+ QString m_lastError;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFIMANAGER_P_H
diff --git a/src/imports/wifi/qwifinetwork.cpp b/src/wifi/qwifinetwork.cpp
index 84e3b5b..937cbfc 100644
--- a/src/imports/wifi/qwifinetwork.cpp
+++ b/src/wifi/qwifinetwork.cpp
@@ -16,20 +16,24 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#include "qwifinetwork.h"
+#include "qwifinetwork_p.h"
+
+QT_BEGIN_NAMESPACE
/*!
\qmltype WifiNetwork
- \inqmlmodule Qt.labs.wifi
+ \inqmlmodule QtWifi
\ingroup wifi-qmltypes
\brief Represents a single WiFi network access point.
- Instances of WifiNetwork cannot be created directly from the QML system, use
- WifiManager::networks.
+ WifiNetwork provides a various information about WiFi network, like network
+ name, siganl strength and supported security protocols. Instances of WifiNetwork cannot
+ be created directly from the QML system, see WifiManager::networks.
*/
/*!
\qmlproperty string WifiNetwork::bssid
+ \readonly
This property holds basic service set identification of a network, used to uniquely
identify BSS.
@@ -38,12 +42,14 @@
/*!
\qmlproperty string WifiNetwork::ssid
+ \readonly
This property holds a network name. The SSID is the informal (human) name of BSS.
*/
/*!
\qmlproperty int WifiNetwork::signalStrength
+ \readonly
This property holds the current strength of a WiFi signal, measured in dBm. New readings are
taken every 5 seconds.
@@ -53,24 +59,28 @@
/*!
\qmlproperty bool WifiNetwork::supportsWPA
+ \readonly
This property holds whether network access point supports WPA security protocol.
*/
/*!
\qmlproperty bool WifiNetwork::supportsWPA2
+ \readonly
This property holds whether network access point supports WPA2 security protocol.
*/
/*!
\qmlproperty bool WifiNetwork::supportsWEP
+ \readonly
This property holds whether network access point supports WEP security protocol.
*/
/*!
\qmlproperty bool WifiNetwork::supportsWPS
+ \readonly
This property holds whether network access point supports WPS security protocol.
*/
@@ -83,22 +93,29 @@
*/
-QWifiNetwork::QWifiNetwork() :
- m_outOfRange(false)
+QWifiNetwork::QWifiNetwork(QObject *parent)
+ : QObject(parent)
+ , m_isOutOfRange(false)
+{
+}
+
+QWifiNetwork::~QWifiNetwork()
{
}
+void QWifiNetwork::setSsid(const QString &ssid)
+{
+ m_ssid = ssid;
+}
+
void QWifiNetwork::setSignalStrength(int strength)
{
- if (m_signalStrength == strength)
- return;
m_signalStrength = strength;
- emit signalStrengthChanged(m_signalStrength);
}
void QWifiNetwork::setOutOfRange(bool outOfRange)
{
- if (m_outOfRange == outOfRange)
- return;
- m_outOfRange = outOfRange;
+ m_isOutOfRange = outOfRange;
}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwifinetwork_p.h b/src/wifi/qwifinetwork_p.h
new file mode 100644
index 0000000..db65e2d
--- /dev/null
+++ b/src/wifi/qwifinetwork_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc
+** All rights reserved.
+** For any questions to Digia, please use the contact form at
+** http://www.qt.io
+**
+** This file is part of Qt Enterprise Embedded.
+**
+** Licensees holding valid Qt Enterprise licenses may use this file in
+** accordance with the Qt Enterprise License Agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia.
+**
+** If you have questions regarding the use of this file, please use
+** the contact form at http://www.qt.io
+**
+****************************************************************************/
+#ifndef QWIFINETWORK_H
+#define QWIFINETWORK_H
+
+#include <QtCore/QObject>
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QWifiNetwork : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QWifiNetwork(QObject *parent = 0);
+ virtual ~QWifiNetwork();
+
+ void setBssid(const QString &bssid) { m_bssid = bssid; }
+ QString bssid() const { return m_bssid; }
+ void setSsid(const QString &ssid);
+ QString ssid() const { return m_ssid; }
+
+ void setSignalStrength(int strength);
+ int signalStrength() const { return m_signalStrength; }
+
+ void setOutOfRange(bool isOutOfRange);
+ // this could be exposed in QWifiManager::Roles,
+ // if there is a use case for it, this would require keeping
+ // the out of range networks in data model, currently they are
+ // removed from the model.
+ bool isOutOfRange() const { return m_isOutOfRange; }
+
+ void setFlags(const QString &flags) { m_flags = flags; }
+ QString flags() const { return m_flags; }
+ bool supportsWPA2() const { return m_flags.contains(QStringLiteral("WPA2")); }
+ bool supportsWPA() const { return m_flags.contains(QStringLiteral("WPA")); }
+ bool supportsWEP() const { return m_flags.contains(QStringLiteral("WEP")); }
+ bool supportsWPS() const { return m_flags.contains(QStringLiteral("WPS")); }
+
+private:
+ QString m_bssid;
+ QString m_ssid;
+ int m_signalStrength;
+ QString m_flags;
+ bool m_isOutOfRange;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFINETWORK_H
diff --git a/src/imports/wifi/qwifinetworklistmodel.cpp b/src/wifi/qwifinetworklistmodel.cpp
index 1886413..7a5de2a 100644
--- a/src/imports/wifi/qwifinetworklistmodel.cpp
+++ b/src/wifi/qwifinetworklistmodel.cpp
@@ -16,14 +16,19 @@
** the contact form at http://www.qt.io
**
****************************************************************************/
-#include "qwifinetworklistmodel.h"
+#include "qwifinetworklistmodel_p.h"
+#include "qwifinetwork_p.h"
-#include <QtCore>
+#include "qwifimanager.h"
-const int ID_NETWORK = (Qt::ItemDataRole) (Qt::UserRole + 1);
+#include <QtCore/QSet>
+#include <QtCore/QString>
+#include <QtCore/QByteArray>
-QWifiNetworkListModel::QWifiNetworkListModel(QWifiManager *manager)
- : m_manager(manager)
+QT_BEGIN_NAMESPACE
+
+QWifiNetworkListModel::QWifiNetworkListModel(QObject *parent)
+ : QAbstractListModel(parent)
{
}
@@ -38,23 +43,56 @@ QWifiNetworkListModel::~QWifiNetworkListModel()
QHash<int, QByteArray> QWifiNetworkListModel::roleNames() const
{
QHash<int, QByteArray> names;
- names.insert(ID_NETWORK, "network");
+ names.insert(QWifiManager::SSIDRole, "ssid");
+ names.insert(QWifiManager::BSSIDRole, "bssid");
+ names.insert(QWifiManager::SignalRole, "signalStrength");
+ names.insert(QWifiManager::WPARole, "supportsWPA");
+ names.insert(QWifiManager::WPA2Role, "supportsWPA2");
+ names.insert(QWifiManager::WEPRole, "supportsWEP");
+ names.insert(QWifiManager::WPSRole, "supportsWPS");
return names;
}
QVariant QWifiNetworkListModel::data(const QModelIndex &index, int role) const
{
QWifiNetwork *n = m_networks.at(index.row());
+
switch (role) {
- case ID_NETWORK: return QVariant::fromValue((QObject *) n);
+ case QWifiManager::SSIDRole:
+ return n->ssid();
+ break;
+ case QWifiManager::BSSIDRole:
+ return n->bssid();
+ break;
+ case QWifiManager::SignalRole:
+ return n->signalStrength();
+ break;
+ case QWifiManager::WPARole:
+ return n->supportsWPA();
+ break;
+ case QWifiManager::WPA2Role:
+ return n->supportsWPA2();
+ break;
+ case QWifiManager::WEPRole:
+ return n->supportsWEP();
+ break;
+ case QWifiManager::WPSRole:
+ return n->supportsWPS();
+ break;
+ default:
+ break;
}
- qWarning("QWifiNetworkListModel::data(), undefined role: %d\n", role);
-
return QVariant();
}
-QWifiNetwork *QWifiNetworkListModel::networkForSSID(const QByteArray &ssid, int *pos)
+QWifiNetwork *QWifiNetworkListModel::networkForSSID(const QString &ssid)
+{
+ int pos = 0; // unused
+ return networkForSSID(ssid, &pos);
+}
+
+QWifiNetwork *QWifiNetworkListModel::networkForSSID(const QString &ssid, int *pos)
{
for (int i = 0; i < m_networks.size(); ++i) {
if (m_networks.at(i)->ssid() == ssid) {
@@ -66,7 +104,7 @@ QWifiNetwork *QWifiNetworkListModel::networkForSSID(const QByteArray &ssid, int
return 0;
}
-QWifiNetwork *QWifiNetworkListModel::outOfRangeListContains(const QByteArray &ssid)
+QWifiNetwork *QWifiNetworkListModel::outOfRangeListContains(const QString &ssid)
{
for (int i = 0; i < m_outOfRangeNetworks.length(); ++i)
if (m_outOfRangeNetworks.at(i)->ssid() == ssid)
@@ -74,20 +112,22 @@ QWifiNetwork *QWifiNetworkListModel::outOfRangeListContains(const QByteArray &ss
return 0;
}
-void QWifiNetworkListModel::parseScanResults(const QByteArray &results)
+void QWifiNetworkListModel::parseScanResults(const QString &results)
{
- QList<QByteArray> lines = results.split('\n');
- QSet<QByteArray> sensibleNetworks;
+ QStringList lines = results.split('\n');
+ QSet<QString> sensibleNetworks;
for (int i = 1; i < lines.size(); ++i) {
- QList<QByteArray> info = lines.at(i).split('\t');
+ QStringList info = lines.at(i).split('\t');
if (info.size() < 5 || info.at(4).isEmpty() || info.at(0).isEmpty())
continue;
int pos = 0;
- sensibleNetworks.insert(info.at(4));
- QWifiNetwork *knownNetwork = networkForSSID(info.at(4), &pos);
+
+ QString ssid = info.at(4);
+ sensibleNetworks.insert(ssid);
+ QWifiNetwork *knownNetwork = networkForSSID(ssid, &pos);
if (!knownNetwork)
- knownNetwork = outOfRangeListContains(info.at(4));
+ knownNetwork = outOfRangeListContains(ssid);
// signal strength is in dBm. Deprecated, but still widely used "wext"
// wifi driver reports positive values for signal strength, we workaround that.
int signalStrength = qAbs(info.at(2).trimmed().toInt()) * -1;
@@ -97,12 +137,12 @@ void QWifiNetworkListModel::parseScanResults(const QByteArray &results)
network->setBssid(info.at(0));
network->setFlags(info.at(3));
network->setSignalStrength(signalStrength);
- network->setSsid(info.at(4));
+ network->setSsid(ssid);
beginInsertRows(QModelIndex(), m_networks.size(), m_networks.size());
m_networks << network;
endInsertRows();
} else {
- if (knownNetwork->outOfRange()) {
+ if (knownNetwork->isOutOfRange()) {
// known network has come back into a range
knownNetwork->setOutOfRange(false);
beginInsertRows(QModelIndex(), m_networks.size(), m_networks.size());
@@ -122,7 +162,7 @@ void QWifiNetworkListModel::parseScanResults(const QByteArray &results)
m_networks.at(pos)->setBssid(info.at(0));
m_networks.at(pos)->setFlags(info.at(3));
m_networks.at(pos)->setSignalStrength(signalStrength);
- m_networks.at(pos)->setSsid(info.at(4));
+ m_networks.at(pos)->setSsid(ssid);
dataChanged(createIndex(pos, 0), createIndex(pos, 0));
}
}
@@ -140,3 +180,5 @@ void QWifiNetworkListModel::parseScanResults(const QByteArray &results)
}
}
}
+
+QT_END_NAMESPACE
diff --git a/src/imports/wifi/qwifinetworklistmodel.h b/src/wifi/qwifinetworklistmodel_p.h
index 0cb9846..25a2b31 100644
--- a/src/imports/wifi/qwifinetworklistmodel.h
+++ b/src/wifi/qwifinetworklistmodel_p.h
@@ -20,35 +20,38 @@
#define QWIFINETWORKLISTMODEL_H
#include <QtCore/QAbstractListModel>
+#include <QtCore/QVariant>
#include <QtCore/QList>
+#include <QtCore/QHash>
+#include <QtCore/QLoggingCategory>
-#include "qwifinetwork.h"
+QT_BEGIN_NAMESPACE
-class QWifiManager;
+Q_DECLARE_LOGGING_CATEGORY(B2QT_WIFI)
+
+class QWifiNetwork;
class QWifiNetworkListModel : public QAbstractListModel
{
Q_OBJECT
-
public:
-
- QWifiNetworkListModel(QWifiManager *manager);
- ~QWifiNetworkListModel();
-
- void parseScanResults(const QByteArray &data);
-
- QWifiNetwork *networkForSSID(const QByteArray &ssid, int *pos);
- QWifiNetwork *outOfRangeListContains(const QByteArray &ssid);
+ explicit QWifiNetworkListModel(QObject *parent = 0);
+ virtual ~QWifiNetworkListModel();
int rowCount(const QModelIndex &) const { return m_networks.size(); }
QVariant data(const QModelIndex &index, int role) const;
-
QHash<int,QByteArray> roleNames() const;
+ void parseScanResults(const QString &data);
+ QWifiNetwork *networkForSSID(const QString &ssid);
+ QWifiNetwork *networkForSSID(const QString &ssid, int *pos);
+ QWifiNetwork *outOfRangeListContains(const QString &ssid);
+
private:
- QWifiManager *m_manager;
QList<QWifiNetwork *> m_networks;
QList<QWifiNetwork *> m_outOfRangeNetworks;
};
+QT_END_NAMESPACE
+
#endif // QWIFINETWORKLISTMODEL_H
diff --git a/src/wifi/wifi.pro b/src/wifi/wifi.pro
new file mode 100644
index 0000000..e558081
--- /dev/null
+++ b/src/wifi/wifi.pro
@@ -0,0 +1,43 @@
+load(qt_build_config)
+
+TARGET = B2QtWifi
+VERSION = 1.0
+CONFIG += dll warn_on
+
+QT += core network
+
+MODULE = b2qtwifi
+load(qt_module)
+
+HEADERS += \
+ $$PWD/qwifimanager.h \
+ $$PWD/qwifimanager_p.h \
+ $$PWD/qwifinetwork_p.h \
+ $$PWD/qwifinetworklistmodel_p.h \
+ $$PWD/qwificontroller_p.h \
+ $$PWD/qwifidevice.h \
+ $$PWD/qwificonfiguration.h
+
+SOURCES += \
+ $$PWD/qwifimanager.cpp \
+ $$PWD/qwifinetwork.cpp \
+ $$PWD/qwifinetworklistmodel.cpp \
+ $$PWD/qwificontroller.cpp \
+ $$PWD/qwifidevice.cpp \
+ $$PWD/qwificonfiguration.cpp
+
+android: {
+ LIBS += -lhardware_legacy -lcutils
+} else {
+ DEFINES += \
+ CONFIG_CTRL_IFACE \
+ CONFIG_CTRL_IFACE_UNIX
+
+ HEADERS += \
+ $$PWD/qwifielinux_p.h
+
+ SOURCES += \
+ $$PWD/qwifielinux.cpp \
+ $$[QT_SYSROOT]/usr/include/wpa-supplicant/wpa_ctrl.c \
+ $$[QT_SYSROOT]/usr/include/wpa-supplicant/os_unix.c
+}
diff --git a/sync.profile b/sync.profile
index ede245e..26efc65 100644
--- a/sync.profile
+++ b/sync.profile
@@ -1,5 +1,6 @@
%modules = ( # path to module name map
- "B2QtUtils" => "$basedir/src/utils"
+ "B2QtUtils" => "$basedir/src/utils",
+ "B2QtWifi" => "$basedir/src/wifi"
);
%moduleheaders = ( # restrict the module headers to those found in relative path
);