summaryrefslogtreecommitdiffstats
path: root/wifi/kwireless/linuxwirelesswidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'wifi/kwireless/linuxwirelesswidget.cpp')
-rw-r--r--wifi/kwireless/linuxwirelesswidget.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/wifi/kwireless/linuxwirelesswidget.cpp b/wifi/kwireless/linuxwirelesswidget.cpp
new file mode 100644
index 00000000..de35b84b
--- /dev/null
+++ b/wifi/kwireless/linuxwirelesswidget.cpp
@@ -0,0 +1,227 @@
+/*
+ $ Author: Mirko Boehm $
+ $ License: This code is licensed under the LGPL $
+ $ Copyright: (C) 1996-2003, Mirko Boehm $
+ $ Contact: Mirko Boehm <mirko@kde.org>
+ http://www.kde.org
+ http://www.hackerbuero.org $
+*/
+
+#include <qtooltip.h>
+#include <qtimer.h>
+#include <kdebug.h>
+#include <klocale.h>
+#include <unistd.h> // for ::close
+#include "linuxwirelesswidget.h"
+#include "config.h"
+
+extern "C" {
+#include <iwlib.h>
+// #include <linux/wireless.h>
+}
+
+int LinuxWireLessWidget::socketFD;
+QStringList LinuxWireLessWidget::deviceNames;
+
+LinuxWireLessWidget::LinuxWireLessWidget(QWidget *parent, const char* name)
+ : KWireLessWidget(parent, name),
+ m_number (-1)
+{
+}
+
+LinuxWireLessWidget::~LinuxWireLessWidget()
+{
+ if(instances() == 1)
+ { // I am the only one
+ if(socketFD != 0)
+ {
+ kdDebug() << "KWireLessWidget dtor: closing FD, over and out."
+ << endl;
+ ::close(socketFD); // prevent from using QWidget::close
+ socketFD = 0;
+ }
+ }
+}
+
+
+void LinuxWireLessWidget::poll()
+{
+ // BE AWARE: do not call this method, only the first instance is
+ // supposed to do so, and it has been taken care of!
+ // this will repoll the device names every ReEnumCountDownStart
+ // timer ticks:
+ const int ReEnumCountDownStart = 30;
+ static int ReEnumCountDown;
+ struct wireless_info info;
+ struct wireless_config config;
+ struct iwreq wrq;
+ bool updateNeeded = false;
+ bool updateToolTip = false;
+
+ // get a socket file descriptor:
+ if(socketFD == 0)
+ {
+ socketFD = iw_sockets_open();
+ }
+ if(socketFD == 0)
+ {
+ kdDebug() << "KWireLessWidget ctor: opening socket file descriptor failed."
+ << endl;
+ return;
+ }
+ // ----- query the available devices:
+ mutex.lock(); // querying the device names is protected:
+ if(ReEnumCountDown-- == 0)
+ {
+ ReEnumCountDown = ReEnumCountDownStart;
+ updateToolTip = true;
+
+ // query device information:
+ deviceNames.clear();
+ iw_enum_devices(socketFD, devEnumHandler, 0, 0);
+
+ if (m_number != (int) deviceNames.count())
+ {
+ m_number = deviceNames.count();
+ kdDebug() << "KWireLessWidget::poll: found "
+ << deviceNames.count() << " wireless "
+ << ((deviceNames.count() == 1) ? "device" : "devices")
+ << endl;
+ }
+ }
+
+ // ----- get the device information:
+ QStringList::Iterator it;
+
+ deviceInfo.clear();
+ for(it=deviceNames.begin(); it!=deviceNames.end(); ++it)
+ {
+ // I think it is OK to use this cast, since the QT docs say the
+ // returned pointer is valid until the value of the string is
+ // changed, which will not happen here (horrible cast, anyway
+ // ...):
+ char *device_c_str = (char*)(*it).latin1();
+
+ if(iw_get_basic_config(socketFD, device_c_str, &config) == -1)
+ {
+ kdDebug() << "KWireLessWidget::poll: device "
+ << *it << " does not seem to be a wireless device"
+ << endl;
+ } else {
+ // WORK_TO_DO: decide whether updates are needed or not
+ // create a DeviceInfo object and fill it:
+ QString dev, essid, encr;
+ float quality=0, signal=0, noise=0;
+ int bitrate;
+
+ dev = *it;
+ // get the bitrate:
+ if(iw_get_ext(socketFD, device_c_str, SIOCGIWRATE, &wrq) >=0)
+ {
+ info.has_bitrate = 1;
+ memcpy(&(info.bitrate), &(wrq.u.bitrate), sizeof(iwparam));
+ }
+ bitrate = info.bitrate.value;
+ // get the ranges (needed to translate the absolute values
+ // reported by the driver):
+ if(iw_get_range_info(socketFD, device_c_str, &(info.range)) >= 0)
+ {
+ info.has_range = 1;
+ }
+
+ // get the device statistics:
+#ifdef HAVE_IW_27
+ if(iw_get_stats(socketFD, device_c_str, &(info.stats), &(info.range), info.has_range)>= 0)
+#else
+ if(iw_get_stats(socketFD, device_c_str, &(info.stats)) >= 0)
+#endif
+ {
+ info.has_stats = 1;
+ // get the link quality (logic has been taken from
+ // wireless-tools, iwlib.c):
+
+ int rqn = info.range.max_qual.noise;
+ int rql = info.range.max_qual.level;
+ int rmq = info.range.max_qual.qual;
+
+ // in case the quality levels are zero, do not allow division by zero, and
+ // instead set the max. possible quality range to 255 (max of "unsigned char")
+ if (!rqn) rqn = 255;
+ if (!rql) rql = 255;
+ if (!rmq) rmq = 255;
+
+ bool isAbs; // true if values are relative tp a peak value,
+ // otherwise values are dBm
+ isAbs = (float)info.stats.qual.level > (int)info.range.max_qual.level;
+ if(isAbs)
+ {
+ noise = 1 + ((float)info.stats.qual.noise - 0x100) / rqn;
+ signal = 1 + ((float)info.stats.qual.level - 0x100) / rql;
+ } else {
+ noise = ((float)info.stats.qual.noise) / rqn;
+ signal = ((float)info.stats.qual.level) / rql;
+ }
+
+ quality = ((float)info.stats.qual.qual) / rmq;
+
+ updateNeeded = true;
+ }
+ if(config.has_essid)
+ essid = config.essid;
+ else
+ essid = i18n("<unknown>");
+
+ if (config.has_key && config.key_size>0) {
+ encr = i18n("enabled");
+ } else {
+ // non-root users don't get information about encryption status
+ encr = (getuid() == 0) ? i18n("disabled") : i18n("no information");
+ }
+
+ DeviceInfo *device = new DeviceInfo(dev, essid, encr, quality, signal,
+ noise, bitrate);
+ deviceInfo.append(device);
+ }
+ }
+ mutex.unlock();
+ if(updateNeeded)
+ {
+ emit(updateDeviceInfo(&deviceInfo));
+ repaint(false);
+ }
+ if(updateToolTip)
+ {
+ DeviceInfo *info;
+ QString text;
+
+ for(info=deviceInfo.first(); info; info=deviceInfo.next())
+ {
+ if (!text.isEmpty())
+ text.append('\n');
+ text += i18n("%1: Link Quality %2, Bitrate: %3")
+ .arg(info->device())
+ .arg(info->qualityString())
+ .arg(info->bitrateString());
+ }
+ QToolTip::add(this, text);
+
+ updateToolTip = false;
+ }
+
+ timer->start(330, true); // single shot
+}
+
+// static:
+int LinuxWireLessWidget::devEnumHandler(int skfd, char * ifname, char **, int)
+{
+ struct wireless_config config;
+
+ if(iw_get_basic_config(skfd, ifname, &config) != -1)
+ {
+ deviceNames.append(ifname);
+ }
+ return 0;
+}
+
+
+#include "linuxwirelesswidget.moc"