diff options
author | Alex Murray <murray.alex@gmail.com> | 2010-10-09 07:50:32 +1030 |
---|---|---|
committer | Richard Hughes <richard@hughsie.com> | 2010-10-11 11:03:06 +0100 |
commit | 5d902c22b7d009b0695587fbe2d1ba46a4f78bac (patch) | |
tree | d58679fe7e0dbb2ddf456748f2450d5e821aa409 /src | |
parent | 58f3d9fbdff88173276f05e0d6da2cf864758381 (diff) |
Add support for controlling leds keyboard backlights
Add a new DBus interface based on the QoS one to provide for controlling a
keyboard backlight via the Linux leds interface.
Signed-off-by: Richard Hughes <richard@hughsie.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 10 | ||||
-rw-r--r-- | src/org.freedesktop.UPower.KbdBacklight.xml | 101 | ||||
-rw-r--r-- | src/org.freedesktop.UPower.conf.in | 4 | ||||
-rw-r--r-- | src/up-kbd-backlight.c | 319 | ||||
-rw-r--r-- | src/up-kbd-backlight.h | 68 | ||||
-rw-r--r-- | src/up-main.c | 5 |
6 files changed, 507 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 5ee559a..36ebf75 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -29,6 +29,7 @@ BUILT_SOURCES = \ up-daemon-glue.h \ up-device-glue.h \ up-qos-glue.h \ + up-kbd-backlight-glue.h \ up-wakeups-glue.h \ up-marshal.h \ up-marshal.c @@ -48,6 +49,9 @@ up-device-glue.h: org.freedesktop.UPower.Device.xml Makefile.am up-qos-glue.h: org.freedesktop.UPower.QoS.xml Makefile.am dbus-binding-tool --prefix=up_qos --mode=glib-server --output=up-qos-glue.h org.freedesktop.UPower.QoS.xml +up-kbd-backlight-glue.h: org.freedesktop.UPower.KbdBacklight.xml Makefile.am + dbus-binding-tool --prefix=up_kbd_backlight --mode=glib-server --output=up-kbd-backlight-glue.h org.freedesktop.UPower.KbdBacklight.xml + up-wakeups-glue.h: org.freedesktop.UPower.Wakeups.xml Makefile.am dbus-binding-tool --prefix=up_wakeups --mode=glib-server --output=up-wakeups-glue.h org.freedesktop.UPower.Wakeups.xml @@ -58,6 +62,7 @@ dbusif_DATA = \ org.freedesktop.UPower.xml \ org.freedesktop.UPower.Device.xml \ org.freedesktop.UPower.QoS.xml \ + org.freedesktop.UPower.KbdBacklight.xml \ org.freedesktop.UPower.Wakeups.xml upowerd_SOURCES = \ @@ -73,6 +78,8 @@ upowerd_SOURCES = \ up-device-list.c \ up-qos.h \ up-qos.c \ + up-kbd-backlight.h \ + up-kbd-backlight.c \ up-wakeups.h \ up-wakeups.c \ up-history.h \ @@ -136,6 +143,8 @@ up_self_test_SOURCES = \ up-device-list.c \ up-qos.h \ up-qos.c \ + up-kbd-backlight.h \ + up-kbd-backlight.c \ up-wakeups.h \ up-wakeups.c \ up-history.h \ @@ -187,6 +196,7 @@ EXTRA_DIST = \ org.freedesktop.UPower.xml \ org.freedesktop.UPower.Device.xml \ org.freedesktop.UPower.QoS.xml \ + org.freedesktop.UPower.KbdBacklight.xml \ org.freedesktop.UPower.Wakeups.xml \ up-marshal.list \ $(service_in_files) \ diff --git a/src/org.freedesktop.UPower.KbdBacklight.xml b/src/org.freedesktop.UPower.KbdBacklight.xml new file mode 100644 index 0000000..3ccc211 --- /dev/null +++ b/src/org.freedesktop.UPower.KbdBacklight.xml @@ -0,0 +1,101 @@ +<!DOCTYPE node PUBLIC +"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" +"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd" [ + <!ENTITY ERROR_GENERAL "org.freedesktop.UPower.GeneralError"> +]> +<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"> + <interface name="org.freedesktop.UPower.KbdBacklight"> + <doc:doc> + <doc:description> + <doc:para> + org.freedesktop.UPower.KbdBacklight is a DBus interface implimented + by UPower. + It allows the keyboard backlight (if present) to be controlled. + </doc:para> + </doc:description> + </doc:doc> + + <!-- ************************************************************ --> + <method name="GetMaxBrightness"> + <arg name="value" direction="out" type="i"> + <doc:doc> + <doc:summary> + The maximum value of the keyboard backlight brightness. + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + Get the maximum brightness level for the keyboard backlight. + </doc:para> + </doc:description> + <doc:errors> + <doc:error name="&ERROR_GENERAL;">if an error occured while getting the maximum brightness</doc:error> + </doc:errors> + </doc:doc> + </method> + + <!-- ************************************************************ --> + <method name="GetBrightness"> + <arg name="value" direction="out" type="i"> + <doc:doc> + <doc:summary> + The current value of the keyboard backlight brightness. + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + Get the brightness level of the keyboard backlight. + </doc:para> + </doc:description> + <doc:errors> + <doc:error name="&ERROR_GENERAL;">if an error occured while getting the brightness</doc:error> + </doc:errors> + </doc:doc> + </method> + + <!-- ************************************************************ --> + <method name="SetBrightness"> + <arg name="value" direction="in" type="i"> + <doc:doc> + <doc:summary> + The value to set the KbdBacklight brightness. + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + Set the brightness level of the keyboard backlight. + </doc:para> + </doc:description> + <doc:errors> + <doc:error name="&ERROR_GENERAL;">if an error occured while setting the brightness</doc:error> + </doc:errors> + </doc:doc> + </method> + + <!-- ************************************************************ --> + <signal name="BrightnessChanged"> + <arg name="value" direction="out" type="i"> + <doc:doc> + <doc:summary> + The new brightness value of the keyboard backlight. + </doc:summary> + </doc:doc> + </arg> + <doc:doc> + <doc:description> + <doc:para> + The keyboard backlight brightness level has changed. + </doc:para> + </doc:description> + </doc:doc> + </signal> + + </interface> + +</node> diff --git a/src/org.freedesktop.UPower.conf.in b/src/org.freedesktop.UPower.conf.in index 26fbb33..a15ce93 100644 --- a/src/org.freedesktop.UPower.conf.in +++ b/src/org.freedesktop.UPower.conf.in @@ -19,6 +19,8 @@ send_interface="org.freedesktop.DBus.Properties"/> <allow send_destination="org.freedesktop.UPower.QoS" send_interface="org.freedesktop.DBus.Properties"/> + <allow send_destination="org.freedesktop.UPower.KbdBacklight" + send_interface="org.freedesktop.DBus.Properties"/> <allow send_destination="org.freedesktop.UPower.Wakeups" send_interface="org.freedesktop.DBus.Properties"/> @@ -29,6 +31,8 @@ <allow send_destination="org.freedesktop.UPower" send_interface="org.freedesktop.UPower.QoS"/> <allow send_destination="org.freedesktop.UPower" + send_interface="org.freedesktop.UPower.KbdBacklight"/> + <allow send_destination="org.freedesktop.UPower" send_interface="org.freedesktop.UPower.Wakeups"/> </policy> </busconfig> diff --git a/src/up-kbd-backlight.c b/src/up-kbd-backlight.c new file mode 100644 index 0000000..249b93d --- /dev/null +++ b/src/up-kbd-backlight.c @@ -0,0 +1,319 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Richard Hughes <richard@hughsie.com> + * 2010 Alex Murray <murray.alex@gmail.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" + +#include <glib.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include <glib/gi18n.h> +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <string.h> +#include <dirent.h> + +#include "egg-debug.h" + +#include "up-kbd-backlight.h" +#include "up-marshal.h" +#include "up-daemon.h" +#include "up-kbd-backlight-glue.h" +#include "up-types.h" + +static void up_kbd_backlight_finalize (GObject *object); + +#define UP_KBD_BACKLIGHT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), UP_TYPE_KBD_BACKLIGHT, UpKbdBacklightPrivate)) + +struct UpKbdBacklightPrivate +{ + gint fd; + gint brightness; + gint max_brightness; + DBusGConnection *connection; +}; + +enum { + BRIGHTNESS_CHANGED, + LAST_SIGNAL +}; + +static guint signals [LAST_SIGNAL] = { 0 }; + +G_DEFINE_TYPE (UpKbdBacklight, up_kbd_backlight, G_TYPE_OBJECT) + +/** + * up_kbd_backlight_brightness_write: + **/ +static gboolean +up_kbd_backlight_brightness_write (UpKbdBacklight *kbd_backlight, gint value) +{ + gchar *text = NULL; + gint retval; + gint length; + gboolean ret = TRUE; + + /* write new values to backlight */ + if (kbd_backlight->priv->fd < 0) { + egg_warning ("cannot write to kbd_backlight as file not open"); + ret = FALSE; + goto out; + } + + /* limit to between 0 and max */ + value = CLAMP (value, 0, kbd_backlight->priv->max_brightness); + + /* convert to text */ + text = g_strdup_printf ("%i", value); + length = strlen (text); + + /* write to file */ + lseek (kbd_backlight->priv->fd, 0, SEEK_SET); + retval = write (kbd_backlight->priv->fd, text, length); + if (retval != length) { + egg_warning ("writing '%s' to device failed", text); + ret = FALSE; + goto out; + } + + /* emit signal */ + kbd_backlight->priv->brightness = value; + g_signal_emit (kbd_backlight, signals [BRIGHTNESS_CHANGED], 0, + kbd_backlight->priv->brightness); + +out: + g_free (text); + return ret; +} + +/** + * up_kbd_backlight_get_brightness: + * + * Gets the current brightness + **/ +gboolean +up_kbd_backlight_get_brightness (UpKbdBacklight *kbd_backlight, gint *value, GError **error) +{ + g_return_val_if_fail (value != NULL, FALSE); + *value = kbd_backlight->priv->brightness; + return TRUE; +} + +/** + * up_kbd_backlight_get_max_brightness: + * + * Gets the max brightness + **/ +gboolean +up_kbd_backlight_get_max_brightness (UpKbdBacklight *kbd_backlight, gint *value, GError **error) +{ + g_return_val_if_fail (value != NULL, FALSE); + *value = kbd_backlight->priv->max_brightness; + return TRUE; +} + +/** + * up_kbd_backlight_set_brightness: + **/ +gboolean +up_kbd_backlight_set_brightness (UpKbdBacklight *kbd_backlight, gint value, GError **error) +{ + gboolean ret = FALSE; + + egg_debug ("setting brightness to %i", value); + ret = up_kbd_backlight_brightness_write(kbd_backlight, value); + + if (!ret) { + *error = g_error_new (UP_DAEMON_ERROR, UP_DAEMON_ERROR_GENERAL, "error writing brightness %d", value); + } + return ret; +} + +/** + * up_kbd_backlight_class_init: + **/ +static void +up_kbd_backlight_class_init (UpKbdBacklightClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + object_class->finalize = up_kbd_backlight_finalize; + + signals [BRIGHTNESS_CHANGED] = + g_signal_new ("brightness-changed", + G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (UpKbdBacklightClass, brightness_changed), + NULL, NULL, g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + + /* introspection */ + dbus_g_object_type_install_info (UP_TYPE_KBD_BACKLIGHT, &dbus_glib_up_kbd_backlight_object_info); + + g_type_class_add_private (klass, sizeof (UpKbdBacklightPrivate)); +} + +/** + * up_kbd_backlight_find: + **/ +static gboolean +up_kbd_backlight_find (UpKbdBacklight *kbd_backlight) +{ + gboolean ret; + gboolean found = FALSE; + GDir *dir; + const gchar *filename; + gchar *dir_path = NULL; + gchar *path_max = NULL; + gchar *path_now = NULL; + gchar *buf_max = NULL; + gchar *buf_now = NULL; + GError *error = NULL; + + kbd_backlight->priv->fd = -1; + + /* open directory */ + dir = g_dir_open ("/sys/class/leds", 0, &error); + if (dir == NULL) { + egg_warning ("failed to get directory: %s", error->message); + g_error_free (error); + goto out; + } + + /* find a led device that is a keyboard device */ + while ((filename = g_dir_read_name (dir)) != NULL) { + if (g_strstr_len (filename, -1, "kbd_backlight") != NULL) { + dir_path = g_build_filename ("/sys/class/leds", + filename, NULL); + break; + } + } + + /* nothing found */ + if (dir_path == NULL) + goto out; + + /* read max brightness */ + path_max = g_build_filename (dir_path, "max_brightness", NULL); + ret = g_file_get_contents (path_max, &buf_max, NULL, &error); + if (!ret) { + egg_warning ("failed to get max brightness: %s", error->message); + g_error_free (error); + goto out; + } + kbd_backlight->priv->max_brightness = g_ascii_strtoull (buf_max, NULL, 10); + if (kbd_backlight->priv->max_brightness <= 0) { + egg_warning ("failed to convert max brightness: %s", buf_max); + goto out; + } + + /* read brightness */ + path_now = g_build_filename (dir_path, "brightness", NULL); + ret = g_file_get_contents (path_now, &buf_now, NULL, &error); + if (!ret) { + egg_warning ("failed to get brightness: %s", error->message); + g_error_free (error); + goto out; + } + kbd_backlight->priv->brightness = g_ascii_strtoull (buf_now, NULL, 10); + if (kbd_backlight->priv->brightness <= 0) { + egg_warning ("failed to convert brightness: %s", buf_now); + goto out; + } + + /* open the file for writing */ + kbd_backlight->priv->fd = open (path_now, O_RDWR); + if (kbd_backlight->priv->fd < 0) + goto out; + + /* success */ + found = TRUE; +out: + if (dir != NULL) + g_dir_close (dir); + g_free (dir_path); + g_free (path_max); + g_free (path_now); + g_free (buf_max); + g_free (buf_now); + return found; +} + +/** + * up_kbd_backlight_init: + **/ +static void +up_kbd_backlight_init (UpKbdBacklight *kbd_backlight) +{ + GError *error = NULL; + + kbd_backlight->priv = UP_KBD_BACKLIGHT_GET_PRIVATE (kbd_backlight); + + /* find a kbd backlight in sysfs */ + if (!up_kbd_backlight_find (kbd_backlight)) { + egg_debug ("cannot find a keyboard backlight"); + return; + } + + kbd_backlight->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (error != NULL) { + egg_warning ("Cannot connect to bus: %s", error->message); + g_error_free (error); + return; + } + + /* register on the bus */ + dbus_g_connection_register_g_object (kbd_backlight->priv->connection, "/org/freedesktop/UPower/KbdBacklight", G_OBJECT (kbd_backlight)); + +} + +/** + * up_kbd_backlight_finalize: + **/ +static void +up_kbd_backlight_finalize (GObject *object) +{ + UpKbdBacklight *kbd_backlight; + + g_return_if_fail (object != NULL); + g_return_if_fail (UP_IS_KBD_BACKLIGHT (object)); + + kbd_backlight = UP_KBD_BACKLIGHT (object); + kbd_backlight->priv = UP_KBD_BACKLIGHT_GET_PRIVATE (kbd_backlight); + + /* close file */ + close (kbd_backlight->priv->fd); + + G_OBJECT_CLASS (up_kbd_backlight_parent_class)->finalize (object); +} + +/** + * up_kbd_backlight_new: + **/ +UpKbdBacklight * +up_kbd_backlight_new (void) +{ + UpKbdBacklight *kbd_backlight; + kbd_backlight = g_object_new (UP_TYPE_KBD_BACKLIGHT, NULL); + return UP_KBD_BACKLIGHT (kbd_backlight); +} + diff --git a/src/up-kbd-backlight.h b/src/up-kbd-backlight.h new file mode 100644 index 0000000..413e908 --- /dev/null +++ b/src/up-kbd-backlight.h @@ -0,0 +1,68 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- + * + * Copyright (C) 2008 Richard Hughes <richard@hughsie.com> + * 2010 Alex Murray <murray.alex@gmail.com> + * + * Licensed under the GNU General Public License Version 2 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef __UP_KBD_BACKLIGHT_H +#define __UP_KBD_BACKLIGHT_H + +#include <glib-object.h> +#include <dbus/dbus-glib.h> + +G_BEGIN_DECLS + +#define UP_TYPE_KBD_BACKLIGHT (up_kbd_backlight_get_type ()) +#define UP_KBD_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), UP_TYPE_KBD_BACKLIGHT, UpKbdBacklight)) +#define UP_KBD_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), UP_TYPE_KBD_BACKLIGHT, UpKbdBacklightClass)) +#define UP_IS_KBD_BACKLIGHT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), UP_TYPE_KBD_BACKLIGHT)) +#define UP_IS_KBD_BACKLIGHT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), UP_TYPE_KBD_BACKLIGHT)) +#define UP_KBD_BACKLIGHT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), UP_TYPE_KBD_BACKLIGHT, UpKbdBacklightClass)) + +typedef struct UpKbdBacklightPrivate UpKbdBacklightPrivate; + +typedef struct +{ + GObject parent; + UpKbdBacklightPrivate *priv; +} UpKbdBacklight; + +typedef struct +{ + GObjectClass parent_class; + void (* brightness_changed) (UpKbdBacklight *kbd_backlight, + gint value); +} UpKbdBacklightClass; + +UpKbdBacklight *up_kbd_backlight_new (void); +GType up_kbd_backlight_get_type (void); + +gboolean up_kbd_backlight_set_brightness (UpKbdBacklight *kbd_backlight, + gint value, + GError **error); +gboolean up_kbd_backlight_get_brightness (UpKbdBacklight *kbd_backlight, + gint *value, + GError **error); +gboolean up_kbd_backlight_get_max_brightness (UpKbdBacklight *kbd_backlight, + gint *value, + GError **error); + +G_END_DECLS + +#endif /* __UP_KBD_BACKLIGHT_H */ diff --git a/src/up-main.c b/src/up-main.c index 281ea28..9f2cb24 100644 --- a/src/up-main.c +++ b/src/up-main.c @@ -40,6 +40,7 @@ #include "up-daemon.h" #include "up-qos.h" +#include "up-kbd-backlight.h" #include "up-wakeups.h" #define DEVKIT_POWER_SERVICE_NAME "org.freedesktop.UPower" @@ -125,6 +126,7 @@ main (gint argc, gchar **argv) GError *error = NULL; UpDaemon *daemon = NULL; UpQos *qos = NULL; + UpKbdBacklight *kbd_backlight = NULL; UpWakeups *wakeups = NULL; GOptionContext *context; DBusGProxy *bus_proxy; @@ -182,6 +184,7 @@ main (gint argc, gchar **argv) egg_debug ("Starting upowerd version %s", PACKAGE_VERSION); qos = up_qos_new (); + kbd_backlight = up_kbd_backlight_new (); wakeups = up_wakeups_new (); daemon = up_daemon_new (); loop = g_main_loop_new (NULL, FALSE); @@ -209,6 +212,8 @@ main (gint argc, gchar **argv) out: if (qos != NULL) g_object_unref (qos); + if (kbd_backlight != NULL) + g_object_unref (kbd_backlight); if (wakeups != NULL) g_object_unref (wakeups); if (daemon != NULL) |