diff options
-rw-r--r-- | configure.in | 25 | ||||
-rw-r--r-- | fdi/policy/10osvendor/10-imac-backlight.fdi | 32 | ||||
-rw-r--r-- | hald/linux/addons/Makefile.am | 6 | ||||
-rw-r--r-- | hald/linux/addons/addon-imac-backlight.c | 224 |
4 files changed, 287 insertions, 0 deletions
diff --git a/configure.in b/configure.in index f4a1aac7..013e2b32 100644 --- a/configure.in +++ b/configure.in @@ -838,6 +838,30 @@ elif test "x$with_macbook" = "x" ; then fi AM_CONDITIONAL(BUILD_MACBOOK, [test x$BUILD_MACBOOK = xyes]) +dnl imac backlight +AC_ARG_WITH([imac], + AS_HELP_STRING([--with-imac], + [Whether to build iMac (x86 only) backlight (auto)])) +BUILD_IMAC=no +if test "x$with_imac" = "xyes" ; then + BUILD_IMAC=yes +elif test "x$with_imac" = "x" ; then + case "${HALD_BACKEND}" in + linux) + case "${host}" in + i[[3456]]86-*-*|x86_64-*-*) + BUILD_IMAC=yes + ;; + *) + ;; + esac + ;; + *) + ;; + esac +fi +AM_CONDITIONAL(BUILD_IMAC, [test x$BUILD_IMAC = xyes]) + AC_ARG_WITH([omap], AS_HELP_STRING([--with-omap], [Whether to build OMAP utils (auto)])) @@ -1064,6 +1088,7 @@ echo " Macbook backlight support: ${BUILD_MACBOOK} (Linux only, x86 only, requires libpci) Macbook Pro utils: ${BUILD_MACBOOKPRO} (Linux only, x86 only, requires libpci) + iMac backlight support: ${BUILD_IMAC} (Linux only, x86) OMAP utils: ${BUILD_OMAP} (Linux only, arm only) CPU frequency scaling: ${BUILD_CPUFREQ} (Linux only) Re-map multimedia keys: ${BUILD_KEYMAPS} (Linux only, requires gperf) diff --git a/fdi/policy/10osvendor/10-imac-backlight.fdi b/fdi/policy/10osvendor/10-imac-backlight.fdi new file mode 100644 index 00000000..56d343e4 --- /dev/null +++ b/fdi/policy/10osvendor/10-imac-backlight.fdi @@ -0,0 +1,32 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<deviceinfo version="0.2"> + <device> + <match key="system.kernel.name" string="Linux"> + <match key="system.hardware.vendor" contains="Apple"> + <!-- iMac (Core 2 Duo) --> + <match key="system.hardware.product" string="iMac5,1"> + <spawn udi="/org/freedesktop/Hal/devices/imac_backlight"/> + </match> + <!-- iMac (24-inch Core 2 Duo) --> + <match key="system.hardware.product" string="iMac6,1"> + <spawn udi="/org/freedesktop/Hal/devices/imac_backlight"/> + </match> + <!-- iMac (Alu 24-inch Core 2 Duo) --> + <match key="system.hardware.product" string="iMac7,1"> + <spawn udi="/org/freedesktop/Hal/devices/imac_backlight"/> + </match> + </match> + </match> + </device> + <device> + <match key="info.udi" string="/org/freedesktop/Hal/devices/imac_backlight"> + <append key="info.capabilities" type="strlist">laptop_panel</append> + <merge key="info.category" type="string">laptop_panel</merge> + <merge key="info.product" type="string">iMac Backlight Control</merge> + <merge key="laptop_panel.access_method" type="string">custom</merge> + <merge key="laptop_panel.num_levels" type="int">15</merge> + <append key="info.addons" type="strlist">hald-addon-imac-backlight</append> + </match> + </device> +</deviceinfo> diff --git a/hald/linux/addons/Makefile.am b/hald/linux/addons/Makefile.am index 8546f02c..37beba45 100644 --- a/hald/linux/addons/Makefile.am +++ b/hald/linux/addons/Makefile.am @@ -35,6 +35,12 @@ hald_addon_omap_backlight_SOURCES = addon-omap-backlight.c ../../logger.c ../../ hald_addon_omap_backlight_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ endif +if BUILD_IMAC +libexec_PROGRAMS += hald-addon-imac-backlight +hald_addon_imac_backlight_SOURCES = addon-imac-backlight.c ../../logger.c +hald_addon_imac_backlight_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ +endif + if BUILD_MACBOOKPRO libexec_PROGRAMS += hald-addon-macbookpro-backlight hald_addon_macbookpro_backlight_SOURCES = addon-macbookpro-backlight.c ../../logger.c diff --git a/hald/linux/addons/addon-imac-backlight.c b/hald/linux/addons/addon-imac-backlight.c new file mode 100644 index 00000000..46cac6db --- /dev/null +++ b/hald/linux/addons/addon-imac-backlight.c @@ -0,0 +1,224 @@ +/* + * Apple iMac Backlight control + * + * Copyright (C) 2007 Martin Szulecki <opensuse@sukimashita.com> + * Copyright (C) 2006 Nicolas Boichat <nicolas@boichat.ch> + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <stdlib.h> +#include <sys/io.h> + +#include <glib/gmain.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include "libhal/libhal.h" +#include "../../logger.h" + +static void +backlight_set(int value) +{ + outb(0x04 | (value << 4), 0xB3); + outb(0xBF, 0xB2); +} + +static int +backlight_get(void) +{ + outb(0x03, 0xB3); + outb(0xBF, 0xB2); + return inb(0xB3) >> 4; +} + +static gboolean +check_priv (DBusConnection *connection, DBusMessage *message, const char *udi, const char *privilege) +#ifdef HAVE_POLKIT +{ + gboolean ret; + char *polkit_result; + const char *invoked_by_syscon_name; + DBusMessage *reply; + DBusError error; + + ret = FALSE; + polkit_result = NULL; + + invoked_by_syscon_name = dbus_message_get_sender (message); + + dbus_error_init (&error); + polkit_result = libhal_device_is_caller_privileged (halctx, + udi, + privilege, + invoked_by_syscon_name, + &error); + if (polkit_result == NULL) { + reply = dbus_message_new_error_printf (message, + "org.freedesktop.Hal.Device.Error", + "Cannot determine if caller is privileged", + privilege, polkit_result); + dbus_connection_send (connection, reply, NULL); + goto out; + } + if (strcmp (polkit_result, "yes") != 0) { + + reply = dbus_message_new_error_printf (message, + "org.freedesktop.Hal.Device.PermissionDeniedByPolicy", + "%s %s <-- (privilege, result)", + privilege, polkit_result); + dbus_connection_send (connection, reply, NULL); + goto out; + } + + ret = TRUE; + +out: + if (polkit_result != NULL) + libhal_free_string (polkit_result); + return ret; +} +#else +{ + return TRUE; +} +#endif + +#define BACKLIGHT_OBJECT \ + "/org/freedesktop/Hal/devices/imac_backlight" +#define BACKLIGHT_IFACE \ + "org.freedesktop.Hal.Device.LaptopPanel" +#define INTERFACE_DESCRIPTION \ + " <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" + +static DBusHandlerResult +filter_function (DBusConnection * connection, DBusMessage * message, void *userdata) +{ + DBusMessage *reply; + DBusError err; + int level; + int ret; + + if (!check_priv (connection, message, dbus_message_get_path (message), "org.freedesktop.hal.power-management.lcd-panel")) { + return DBUS_HANDLER_RESULT_HANDLED; + } + + reply = NULL; + ret = 0; + + dbus_error_init (&err); + + if (dbus_message_is_method_call (message, BACKLIGHT_IFACE, "SetBrightness")) { + + if (dbus_message_get_args (message, &err, DBUS_TYPE_INT32, + &level, DBUS_TYPE_INVALID)) { + if (level < 0 || level > 15) { + reply = dbus_message_new_error (message, + "org.freedesktop.Hal.Device.LaptopPanel.Invalid", + "Brightness has to be between 0 and 15!"); + + } else { + backlight_set (level); + + if ((reply = dbus_message_new_method_return (message))) + dbus_message_append_args (reply, DBUS_TYPE_INT32, + &ret, DBUS_TYPE_INVALID); + } + } + } else if (dbus_message_is_method_call (message, BACKLIGHT_IFACE, "GetBrightness")) { + if (dbus_message_get_args (message, &err, DBUS_TYPE_INVALID)) { + level = backlight_get(); + if (level < 0) + level = 0; + if (level > 15) + level = 15; + + if ((reply = dbus_message_new_method_return (message))) + dbus_message_append_args (reply, DBUS_TYPE_INT32, + &level, DBUS_TYPE_INVALID); + } + } + + if (reply) { + dbus_connection_send (connection, reply, NULL); + return DBUS_HANDLER_RESULT_HANDLED; + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +int +main (int argc, char **argv) +{ + LibHalContext *halctx; + DBusConnection *conn; + GMainLoop *main_loop; + const char *udi; + DBusError err; + + setup_logger (); + udi = getenv ("UDI"); + + HAL_DEBUG (("udi=%s", udi)); + if (udi == NULL) + { + HAL_ERROR (("No device specified")); + return -2; + } + + dbus_error_init (&err); + if ((halctx = libhal_ctx_init_direct (&err)) == NULL) + { + HAL_ERROR (("Cannot connect to hald")); + return -3; + } + + dbus_error_init (&err); + if (!libhal_device_addon_is_ready (halctx, udi, &err)) + return -4; + + if (ioperm(0xB2, 0xB3, 1) < 0) + { + HAL_ERROR (("ioperm failed (you should be root).")); + exit(1); + } + + conn = libhal_ctx_get_dbus_connection (halctx); + dbus_connection_setup_with_g_main (conn, NULL); + + dbus_connection_add_filter (conn, filter_function, NULL, NULL); + + if (!libhal_device_claim_interface (halctx, BACKLIGHT_OBJECT, + BACKLIGHT_IFACE, INTERFACE_DESCRIPTION, &err)) + { + HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.LaptopPanel'")); + return -4; + } + + main_loop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (main_loop); + return 0; +} + |