/* $ Author: Mirko Boehm $ $ License: This code is licensed under the LGPL $ $ Copyright: (C) 1996-2003, Mirko Boehm $ $ Contact: Mirko Boehm http://www.kde.org http://www.hackerbuero.org $ */ #include #include #include #include #include // for ::close #include "linuxwirelesswidget.h" #include "config.h" extern "C" { #include // #include } int LinuxWireLessWidget::socketFD; TQStringList LinuxWireLessWidget::deviceNames; LinuxWireLessWidget::LinuxWireLessWidget(TQWidget *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 TQWidget::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: TQStringList::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: TQString 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(""); 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; TQString 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()); } TQToolTip::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"