diff --git a/wpa_supplicant/doc/docbook/wpa_gui.sgml b/wpa_supplicant/doc/docbook/wpa_gui.sgml
index fe9123624..5f7b49da0 100644
--- a/wpa_supplicant/doc/docbook/wpa_gui.sgml
+++ b/wpa_supplicant/doc/docbook/wpa_gui.sgml
@@ -16,6 +16,7 @@
wpa_gui
-p path to ctrl sockets
-i ifname
+ -m seconds
-t
-q
@@ -51,6 +52,14 @@
a control socket in the socket path.
+
+ -m seconds
+
+ Set the update interval in seconds for the signal
+ strength meter. This value must be a positive integer, otherwise
+ meter is not enabled (default behavior).
+
+
-t
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
index bc6fa7f4a..408e3876c 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.cpp
@@ -135,6 +135,7 @@ WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
monitor_conn = NULL;
msgNotifier = NULL;
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
+ signalMeterInterval = 0;
parse_argv();
@@ -161,6 +162,10 @@ WpaGui::WpaGui(QApplication *_app, QWidget *parent, const char *, Qt::WFlags)
timer->setSingleShot(FALSE);
timer->start(1000);
+ signalMeterTimer = new QTimer(this);
+ signalMeterTimer->setInterval(signalMeterInterval);
+ connect(signalMeterTimer, SIGNAL(timeout()), SLOT(signalMeterUpdate()));
+
if (openCtrlConnection(ctrl_iface) < 0) {
debug("Failed to open control connection to "
"wpa_supplicant.");
@@ -234,7 +239,7 @@ void WpaGui::parse_argv()
{
int c;
for (;;) {
- c = getopt(qApp->argc(), qApp->argv(), "i:p:tq");
+ c = getopt(qApp->argc(), qApp->argv(), "i:m:p:tq");
if (c < 0)
break;
switch (c) {
@@ -242,6 +247,9 @@ void WpaGui::parse_argv()
free(ctrl_iface);
ctrl_iface = strdup(optarg);
break;
+ case 'm':
+ signalMeterInterval = atoi(optarg) * 1000;
+ break;
case 'p':
free(ctrl_iface_dir);
ctrl_iface_dir = strdup(optarg);
@@ -496,6 +504,8 @@ void WpaGui::updateStatus()
textBssid->clear();
textIpAddress->clear();
updateTrayToolTip(tr("no status information"));
+ updateTrayIcon(TrayIconOffline);
+ signalMeterTimer->stop();
#ifdef CONFIG_NATIVE_WINDOWS
static bool first = true;
@@ -544,6 +554,11 @@ void WpaGui::updateStatus()
ssid_updated = true;
textSsid->setText(pos);
updateTrayToolTip(pos + tr(" (associated)"));
+ if (!signalMeterInterval) {
+ /* if signal meter is not enabled show
+ * full signal strength */
+ updateTrayIcon(TrayIconSignalExcellent);
+ }
} else if (strcmp(start, "ip_address") == 0) {
ipaddr_updated = true;
textIpAddress->setText(pos);
@@ -587,6 +602,23 @@ void WpaGui::updateStatus()
} else
textEncryption->clear();
+ if (signalMeterInterval) {
+ /*
+ * Handle signal meter service. When network is not associated,
+ * deactivate timer, otherwise keep it going. Tray icon has to
+ * be initialized here, because of the initial delay of the
+ * timer.
+ */
+ if (ssid_updated) {
+ if (!signalMeterTimer->isActive()) {
+ updateTrayIcon(TrayIconConnected);
+ signalMeterTimer->start();
+ }
+ } else {
+ signalMeterTimer->stop();
+ }
+ }
+
if (!status_updated)
textStatus->clear();
if (!auth_updated)
@@ -594,6 +626,7 @@ void WpaGui::updateStatus()
if (!ssid_updated) {
textSsid->clear();
updateTrayToolTip(tr("(not-associated)"));
+ updateTrayIcon(TrayIconOffline);
}
if (!bssid_updated)
textBssid->clear();
@@ -828,6 +861,53 @@ void WpaGui::ping()
}
+void WpaGui::signalMeterUpdate()
+{
+ char reply[128];
+ size_t reply_len = sizeof(reply);
+ char *rssi;
+ int rssi_value;
+
+ ctrlRequest("SIGNAL_POLL", reply, &reply_len);
+
+ /* In order to eliminate signal strength fluctuations, try
+ * to obtain averaged RSSI value in the first place. */
+ if ((rssi = strstr(reply, "AVG_RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("AVG_RSSI")]);
+ else if ((rssi = strstr(reply, "RSSI=")) != NULL)
+ rssi_value = atoi(&rssi[sizeof("RSSI")]);
+ else {
+ debug("Failed to get RSSI value");
+ updateTrayIcon(TrayIconSignalNone);
+ return;
+ }
+
+ debug("RSSI value: %d", rssi_value);
+
+ /*
+ * NOTE: The code below assumes, that the unit of the value returned
+ * by the SIGNAL POLL request is dBm. It might not be true for all
+ * wpa_supplicant drivers.
+ */
+
+ /*
+ * Calibration is based on "various Internet sources". Nonetheless,
+ * it seems to be compatible with the Windows 8.1 strength meter -
+ * tested on Intel Centrino Advanced-N 6235.
+ */
+ if (rssi_value >= -60)
+ updateTrayIcon(TrayIconSignalExcellent);
+ else if (rssi_value >= -68)
+ updateTrayIcon(TrayIconSignalGood);
+ else if (rssi_value >= -76)
+ updateTrayIcon(TrayIconSignalOk);
+ else if (rssi_value >= -84)
+ updateTrayIcon(TrayIconSignalWeak);
+ else
+ updateTrayIcon(TrayIconSignalNone);
+}
+
+
static int str_match(const char *a, const char *b)
{
return strncmp(a, b, strlen(b)) == 0;
@@ -1278,10 +1358,7 @@ void WpaGui::createTrayIcon(bool trayOnly)
QApplication::setQuitOnLastWindowClosed(false);
tray_icon = new QSystemTrayIcon(this);
- if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
- else
- tray_icon->setIcon(QIcon(":/icons/wpa_gui.png"));
+ updateTrayIcon(TrayIconOffline);
connect(tray_icon,
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
@@ -1421,6 +1498,59 @@ void WpaGui::updateTrayToolTip(const QString &msg)
}
+void WpaGui::updateTrayIcon(TrayIconType type)
+{
+ if (!tray_icon || currentIconType == type)
+ return;
+
+ QIcon icon;
+ QIcon fallback_icon;
+
+ if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
+ fallback_icon = QIcon(":/icons/wpa_gui.svg");
+ else
+ fallback_icon = QIcon(":/icons/wpa_gui.png");
+
+ switch (type) {
+ case TrayIconOffline:
+ icon = QIcon::fromTheme("network-wireless-offline",
+ fallback_icon);
+ break;
+ case TrayIconAcquiring:
+ icon = QIcon::fromTheme("network-wireless-acquiring",
+ fallback_icon);
+ break;
+ case TrayIconConnected:
+ icon = QIcon::fromTheme("network-wireless-connected",
+ fallback_icon);
+ break;
+ case TrayIconSignalNone:
+ icon = QIcon::fromTheme("network-wireless-signal-none",
+ fallback_icon);
+ break;
+ case TrayIconSignalWeak:
+ icon = QIcon::fromTheme("network-wireless-signal-weak",
+ fallback_icon);
+ break;
+ case TrayIconSignalOk:
+ icon = QIcon::fromTheme("network-wireless-signal-ok",
+ fallback_icon);
+ break;
+ case TrayIconSignalGood:
+ icon = QIcon::fromTheme("network-wireless-signal-good",
+ fallback_icon);
+ break;
+ case TrayIconSignalExcellent:
+ icon = QIcon::fromTheme("network-wireless-signal-excellent",
+ fallback_icon);
+ break;
+ }
+
+ currentIconType = type;
+ tray_icon->setIcon(icon);
+}
+
+
void WpaGui::closeEvent(QCloseEvent *event)
{
if (eh) {
diff --git a/wpa_supplicant/wpa_gui-qt4/wpagui.h b/wpa_supplicant/wpa_gui-qt4/wpagui.h
index 026eacb92..c0de67b0d 100644
--- a/wpa_supplicant/wpa_gui-qt4/wpagui.h
+++ b/wpa_supplicant/wpa_gui-qt4/wpagui.h
@@ -22,6 +22,18 @@ class WpaGui : public QMainWindow, public Ui::WpaGui
Q_OBJECT
public:
+
+ enum TrayIconType {
+ TrayIconOffline = 0,
+ TrayIconAcquiring,
+ TrayIconConnected,
+ TrayIconSignalNone,
+ TrayIconSignalWeak,
+ TrayIconSignalOk,
+ TrayIconSignalGood,
+ TrayIconSignalExcellent,
+ };
+
WpaGui(QApplication *app, QWidget *parent = 0, const char *name = 0,
Qt::WFlags fl = 0);
~WpaGui();
@@ -49,6 +61,7 @@ public slots:
virtual void scan();
virtual void eventHistory();
virtual void ping();
+ virtual void signalMeterUpdate();
virtual void processMsg(char *msg);
virtual void processCtrlReq(const char *req);
virtual void receiveMsgs();
@@ -70,6 +83,7 @@ public slots:
virtual void showTrayMessage(QSystemTrayIcon::MessageIcon type,
int sec, const QString &msg);
virtual void showTrayStatus();
+ virtual void updateTrayIcon(TrayIconType type);
virtual void updateTrayToolTip(const QString &msg);
virtual void wpsDialog();
virtual void peersDialog();
@@ -113,6 +127,7 @@ private:
QAction *quitAction;
QMenu *tray_menu;
QSystemTrayIcon *tray_icon;
+ TrayIconType currentIconType;
QString wpaStateTranslate(char *state);
void createTrayIcon(bool);
bool ackTrayIcon;
@@ -127,6 +142,9 @@ private:
void stopWpsRun(bool success);
+ QTimer *signalMeterTimer;
+ int signalMeterInterval;
+
#ifdef CONFIG_NATIVE_WINDOWS
QAction *fileStartServiceAction;
QAction *fileStopServiceAction;