From 11b3e922164fb9ca4f8d958aa26a117c54faa621 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 14 Apr 2012 19:13:58 -0500 Subject: Add ability to read switch states --- tdecore/tdehardwaredevices.cpp | 317 ++++++++++++++++++++++++++++++++++++++--- tdecore/tdehardwaredevices.h | 121 +++++++++++++++- 2 files changed, 417 insertions(+), 21 deletions(-) (limited to 'tdecore') diff --git a/tdecore/tdehardwaredevices.cpp b/tdecore/tdehardwaredevices.cpp index 14501d2c8..3c1afe44a 100644 --- a/tdecore/tdehardwaredevices.cpp +++ b/tdecore/tdehardwaredevices.cpp @@ -44,6 +44,9 @@ // Backlight devices #include +// Input devices +#include + // Network devices #include #include @@ -53,7 +56,6 @@ #include #include - // BEGIN BLOCK // Copied from include/linux/genhd.h #define GENHD_FL_REMOVABLE 1 @@ -81,6 +83,8 @@ unsigned int reverse_bits(register unsigned int x) return((x >> 16) | (x << 16)); } +#define BIT_IS_SET(bits, n) (bits[n >> 3] & (1 << (n & 0x7))) + TDESensorCluster::TDESensorCluster() { label = TQString::null; current = -1; @@ -1501,9 +1505,13 @@ void TDEMonitorDevice::internalSetPowerLevel(TDEDisplayPowerLevel::TDEDisplayPow } TDEEventDevice::TDEEventDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn) { + m_fd = -1; } TDEEventDevice::~TDEEventDevice() { + if (m_fd >= 0) { + close(m_fd); + } } TDEEventDeviceType::TDEEventDeviceType TDEEventDevice::eventType() { @@ -1514,6 +1522,89 @@ void TDEEventDevice::internalSetEventType(TDEEventDeviceType::TDEEventDeviceType m_eventType = et; } +TDESwitchType::TDESwitchType TDEEventDevice::providedSwitches() { + return m_providedSwitches; +} + +void TDEEventDevice::internalSetProvidedSwitches(TDESwitchType::TDESwitchType sl) { + m_providedSwitches = sl; +} + +TDESwitchType::TDESwitchType TDEEventDevice::activeSwitches() { + return m_switchActive; +} + +void TDEEventDevice::internalSetActiveSwitches(TDESwitchType::TDESwitchType sl) { + m_switchActive = sl; +} + +// Keep this in sync with the TDESwitchType definition in the header +TQStringList TDEEventDevice::friendlySwitchList(TDESwitchType::TDESwitchType switches) { + TQStringList ret; + + if (switches & TDESwitchType::Lid) { + ret.append(i18n("Lid Switch")); + } + if (switches & TDESwitchType::TabletMode) { + ret.append(i18n("Tablet Mode")); + } + if (switches & TDESwitchType::HeadphoneInsert) { + ret.append(i18n("Headphone Inserted")); + } + if (switches & TDESwitchType::RFKill) { + ret.append(i18n("Radio Frequency Device Kill Switch")); + } + if (switches & TDESwitchType::Radio) { + ret.append(i18n("Enable Radio")); + } + if (switches & TDESwitchType::MicrophoneInsert) { + ret.append(i18n("Microphone Inserted")); + } + if (switches & TDESwitchType::Dock) { + ret.append(i18n("Docked")); + } + if (switches & TDESwitchType::LineOutInsert) { + ret.append(i18n("Line Out Inserted")); + } + if (switches & TDESwitchType::JackPhysicalInsert) { + ret.append(i18n("Physical Jack Inserted")); + } + if (switches & TDESwitchType::VideoOutInsert) { + ret.append(i18n("Video Out Inserted")); + } + if (switches & TDESwitchType::CameraLensCover) { + ret.append(i18n("Camera Lens Cover")); + } + if (switches & TDESwitchType::KeypadSlide) { + ret.append(i18n("Keypad Slide")); + } + if (switches & TDESwitchType::FrontProximity) { + ret.append(i18n("Front Proximity")); + } + if (switches & TDESwitchType::RotateLock) { + ret.append(i18n("Rotate Lock")); + } + if (switches & TDESwitchType::LineInInsert) { + ret.append(i18n("Line In Inserted")); + } + + return ret; +} + +TDEInputDevice::TDEInputDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn) { +} + +TDEInputDevice::~TDEInputDevice() { +} + +TDEInputDeviceType::TDEInputDeviceType TDEInputDevice::inputType() { + return m_inputType; +} + +void TDEInputDevice::internalSetInputType(TDEInputDeviceType::TDEInputDeviceType it) { + m_inputType = it; +} + TDEHardwareDevices::TDEHardwareDevices() { // Initialize members pci_id_map = 0; @@ -1653,6 +1744,19 @@ TDEGenericDevice* TDEHardwareDevices::findBySystemPath(TQString syspath) { 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() ) { @@ -1919,7 +2023,7 @@ void TDEHardwareDevices::processStatelessDevices() { // 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)) { + if ((hwdevice->type() == TDEGenericDeviceType::RootSystem) || (hwdevice->type() == TDEGenericDeviceType::Network) || (hwdevice->type() == TDEGenericDeviceType::OtherSensor) || (hwdevice->type() == TDEGenericDeviceType::Event)) { rescanDeviceInformation(hwdevice); emit hardwareUpdated(hwdevice); } @@ -2553,22 +2657,58 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDeviceByExternalRules(udev_ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice, bool force_full_classification) { // Classify device and create TDEHW device object - TQString devicename(udev_device_get_sysname(dev)); - TQString devicetype(udev_device_get_devtype(dev)); - TQString devicedriver(udev_device_get_driver(dev)); - 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")); - 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")); + 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; + 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)); + 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(); + } + } // FIXME // Only a small subset of devices are classified right now @@ -2676,7 +2816,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD } // Pull out all input special devices and stuff them under Input if (syspath_tail.startsWith("input")) { - if (!device) device = new TDEGenericDevice(TDEGenericDeviceType::Input); + if (!device) device = new TDEInputDevice(TDEGenericDeviceType::Input); } // Check for keyboard @@ -3753,7 +3893,7 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD // Get current hibernation method line.truncate(line.findRev("]")); line.remove(0, line.findRev("[")+1); - TDESystemHibernationMethod::TDESystemHibernationMethod hibernationmethod = TDESystemHibernationMethod::None; + TDESystemHibernationMethod::TDESystemHibernationMethod hibernationmethod = TDESystemHibernationMethod::Unsupported; if (line.contains("platform")) { hibernationmethod = TDESystemHibernationMethod::Platform; } @@ -3781,8 +3921,11 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD } } + // NOTE + // Keep these two handlers (Event and Input) in sync! + if (device->type() == TDEGenericDeviceType::Event) { - // Try to obtain as much generic information about this event device as possible + // Try to obtain as much type information about this event device as possible TDEEventDevice* edevice = dynamic_cast(device); if (edevice->systemPath().contains("PNP0C0D")) { edevice->internalSetEventType(TDEEventDeviceType::ACPILidSwitch); @@ -3798,6 +3941,135 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD } } + if (device->type() == TDEGenericDeviceType::Input) { + // Try to obtain as much type information about this input device as possible + TDEInputDevice* idevice = dynamic_cast(device); + if (idevice->systemPath().contains("PNP0C0D")) { + idevice->internalSetInputType(TDEInputDeviceType::ACPILidSwitch); + } + else if (idevice->systemPath().contains("PNP0C0E")) { + idevice->internalSetInputType(TDEInputDeviceType::ACPISleepButton); + } + else if (idevice->systemPath().contains("PNP0C0C")) { + idevice->internalSetInputType(TDEInputDeviceType::ACPIPowerButton); + } + else { + idevice->internalSetInputType(TDEInputDeviceType::Unknown); + } + } + + if (device->type() == TDEGenericDeviceType::Event) { + // Try to obtain as much specific information about this event device as possible + TDEEventDevice* edevice = dynamic_cast(device); + int r; + char switches[SW_CNT]; + + // Figure out which switch types are supported, if any + TDESwitchType::TDESwitchType supportedSwitches = TDESwitchType::Null; + if (edevice->m_fd < 0) { + edevice->m_fd = open(edevice->deviceNode().ascii(), O_RDONLY); + } + r = ioctl(edevice->m_fd, EVIOCGBIT(EV_SW, sizeof(switches)), switches); + if (r > 0) { + if (BIT_IS_SET(switches, SW_LID)) { + supportedSwitches = supportedSwitches | TDESwitchType::Lid; + } + if (BIT_IS_SET(switches, SW_TABLET_MODE)) { + supportedSwitches = supportedSwitches | TDESwitchType::TabletMode; + } + if (BIT_IS_SET(switches, SW_RFKILL_ALL)) { + supportedSwitches = supportedSwitches | TDESwitchType::RFKill; + } + if (BIT_IS_SET(switches, SW_RADIO)) { + supportedSwitches = supportedSwitches | TDESwitchType::Radio; + } + if (BIT_IS_SET(switches, SW_MICROPHONE_INSERT)) { + supportedSwitches = supportedSwitches | TDESwitchType::MicrophoneInsert; + } + if (BIT_IS_SET(switches, SW_DOCK)) { + supportedSwitches = supportedSwitches | TDESwitchType::Dock; + } + if (BIT_IS_SET(switches, SW_LINEOUT_INSERT)) { + supportedSwitches = supportedSwitches | TDESwitchType::LineOutInsert; + } + if (BIT_IS_SET(switches, SW_JACK_PHYSICAL_INSERT)) { + supportedSwitches = supportedSwitches | TDESwitchType::JackPhysicalInsert; + } + if (BIT_IS_SET(switches, SW_VIDEOOUT_INSERT)) { + supportedSwitches = supportedSwitches | TDESwitchType::VideoOutInsert; + } +#if 0 // Some old kernels don't provide these defines... [FIXME] + if (BIT_IS_SET(switches, SW_CAMERA_LENS_COVER)) { + supportedSwitches = supportedSwitches | TDESwitchType::CameraLensCover; + } + if (BIT_IS_SET(switches, SW_KEYPAD_SLIDE)) { + supportedSwitches = supportedSwitches | TDESwitchType::KeypadSlide; + } + if (BIT_IS_SET(switches, SW_FRONT_PROXIMITY)) { + supportedSwitches = supportedSwitches | TDESwitchType::FrontProximity; + } + if (BIT_IS_SET(switches, SW_ROTATE_LOCK)) { + supportedSwitches = supportedSwitches | TDESwitchType::RotateLock; + } + if (BIT_IS_SET(switches, SW_LINEIN_INSERT)) { + supportedSwitches = supportedSwitches | TDESwitchType::LineInInsert; + } +#endif + } + edevice->internalSetProvidedSwitches(supportedSwitches); + + // Figure out which switch types are active, if any + TDESwitchType::TDESwitchType activeSwitches = TDESwitchType::Null; + r = ioctl(edevice->m_fd, EVIOCGSW(sizeof(switches)), switches); + if (r > 0) { + if (BIT_IS_SET(switches, SW_LID)) { + activeSwitches = activeSwitches | TDESwitchType::Lid; + } + if (BIT_IS_SET(switches, SW_TABLET_MODE)) { + activeSwitches = activeSwitches | TDESwitchType::TabletMode; + } + if (BIT_IS_SET(switches, SW_RFKILL_ALL)) { + activeSwitches = activeSwitches | TDESwitchType::RFKill; + } + if (BIT_IS_SET(switches, SW_RADIO)) { + activeSwitches = activeSwitches | TDESwitchType::Radio; + } + if (BIT_IS_SET(switches, SW_MICROPHONE_INSERT)) { + activeSwitches = activeSwitches | TDESwitchType::MicrophoneInsert; + } + if (BIT_IS_SET(switches, SW_DOCK)) { + activeSwitches = activeSwitches | TDESwitchType::Dock; + } + if (BIT_IS_SET(switches, SW_LINEOUT_INSERT)) { + activeSwitches = activeSwitches | TDESwitchType::LineOutInsert; + } + if (BIT_IS_SET(switches, SW_JACK_PHYSICAL_INSERT)) { + activeSwitches = activeSwitches | TDESwitchType::JackPhysicalInsert; + } + if (BIT_IS_SET(switches, SW_VIDEOOUT_INSERT)) { + activeSwitches = activeSwitches | TDESwitchType::VideoOutInsert; + } +#if 0 // Some old kernels don't provide these defines... [FIXME] + if (BIT_IS_SET(switches, SW_CAMERA_LENS_COVER)) { + activeSwitches = activeSwitches | TDESwitchType::CameraLensCover; + } + if (BIT_IS_SET(switches, SW_KEYPAD_SLIDE)) { + activeSwitches = activeSwitches | TDESwitchType::KeypadSlide; + } + if (BIT_IS_SET(switches, SW_FRONT_PROXIMITY)) { + activeSwitches = activeSwitches | TDESwitchType::FrontProximity; + } + if (BIT_IS_SET(switches, SW_ROTATE_LOCK)) { + activeSwitches = activeSwitches | TDESwitchType::RotateLock; + } + if (BIT_IS_SET(switches, SW_LINEIN_INSERT)) { + activeSwitches = activeSwitches | TDESwitchType::LineInInsert; + } +#endif + } + edevice->internalSetActiveSwitches(activeSwitches); + } + // Root devices are still special if ((device->type() == TDEGenericDeviceType::Root) || (device->type() == TDEGenericDeviceType::RootSystem)) { systempath = device->systemPath(); @@ -3817,6 +4089,11 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD device->internalSetSubsystem(devicesubsystem); device->internalSetPCIClass(devicepciclass); + // Internal use only! + device->m_udevtype = devicetype; + device->m_udevdevicetypestring = devicetypestring; + device->udevdevicetypestring_alt = devicetypestring_alt; + return device; } diff --git a/tdecore/tdehardwaredevices.h b/tdecore/tdehardwaredevices.h index 69c7e9db1..f3c11126f 100644 --- a/tdecore/tdehardwaredevices.h +++ b/tdecore/tdehardwaredevices.h @@ -485,6 +485,9 @@ class TDECORE_EXPORT TDEGenericDevice // Internal use only! TQStringList m_externalSubtype; TQString m_externalRulesFile; + TQString m_udevtype; + TQString m_udevdevicetypestring; + TQString udevdevicetypestring_alt; friend class TDEHardwareDevices; }; @@ -1484,7 +1487,7 @@ enum TDESystemPowerState { namespace TDESystemHibernationMethod { enum TDESystemHibernationMethod { - None, + Unsupported, Platform, Shutdown, Reboot, @@ -1622,6 +1625,43 @@ enum TDEEventDeviceType { }; }; +// Keep friendlySwitchList() in tdehardwaredevices.cpp in sync with this enum +namespace TDESwitchType { +enum TDESwitchType { + Null = 0x00000000, + Lid = 0x00000001, + TabletMode = 0x00000002, + HeadphoneInsert = 0x00000004, + RFKill = 0x00000008, + Radio = 0x00000010, + MicrophoneInsert = 0x00000020, + Dock = 0x00000040, + LineOutInsert = 0x00000080, + JackPhysicalInsert = 0x00000100, + VideoOutInsert = 0x00000200, + CameraLensCover = 0x00000400, + KeypadSlide = 0x00000800, + FrontProximity = 0x00001000, + RotateLock = 0x00002000, + LineInInsert = 0x00004000 +}; + +inline TDESwitchType operator|(TDESwitchType a, TDESwitchType b) +{ + return static_cast(static_cast(a) | static_cast(b)); +} + +inline TDESwitchType operator&(TDESwitchType a, TDESwitchType b) +{ + return static_cast(static_cast(a) & static_cast(b)); +} + +inline TDESwitchType operator~(TDESwitchType a) +{ + return static_cast(~static_cast(a)); +} +}; + class TDECORE_EXPORT TDEEventDevice : public TDEGenericDevice { public: @@ -1641,6 +1681,22 @@ class TDECORE_EXPORT TDEEventDevice : public TDEGenericDevice */ TDEEventDeviceType::TDEEventDeviceType eventType(); + /** + * @return a TDESwitchType::TDESwitchType with all switches provided by this device + */ + TDESwitchType::TDESwitchType providedSwitches(); + + /** + * @return a TDESwitchType::TDESwitchType with all active switches provided by this device + */ + TDESwitchType::TDESwitchType activeSwitches(); + + /** + * @param switches a TDESwitchType::TDESwitchType with any switch flags set + * @return a TQStringList with friendly names for all set switch flags + */ + static TQStringList friendlySwitchList(TDESwitchType::TDESwitchType switches); + protected: /** * @param et a TDEEventDeviceType::TDEEventDeviceType with the event device type, if known @@ -1648,12 +1704,69 @@ class TDECORE_EXPORT TDEEventDevice : public TDEGenericDevice */ void internalSetEventType(TDEEventDeviceType::TDEEventDeviceType et); + /** + * @param sl a TDESwitchType::TDESwitchType with all switches provided by this device + * @internal + */ + void internalSetProvidedSwitches(TDESwitchType::TDESwitchType sl); + + /** + * @param sl a TDESwitchType::TDESwitchType with all active switches provided by this device + * @internal + */ + void internalSetActiveSwitches(TDESwitchType::TDESwitchType sl); + private: TDEEventDeviceType::TDEEventDeviceType m_eventType; + TDESwitchType::TDESwitchType m_providedSwitches; + TDESwitchType::TDESwitchType m_switchActive; + + int m_fd; friend class TDEHardwareDevices; }; +namespace TDEInputDeviceType { +enum TDEInputDeviceType { + Unknown, + ACPILidSwitch, + ACPISleepButton, + ACPIPowerButton, + Other = 0x80000000 +}; +}; + +class TDECORE_EXPORT TDEInputDevice : public TDEGenericDevice +{ + public: + /** + * Constructor. + * @param Device type + */ + TDEInputDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn=TQString::null); + + /** + * Destructor. + */ + ~TDEInputDevice(); + + /** + * @return a TDEInputDeviceType::TDEInputDeviceType with the input device type, if known + */ + TDEInputDeviceType::TDEInputDeviceType inputType(); + + protected: + /** + * @param it a TDEInputDeviceType::TDEInputDeviceType with the input device type, if known + * @internal + */ + void internalSetInputType(TDEInputDeviceType::TDEInputDeviceType it); + + private: + TDEInputDeviceType::TDEInputDeviceType m_inputType; + + friend class TDEHardwareDevices; +}; typedef TQPtrList TDEGenericHardwareList; typedef TQMap TDEDeviceIDMap; @@ -1707,6 +1820,12 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject */ TDEGenericDevice* findBySystemPath(TQString syspath); + /** + * Return the device with unique ID @arg uid, or 0 if no device exists for that uid + * @return TDEGenericDevice + */ + TDEGenericDevice* findByUniqueID(TQString uid); + /** * Return the device with device node @arg devnode, or 0 if no device exists at that node * @return TDEGenericDevice -- cgit v1.2.1