summaryrefslogtreecommitdiffstats
path: root/src/imports/wifi
diff options
context:
space:
mode:
Diffstat (limited to 'src/imports/wifi')
-rw-r--r--src/imports/wifi/pluginmain.cpp59
-rw-r--r--src/imports/wifi/qwifimanager.cpp356
-rw-r--r--src/imports/wifi/qwifimanager.h83
-rw-r--r--src/imports/wifi/qwifinetwork.cpp18
-rw-r--r--src/imports/wifi/qwifinetwork.h18
-rw-r--r--src/imports/wifi/qwifinetworklist.cpp64
-rw-r--r--src/imports/wifi/qwifinetworklist.h20
-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