summaryrefslogtreecommitdiffstats
path: root/src/wifi
diff options
context:
space:
mode:
Diffstat (limited to 'src/wifi')
-rw-r--r--src/wifi/qwificonfiguration.cpp24
-rw-r--r--src/wifi/qwificonfiguration.h3
-rw-r--r--src/wifi/qwificontroller.cpp68
-rw-r--r--src/wifi/qwificontroller_p.h16
-rw-r--r--src/wifi/qwifielinux.cpp89
-rw-r--r--src/wifi/qwifimanager.cpp114
-rw-r--r--src/wifi/qwifimanager_p.h9
-rw-r--r--src/wifi/qwifinetworklistmodel.cpp19
-rw-r--r--src/wifi/qwifiutils.cpp135
-rw-r--r--src/wifi/qwifiutils_p.h37
-rw-r--r--src/wifi/wifi.pro6
11 files changed, 361 insertions, 159 deletions
diff --git a/src/wifi/qwificonfiguration.cpp b/src/wifi/qwificonfiguration.cpp
index 42196a2..b532620 100644
--- a/src/wifi/qwificonfiguration.cpp
+++ b/src/wifi/qwificonfiguration.cpp
@@ -31,10 +31,12 @@ public:
QString m_ssid;
QString m_psk;
QString m_protocol;
+ bool m_ssidHidden;
};
QWifiConfigurationPrivate::QWifiConfigurationPrivate(QWifiConfiguration *config)
: q_ptr(config)
+ , m_ssidHidden(false)
{
}
@@ -119,4 +121,26 @@ void QWifiConfiguration::setProtocol(const QString &protocol)
d->m_protocol = protocol;
}
+/*!
+ \property QWifiConfiguration::ssidHidden
+ \brief Holds whether a Wifi access point broadcasts its SSID
+
+ If a Wifi access point does not broadcast its SSID, setting this
+ property to \c true ensures that the Wifi backend can detect the
+ specified network.
+
+ By default this property is set to \c false.
+*/
+bool QWifiConfiguration::isSsidHidden() const
+{
+ Q_D(const QWifiConfiguration);
+ return d->m_ssidHidden;
+}
+
+void QWifiConfiguration::setSsidHidden(bool hidden)
+{
+ Q_D(QWifiConfiguration);
+ d->m_ssidHidden = hidden;
+}
+
QT_END_NAMESPACE
diff --git a/src/wifi/qwificonfiguration.h b/src/wifi/qwificonfiguration.h
index 9b03c9e..cdeb453 100644
--- a/src/wifi/qwificonfiguration.h
+++ b/src/wifi/qwificonfiguration.h
@@ -32,6 +32,7 @@ class Q_DECL_EXPORT QWifiConfiguration : public QObject
Q_PROPERTY(QString ssid READ ssid WRITE setSsid)
Q_PROPERTY(QString passphrase READ passphrase WRITE setPassphrase)
Q_PROPERTY(QString protocol READ protocol WRITE setProtocol)
+ Q_PROPERTY(bool ssidHidden READ isSsidHidden WRITE setSsidHidden)
public:
explicit QWifiConfiguration(QObject *parent = 0);
virtual ~QWifiConfiguration();
@@ -42,6 +43,8 @@ public:
QString passphrase() const;
void setProtocol(const QString &protocol);
QString protocol() const;
+ void setSsidHidden(bool hidden);
+ bool isSsidHidden() const;
private:
Q_DISABLE_COPY(QWifiConfiguration)
diff --git a/src/wifi/qwificontroller.cpp b/src/wifi/qwificontroller.cpp
index ea49764..7b8be80 100644
--- a/src/wifi/qwificontroller.cpp
+++ b/src/wifi/qwificontroller.cpp
@@ -33,7 +33,7 @@
#ifdef Q_OS_ANDROID_NO_SDK
/*
- * Work API differences between Android versions
+ * Workaround API differences between Android versions
*/
int q_wifi_start_supplicant()
{
@@ -129,21 +129,6 @@ 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:
@@ -155,7 +140,7 @@ public:
void run() {
qCDebug(B2QT_WIFI) << "running wifi event thread";
- QWifiManagerEvent *event = 0;
+ QWifiEvent *event = 0;
char buffer[2048];
forever {
int size = q_wifi_wait_for_event(m_interface, buffer, sizeof(buffer) - 1);
@@ -163,21 +148,24 @@ public:
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);
+ event = new QWifiEvent(WIFI_SCAN_RESULTS);
} else if (strstr(buffer, "CTRL-EVENT-CONNECTED")) {
- event = new QWifiManagerEvent(WIFI_CONNECTED);
+ event = new QWifiEvent(WIFI_CONNECTED);
} else if (strstr(buffer, "CTRL-EVENT-DISCONNECTED")) {
- event = new QWifiManagerEvent(WIFI_DISCONNECTED);
+ event = new QWifiEvent(WIFI_DISCONNECTED);
} else if (strstr(buffer, "Trying to associate")) {
- event = new QWifiManagerEvent(WIFI_AUTHENTICATING);
+ event = new QWifiEvent(WIFI_AUTHENTICATING, QLatin1String(buffer));
} else if (strstr(buffer, "Handshake failed")) {
- event = new QWifiManagerEvent(WIFI_HANDSHAKE_FAILED);
+ event = new QWifiEvent(WIFI_HANDSHAKE_FAILED);
}
+
if (event)
QCoreApplication::postEvent(m_controller->wifiManager(), event);
}
@@ -272,12 +260,12 @@ void QWifiController::initializeBackend()
{
qCDebug(B2QT_WIFI) << "initializing wifi backend";
emit backendStateChanged(QWifiManager::Initializing);
-
+ bool initFailed = false;
#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;
+ initFailed = true;
}
#else
qCDebug(B2QT_WIFI) << "run ifconfig (up)";
@@ -286,39 +274,42 @@ void QWifiController::initializeBackend()
ifconfig.waitForFinished();
if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0) {
qCWarning(B2QT_WIFI) << "failed to bring up wifi interface!";
- return;
+ initFailed = true;
}
#endif
- resetSupplicantSocket();
- startWifiEventThread();
- qCDebug(B2QT_WIFI) << "wifi backend started successfully";
- emit backendStateChanged(QWifiManager::Running);
+ if (!initFailed && resetSupplicantSocket()) {
+ qCDebug(B2QT_WIFI) << "wifi backend started successfully";
+ emit backendStateChanged(QWifiManager::Running);
+ } else {
+ emit backendStateChanged(QWifiManager::NotRunning);
+ }
}
-void QWifiController::resetSupplicantSocket() const
+bool QWifiController::resetSupplicantSocket()
{
qCDebug(B2QT_WIFI) << "reset supplicant socket";
- // close down the previous connection to supplicant if
- // one exists before re-connecting.
+ exitWifiEventThread();
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;
+ return false;
}
#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;
+ return false;
}
#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;
+ return false;
}
+ startWifiEventThread();
+ return true;
}
void QWifiController::terminateBackend()
@@ -334,10 +325,8 @@ void QWifiController::terminateBackend()
QProcess ifconfig;
ifconfig.start(QStringLiteral("ifconfig"), QStringList() << QLatin1String(m_interface) << QStringLiteral("down"));
ifconfig.waitForFinished();
- if (ifconfig.exitStatus() != QProcess::NormalExit && ifconfig.exitCode() != 0) {
+ 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";
@@ -355,7 +344,8 @@ void QWifiController::exitWifiEventThread()
if (m_eventThread->isRunning()) {
m_exitEventThread = true;
m_managerPrivate->call(QStringLiteral("SCAN"));
- m_eventThread->wait();
+ if (!m_eventThread->wait(8000))
+ qCWarning(B2QT_WIFI, "timed out waiting for wifi event thread to exit!");
}
}
diff --git a/src/wifi/qwificontroller_p.h b/src/wifi/qwificontroller_p.h
index 230b7c8..185cff9 100644
--- a/src/wifi/qwificontroller_p.h
+++ b/src/wifi/qwificontroller_p.h
@@ -62,6 +62,20 @@ class QWifiEventThread;
class QLocalSocket;
#endif
+class QWifiEvent : public QEvent
+{
+public:
+ QWifiEvent(QEvent::Type type, const QString &data = QString())
+ : QEvent(type)
+ , m_data(data)
+ {
+ }
+ QString data() const { return m_data; }
+
+private:
+ QString m_data;
+};
+
class QWifiController : public QThread
{
Q_OBJECT
@@ -83,7 +97,7 @@ public:
void startWifiEventThread();
void acquireIPAddress();
void stopDhcp() const;
- void resetSupplicantSocket() const;
+ bool resetSupplicantSocket();
signals:
void backendStateChanged(QWifiManager::BackendState backendState);
diff --git a/src/wifi/qwifielinux.cpp b/src/wifi/qwifielinux.cpp
index 0dc3a39..e7dabb3 100644
--- a/src/wifi/qwifielinux.cpp
+++ b/src/wifi/qwifielinux.cpp
@@ -38,7 +38,6 @@ 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];
-QByteArray ctrlInterface;
int wifi_connect_on_socket_path(const char *path);
int wifi_ctrl_recv(char *reply, size_t *reply_len);
@@ -46,12 +45,33 @@ int wifi_wait_on_socket(char *buf, size_t buflen);
int wifi_send_command(const char *cmd, char *reply, size_t *reply_len);
void wifi_close_sockets();
+QByteArray controlInterfacePath()
+{
+ QByteArray path;
+ QFile configFile;
+ configFile.setFileName(QLatin1String(SUPP_CONFIG_FILE));
+ if (configFile.open(QFile::ReadOnly)) {
+ while (!configFile.atEnd()) {
+ QByteArray line = configFile.readLine().trimmed();
+ if (line.startsWith("ctrl_interface")) {
+ path = line.mid(16);
+ if (path.isEmpty())
+ qCWarning(B2QT_WIFI) << "ctrl_interface is not set in " << SUPP_CONFIG_FILE;
+ break;
+ }
+ }
+ configFile.close();
+ } else {
+ qCWarning(B2QT_WIFI) << "could not find/read wpa_supplicant configuration file in" << SUPP_CONFIG_FILE;
+ }
+ return path;
+}
+
int q_wifi_start_supplicant()
{
- // #### 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");
+ QString driver(QStringLiteral("nl80211,wext"));
QStringList arg;
arg << QStringLiteral("--start") << QStringLiteral("--quiet") << QStringLiteral("--name");
@@ -64,33 +84,14 @@ int q_wifi_start_supplicant()
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!";
+
+ QByteArray path = controlInterfacePath();
+ if (path.isEmpty())
return -1;
- }
- 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;
+ // if the interface socket exists then wpa-supplicant was invoked successfully
+ if (!QFile(QLatin1String(path + "/" + ifc)).exists()) {
+ qCWarning(B2QT_WIFI) << "failed to invoke wpa_supplicant!\n" << ssDaemon.readAll();
return -1;
}
// reset sockets used for exiting from hung state
@@ -102,19 +103,29 @@ int q_wifi_stop_supplicant()
{
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;
+
+ if (QFile(pidFile).exists()) {
+ 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) {
+ qCWarning(B2QT_WIFI) << "failed to stop a supplicant process!\n" << ssDaemon.readAll();;
+ return -1;
+ }
+
+ QFile::remove(pidFile);
}
- QFile::remove(QLatin1String(ctrlInterface + "/" + ifc));
- QFile::remove(pidFile);
+ QByteArray path = controlInterfacePath();
+ if (path.isEmpty())
+ return -1;
+
+ QFile::remove(QLatin1String(path + "/" + ifc));
+
return 0;
}
diff --git a/src/wifi/qwifimanager.cpp b/src/wifi/qwifimanager.cpp
index e971fd1..2a5cfff 100644
--- a/src/wifi/qwifimanager.cpp
+++ b/src/wifi/qwifimanager.cpp
@@ -20,6 +20,8 @@
#include "qwifinetworklistmodel_p.h"
#include "qwifinetwork_p.h"
#include "qwifimanager_p.h"
+#include "qwifiutils_p.h"
+
#include "qwifidevice.h"
#include <QtCore/QFile>
@@ -40,7 +42,6 @@ QWifiManagerPrivate::QWifiManagerPrivate(QWifiManager *manager)
, m_interface(QWifiDevice::wifiInterfaceName())
, m_backendState(QWifiManager::NotRunning)
, m_networkState(QWifiManager::Disconnected)
- , m_setCurrentSSID(true)
{
qCDebug(B2QT_WIFI) << "using wifi interface: " << m_interface;
}
@@ -51,54 +52,29 @@ QWifiManagerPrivate::~QWifiManagerPrivate()
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()
+void QWifiManagerPrivate::setCurrentSSID(const QString &ssid)
{
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);
- }
+ qCDebug(B2QT_WIFI) << "current SSID: " << m_currentSSID << " -> " << ssid;
+ if (m_currentSSID == ssid)
+ return;
+
+ m_currentSSID = ssid;
+ emit q->currentSSIDChanged(m_currentSSID);
}
-void QWifiManagerPrivate::setCurrentSSID()
+void QWifiManagerPrivate::handleAuthenticating(QWifiEvent *event)
{
- 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);
- }
- }
+ QString data = event->data().trimmed();
+ QString ssid = data.mid(data.indexOf(QLatin1String("SSID")) + 6);
+ ssid = ssid.left(ssid.lastIndexOf(QLatin1Char('\'')));
+
+ setCurrentSSID(QWifiUtils::decodeHexEncoded(ssid));
+ updateNetworkState(QWifiManager::Authenticating);
}
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);
@@ -147,11 +123,8 @@ void QWifiManagerPrivate::updateWifiState()
if (ps.readAll().contains("wpa_supplicant"))
supplicantRunning = true;
#endif
- if (supplicantRunning) {
- m_wifiController->resetSupplicantSocket();
- m_wifiController->startWifiEventThread();
+ if (supplicantRunning && m_wifiController->resetSupplicantSocket())
m_backendState = QWifiManager::Running;
- }
}
QString QWifiManagerPrivate::call(const QString &command)
@@ -168,20 +141,21 @@ QString QWifiManagerPrivate::call(const QString &command)
actualCommand.prepend(prefix);
#endif
#endif
- if (q_wifi_command(m_interface, actualCommand.toLatin1(), data, &len) < 0) {
- qCDebug(B2QT_WIFI) << "call to supplicant failed: " << actualCommand;
+ qCDebug(B2QT_WIFI) << "call command: " << actualCommand.toLocal8Bit();
+ if (q_wifi_command(m_interface, actualCommand.toLocal8Bit(), data, &len) < 0) {
+ qCDebug(B2QT_WIFI) << "call to supplicant failed!";
return QString();
}
if (len < sizeof(data))
data[len] = 0;
QString result = QLatin1String(data);
- return result;
+ return result.trimmed();
}
bool QWifiManagerPrivate::checkedCall(const QString &command)
{
- return call(command).trimmed().toUpper() == QLatin1String("OK");
+ return call(command).toUpper() == QLatin1String("OK");
}
void QWifiManagerPrivate::updateLastError(const QString &error)
@@ -238,11 +212,11 @@ void QWifiManagerPrivate::updateLastError(const QString &error)
\value SSID informal (human) name of a Wifi network (QString)
\value BSSID basic service set identification of a network, used to uniquely identify BSS (QString)
- \value SignalStrength strength of a Wifi signal, measured in dBm (int)
- \value WPASupported holds whether network access point supports WPA security protocol (QString)
- \value WPA2Supported holds whether network access point supports WPA2 security protocol (QString)
- \value WEPSupported holds whether network access point supports WEP security protocol (QString)
- \value WPSSupported holds whether network access point supports WPS security protocol (QString)
+ \value SignalStrength strength of a Wifi signal represented as percentage (0-100) (int)
+ \value WPASupported holds whether network access point supports WPA security protocol (bool)
+ \value WPA2Supported holds whether network access point supports WPA2 security protocol (bool)
+ \value WEPSupported holds whether network access point supports WEP security protocol (bool)
+ \value WPSSupported holds whether network access point supports WPS security protocol (bool)
*/
QWifiManager* QWifiManager::m_instance = 0;
@@ -424,8 +398,6 @@ bool QWifiManager::event(QEvent *event)
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();
@@ -434,11 +406,10 @@ bool QWifiManager::event(QEvent *event)
d->handleDisconneced();
return true;
case WIFI_AUTHENTICATING:
- d->updateNetworkState(Authenticating);
- d->emitCurrentSSIDChanged();
+ d->handleAuthenticating(static_cast<QWifiEvent *>(event));
return true;
case WIFI_HANDSHAKE_FAILED:
- d->updateNetworkState(HandshakeFailed);
+ d->updateNetworkState(QWifiManager::HandshakeFailed);
return true;
case QEvent::Timer: {
int tid = static_cast<QTimerEvent *>(event)->timerId();
@@ -469,15 +440,16 @@ bool QWifiManager::connect(QWifiConfiguration *config)
}
d->call(QStringLiteral("DISABLE_NETWORK all"));
+ d->setCurrentSSID(config->ssid());
- 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);
+ const QStringList configuredNetworks = d->call(QStringLiteral("LIST_NETWORKS")).split('\n');
+ for (int i = 1; i < configuredNetworks.length(); ++i) {
+ const QStringList networkFields = configuredNetworks.at(i).split('\t');
+ const QString ssid = QWifiUtils::decodeHexEncoded(networkFields.at(1));
+ if (ssid == d->m_currentSSID) {
+ id = networkFields.at(0);
networkKnown = true;
break;
}
@@ -485,7 +457,7 @@ bool QWifiManager::connect(QWifiConfiguration *config)
if (!networkKnown) {
bool ok;
- id = d->call(QStringLiteral("ADD_NETWORK")).trimmed();
+ id = d->call(QStringLiteral("ADD_NETWORK"));
id.toInt(&ok);
if (!ok) {
d->updateLastError(QStringLiteral("failed to add network!"));
@@ -503,7 +475,11 @@ bool QWifiManager::connect(QWifiConfiguration *config)
QString key_mgmt;
QString protocol = config->protocol().toUpper();
QString psk = config->passphrase();
+
+ // --------------------- configure network ------------------------------
// ref: http://w1.fi/cgit/hostap/plain/wpa_supplicant/wpa_supplicant.conf
+ // ref: https://www.freebsd.org/cgi/man.cgi?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.
@@ -517,6 +493,10 @@ bool QWifiManager::connect(QWifiConfiguration *config)
// open network
key_mgmt = QLatin1String("NONE");
}
+
+ if (config->isSsidHidden())
+ ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" scan_ssid 1"));
+
ok = ok && d->checkedCall(setNetworkCommand + QLatin1String(" key_mgmt ") + key_mgmt);
if (!ok) {
if (!networkKnown)
@@ -547,9 +527,6 @@ void QWifiManager::handleBackendStateChanged(BackendState backendState)
{
Q_D(QWifiManager);
switch (backendState) {
- case Running:
- d->m_setCurrentSSID = true;
- break;
case NotRunning:
d->updateNetworkState(Disconnected);
break;
@@ -564,7 +541,6 @@ 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 {
diff --git a/src/wifi/qwifimanager_p.h b/src/wifi/qwifimanager_p.h
index ef8a0da..6142c83 100644
--- a/src/wifi/qwifimanager_p.h
+++ b/src/wifi/qwifimanager_p.h
@@ -25,6 +25,8 @@
QT_BEGIN_NAMESPACE
+class QWifiEvent;
+
class QWifiManagerPrivate
{
Q_DECLARE_PUBLIC(QWifiManager)
@@ -33,11 +35,10 @@ public:
virtual ~QWifiManagerPrivate();
// methods
- QString getConnectedNetwork();
- void setCurrentSSID();
- void emitCurrentSSIDChanged();
+ void setCurrentSSID(const QString &ssid);
void handleConnected();
void handleDisconneced();
+ void handleAuthenticating(QWifiEvent *event);
void updateNetworkState(QWifiManager::NetworkState networkState);
void updateBackendState(QWifiManager::BackendState backendState);
@@ -57,9 +58,7 @@ public:
QByteArray m_interface;
QWifiManager::BackendState m_backendState;
QWifiManager::NetworkState m_networkState;
- bool m_setCurrentSSID;
QString m_currentSSID;
- QString m_previousSSID;
QString m_lastError;
};
diff --git a/src/wifi/qwifinetworklistmodel.cpp b/src/wifi/qwifinetworklistmodel.cpp
index 6f53295..9d6202f 100644
--- a/src/wifi/qwifinetworklistmodel.cpp
+++ b/src/wifi/qwifinetworklistmodel.cpp
@@ -18,6 +18,7 @@
****************************************************************************/
#include "qwifinetworklistmodel_p.h"
#include "qwifinetwork_p.h"
+#include "qwifiutils_p.h"
#include "qwifimanager.h"
@@ -123,14 +124,24 @@ void QWifiNetworkListModel::parseScanResults(const QString &results)
continue;
int pos = 0;
- QString ssid = info.at(4);
+ QString ssid = QWifiUtils::decodeHexEncoded(info.at(4));
+ if (ssid.isEmpty())
+ continue;
+
sensibleNetworks.insert(ssid);
QWifiNetwork *knownNetwork = networkForSSID(ssid, &pos);
if (!knownNetwork)
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;
+
+ int signalStrength = info.at(2).trimmed().toInt();
+ if (signalStrength < 0) {
+ // signal is reported in dBm, rough conversion: best = -40, worst = -100
+ int val = qAbs(qMax(-100, qMin(signalStrength, -40)) + 40); // clamp and normalize to 0
+ signalStrength = 100 - (int) ((100.0 * (double) val) / 60.0);
+ } else if (signalStrength > 100) {
+ qCWarning(B2QT_WIFI) << "unexpected value for a signal level: " << signalStrength;
+ }
+
if (!knownNetwork) {
QWifiNetwork *network = new QWifiNetwork();
network->setOutOfRange(false);
diff --git a/src/wifi/qwifiutils.cpp b/src/wifi/qwifiutils.cpp
new file mode 100644
index 0000000..21c440b
--- /dev/null
+++ b/src/wifi/qwifiutils.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 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 "qwifiutils_p.h"
+
+QT_BEGIN_NAMESPACE
+
+int QWifiUtils::hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+
+int QWifiUtils::hex2byte(const char *hex)
+{
+ int a, b;
+ a = hex2num(*hex++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*hex++);
+ if (b < 0)
+ return -1;
+ return (a << 4) | b;
+}
+
+// the logic of this function is taken from wpa_supplicant source code (BSD
+// licensed code) see http://w1.fi/cgit file hostapd/src/utils/common.c
+// For Ascii encoded string, any octet < 32 or > 127 is encoded as a "\x"
+// followed by the hex representation of the octet. Exception chars are ",
+// \, \e, \n, \r, \t which are escaped by a backslash
+QString QWifiUtils::decodeHexEncoded(const QString &encoded)
+{
+ int maxlen = encoded.size() + 1;
+ QByteArray buf;
+ buf.resize(maxlen);
+ const char *pos = encoded.toLocal8Bit().constData();
+ int len = 0;
+ int val;
+
+ while (*pos) {
+ if (len + 1 >= maxlen)
+ break;
+ switch (*pos) {
+ case '\\':
+ pos++;
+ switch (*pos) {
+ case '\\':
+ buf[len++] = '\\';
+ pos++;
+ break;
+ case '"':
+ buf[len++] = '"';
+ pos++;
+ break;
+ case 'n':
+ buf[len++] = '\n';
+ pos++;
+ break;
+ case 'r':
+ buf[len++] = '\r';
+ pos++;
+ break;
+ case 't':
+ buf[len++] = '\t';
+ pos++;
+ break;
+ case 'e':
+ buf[len++] = '\033';
+ pos++;
+ break;
+ case 'x':
+ pos++;
+ val = hex2byte(pos);
+ if (val < 0) {
+ val = hex2num(*pos);
+ if (val < 0)
+ break;
+ buf[len++] = val;
+ pos++;
+ } else {
+ buf[len++] = val;
+ pos += 2;
+ }
+ break;
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ val = *pos++ - '0';
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ if (*pos >= '0' && *pos <= '7')
+ val = val * 8 + (*pos++ - '0');
+ buf[len++] = val;
+ break;
+ default:
+ break;
+ }
+ break;
+ default:
+ buf[len++] = *pos++;
+ break;
+ }
+ }
+ if (maxlen > len)
+ buf[len] = '\0';
+
+ return QString::fromUtf8(buf);
+}
+
+QT_END_NAMESPACE
diff --git a/src/wifi/qwifiutils_p.h b/src/wifi/qwifiutils_p.h
new file mode 100644
index 0000000..8b3e54a
--- /dev/null
+++ b/src/wifi/qwifiutils_p.h
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 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 QWIFIUTILS_H
+#define QWIFIUTILS_H
+
+#include <QtCore/QString>
+
+QT_BEGIN_NAMESPACE
+
+class QWifiUtils
+{
+public:
+ static int hex2num(char c);
+ static int hex2byte(const char *hex);
+
+ static QString decodeHexEncoded(const QString &encoded);
+};
+
+QT_END_NAMESPACE
+
+#endif // QWIFIUTILS_H
diff --git a/src/wifi/wifi.pro b/src/wifi/wifi.pro
index e558081..f248774 100644
--- a/src/wifi/wifi.pro
+++ b/src/wifi/wifi.pro
@@ -16,7 +16,8 @@ HEADERS += \
$$PWD/qwifinetworklistmodel_p.h \
$$PWD/qwificontroller_p.h \
$$PWD/qwifidevice.h \
- $$PWD/qwificonfiguration.h
+ $$PWD/qwificonfiguration.h \
+ $$PWD/qwifiutils_p.h
SOURCES += \
$$PWD/qwifimanager.cpp \
@@ -24,7 +25,8 @@ SOURCES += \
$$PWD/qwifinetworklistmodel.cpp \
$$PWD/qwificontroller.cpp \
$$PWD/qwifidevice.cpp \
- $$PWD/qwificonfiguration.cpp
+ $$PWD/qwificonfiguration.cpp \
+ $$PWD/qwifiutils.cpp
android: {
LIBS += -lhardware_legacy -lcutils