Darrell Anderson 13 years ago
commit 70341737e1

@ -123,7 +123,7 @@ set( ${target}_SRCS
ktempdir.cpp kshell.cpp kmountpoint.cpp kcalendarsystemjalali.cpp
kprotocolinfo_tdecore.cpp kprotocolinfofactory.cpp kxerrorhandler.cpp
kuser.cpp kconfigskeleton.cpp kconfigdialogmanager.cpp klockfile.cpp
kqiodevicegzip_p.cpp ktimezones.cpp tdehardwaredevices.cpp
kqiodevicegzip_p.cpp ktimezones.cpp tdehardwaredevices.cpp ksimpledirwatch.cpp
)
tde_add_library( ${target} SHARED AUTOMOC

@ -11,3 +11,4 @@
add_subdirectory( classrules )
add_subdirectory( pnpdev )

@ -0,0 +1,17 @@
#################################################
#
# (C) 2012 Timothy Pearson
# kb9vqf (AT) pearsoncomputing.net
#
# Improvements and feedback are welcome
#
# This file is released under GPL >= 2
#
#################################################
##### other data ################################
install( FILES
pnp.ids
DESTINATION ${DATA_INSTALL_DIR}/tdehwlib/pnpdev )

@ -0,0 +1,156 @@
# The information provided in this PNP ID to friendly name mapping table was obtained from
# multiple public sources, as well as this authoritative publicly accessible file:
# ftp://ftpmicrosoftcom/developr/drg/plug-and-play/devidstxt
#
# This file is provided soley in the interest of cross platform compatibility
# It only contains information on certain generic core system devices that cannot be looked up via another method
# All marks are the property of their owners
#
# A typical PNP ID takes the form of PNPxxxx:yy
#
# Some additional information that may be useful for applications parsing PNP device ID strings:
# PNP0xxx System devices
# PNP8xxx Network adapters
# PNPAxxx SCSI, proprietary CD adapters
# PNPBxxx Sound, video capture, multimedia
# PNPCxxx - PNPDxxx Modems
#
# The two digit code yy appears to be a PCI device type code followed by a subtype code and should be parsed as such
PNP0802 Microsoft® Sound System-compatible device
PNP0000 AT Interrupt Controller
PNP0001 EISA Interrupt Controller
PNP0002 MCA Interrupt Controller
PNP0003 APIC
PNP0004 Cyrix SLiC MP Interrupt Controller
PNP0100 AT Timer
PNP0101 EISA Timer
PNP0102 MCA Timer
PNP0103 High Precision Event Timer
PNP0200 AT DMA Controller
PNP0201 EISA DMA Controller
PNP0202 MCA DMA Controller
PNP0300 IBM PC/XT keyboard controller (83-key)
PNP0301 IBM PC/AT keyboard controller (86-key)
PNP0302 IBM PC/XT keyboard controller (84-key)
PNP0303 IBM Enhanced (101/102-key, PS/2 mouse support)
PNP0304 Olivetti Keyboard (83-key)
PNP0305 Olivetti Keyboard (102-key)
PNP0306 Olivetti Keyboard (86-key)
PNP0307 Microsoft® Windows(R) Keyboard
PNP0308 General Input Device Emulation Interface (GIDEI) legacy
PNP0309 Olivetti Keyboard (A101/102 key)
PNP030A AT&T 302 keyboard
PNP030B Reserved by Microsoft®
PNP0320 Japanese 106-key keyboard A01
PNP0321 Japanese 101-key keyboard
PNP0322 Japanese AX keyboard
PNP0323 Japanese 106-key keyboard 002/003
PNP0324 Japanese 106-key keyboard 001
PNP0325 Japanese Toshiba Desktop keyboard
PNP0326 Japanese Toshiba Laptop keyboard
PNP0327 Japanese Toshiba Notebook keyboard
PNP0340 Korean 84-key keyboard
PNP0341 Korean 86-key keyboard
PNP0342 Korean Enhanced keyboard
PNP0343 Korean Enhanced keyboard 101b
PNP0343 Korean Enhanced keyboard 101c
PNP0344 Korean Enhanced keyboard 103
PNP0400 Standard LPT Printer Port
PNP0401 ECP Printer Port
PNP0500 Standard PC Serial Port
PNP0501 16550A-compatible Serial Port
PNP0502 Multiport Serial Device (non-intelligent 16550)
PNP0510 Generic IRDA-compatible Device
PNP0511 Generic IRDA-compatible Device
PNP0600 Generic ESDI/IDE/ATA Compatible Hard Disk Controller
PNP0603 Generic IDE supporting Microsoft® Device Bay Specification
PNP0700 PC Standard Floppy Disk Controller
PNP0701 Microsoft® Device Bay Compatible Floppy Controller
PNP0802 Microsoft® Sound System compatible device
PNP0900 VGA Compatible Display Controller
PNP09FF Plug and Play Monitor (VESA DDC)
PNP0A00 ISA Root Bus
PNP0A01 EISA Root Bus
PNP0A02 MCA Root Bus
PNP0A03 PCI Root Bus
PNP0A04 VESA/VL Bus
PNP0A05 Generic ACPI Root Bus
PNP0A06 Generic ACPI Extended-IO Root Bus (EIO Root Bus)
PNP0A08 PCI Express Root Bus
PNP0800 AT-style Speaker
PNP0B00 AT Real-Time Clock
PNP0C00 Plug and Play BIOS
PNP0C01 System Board
PNP0C02 Plug and Play Motherboard Register Resource
PNP0C03 Plug and Play BIOS Event Notification Interrupt
PNP0C04 Math Coprocessor
PNP0C05 APM BIOS
PNP0C06 Early Plug and Play BIOS
PNP0C07 Early Plug and Play BIOS
PNP0C08 ACPI System Board
PNP0C09 ACPI Embedded Controller
PNP0C0A ACPI Control Method Battery
PNP0C0B ACPI Fan
PNP0C0C ACPI Power Button
PNP0C0D ACPI Lid Switch
PNP0C0E ACPI Sleep Button
PNP0C0F PCI Interrupt Link
PNP0C10 ACPI System Indicator
PNP0C11 ACPI Thermal Zone
PNP0C12 Device Bay Controller
PNP0C13 Plug and Play BIOS
PNP0E00 Intel 82365-Compatible PCMCIA Controller
PNP0E01 Cirrus Logic CL-PD6720 PCMCIA Controller
PNP0E02 VLSI VL82C146 PCMCIA Controller
PNP0E03 Intel 82365-compatible CardBus controller
PNP0F00 Microsoft® Bus Mouse
PNP0F01 Microsoft® Serial Mouse
PNP0F02 Microsoft® InPort Mouse
PNP0F03 Microsoft® PS/2-style Mouse
PNP0F04 Mouse Systems Mouse
PNP0F05 Mouse Systems 3-Button Mouse
PNP0F06 Genius Mouse
PNP0F07 Genius Mouse
PNP0F08 Logitech Serial Mouse
PNP0F09 Microsoft® BallPoint Serial Mouse
PNP0F0A Microsoft® Plug and Play Mouse
PNP0F0B Microsoft® Plug and Play BallPoint Mouse
PNP0F0C Microsoft®-compatible Serial Mouse
PNP0F0D Microsoft®-compatible InPort-compatible Mouse
PNP0F0E Microsoft®-compatible PS/2-style Mouse
PNP0F0F Microsoft®-compatible Serial BallPoint-compatible Mouse
PNP0F10 Texas Instruments QuickPort Mouse
PNP0F11 Microsoft®-compatible Bus Mouse
PNP0F12 Logitech PS/2-style Mouse
PNP0F13 PS/2 Port for PS/2-style Mice
PNP0F14 Microsoft® Kids Mouse
PNP0F15 Logitech bus mouse
PNP0F16 Logitech SWIFT device
PNP0F17 Logitech-compatible serial mouse
PNP0F18 Logitech-compatible bus mouse
PNP0F19 Logitech-compatible PS/2-style Mouse
PNP0F1A Logitech-compatible SWIFT Device
PNP0F1B HP Omnibook Mouse
PNP0F1C Compaq LTE Trackball PS/2-style Mouse
PNP0F1D Compaq LTE Trackball Serial Mouse
PNP0F1E Microsoft® Kids Trackball Mouse
PNP0F1F Reserved by Microsoft® Input Device Group
PNP0F20 Reserved by Microsoft® Input Device Group
PNP0F21 Reserved by Microsoft® Input Device Group
PNP0F22 Reserved by Microsoft® Input Device Group
PNP0F23 Reserved by Microsoft® Input Device Group
PNP0FFF Reserved by Microsoft® Systems

File diff suppressed because it is too large Load Diff

@ -0,0 +1,293 @@
/* This file is part of the KDE libraries
Copyright (C) 1998 Sven Radej <sven@lisa.exp.univie.ac.at>
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.
*/
#ifndef _KSIMPLEDIRWATCH_H
#define _KSIMPLEDIRWATCH_H
#include <tqtimer.h>
#include <tqdatetime.h>
#include <tqmap.h>
#include <tdelibs_export.h>
#define kdirwatch KSimpleDirWatch::self()
class KSimpleDirWatchPrivate;
/**
* KSimpleDirWatch is a basic copy of KDirWatch
* but with the KIO linking requirement removed
*
* Watch directories and files for changes.
* The watched directories or files don't have to exist yet.
*
* When a watched directory is changed, i.e. when files therein are
* created or deleted, KSimpleDirWatch will emit the signal dirty().
*
* When a watched, but previously not existing directory gets created,
* KSimpleDirWatch will emit the signal created().
*
* When a watched directory gets deleted, KSimpleDirWatch will emit the
* signal deleted(). The directory is still watched for new
* creation.
*
* When a watched file is changed, i.e. attributes changed or written
* to, KSimpleDirWatch will emit the signal dirty().
*
* Scanning of particular directories or files can be stopped temporarily
* and restarted. The whole class can be stopped and restarted.
* Directories and files can be added/removed from the list in any state.
*
* The implementation uses the FAM service when available;
* if FAM is not available, the DNOTIFY functionality is used on LINUX.
* As a last resort, a regular polling for change of modification times
* is done; the polling interval is a global config option:
* DirWatch/PollInterval and DirWatch/NFSPollInterval for NFS mounted
* directories.
*
* @see self()
* @short Class for watching directory and file changes.
* @author Sven Radej <sven@lisa.exp.univie.ac.at>
*/
class KIO_EXPORT KSimpleDirWatch : public TQObject
{
Q_OBJECT
public:
/**
* Constructor.
*
* Scanning begins immediately when a dir/file watch
* is added.
* @param parent the parent of the TQObject (or 0 for parent-less KDataTools)
* @param name the name of the TQObject, can be 0
*/
KSimpleDirWatch (TQObject* parent = 0, const char* name = 0);
/**
* Destructor.
*
* Stops scanning and cleans up.
*/
~KSimpleDirWatch();
/**
* Adds a directory to be watched.
*
* The directory does not have to exist. When @p watchFiles is
* false (the default), the signals dirty(), created(), deleted()
* can be emitted, all for the watched directory.
* When @p watchFiles is true, all files in the watched directory
* are watched for changes, too. Thus, the signals dirty(),
* created(), deleted() can be emitted.
*
* @param path the path to watch
* @param watchFiles if true, the KSimpleDirWatch will also watch files - NOT IMPLEMENTED YET
* @param recursive if true, all sub directories are also watched - NOT IMPLEMENTED YET
*/
void addDir(const TQString& path,
bool watchFiles = false, bool recursive = false);
/**
* Adds a file to be watched.
* @param file the file to watch
*/
void addFile(const TQString& file);
/**
* Returns the time the directory/file was last changed.
* @param path the file to check
* @return the date of the last modification
*/
TQDateTime ctime(const TQString& path);
/**
* Removes a directory from the list of scanned directories.
*
* If specified path is not in the list this does nothing.
* @param path the path of the dir to be removed from the list
*/
void removeDir(const TQString& path);
/**
* Removes a file from the list of watched files.
*
* If specified path is not in the list this does nothing.
* @param file the file to be removed from the list
*/
void removeFile(const TQString& file);
/**
* Stops scanning the specified path.
*
* The @p path is not deleted from the interal just, it is just skipped.
* Call this function when you perform an huge operation
* on this directory (copy/move big files or many files). When finished,
* call restartDirScan(path).
*
* @param path the path to skip
* @return true if the @p path is being watched, otherwise false
* @see restartDirScanning()
*/
bool stopDirScan(const TQString& path);
/**
* Restarts scanning for specified path.
*
* Resets ctime. It doesn't notify
* the change (by emitted a signal), since the ctime value is reset.
*
* Call it when you are finished with big operations on that path,
* @em and when @em you have refreshed that path.
*
* @param path the path to restart scanning
* @return true if the @p path is being watched, otherwise false
* @see stopDirScanning()
*/
bool restartDirScan(const TQString& path);
/**
* Starts scanning of all dirs in list.
*
* @param notify If true, all changed directories (since
* stopScan() call) will be notified for refresh. If notify is
* false, all ctimes will be reset (except those who are stopped,
* but only if @p skippedToo is false) and changed dirs won't be
* notified. You can start scanning even if the list is
* empty. First call should be called with @p false or else all
* directories
* in list will be notified.
* @param skippedToo if true, the skipped directoris (scanning of which was
* stopped with stopDirScan() ) will be reset and notified
* for change. Otherwise, stopped directories will continue to be
* unnotified.
*/
void startScan( bool notify=false, bool skippedToo=false );
/**
* Stops scanning of all directories in internal list.
*
* The timer is stopped, but the list is not cleared.
*/
void stopScan();
/**
* Is scanning stopped?
* After creation of a KSimpleDirWatch instance, this is false.
* @return true when scanning stopped
*/
bool isStopped() { return _isStopped; }
/**
* Check if a directory is being watched by this KSimpleDirWatch instance
* @param path the directory to check
* @return true if the directory is being watched
*/
bool contains( const TQString& path ) const;
/**
* Dump statistic information about all KSimpleDirWatch instances.
* This checks for consistency, too.
*/
static void statistics();
/**
* Emits created().
* @param path the path of the file or directory
*/
void setCreated( const TQString &path );
/**
* Emits dirty().
* @param path the path of the file or directory
*/
void setDirty( const TQString &path );
/**
* Emits deleted().
* @param path the path of the file or directory
*/
void setDeleted( const TQString &path );
enum Method { FAM, DNotify, Stat, INotify };
/**
* Returns the preferred internal method to
* watch for changes.
* @since 3.2
*/
Method internalMethod();
/**
* The KSimpleDirWatch instance usually globally used in an application.
* It is automatically deleted when the application exits.
*
* However, you can create an arbitrary number of KSimpleDirWatch instances
* aside from this one - for those you have to take care of memory management.
*
* This function returns an instance of KSimpleDirWatch. If there is none, it
* will be created.
*
* @return a KSimpleDirWatch instance
*/
static KSimpleDirWatch* self();
/**
* Returns true if there is an instance of KSimpleDirWatch.
* @return true if there is an instance of KSimpleDirWatch.
* @see KSimpleDirWatch::self()
* @since 3.1
*/
static bool exists();
signals:
/**
* Emitted when a watched object is changed.
* For a directory this signal is emitted when files
* therein are created or deleted.
* For a file this signal is emitted when its size or attributes change.
*
* When you watch a directory, changes in the size or attributes of
* contained files may or may not trigger this signal to be emitted
* depending on which backend is used by KSimpleDirWatch.
*
* The new ctime is set before the signal is emitted.
* @param path the path of the file or directory
*/
void dirty (const TQString &path);
/**
* Emitted when a file or directory is created.
* @param path the path of the file or directory
*/
void created (const TQString &path );
/**
* Emitted when a file or directory is deleted.
*
* The object is still watched for new creation.
* @param path the path of the file or directory
*/
void deleted (const TQString &path );
private:
bool _isStopped;
KSimpleDirWatchPrivate *d;
static KSimpleDirWatch* s_pSelf;
};
#endif
// vim: sw=3 et

@ -0,0 +1,161 @@
/* Private Header for class of KSimpleDirWatchPrivate
*
* this separate header file is needed for TQMOC processing
* because KSimpleDirWatchPrivate has signals and slots
*
* KSimpleDirWatch is a basic copy of KDirWatch
* but with the KIO linking requirement removed
*/
#ifndef _KSIMPLEDIRWATCH_P_H
#define _KSIMPLEDIRWATCH_P_H
#ifdef HAVE_FAM
#include <fam.h>
#endif
#include <ctime>
#define invalid_ctime ((time_t)-1)
/* KSimpleDirWatchPrivate is a singleton and does the watching
* for every KSimpleDirWatch instance in the application.
*/
class KSimpleDirWatchPrivate : public TQObject
{
Q_OBJECT
public:
enum entryStatus { Normal = 0, NonExistent };
enum entryMode { UnknownMode = 0, StatMode, DNotifyMode, INotifyMode, FAMMode };
enum { NoChange=0, Changed=1, Created=2, Deleted=4 };
struct Client {
KSimpleDirWatch* instance;
int count;
// did the instance stop watching
bool watchingStopped;
// events blocked when stopped
int pending;
};
class Entry
{
public:
// the last observed modification time
time_t m_ctime;
// the last observed link count
int m_nlink;
entryStatus m_status;
entryMode m_mode;
bool isDir;
// instances interested in events
TQPtrList<Client> m_clients;
// nonexistent entries of this directory
TQPtrList<Entry> m_entries;
TQString path;
int msecLeft, freq;
void addClient(KSimpleDirWatch*);
void removeClient(KSimpleDirWatch*);
int clients();
bool isValid() { return m_clients.count() || m_entries.count(); }
bool dirty;
void propagate_dirty();
#ifdef HAVE_FAM
FAMRequest fr;
#endif
#ifdef HAVE_DNOTIFY
int dn_fd;
#endif
#ifdef HAVE_INOTIFY
int wd;
#endif
};
typedef TQMap<TQString,Entry> EntryMap;
KSimpleDirWatchPrivate();
~KSimpleDirWatchPrivate();
void resetList (KSimpleDirWatch*,bool);
void useFreq(Entry* e, int newFreq);
void addEntry(KSimpleDirWatch*,const TQString&, Entry*, bool);
void removeEntry(KSimpleDirWatch*,const TQString&, Entry*);
bool stopEntryScan(KSimpleDirWatch*, Entry*);
bool restartEntryScan(KSimpleDirWatch*, Entry*, bool );
void stopScan(KSimpleDirWatch*);
void startScan(KSimpleDirWatch*, bool, bool);
void removeEntries(KSimpleDirWatch*);
void statistics();
Entry* entry(const TQString&);
int scanEntry(Entry* e);
void emitEvent(Entry* e, int event, const TQString &fileName = TQString::null);
// Memory management - delete when last KSimpleDirWatch gets deleted
void ref() { m_ref++; }
bool deref() { return ( --m_ref == 0 ); }
static bool isNoisyFile( const char *filename );
public slots:
void slotRescan();
void famEventReceived(); // for FAM
void slotActivated(); // for DNOTIFY
void slotRemoveDelayed();
public:
TQTimer *timer;
EntryMap m_mapEntries;
int freq;
int statEntries;
int m_nfsPollInterval, m_PollInterval;
int m_ref;
bool useStat(Entry*);
bool delayRemove;
TQPtrList<Entry> removeList;
bool rescan_all;
TQTimer rescan_timer;
#ifdef HAVE_FAM
TQSocketNotifier *sn;
FAMConnection fc;
bool use_fam;
void checkFAMEvent(FAMEvent*);
bool useFAM(Entry*);
#endif
#if defined(HAVE_DNOTIFY) || defined(HAVE_INOTIFY)
TQSocketNotifier *mSn;
#endif
#ifdef HAVE_DNOTIFY
bool supports_dnotify;
int mPipe[2];
TQIntDict<Entry> fd_Entry;
static void dnotify_handler(int, siginfo_t *si, void *);
static void dnotify_sigio_handler(int, siginfo_t *si, void *);
bool useDNotify(Entry*);
#endif
#ifdef HAVE_INOTIFY
bool supports_inotify;
int m_inotify_fd;
bool useINotify(Entry*);
#endif
};
#endif // KSIMPLEDIRWATCH_P_H

@ -27,6 +27,7 @@
#include <klocale.h>
#include <kconfig.h>
#include <ktempfile.h>
#include <ksimpledirwatch.h>
#include <kstandarddirs.h>
#include <libudev.h>
@ -37,10 +38,31 @@
#include <sys/ioctl.h>
#include <linux/fs.h>
// 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/....
TDESensorCluster::TDESensorCluster() {
label = TQString::null;
current = -1;
minimum = -1;
maximum = -1;
warning = -1;
critical = -1;
}
TDEGenericDevice::TDEGenericDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) {
m_deviceType = dt;
m_deviceName = dn;
@ -128,6 +150,22 @@ void TDEGenericDevice::setModelID(TQString id) {
m_modelID.replace("0x", "");
}
TQString &TDEGenericDevice::vendorEncoded() {
return m_vendorenc;
}
void TDEGenericDevice::setVendorEncoded(TQString id) {
m_vendorenc = id;
}
TQString &TDEGenericDevice::modelEncoded() {
return m_modelenc;
}
void TDEGenericDevice::setModelEncoded(TQString id) {
m_modelenc = id;
}
TQString &TDEGenericDevice::subVendorID() {
return m_subvendorID;
}
@ -223,6 +261,20 @@ TQString TDEGenericDevice::friendlyName() {
else if (m_modAlias.lower().startsWith("usb")) {
m_friendlyName = KGlobal::hardwareDevices()->findUSBDeviceName(m_vendorID, m_modelID, m_subvendorID, m_submodelID);
}
else {
TQString acpigentype = systemPath();
acpigentype.remove(0, acpigentype.findRev("/")+1);
TQString pnpgentype = acpigentype;
pnpgentype.truncate(pnpgentype.find(":"));
if (pnpgentype.startsWith("PNP")) {
m_friendlyName = KGlobal::hardwareDevices()->findPNPDeviceName(pnpgentype);
}
else if (acpigentype.startsWith("device:")) {
acpigentype.remove(0, acpigentype.findRev(":")+1);
acpigentype.prepend("0x");
m_friendlyName = i18n("ACPI Node %1").arg(acpigentype.toUInt(0,0));
}
}
}
if (m_friendlyName.isNull()) {
@ -231,6 +283,24 @@ TQString TDEGenericDevice::friendlyName() {
if (type() == TDEGenericDeviceType::CPU) {
m_friendlyName = name();
}
else if (type() == TDEGenericDeviceType::Event) {
// Use parent node name
if (m_parentDevice) {
return m_parentDevice->friendlyName();
}
else {
m_friendlyName = i18n("Generic Event Device");
}
}
else if (type() == TDEGenericDeviceType::Input) {
// Use parent node name
if (m_parentDevice) {
return m_parentDevice->friendlyName();
}
else {
m_friendlyName = i18n("Generic Input Device");
}
}
// Guess by driver
else if (!m_deviceDriver.isNull()) {
TQString friendlyDriverName = m_deviceDriver.lower();
@ -345,6 +415,27 @@ void TDEStorageDevice::setSlaveDevices(TQStringList sd) {
}
TQString TDEStorageDevice::friendlyName() {
// Return the actual storage device name
TQString devicevendorid = vendorEncoded();
TQString devicemodelid = modelEncoded();
devicevendorid.replace("\\x20", " ");
devicemodelid.replace("\\x20", " ");
devicevendorid = devicevendorid.stripWhiteSpace();
devicemodelid = devicemodelid.stripWhiteSpace();
devicevendorid = devicevendorid.simplifyWhiteSpace();
devicemodelid = devicemodelid.simplifyWhiteSpace();
TQString devicename = devicevendorid + " " + devicemodelid;
devicename = devicename.stripWhiteSpace();
devicename = devicename.simplifyWhiteSpace();
if (devicename != "") {
return devicename;
}
if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
return friendlyDeviceType();
}
@ -352,7 +443,7 @@ TQString TDEStorageDevice::friendlyName() {
TQString label = diskLabel();
if (label.isNull()) {
if (deviceSize() > 0) {
if (checkDiskStatus(TDEDiskDeviceStatus::Removable)) {
if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
label = i18n("%1 Removable Device").arg(deviceFriendlySize());
}
else {
@ -399,7 +490,7 @@ TQString TDEStorageDevice::friendlyDeviceType() {
if (isDiskOfType(TDEDiskDeviceType::HDD)) {
ret = i18n("Hard Disk Drive");
if (checkDiskStatus(TDEDiskDeviceStatus::Removable)) {
if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
ret = i18n("Removable Storage");
}
if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
@ -447,7 +538,7 @@ TQPixmap TDEStorageDevice::icon(KIcon::StdSizes size) {
if (isDiskOfType(TDEDiskDeviceType::HDD)) {
ret = DesktopIcon("hdd_unmount", size);
if (checkDiskStatus(TDEDiskDeviceStatus::Removable)) {
if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
ret = DesktopIcon("usbpendrive_unmount", size);
}
if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
@ -710,10 +801,95 @@ bool TDEStorageDevice::unmountDevice(TQString* errRet, int* retcode) {
return false;
}
TDECPUDevice::TDECPUDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn) {
}
TDECPUDevice::~TDECPUDevice() {
}
double &TDECPUDevice::frequency() {
return m_frequency;
}
void TDECPUDevice::setFrequency(double fr) {
m_frequency = fr;
}
double &TDECPUDevice::minFrequency() {
return m_minfrequency;
}
void TDECPUDevice::setMinFrequency(double fr) {
m_minfrequency = fr;
}
double &TDECPUDevice::maxFrequency() {
return m_maxfrequency;
}
void TDECPUDevice::setMaxFrequency(double fr) {
m_maxfrequency = fr;
}
double &TDECPUDevice::transitionLatency() {
return m_transitionlatency;
}
void TDECPUDevice::setTransitionLatency(double tl) {
m_transitionlatency = tl;
}
TQString &TDECPUDevice::governor() {
return m_governor;
}
void TDECPUDevice::setGovernor(TQString gr) {
m_governor = gr;
}
TQString &TDECPUDevice::scalingDriver() {
return m_scalingdriver;
}
void TDECPUDevice::setScalingDriver(TQString dr) {
m_scalingdriver = dr;
}
TQStringList &TDECPUDevice::dependentProcessors() {
return m_tiedprocs;
}
void TDECPUDevice::setDependentProcessors(TQStringList dp) {
m_tiedprocs = dp;
}
TQStringList &TDECPUDevice::availableFrequencies() {
return m_frequencies;
}
void TDECPUDevice::setAvailableFrequencies(TQStringList af) {
m_frequencies = af;
}
TDESensorDevice::TDESensorDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn) {
}
TDESensorDevice::~TDESensorDevice() {
}
TDESensorClusterMap TDESensorDevice::values() {
return m_sensorValues;
}
void TDESensorDevice::setValues(TDESensorClusterMap cl) {
m_sensorValues = cl;
}
TDEHardwareDevices::TDEHardwareDevices() {
// Initialize members
pci_id_map = 0;
usb_id_map = 0;
pnp_id_map = 0;
// Set up device list
m_deviceList.setAutoDelete( TRUE ); // the list owns the objects
@ -750,12 +926,49 @@ TDEHardwareDevices::TDEHardwareDevices() {
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()) );
TQDir nodezerocpufreq("/sys/devices/system/cpu/cpu0/cpufreq");
if (nodezerocpufreq.exists()) {
m_cpuWatchTimer->start( 500, FALSE ); // 0.5 second repeating timer
}
#endif
// Update internal device information
queryHardwareInformation();
}
}
TDEHardwareDevices::~TDEHardwareDevices() {
// [FIXME 0.01]
#if 0
// Stop CPU scanning
m_cpuWatch->stopScan();
#else
m_cpuWatchTimer->stop();
#endif
// Stop mount scanning
close(m_procMountsFd);
@ -769,6 +982,9 @@ TDEHardwareDevices::~TDEHardwareDevices() {
if (usb_id_map) {
delete usb_id_map;
}
if (pnp_id_map) {
delete pnp_id_map;
}
}
void TDEHardwareDevices::rescanDeviceInformation(TDEGenericDevice* hwdevice) {
@ -885,6 +1101,158 @@ void TDEHardwareDevices::processHotPluggedHardware() {
}
}
void TDEHardwareDevices::processModifiedCPUs() {
// Detect what changed between the old cpu information and the new information,
// and emit appropriate events
// Read new CPU information table
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();
}
// Parse CPU information table
TDECPUDevice *cdevice;
cdevice = 0;
bool modified = false;
TQString curline;
int processorNumber = 0;
int processorCount = 0;
for (TQStringList::Iterator cpuit = m_cpuInfo.begin(); cpuit != m_cpuInfo.end(); ++cpuit) {
// WARNING This routine assumes that "processor" is always the first entry in /proc/cpuinfo!
curline = *cpuit;
if (curline.startsWith("processor")) {
curline.remove(0, curline.find(":")+1);
curline = curline.stripWhiteSpace();
processorNumber = curline.toInt();
cdevice = dynamic_cast<TDECPUDevice*>(findBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber)));
}
if (curline.startsWith("model name")) {
curline.remove(0, curline.find(":")+1);
curline = curline.stripWhiteSpace();
if (cdevice->name() != curline) modified = true;
cdevice->setName(curline);
}
if (curline.startsWith("cpu MHz")) {
curline.remove(0, curline.find(":")+1);
curline = curline.stripWhiteSpace();
if (cdevice->frequency() != curline.toDouble()) modified = true;
cdevice->setFrequency(curline.toDouble());
}
if (curline.startsWith("vendor_id")) {
curline.remove(0, curline.find(":")+1);
curline = curline.stripWhiteSpace();
if (cdevice->vendorName() != curline) modified = true;
cdevice->setVendorName(curline);
if (cdevice->vendorEncoded() != curline) modified = true;
cdevice->setVendorEncoded(curline);
}
}
processorCount = processorNumber+1;
// Read in other information from cpufreq, if available
for (processorNumber=0; processorNumber<processorCount; processorNumber++) {
cdevice = dynamic_cast<TDECPUDevice*>(findBySystemPath(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;
if (cpufreq_dir.exists()) {
TQString 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("/scaling_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("/scaling_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("/affected_cpus");
TQFile tiedcpusfile(nodename);
if (tiedcpusfile.open(IO_ReadOnly)) {
TQTextStream stream( &tiedcpusfile );
affectedcpulist = TQStringList::split(" ", stream.readLine());
tiedcpusfile.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();
}
}
// Update CPU information structure
if (cdevice->governor() != scalinggovernor) modified = true;
cdevice->setGovernor(scalinggovernor);
if (cdevice->scalingDriver() != scalingdriver) modified = true;
cdevice->setScalingDriver(scalingdriver);
if (cdevice->minFrequency() != minfrequency) modified = true;
cdevice->setMinFrequency(minfrequency);
if (cdevice->maxFrequency() != maxfrequency) modified = true;
cdevice->setMaxFrequency(maxfrequency);
if (cdevice->transitionLatency() != trlatency) modified = true;
cdevice->setTransitionLatency(trlatency);
if (cdevice->dependentProcessors().join(" ") != affectedcpulist.join(" ")) modified = true;
cdevice->setDependentProcessors(affectedcpulist);
if (cdevice->availableFrequencies().join(" ") != frequencylist.join(" ")) modified = true;
cdevice->setAvailableFrequencies(frequencylist);
}
if (modified) {
for (processorNumber=0; processorNumber<processorCount; processorNumber++) {
TDEGenericDevice* hwdevice = findBySystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber));
// Signal new information available
emit hardwareUpdated(hwdevice);
}
}
}
void TDEHardwareDevices::processModifiedMounts() {
// Detect what changed between the old mount table and the new one,
// and emit appropriate events
@ -1205,6 +1573,12 @@ TDEGenericDeviceType::TDEGenericDeviceType readGenericDeviceTypeFromString(TQStr
else if (query == "Platform") {
ret = TDEGenericDeviceType::Platform;
}
else if (query == "Event") {
ret = TDEGenericDeviceType::Event;
}
else if (query == "Input") {
ret = TDEGenericDeviceType::Input;
}
else if (query == "PNP") {
ret = TDEGenericDeviceType::PNP;
}
@ -1479,12 +1853,13 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
TQString systempath(udev_device_get_syspath(dev));
TQString devicevendorid(udev_device_get_property_value(dev, "ID_VENDOR_ID"));
TQString devicemodelid(udev_device_get_property_value(dev, "ID_MODEL_ID"));
TQString devicevendoridenc(udev_device_get_property_value(dev, "ID_VENDOR_ENC"));
TQString devicemodelidenc(udev_device_get_property_value(dev, "ID_MODEL_ENC"));
TQString devicesubvendorid(udev_device_get_property_value(dev, "ID_SUBVENDOR_ID"));
TQString devicesubmodelid(udev_device_get_property_value(dev, "ID_SUBMODEL_ID"));
TQString devicetypestring(udev_device_get_property_value(dev, "ID_TYPE"));
TQString devicetypestring_alt(udev_device_get_property_value(dev, "DEVTYPE"));
TQString devicepciclass(udev_device_get_property_value(dev, "PCI_CLASS"));
bool removable = false;
TDEGenericDevice* device = existingdevice;
// FIXME
@ -1522,12 +1897,13 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
// Go after it manually...
if (devicevendorid.isNull() || devicemodelid.isNull()) {
if (devicemodalias != TQString::null) {
int vloc = devicemodalias.find("v");
int dloc = devicemodalias.find("d", vloc);
int svloc = devicemodalias.find("sv");
int sdloc = devicemodalias.find("sd", vloc);
// 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) {
@ -1540,6 +1916,11 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
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) {
@ -1579,11 +1960,43 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
// Classify generic device type and create appropriate object
// Pull out all event special devices and stuff them under Platform
// Pull out all event special devices and stuff them under Event
TQString syspath_tail = systempath.lower();
syspath_tail.remove(0, syspath_tail.findRev("/")+1);
if (syspath_tail.startsWith("event")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Platform);
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Event);
}
// Pull out all input special devices and stuff them under Input
if (syspath_tail.startsWith("input")) {
if (!device) device = new TDEGenericDevice(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
@ -1597,7 +2010,38 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
}
else if (devicetype.isNull()) {
if (devicesubsystem == "acpi") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherACPI);
// 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")) {
// We support a limited number of specific PNP IDs here
if (pnpgentype == "PNP0C0A") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Battery);
}
else if (pnpgentype == "PNP0C0B") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::ThermalControl);
}
else if (pnpgentype == "PNP0C0C") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Power);
}
else if (pnpgentype == "PNP0C0D") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Power);
}
else if (pnpgentype == "PNP0C0E") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Power);
}
else if (pnpgentype == "PNP0C11") {
if (!device) device = new TDESensorDevice(TDEGenericDeviceType::ThermalSensor);
}
else {
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
@ -1640,7 +2084,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
else if (devicesubsystem == "hwmon") {
// FIXME
// This might pick up thermal sensors
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::OtherSensor);
if (!device) device = new TDESensorDevice(TDEGenericDeviceType::OtherSensor);
}
}
@ -1709,9 +2153,22 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::PNP);
}
if ((devicesubsystem == "hid")
|| (devicesubsystem == "hidraw")) {
|| (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 (powersupplyname.upper().startsWith("AC")) {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Power);
}
else {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Battery);
}
}
if (devicesubsystem == "backlight") {
if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Power);
}
// Moderate accuracy classification, if PCI device class is available
// See http://www.acm.uiuc.edu/sigops/roll_your_own/7.c.1.html for codes and meanings
@ -1773,6 +2230,8 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
device->setSystemPath(systempath);
device->setVendorID(devicevendorid);
device->setModelID(devicemodelid);
device->setVendorEncoded(devicevendoridenc);
device->setModelEncoded(devicemodelidenc);
device->setSubVendorID(devicesubvendorid);
device->setSubModelID(devicesubmodelid);
device->setModuleAlias(devicemodalias);
@ -1788,18 +2247,37 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
}
if (device->type() == TDEGenericDeviceType::Disk) {
// Determine if disk is removable
TQString removablenodename = udev_device_get_syspath(dev);
removablenodename.append("/removable");
FILE *fp = fopen(removablenodename.ascii(),"r");
if (fp) {
if (fgetc(fp) == '1') {
removable = true;
}
fclose(fp);
bool removable = false;
bool hotpluggable = false;
// We can get the removable flag, but we have no idea if the device has the ability to notify on media insertion/removal
// If there is no such notification possible, then we should not set the removable flag
// udev can be such an amazing pain at times
// It exports a /capabilities node with no info on what the bits actually mean
// This information is very poorly documented as a set of #defines in include/linux/genhd.h
// We are specifically interested in GENHD_FL_REMOVABLE and GENHD_FL_MEDIA_CHANGE_NOTIFY
// The "removable" flag should also really be renamed to "hotpluggable", as that is far more precise...
TQString capabilitynodename = systempath;
capabilitynodename.append("/capability");
TQFile capabilityfile( capabilitynodename );
unsigned int capabilities = 0;
if ( capabilityfile.open( IO_ReadOnly ) ) {
TQTextStream stream( &capabilityfile );
TQString capabilitystring;
capabilitystring = stream.readLine();
capabilities = capabilitystring.toUInt();
capabilityfile.close();
}
if (capabilities & GENHD_FL_REMOVABLE) {
// FIXME
// For added fun this is not always true; i.e. GENHD_FL_REMOVABLE can be set when the device cannot be hotplugged (floppy drives).
hotpluggable = true;
}
if (capabilities & GENHD_FL_MEDIA_CHANGE_NOTIFY) {
removable = true;
}
// See if any other devices are exclusively using this device, such as the Device Mapper|
// See if any other devices are exclusively using this device, such as the Device Mapper
TQStringList holdingDeviceNodes;
TQString holdersnodename = udev_device_get_syspath(dev);
holdersnodename.append("/holders/");
@ -1955,6 +2433,9 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
if (removable) {
diskstatus = diskstatus | TDEDiskDeviceStatus::Removable;
}
if (hotpluggable) {
diskstatus = diskstatus | TDEDiskDeviceStatus::Hotpluggable;
}
if ((filesystemtype.upper() != "CRYPTO_LUKS") && (filesystemtype.upper() != "CRYPTO") && (!filesystemtype.isNull())) {
diskstatus = diskstatus | TDEDiskDeviceStatus::ContainsFilesystem;
@ -1962,7 +2443,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
// Set mountable flag if device is likely to be mountable
diskstatus = diskstatus | TDEDiskDeviceStatus::Mountable;
if ((!devicetypestring.upper().isNull()) && (disktype & TDEDiskDeviceType::HDD)) {
if ((devicetypestring.upper().isNull()) && (disktype & TDEDiskDeviceType::HDD)) {
diskstatus = diskstatus & ~TDEDiskDeviceStatus::Mountable;
}
if (removable) {
@ -2035,12 +2516,65 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
devicenode.remove(0, devicenode.findRev("/")+1);
}
if ((device->type() == TDEGenericDeviceType::OtherSensor) || (device->type() == TDEGenericDeviceType::ThermalSensor)) {
// Populate all sensor values
TDESensorClusterMap sensors;
TQString valuesnodename = systempath + "/";
TQDir valuesdir(valuesnodename);
valuesdir.setFilter(TQDir::All);
TQString nodename;
const TQFileInfoList *dirlist = valuesdir.entryInfoList();
if (dirlist) {
TQFileInfoListIterator valuesdirit(*dirlist);
TQFileInfo *dirfi;
while ( (dirfi = valuesdirit.current()) != 0 ) {
nodename = dirfi->fileName();
if (nodename.contains("_")) {
TQFile file( valuesnodename + nodename );
if ( file.open( IO_ReadOnly ) ) {
TQTextStream stream( &file );
TQString line;
line = stream.readLine();
TQStringList sensornodelist = TQStringList::split("_", nodename);
TQString sensornodename = *(sensornodelist.at(0));
TQString sensornodetype = *(sensornodelist.at(1));
if (sensornodetype == "label") {
sensors[sensornodename].label = line;
}
if (sensornodetype == "input") {
sensors[sensornodename].current = line.toDouble();
}
if (sensornodetype == "min") {
sensors[sensornodename].minimum = line.toDouble();
}
if (sensornodetype == "max") {
sensors[sensornodename].maximum = line.toDouble();
}
if (sensornodetype == "warn") {
sensors[sensornodename].warning = line.toDouble();
}
if (sensornodetype == "crit") {
sensors[sensornodename].critical = line.toDouble();
}
file.close();
}
}
++valuesdirit;
}
}
TDESensorDevice* sdevice = dynamic_cast<TDESensorDevice*>(device);
sdevice->setValues(sensors);
}
// Set basic device information again, as some information may have changed
device->setName(devicename);
device->setDeviceNode(devicenode);
device->setSystemPath(systempath);
device->setVendorID(devicevendorid);
device->setModelID(devicemodelid);
device->setVendorEncoded(devicevendoridenc);
device->setModelEncoded(devicemodelidenc);
device->setSubVendorID(devicesubvendorid);
device->setSubModelID(devicesubmodelid);
device->setDeviceDriver(devicedriver);
@ -2189,23 +2723,28 @@ void TDEHardwareDevices::addCoreSystemDevices() {
while ( !stream.atEnd() ) {
line = stream.readLine();
// WARNING This routine assumes that "processor" is always the first entry in /proc/cpuinfo!
// FIXME Parse all available information, such as frequency, etc.
if (line.startsWith("processor")) {
line.remove(0, line.find(":")+1);
line = line.stripWhiteSpace();
processorNumber = line.toInt();
hwdevice = new TDEGenericDevice(TDEGenericDeviceType::CPU);
hwdevice->setSystemPath(TQString("/sys/devices/cpu/cpu%1").arg(processorNumber)); // FIXME: A system path is required, but I can't give a real, extant, unique path to the hardware manager due to kernel limitations
hwdevice = new TDECPUDevice(TDEGenericDeviceType::CPU);
hwdevice->setSystemPath(TQString("/sys/devices/system/cpu/cpu%1").arg(processorNumber));
m_deviceList.append(hwdevice);
}
if (line.startsWith("model name")) {
line.remove(0, line.find(":")+1);
line = line.stripWhiteSpace();
hwdevice->setName(line);
#if 0
// Set up CPU information monitor
// The only way CPU information can be changed is if something changes in the cpufreq node
// This may change in the future, but for now it is a fairly good assumption
m_cpuWatch->addDir(TQString("/sys/devices/system/cpu/cpu%1/cpufreq").arg(processorNumber));
#endif
}
lines += line;
}
file.close();
}
// Populate CPU information
processModifiedCPUs();
}
TQString TDEHardwareDevices::findPCIDeviceName(TQString vendorid, TQString modelid, TQString subvendorid, TQString submodelid) {
@ -2428,6 +2967,76 @@ TQString TDEHardwareDevices::findUSBDeviceName(TQString vendorid, TQString model
}
}
TQString TDEHardwareDevices::findPNPDeviceName(TQString pnpid) {
TQString friendlyName = TQString::null;
if (!pnp_id_map) {
pnp_id_map = new TDEDeviceIDMap;
TQStringList hardware_info_directories(KGlobal::dirs()->resourceDirs("data"));
TQString hardware_info_directory_suffix("tdehwlib/pnpdev/");
TQString hardware_info_directory;
TQString database_filename;
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 (KGlobal::dirs()->exists(hardware_info_directory)) {
database_filename = hardware_info_directory + "pnp.ids";
if (TQFile::exists(database_filename)) {
break;
}
}
}
if (!TQFile::exists(database_filename)) {
printf("[tdehardwaredevices] Unable to locate PNP information database pnp.ids\n\r"); fflush(stdout);
return i18n("Unknown PNP Device");
}
TQFile database(database_filename);
if (database.open(IO_ReadOnly)) {
TQTextStream stream(&database);
TQString line;
TQString pnpID;
TQString vendorName;
TQString deviceMapKey;
TQStringList devinfo;
while (!stream.atEnd()) {
line = stream.readLine();
if ((!line.upper().startsWith("\t")) && (!line.upper().startsWith("#"))) {
devinfo = TQStringList::split('\t', line, false);
if (devinfo.count() > 1) {
pnpID = *(devinfo.at(0));
vendorName = *(devinfo.at(1));;
vendorName = vendorName.stripWhiteSpace();
deviceMapKey = pnpID.upper().stripWhiteSpace();
if (!deviceMapKey.isNull()) {
pnp_id_map->insert(deviceMapKey, vendorName, true);
}
}
}
}
database.close();
}
else {
printf("[tdehardwaredevices] Unable to open PNP information database %s\n\r", database_filename.ascii()); fflush(stdout);
}
}
if (pnp_id_map) {
TQString deviceName;
deviceName = (*pnp_id_map)[pnpid];
return deviceName;
}
else {
return i18n("Unknown PNP Device");
}
}
TQString TDEHardwareDevices::getFriendlyDeviceTypeStringFromType(TDEGenericDeviceType::TDEGenericDeviceType query) {
TQString ret = "Unknown Device";
@ -2528,6 +3137,12 @@ TQString TDEHardwareDevices::getFriendlyDeviceTypeStringFromType(TDEGenericDevic
else if (query == TDEGenericDeviceType::Platform) {
ret = i18n("Platform");
}
else if (query == TDEGenericDeviceType::Event) {
ret = i18n("Platform Event");
}
else if (query == TDEGenericDeviceType::Input) {
ret = i18n("Platform Input");
}
else if (query == TDEGenericDeviceType::PNP) {
ret = i18n("Plug and Play");
}
@ -2656,6 +3271,12 @@ TQPixmap TDEHardwareDevices::getDeviceTypeIconFromType(TDEGenericDeviceType::TDE
else if (query == TDEGenericDeviceType::Platform) {
ret = DesktopIcon("kcmsystem", size);
}
else if (query == TDEGenericDeviceType::Event) {
ret = DesktopIcon("kcmsystem", size);
}
else if (query == TDEGenericDeviceType::Input) {
ret = DesktopIcon("kcmsystem", size);
}
else if (query == TDEGenericDeviceType::PNP) {
ret = DesktopIcon("kcmsystem", size);
}

@ -74,6 +74,8 @@ enum TDEGenericDeviceType {
ThermalControl,
Bridge,
Platform,
Event,
Input,
PNP,
OtherACPI,
OtherUSB,
@ -149,6 +151,7 @@ enum TDEDiskDeviceStatus {
UsedByDevice = 0x00000010,
UsesDevice = 0x00000020,
ContainsFilesystem = 0x00000040,
Hotpluggable = 0x00000080,
Other = 0x80000000
};
@ -168,6 +171,22 @@ inline TDEDiskDeviceStatus operator~(TDEDiskDeviceStatus a)
}
};
class TDECORE_EXPORT TDESensorCluster
{
public:
/**
* Constructor.
*/
TDESensorCluster();
TQString label;
double current;
double minimum;
double maximum;
double warning;
double critical;
};
class TDECORE_EXPORT TDEGenericDevice
{
public:
@ -298,6 +317,26 @@ class TDECORE_EXPORT TDEGenericDevice
*/
void setModelID(TQString id);
/**
* @return a TQString with the encoded vendor, if any
*/
TQString &vendorEncoded();
/**
* @param a TQString with the encoded vendor, if any
*/
void setVendorEncoded(TQString id);
/**
* @return a TQString with the encoded model, if any
*/
TQString &modelEncoded();
/**
* @param a TQString with the encoded model, if any
*/
void setModelEncoded(TQString id);
/**
* @return a TQString with the subvendor ID, if any
*/
@ -396,6 +435,8 @@ class TDECORE_EXPORT TDEGenericDevice
TQString m_uniqueID;
TQString m_vendorID;
TQString m_modelID;
TQString m_vendorenc;
TQString m_modelenc;
TQString m_subvendorID;
TQString m_submodelID;
TQString m_pciClass;
@ -613,10 +654,146 @@ class TDECORE_EXPORT TDEStorageDevice : public TDEGenericDevice
TQStringList m_slaveDevices;
};
class TDECORE_EXPORT TDECPUDevice : public TDEGenericDevice
{
public:
/**
* Constructor.
* @param Device type
*/
TDECPUDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn=TQString::null);
/**
* Destructor.
*/
~TDECPUDevice();
/**
* @return a double with the current CPU frequency in MHz, if available
*/
double &frequency();
/**
* @param a double with the current CPU frequency in MHz, if available
*/
void setFrequency(double fr);
/**
* @return a double with the minimum CPU frequency in MHz, if available
*/
double &minFrequency();
/**
* @param a double with the minimum CPU frequency in MHz, if available
*/
void setMinFrequency(double fr);
/**
* @return a double with the maximum CPU frequency in MHz, if available
*/
double &maxFrequency();
/**
* @param a double with the maximum CPU frequency in MHz, if available
*/
void setMaxFrequency(double fr);
/**
* @return a double with the transition latency in ns, if available
*/
double &transitionLatency();
/**
* @param a double with the transition latency in ns, if available
*/
void setTransitionLatency(double tl);
/**
* @return a TQString with the current CPU governor policy, if available
*/
TQString &governor();
/**
* @param a TQString with the current CPU governor policy, if available
*/
void setGovernor(TQString gr);
/**
* @return a TQString with the current CPU scaling driver, if available
*/
TQString &scalingDriver();
/**
* @param a TQString with the current CPU scaling driver, if available
*/
void setScalingDriver(TQString dr);
/**
* @return a TQStringList with the IDs of all processors that are dependent on the frequency/power settings of this one, if available
*/
TQStringList &dependentProcessors();
/**
* @param a TQStringList with the IDs of all processors that are dependent on the frequency/power settings of this one, if available
*/
void setDependentProcessors(TQStringList dp);
/**
* @return a TQStringList with all valid scaling frequencies in Hz, if available
*/
TQStringList &availableFrequencies();
/**
* @param a TQStringList with all valid scaling frequencies in Hz, if available
*/
void setAvailableFrequencies(TQStringList af);
private:
double m_frequency;
double m_minfrequency;
double m_maxfrequency;
double m_transitionlatency;
TQString m_governor;
TQString m_scalingdriver;
TQStringList m_tiedprocs;
TQStringList m_frequencies;
};
typedef TQMap<TQString, TDESensorCluster> TDESensorClusterMap;
class TDECORE_EXPORT TDESensorDevice : public TDEGenericDevice
{
public:
/**
* Constructor.
* @param Device type
*/
TDESensorDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn=TQString::null);
/**
* Destructor.
*/
~TDESensorDevice();
/**
* @return a TDESensorClusterMap with the current sensor values
*/
TDESensorClusterMap values();
/**
* @param a TDESensorClusterMap with the current sensor values
*/
void setValues(TDESensorClusterMap cl);
private:
TDESensorClusterMap m_sensorValues;
};
typedef TQPtrList<TDEGenericDevice> TDEGenericHardwareList;
typedef TQMap<TQString, TQString> TDEDeviceIDMap;
class TQSocketNotifier;
class KSimpleDirWatch;
class TDECORE_EXPORT TDEHardwareDevices : public TQObject
{
@ -696,6 +873,13 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject
*/
TQString findUSBDeviceName(TQString vendorid, TQString modelid, TQString subvendorid, TQString submodelid);
/**
* Look up the device in the system PNP database
* @param pnpid a TQString containing the PNP ID
* @return a TQString containing the device name, if found
*/
TQString findPNPDeviceName(TQString pnpid);
/**
* Get a friendly string describing a device type
* @param query a TDEGenericDeviceType::TDEGenericDeviceType specifying a device type
@ -720,6 +904,7 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject
private slots:
void processHotPluggedHardware();
void processModifiedMounts();
void processModifiedCPUs();
private:
void rescanDeviceInformation(TDEGenericDevice* hwdevice);
@ -738,14 +923,18 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject
struct udev_monitor *m_udevMonitorStruct;
TDEGenericHardwareList m_deviceList;
int m_procMountsFd;
KSimpleDirWatch* m_cpuWatch;
TQTimer* m_cpuWatchTimer;
TQSocketNotifier* m_devScanNotifier;
TQSocketNotifier* m_mountScanNotifier;
TQStringList m_mountTable;
TQStringList m_cpuInfo;
TDEDeviceIDMap* pci_id_map;
TDEDeviceIDMap* usb_id_map;
TDEDeviceIDMap* pnp_id_map;
friend class TDEGenericDevice;
friend class TDEStorageDevice;

Loading…
Cancel
Save