Fix detection of switches on input event devices

This relates to Bug 1597
pull/16/head
Slávek Banko 11 years ago
parent 5393539018
commit a7e4c6b5e7

@ -16,19 +16,23 @@
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.Brightness"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.CPUGovernor"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.Brightness"
<allow send_destination="org.trinitydesktop.hardwarecontrol.InputEvents"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol.Power"
send_interface="org.freedesktop.DBus.Properties"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.Brightness"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.CPUGovernor"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.Brightness"/>
send_interface="org.trinitydesktop.hardwarecontrol.InputEvents"/>
<allow send_destination="org.trinitydesktop.hardwarecontrol"
send_interface="org.trinitydesktop.hardwarecontrol.Power"/>
</policy>

@ -5,6 +5,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
// Input devices
#include <linux/input.h>
#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, " <node name=\"hardwarecontrol\" />\n", size-strlen(data));
}
else if(strcmp("/org/trinitydesktop/hardwarecontrol", path) == 0) {
strncat(data,
" <interface name=\"org.trinitydesktop.hardwarecontrol.Brightness\">\n"
" <method name=\"CanSetBrightness\">\n"
" <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
" </method>\n"
" <method name=\"SetBrightness\">\n"
" <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"brightness\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
" </method>\n"
" </interface>\n",
size-strlen(data));
strncat(data,
" <interface name=\"org.trinitydesktop.hardwarecontrol.CPUGovernor\">\n"
" <method name=\"CanSetCPUGovernor\">\n"
@ -367,15 +477,14 @@ void reply_Introspect(DBusMessage* msg, DBusConnection* conn) {
" </interface>\n",
size-strlen(data));
strncat(data,
" <interface name=\"org.trinitydesktop.hardwarecontrol.Brightness\">\n"
" <method name=\"CanSetBrightness\">\n"
" <interface name=\"org.trinitydesktop.hardwarecontrol.InputEvents\">\n"
" <method name=\"GetProvidedSwitches\">\n"
" <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"au\" />\n"
" </method>\n"
" <method name=\"SetBrightness\">\n"
" <method name=\"GetActiveSwitches\">\n"
" <arg name=\"device\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"brightness\" direction=\"in\" type=\"s\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"b\" />\n"
" <arg name=\"value\" direction=\"out\" type=\"au\" />\n"
" </method>\n"
" </interface>\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);
}

@ -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 <tqdbusconnection.h>
#include <tqdbusproxy.h>
#include <tqdbusmessage.h>
#include <tqdbusvariant.h>
#include <tqdbusdata.h>
#include <tqdbusdatalist.h>
// 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<TDEEventDevice*>(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<TQT_DBusData> 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<TQ_UINT32> list = reply[0].toList().toUInt32List();
TQValueList<TQ_UINT32>::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<TQT_DBusData> 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<TQ_UINT32> list = reply[0].toList().toUInt32List();
TQValueList<TQ_UINT32>::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);

Loading…
Cancel
Save