From ee68b0ebfcadf60bf31dd1b3163f52741dce25f1 Mon Sep 17 00:00:00 2001 From: Martin Szulecki Date: Thu, 13 Mar 2008 20:38:18 +0100 Subject: add iMac (x86 linux) backlight addon Added iMac (x86 linux) backlight addon. On my way to control the hardcore radioactive backlight of the newer iMac 24" aluminum models some older code from the mactel guys appeared to work (while the brightness level range lacks on the 24" but is good on the 20" ones, compared to Mac OS). I glued a patch which exposes the control like the other Macbook and Macbook Pro addons. People reported that it apparently also worked on other iMac models which I added to the corresponding fdi. With the lately upstreamed hid patches to support the new aluminum apple keyboard (really nice!) one can control the backlight of the display nicely. --- configure.in | 25 ++++ fdi/policy/10osvendor/10-imac-backlight.fdi | 32 ++++ hald/linux/addons/Makefile.am | 6 + hald/linux/addons/addon-imac-backlight.c | 224 ++++++++++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 fdi/policy/10osvendor/10-imac-backlight.fdi create mode 100644 hald/linux/addons/addon-imac-backlight.c 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + laptop_panel + laptop_panel + iMac Backlight Control + custom + 15 + hald-addon-imac-backlight + + + 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 + * Copyright (C) 2006 Nicolas Boichat + * + * 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 + +#include +#include +#include + +#include +#include +#include + +#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 \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \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; +} + -- cgit v1.2.3-65-gdbad