summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTimothy Pearson <[email protected]>2012-04-02 13:18:59 -0500
committerTimothy Pearson <[email protected]>2012-04-02 13:18:59 -0500
commit5bb9a959afb70b7ad27a331b6088d5bab82b6658 (patch)
tree4362dc738dd14818a29a311e5416ecfa270ba07e
parent607d5f575d500649c354c1e4a8032a17ab06cc79 (diff)
downloadtdelibs-5bb9a959afb70b7ad27a331b6088d5bab82b6658.tar.gz
tdelibs-5bb9a959afb70b7ad27a331b6088d5bab82b6658.zip
Add external textfile device class rule support to TDE hardware library
Move floppy detection to the new system as an example
-rw-r--r--tdecore/hwlibdata/CMakeLists.txt13
-rw-r--r--tdecore/hwlibdata/classrules/CMakeLists.txt17
-rw-r--r--tdecore/hwlibdata/classrules/floppydisk-platform.hwclass9
-rw-r--r--tdecore/hwlibdata/classrules/floppydisk-udev.hwclass9
-rw-r--r--tdecore/tdehardwaredevices.cpp578
-rw-r--r--tdecore/tdehardwaredevices.h48
6 files changed, 596 insertions, 78 deletions
diff --git a/tdecore/hwlibdata/CMakeLists.txt b/tdecore/hwlibdata/CMakeLists.txt
new file mode 100644
index 000000000..d18877c5f
--- /dev/null
+++ b/tdecore/hwlibdata/CMakeLists.txt
@@ -0,0 +1,13 @@
+#################################################
+#
+# (C) 2012 Timothy Pearson
+# kb9vqf (AT) pearsoncomputing.net
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+
+add_subdirectory( classrules )
diff --git a/tdecore/hwlibdata/classrules/CMakeLists.txt b/tdecore/hwlibdata/classrules/CMakeLists.txt
new file mode 100644
index 000000000..3b9452f43
--- /dev/null
+++ b/tdecore/hwlibdata/classrules/CMakeLists.txt
@@ -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
+ floppydisk-platform.hwclass floppydisk-udev.hwclass
+ DESTINATION ${DATA_INSTALL_DIR}/tdehwlib/deviceclasses )
diff --git a/tdecore/hwlibdata/classrules/floppydisk-platform.hwclass b/tdecore/hwlibdata/classrules/floppydisk-platform.hwclass
new file mode 100644
index 000000000..8b038b300
--- /dev/null
+++ b/tdecore/hwlibdata/classrules/floppydisk-platform.hwclass
@@ -0,0 +1,9 @@
+[Conditions]
+DRIVER=floppy
+
+[DeviceType]
+GENTYPE=Disk
+SUBTYPE=Floppy
+
+[DeviceSettings]
+UPDATE_BLACKLISTED=false
diff --git a/tdecore/hwlibdata/classrules/floppydisk-udev.hwclass b/tdecore/hwlibdata/classrules/floppydisk-udev.hwclass
new file mode 100644
index 000000000..6c76d3c85
--- /dev/null
+++ b/tdecore/hwlibdata/classrules/floppydisk-udev.hwclass
@@ -0,0 +1,9 @@
+[Conditions]
+ID_TYPE=floppy
+
+[DeviceType]
+GENTYPE=Disk
+SUBTYPE=Floppy
+
+[DeviceSettings]
+UPDATE_BLACKLISTED=false
diff --git a/tdecore/tdehardwaredevices.cpp b/tdecore/tdehardwaredevices.cpp
index 86fc16820..3c037a3b7 100644
--- a/tdecore/tdehardwaredevices.cpp
+++ b/tdecore/tdehardwaredevices.cpp
@@ -24,7 +24,9 @@
#include <tqsocketnotifier.h>
#include <kglobal.h>
+#include <kconfig.h>
#include <ktempfile.h>
+#include <kstandarddirs.h>
#include <libudev.h>
@@ -41,6 +43,8 @@
TDEGenericDevice::TDEGenericDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) {
m_deviceType = dt;
m_deviceName = dn;
+
+ m_blacklistedForUpdate = false;
}
TDEGenericDevice::~TDEGenericDevice() {
@@ -103,7 +107,33 @@ TQString TDEGenericDevice::uniqueID() {
return m_uniqueID;
}
+TQString &TDEGenericDevice::vendorID() {
+ return m_vendorID;
+}
+
+void TDEGenericDevice::setVendorID(TQString id) {
+ m_vendorID = id;
+}
+
+TQString &TDEGenericDevice::modelID() {
+ return m_modelID;
+}
+
+void TDEGenericDevice::setModelID(TQString id) {
+ m_modelID = id;
+}
+
+bool TDEGenericDevice::blacklistedForUpdate() {
+ return m_blacklistedForUpdate;
+}
+
+void TDEGenericDevice::setBlacklistedForUpdate(bool bl) {
+ m_blacklistedForUpdate = bl;
+}
+
TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true) {
+ m_diskType = TDEDiskDeviceType::Null;
+ m_diskStatus = TDEDiskDeviceStatus::Null;
}
TDEStorageDevice::~TDEStorageDevice() {
@@ -118,7 +148,7 @@ void TDEStorageDevice::setDiskType(TDEDiskDeviceType::TDEDiskDeviceType dt) {
}
bool TDEStorageDevice::isDiskOfType(TDEDiskDeviceType::TDEDiskDeviceType tf) {
- return ((m_diskType&tf)!=(TDEDiskDeviceType::TDEDiskDeviceType)0);
+ return ((m_diskType&tf)!=TDEDiskDeviceType::Null);
}
TDEDiskDeviceStatus::TDEDiskDeviceStatus TDEStorageDevice::diskStatus() {
@@ -483,7 +513,7 @@ TDEHardwareDevices::~TDEHardwareDevices() {
void TDEHardwareDevices::rescanDeviceInformation(TDEGenericDevice* hwdevice) {
struct udev_device *dev;
dev = udev_device_new_from_syspath(m_udevStruct, hwdevice->systemPath().ascii());
- classifyUnknownDevice(dev, hwdevice);
+ classifyUnknownDevice(dev, hwdevice, false);
udev_device_unref(dev);
}
@@ -580,19 +610,9 @@ void TDEHardwareDevices::processHotPluggedHardware() {
TDEGenericDevice *hwdevice;
for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) {
if (hwdevice->systemPath() == systempath) {
- // HACK
- // I am lucky enough to have a Flash drive that spams udev continually with device change events
- // I imagine I am not the only one, so here is a section in which specific devices can be blacklisted!
- bool blacklisted = false;
-
- // For "U3 System" fake CD
- if ((TQString(udev_device_get_property_value(dev, "ID_VENDOR_ID")) == "08ec") && (TQString(udev_device_get_property_value(dev, "ID_MODEL_ID")) == "0020") && (TQString(udev_device_get_property_value(dev, "ID_TYPE")) == "cd")); {
- blacklisted = true;
- }
-
- if (!blacklisted) {
- classifyUnknownDevice(dev, hwdevice);
- emit hardwareUpdated(hwdevice);
+ if (!hwdevice->blacklistedForUpdate()) {
+ classifyUnknownDevice(dev, hwdevice, false);
+ emit hardwareUpdated(hwdevice);
}
break;
}
@@ -680,7 +700,7 @@ void TDEHardwareDevices::processModifiedMounts() {
TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, 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::TDEDiskDeviceType)0;
+ TDEDiskDeviceType::TDEDiskDeviceType disktype = TDEDiskDeviceType::Null;
if (devicebus.upper() == "USB") {
disktype = disktype | TDEDiskDeviceType::USB;
@@ -700,13 +720,6 @@ TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, const TQ
disktype = disktype | TDEDiskDeviceType::MediaDevice;
}
- if (disktypestring.upper() == "FLOPPY") {
- disktype = disktype | TDEDiskDeviceType::Floppy;
- }
- if (devicedriver.upper() == "FLOPPY") {
- disktype = disktype | TDEDiskDeviceType::Floppy;
- }
-
if (disktypestring.upper() == "TAPE") {
disktype = disktype | TDEDiskDeviceType::Tape;
}
@@ -800,6 +813,7 @@ TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, const TQ
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;
}
+ disktype = disktype | TDEDiskDeviceType::Optical;
}
// Detect RAM and Loop devices, since udev can't seem to...
@@ -820,7 +834,332 @@ TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, const TQ
return disktype;
}
-TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice) {
+ // KStandardDirs::kde_default
+
+typedef TQMap<TQString, TQString> KConfigMap;
+
+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 == "CPU") {
+ ret = TDEGenericDeviceType::CPU;
+ }
+ else if (query == "GPU") {
+ ret = TDEGenericDeviceType::GPU;
+ }
+ else if (query == "RAM") {
+ ret = TDEGenericDeviceType::RAM;
+ }
+ else if (query == "Mainboard") {
+ ret = TDEGenericDeviceType::Mainboard;
+ }
+ else if (query == "Disk") {
+ ret = TDEGenericDeviceType::Disk;
+ }
+ 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 == "Network") {
+ ret = TDEGenericDeviceType::Network;
+ }
+ else if (query == "Printer") {
+ ret = TDEGenericDeviceType::Printer;
+ }
+ else if (query == "Scanner") {
+ ret = TDEGenericDeviceType::Scanner;
+ }
+ else if (query == "Sound") {
+ ret = TDEGenericDeviceType::Sound;
+ }
+ else if (query == "IEEE1394") {
+ ret = TDEGenericDeviceType::IEEE1394;
+ }
+ else if (query == "Camera") {
+ ret = TDEGenericDeviceType::Camera;
+ }
+ else if (query == "TextIO") {
+ ret = TDEGenericDeviceType::TextIO;
+ }
+ else if (query == "Peripheral") {
+ ret = TDEGenericDeviceType::Peripheral;
+ }
+ else if (query == "Battery") {
+ ret = TDEGenericDeviceType::Battery;
+ }
+ else if (query == "Power") {
+ ret = TDEGenericDeviceType::Power;
+ }
+ else if (query == "ThermalSensor") {
+ ret = TDEGenericDeviceType::ThermalSensor;
+ }
+ else if (query == "ThermalControl") {
+ ret = TDEGenericDeviceType::ThermalControl;
+ }
+ else if (query == "OtherACPI") {
+ ret = TDEGenericDeviceType::OtherACPI;
+ }
+ else if (query == "OtherUSB") {
+ ret = TDEGenericDeviceType::OtherUSB;
+ }
+ else if (query == "OtherPeripheral") {
+ ret = TDEGenericDeviceType::OtherPeripheral;
+ }
+ else if (query == "OtherSensor") {
+ ret = TDEGenericDeviceType::OtherSensor;
+ }
+ 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 == "CDRW") {
+ ret = ret | TDEDiskDeviceType::CDRW;
+ }
+ if (query == "DVDROM") {
+ ret = ret | TDEDiskDeviceType::DVDROM;
+ }
+ if (query == "DVDRAM") {
+ ret = ret | TDEDiskDeviceType::DVDRAM;
+ }
+ if (query == "DVDRW") {
+ ret = ret | TDEDiskDeviceType::DVDRW;
+ }
+ if (query == "BDROM") {
+ ret = ret | TDEDiskDeviceType::BDROM;
+ }
+ if (query == "BDRW") {
+ ret = ret | TDEDiskDeviceType::BDRW;
+ }
+ 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\r", device->m_externalRulesFile.ascii(), device->systemPath().ascii()); fflush(stdout);
+ sdevice->setDiskType(desiredSubdeviceType);
+ }
+ }
+ }
+ }
+ }
+ else {
+ TQStringList hardware_info_directories(KGlobal::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 KConfig() 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 (KGlobal::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
+ KConfig rulesFile(fi->absFilePath(), true, false);
+ rulesFile.setGroup("Conditions");
+ KConfigMap conditionmap = rulesFile.entryMap("Conditions");
+ KConfigMap::Iterator cndit;
+ for (cndit = conditionmap.begin(); cndit != conditionmap.end(); ++cndit) {
+ TQStringList conditionList = TQStringList::split(',', cndit.data(), false);
+ bool atleastonematch = false;
+ for ( TQStringList::Iterator paramit = conditionList.begin(); paramit != conditionList.end(); ++paramit ) {
+ if (cndit.key() == "VENDOR_ID") {
+ if (device->vendorID() == (*paramit)) {
+ atleastonematch = true;
+ }
+ }
+ else if (cndit.key() == "MODEL_ID") {
+ if (device->modelID() == (*paramit)) {
+ atleastonematch = true;
+ }
+ }
+ else if (readUdevAttribute(dev, cndit.key()) == (*paramit)) {
+ atleastonematch = true;
+ }
+ }
+ if (!atleastonematch) {
+ 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\r", 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->setBlacklistedForUpdate(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 TDEW device object
TQString devicename(udev_device_get_sysname(dev));
TQString devicetype(udev_device_get_devtype(dev));
@@ -828,6 +1167,8 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
TQString devicesubsystem(udev_device_get_subsystem(dev));
TQString devicenode(udev_device_get_devnode(dev));
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"));
bool removable = false;
TDEGenericDevice* device = existingdevice;
@@ -836,10 +1177,124 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
// 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
+ // Many devices do not provide their vendor/model ID via udev
+ // Go after it manually...
+ if (devicevendorid.isNull() || devicemodelid.isNull()) {
+ bool done = false;
+ TQString current_path = systempath;
+ TQString modalias_string = TQString::null;;
+
+ while (done == false) {
+ TQString malnodename = current_path;
+ malnodename.append("/modalias");
+ TQFile malfile(malnodename);
+ if (malfile.open(IO_ReadOnly)) {
+ TQTextStream stream( &malfile );
+ modalias_string = stream.readLine();
+ malfile.close();
+ }
+ if (modalias_string.startsWith("pci") || modalias_string.startsWith("usb")) {
+ done = true;
+ }
+ else {
+ modalias_string = TQString::null;
+ current_path.truncate(current_path.findRev("/"));
+ if (!current_path.startsWith("/sys/devices")) {
+ // Abort!
+ done = true;
+ }
+ }
+ }
+
+ if (modalias_string != TQString::null) {
+ int vloc = modalias_string.find("v");
+ int dloc = modalias_string.find("d", vloc);
+ // For added fun the device string lengths differ between pci and usb
+ if (modalias_string.startsWith("pci")) {
+ devicevendorid = modalias_string.mid(vloc+1, 8).lower();
+ devicemodelid = modalias_string.mid(dloc+1, 8).lower();
+ devicevendorid.remove(0,4);
+ devicemodelid.remove(0,4);
+ }
+ if (modalias_string.startsWith("usb")) {
+ devicevendorid = modalias_string.mid(vloc+1, 4).lower();
+ devicemodelid = modalias_string.mid(dloc+1, 4).lower();
+ }
+ }
+ }
+
+ // Classify generic device type and create appropriate object
if ((devicetype == "disk")
|| (devicetype == "partition")
|| (devicedriver == "floppy")
) {
+ if (!device) device = new TDEStorageDevice(TDEGenericDeviceType::Disk);
+ }
+ else if (devicetype.isNull()) {
+ if (devicesubsystem == "acpi") {
+ 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 (!device) device = new TDEGenericDevice(TDEGenericDeviceType::TextIO);
+ }
+ 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 TDEGenericDevice(TDEGenericDeviceType::OtherSensor);
+ }
+ }
+
+ if (device == 0) {
+ // Unhandled
+ if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Other);
+ printf("[FIXME] UNCLASSIFIED DEVICE name: %s type: %s subsystem: %s driver: %s [Node Path: %s] [Syspath: %s] [%s:%s]\n\r", devicename.ascii(), devicetype.ascii(), devicesubsystem.ascii(), devicedriver.ascii(), devicenode.ascii(), udev_device_get_syspath(dev), devicevendorid.ascii(), devicemodelid.ascii()); fflush(stdout);
+ }
+
+ // Set preliminary basic device information
+ device->setName(devicename);
+ device->setDeviceNode(devicenode);
+ device->setSystemPath(systempath);
+ device->setVendorID(devicevendorid);
+ device->setModelID(devicemodelid);
+
+ updateBlacklists(device, dev);
+
+ if (force_full_classification) {
+ // Check external rules for possible device type overrides
+ device = classifyUnknownDeviceByExternalRules(dev, device, false);
+ }
+
+ if (device->type() == TDEGenericDeviceType::Disk) {
// Determine if disk is removable
TQString removablenodename = udev_device_get_syspath(dev);
removablenodename.append("/removable");
@@ -891,8 +1346,6 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
}
}
- if (!device) device = new TDEStorageDevice(TDEGenericDeviceType::Disk);
-
// Determine generic disk information
TQString devicevendor(udev_device_get_property_value(dev, "ID_VENDOR"));
TQString devicemodel(udev_device_get_property_value(dev, "ID_MODEL"));
@@ -911,10 +1364,15 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(device);
- TDEDiskDeviceType::TDEDiskDeviceType disktype = (TDEDiskDeviceType::TDEDiskDeviceType)0;
- TDEDiskDeviceStatus::TDEDiskDeviceStatus diskstatus = (TDEDiskDeviceStatus::TDEDiskDeviceStatus)0;
+ TDEDiskDeviceType::TDEDiskDeviceType disktype = sdevice->diskType();
+ TDEDiskDeviceStatus::TDEDiskDeviceStatus diskstatus = sdevice->diskStatus();
- disktype = classifyDiskType(dev, devicebus, disktypestring, systempath, devicevendor, devicemodel, filesystemtype, devicedriver);
+ if (force_full_classification) {
+ disktype = classifyDiskType(dev, devicebus, disktypestring, systempath, devicevendor, devicemodel, filesystemtype, devicedriver);
+ sdevice->setDiskType(disktype);
+ device = classifyUnknownDeviceByExternalRules(dev, device, true); // Check external rules for possible subtype overrides
+ disktype = sdevice->diskType(); // The type can be overridden by an external rule
+ }
if (disktype & TDEDiskDeviceType::Floppy) {
// Floppy drives don't work well under udev
@@ -1062,62 +1520,28 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD
sdevice->setDiskLabel(disklabel);
}
- else if (devicetype.isNull()) {
- if (devicesubsystem == "acpi") {
- 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 (!device) device = new TDEGenericDevice(TDEGenericDeviceType::TextIO);
- }
- 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 TDEGenericDevice(TDEGenericDeviceType::OtherSensor);
- }
- }
- if (device == 0) {
- // Unhandled
- if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Other);
- printf("[FIXME] UNCLASSIFIED DEVICE name: %s type: %s subsystem: %s driver: %s [Node Path: %s] [Syspath: %s]\n\r", devicename.ascii(), devicetype.ascii(), devicesubsystem.ascii(), devicedriver.ascii(), devicenode.ascii(), udev_device_get_syspath(dev)); fflush(stdout);
- }
+ // 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);
return device;
}
+void TDEHardwareDevices::updateBlacklists(TDEGenericDevice* hwdevice, udev_device* dev) {
+ // HACK
+ // I am lucky enough to have a Flash drive that spams udev continually with device change events
+ // I imagine I am not the only one, so here is a section in which specific devices can be blacklisted!
+
+ // For "U3 System" fake CD
+ if ((hwdevice->vendorID() == "08ec") && (hwdevice->modelID() == "0020") && (TQString(udev_device_get_property_value(dev, "ID_TYPE")) == "cd")) {
+ hwdevice->setBlacklistedForUpdate(true);
+ }
+}
+
bool TDEHardwareDevices::queryHardwareInformation() {
if (!m_udevStruct) {
return false;
diff --git a/tdecore/tdehardwaredevices.h b/tdecore/tdehardwaredevices.h
index c6cf43cac..5f594a8ab 100644
--- a/tdecore/tdehardwaredevices.h
+++ b/tdecore/tdehardwaredevices.h
@@ -38,6 +38,7 @@
* @author Timothy Pearson
*/
+// Keep readGenericDeviceTypeFromString() in tdehardwaredevices.cpp in sync with this enum
namespace TDEGenericDeviceType {
enum TDEGenericDeviceType {
CPU,
@@ -69,8 +70,10 @@ enum TDEGenericDeviceType {
};
};
+// Keep readDiskDeviceSubtypeFromString() in tdehardwaredevices.cpp in sync with this enum
namespace TDEDiskDeviceType {
enum TDEDiskDeviceType {
+ Null = 0x00000000,
MediaDevice = 0x00000001,
Floppy = 0x00000002,
CDROM = 0x00000004,
@@ -122,6 +125,7 @@ inline TDEDiskDeviceType operator~(TDEDiskDeviceType a)
namespace TDEDiskDeviceStatus {
enum TDEDiskDeviceStatus {
+ Null = 0x00000000,
Mountable = 0x00000001,
Removable = 0x00000002,
Inserted = 0x00000004,
@@ -236,10 +240,40 @@ class TDECORE_EXPORT TDEGenericDevice
void setDeviceNode(TQString sn);
/**
+ * @return true if this device has been blacklisted for update actions
+ */
+ bool blacklistedForUpdate();
+
+ /**
+ * @param bl true if this device has been blacklisted for update actions
+ */
+ void setBlacklistedForUpdate(bool bl);
+
+ /**
* @return a TQString containing a unique identifier for this device
*/
TQString uniqueID();
+ /**
+ * @return a TQString with the vendor ID, if any
+ */
+ TQString &vendorID();
+
+ /**
+ * @param a TQString with the vendor ID, if any
+ */
+ void setVendorID(TQString id);
+
+ /**
+ * @return a TQString with the model ID, if any
+ */
+ TQString &modelID();
+
+ /**
+ * @param a TQString with the model ID, if any
+ */
+ void setModelID(TQString id);
+
private:
TDEGenericDeviceType::TDEGenericDeviceType m_deviceType;
TQString m_deviceName;
@@ -249,6 +283,15 @@ class TDECORE_EXPORT TDEGenericDevice
TQString m_vendorModel;
TQString m_deviceBus;
TQString m_uniqueID;
+ TQString m_vendorID;
+ TQString m_modelID;
+ bool m_blacklistedForUpdate;
+
+ // Internal use only!
+ TQStringList m_externalSubtype;
+ TQString m_externalRulesFile;
+
+ friend class TDEHardwareDevices;
};
class TDECORE_EXPORT TDEStorageDevice : public TDEGenericDevice
@@ -495,9 +538,11 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject
private:
void rescanDeviceInformation(TDEGenericDevice* hwdevice);
+ void updateBlacklists(TDEGenericDevice* hwdevice, udev_device* dev);
private:
- TDEGenericDevice *classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice=0);
+ TDEGenericDevice *classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice=0, bool force_full_classification=true);
+ TDEGenericDevice *classifyUnknownDeviceByExternalRules(udev_device* dev, TDEGenericDevice* existingdevice=0, bool classifySubDevices=false);
struct udev *m_udevStruct;
struct udev_monitor *m_udevMonitorStruct;
@@ -509,6 +554,7 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject
TQStringList m_mountTable;
+ friend class TDEGenericDevice;
friend class TDEStorageDevice;
};