summaryrefslogtreecommitdiffstats
path: root/src/systeminfo/linux/qnetworkinfo_linux.cpp
diff options
context:
space:
mode:
authorLorn Potter <lorn.potter@jollamobile.com>2013-05-09 07:51:50 +1000
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-05-09 07:43:28 +0200
commite70d49413c9e01cfad27156c6264e627cec2a919 (patch)
tree58cba2a6aee49361ad172b7fced449531d461c64 /src/systeminfo/linux/qnetworkinfo_linux.cpp
parent701442ad6358b9f27978aafae82074124468f88c (diff)
refactor the dir structure
putting system specific files into their own directories makes it look nicer and easier to work on. Change-Id: I485640a93d8fda8d60f6e92b34834f877f19f5b6 Reviewed-by: Lorn Potter <lorn.potter@jollamobile.com>
Diffstat (limited to 'src/systeminfo/linux/qnetworkinfo_linux.cpp')
-rw-r--r--src/systeminfo/linux/qnetworkinfo_linux.cpp1047
1 files changed, 1047 insertions, 0 deletions
diff --git a/src/systeminfo/linux/qnetworkinfo_linux.cpp b/src/systeminfo/linux/qnetworkinfo_linux.cpp
new file mode 100644
index 00000000..effdc93c
--- /dev/null
+++ b/src/systeminfo/linux/qnetworkinfo_linux.cpp
@@ -0,0 +1,1047 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtSystems module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkinfo_linux_p.h"
+
+#if !defined(QT_NO_OFONO)
+#include "qofonowrapper_p.h"
+#endif
+
+#include <QtCore/qdir.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qtextstream.h>
+#include <QtCore/qtimer.h>
+#if !defined(QT_NO_BLUEZ)
+#include <bluetooth/bluetooth.h>
+#include <bluetooth/hci.h>
+#include <bluetooth/hci_lib.h>
+#endif // QT_NO_BLUEZ
+
+#if !defined(QT_NO_UDEV)
+#include <QtCore/qsocketnotifier.h>
+#include <libudev.h>
+#endif // QT_NO_UDEV
+
+#include <math.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <linux/wireless.h>
+#include <unistd.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(const QString, NETWORK_SYSFS_PATH, (QLatin1String("/sys/class/net/")))
+
+Q_GLOBAL_STATIC_WITH_ARGS(const QStringList, WLAN_MASK, (QStringList() << QLatin1String("wlan*")))
+Q_GLOBAL_STATIC_WITH_ARGS(const QStringList, ETHERNET_MASK, (QStringList() << QLatin1String("eth*") << QLatin1String("usb*")))
+
+QNetworkInfoPrivate::QNetworkInfoPrivate(QNetworkInfo *parent)
+ : QObject(parent)
+ , q_ptr(parent)
+ , watchCurrentNetworkMode(false)
+ , watchNetworkInterfaceCount(false)
+ , watchNetworkSignalStrength(false)
+ , watchNetworkStatus(false)
+ , watchNetworkName(false)
+ , timer(0)
+#if !defined(QT_NO_OFONO)
+ , ofonoWrapper(0)
+#endif
+#if !defined(QT_NO_UDEV)
+ , udevNotifier(0)
+ , udevHandle(0)
+ , udevMonitor(0)
+#endif // QT_NO_UDEV
+{
+}
+
+QNetworkInfoPrivate::~QNetworkInfoPrivate()
+{
+#if !defined(QT_NO_UDEV)
+ if (udevMonitor)
+ udev_monitor_unref(udevMonitor);
+
+ if (udevHandle)
+ udev_unref(udevHandle);
+#endif // QT_NO_UDEV
+}
+
+int QNetworkInfoPrivate::networkInterfaceCount(QNetworkInfo::NetworkMode mode)
+{
+ if (watchNetworkInterfaceCount && (mode == QNetworkInfo::WlanMode
+ || mode == QNetworkInfo::EthernetMode
+ || mode == QNetworkInfo::BluetoothMode)) {
+ return networkInterfaceCounts.value(mode);
+ } else
+ return getNetworkInterfaceCount(mode);
+}
+
+int QNetworkInfoPrivate::networkSignalStrength(QNetworkInfo::NetworkMode mode, int interface)
+{
+ if (watchNetworkSignalStrength && (mode == QNetworkInfo::WlanMode
+ || mode == QNetworkInfo::EthernetMode
+ || mode == QNetworkInfo::BluetoothMode)) {
+ return networkSignalStrengths.value(QPair<QNetworkInfo::NetworkMode, int>(mode, interface));
+ } else
+ return getNetworkSignalStrength(mode, interface);
+}
+
+QNetworkInfo::CellDataTechnology QNetworkInfoPrivate::currentCellDataTechnology(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->currentCellDataTechnology(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QNetworkInfo::UnknownDataTechnology;
+}
+
+QNetworkInfo::NetworkMode QNetworkInfoPrivate::currentNetworkMode()
+{
+ if (watchCurrentNetworkMode)
+ return currentMode;
+ else
+ return getCurrentNetworkMode();
+}
+
+QNetworkInfo::NetworkStatus QNetworkInfoPrivate::networkStatus(QNetworkInfo::NetworkMode mode, int interface)
+{
+ if (watchNetworkStatus && (mode == QNetworkInfo::WlanMode
+ || mode == QNetworkInfo::EthernetMode
+ || mode == QNetworkInfo::BluetoothMode)) {
+ return networkStatuses.value(QPair<QNetworkInfo::NetworkMode, int>(mode, interface));
+ } else
+ return getNetworkStatus(mode, interface);
+}
+
+#ifndef QT_NO_NETWORKINTERFACE
+QNetworkInterface QNetworkInfoPrivate::interfaceForMode(QNetworkInfo::NetworkMode mode, int interface)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode: {
+ QStringList dirs = QDir(*NETWORK_SYSFS_PATH()).entryList(*WLAN_MASK());
+ if (interface < dirs.size()) {
+ QNetworkInterface networkInterface = QNetworkInterface::interfaceFromName(dirs.at(interface));
+ if (networkInterface.isValid())
+ return networkInterface;
+ }
+ break;
+ }
+
+ case QNetworkInfo::EthernetMode: {
+ QStringList dirs = QDir(*NETWORK_SYSFS_PATH()).entryList(*ETHERNET_MASK());
+ if (interface < dirs.size()) {
+ QNetworkInterface networkInterface = QNetworkInterface::interfaceFromName(dirs.at(interface));
+ if (networkInterface.isValid())
+ return networkInterface;
+ }
+ break;
+ }
+
+// case QNetworkInfo::BluetoothMode:
+// case QNetworkInfo::GsmMode:
+// case QNetworkInfo::CdmaMode:
+// case QNetworkInfo::WcdmaMode:
+// case QNetworkInfo::WimaxMode:
+// case QNetworkInfo::LteMode:
+// case QNetworkInfo::TdscdmaMode:
+ default:
+ break;
+ };
+
+ return QNetworkInterface();
+}
+#endif // QT_NO_NETWORKINTERFACE
+
+QString QNetworkInfoPrivate::cellId(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->cellId(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::currentMobileCountryCode(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->currentMcc(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::currentMobileNetworkCode(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->currentMnc(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::homeMobileCountryCode(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->homeMcc(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::homeMobileNetworkCode(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->homeMnc(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::imsi(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->imsi(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::locationAreaCode(int interface)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->lac(modem);
+ }
+ }
+#else
+ Q_UNUSED(interface)
+#endif
+ return QString();
+}
+
+QString QNetworkInfoPrivate::macAddress(QNetworkInfo::NetworkMode mode, int interface)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode: {
+ QStringList dirs = QDir(*NETWORK_SYSFS_PATH()).entryList(*WLAN_MASK());
+ if (interface < dirs.size()) {
+ QFile carrier(*NETWORK_SYSFS_PATH() + dirs.at(interface) + QString(QStringLiteral("/address")));
+ if (carrier.open(QIODevice::ReadOnly))
+ return QString::fromLatin1(carrier.readAll().simplified().data());
+ }
+ break;
+ }
+
+ case QNetworkInfo::EthernetMode: {
+ QStringList dirs = QDir(*NETWORK_SYSFS_PATH()).entryList(*ETHERNET_MASK());
+ if (interface < dirs.size()) {
+ QFile carrier(*NETWORK_SYSFS_PATH() + dirs.at(interface) + QString(QStringLiteral("/address")));
+ if (carrier.open(QIODevice::ReadOnly))
+ return QString::fromLatin1(carrier.readAll().simplified().data());
+ }
+ break;
+ }
+
+ case QNetworkInfo::BluetoothMode: {
+#if !defined(QT_NO_BLUEZ)
+ int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (ctl < 0)
+ break;
+ struct hci_dev_list_req *deviceList = (struct hci_dev_list_req *)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
+ deviceList->dev_num = HCI_MAX_DEV;
+ QString macAddress;
+ if (ioctl(ctl, HCIGETDEVLIST, deviceList) == 0) {
+ int count = deviceList->dev_num;
+ if (interface < count) {
+ struct hci_dev_info deviceInfo;
+ deviceInfo.dev_id = (deviceList->dev_req + interface)->dev_id;
+ if (ioctl(ctl, HCIGETDEVINFO, &deviceInfo) == 0) {
+ // do not use BDADDR_ANY, fails with gcc 4.6
+ bdaddr_t bdaddr_any = (bdaddr_t) {{0, 0, 0, 0, 0, 0}};
+ if (hci_test_bit(HCI_RAW, &deviceInfo.flags) && !bacmp(&deviceInfo.bdaddr, &bdaddr_any)) {
+ int hciDevice = hci_open_dev(deviceInfo.dev_id);
+ hci_read_bd_addr(hciDevice, &deviceInfo.bdaddr, 1000);
+ hci_close_dev(hciDevice);
+ }
+ char address[18];
+ ba2str(&deviceInfo.bdaddr, address);
+ macAddress = QString::fromLatin1(address);
+ }
+ }
+ }
+ free(deviceList);
+ close(ctl);
+ return macAddress;
+#else
+ break;
+#endif // QT_NO_BLUEZ
+ }
+
+// case QNetworkInfo::GsmMode:
+// case QNetworkInfo::CdmaMode:
+// case QNetworkInfo::WcdmaMode:
+// case QNetworkInfo::WimaxMode:
+// case QNetworkInfo::LteMode:
+// case QNetworkInfo::TdscdmaMode:
+ default:
+ break;
+ };
+
+ return QString();
+}
+
+QString QNetworkInfoPrivate::networkName(QNetworkInfo::NetworkMode mode, int interface)
+{
+ if (watchNetworkName && (mode == QNetworkInfo::WlanMode
+ || mode == QNetworkInfo::EthernetMode
+ || mode == QNetworkInfo::BluetoothMode)) {
+ return networkNames.value(QPair<QNetworkInfo::NetworkMode, int>(mode, interface));
+ } else
+ return getNetworkName(mode, interface);
+}
+
+extern QMetaMethod proxyToSourceSignal(const QMetaMethod &, QObject *);
+
+void QNetworkInfoPrivate::connectNotify(const QMetaMethod &signal)
+{
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QMetaMethod sourceSignal = proxyToSourceSignal(signal, ofonoWrapper);
+ connect(ofonoWrapper, sourceSignal, this, signal, Qt::UniqueConnection);
+ }
+#endif
+
+ static const QMetaMethod currentNetworkModeChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::currentNetworkModeChanged);
+ static const QMetaMethod networkNameChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkNameChanged);
+ static const QMetaMethod networkSignalStrengthChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkSignalStrengthChanged);
+ static const QMetaMethod networkStatusChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkStatusChanged);
+
+ // we always monitor "networkInterfaceCount" , as long as users connect any signals,
+ // with update to date network interface counts, we can compute network mode, strength,
+ // status, name properties in an efficient way
+ if (!watchNetworkInterfaceCount) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ networkInterfaceCounts.clear();
+ foreach (QNetworkInfo::NetworkMode mode, modes)
+ networkInterfaceCounts[mode] = getNetworkInterfaceCount(mode);
+#if !defined(QT_NO_UDEV)
+ if (!udevHandle) {
+ udevHandle = udev_new();
+ udevMonitor = udev_monitor_new_from_netlink(udevHandle, "udev");
+ udev_monitor_filter_add_match_subsystem_devtype(udevMonitor, "net", NULL);
+ udev_monitor_enable_receiving(udevMonitor);
+ udevNotifier = new QSocketNotifier(udev_monitor_get_fd(udevMonitor), QSocketNotifier::Read, this);
+ connect(udevNotifier, SIGNAL(activated(int)), this, SLOT(onUdevChanged()));
+ }
+ udevNotifier->setEnabled(true);
+
+#endif // QT_NO_UDEV
+ watchNetworkInterfaceCount = true;
+ }
+
+ if (signal == currentNetworkModeChangedSignal) {
+// we monitor "networkStatus" by default, as long as currentNetworkModeChanged signal
+// is connected, with always up to date network status, current network mode can
+// be fast computed.
+ if (!watchNetworkStatus) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ networkStatuses.clear();
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int count = networkInterfaceCount(mode);
+ for (int i = 0; i < count; ++i)
+ networkStatuses[QPair<QNetworkInfo::NetworkMode, int>(mode, i)] = getNetworkStatus(mode, i);
+ }
+ watchNetworkStatus = true;
+ }
+ currentMode = getCurrentNetworkMode();
+ watchCurrentNetworkMode = true;
+ } else if (signal == networkSignalStrengthChangedSignal) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ networkSignalStrengths.clear();
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int count = networkInterfaceCount(mode);
+ for (int i = 0; i < count; ++i)
+ networkSignalStrengths[QPair<QNetworkInfo::NetworkMode, int>(mode, i)] = getNetworkSignalStrength(mode, i);
+ }
+
+ watchNetworkSignalStrength = true;
+ } else if (signal == networkStatusChangedSignal) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ networkStatuses.clear();
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int count = networkInterfaceCount(mode);
+ for (int i = 0; i < count; ++i)
+ networkStatuses[QPair<QNetworkInfo::NetworkMode, int>(mode, i)] = getNetworkStatus(mode, i);
+ }
+
+ watchNetworkStatus = true;
+ } else if (signal == networkNameChangedSignal) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ networkNames.clear();
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int count = networkInterfaceCount(mode);
+ for (int i = 0; i < count; ++i)
+ networkNames[QPair<QNetworkInfo::NetworkMode, int>(mode, i)] = getNetworkName(mode, i);
+ }
+
+ watchNetworkName = true;
+ } else if (signal == currentNetworkModeChangedSignal) {
+ currentMode = getCurrentNetworkMode();
+ watchCurrentNetworkMode = true;
+ } else {
+ return;
+ }
+
+ if (!timer) {
+ timer = new QTimer(this);
+ timer->setInterval(2000);
+ connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
+ }
+
+ if (!timer->isActive())
+ timer->start();
+}
+
+void QNetworkInfoPrivate::disconnectNotify(const QMetaMethod &signal)
+{
+#if !defined(QT_NO_OFONO)
+ if (!QOfonoWrapper::isOfonoAvailable() || !ofonoWrapper)
+ return;
+
+ {
+ QMetaMethod sourceSignal = proxyToSourceSignal(signal, ofonoWrapper);
+ disconnect(ofonoWrapper, sourceSignal, this, signal);
+ }
+#endif
+
+ static const QMetaMethod currentNetworkModeChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::currentNetworkModeChanged);
+ static const QMetaMethod networkInterfaceCountChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkInterfaceCountChanged);
+ static const QMetaMethod networkNameChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkNameChanged);
+ static const QMetaMethod networkSignalStrengthChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkSignalStrengthChanged);
+ static const QMetaMethod networkStatusChangedSignal = QMetaMethod::fromSignal(&QNetworkInfoPrivate::networkStatusChanged);
+
+ if (signal == networkInterfaceCountChangedSignal
+ && !watchNetworkStatus && !watchNetworkName && !watchNetworkSignalStrength ) {
+#if !defined(QT_NO_UDEV)
+ udevNotifier->setEnabled(false);
+ watchNetworkInterfaceCount = false;
+ return;
+#endif // QT_NO_UDEV
+ watchNetworkInterfaceCount = false;
+ } else if (signal == networkSignalStrengthChangedSignal) {
+ watchNetworkSignalStrength = false;
+ } else if ((!watchCurrentNetworkMode) && (signal == networkStatusChangedSignal)) {
+ watchNetworkStatus = false;
+ } else if (signal == networkNameChangedSignal) {
+ watchNetworkName = false;
+ } else if (signal == currentNetworkModeChangedSignal) {
+ watchCurrentNetworkMode = false;
+ } else {
+ return;
+ }
+
+ if (!watchNetworkInterfaceCount && !watchNetworkSignalStrength && !watchNetworkStatus && !watchNetworkName && !watchCurrentNetworkMode)
+ timer->stop();
+}
+
+#if !defined(QT_NO_UDEV)
+void QNetworkInfoPrivate::onUdevChanged()
+{
+ struct udev_device *udevDevice = udev_monitor_receive_device(udevMonitor);
+ if (!udevDevice)
+ return;
+
+ if (0 != strcmp(udev_device_get_subsystem(udevDevice), "net"))
+ return;
+
+ QString sysname(QString::fromLocal8Bit(udev_device_get_sysname(udevDevice)));
+ if (watchNetworkInterfaceCount) {
+ if (sysname.startsWith(QString(QStringLiteral("eth"))) || sysname.startsWith(QString(QStringLiteral("usb")))) {
+ if (0 == strcmp(udev_device_get_action(udevDevice), "add"))
+ ++networkInterfaceCounts[QNetworkInfo::EthernetMode];
+ else if (0 == strcmp(udev_device_get_action(udevDevice), "remove"))
+ --networkInterfaceCounts[QNetworkInfo::EthernetMode];
+ emit networkInterfaceCountChanged(QNetworkInfo::EthernetMode,
+ networkInterfaceCounts[QNetworkInfo::EthernetMode]);
+ } else if (sysname.startsWith(QString(QStringLiteral("wlan")))) {
+ if (0 == strcmp(udev_device_get_action(udevDevice), "add"))
+ ++networkInterfaceCounts[QNetworkInfo::WlanMode];
+ else if (0 == strcmp(udev_device_get_action(udevDevice), "remove"))
+ --networkInterfaceCounts[QNetworkInfo::WlanMode];
+ emit networkInterfaceCountChanged(QNetworkInfo::WlanMode,
+ networkInterfaceCounts[QNetworkInfo::WlanMode]);
+ }
+ }
+
+ udev_device_unref(udevDevice);
+}
+#endif // QT_NO_UDEV
+
+void QNetworkInfoPrivate::onTimeout()
+{
+#if defined(QT_NO_UDEV)
+ if (watchNetworkInterfaceCount) {
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int value = getNetworkInterfaceCount(mode);
+ if (networkInterfaceCounts.value(mode) != value) {
+ networkInterfaceCounts[mode] = value;
+ emit networkInterfaceCountChanged(mode, value);
+ }
+ }
+ }
+#endif // QT_NO_UDEV
+
+ if (!watchNetworkSignalStrength && !watchNetworkStatus && !watchNetworkName && !watchCurrentNetworkMode)
+ return;
+
+ QList<QNetworkInfo::NetworkMode> modes;
+ modes << QNetworkInfo::WlanMode << QNetworkInfo::EthernetMode << QNetworkInfo::BluetoothMode;
+ foreach (QNetworkInfo::NetworkMode mode, modes) {
+ int count = networkInterfaceCount(mode);
+ for (int i = 0; i < count; ++i) {
+ if (watchNetworkSignalStrength) {
+ int value = getNetworkSignalStrength(mode, i);
+ QPair<QNetworkInfo::NetworkMode, int> key(mode, i);
+ if (networkSignalStrengths.value(key) != value) {
+ networkSignalStrengths[key] = value;
+ emit networkSignalStrengthChanged(mode, i, value);
+ }
+ }
+
+ if (watchNetworkStatus) {
+ QNetworkInfo::NetworkStatus value = getNetworkStatus(mode, i);
+ QPair<QNetworkInfo::NetworkMode, int> key(mode, i);
+ if (networkStatuses.value(key) != value) {
+ networkStatuses[key] = value;
+ emit networkStatusChanged(mode, i, value);
+ }
+ }
+
+ if (watchNetworkName) {
+ QString value = getNetworkName(mode, i);
+ QPair<QNetworkInfo::NetworkMode, int> key(mode, i);
+ if (networkNames.value(key) != value) {
+ networkNames[key] = value;
+ emit networkNameChanged(mode, i, value);
+ }
+ }
+ }
+ }
+
+ if (watchCurrentNetworkMode) {
+ QNetworkInfo::NetworkMode value = getCurrentNetworkMode();
+ if (currentMode != value) {
+ currentMode = value;
+ emit currentNetworkModeChanged(value);
+ }
+ }
+
+}
+
+int QNetworkInfoPrivate::getNetworkInterfaceCount(QNetworkInfo::NetworkMode mode)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode:
+ return QDir(*NETWORK_SYSFS_PATH()).entryList(*WLAN_MASK()).size();
+
+ case QNetworkInfo::EthernetMode:
+ return QDir(*NETWORK_SYSFS_PATH()).entryList(*ETHERNET_MASK()).size();
+
+ case QNetworkInfo::BluetoothMode: {
+ int count = -1;
+#if !defined(QT_NO_BLUEZ)
+ int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (ctl < 0)
+ return count;
+ struct hci_dev_list_req *deviceList = (struct hci_dev_list_req *)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
+ deviceList->dev_num = HCI_MAX_DEV;
+ if (ioctl(ctl, HCIGETDEVLIST, deviceList) == 0)
+ count = deviceList->dev_num;
+ free(deviceList);
+ close(ctl);
+#endif // QT_NO_BLUEZ
+ return count;
+ }
+
+ case QNetworkInfo::GsmMode:
+ case QNetworkInfo::CdmaMode:
+ case QNetworkInfo::WcdmaMode:
+ case QNetworkInfo::LteMode:
+ case QNetworkInfo::TdscdmaMode:
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ return ofonoWrapper->allModems().size();
+ }
+#endif
+
+// case QNetworkInfo::WimaxMode:
+ default:
+ return -1;
+ };
+}
+
+int QNetworkInfoPrivate::getNetworkSignalStrength(QNetworkInfo::NetworkMode mode, int interface)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode: {
+ QFile file(QString(QStringLiteral("/proc/net/wireless")));
+ if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
+ return -1;
+
+ QTextStream in(&file);
+ QString interfaceName = interfaceForMode(QNetworkInfo::WlanMode, interface).name();
+
+ QStringList lines = in.readAll().split(QStringLiteral("\n"));
+ for (int i = 0; i < lines.size(); i++) {
+ QString line = lines.at(i);
+ if (!line.isNull() && line.left(6).contains(interfaceName)) {
+ // A typical wireless received signal power over a network falls into the range of (-120, -20),
+ // we shift the dbm value, which is read from the field "Quality - level" in "/proc/net/wireless",
+ // from (-120, -20) to (0, 100) by adding 120. In case of outliers, we restrict them to the
+ // corresponding boundary value.
+ QString token = line.section(QString(QStringLiteral(" ")), 3, 3, QString::SectionSkipEmpty).simplified();
+ token.chop(1);
+ bool ok;
+ int signalStrength = token.toInt(&ok);
+ if (ok) {
+ signalStrength += 120;
+ if (signalStrength > 100)
+ signalStrength = 100;
+ else if (signalStrength < 0)
+ signalStrength = 0;
+ return signalStrength;
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ break;
+ }
+
+ case QNetworkInfo::EthernetMode:
+ if (networkStatus(QNetworkInfo::EthernetMode, interface) == QNetworkInfo::HomeNetwork)
+ return 100;
+ else
+ return -1;
+
+ case QNetworkInfo::GsmMode:
+ case QNetworkInfo::CdmaMode:
+ case QNetworkInfo::WcdmaMode:
+ case QNetworkInfo::LteMode:
+ case QNetworkInfo::TdscdmaMode:
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->signalStrength(modem);
+ }
+ }
+#endif
+ break;
+
+ case QNetworkInfo::BluetoothMode: {
+ int signalStrength = -1;
+#if !defined(QT_NO_BLUEZ)
+ int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (ctl < 0)
+ break;
+ struct hci_dev_list_req *deviceList = (struct hci_dev_list_req *)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
+ deviceList->dev_num = HCI_MAX_DEV;
+ if (ioctl(ctl, HCIGETDEVLIST, deviceList) == 0) {
+ int count = deviceList->dev_num;
+ if (interface < count) {
+ signalStrength = 0; // Valid interface
+
+ struct hci_conn_list_req *connectionList = (struct hci_conn_list_req *)malloc(sizeof(struct hci_conn_info) + sizeof(struct hci_conn_list_req));
+ connectionList->dev_id = (deviceList->dev_req + interface)->dev_id;
+ connectionList->conn_num = 1;
+ if (ioctl(ctl, HCIGETCONNLIST, connectionList) == 0) {
+ if (connectionList->conn_num == 1) {
+ int fd = hci_open_dev((deviceList->dev_req + interface)->dev_id);
+ if (fd > 0) {
+ struct hci_conn_info_req *connectionInfo = (struct hci_conn_info_req *)malloc(sizeof(struct hci_conn_info_req) + sizeof(struct hci_conn_info));
+ bacpy(&connectionInfo->bdaddr, &connectionList->conn_info->bdaddr);
+ connectionInfo->type = ACL_LINK;
+ if (ioctl(fd, HCIGETCONNINFO, connectionInfo) == 0) {
+ uint8_t linkQuality;
+ if (hci_read_link_quality(fd, htobs(connectionInfo->conn_info->handle), &linkQuality, 0) == 0)
+ signalStrength = linkQuality * 100 / 255;
+ }
+ free(connectionInfo);
+ }
+ }
+ }
+ free (connectionList);
+ }
+ }
+ free(deviceList);
+ close(ctl);
+#endif // QT_NO_BLUEZ
+ return signalStrength;
+ }
+
+// case QNetworkInfo::WimaxMode:
+ default:
+ break;
+ };
+
+ return -1;
+}
+
+QNetworkInfo::NetworkMode QNetworkInfoPrivate::getCurrentNetworkMode()
+{
+ // TODO multiple-interface support
+ if (networkStatus(QNetworkInfo::EthernetMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::EthernetMode;
+ else if (networkStatus(QNetworkInfo::WlanMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::WlanMode;
+ else if (networkStatus(QNetworkInfo::BluetoothMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::BluetoothMode;
+ else if (networkStatus(QNetworkInfo::WimaxMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::WimaxMode;
+ else if (networkStatus(QNetworkInfo::LteMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::LteMode;
+ else if (networkStatus(QNetworkInfo::WcdmaMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::WcdmaMode;
+ else if (networkStatus(QNetworkInfo::CdmaMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::CdmaMode;
+ else if (networkStatus(QNetworkInfo::GsmMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::GsmMode;
+ else if (networkStatus(QNetworkInfo::TdscdmaMode, 0) == QNetworkInfo::HomeNetwork)
+ return QNetworkInfo::TdscdmaMode;
+ else if (networkStatus(QNetworkInfo::WimaxMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::WimaxMode;
+ else if (networkStatus(QNetworkInfo::LteMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::LteMode;
+ else if (networkStatus(QNetworkInfo::WcdmaMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::WcdmaMode;
+ else if (networkStatus(QNetworkInfo::CdmaMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::CdmaMode;
+ else if (networkStatus(QNetworkInfo::GsmMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::GsmMode;
+ else if (networkStatus(QNetworkInfo::TdscdmaMode, 0) == QNetworkInfo::Roaming)
+ return QNetworkInfo::TdscdmaMode;
+ else
+ return QNetworkInfo::UnknownMode;
+}
+
+QNetworkInfo::NetworkStatus QNetworkInfoPrivate::getNetworkStatus(QNetworkInfo::NetworkMode mode, int interface)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode: {
+ if (interface < networkInterfaceCount(QNetworkInfo::WlanMode)) {
+ QString fileName = (*WLAN_MASK()).at(0);
+ fileName.chop(1);
+ fileName.append(QString::number(interface));
+ QFile carrier(*NETWORK_SYSFS_PATH() + fileName + QStringLiteral("/carrier"));
+ if (carrier.open(QIODevice::ReadOnly)) {
+ char state;
+ if ((carrier.read(&state, 1) == 1) &&
+ (state == '1') &&
+ (networkSignalStrength(QNetworkInfo::WlanMode, interface) > -1)) {
+ return QNetworkInfo::HomeNetwork;
+ }
+ }
+ }
+ return QNetworkInfo::NoNetworkAvailable;
+ }
+
+ case QNetworkInfo::EthernetMode: {
+ if (interface < networkInterfaceCount(QNetworkInfo::EthernetMode)) {
+ for (int i = 0; i < (*ETHERNET_MASK()).length(); i++) {
+ QString fileName = (*ETHERNET_MASK()).at(i);
+ fileName.chop(1);
+ fileName.append(QString::number(interface));
+ QFile carrier(*NETWORK_SYSFS_PATH() + fileName + QStringLiteral("/carrier"));
+ if (carrier.open(QIODevice::ReadOnly)) {
+ char state;
+ if ((carrier.read(&state, 1) == 1) && (state == '1'))
+ return QNetworkInfo::HomeNetwork;
+ }
+ }
+ }
+ return QNetworkInfo::NoNetworkAvailable;
+ }
+
+ case QNetworkInfo::BluetoothMode: {
+ QNetworkInfo::NetworkStatus status = QNetworkInfo::UnknownStatus;
+
+#if !defined(QT_NO_BLUEZ)
+ int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (ctl < 0)
+ break;
+ struct hci_dev_list_req *deviceList = (struct hci_dev_list_req *)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
+ deviceList->dev_num = HCI_MAX_DEV;
+ if (ioctl(ctl, HCIGETDEVLIST, deviceList) == 0) {
+ int count = deviceList->dev_num;
+ if (interface < count) {
+ status = QNetworkInfo::NoNetworkAvailable; // Valid interface, so either not connected or connected
+ // TODO add support for searching and denied
+ struct hci_conn_list_req *connectionList = (struct hci_conn_list_req *)malloc(sizeof(struct hci_conn_info) + sizeof(struct hci_conn_list_req));
+ connectionList->dev_id = (deviceList->dev_req + interface)->dev_id;
+ connectionList->conn_num = 1;
+ if (ioctl(ctl, HCIGETCONNLIST, connectionList) == 0) {
+ if (connectionList->conn_num == 1)
+ status = QNetworkInfo::HomeNetwork;
+ }
+ free (connectionList);
+ }
+ }
+ free(deviceList);
+ close(ctl);
+#endif // QT_NO_BLUEZ
+
+ return status;
+ }
+
+ case QNetworkInfo::GsmMode:
+ case QNetworkInfo::CdmaMode:
+ case QNetworkInfo::WcdmaMode:
+ case QNetworkInfo::LteMode:
+ case QNetworkInfo::TdscdmaMode:
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->networkStatus(modem);
+ }
+ }
+#endif
+ break;
+
+// case QNetworkInfo::WimaxMode:
+ default:
+ break;
+ };
+
+ return QNetworkInfo::UnknownStatus;
+}
+
+QString QNetworkInfoPrivate::getNetworkName(QNetworkInfo::NetworkMode mode, int interface)
+{
+ switch (mode) {
+ case QNetworkInfo::WlanMode: {
+ if (interface < networkInterfaceCount(QNetworkInfo::WlanMode)) {
+ int sock = socket(PF_INET, SOCK_DGRAM, 0);
+ if (sock > 0) {
+ char buffer[IW_ESSID_MAX_SIZE + 1];
+ iwreq iwInfo;
+
+ iwInfo.u.essid.pointer = (caddr_t)&buffer;
+ iwInfo.u.essid.length = IW_ESSID_MAX_SIZE + 1;
+ iwInfo.u.essid.flags = 0;
+ QString fileName = (*WLAN_MASK()).at(0);
+ fileName.chop(1);
+ fileName.append(QString::number(interface));
+ strncpy(iwInfo.ifr_name, fileName.toLocal8Bit().constData(), IFNAMSIZ);
+ if (ioctl(sock, SIOCGIWESSID, &iwInfo) == 0) {
+ close(sock);
+ return QString::fromLatin1((const char *)iwInfo.u.essid.pointer);
+ }
+
+ close(sock);
+ }
+ }
+ break;
+ }
+
+ case QNetworkInfo::EthernetMode: {
+ // TODO multiple-interface support
+ char domainName[64];
+ if (getdomainname(domainName, 64) == 0) {
+ if (strcmp(domainName, "(none)") != 0)
+ return QString::fromLatin1(domainName);
+ }
+ break;
+ }
+
+ case QNetworkInfo::BluetoothMode: {
+#if !defined(QT_NO_BLUEZ)
+ int ctl = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
+ if (ctl < 0)
+ break;
+ struct hci_dev_list_req *deviceList = (struct hci_dev_list_req *)malloc(HCI_MAX_DEV * sizeof(struct hci_dev_req) + sizeof(uint16_t));
+ deviceList->dev_num = HCI_MAX_DEV;
+ QString networkName;
+ if (ioctl(ctl, HCIGETDEVLIST, deviceList) == 0) {
+ int count = deviceList->dev_num;
+ if (interface < count) {
+ int fd = hci_open_dev((deviceList->dev_req + interface)->dev_id);
+ if (fd > 0) {
+ char name[249];
+ if (hci_read_local_name(fd, sizeof(name), name, 0) == 0)
+ networkName = QString::fromLatin1(name);
+ }
+ }
+ }
+ free(deviceList);
+ close(ctl);
+ return networkName;
+#endif // QT_NO_BLUEZ
+ break;
+ }
+
+ case QNetworkInfo::GsmMode:
+ case QNetworkInfo::CdmaMode:
+ case QNetworkInfo::WcdmaMode:
+ case QNetworkInfo::LteMode:
+ case QNetworkInfo::TdscdmaMode:
+#if !defined(QT_NO_OFONO)
+ if (QOfonoWrapper::isOfonoAvailable()) {
+ if (!ofonoWrapper)
+ ofonoWrapper = new QOfonoWrapper(this);
+ QStringList modems = ofonoWrapper->allModems();
+ if (interface < modems.size()) {
+ QString modem = ofonoWrapper->allModems().at(interface);
+ if (!modem.isEmpty())
+ return ofonoWrapper->operatorName(modem);
+ }
+ }
+#endif
+ break;
+
+// case QNetworkInfo::WimaxMode:
+ default:
+ break;
+ };
+
+ return QString();
+}
+
+QT_END_NAMESPACE