From a7e4c6b5e7916d924c2a9b75a10e427b556b8d65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sl=C3=A1vek=20Banko?= Date: Tue, 25 Feb 2014 19:45:39 +0100 Subject: Fix detection of switches on input event devices This relates to Bug 1597 --- .../dbus/org.trinitydesktop.hardwarecontrol.conf | 8 +- .../hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c | 167 +++++++++++++++++++-- tdecore/tdehw/tdehardwaredevices.cpp | 89 +++++++++-- 3 files changed, 244 insertions(+), 20 deletions(-) (limited to 'tdecore/tdehw') diff --git a/tdecore/tdehw/hwlibdaemons/dbus/org.trinitydesktop.hardwarecontrol.conf b/tdecore/tdehw/hwlibdaemons/dbus/org.trinitydesktop.hardwarecontrol.conf index f8537010f..b897da36b 100644 --- a/tdecore/tdehw/hwlibdaemons/dbus/org.trinitydesktop.hardwarecontrol.conf +++ b/tdecore/tdehw/hwlibdaemons/dbus/org.trinitydesktop.hardwarecontrol.conf @@ -16,19 +16,23 @@ + - + + send_interface="org.trinitydesktop.hardwarecontrol.InputEvents"/> diff --git a/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c index d00f06eb5..f88c5ab5a 100644 --- a/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c +++ b/tdecore/tdehw/hwlibdaemons/dbus/tde_dbus_hardwarecontrol.c @@ -5,6 +5,13 @@ #include #include #include +#include + +// Input devices +#include + +#define BITS_PER_LONG (sizeof(long) * 8) +#define NUM_BITS(x) ((((x) - 1) / BITS_PER_LONG) + 1) void reply_Bool(DBusMessage* msg, DBusConnection* conn, int value) { DBusMessage* reply; @@ -177,7 +184,6 @@ void reply_CanSetBrightness(DBusMessage* msg, DBusConnection* conn) { const char* member = dbus_message_get_member(msg); char* rawpath; char* safepath; - char path[256]; // read the arguments if (!dbus_message_iter_init(msg, &args)) { @@ -211,7 +217,6 @@ void reply_SetBrightness(DBusMessage* msg, DBusConnection* conn) { char* rawpath; char* safepath; char* brightness; - char path[256]; // read the arguments if (!dbus_message_iter_init(msg, &args)) { @@ -266,7 +271,7 @@ void reply_CanSetPower(DBusMessage* msg, DBusConnection* conn, char* state) { char *line = NULL; size_t len = 0; ssize_t read = getline(&line, &len, node); - if (line) { + if (read > 0 && line) { method = strstr(line, state) != NULL; free(line); } @@ -317,6 +322,98 @@ void reply_SetHibernationMethod(DBusMessage* msg, DBusConnection* conn) { } } +void reply_InputEventsGetSwitches(DBusMessage* msg, DBusConnection* conn, bool active) { + DBusMessage* reply; + DBusMessageIter args, arrayIter; + const char* member = dbus_message_get_member(msg); + dbus_uint32_t serial = 0; + char* rawpath; + char* safepath; + int fd, r; + unsigned long switches[NUM_BITS(EV_CNT)]; + + // read the arguments + if (!dbus_message_iter_init(msg, &args)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: no argument supplied\n", member); + } + else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type(&args)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: argument not string\n", member); + } + else { + dbus_message_iter_get_basic(&args, &rawpath); + } + + safepath = realpath(rawpath, NULL); + + if (safepath && + (strstr(safepath, "/dev/input/event") == safepath) + ) { + + fd = open(safepath, O_RDONLY); + if( active ) { + r = ioctl(fd, EVIOCGSW(sizeof(switches)), switches); + } + else { + r = ioctl(fd, EVIOCGBIT(EV_SW, EV_CNT), switches); + } + if( r > 0 ) { + dbus_uint32_t dSwitches[NUM_BITS(EV_CNT)]; + dbus_uint32_t *dSwitchesP = dSwitches; + int i; + + // create a reply from the message + reply = dbus_message_new_method_return(msg); + + // add the arguments to the reply + for( i = 0; i < sizeof(switches)/sizeof(switches[0]); i++ ) { + dSwitches[i] = switches[i]; + } + dbus_message_iter_init_append(reply, &args); + if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "u", &arrayIter)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_open_container failed\n", member); + return; + } + if( !dbus_message_iter_append_fixed_array(&arrayIter, DBUS_TYPE_UINT32, + &dSwitchesP, sizeof(switches)/sizeof(switches[0])) ) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_append_fixed_array failed\n", member); + return; + } + if (!dbus_message_iter_close_container(&args, &arrayIter)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_close_container failed\n", member); + return; + } + } + else { + // create a reply from the message + reply = dbus_message_new_error_printf(msg, + "org.freedesktop.DBus.Error.NotSupported", + "Event device \"%s\" not support EV_SW ioctl", + safepath); + } + close(fd); + } + else { + // create a reply from the message + reply = dbus_message_new_error_printf(msg, + "org.freedesktop.DBus.Error.InvalidArgs", + "Event device \"%s\" is invalid", + rawpath); + } + + // send the reply && flush the connection + if (!dbus_connection_send(conn, reply, &serial)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_connection_send failed\n", member); + return; + } + dbus_connection_flush(conn); + + // free the reply + dbus_message_unref(reply); + + // free safepath + free(safepath); +} + void signal_NameAcquired(DBusMessage* msg) { DBusMessageIter args; char *name = NULL; @@ -353,6 +450,19 @@ void reply_Introspect(DBusMessage* msg, DBusConnection* conn) { strncat(data, " \n", size-strlen(data)); } else if(strcmp("/org/trinitydesktop/hardwarecontrol", path) == 0) { + strncat(data, + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \n", + size-strlen(data)); strncat(data, " \n" " \n" @@ -367,15 +477,14 @@ void reply_Introspect(DBusMessage* msg, DBusConnection* conn) { " \n", size-strlen(data)); strncat(data, - " \n" - " \n" + " \n" + " \n" " \n" - " \n" + " \n" " \n" - " \n" + " \n" " \n" - " \n" - " \n" + " \n" " \n" " \n", size-strlen(data)); @@ -439,6 +548,37 @@ void reply_Introspect(DBusMessage* msg, DBusConnection* conn) { free((void*)data); } +void reply_PropertiesGetAll(DBusMessage* msg, DBusConnection* conn) { + DBusMessage* reply; + DBusMessageIter args, arrayIter; + const char* member = dbus_message_get_member(msg); + dbus_uint32_t serial = 0; + + // create a reply from the message + reply = dbus_message_new_method_return(msg); + + // add the arguments to the reply + dbus_message_iter_init_append(reply, &args); + if (!dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "sv", &arrayIter)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_open_container failed\n", member); + return; + } + if (!dbus_message_iter_close_container(&args, &arrayIter)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_message_iter_close_container failed\n", member); + return; + } + + // send the reply && flush the connection + if (!dbus_connection_send(conn, reply, &serial)) { + fprintf(stderr, "[tde_dbus_hardwarecontrol] %s: dbus_connection_send failed\n", member); + return; + } + dbus_connection_flush(conn); + + // free the reply + dbus_message_unref(reply); +} + void error_UnknownMessage(DBusMessage* msg, DBusConnection* conn) { DBusMessage* reply; dbus_uint32_t serial = 0; @@ -555,12 +695,21 @@ void listen() { else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.Power", "SetHibernationMethod")) { reply_SetHibernationMethod(msg, conn); } + else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.InputEvents", "GetProvidedSwitches")) { + reply_InputEventsGetSwitches(msg, conn, false); + } + else if (dbus_message_is_method_call(msg, "org.trinitydesktop.hardwarecontrol.InputEvents", "GetActiveSwitches")) { + reply_InputEventsGetSwitches(msg, conn, true); + } else if (dbus_message_is_signal(msg, "org.freedesktop.DBus", "NameAcquired")) { signal_NameAcquired(msg); } else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Introspectable", "Introspect")) { reply_Introspect(msg, conn); } + else if (dbus_message_is_method_call(msg, "org.freedesktop.DBus.Properties", "GetAll")) { + reply_PropertiesGetAll(msg, conn); + } else { error_UnknownMessage(msg, conn); } diff --git a/tdecore/tdehw/tdehardwaredevices.cpp b/tdecore/tdehw/tdehardwaredevices.cpp index 8038a3380..30d06a75c 100644 --- a/tdecore/tdehw/tdehardwaredevices.cpp +++ b/tdecore/tdehw/tdehardwaredevices.cpp @@ -97,11 +97,20 @@ 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))) - -#if defined(WITH_UDISKS) || defined(WITH_UDISKS2) || defined(WITH_NETWORK_MANAGER_BACKEND) +#define BITS_PER_LONG (sizeof(long) * 8) +#define NUM_BITS(x) ((((x) - 1) / BITS_PER_LONG) + 1) +#define OFF(x) ((x) % BITS_PER_LONG) +#define BIT(x) (1UL << OFF(x)) +#define LONG(x) ((x) / BITS_PER_LONG) +#define BIT_IS_SET(array, bit) ((array[LONG(bit)] >> OFF(bit)) & 1) + +#if defined(WITH_TDEHWLIB_DAEMONS) || defined(WITH_UDISKS) || defined(WITH_UDISKS2) || defined(WITH_NETWORK_MANAGER_BACKEND) +#include +#include +#include #include #include +#include // Convenience method for tdehwlib DBUS calls // FIXME // Should probably be part of dbus-1-tqt @@ -3105,14 +3114,37 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist // Try to obtain as much specific information about this event device as possible TDEEventDevice* edevice = dynamic_cast(device); int r; - char switches[SW_CNT]; + unsigned long switches[NUM_BITS(EV_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); + r = ioctl(edevice->m_fd, EVIOCGBIT(EV_SW, EV_CNT), switches); +#ifdef WITH_TDEHWLIB_DAEMONS + if( r < 1 ) { + TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus); + if (dbusConn.isConnected()) { + TQT_DBusProxy switchesProxy("org.trinitydesktop.hardwarecontrol", + "/org/trinitydesktop/hardwarecontrol", + "org.trinitydesktop.hardwarecontrol.InputEvents", + dbusConn); + if (switchesProxy.canSend()) { + TQValueList params; + params << TQT_DBusData::fromString(edevice->deviceNode().ascii()); + TQT_DBusMessage reply = switchesProxy.sendWithReply("GetProvidedSwitches", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) { + TQValueList list = reply[0].toList().toUInt32List(); + TQValueList::const_iterator it = list.begin(); + for (r = 0; it != list.end(); ++it, r++) { + switches[r] = (*it); + } + } + } + } + } +#endif if (r > 0) { if (BIT_IS_SET(switches, SW_LID)) { supportedSwitches = supportedSwitches | TDESwitchType::Lid; @@ -3141,23 +3173,31 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist if (BIT_IS_SET(switches, SW_VIDEOOUT_INSERT)) { supportedSwitches = supportedSwitches | TDESwitchType::VideoOutInsert; } -#if 0 // Some old kernels don't provide these defines... [FIXME] +# ifdef SW_CAMERA_LENS_COVER if (BIT_IS_SET(switches, SW_CAMERA_LENS_COVER)) { supportedSwitches = supportedSwitches | TDESwitchType::CameraLensCover; } +# endif +# ifdef SW_KEYPAD_SLIDE if (BIT_IS_SET(switches, SW_KEYPAD_SLIDE)) { supportedSwitches = supportedSwitches | TDESwitchType::KeypadSlide; } +# endif +# ifdef SW_FRONT_PROXIMITY if (BIT_IS_SET(switches, SW_FRONT_PROXIMITY)) { supportedSwitches = supportedSwitches | TDESwitchType::FrontProximity; } +# endif +# ifdef SW_ROTATE_LOCK if (BIT_IS_SET(switches, SW_ROTATE_LOCK)) { supportedSwitches = supportedSwitches | TDESwitchType::RotateLock; } +# endif +# ifdef SW_LINEIN_INSERT if (BIT_IS_SET(switches, SW_LINEIN_INSERT)) { supportedSwitches = supportedSwitches | TDESwitchType::LineInInsert; } -#endif +# endif // Keep in sync with ACPI Event/Input identification routines above if (edevice->systemPath().contains("PNP0C0D")) { supportedSwitches = supportedSwitches | TDESwitchType::Lid; @@ -3174,6 +3214,29 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist // Figure out which switch types are active, if any TDESwitchType::TDESwitchType activeSwitches = TDESwitchType::Null; r = ioctl(edevice->m_fd, EVIOCGSW(sizeof(switches)), switches); +#ifdef WITH_TDEHWLIB_DAEMONS + if( r < 1 ) { + TQT_DBusConnection dbusConn = TQT_DBusConnection::addConnection(TQT_DBusConnection::SystemBus); + if (dbusConn.isConnected()) { + TQT_DBusProxy switchesProxy("org.trinitydesktop.hardwarecontrol", + "/org/trinitydesktop/hardwarecontrol", + "org.trinitydesktop.hardwarecontrol.InputEvents", + dbusConn); + if (switchesProxy.canSend()) { + TQValueList params; + params << TQT_DBusData::fromString(edevice->deviceNode().ascii()); + TQT_DBusMessage reply = switchesProxy.sendWithReply("GetActiveSwitches", params); + if (reply.type() == TQT_DBusMessage::ReplyMessage && reply.count() == 1) { + TQValueList list = reply[0].toList().toUInt32List(); + TQValueList::const_iterator it = list.begin(); + for (r = 0; it != list.end(); ++it, r++) { + switches[r] = (*it); + } + } + } + } + } +#endif if (r > 0) { if (BIT_IS_SET(switches, SW_LID)) { activeSwitches = activeSwitches | TDESwitchType::Lid; @@ -3202,23 +3265,31 @@ void TDEHardwareDevices::updateExistingDeviceInformation(TDEGenericDevice* exist if (BIT_IS_SET(switches, SW_VIDEOOUT_INSERT)) { activeSwitches = activeSwitches | TDESwitchType::VideoOutInsert; } -#if 0 // Some old kernels don't provide these defines... [FIXME] +# ifdef SW_CAMERA_LENS_COVER if (BIT_IS_SET(switches, SW_CAMERA_LENS_COVER)) { activeSwitches = activeSwitches | TDESwitchType::CameraLensCover; } +# endif +# ifdef SW_KEYPAD_SLIDE if (BIT_IS_SET(switches, SW_KEYPAD_SLIDE)) { activeSwitches = activeSwitches | TDESwitchType::KeypadSlide; } +# endif +# ifdef SW_FRONT_PROXIMITY if (BIT_IS_SET(switches, SW_FRONT_PROXIMITY)) { activeSwitches = activeSwitches | TDESwitchType::FrontProximity; } +# endif +# ifdef SW_ROTATE_LOCK if (BIT_IS_SET(switches, SW_ROTATE_LOCK)) { activeSwitches = activeSwitches | TDESwitchType::RotateLock; } +# endif +# ifdef SW_LINEIN_INSERT if (BIT_IS_SET(switches, SW_LINEIN_INSERT)) { activeSwitches = activeSwitches | TDESwitchType::LineInInsert; } -#endif +# endif } edevice->internalSetActiveSwitches(activeSwitches); -- cgit v1.2.1