TDE core libraries
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

4566 lines
158 KiB

/* This file is part of the TDE libraries
Copyright (C) 2012-2014 Timothy Pearson <kb9vqf@pearsoncomputing.net>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "tdehardwaredevices.h"
#include <tqfile.h>
#include <tqdir.h>
#include <tqtimer.h>
#include <tqsocketnotifier.h>
#include <tqstringlist.h>
#include <tdeconfig.h>
#include <kstandarddirs.h>
#include <tdeglobal.h>
#include <tdelocale.h>
#include <tdeapplication.h>
#include <dcopclient.h>
extern "C" {
#include <libudev.h>
}
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
// Network devices
#include <sys/types.h>
#include <ifaddrs.h>
#include <netdb.h>
// Backlight devices
#include <linux/fb.h>
// Input devices
#include <linux/input.h>
#include "kiconloader.h"
#include "tdegenericdevice.h"
#include "tdestoragedevice.h"
#include "tdecpudevice.h"
#include "tdebatterydevice.h"
#include "tdemainspowerdevice.h"
#include "tdenetworkdevice.h"
#include "tdebacklightdevice.h"
#include "tdemonitordevice.h"
#include "tdesensordevice.h"
#include "tderootsystemdevice.h"
#include "tdeeventdevice.h"
#include "tdeinputdevice.h"
#include "tdecryptographiccarddevice.h"
// Compile-time configuration
#include "config.h"
// Profiling stuff
//#define CPUPROFILING
//#define STATELESSPROFILING
#include <time.h>
timespec diff(timespec start, timespec end)
{
timespec temp;
if ((end.tv_nsec-start.tv_nsec)<0) {
temp.tv_sec = end.tv_sec-start.tv_sec-1;
temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
} else {
temp.tv_sec = end.tv_sec-start.tv_sec;
temp.tv_nsec = end.tv_nsec-start.tv_nsec;
}
return temp;
}
// BEGIN BLOCK
// Copied from include/linux/genhd.h
#define GENHD_FL_REMOVABLE 1
#define GENHD_FL_MEDIA_CHANGE_NOTIFY 4
#define GENHD_FL_CD 8
#define GENHD_FL_UP 16
#define GENHD_FL_SUPPRESS_PARTITION_INFO 32
#define GENHD_FL_EXT_DEVT 64
#define GENHD_FL_NATIVE_CAPACITY 128
#define GENHD_FL_BLOCK_EVENTS_ON_EXCL_WRITE 256
// END BLOCK
// NOTE TO DEVELOPERS
// This command will greatly help when attempting to find properties to distinguish one device from another
// udevadm info --query=all --path=/sys/....
// This routine is courtsey of an answer on "Stack Overflow"
// It takes an LSB-first int and makes it an MSB-first int (or vice versa)
unsigned int reverse_bits(register unsigned int x)
{
x = (((x & 0xaaaaaaaa) >> 1) | ((x & 0x55555555) << 1));
x = (((x & 0xcccccccc) >> 2) | ((x & 0x33333333) << 2));
x = (((x & 0xf0f0f0f0) >> 4) | ((x & 0x0f0f0f0f) << 4));
x = (((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8));
return((x >> 16) | (x << 16));
}
// Helper function implemented in tdestoragedevice.cpp
TQString decodeHexEncoding(TQString str);
#if defined(WITH_TDEHWLIB_DAEMONS) || defined(WITH_UDISKS) || defined(WITH_UDISKS2) || defined(WITH_NETWORK_MANAGER_BACKEND)
#include <tqdbusvariant.h>
#include <tqdbusdata.h>
// Convenience method for tdehwlib DBUS calls
// FIXME
// Should probably be part of dbus-1-tqt
TQT_DBusData convertDBUSDataToVariantData(TQT_DBusData object) {
TQT_DBusVariant variant;
variant.value = object;
variant.signature = variant.value.buildDBusSignature();
return TQT_DBusData::fromVariant(variant);
}
#endif // defined(WITH_UDISKS) || defined(WITH_UDISKS2) || defined(WITH_NETWORK_MANAGER_BACKEND)
TDEHardwareDevices::TDEHardwareDevices() {
// Initialize members
pci_id_map = 0;
usb_id_map = 0;
pnp_id_map = 0;
dpy_id_map = 0;
// Set up device list
m_deviceList.setAutoDelete( TRUE ); // the list owns the objects
// Initialize udev interface
m_udevStruct = udev_new();
if (!m_udevStruct) {
printf("Unable to create udev interface\n");
}
if (m_udevStruct) {
// Set up device add/remove monitoring
m_udevMonitorStruct = udev_monitor_new_from_netlink(m_udevStruct, "udev");
udev_monitor_filter_add_match_subsystem_devtype(m_udevMonitorStruct, NULL, NULL);
udev_monitor_enable_receiving(m_udevMonitorStruct);
int udevmonitorfd = udev_monitor_get_fd(m_udevMonitorStruct);
if (udevmonitorfd >= 0) {
m_devScanNotifier = new TQSocketNotifier(udevmonitorfd, TQSocketNotifier::Read, this);
connect( m_devScanNotifier, TQT_SIGNAL(activated(int)), this, TQT_SLOT(processHotPluggedHardware()) );
}
// Read in the current mount table
// Yes, a race condition exists between this and the mount monitor start below, but it shouldn't be a problem 99.99% of the time
m_mountTable.clear();
TQFile file( "/proc/mounts" );
if ( file.open( IO_ReadOnly ) ) {
TQTextStream stream( &file );
while ( !stream.atEnd() ) {
m_mountTable.append(stream.readLine());
}
file.close();
}
// Monitor for changed mounts
m_procMountsFd = open("/proc/mounts", O_RDONLY, 0);
if (m_procMountsFd >= 0) {
m_mountScanNotifier = new TQSocketNotifier(m_procMountsFd, TQSocketNotifier::Exception, this);
connect( m_mountScanNotifier, TQT_SIGNAL(activated(int)), this, TQT_SLOT(processModifiedMounts()) );
}
// Read in the current cpu information
// Yes, a race condition exists between this and the cpu monitor start below, but it shouldn't be a problem 99.99% of the time
m_cpuInfo.clear();
TQFile cpufile( "/proc/cpuinfo" );
if ( cpufile.open( IO_ReadOnly ) ) {
TQTextStream stream( &cpufile );
while ( !stream.atEnd() ) {
m_cpuInfo.append(stream.readLine());
}
cpufile.close();
}
// [FIXME 0.01]
// Apparently the Linux kernel just does not notify userspace applications of CPU frequency changes
// This is STUPID, as it means I have to poll the CPU information structures with a 0.5 second or so timer just to keep the information up to date
#if 0
// Monitor for changed cpu information
// Watched directories are set up during the initial CPU scan
m_cpuWatch = new KSimpleDirWatch(this);
connect( m_cpuWatch, TQT_SIGNAL(dirty(const TQString &)), this, TQT_SLOT(processModifiedCPUs()) );
#else
m_cpuWatchTimer = new TQTimer(this);
connect( m_cpuWatchTimer, SIGNAL(timeout()), this, SLOT(processModifiedCPUs()) );
#endif
// Some devices do not receive update signals from udev
// These devices must be polled, and a good polling interval is 1 second
m_deviceWatchTimer = new TQTimer(this);
connect( m_deviceWatchTimer, SIGNAL(timeout()), this, SLOT(processStatelessDevices()) );
// Special case for battery polling (longer delay, 5 seconds)
m_batteryWatchTimer = new TQTimer(this);
connect( m_batteryWatchTimer, SIGNAL(timeout()), this, SLOT(processBatteryDevices()) );
// Update internal device information
queryHardwareInformation();
}
}
TDEHardwareDevices::~TDEHardwareDevices() {
// Stop device scanning
m_deviceWatchTimer->stop();
m_batteryWatchTimer->stop();
// [FIXME 0.01]
#if 0
// Stop CPU scanning
m_cpuWatch->stopScan();
#else
m_cpuWatchTimer->stop();
#endif
// Stop mount scanning
close(m_procMountsFd);
// Tear down udev interface
if(m_udevMonitorStruct) {
udev_monitor_unref(m_udevMonitorStruct);
}
udev_unref(m_udevStruct);
// Delete members
if (pci_id_map) {
delete pci_id_map;
}
if (usb_id_map) {
delete usb_id_map;
}
if (pnp_id_map) {
delete pnp_id_map;
}
if (dpy_id_map) {
delete dpy_id_map;
}
}
void TDEHardwareDevices::setTriggerlessHardwareUpdatesEnabled(bool enable) {
if (enable) {
TQDir nodezerocpufreq("/sys/devices/system/cpu/cpu0/cpufreq");
if (nodezerocpufreq.exists()) {
m_cpuWatchTimer->start( 500, FALSE ); // 0.5 second repeating timer
}
m_batteryWatchTimer->stop(); // Battery devices are included in stateless devices
m_deviceWatchTimer->start( 1000, FALSE ); // 1 second repeating timer
}
else {
m_cpuWatchTimer->stop();
m_deviceWatchTimer->stop();
}
}
void TDEHardwareDevices::setBatteryUpdatesEnabled(bool enable) {
if (enable) {
TQDir nodezerocpufreq("/sys/devices/system/cpu/cpu0/cpufreq");
if (nodezerocpufreq.exists()) {
m_cpuWatchTimer->start( 500, FALSE ); // 0.5 second repeating timer
}
m_batteryWatchTimer->start( 5000, FALSE ); // 5 second repeating timer
}
else {
m_cpuWatchTimer->stop();
m_batteryWatchTimer->stop();
}
}
void TDEHardwareDevices::rescanDeviceInformation(TDEGenericDevice* hwdevice) {
rescanDeviceInformation(hwdevice, true);
}
void TDEHardwareDevices::rescanDeviceInformation(TDEGenericDevice* hwdevice, bool regenerateDeviceTree) {
struct udev_device *dev;
dev = udev_device_new_from_syspath(m_udevStruct, hwdevice->systemPath().ascii());
updateExistingDeviceInformation(hwdevice);
if (regenerateDeviceTree) {
updateParentDeviceInformation(hwdevice); // Update parent/child tables for this device
}
udev_device_unref(dev);
}
TDEGenericDevice* TDEHardwareDevices::findBySystemPath(TQString syspath) {
if (!syspath.endsWith("/")) {
syspath += "/";
}
TDEGenericDevice *hwdevice;
// We can't use m_deviceList directly as m_deviceList can only have one iterator active against it at any given time
TDEGenericHardwareList devList = listAllPhysicalDevices();
for ( hwdevice = devList.first(); hwdevice; hwdevice = devList.next() ) {
if (hwdevice->systemPath() == syspath) {
return hwdevice;
}
}
return 0;
}
TDECPUDevice* TDEHardwareDevices::findCPUBySystemPath(TQString syspath, bool inCache=true) {
TDECPUDevice* cdevice;
// Look for the device in the cache first
if(inCache && !m_cpuByPathCache.isEmpty()) {
cdevice = m_cpuByPathCache.find(syspath);
if(cdevice) {
return cdevice;
}
}
// If the CPU was not found in cache, we need to parse the entire device list to get it.
cdevice = dynamic_cast<TDECPUDevice*>(findBySystemPath(syspath));
if(cdevice) {
if(inCache) {
m_cpuByPathCache.insert(syspath, cdevice); // Add the device to the cache
}
return cdevice;
}
return 0;
}
TDEGenericDevice* TDEHardwareDevices::findByUniqueID(TQString uid) {
TDEGenericDevice *hwdevice;
// We can't use m_deviceList directly as m_deviceList can only have one iterator active against it at any given time
TDEGenericHardwareList devList = listAllPhysicalDevices();
for ( hwdevice = devList.first(); hwdevice; hwdevice = devList.next() ) {
if (hwdevice->uniqueID() == uid) {
return hwdevice;
}
}
return 0;
}
TDEGenericDevice* TDEHardwareDevices::findByDeviceNode(TQString devnode) {
TDEGenericDevice *hwdevice;
for ( hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next() ) {
if (hwdevice->deviceNode() == devnode) {
return hwdevice;
}
}
return 0;
}
TDEStorageDevice* TDEHardwareDevices::findDiskByUID(TQString uid) {
TDEGenericDevice *hwdevice;
for ( hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next() ) {
if (hwdevice->type() == TDEGenericDeviceType::Disk) {
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
if (sdevice->uniqueID() == uid) {
return sdevice;
}
}
}
return 0;
}
void TDEHardwareDevices::processHotPluggedHardware() {
udev_device* dev = udev_monitor_receive_device(m_udevMonitorStruct);
if (dev) {
TQString actionevent(udev_device_get_action(dev));
if (actionevent == "add") {
TDEGenericDevice* device = classifyUnknownDevice(dev);
// Make sure this device is not a duplicate
TDEGenericDevice *hwdevice;
for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) {
if (hwdevice->systemPath() == device->systemPath()) {
delete device;
device = 0;
break;
}
}
if (device) {
m_deviceList.append(device);
updateParentDeviceInformation(device); // Update parent/child tables for this device
emit hardwareAdded(device);
emit hardwareEvent(TDEHardwareEvent::HardwareAdded, device->uniqueID());
}
}
else if (actionevent == "remove") {
// Delete device from hardware listing
TQString systempath(udev_device_get_syspath(dev));
systempath += "/";
TDEGenericDevice *hwdevice;
for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) {
if (hwdevice->systemPath() == systempath) {
// Temporarily disable auto-deletion to ensure object validity when calling the Removed events below
m_deviceList.setAutoDelete(false);
// If the device is a storage device and has a slave, update it as well
if (hwdevice->type() == TDEGenericDeviceType::Disk) {
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
TQStringList slavedevices = sdevice->slaveDevices();
m_deviceList.remove(hwdevice);
for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) {
TDEGenericDevice* slavedevice = findBySystemPath(*slaveit);
if (slavedevice) {
rescanDeviceInformation(slavedevice);
emit hardwareUpdated(slavedevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, slavedevice->uniqueID());
}
}
}
else {
m_deviceList.remove(hwdevice);
}
emit hardwareRemoved(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareRemoved, hwdevice->uniqueID());
// Reenable auto-deletion and delete the removed device object
m_deviceList.setAutoDelete(true);
delete hwdevice;
break;
}
}
}
else if (actionevent == "change") {
// Update device and emit change event
TQString systempath(udev_device_get_syspath(dev));
systempath += "/";
TDEGenericDevice *hwdevice;
for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) {
if (hwdevice->systemPath() == systempath) {
if (!hwdevice->blacklistedForUpdate()) {
classifyUnknownDevice(dev, hwdevice, false);
updateParentDeviceInformation(hwdevice); // Update parent/child tables for this device
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
}
}
else if ((hwdevice->type() == TDEGenericDeviceType::Monitor)
&& (hwdevice->systemPath().contains(systempath))) {
if (!hwdevice->blacklistedForUpdate()) {
struct udev_device *slavedev;
slavedev = udev_device_new_from_syspath(m_udevStruct, hwdevice->systemPath().ascii());
classifyUnknownDevice(slavedev, hwdevice, false);
udev_device_unref(slavedev);
updateParentDeviceInformation(hwdevice); // Update parent/child tables for this device
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
}
}
}
}
udev_device_unref(dev);
}
}
void TDEHardwareDevices::processModifiedCPUs() {
// Detect what changed between the old cpu information and the new information,
// and emit appropriate events
#ifdef CPUPROFILING
timespec time1, time2, time3;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
time3 = time1;
printf("TDEHardwareDevices::processModifiedCPUs() : begin at '%u'\n", time1.tv_nsec);
#endif
// Read new CPU information table
m_cpuInfo.clear();
TQFile cpufile( "/proc/cpuinfo" );
if ( cpufile.open( IO_ReadOnly ) ) {
TQTextStream stream( &cpufile );
// Using read() instead of readLine() inside a loop is 4 times faster !
m_cpuInfo = TQStringList::split('\n', stream.read(), true);
cpufile.close();
}
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint1 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
// Ensure "processor" is the first entry in each block and determine which cpuinfo type is in use
bool cpuinfo_format_x86 = true;
bool cpuinfo_format_arm = false;
TQString curline1;
TQString curline2;
int blockNumber = 0;
TQStringList::Iterator blockBegin = m_cpuInfo.begin();
for (TQStringList::Iterator cpuit1 = m_cpuInfo.begin(); cpuit1 != m_cpuInfo.end(); ++cpuit1) {
curline1 = *cpuit1;
if (!(*blockBegin).startsWith("processor")) {
bool found = false;
TQStringList::Iterator cpuit2;
for (cpuit2 = blockBegin; cpuit2 != m_cpuInfo.end(); ++cpuit2) {
curline2 = *cpuit2;
if (curline2.startsWith("processor")) {
found = true;
break;
}
else if (curline2 == NULL || curline2 == "") {
break;
}
}
if (found) {
m_cpuInfo.insert(blockBegin, (*cpuit2));
}
else if(blockNumber == 0) {
m_cpuInfo.insert(blockBegin, "processor : 0");
}
}
if (curline1 == NULL || curline1 == "") {
blockNumber++;
blockBegin = cpuit1;
blockBegin++;
}
else if (curline1.startsWith("Processor")) {
cpuinfo_format_x86 = false;
cpuinfo_format_arm = true;
}
}
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint2 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
// Parse CPU information table
TDECPUDevice *cdevice;
cdevice = 0;
bool modified = false;
bool have_frequency = false;
TQString curline;
int processorNumber = 0;
int processorCount = 0;
if (cpuinfo_format_x86) {
// ===================================================================================================================================
// x86/x86_64
// ===================================================================================================================================
TQStringList::Iterator cpuit;
for (cpuit = m_cpuInfo.begin(); cpuit != m_cpuInfo.end(); ++cpuit) {
curline = *cpuit;
if (curline.startsWith("processor")) {
curline.remove(0, curline.find(":")+2);
processorNumber = curline.toInt();
if (!cdevice) {
cdevice = dynamic_cast<TDECPUDevice*>(findCPUBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber)));
}
if (cdevice) {
if (cdevice->coreNumber() != processorNumber) {
modified = true;
cdevice->internalSetCoreNumber(processorNumber);
}
}
}
else if (cdevice && curline.startsWith("model name")) {
curline.remove(0, curline.find(":")+2);
if (cdevice->name() != curline) {
modified = true;
cdevice->internalSetName(curline);
}
}
else if (cdevice && curline.startsWith("cpu MHz")) {
curline.remove(0, curline.find(":")+2);
if (cdevice->frequency() != curline.toDouble()) {
modified = true;
cdevice->internalSetFrequency(curline.toDouble());
}
have_frequency = true;
}
else if (cdevice && curline.startsWith("vendor_id")) {
curline.remove(0, curline.find(":")+2);
if (cdevice->vendorName() != curline) {
modified = true;
cdevice->internalSetVendorName(curline);
}
if (cdevice->vendorEncoded() != curline) {
modified = true;
cdevice->internalSetVendorEncoded(curline);
}
}
else if (curline == NULL || curline == "") {
cdevice = 0;
}
}
}
else if (cpuinfo_format_arm) {
// ===================================================================================================================================
// ARM
// ===================================================================================================================================
TQStringList::Iterator cpuit;
TQString modelName;
TQString vendorName;
TQString serialNumber;
for (cpuit = m_cpuInfo.begin(); cpuit != m_cpuInfo.end(); ++cpuit) {
curline = *cpuit;
if (curline.startsWith("Processor")) {
curline.remove(0, curline.find(":")+2);
modelName = curline;
}
else if (curline.startsWith("Hardware")) {
curline.remove(0, curline.find(":")+2);
vendorName = curline;
}
else if (curline.startsWith("Serial")) {
curline.remove(0, curline.find(":")+2);
serialNumber = curline;
}
}
for (TQStringList::Iterator cpuit = m_cpuInfo.begin(); cpuit != m_cpuInfo.end(); ++cpuit) {
curline = *cpuit;
if (curline.startsWith("processor")) {
curline.remove(0, curline.find(":")+2);
processorNumber = curline.toInt();
if (!cdevice) {
cdevice = dynamic_cast<TDECPUDevice*>(findCPUBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber)));
if (cdevice) {
// Set up CPU information structures
if (cdevice->coreNumber() != processorNumber) modified = true;
cdevice->internalSetCoreNumber(processorNumber);
if (cdevice->name() != modelName) modified = true;
cdevice->internalSetName(modelName);
if (cdevice->vendorName() != vendorName) modified = true;
cdevice->internalSetVendorName(vendorName);
if (cdevice->vendorEncoded() != vendorName) modified = true;
cdevice->internalSetVendorEncoded(vendorName);
if (cdevice->serialNumber() != serialNumber) modified = true;
cdevice->internalSetSerialNumber(serialNumber);
}
}
}
if (curline == NULL || curline == "") {
cdevice = 0;
}
}
}
processorCount = processorNumber+1;
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint3 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
TDECPUDevice* firstCPU = NULL;
// Read in other information from cpufreq, if available
for (processorNumber=0; processorNumber<processorCount; processorNumber++) {
cdevice = dynamic_cast<TDECPUDevice*>(findCPUBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber)));
TQDir cpufreq_dir(TQString("/sys/devices/system/cpu/cpu%1/cpufreq").arg(processorNumber));
TQString scalinggovernor;
TQString scalingdriver;
double minfrequency = -1;
double maxfrequency = -1;
double trlatency = -1;
TQStringList affectedcpulist;
TQStringList frequencylist;
TQStringList governorlist;
if (cpufreq_dir.exists()) {
TQString nodename;
if ((processorNumber == 0) || (!firstCPU)) {
// Remember the first CPU options so that we can reuse it later.
firstCPU = cdevice;
nodename = cpufreq_dir.path();
nodename.append("/scaling_governor");
TQFile scalinggovernorfile(nodename);
if (scalinggovernorfile.open(IO_ReadOnly)) {
TQTextStream stream( &scalinggovernorfile );
scalinggovernor = stream.readLine();
scalinggovernorfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/scaling_driver");
TQFile scalingdriverfile(nodename);
if (scalingdriverfile.open(IO_ReadOnly)) {
TQTextStream stream( &scalingdriverfile );
scalingdriver = stream.readLine();
scalingdriverfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/cpuinfo_min_freq");
TQFile minfrequencyfile(nodename);
if (minfrequencyfile.open(IO_ReadOnly)) {
TQTextStream stream( &minfrequencyfile );
minfrequency = stream.readLine().toDouble()/1000.0;
minfrequencyfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/cpuinfo_max_freq");
TQFile maxfrequencyfile(nodename);
if (maxfrequencyfile.open(IO_ReadOnly)) {
TQTextStream stream( &maxfrequencyfile );
maxfrequency = stream.readLine().toDouble()/1000.0;
maxfrequencyfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/cpuinfo_transition_latency");
TQFile trlatencyfile(nodename);
if (trlatencyfile.open(IO_ReadOnly)) {
TQTextStream stream( &trlatencyfile );
trlatency = stream.readLine().toDouble()/1000.0;
trlatencyfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/scaling_available_frequencies");
TQFile availfreqsfile(nodename);
if (availfreqsfile.open(IO_ReadOnly)) {
TQTextStream stream( &availfreqsfile );
frequencylist = TQStringList::split(" ", stream.readLine());
availfreqsfile.close();
}
nodename = cpufreq_dir.path();
nodename.append("/scaling_available_governors");
TQFile availgvrnsfile(nodename);
if (availgvrnsfile.open(IO_ReadOnly)) {
TQTextStream stream( &availgvrnsfile );
governorlist = TQStringList::split(" ", stream.readLine());
availgvrnsfile.close();
}
}
// Other CPU should have the same values as the first one. Simply copy them.
else {
scalinggovernor = firstCPU->governor();
scalingdriver = firstCPU->scalingDriver();
minfrequency = firstCPU->minFrequency();
maxfrequency = firstCPU->maxFrequency();
trlatency = firstCPU->transitionLatency();
frequencylist = firstCPU->availableFrequencies();
governorlist = firstCPU->availableGovernors();
}
// The following data are different on each CPU
nodename = cpufreq_dir.path();
nodename.append("/affected_cpus");
TQFile tiedcpusfile(nodename);
if (tiedcpusfile.open(IO_ReadOnly)) {
TQTextStream stream( &tiedcpusfile );
affectedcpulist = TQStringList::split(" ", stream.readLine());
tiedcpusfile.close();
}
// We may already have the CPU Mhz information in '/proc/cpuinfo'
if (!have_frequency) {
nodename = cpufreq_dir.path();
nodename.append("/cpuinfo_cur_freq");
TQFile cpufreqfile(nodename);
if (cpufreqfile.open(IO_ReadOnly)) {
TQTextStream stream( &cpufreqfile );
if (cdevice) {
cdevice->internalSetFrequency(stream.readLine().toDouble()/1000.0);
}
cpufreqfile.close();
have_frequency = true;
}
}
bool minfrequencyFound = false;
bool maxfrequencyFound = false;
TQStringList::Iterator freqit;
for ( freqit = frequencylist.begin(); freqit != frequencylist.end(); ++freqit ) {
double thisfrequency = (*freqit).toDouble()/1000.0;
if (thisfrequency == minfrequency) {
minfrequencyFound = true;
}
if (thisfrequency == maxfrequency) {
maxfrequencyFound = true;
}
}
if (!minfrequencyFound) {
int minFrequencyInt = (minfrequency*1000.0);
frequencylist.prepend(TQString("%1").arg(minFrequencyInt));
}
if (!maxfrequencyFound) {
int maxfrequencyInt = (maxfrequency*1000.0);
frequencylist.append(TQString("%1").arg(maxfrequencyInt));
}
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint3.%u at %u [%u]\n", processorNumber, time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
}
else {
if (have_frequency) {
if (cdevice) {
minfrequency = cdevice->frequency();
maxfrequency = cdevice->frequency();
}
}
}
// Update CPU information structure
if (cdevice) {
if (cdevice->governor() != scalinggovernor) {
modified = true;
cdevice->internalSetGovernor(scalinggovernor);
}
if (cdevice->scalingDriver() != scalingdriver) {
modified = true;
cdevice->internalSetScalingDriver(scalingdriver);
}
if (cdevice->minFrequency() != minfrequency) {
modified = true;
cdevice->internalSetMinFrequency(minfrequency);
}
if (cdevice->maxFrequency() != maxfrequency) {
modified = true;
cdevice->internalSetMaxFrequency(maxfrequency);
}
if (cdevice->transitionLatency() != trlatency) {
modified = true;
cdevice->internalSetTransitionLatency(trlatency);
}
if (cdevice->dependentProcessors().join(" ") != affectedcpulist.join(" ")) {
modified = true;
cdevice->internalSetDependentProcessors(affectedcpulist);
}
if (cdevice->availableFrequencies().join(" ") != frequencylist.join(" ")) {
modified = true;
cdevice->internalSetAvailableFrequencies(frequencylist);
}
if (cdevice->availableGovernors().join(" ") != governorlist.join(" ")) {
modified = true;
cdevice->internalSetAvailableGovernors(governorlist);
}
}
}
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : checkpoint4 at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
if (modified) {
for (processorNumber=0; processorNumber<processorCount; processorNumber++) {
TDEGenericDevice* hwdevice = findCPUBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber));
if (hwdevice) {
// Signal new information available
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
}
}
}
#ifdef CPUPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processModifiedCPUs() : end at %u [%u]\n", time2.tv_nsec, diff(time1,time2).tv_nsec);
printf("TDEHardwareDevices::processModifiedCPUs() : total time: %u\n", diff(time3,time2).tv_nsec);
#endif
}
void TDEHardwareDevices::processStatelessDevices() {
// Some devices do not emit changed signals
// So far, network cards and sensors need to be polled
TDEGenericDevice *hwdevice;
#ifdef STATELESSPROFILING
timespec time1, time2, time3;
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time1);
printf("TDEHardwareDevices::processStatelessDevices() : begin at '%u'\n", time1.tv_nsec);
time3 = time1;
#endif
// We can't use m_deviceList directly as m_deviceList can only have one iterator active against it at any given time
TDEGenericHardwareList devList = listAllPhysicalDevices();
for ( hwdevice = devList.first(); hwdevice; hwdevice = devList.next() ) {
if ((hwdevice->type() == TDEGenericDeviceType::RootSystem) || (hwdevice->type() == TDEGenericDeviceType::Network) || (hwdevice->type() == TDEGenericDeviceType::OtherSensor) || (hwdevice->type() == TDEGenericDeviceType::Event) || (hwdevice->type() == TDEGenericDeviceType::Battery) || (hwdevice->type() == TDEGenericDeviceType::PowerSupply)) {
rescanDeviceInformation(hwdevice, false);
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
#ifdef STATELESSPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processStatelessDevices() : '%s' finished at %u [%u]\n", (hwdevice->name()).ascii(), time2.tv_nsec, diff(time1,time2).tv_nsec);
time1 = time2;
#endif
}
}
#ifdef STATELESSPROFILING
clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &time2);
printf("TDEHardwareDevices::processStatelessDevices() : end at '%u'\n", time2.tv_nsec);
printf("TDEHardwareDevices::processStatelessDevices() : took '%u'\n", diff(time3,time2).tv_nsec);
#endif
}
void TDEHardwareDevices::processBatteryDevices() {
TDEGenericDevice *hwdevice;
// We can't use m_deviceList directly as m_deviceList can only have one iterator active against it at any given time
TDEGenericHardwareList devList = listAllPhysicalDevices();
for ( hwdevice = devList.first(); hwdevice; hwdevice = devList.next() ) {
if (hwdevice->type() == TDEGenericDeviceType::Battery) {
rescanDeviceInformation(hwdevice, false);
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
}
}
}
void TDEHardwareDevices::processEventDeviceKeyPressed(unsigned int keycode, TDEEventDevice* edevice) {
emit eventDeviceKeyPressed(keycode, edevice);
}
void TDEHardwareDevices::processModifiedMounts() {
// Detect what changed between the old mount table and the new one,
// and emit appropriate events
TQStringList deletedEntries = m_mountTable;
// Read in the new mount table
m_mountTable.clear();
TQFile file( "/proc/mounts" );
if ( file.open( IO_ReadOnly ) ) {
TQTextStream stream( &file );
while ( !stream.atEnd() ) {
m_mountTable.append(stream.readLine());
}
file.close();
}
TQStringList addedEntries = m_mountTable;
// Remove all entries that are identical in both tables
processModifiedMounts_removeagain:
for ( TQStringList::Iterator delit = deletedEntries.begin(); delit != deletedEntries.end(); ++delit ) {
for ( TQStringList::Iterator addit = addedEntries.begin(); addit != addedEntries.end(); ++addit ) {
if ((*delit) == (*addit)) {
deletedEntries.remove(delit);
addedEntries.remove(addit);
// Reset iterators to prevent bugs/crashes
// FIXME
// Is there any way to completely reset both loops without using goto?
goto processModifiedMounts_removeagain;
}
}
}
TQStringList::Iterator it;
for ( it = addedEntries.begin(); it != addedEntries.end(); ++it ) {
TQStringList mountInfo = TQStringList::split(" ", (*it), true);
// Try to find a device that matches the altered node
TDEGenericDevice* hwdevice = findByDeviceNode(*mountInfo.at(0));
if (hwdevice) {
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
// If the device is a storage device and has a slave, update it as well
if (hwdevice->type() == TDEGenericDeviceType::Disk) {
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
TQStringList slavedevices = sdevice->slaveDevices();
for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) {
TDEGenericDevice* slavedevice = findBySystemPath(*slaveit);
if (slavedevice) {
emit hardwareUpdated(slavedevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, slavedevice->uniqueID());
}
}
}
}
}
for ( it = deletedEntries.begin(); it != deletedEntries.end(); ++it ) {
TQStringList mountInfo = TQStringList::split(" ", (*it), true);
// Try to find a device that matches the altered node
TDEGenericDevice* hwdevice = findByDeviceNode(*mountInfo.at(0));
if (hwdevice) {
emit hardwareUpdated(hwdevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, hwdevice->uniqueID());
// If the device is a storage device and has a slave, update it as well
if (hwdevice->type() == TDEGenericDeviceType::Disk) {
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
TQStringList slavedevices = sdevice->slaveDevices();
for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) {
TDEGenericDevice* slavedevice = findBySystemPath(*slaveit);
if (slavedevice) {
emit hardwareUpdated(slavedevice);
emit hardwareEvent(TDEHardwareEvent::HardwareUpdated, slavedevice->uniqueID());
}
}
}
}
}
emit mountTableModified();
emit hardwareEvent(TDEHardwareEvent::MountTableModified, TQString());
}
TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, const TQString devicenode, const TQString devicebus, const TQString disktypestring, const TQString systempath, const TQString devicevendor, const TQString devicemodel, const TQString filesystemtype, const TQString devicedriver) {
// Classify a disk device type to the best of our ability
TDEDiskDeviceType::TDEDiskDeviceType disktype = TDEDiskDeviceType::Null;
if (devicebus.upper() == "USB") {
disktype = disktype | TDEDiskDeviceType::USB;
}
if (disktypestring.upper() == "DISK") {
disktype = disktype | TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "FLOPPY")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLOPPY")) == "1")) {
disktype = disktype | TDEDiskDeviceType::Floppy;
disktype = disktype & ~TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "ZIP")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLOPPY_ZIP")) == "1")
|| ((devicevendor.upper() == "IOMEGA") && (devicemodel.upper().contains("ZIP")))) {
disktype = disktype | TDEDiskDeviceType::Zip;
disktype = disktype & ~TDEDiskDeviceType::HDD;
}
if ((devicevendor.upper() == "APPLE") && (devicemodel.upper().contains("IPOD"))) {
disktype = disktype | TDEDiskDeviceType::MediaDevice;
}
if ((devicevendor.upper() == "SANDISK") && (devicemodel.upper().contains("SANSA"))) {
disktype = disktype | TDEDiskDeviceType::MediaDevice;
}
if (disktypestring.upper() == "TAPE") {
disktype = disktype | TDEDiskDeviceType::Tape;
}
if ((disktypestring.upper() == "COMPACT_FLASH")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_CF")) == "1")
|| (TQString(udev_device_get_property_value(dev, "ID_ATA_CFA")) == "1")) {
disktype = disktype | TDEDiskDeviceType::CompactFlash;
disktype = disktype | TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "MEMORY_STICK")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_MS")) == "1")) {
disktype = disktype | TDEDiskDeviceType::MemoryStick;
disktype = disktype | TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "SMART_MEDIA")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_SM")) == "1")) {
disktype = disktype | TDEDiskDeviceType::SmartMedia;
disktype = disktype | TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "SD_MMC")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_SD")) == "1")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_SDHC")) == "1")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH_MMC")) == "1")) {
disktype = disktype | TDEDiskDeviceType::SDMMC;
disktype = disktype | TDEDiskDeviceType::HDD;
}
if ((disktypestring.upper() == "FLASHKEY")
|| (TQString(udev_device_get_property_value(dev, "ID_DRIVE_FLASH")) == "1")) {
disktype = disktype | TDEDiskDeviceType::Flash;
disktype = disktype | TDEDiskDeviceType::HDD;
}
if (disktypestring.upper() == "OPTICAL") {
disktype = disktype | TDEDiskDeviceType::Optical;
}
if (disktypestring.upper() == "JAZ") {
disktype = disktype | TDEDiskDeviceType::Jaz;
}
if (disktypestring.upper() == "CD") {
disktype = disktype | TDEDiskDeviceType::Optical;
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_CD_R")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDR;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_CD_RW")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDRW;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
disktype = disktype & ~TDEDiskDeviceType::CDR;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_MRW")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDMRRW;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
disktype = disktype & ~TDEDiskDeviceType::CDR;
disktype = disktype & ~TDEDiskDeviceType::CDRW;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_MRW_W")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDMRRWW;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
disktype = disktype & ~TDEDiskDeviceType::CDR;
disktype = disktype & ~TDEDiskDeviceType::CDRW;
disktype = disktype & ~TDEDiskDeviceType::CDMRRW;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_MO")) == "1") {
disktype = disktype | TDEDiskDeviceType::CDMO;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
disktype = disktype & ~TDEDiskDeviceType::CDR;
disktype = disktype & ~TDEDiskDeviceType::CDRW;
disktype = disktype & ~TDEDiskDeviceType::CDMRRW;
disktype = disktype & ~TDEDiskDeviceType::CDMRRWW;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_RAM")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDRAM;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_R")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_R_DL")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_PLUS_R")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDPLUSR;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_PLUS_R_DL")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDPLUSRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSR;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_RW")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDRW;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSR;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSRDL;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_RW_DL")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDRWDL;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSR;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDRW;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_PLUS_RW")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDPLUSRW;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSR;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDRW;
disktype = disktype & ~TDEDiskDeviceType::DVDRWDL;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_DVD_PLUS_RW_DL")) == "1") {
disktype = disktype | TDEDiskDeviceType::DVDPLUSRWDL;
disktype = disktype & ~TDEDiskDeviceType::DVDROM;
disktype = disktype & ~TDEDiskDeviceType::DVDR;
disktype = disktype & ~TDEDiskDeviceType::DVDRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSR;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSRDL;
disktype = disktype & ~TDEDiskDeviceType::DVDRW;
disktype = disktype & ~TDEDiskDeviceType::DVDRWDL;
disktype = disktype & ~TDEDiskDeviceType::DVDPLUSRW;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_BD")) == "1") {
disktype = disktype | TDEDiskDeviceType::BDROM;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
}
if ((TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_BD_R")) == "1")
|| (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_BD_R_DL")) == "1") // FIXME There is no official udev attribute for this type of disc (yet!)
) {
disktype = disktype | TDEDiskDeviceType::BDR;
disktype = disktype & ~TDEDiskDeviceType::BDROM;
}
if ((TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_BD_RE")) == "1")
|| (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_BD_RE_DL")) == "1") // FIXME There is no official udev attribute for this type of disc (yet!)
) {
disktype = disktype | TDEDiskDeviceType::BDRW;
disktype = disktype & ~TDEDiskDeviceType::BDROM;
disktype = disktype & ~TDEDiskDeviceType::BDR;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_HDDVD")) == "1") {
disktype = disktype | TDEDiskDeviceType::HDDVDROM;
disktype = disktype & ~TDEDiskDeviceType::CDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_HDDVD_R")) == "1") {
disktype = disktype | TDEDiskDeviceType::HDDVDR;
disktype = disktype & ~TDEDiskDeviceType::HDDVDROM;
}
if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_HDDVD_RW")) == "1") {
disktype = disktype | TDEDiskDeviceType::HDDVDRW;
disktype = disktype & ~TDEDiskDeviceType::HDDVDROM;
disktype = disktype & ~TDEDiskDeviceType::HDDVDR;
}
if (!TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_TRACK_COUNT_AUDIO")).isNull()) {
disktype = disktype | TDEDiskDeviceType::CDAudio;
}
if ((TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_VCD")) == "1") || (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA_SDVD")) == "1")) {
disktype = disktype | TDEDiskDeviceType::CDVideo;
}
if ((disktype & TDEDiskDeviceType::DVDROM)
|| (disktype & TDEDiskDeviceType::DVDRAM)
|| (disktype & TDEDiskDeviceType::DVDR)
|| (disktype & TDEDiskDeviceType::DVDRW)
|| (disktype & TDEDiskDeviceType::DVDRDL)
|| (disktype & TDEDiskDeviceType::DVDRWDL)
|| (disktype & TDEDiskDeviceType::DVDPLUSR)
|| (disktype & TDEDiskDeviceType::DVDPLUSRW)
|| (disktype & TDEDiskDeviceType::DVDPLUSRDL)
|| (disktype & TDEDiskDeviceType::DVDPLUSRWDL)
) {
// Every VideoDVD must have a VIDEO_TS.IFO file
// Read this info via tdeiso_info, since udev couldn't be bothered to check DVD type on its own
int retcode = system(TQString("tdeiso_info --exists=ISO9660/VIDEO_TS/VIDEO_TS.IFO %1").arg(devicenode).ascii());
if (retcode == 0) {
disktype = disktype | TDEDiskDeviceType::DVDVideo;
}
}
}
// Detect RAM and Loop devices, since udev can't seem to...
if (systempath.startsWith("/sys/devices/virtual/block/ram")) {
disktype = disktype | TDEDiskDeviceType::RAM;
}
if (systempath.startsWith("/sys/devices/virtual/block/loop")) {
disktype = disktype | TDEDiskDeviceType::Loop;
}
if (disktype == TDEDiskDeviceType::Null) {
// Fallback
// If we can't recognize the disk type then set it as a simple HDD volume
disktype = disktype | TDEDiskDeviceType::HDD;
}
if (filesystemtype.upper() == "CRYPTO_LUKS") {
disktype = disktype | TDEDiskDeviceType::LUKS;
}
else if (filesystemtype.upper() == "CRYPTO") {
disktype = disktype | TDEDiskDeviceType::OtherCrypted;
}
return disktype;
}
// TDEStandardDirs::kde_default
typedef TQMap<TQString, TQString> TDEConfigMap;
TQString readUdevAttribute(udev_device* dev, TQString attr) {
return TQString(udev_device_get_property_value(dev, attr.ascii()));
}
TDEGenericDeviceType::TDEGenericDeviceType readGenericDeviceTypeFromString(TQString query) {
TDEGenericDeviceType::TDEGenericDeviceType ret = TDEGenericDeviceType::Other;
// Keep this in sync with the TDEGenericDeviceType definition in the header
if (query == "Root") {
ret = TDEGenericDeviceType::Root;
}
else if (query == "RootSystem") {
ret = TDEGenericDeviceType::RootSystem;
}
else if (query == "CPU") {
ret = TDEGenericDeviceType::CPU;
}
else if (query == "GPU") {
ret = TDEGenericDeviceType::GPU;
}
else if (query == "RAM") {
ret = TDEGenericDeviceType::RAM;
}
else if (query == "Bus") {
ret = TDEGenericDeviceType::Bus;
}
else if (query == "I2C") {
ret = TDEGenericDeviceType::I2C;
}
else if (query == "MDIO") {
ret = TDEGenericDeviceType::MDIO;
}
else if (query == "Mainboard") {
ret = TDEGenericDeviceType::Mainboard;
}
else if (query == "Disk") {
ret = TDEGenericDeviceType::Disk;
}
else if (query == "SCSI") {
ret = TDEGenericDeviceType::SCSI;
}
else if (query == "StorageController") {
ret = TDEGenericDeviceType::StorageController;
}
else if (query == "Mouse") {
ret = TDEGenericDeviceType::Mouse;
}
else if (query == "Keyboard") {
ret = TDEGenericDeviceType::Keyboard;
}
else if (query == "HID") {
ret = TDEGenericDeviceType::HID;
}
else if (query == "Modem") {
ret = TDEGenericDeviceType::Modem;
}
else if (query == "Monitor") {
ret = TDEGenericDeviceType::Monitor;
}
else if (query == "Network") {
ret = TDEGenericDeviceType::Network;
}
else if (query == "NonvolatileMemory") {
ret = TDEGenericDeviceType::NonvolatileMemory;
}
else if (query == "Printer") {
ret = TDEGenericDeviceType::Printer;
}
else if (query == "Scanner") {
ret = TDEGenericDeviceType::Scanner;
}
else if (query == "Sound") {
ret = TDEGenericDeviceType::Sound;
}
else if (query == "VideoCapture") {
ret = TDEGenericDeviceType::VideoCapture;
}
else if (query == "IEEE1394") {
ret = TDEGenericDeviceType::IEEE1394;
}
else if (query == "PCMCIA") {
ret = TDEGenericDeviceType::PCMCIA;
}
else if (query == "Camera") {
ret = TDEGenericDeviceType::Camera;
}
else if (query == "Serial") {
ret = TDEGenericDeviceType::Serial;
}
else if (query == "Parallel") {
ret = TDEGenericDeviceType::Parallel;
}
else if (query == "TextIO") {
ret = TDEGenericDeviceType::TextIO;
}
else if (query == "Peripheral") {
ret = TDEGenericDeviceType::Peripheral;
}
else if (query == "Backlight") {
ret = TDEGenericDeviceType::Backlight;
}
else if (query == "Battery") {
ret = TDEGenericDeviceType::Battery;
}
else if (query == "Power") {
ret = TDEGenericDeviceType::PowerSupply;
}
else if (query == "Dock") {
ret = TDEGenericDeviceType::Dock;
}
else if (query == "ThermalSensor") {
ret = TDEGenericDeviceType::ThermalSensor;
}
else if (query == "ThermalControl") {
ret = TDEGenericDeviceType::ThermalControl;
}
else if (query == "Bluetooth") {
ret = TDEGenericDeviceType::BlueTooth;
}
else if (query == "Bridge") {
ret = TDEGenericDeviceType::Bridge;
}
else if (query == "Hub") {
ret = TDEGenericDeviceType::Hub;
}
else if (query == "Platform") {
ret = TDEGenericDeviceType::Platform;
}
else if (query == "Cryptography") {
ret = TDEGenericDeviceType::Cryptography;
}
else if (query == "CryptographicCard") {
ret = TDEGenericDeviceType::CryptographicCard;
}
else if (query == "BiometricSecurity") {
ret = TDEGenericDeviceType::BiometricSecurity;
}
else if (query == "TestAndMeasurement") {
ret = TDEGenericDeviceType::TestAndMeasurement;
}
else if (query == "Timekeeping") {
ret = TDEGenericDeviceType::Timekeeping;
}
else if (query == "Event") {
ret = TDEGenericDeviceType::Event;
}
else if (query == "Input") {
ret = TDEGenericDeviceType::Input;
}
else if (query == "PNP") {
ret = TDEGenericDeviceType::PNP;
}
else if (query == "OtherACPI") {
ret = TDEGenericDeviceType::OtherACPI;
}
else if (query == "OtherUSB") {
ret = TDEGenericDeviceType::OtherUSB;
}
else if (query == "OtherMultimedia") {
ret = TDEGenericDeviceType::OtherMultimedia;
}
else if (query == "OtherPeripheral") {
ret = TDEGenericDeviceType::OtherPeripheral;
}
else if (query == "OtherSensor") {
ret = TDEGenericDeviceType::OtherSensor;
}
else if (query == "OtherVirtual") {
ret = TDEGenericDeviceType::OtherVirtual;
}
else {
ret = TDEGenericDeviceType::Other;
}
return ret;
}
TDEDiskDeviceType::TDEDiskDeviceType readDiskDeviceSubtypeFromString(TQString query, TDEDiskDeviceType::TDEDiskDeviceType flagsIn=TDEDiskDeviceType::Null) {
TDEDiskDeviceType::TDEDiskDeviceType ret = flagsIn;
// Keep this in sync with the TDEDiskDeviceType definition in the header
if (query == "MediaDevice") {
ret = ret | TDEDiskDeviceType::MediaDevice;
}
if (query == "Floppy") {
ret = ret | TDEDiskDeviceType::Floppy;
}
if (query == "CDROM") {
ret = ret | TDEDiskDeviceType::CDROM;
}
if (query == "CDR") {
ret = ret | TDEDiskDeviceType::CDR;
}
if (query == "CDRW") {
ret = ret | TDEDiskDeviceType::CDRW;
}
if (query == "CDMO") {
ret = ret | TDEDiskDeviceType::CDMO;
}
if (query == "CDMRRW") {
ret = ret | TDEDiskDeviceType::CDMRRW;
}
if (query == "CDMRRWW") {
ret = ret | TDEDiskDeviceType::CDMRRWW;
}
if (query == "DVDROM") {
ret = ret | TDEDiskDeviceType::DVDROM;
}
if (query == "DVDRAM") {
ret = ret | TDEDiskDeviceType::DVDRAM;
}
if (query == "DVDR") {
ret = ret | TDEDiskDeviceType::DVDR;
}
if (query == "DVDRW") {
ret = ret | TDEDiskDeviceType::DVDRW;
}
if (query == "DVDRDL") {
ret = ret | TDEDiskDeviceType::DVDRDL;
}
if (query == "DVDRWDL") {
ret = ret | TDEDiskDeviceType::DVDRWDL;
}
if (query == "DVDPLUSR") {
ret = ret | TDEDiskDeviceType::DVDPLUSR;
}
if (query == "DVDPLUSRW") {
ret = ret | TDEDiskDeviceType::DVDPLUSRW;
}
if (query == "DVDPLUSRDL") {
ret = ret | TDEDiskDeviceType::DVDPLUSRDL;
}
if (query == "DVDPLUSRWDL") {
ret = ret | TDEDiskDeviceType::DVDPLUSRWDL;
}
if (query == "BDROM") {
ret = ret | TDEDiskDeviceType::BDROM;
}
if (query == "BDR") {
ret = ret | TDEDiskDeviceType::BDR;
}
if (query == "BDRW") {
ret = ret | TDEDiskDeviceType::BDRW;
}
if (query == "HDDVDROM") {
ret = ret | TDEDiskDeviceType::HDDVDROM;
}
if (query == "HDDVDR") {
ret = ret | TDEDiskDeviceType::HDDVDR;
}
if (query == "HDDVDRW") {
ret = ret | TDEDiskDeviceType::HDDVDRW;
}
if (query == "Zip") {
ret = ret | TDEDiskDeviceType::Zip;
}
if (query == "Jaz") {
ret = ret | TDEDiskDeviceType::Jaz;
}
if (query == "Camera") {
ret = ret | TDEDiskDeviceType::Camera;
}
if (query == "LUKS") {
ret = ret | TDEDiskDeviceType::LUKS;
}
if (query == "OtherCrypted") {
ret = ret | TDEDiskDeviceType::OtherCrypted;
}
if (query == "CDAudio") {
ret = ret | TDEDiskDeviceType::CDAudio;
}
if (query == "CDVideo") {
ret = ret | TDEDiskDeviceType::CDVideo;
}
if (query == "DVDVideo") {
ret = ret | TDEDiskDeviceType::DVDVideo;
}
if (query == "BDVideo") {
ret = ret | TDEDiskDeviceType::BDVideo;
}
if (query == "Flash") {
ret = ret | TDEDiskDeviceType::Flash;
}
if (query == "USB") {
ret = ret | TDEDiskDeviceType::USB;
}
if (query == "Tape") {
ret = ret | TDEDiskDeviceType::Tape;
}
if (query == "HDD") {
ret = ret | TDEDiskDeviceType::HDD;
}
if (query == "Optical") {
ret = ret | TDEDiskDeviceType::Optical;
}
if (query == "RAM") {
ret = ret | TDEDiskDeviceType::RAM;
}
if (query == "Loop") {
ret = ret | TDEDiskDeviceType::Loop;
}
if (query == "CompactFlash") {
ret = ret | TDEDiskDeviceType::CompactFlash;
}
if (query == "MemoryStick") {
ret = ret | TDEDiskDeviceType::MemoryStick;
}
if (query == "SmartMedia") {
ret = ret | TDEDiskDeviceType::SmartMedia;
}
if (query == "SDMMC") {
ret = ret | TDEDiskDeviceType::SDMMC;
}
if (query == "UnlockedCrypt") {
ret = ret | TDEDiskDeviceType::UnlockedCrypt;
}
return ret;
}
TDEGenericDevice* createDeviceObjectForType(TDEGenericDeviceType::TDEGenericDeviceType type) {
TDEGenericDevice* ret = 0;
if (type == TDEGenericDeviceType::Disk) {
ret = new TDEStorageDevice(type);
}
else {
ret = new TDEGenericDevice(type);
}
return ret;
}
TDEGenericDevice* TDEHardwareDevices::classifyUnknownDeviceByExternalRules(udev_device* dev, TDEGenericDevice* existingdevice, bool classifySubDevices) {
// This routine expects to see the hardware config files into <prefix>/share/apps/tdehwlib/deviceclasses/, suffixed with "hwclass"
TDEGenericDevice* device = existingdevice;
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Other);
// Handle subtype if needed/desired
// To speed things up we rely on the prior scan results stored in m_externalSubtype
if (classifySubDevices) {
if (!device->m_externalRulesFile.isNull()) {
if (device->type() == TDEGenericDeviceType::Disk) {
// Disk class
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device);
TQStringList subtype = device->m_externalSubtype;
TDEDiskDeviceType::TDEDiskDeviceType desiredSubdeviceType = TDEDiskDeviceType::Null;
if (subtype.count()>0) {
for ( TQStringList::Iterator paramit = subtype.begin(); paramit != subtype.end(); ++paramit ) {
desiredSubdeviceType = readDiskDeviceSubtypeFromString(*paramit, desiredSubdeviceType);
}
if (desiredSubdeviceType != sdevice->diskType()) {
printf("[tdehardwaredevices] Rules file %s used to set device subtype for device at path %s\n", device->m_externalRulesFile.ascii(), device->systemPath().ascii()); fflush(stdout);
sdevice->internalSetDiskType(desiredSubdeviceType);
}
}
}
}
}
else {
TQStringList hardware_info_directories(TDEGlobal::dirs()->resourceDirs("data"));
TQString hardware_info_directory_suffix("tdehwlib/deviceclasses/");
TQString hardware_info_directory;
// Scan the hardware_info_directory for configuration files
// For each one, open it with TDEConfig() and apply its rules to classify the device
// FIXME
// Should this also scan up to <n> subdirectories for the files? That feature might end up being too expensive...
device->m_externalRulesFile = TQString::null;
for ( TQStringList::Iterator it = hardware_info_directories.begin(); it != hardware_info_directories.end(); ++it ) {
hardware_info_directory = (*it);
hardware_info_directory += hardware_info_directory_suffix;
if (TDEGlobal::dirs()->exists(hardware_info_directory)) {
TQDir d(hardware_info_directory);
d.setFilter( TQDir::Files | TQDir::Hidden );
const TQFileInfoList *list = d.entryInfoList();
TQFileInfoListIterator it( *list );
TQFileInfo *fi;
while ((fi = it.current()) != 0) {
if (fi->extension(false) == "hwclass") {
bool match = true;
// Open the rules file
TDEConfig rulesFile(fi->absFilePath(), true, false);
rulesFile.setGroup("Conditions");
TDEConfigMap conditionmap = rulesFile.entryMap("Conditions");
TDEConfigMap::Iterator cndit;
for (cndit = conditionmap.begin(); cndit != conditionmap.end(); ++cndit) {
TQStringList conditionList = TQStringList::split(',', cndit.data(), false);
bool atleastonematch = false;
bool allmatch = true;
TQString matchtype = rulesFile.readEntry("MATCH_TYPE", "All");
if (conditionList.count() < 1) {
allmatch = false;
}
else {
for ( TQStringList::Iterator paramit = conditionList.begin(); paramit != conditionList.end(); ++paramit ) {
if ((*paramit) == "MatchType") {
continue;
}
if (cndit.key() == "VENDOR_ID") {
if (device->vendorID() == (*paramit)) {
atleastonematch = true;
}
else {
allmatch = false;
}
}
else if (cndit.key() == "MODEL_ID") {
if (device->modelID() == (*paramit)) {
atleastonematch = true;
}
else {
allmatch = false;
}
}
else if (cndit.key() == "DRIVER") {
if (device->deviceDriver() == (*paramit)) {
atleastonematch = true;
}
else {
allmatch = false;
}
}
else {
if (readUdevAttribute(dev, cndit.key()) == (*paramit)) {
atleastonematch = true;
}
else {
allmatch = false;
}
}
}
}
if (matchtype == "All") {
if (!allmatch) {
match = false;
}
}
else if (matchtype == "Any") {
if (!atleastonematch) {
match = false;
}
}
else {
match = false;
}
}
if (match) {
rulesFile.setGroup("DeviceType");
TQString gentype = rulesFile.readEntry("GENTYPE");
TDEGenericDeviceType::TDEGenericDeviceType desiredDeviceType = device->type();
if (!gentype.isNull()) {
desiredDeviceType = readGenericDeviceTypeFromString(gentype);
}
// Handle main type
if (desiredDeviceType != device->type()) {
printf("[tdehardwaredevices] Rules file %s used to set device type for device at path %s\n", fi->absFilePath().ascii(), device->systemPath().ascii()); fflush(stdout);
if (m_deviceList.contains(device)) {
m_deviceList.remove(device);
}
else {
delete device;
}
device = createDeviceObjectForType(desiredDeviceType);
}
// Parse subtype and store in m_externalSubtype for later
// This speeds things up considerably due to the expense of the file scanning/parsing/matching operation
device->m_externalSubtype = rulesFile.readListEntry("SUBTYPE", ',');
device->m_externalRulesFile = fi->absFilePath();
// Process blacklist entries
rulesFile.setGroup("DeviceSettings");
device->internalSetBlacklistedForUpdate(rulesFile.readBoolEntry("UPDATE_BLACKLISTED", device->blacklistedForUpdate()));
}
}
++it;
}
}
}
}
return device;
}
TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice, bool force_full_classification) {
// Classify device and create TDEHW device object
TQString devicename;
TQString devicetype;
TQString devicedriver;
TQString devicesubsystem;
TQString devicenode;
TQString systempath;
TQString devicevendorid;
TQString devicemodelid;
TQString devicevendoridenc;
TQString devicemodelidenc;
TQString devicesubvendorid;
TQString devicesubmodelid;
TQString devicetypestring;
TQString devicetypestring_alt;
TQString devicepciclass;
TDEGenericDevice* device = existingdevice;
bool temp_udev_device = !dev;
if (dev) {
devicename = (udev_device_get_sysname(dev));
devicetype = (udev_device_get_devtype(dev));
devicedriver = (udev_device_get_driver(dev));
devicesubsystem = (udev_device_get_subsystem(dev));
devicenode = (udev_device_get_devnode(dev));
systempath = (udev_device_get_syspath(dev));
systempath += "/";
devicevendorid = (udev_device_get_property_value(dev, "ID_VENDOR_ID"));
devicemodelid = (udev_device_get_property_value(dev, "ID_MODEL_ID"));
devicevendoridenc = (udev_device_get_property_value(dev, "ID_VENDOR_ENC"));
devicemodelidenc = (udev_device_get_property_value(dev, "ID_MODEL_ENC"));
devicesubvendorid = (udev_device_get_property_value(dev, "ID_SUBVENDOR_ID"));
devicesubmodelid = (udev_device_get_property_value(dev, "ID_SUBMODEL_ID"));
devicetypestring = (udev_device_get_property_value(dev, "ID_TYPE"));
devicetypestring_alt = (udev_device_get_property_value(dev, "DEVTYPE"));
devicepciclass = (udev_device_get_property_value(dev, "PCI_CLASS"));
}
else {
if (device) {
devicename = device->name();
devicetype = device->m_udevtype;
devicedriver = device->deviceDriver();
devicesubsystem = device->subsystem();
devicenode = device->deviceNode();
systempath = device->systemPath();
devicevendorid = device->vendorID();
devicemodelid = device->modelID();
devicevendoridenc = device->vendorEncoded();
devicemodelidenc = device->modelEncoded();
devicesubvendorid = device->subVendorID();
devicesubmodelid = device->subModelID();
devicetypestring = device->m_udevdevicetypestring;
devicetypestring_alt = device->udevdevicetypestring_alt;
devicepciclass = device->PCIClass();
}
TQString syspathudev = systempath;
syspathudev.truncate(syspathudev.length()-1); // Remove trailing slash
dev = udev_device_new_from_syspath(m_udevStruct, syspathudev.ascii());
}
// FIXME
// Only a small subset of devices are classified right now
// Figure out the remaining udev logic to classify the rest!
// Helpful file: http://www.enlightenment.org/svn/e/trunk/PROTO/enna-explorer/src/bin/udev.c
bool done = false;
TQString current_path = systempath;
TQString devicemodalias = TQString::null;
while (done == false) {
TQString malnodename = current_path;
malnodename.append("/modalias");
TQFile malfile(malnodename);
if (malfile.open(IO_ReadOnly)) {
TQTextStream stream( &malfile );
devicemodalias = stream.readLine();
malfile.close();
}
if (devicemodalias.startsWith("pci") || devicemodalias.startsWith("usb")) {
done = true;
}
else {
devicemodalias = TQString::null;
current_path.truncate(current_path.findRev("/"));
if (!current_path.startsWith("/sys/devices")) {
// Abort!
done = true;
}
}
}
// Many devices do not provide their vendor/model ID via udev
// Worse, sometimes udev provides an invalid model ID!
// Go after it manually if needed...
if (devicevendorid.isNull() || devicemodelid.isNull() || devicemodelid.contains("/")) {
if (devicemodalias != TQString::null) {
// For added fun the device string lengths differ between pci and usb
if (devicemodalias.startsWith("pci")) {
int vloc = devicemodalias.find("v");
int dloc = devicemodalias.find("d", vloc);
int svloc = devicemodalias.find("sv");
int sdloc = devicemodalias.find("sd", vloc);
devicevendorid = devicemodalias.mid(vloc+1, 8).lower();
devicemodelid = devicemodalias.mid(dloc+1, 8).lower();
if (svloc != -1) {
devicesubvendorid = devicemodalias.mid(svloc+1, 8).lower();
devicesubmodelid = devicemodalias.mid(sdloc+1, 8).lower();
}
devicevendorid.remove(0,4);
devicemodelid.remove(0,4);
devicesubvendorid.remove(0,4);
devicesubmodelid.remove(0,4);
}
if (devicemodalias.startsWith("usb")) {
int vloc = devicemodalias.find("v");
int dloc = devicemodalias.find("p", vloc);
int svloc = devicemodalias.find("sv");
int sdloc = devicemodalias.find("sp", vloc);
devicevendorid = devicemodalias.mid(vloc+1, 4).lower();
devicemodelid = devicemodalias.mid(dloc+1, 4).lower();
if (svloc != -1) {
devicesubvendorid = devicemodalias.mid(svloc+1, 4).lower();
devicesubmodelid = devicemodalias.mid(sdloc+1, 4).lower();
}
}
}
}
// Most of the time udev doesn't barf up a device driver either, so go after it manually...
if (devicedriver.isNull()) {
TQString driverSymlink = udev_device_get_syspath(dev);
TQString driverSymlinkDir = driverSymlink;
driverSymlink.append("/device/driver");
driverSymlinkDir.append("/device/");
TQFileInfo dirfi(driverSymlink);
if (dirfi.isSymLink()) {
char* collapsedPath = realpath((driverSymlinkDir + dirfi.readLink()).ascii(), NULL);
devicedriver = TQString(collapsedPath);
free(collapsedPath);
devicedriver.remove(0, devicedriver.findRev("/")+1);
}
}
// udev removes critical leading zeroes in the PCI device class, so go after it manually...
TQString classnodename = systempath;
classnodename.append("/class");
TQFile classfile( classnodename );
if ( classfile.open( IO_ReadOnly ) ) {
TQTextStream stream( &classfile );
devicepciclass = stream.readLine();
devicepciclass.replace("0x", "");
devicepciclass = devicepciclass.lower();
classfile.close();
}
// Classify generic device type and create appropriate object
// Pull out all event special devices and stuff them under Event
TQString syspath_tail = systempath.lower();
syspath_tail.truncate(syspath_tail.length()-1);
syspath_tail.remove(0, syspath_tail.findRev("/")+1);
if (syspath_tail.startsWith("event")) {
if (!device) device = new TDEEventDevice(TDEGenericDeviceType::Event);
}
// Pull out all input special devices and stuff them under Input
if (syspath_tail.startsWith("input")) {
if (!device) device = new TDEInputDevice(TDEGenericDeviceType::Input);
}
// Pull out remote-control devices and stuff them under Input
if (devicesubsystem == "rc") {
if (!device) device = new TDEInputDevice(TDEGenericDeviceType::Input);
}
// Check for keyboard
// Linux doesn't actually ID the keyboard device itself as such, it instead IDs the input device that is underneath the actual keyboard itseld
// Therefore we need to scan <syspath>/input/input* for the ID_INPUT_KEYBOARD attribute
bool is_keyboard = false;
TQString inputtopdirname = udev_device_get_syspath(dev);
inputtopdirname.append("/input/");
TQDir inputdir(inputtopdirname);
inputdir.setFilter(TQDir::All);
const TQFileInfoList *dirlist = inputdir.entryInfoList();
if (dirlist) {
TQFileInfoListIterator inputdirsit(*dirlist);
TQFileInfo *dirfi;
while ( (dirfi = inputdirsit.current()) != 0 ) {
if ((dirfi->fileName() != ".") && (dirfi->fileName() != "..")) {
struct udev_device *slavedev;
slavedev = udev_device_new_from_syspath(m_udevStruct, (inputtopdirname + dirfi->fileName()).ascii());
if (udev_device_get_property_value(slavedev, "ID_INPUT_KEYBOARD") != 0) {
is_keyboard = true;
}
udev_device_unref(slavedev);
}
++inputdirsit;
}
}
if (is_keyboard) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Keyboard);
}
// Classify specific known devices
if (((devicetype == "disk")
|| (devicetype == "partition")
|| (devicedriver == "floppy")
|| (devicesubsystem == "scsi_disk")
|| (devicesubsystem == "scsi_tape"))
&& ((devicenode != "")
)) {
if (!device) device = new TDEStorageDevice(TDEGenericDeviceType::Disk);
}
else if (devicetype == "host") {
if (devicesubsystem == "bluetooth") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::BlueTooth);
}
}
else if (devicetype.isNull()) {
if (devicesubsystem == "acpi") {
// If the ACPI device exposes a system path ending in /PNPxxxx:yy, the device type can be precisely determined
// See ftp://ftp.microsoft.com/developr/drg/plug-and-play/devids.txt for more information
TQString pnpgentype = systempath;
pnpgentype.remove(0, pnpgentype.findRev("/")+1);
pnpgentype.truncate(pnpgentype.find(":"));
if (pnpgentype.startsWith("PNP")) {
// If a device has been classified as belonging to the ACPI subsystem usually there is a "real" device related to it elsewhere in the system
// Furthermore, the "real" device elsewhere almost always has more functionality exposed via sysfs
// Therefore all ACPI subsystem devices should be stuffed in the OtherACPI category and largely ignored
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherACPI);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherACPI);
}
}
else if (devicesubsystem == "input") {
// Figure out if this device is a mouse, keyboard, or something else
// Check for mouse
// udev doesn't reliably help here, so guess from the device name
if (systempath.contains("/mouse")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Mouse);
}
if (!device) {
// Second mouse check
// Look for ID_INPUT_MOUSE property presence
if (udev_device_get_property_value(dev, "ID_INPUT_MOUSE") != 0) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Mouse);
}
}
if (!device) {
// Check for keyboard
// Look for ID_INPUT_KEYBOARD property presence
if (udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD") != 0) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Keyboard);
}
}
if (!device) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::HID);
}
}
else if (devicesubsystem == "tty") {
if (devicenode.contains("/ttyS")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Serial);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::TextIO);
}
}
else if (devicesubsystem == "usb-serial") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Serial);
}
else if ((devicesubsystem == "spi_master")
|| (devicesubsystem == "spidev")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Serial);
}
else if (devicesubsystem == "spi") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "watchdog") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "node") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "regulator") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "memory") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "clockevents") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "thermal") {
// FIXME
// Figure out a way to differentiate between ThermalControl (fans and coolers) and ThermalSensor types
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::ThermalControl);
}
else if (devicesubsystem == "hwmon") {
// FIXME
// This might pick up thermal sensors
if (!device) device = new TDESensorDevice(TDEGenericDeviceType::OtherSensor);
}
else if (devicesubsystem == "vio") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
else if (devicesubsystem == "virtio") {
if (devicedriver == "virtio_blk") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::SCSI);
}
if (devicedriver == "virtio_net") {
if (!device) device = new TDENetworkDevice(TDEGenericDeviceType::Network);
}
if (devicedriver == "virtio_balloon") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::RAM);
}
}
}
// Try to at least generally classify unclassified devices
if (device == 0) {
if (devicesubsystem == "backlight") {
if (!device) device = new TDEBacklightDevice(TDEGenericDeviceType::Backlight);
}
if (systempath.lower().startsWith("/sys/module/")
|| (systempath.lower().startsWith("/sys/kernel/"))) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform); // FIXME Should go into a new kernel module category when the tdelibs ABI can be broken again
}
if ((devicetypestring == "audio")
|| (devicesubsystem == "sound")
|| (devicesubsystem == "hdaudio")
|| (devicesubsystem == "ac97")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Sound);
}
if (devicesubsystem == "container") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherACPI);
}
if ((devicesubsystem == "video4linux")
|| (devicesubsystem == "dvb")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::VideoCapture);
}
if ((devicetypestring_alt == "scsi_target")
|| (devicesubsystem == "scsi_host")
|| (devicesubsystem == "scsi_disk")
|| (devicesubsystem == "scsi_device")
|| (devicesubsystem == "scsi_generic")
|| (devicesubsystem == "scsi")
|| (devicetypestring_alt == "sas_target")
|| (devicesubsystem == "sas_host")
|| (devicesubsystem == "sas_port")
|| (devicesubsystem == "sas_device")
|| (devicesubsystem == "sas_expander")
|| (devicesubsystem == "sas_generic")
|| (devicesubsystem == "sas_phy")
|| (devicesubsystem == "sas_end_device")
|| (devicesubsystem == "spi_transport")
|| (devicesubsystem == "spi_host")
|| (devicesubsystem == "ata_port")
|| (devicesubsystem == "ata_link")
|| (devicesubsystem == "ata_disk")
|| (devicesubsystem == "ata_device")
|| (devicesubsystem == "ata")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "infiniband") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Peripheral);
}
if ((devicesubsystem == "infiniband_cm")
|| (devicesubsystem == "infiniband_mad")
|| (devicesubsystem == "infiniband_verbs")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "infiniband_srp") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::SCSI);
}
if ((devicesubsystem == "enclosure")
|| (devicesubsystem == "clocksource")
|| (devicesubsystem == "amba")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "edac") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::RAM);
}
if (devicesubsystem.startsWith("mc") && systempath.contains("/edac/")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::RAM);
}
if ((devicesubsystem == "ipmi")
|| (devicesubsystem == "ipmi_si")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Mainboard);
}
if (devicesubsystem == "iommu") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "misc") {
if (devicedriver.startsWith("tpm_")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Cryptography);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
}
if (devicesubsystem == "media") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "nd") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::RAM);
}
if (devicesubsystem == "ptp") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Timekeeping);
}
if (devicesubsystem == "leds") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherACPI);
}
if (devicesubsystem == "net") {
if (!device) device = new TDENetworkDevice(TDEGenericDeviceType::Network);
}
if ((devicesubsystem == "i2c")
|| (devicesubsystem == "i2c-dev")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::I2C);
}
if (devicesubsystem == "mdio_bus") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::MDIO);
}
if (devicesubsystem == "graphics") {
if (devicenode.isNull()) { // GPUs do not have associated device nodes
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::GPU);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
}
if (devicesubsystem == "tifm_adapter") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::StorageController);
}
if ((devicesubsystem == "mmc_host")
|| (devicesubsystem == "memstick_host")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::StorageController);
}
if (devicesubsystem == "mmc") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if ((devicesubsystem == "event_source")
|| (devicesubsystem == "rtc")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Mainboard);
}
if (devicesubsystem == "bsg") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::SCSI);
}
if (devicesubsystem == "firewire") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::IEEE1394);
}
if (devicesubsystem == "drm") {
if (devicenode.isNull()) { // Monitors do not have associated device nodes
if (!device) device = new TDEMonitorDevice(TDEGenericDeviceType::Monitor);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
}
if (devicesubsystem == "nvmem") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::NonvolatileMemory);
}
if (devicesubsystem == "serio") {
if (devicedriver.contains("atkbd")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Keyboard);
}
else if (devicedriver.contains("mouse")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Mouse);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Serial);
}
}
if ((devicesubsystem == "ppdev")
|| (devicesubsystem == "parport")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Parallel);
}
if (devicesubsystem == "printer") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Printer);
}
if (devicesubsystem == "bridge") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Bridge);
}
if ((devicesubsystem == "pci_bus")
|| (devicesubsystem == "pci_express")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Bus);
}
if (devicesubsystem == "pcmcia_socket") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::PCMCIA);
}
if (devicesubsystem == "platform") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "ieee80211") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "rfkill") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "machinecheck") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
}
if (devicesubsystem == "pnp") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::PNP);
}
if ((devicesubsystem == "hid")
|| (devicesubsystem == "hidraw")
|| (devicesubsystem == "usbhid")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::HID);
}
if (devicesubsystem == "power_supply") {
TQString powersupplyname(udev_device_get_property_value(dev, "POWER_SUPPLY_NAME"));
if ((devicedriver == "ac")
|| (powersupplyname.upper().startsWith("AC"))) {
if (!device) device = new TDEMainsPowerDevice(