diff options
Diffstat (limited to 'src/imports/wifi')
-rw-r--r-- | src/imports/wifi/pluginmain.cpp | 59 | ||||
-rw-r--r-- | src/imports/wifi/qwifimanager.cpp | 356 | ||||
-rw-r--r-- | src/imports/wifi/qwifimanager.h | 83 | ||||
-rw-r--r-- | src/imports/wifi/qwifinetwork.cpp | 18 | ||||
-rw-r--r-- | src/imports/wifi/qwifinetwork.h | 18 | ||||
-rw-r--r-- | src/imports/wifi/qwifinetworklist.cpp | 64 | ||||
-rw-r--r-- | src/imports/wifi/qwifinetworklist.h | 20 | ||||
-rw-r--r-- | src/imports/wifi/wifi.pro (renamed from src/imports/wifi/qwifimodule.pro) | 2 |
8 files changed, 413 insertions, 207 deletions
diff --git a/src/imports/wifi/pluginmain.cpp b/src/imports/wifi/pluginmain.cpp index c9dac53..3c560f9 100644 --- a/src/imports/wifi/pluginmain.cpp +++ b/src/imports/wifi/pluginmain.cpp @@ -1,8 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #include "qwifimanager.h" +#include <QtCore/QDir> +#include <QtCore/QByteArray> #include <QtQml/QQmlExtensionPlugin> #include <QtQml/qqml.h> +#include <hardware_legacy/wifi.h> + +class QWifiGlobal : public QObject +{ + Q_OBJECT +public: + explicit QWifiGlobal(QObject *parent = 0) + : QObject(parent) {} + ~QWifiGlobal() {} + + Q_INVOKABLE bool wifiSupported() const + { + bool supported = false; + if (wifi_load_driver() == 0 && wifi_start_supplicant(0) == 0) { + char interface[PROPERTY_VALUE_MAX]; + property_get("wifi.interface", interface, NULL); + // standard linux kernel path + QByteArray path; + path.append("/sys/class/net/").append(interface); + supported = QDir().exists(path.constData()); + if (!supported) + qWarning() << "QWifiGlobal: could not find wifi interface in " << path; + } else { + qWarning() << "QWifiGlobal: wifi driver is not available"; + } + return supported; + } +}; + +static QObject *global_object_wifi(QQmlEngine *, QJSEngine *) +{ + return new QWifiGlobal; +} + class QWifiPlugin : public QQmlExtensionPlugin { Q_OBJECT @@ -13,11 +67,10 @@ public: { Q_ASSERT(QLatin1String(uri) == QLatin1String("Qt.labs.wifi")); - qmlRegisterType<QWifiManager>(uri, 0, 1, "QWifiManager"); + qmlRegisterType<QWifiManager>(uri, 0, 1, "WifiManager"); qmlRegisterType<QWifiNetworkList>(); + qmlRegisterSingletonType<QWifiGlobal>(uri, 0, 1, "Interface", global_object_wifi); } }; #include "pluginmain.moc" - - diff --git a/src/imports/wifi/qwifimanager.cpp b/src/imports/wifi/qwifimanager.cpp index 1ba3d64..7d6683b 100644 --- a/src/imports/wifi/qwifimanager.cpp +++ b/src/imports/wifi/qwifimanager.cpp @@ -1,56 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #include "qwifimanager.h" #include <QtCore> #include <hardware_legacy/wifi.h> -#include <cutils/properties.h> +#include <cutils/sockets.h> #include <unistd.h> -#define WLAN_INTERFACE "wlan0" +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); -static int q_wifi_start_supplicant() +/* + * 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) { -#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1) - return wifi_start_supplicant(0); -#else - return wifi_start_supplicant(); -#endif -} - -static int q_wifi_connect_to_supplicant() -{ -#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1) - return wifi_connect_to_supplicant(WLAN_INTERFACE); -#else - return wifi_connect_to_supplicant(); -#endif -} - -static int q_wifi_command(const char *command, char *reply, size_t *reply_len) -{ -#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1) - return wifi_command(WLAN_INTERFACE, command, reply, reply_len); -#else - return wifi_command(command, reply, reply_len); -#endif + char value[PROPERTY_VALUE_MAX] = {'\0'}; + int maxnaps = (maxwait * 1000) / NAP_TIME; -} + if (maxnaps < 1) { + maxnaps = 1; + } -static int q_wifi_wait_for_event(char *buf, size_t len) -{ -#if Q_ANDROID_VERSION_MAJOR > 4 || (Q_ANDROID_VERSION_MAJOR == 4 && Q_ANDROID_VERSION_MINOR >= 1) - return wifi_wait_for_event(WLAN_INTERFACE, buf, len); -#else - return wifi_wait_for_event(buf, len); -#endif + 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 */ } - class QWifiManagerEvent : public QEvent { public: @@ -66,13 +78,12 @@ private: QByteArray m_data; }; - - class QWifiManagerEventThread : public QThread { public: - QWifiManagerEventThread(QWifiManager *manager) + QWifiManagerEventThread(QWifiManager *manager, const QByteArray &interface) : m_manager(manager) + , m_if(interface) { } @@ -81,7 +92,7 @@ public: if (QT_WIFI_DEBUG) qDebug("EventReceiver thread is running"); char buffer[2048]; while (1) { - int size = q_wifi_wait_for_event(buffer, sizeof(buffer) - 1); + int size = wifi_wait_for_event(m_if.constData(), buffer, sizeof(buffer) - 1); if (size > 0) { buffer[size] = 0; @@ -89,39 +100,166 @@ public: char *event = &buffer[11]; if (strstr(event, "SCAN-RESULTS")) { + if (m_manager->exitingEventThread()) + return; QWifiManagerEvent *e = new QWifiManagerEvent(WIFI_SCAN_RESULTS); QCoreApplication::postEvent(m_manager, e); } else if (strstr(event, "CONNECTED")) { QWifiManagerEvent *e = new QWifiManagerEvent(WIFI_CONNECTED); QCoreApplication::postEvent(m_manager, e); + } else if (strstr(event, "TERMINATING")) { + // stop monitoring for events when supplicant is terminating + return; } } } } QWifiManager *m_manager; + QByteArray m_if; }; - - QWifiManager::QWifiManager() : m_networks(this) , m_eventThread(0) , m_scanTimer(0) - , m_internalState(IS_Uninitialized) , m_scanning(false) + , m_daemonClientSocket(0) + , m_exitingEventThread(false) { + char interface[PROPERTY_VALUE_MAX]; + property_get(WIFI_INTERFACE, interface, NULL); + m_interface = interface; + if (QT_WIFI_DEBUG) qDebug("QWifiManager: using wifi interface: %s", m_interface.constData()); + m_eventThread = new QWifiManagerEventThread(this, m_interface); + + 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 backend_status[PROPERTY_VALUE_MAX]; + if (property_get(QT_WIFI_BACKEND, backend_status, NULL)) { + if (strcmp(backend_status, "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(backend_status, "stopped") == 0) { + // same here, cleans up the state + disconnectFromBackend(); + } + } } +QWifiManager::~QWifiManager() +{ + // exit event thread if it is running + if (m_eventThread->isRunning()) { + m_exitingEventThread = true; + call("SCAN"); + m_eventThread->wait(); + } + delete m_eventThread; + delete m_daemonClientSocket; +} + +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") { + m_state = Connected; + emit networkStateChanged(); + emit connectedSSIDChanged(m_connectedSSID); + // Store settings of a working wifi connection + call("SAVE_CONFIG"); + } else if (receivedMessage == "failed") { + m_state = DhcpRequestFailed; + emit networkStateChanged(); + } 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(); +} void QWifiManager::start() { - if (QT_WIFI_DEBUG) qDebug("QWifiManager: start"); + if (QT_WIFI_DEBUG) qDebug("QWifiManager: connecting to the backend"); connectToBackend(); } +void QWifiManager::stop() +{ + if (QT_WIFI_DEBUG) qDebug("QWifiManager: shutting down"); + disconnectFromBackend(); +} +void QWifiManager::connectToBackend() +{ + if (!(is_wifi_driver_loaded() || wifi_load_driver() == 0)) { + qWarning("QWifiManager: failed to load a driver"); + return; + } + if (wifi_start_supplicant(0) != 0) { + qWarning("QWifiManager: failed to start a supplicant"); + return; + } + if (wait_for_property(SUPPLICANT_SVC, "running", 5) < 0) { + qWarning("QWifiManager: Timed out waiting for supplicant to start"); + return; + } + if (wifi_connect_to_supplicant(m_interface.constData()) == 0) { + m_backendReady = true; + emit backendReadyChanged(); + property_set(QT_WIFI_BACKEND, "running"); + } else { + qWarning("QWifiManager: failed to connect to a supplicant"); + return; + } + if (QT_WIFI_DEBUG) qDebug("QWifiManager: started successfully"); + m_exitingEventThread = false; + m_eventThread->start(); + handleConnected(); +} + +void QWifiManager::disconnectFromBackend() +{ + m_exitingEventThread = true; + call("SCAN"); + m_eventThread->wait(); + + if (wifi_stop_supplicant(0) < 0) + qWarning("QWifiManager: failed to stop supplicant"); + wifi_close_supplicant_connection(m_interface.constData()); + property_set(QT_WIFI_BACKEND, "stopped"); + m_backendReady = false; + emit backendReadyChanged(); +} void QWifiManager::setScanning(bool scanning) { @@ -129,70 +267,23 @@ void QWifiManager::setScanning(bool scanning) return; m_scanning = scanning; - emit scanningChanged(scanning); + emit scanningChanged(m_scanning); if (m_scanning) { if (QT_WIFI_DEBUG) qDebug("QWifiManager: scanning"); call("SCAN"); - m_scanTimer = startTimer(5000); + m_scanTimer = startTimer(5000); // ### todo - this could be a qml property } else { if (QT_WIFI_DEBUG) qDebug("QWifiManager: stop scanning"); killTimer(m_scanTimer); } } - - -QByteArray int_to_ip(int i) { - QByteArray ip; - - ip.append(QByteArray::number(i & 0x000000ff)); - ip.append('.'); - ip.append(QByteArray::number((i & 0x0000ff00) >> 8)); - ip.append('.'); - ip.append(QByteArray::number((i & 0x00ff0000) >> 16)); - ip.append('.'); - ip.append(QByteArray::number(i >> 24)); - - return ip; -} - - -void QWifiManager::connectToBackend() -{ - if (m_internalState == IS_Uninitialized) - m_internalState = IS_LoadDriver; - - if (m_internalState == IS_LoadDriver && (is_wifi_driver_loaded() || wifi_load_driver() >= 0)) - m_internalState = IS_StartBackend; - - if (m_internalState == IS_StartBackend && q_wifi_start_supplicant() >= 0) { - m_internalState = IS_ConnectToBackend; - sleep(3); //### - } - - if (m_internalState == IS_ConnectToBackend && q_wifi_connect_to_supplicant() >= 0) - m_internalState = IS_UpAndRunning; - - if (m_internalState == IS_UpAndRunning) { - qDebug("QWifiManager: started successfully"); - - emit readyChanged(true); - m_eventThread = new QWifiManagerEventThread(this); - m_eventThread->start(); - - handleConnected(); - } else { - qWarning("QWifiManager: stuck at internal state level: %d", m_internalState); - } -} - - -QByteArray QWifiManager::call(const char *command) +QByteArray QWifiManager::call(const char *command) const { char data[2048]; size_t len = sizeof(data) - 1; // -1: room to add a 0-terminator - if (q_wifi_command(command, data, &len) < 0) { + if (wifi_command(m_interface.constData(), command, data, &len) < 0) { qWarning("QWifiManager: call failed: %s", command); return QByteArray(); } @@ -203,13 +294,11 @@ QByteArray QWifiManager::call(const char *command) return result; } - -bool QWifiManager::checkedCall(const char *command) +bool QWifiManager::checkedCall(const char *command) const { return call(command).trimmed().toUpper() == "OK"; } - bool QWifiManager::event(QEvent *e) { switch ((int) e->type()) { @@ -243,9 +332,10 @@ void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase) if (!m_connectedSSID.isEmpty()) { m_connectedSSID.clear(); emit connectedSSIDChanged(m_connectedSSID); - //also possibly change online state } + m_state = ObtainingIPAddress; + emit networkStateChanged(); bool networkKnown = false; QByteArray id; QByteArray listResult = call("LIST_NETWORKS"); @@ -277,7 +367,7 @@ void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase) QByteArray key_mgmt; if (network->supportsWPA() || network->supportsWPA2()) { ok = ok && checkedCall(setNetworkCommand + QByteArray(" psk ") + '"' + passphrase.toLatin1() + '"'); - key_mgmt = "WPA_PSK"; + 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")); @@ -299,19 +389,16 @@ void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase) call("RECONNECT"); } - -class ProcessRunner : public QThread { -public: - void run() { - QStringList args; - args << QStringLiteral("-A") - << QStringLiteral("-h") << QStringLiteral("KAON") //### hardcoded hostname, for testing - << QStringLiteral("wlan0"); - QProcess::execute(QStringLiteral("dhcpcd"), args); - deleteLater(); - } -}; - +void QWifiManager::disconnect() +{ + call("DISCONNECT"); + QByteArray req = m_interface; + sendDhcpRequest(req.append(" disconnect")); + m_state = Disconnected; + m_connectedSSID.clear(); + emit networkStateChanged(); + emit connectedSSIDChanged(m_connectedSSID); +} void QWifiManager::handleConnected() { @@ -326,49 +413,16 @@ void QWifiManager::handleConnected() if (connectedNetwork.isEmpty()) { if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: not connected to a network..."); - m_online = false; - onlineChanged(m_online); + m_state = Disconnected; + emit networkStateChanged(); return; - } else { - if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: current is %s", connectedNetwork.constData()); } + if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: current is %s", connectedNetwork.constData()); + QList<QByteArray> info = connectedNetwork.split('\t'); m_connectedSSID = info.at(1); - emit connectedSSIDChanged(m_connectedSSID); - - if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: starting dhcpcd..."); - QThread *t = new ProcessRunner(); - t->start(); - - int ipaddr, gateway, mask, dns1, dns2, server, lease; - if (do_dhcp_request(&ipaddr, &gateway, &mask, &dns1, &dns2, &server, &lease) == 0) { - if (QT_WIFI_DEBUG) { - printf("ip ........: %s\n" - "gateway ...: %s\n" - "mask ......: %s\n" - "dns1 ......: %s\n" - "dns2 ......: %s\n" - "lease .....: %d\n", - int_to_ip(ipaddr).constData(), - int_to_ip(gateway).constData(), - int_to_ip(mask).constData(), - int_to_ip(dns1).constData(), - int_to_ip(dns2).constData(), - lease); - } - - // Updating dns values.. - property_set("net.dns1", int_to_ip(dns1).constData()); - property_set("net.dns2", int_to_ip(dns2).constData()); - - // Store (possibly updated) settings - call("SAVE_CONFIG"); - - m_online = true; - onlineChanged(m_online); - } else { - if (QT_WIFI_DEBUG) qDebug("QWifiManager::handleConnected: dhcp request failed..."); - } + QByteArray req = m_interface; + sendDhcpRequest(req.append(" connect")); } diff --git a/src/imports/wifi/qwifimanager.h b/src/imports/wifi/qwifimanager.h index 5fd74f5..432f411 100644 --- a/src/imports/wifi/qwifimanager.h +++ b/src/imports/wifi/qwifimanager.h @@ -1,8 +1,29 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #ifndef QWIFIMANAGER_H #define QWIFIMANAGER_H #include <QtCore/QObject> #include <QtCore/QByteArray> +#include <QtNetwork/QLocalSocket> + +#include <cutils/properties.h> #include "qwifinetworklist.h" @@ -11,71 +32,73 @@ class QWifiManagerEventThread; class QWifiManager : public QObject { Q_OBJECT - - Q_PROPERTY(bool ready READ isReady NOTIFY readyChanged) - Q_PROPERTY(bool online READ isOnline NOTIFY onlineChanged) + 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(QWifiNetworkList *networks READ networks CONSTANT) public: - enum InternalState { - IS_Uninitialized, - IS_LoadDriver, - IS_StartBackend, - IS_ConnectToBackend, - IS_UpAndRunning + enum NetworkState { + Disconnected, + ObtainingIPAddress, + DhcpRequestFailed, + Connected }; QWifiManager(); + ~QWifiManager(); QWifiNetworkList *networks() { return &m_networks; } - QString connectedSSID() const { return m_connectedSSID; } - bool scanning() const { return m_scanning; } void setScanning(bool scanning); - - bool isReady() const { return m_internalState == IS_UpAndRunning; } - bool isOnline() const { return m_online; } - + 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 arg); - void readyChanged(bool ready); - void onlineChanged(bool online); + void networkStateChanged(); + void backendReadyChanged(); void connectedSSIDChanged(const QString &); protected: bool event(QEvent *); + void sendDhcpRequest(const QByteArray &request); + void handleConnected(); + void connectToBackend(); + void disconnectFromBackend(); + QByteArray call(const char *command) const; + bool checkedCall(const char *command) const; + +protected slots: + void connectedToDaemon(); + void handleDhcpReply(); private: friend class QWifiManagerEventThread; - void handleConnected(); - void parseScanResults(); - void connectToBackend(); - QByteArray call(const char *command); - bool checkedCall(const char *command); - QString m_connectedSSID; QWifiNetworkList m_networks; - QWifiManagerEventThread *m_eventThread; int m_scanTimer; - - InternalState m_internalState; - bool m_scanning; - bool m_online; + bool m_backendReady; + QByteArray m_interface; + NetworkState m_state; + QLocalSocket *m_daemonClientSocket; + QByteArray m_request; + bool m_exitingEventThread; }; #endif // QWIFIMANAGER_H diff --git a/src/imports/wifi/qwifinetwork.cpp b/src/imports/wifi/qwifinetwork.cpp index 5de8711..a159e59 100644 --- a/src/imports/wifi/qwifinetwork.cpp +++ b/src/imports/wifi/qwifinetwork.cpp @@ -1,3 +1,21 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #include "qwifinetwork.h" QWifiNetwork::QWifiNetwork() diff --git a/src/imports/wifi/qwifinetwork.h b/src/imports/wifi/qwifinetwork.h index 8bcb410..780fc87 100644 --- a/src/imports/wifi/qwifinetwork.h +++ b/src/imports/wifi/qwifinetwork.h @@ -1,3 +1,21 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #ifndef QWIFINETWORK_H #define QWIFINETWORK_H diff --git a/src/imports/wifi/qwifinetworklist.cpp b/src/imports/wifi/qwifinetworklist.cpp index e7fa92d..60fdc53 100644 --- a/src/imports/wifi/qwifinetworklist.cpp +++ b/src/imports/wifi/qwifinetworklist.cpp @@ -1,3 +1,21 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #include "qwifinetworklist.h" #include <QtCore> @@ -14,7 +32,6 @@ QWifiNetworkList::QWifiNetworkList(QWifiManager *manager) { } - QHash<int, QByteArray> QWifiNetworkList::roleNames() const { QHash<int, QByteArray> names; @@ -27,8 +44,6 @@ QHash<int, QByteArray> QWifiNetworkList::roleNames() const return names; } - - QVariant QWifiNetworkList::data(const QModelIndex &index, int role) const { QWifiNetwork *n = m_networks.at(index.row()); @@ -42,15 +57,15 @@ QVariant QWifiNetworkList::data(const QModelIndex &index, int role) const case ID_NETWORK: return QVariant::fromValue((QObject *) n); } - qDebug("QWifiNetworkList::data(), undefined role: %d\n", role); + qWarning("QWifiNetworkList::data(), undefined role: %d\n", role); return QVariant(); } -QWifiNetwork *QWifiNetworkList::networkForBSSID(const QByteArray &bssid, int *pos) +QWifiNetwork *QWifiNetworkList::networkForSSID(const QByteArray &ssid, int *pos) { for (int i=0; i<m_networks.size(); ++i) { - if (m_networks.at(i)->bssid() == bssid) { + if (m_networks.at(i)->ssid() == ssid) { if (pos) *pos = i; return m_networks.at(i); @@ -59,37 +74,48 @@ QWifiNetwork *QWifiNetworkList::networkForBSSID(const QByteArray &bssid, int *po return 0; } - void QWifiNetworkList::parseScanResults(const QByteArray &results) { QList<QByteArray> lines = results.split('\n'); - QSet<QByteArray> bssids; + QSet<QByteArray> sensibleNetworks; for (int i=1; i<lines.size(); ++i) { QList<QByteArray> info = lines.at(i).split('\t'); if (info.size() < 5 || info.at(4).isEmpty() || info.at(0).isEmpty()) continue; - bssids.insert(info.at(0)); int pos = 0; - QWifiNetwork *existing = networkForBSSID(info.at(0), &pos); - if (!existing) { + if (!sensibleNetworks.contains(info.at(4))) + sensibleNetworks.insert(info.at(4)); + QWifiNetwork *existingNetwork = networkForSSID(info.at(4), &pos); + if (!existingNetwork) { QWifiNetwork *network = new QWifiNetwork(); network->setBssid(info.at(0)); network->setFlags(info.at(3)); + // signal strength is in dBm network->setSignalStrength(info.at(2).toInt()); network->setSsid(info.at(4)); beginInsertRows(QModelIndex(), m_networks.size(), m_networks.size()); m_networks << network; endInsertRows(); - } else { - existing->setSignalStrength(info.at(2).toInt()); - dataChanged(createIndex(pos, 0), createIndex(pos, 0)); + // ssids are the same, compare bssids.. + if (existingNetwork->bssid() == info.at(0)) { + // same access point, simply update the signal strength + existingNetwork->setSignalStrength(info.at(2).toInt()); + dataChanged(createIndex(pos, 0), createIndex(pos, 0)); + } else if (existingNetwork->signalStrength() < info.at(2).toInt()) { + // replace with a stronger access point within the same network + m_networks.at(pos)->setBssid(info.at(0)); + m_networks.at(pos)->setFlags(info.at(3)); + m_networks.at(pos)->setSignalStrength(info.at(2).toInt()); + m_networks.at(pos)->setSsid(info.at(4)); + dataChanged(createIndex(pos, 0), createIndex(pos, 0)); + } } } - - for (int i=0; i<m_networks.size(); ) { - if (!bssids.contains(m_networks.at(i)->bssid())) { + // remove networks that have gone out of range + for (int i = 0; i < m_networks.size(); ++i) { + if (!sensibleNetworks.contains(m_networks.at(i)->ssid())) { beginRemoveRows(QModelIndex(), i, i); delete m_networks.takeAt(i); endRemoveRows(); @@ -97,10 +123,6 @@ void QWifiNetworkList::parseScanResults(const QByteArray &results) ++i; } } - -// for (int i=0; i<m_networks.size(); ++i) { -// qDebug() << " - network:" << m_networks.at(i)->bssid() << m_networks.at(i)->ssid() << m_networks.at(i)->flags() << m_networks.at(i)->signalStrength(); -// } } diff --git a/src/imports/wifi/qwifinetworklist.h b/src/imports/wifi/qwifinetworklist.h index f6e134c..84e78fc 100644 --- a/src/imports/wifi/qwifinetworklist.h +++ b/src/imports/wifi/qwifinetworklist.h @@ -1,3 +1,21 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc +** All rights reserved. +** For any questions to Digia, please use the contact form at +** http://qt.digia.com/ +** +** 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://qt.digia.com/ +** +****************************************************************************/ #ifndef QWIFINETWORKLIST_H #define QWIFINETWORKLIST_H @@ -18,7 +36,7 @@ public: void parseScanResults(const QByteArray &data); - QWifiNetwork *networkForBSSID(const QByteArray &bssid, int *pos); + QWifiNetwork *networkForSSID(const QByteArray &ssid, int *pos); int rowCount(const QModelIndex &) const { return m_networks.size(); } QVariant data(const QModelIndex &index, int role) const; diff --git a/src/imports/wifi/qwifimodule.pro b/src/imports/wifi/wifi.pro index 449617f..0231479 100644 --- a/src/imports/wifi/qwifimodule.pro +++ b/src/imports/wifi/wifi.pro @@ -1,5 +1,5 @@ CXX_MODULE = qml -QT += qml quick +QT += qml quick network TARGET = qwifimodule TARGETPATH = Qt/labs/wifi IMPORT_VERSION = 0.1 |