From 88a2385ab7b9f33437ce648a70757b9d8c8a48c7 Mon Sep 17 00:00:00 2001 From: Gatis Paeglis Date: Wed, 19 Mar 2014 18:41:20 +0100 Subject: [Wifi] Add new enums and make some API changes - Now QtWifi can provide feedback when incorrect password is entered. - networkStateChanged signal provides a reference to the currently active network connection. - bug fixes in QWifiManager::connect Task-number: QTEE-408 Change-Id: Ic7458b864f09aef3cfca40fb081dec45e0bba7db Reviewed-by: Eirik Aavitsland --- src/imports/wifi/qwifimanager.cpp | 129 +++++++++++++++++++++++--------------- 1 file changed, 79 insertions(+), 50 deletions(-) (limited to 'src/imports/wifi/qwifimanager.cpp') diff --git a/src/imports/wifi/qwifimanager.cpp b/src/imports/wifi/qwifimanager.cpp index bc4b6fe..af6f5d3 100644 --- a/src/imports/wifi/qwifimanager.cpp +++ b/src/imports/wifi/qwifimanager.cpp @@ -32,6 +32,7 @@ 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); /* * This function is borrowed from /system/core/libnetutils/dhcp_utils.c @@ -89,28 +90,30 @@ public: } void run() { - if (QT_WIFI_DEBUG) qDebug("EventReceiver thread is running"); + if (QT_WIFI_DEBUG) qDebug("WiFi event thread is running"); + QWifiManagerEvent *event = 0; char buffer[2048]; while (1) { int size = wifi_wait_for_event(m_if.constData(), buffer, sizeof(buffer) - 1); if (size > 0) { buffer[size] = 0; - - if (QT_WIFI_DEBUG) qDebug("EVENT: %s", buffer); - - char *event = &buffer[11]; - if (strstr(event, "SCAN-RESULTS")) { - if (m_manager->exitingEventThread()) + event = 0; + if (strstr(buffer, "SCAN-RESULTS")) { + if (m_manager->exitingEventThread()) { + if (QT_WIFI_DEBUG) qDebug() << "Exiting WiFi event thread"; 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")) { + } + 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); } } } @@ -161,6 +164,8 @@ public: \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 @@ -212,8 +217,8 @@ public: /*! \qmlproperty WifiNetworkListModel WifiManager::networks - This property holds a list of networks that can be sensed by a device and should be used as a - data model in ListView. List is updated every 5 seconds. + 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. @@ -313,9 +318,10 @@ public: */ /*! - \qmlsignal void WifiManager::networkStateChanged() + \qmlsignal void WifiManager::networkStateChanged(WifiNetwork network) - This signal is emitted whenever changes in a network state occur. + This signal is emitted whenever changes in a network state occur. Network \a network is the + the currently active network connection. \sa networkState */ @@ -338,12 +344,14 @@ public: */ QWifiManager::QWifiManager() - : m_networks(this) + : m_networkListModel(this) , m_eventThread(0) , m_scanTimer(0) , m_scanning(false) , m_daemonClientSocket(0) , m_exitingEventThread(false) + , m_startingUp(true) + , m_network(0) { char interface[PROPERTY_VALUE_MAX]; property_get(WIFI_INTERFACE, interface, NULL); @@ -361,15 +369,15 @@ QWifiManager::QWifiManager() 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) { + 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(backend_status, "stopped") == 0) { + } else if (strcmp(backendStatus, "stopped") == 0) { // same here, cleans up the state disconnectFromBackend(); } @@ -378,12 +386,7 @@ QWifiManager::QWifiManager() QWifiManager::~QWifiManager() { - // exit event thread if it is running - if (m_eventThread->isRunning()) { - m_exitingEventThread = true; - call("SCAN"); - m_eventThread->wait(); - } + exitEventThread(); delete m_eventThread; delete m_daemonClientSocket; } @@ -395,14 +398,12 @@ void QWifiManager::handleDhcpReply() 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(); + updateNetworkState(Connected); emit connectedSSIDChanged(m_connectedSSID); // Store settings of a working wifi connection call("SAVE_CONFIG"); } else if (receivedMessage == "failed") { - m_state = DhcpRequestFailed; - emit networkStateChanged(); + updateNetworkState(DhcpRequestFailed); } else { qWarning() << "QWifiManager: unknown message: " << receivedMessage; } @@ -428,12 +429,16 @@ void QWifiManager::connectedToDaemon() 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(); } @@ -462,15 +467,12 @@ void QWifiManager::connectToBackend() if (QT_WIFI_DEBUG) qDebug("QWifiManager: started successfully"); m_exitingEventThread = false; m_eventThread->start(); - handleConnected(); + call("SCAN"); } void QWifiManager::disconnectFromBackend() { - m_exitingEventThread = true; - call("SCAN"); - m_eventThread->wait(); - + exitEventThread(); if (wifi_stop_supplicant(0) < 0) qWarning("QWifiManager: failed to stop supplicant"); wifi_close_supplicant_connection(m_interface.constData()); @@ -479,9 +481,18 @@ void QWifiManager::disconnectFromBackend() emit backendReadyChanged(); } +void QWifiManager::exitEventThread() +{ + if (m_eventThread->isRunning()) { + m_exitingEventThread = true; + call("SCAN"); + m_eventThread->wait(); + } +} + void QWifiManager::setScanning(bool scanning) { - if (m_scanning == scanning) + if (!m_backendReady || m_scanning == scanning) return; m_scanning = scanning; @@ -517,15 +528,27 @@ 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_networks.parseScanResults(call("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(e)->timerId(); if (tid == m_scanTimer) { @@ -541,10 +564,13 @@ bool QWifiManager::event(QEvent *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()); + 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()) { @@ -552,16 +578,13 @@ void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase) emit connectedSSIDChanged(m_connectedSSID); } - m_state = ObtainingIPAddress; - emit networkStateChanged(); bool networkKnown = false; QByteArray id; QByteArray listResult = call("LIST_NETWORKS"); QList lines = listResult.split('\n'); foreach (const QByteArray &line, lines) { if (line.contains(network->ssid())) { - int networkId = line.toInt(); - id = QByteArray::number(networkId); + id = line.split('\t').at(0); networkKnown = true; break; } @@ -569,7 +592,7 @@ void QWifiManager::connect(QWifiNetwork *network, const QString &passphrase) if (!networkKnown) { bool ok; - QByteArray id = call("ADD_NETWORK").trimmed(); + id = call("ADD_NETWORK").trimmed(); id.toInt(&ok); if (!ok) { qWarning("QWifiManager::connect(), failed to add network"); @@ -612,9 +635,8 @@ void QWifiManager::disconnect() call("DISCONNECT"); QByteArray req = m_interface; sendDhcpRequest(req.append(" disconnect")); - m_state = Disconnected; m_connectedSSID.clear(); - emit networkStateChanged(); + updateNetworkState(Disconnected); emit connectedSSIDChanged(m_connectedSSID); } @@ -622,7 +644,7 @@ void QWifiManager::handleConnected() { QList lists = call("LIST_NETWORKS").split('\n'); QByteArray connectedNetwork; - for (int i=1; i 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); QByteArray req = m_interface; sendDhcpRequest(req.append(" connect")); } -- cgit v1.2.3