diff options
author | Danny Kukawka <danny.kukawka@web.de> | 2008-11-28 19:30:19 +0100 |
---|---|---|
committer | Danny Kukawka <danny.kukawka@web.de> | 2008-11-28 19:30:19 +0100 |
commit | 33d15dd2d91f06c6eb629eae5694b4945ef1ba7d (patch) | |
tree | bfc92153e3b54311ad6828fe54c3551756e8467b | |
parent | eef409dfc82433edb32c73ce352671ab7fb1f79d (diff) |
add a new singleton addon to handle leds
Added a new singleton addon to handle led devices. The new interface
is called org.freedesktop.Hal.Device.Leds and provide these methodes:
- int SetBrightness (int brightness_value)
- int GetBrightness ()
-rw-r--r-- | fdi/policy/10osvendor/10-leds.fdi | 15 | ||||
-rw-r--r-- | fdi/policy/10osvendor/Makefile.am | 1 | ||||
-rw-r--r-- | hald/linux/addons/Makefile.am | 3 | ||||
-rw-r--r-- | hald/linux/addons/addon-leds.c | 347 | ||||
-rw-r--r-- | policy/Makefile.am | 1 | ||||
-rw-r--r-- | policy/org.freedesktop.hal.leds.policy | 28 |
6 files changed, 395 insertions, 0 deletions
diff --git a/fdi/policy/10osvendor/10-leds.fdi b/fdi/policy/10osvendor/10-leds.fdi new file mode 100644 index 00000000..1d14545d --- /dev/null +++ b/fdi/policy/10osvendor/10-leds.fdi @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<deviceinfo version="0.2"> + + <device> + <match key="info.capabilities" contains="leds"> + <match key="leds.device_name" exists="true"> + <match key="leds.function" exists="true"> + <append key="info.addons.singleton" type="strlist">hald-addon-leds</append> + </match> + </match> + </match> + </device> + +</deviceinfo> diff --git a/fdi/policy/10osvendor/Makefile.am b/fdi/policy/10osvendor/Makefile.am index a30aac04..67c021c3 100644 --- a/fdi/policy/10osvendor/Makefile.am +++ b/fdi/policy/10osvendor/Makefile.am @@ -5,6 +5,7 @@ dist_fdi_DATA = \ 10-input-policy.fdi \ 10-dockstation.fdi \ 10-laptop-panel-mgmt-policy.fdi \ + 10-leds.fdi \ 10-power-mgmt-policy.fdi \ 10-rfkill-switch.fdi \ 10-tabletPCs.fdi \ diff --git a/hald/linux/addons/Makefile.am b/hald/linux/addons/Makefile.am index ccfb6e65..b4a7ef95 100644 --- a/hald/linux/addons/Makefile.am +++ b/hald/linux/addons/Makefile.am @@ -14,6 +14,7 @@ libexec_PROGRAMS = \ hald-addon-hid-ups \ hald-addon-input \ hald-addon-ipw-killswitch \ + hald-addon-leds \ hald-addon-rfkill-killswitch \ hald-addon-storage @@ -105,3 +106,5 @@ hald_addon_ipw_killswitch_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ hald_addon_rfkill_killswitch_SOURCES = addon-rfkill-killswitch.c ../../logger.c ../../util_helper.c ../../util_helper_priv.c hald_addon_rfkill_killswitch_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ +hald_addon_leds_SOURCES = addon-leds.c ../../logger.c ../../util_helper.c ../../util_helper_priv.c +hald_addon_leds_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ diff --git a/hald/linux/addons/addon-leds.c b/hald/linux/addons/addon-leds.c new file mode 100644 index 00000000..86997b1c --- /dev/null +++ b/hald/linux/addons/addon-leds.c @@ -0,0 +1,347 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * addon-leds.c: + * Copyright (C) 2008 Danny Kukawka <danny.kukawka@web.de> + * + * Licensed under the Academic Free License version 2.1 + * + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> + +#include <string.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <glib.h> +#include <glib/gmain.h> +#include <glib/gstdio.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include "libhal/libhal.h" +#include "../../logger.h" +#include "../../util_helper.h" +#include "../../util_helper_priv.h" + +static GMainLoop *gmain = NULL; +static LibHalContext *ctx = NULL; +static GHashTable *leds = NULL; + +/* Getting current brightness */ +static int +get_leds_brightness (const char *udi) +{ + FILE *f; + char buf[64]; + char path[256]; + char *sysfs_path; + int brightness; + + f = NULL; + + if (!g_hash_table_lookup_extended (leds, udi, NULL, (gpointer) &sysfs_path)) { + return -1; + } + + snprintf (path, sizeof (path), "%s/brightness", sysfs_path); + + if ((f = fopen (path, "rb")) == NULL) { + HAL_WARNING(("Could not read brightness from '%s' for device '%s'", path, udi)); + return -1; + } + + if (fgets (buf, sizeof (buf), f) == NULL) { + HAL_ERROR (("Cannot read from '%s' for device '%s'", path, udi)); + goto out; + } + + errno = 0; + brightness = strtol (buf, NULL, 10); + if (errno != 0) { + brightness = -1; + } + +out: + if (f != NULL) + fclose (f); + + return brightness; +} + +/* Setting current brightness of the led */ +static int +set_leds_brightness (const char *udi, int level) +{ + int fd, l, ret; + char path[256]; + char buf[5]; /* Assume we don't need more */ + char *sysfs_path; + + ret = -1; + + if (!g_hash_table_lookup_extended (leds, udi, NULL, (gpointer) &sysfs_path)) { + return -1; + } + + snprintf (path, sizeof (path), "%s/brightness", sysfs_path); + + fd = open (path, O_WRONLY); + if (fd < 0) { + HAL_WARNING(("Could not open '%s' for '%s', error='%s'", sysfs_path, udi, strerror(errno))); + goto out; + } + + if ((l = snprintf (buf, 4, "%d", level)) < 4) { + if (write (fd, buf, l) < 0) { + HAL_WARNING(("Could not write '%s' to '%s'", buf , sysfs_path)); + } else { + /* everything okay */ + ret = level; + } + } + +out: + if (fd >= 0) + close (fd); + + return ret; +} + +/* DBus filter function */ +static DBusHandlerResult +filter_function (DBusConnection *connection, DBusMessage *message, void *userdata) +{ + DBusError err; + DBusMessage *reply; + const char *_udi; + char *sysfs_path; + + if ((_udi = dbus_message_get_path (message)) == NULL) { + HAL_DEBUG (("Couldn't get the udi for this call, ignore it.")); + return DBUS_HANDLER_RESULT_HANDLED; + } else { + if(!g_hash_table_lookup_extended (leds, _udi, NULL, (gpointer *) &sysfs_path)) { + HAL_DEBUG (("This device (%s) isn't yet handled by the addon.", _udi)); + return DBUS_HANDLER_RESULT_HANDLED; + } + } + + dbus_error_init (&err); + + if (!check_priv (ctx, connection, message, dbus_message_get_path (message), "org.freedesktop.hal.leds.brightness")) { + HAL_DEBUG(("User don't have the permissions to call the interface")); + return DBUS_HANDLER_RESULT_HANDLED; + } + + reply = NULL; + + if (dbus_message_is_method_call (message, + "org.freedesktop.Hal.Device.Leds", + "SetBrightness")) { + int brightness; + + dbus_error_init (&err); + if (dbus_message_get_args (message, + &err, + DBUS_TYPE_INT32, &brightness, + DBUS_TYPE_INVALID)) { + int return_code = 0; + int set; + + set = set_leds_brightness (_udi, brightness); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto error; + + if (set == brightness) + return_code = 0; + else + return_code = 1; + + dbus_message_append_args (reply, + DBUS_TYPE_INT32, &return_code, + DBUS_TYPE_INVALID); + + dbus_connection_send (connection, reply, NULL); + } + } else if (dbus_message_is_method_call (message, + "org.freedesktop.Hal.Device.Leds", + "GetBrightness")) { + int brightness; + + dbus_error_init (&err); + if (dbus_message_get_args (message, + &err, + DBUS_TYPE_INVALID)) { + brightness = get_leds_brightness(_udi); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto error; + + dbus_message_append_args (reply, + DBUS_TYPE_INT32, &brightness, + DBUS_TYPE_INVALID); + dbus_connection_send (connection, reply, NULL); + } + } + +error: + if (reply != NULL) + dbus_message_unref (reply); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void +add_device (LibHalContext *ctx, + const char *udi, + const LibHalPropertySet *properties) +{ + DBusError err; + DBusConnection *dbus_connection; + const char* sysfs_path; + static gboolean initialized = FALSE; + + if ((sysfs_path = libhal_ps_get_string (properties, "linux.sysfs_path")) == NULL) { + HAL_ERROR(("%s has no property linux.sysfs_path", udi)); + return; + } + + /* claim the interface */ + + if ((dbus_connection = libhal_ctx_get_dbus_connection(ctx)) == NULL) { + HAL_WARNING (("Cannot get DBus connection")); + return; + } + + if (!initialized) { + dbus_connection_add_filter (dbus_connection, filter_function, NULL, NULL); + initialized = TRUE; + } + + dbus_error_init (&err); + + if (!libhal_device_claim_interface (ctx, + udi, + "org.freedesktop.Hal.Device.Leds", + " <method name=\"SetBrightness\">\n" + " <arg name=\"brightness_value\" direction=\"in\" type=\"i\"/>\n" + " <arg name=\"return_code\" direction=\"out\" type=\"i\"/>\n" + " </method>\n" + " <method name=\"GetBrightness\">\n" + " <arg name=\"brightness_value\" direction=\"out\" type=\"i\"/>\n" + " </method>\n", + &err)) { + HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.Leds'")); + return; + } + + g_hash_table_insert (leds, g_strdup(udi), g_strdup(sysfs_path)); +} + +static void +remove_device (LibHalContext *ctx, + const char *udi, + const LibHalPropertySet *properties) +{ + gpointer sysfs_path; + gboolean handling_udi; + + HAL_DEBUG (("Removing channel for '%s'", udi)); + + handling_udi = g_hash_table_lookup_extended (leds, udi, NULL, &sysfs_path); + + if (!handling_udi) { + HAL_ERROR(("DeviceRemove called for unknown device: '%s'.", udi)); + return; + } + + g_hash_table_remove (leds, udi); + + if (g_hash_table_size (leds) == 0) { + HAL_INFO(("no more devices, exiting")); + g_main_loop_quit (gmain); + } +} + +int +main (int argc, char *argv[]) +{ + DBusConnection *dbus_connection; + DBusError error; + const char *commandline; + + hal_set_proc_title_init (argc, argv); + + setup_logger (); + + dbus_error_init (&error); + if ((ctx = libhal_ctx_init_direct (&error)) == NULL) { + HAL_WARNING (("Unable to init libhal context")); + goto out; + } + + if ((dbus_connection = libhal_ctx_get_dbus_connection(ctx)) == NULL) { + HAL_WARNING (("Cannot get DBus connection")); + goto out; + } + + if ((commandline = getenv ("SINGLETON_COMMAND_LINE")) == NULL) { + HAL_WARNING (("SINGLETON_COMMAND_LINE not set")); + goto out; + } + + libhal_ctx_set_singleton_device_added (ctx, add_device); + libhal_ctx_set_singleton_device_removed (ctx, remove_device); + + dbus_connection_setup_with_g_main (dbus_connection, NULL); + dbus_connection_set_exit_on_disconnect (dbus_connection, 0); + + dbus_error_init (&error); + + if (!libhal_device_singleton_addon_is_ready (ctx, commandline, &error)) { + goto out; + } + + leds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + + gmain = g_main_loop_new (NULL, FALSE); + g_main_loop_run (gmain); + + return 0; + +out: + HAL_DEBUG (("An error occured, exiting cleanly")); + if (ctx != NULL) { + dbus_error_init (&error); + libhal_ctx_shutdown (ctx, &error); + libhal_ctx_free (ctx); + } + + return 0; +} diff --git a/policy/Makefile.am b/policy/Makefile.am index 28f31d41..b506a088 100644 --- a/policy/Makefile.am +++ b/policy/Makefile.am @@ -8,6 +8,7 @@ dist_polkit_policy_DATA = \ org.freedesktop.hal.power-management.policy \ org.freedesktop.hal.killswitch.policy \ org.freedesktop.hal.dockstation.policy \ + org.freedesktop.hal.leds.policy \ org.freedesktop.hal.wol.policy if HAVE_ACLMGMT diff --git a/policy/org.freedesktop.hal.leds.policy b/policy/org.freedesktop.hal.leds.policy new file mode 100644 index 00000000..c7d852e1 --- /dev/null +++ b/policy/org.freedesktop.hal.leds.policy @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE policyconfig PUBLIC + "-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN" + "http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd"> + +<!-- +Policy definitions for HAL's ACL Management mechanism + +Copyright (c) 2008 Danny Kukawka <danny.kukawka@web.de> + +HAL is licensed to you under your choice of the the Academic Free +License Version 2.1, or the GNU General Public License version 2. Some +individual source files may be under the GPL only. See COPYING for +details. +--> + +<policyconfig> + + <action id="org.freedesktop.hal.leds.brightness"> + <description>Set the brightness of a led device</description> + <message>System policy prevents adjusting the led brightness</message> + <defaults> + <allow_inactive>no</allow_inactive> + <allow_active>yes</allow_active> + </defaults> + </action> + +</policyconfig> |