hal: Branch 'master'

Richard Hughes hughsient at kemper.freedesktop.org
Mon Mar 19 14:15:08 PDT 2007


 configure.in                                   |   25 ++
 fdi/policy/10osvendor/10-macbook-backlight.fdi |   23 ++
 fdi/policy/10osvendor/Makefile.am              |    4 
 hald/linux/addons/.gitignore                   |    1 
 hald/linux/addons/Makefile.am                  |    6 
 hald/linux/addons/addon-macbook-backlight.c    |  274 +++++++++++++++++++++++++
 6 files changed, 333 insertions(+)

New commits:
diff-tree 7f278b8a9d38a5c0851f20f12a4709684571d3d1 (from a0af30e5d063ca863713d365b54bb0ca45814341)
Author: Richard Hughes <richard at hughsie.com>
Date:   Mon Mar 19 21:14:11 2007 +0000

    add support for the macbook backlight
    
    Apply a patch from Ryan Lortie <desrt at desrt.ca> to support the Macbook
    backlight.
    The code was written after the AppleIntelIntegratedFramebuffer.kext kernel
    extension was reverse engineered by Ryan.
    
    Rebased to master, and CodingStyle corrected by me, no other changes.

diff --git a/configure.in b/configure.in
index ebd7996..d9f61e6 100644
--- a/configure.in
+++ b/configure.in
@@ -675,6 +675,30 @@ elif test "x$with_macbookpro" = "x" ; th
 fi
 AM_CONDITIONAL(BUILD_MACBOOKPRO, test x$BUILD_MACBOOKPRO = xyes)
 
+dnl macbook backlight support
+AC_ARG_WITH(macbook,     [  --with-macbook          Include support for Macbook backlight (auto)])
+BUILD_MACBOOK=no
+if test "x$with_macbook" = "xyes" ; then
+   BUILD_MACBOOK=yes
+elif test "x$with_macbook" = "x" ; then
+  if test "x$USE_LIBPCI" != "xno" ; then
+    case "${HALD_BACKEND}" in
+      linux)
+        case "${host}" in
+	  i[[3456]]86-*-*)
+            BUILD_MACBOOK=yes
+	    ;;
+	  *)
+	    ;;
+	esac
+        ;;
+      *)
+        ;;
+    esac
+   fi
+fi
+AM_CONDITIONAL(BUILD_MACBOOK, test x$BUILD_MACBOOK = xyes)
+
 AC_ARG_WITH([omap],
 	    [AS_HELP_STRING([--with-omap],
 			    [Whether to build OMAP utils (auto)])])
@@ -884,6 +908,7 @@ echo "
         use APM:                    ${msg_apm}
         use Sony PIC:               ${msg_sonypic}
 
+        Macbook backlight support:  ${BUILD_MACBOOK} (Linux only, x86 only, requires libpci)
         Macbook Pro utils:          ${BUILD_MACBOOKPRO} (Linux only, x86 only, requires libpci)
         OMAP utils:                 ${BUILD_OMAP} (Linux only, arm only)
         CPU frequency scaling:      ${BUILD_CPUFREQ} (Linux only)
diff --git a/fdi/policy/10osvendor/10-macbook-backlight.fdi b/fdi/policy/10osvendor/10-macbook-backlight.fdi
new file mode 100644
index 0000000..227bbb5
--- /dev/null
+++ b/fdi/policy/10osvendor/10-macbook-backlight.fdi
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deviceinfo version="0.2">
+  <device>
+    <match key="system.kernel.name" string="Linux">
+      <match key="smbios.system.manufacturer" string="Apple Computer, Inc.">
+        <match key="smbios.system.product" string="MacBook1,1">
+          <spawn udi="/org/freedesktop/Hal/devices/macbook_backlight"/>
+        </match>
+      </match>
+    </match>
+  </device>
+  <device>
+    <match key="info.udi" string="/org/freedesktop/Hal/devices/macbook_backlight">
+      <append key="info.capabilities" type="strlist">laptop_panel</append>
+      <merge key="info.product" type="string">MacBook Backlight Control</merge>
+      <merge key="laptop_panel.access_method" type="string">custom</merge>
+      <merge key="laptop_panel.num_levels" type="int">118</merge>
+      <append key="info.addons" type="strlist">hald-addon-macbook-backlight</append>
+    </match>
+  </device>
+</deviceinfo>
+
diff --git a/fdi/policy/10osvendor/Makefile.am b/fdi/policy/10osvendor/Makefile.am
index 55666ef..7b84aef 100644
--- a/fdi/policy/10osvendor/Makefile.am
+++ b/fdi/policy/10osvendor/Makefile.am
@@ -14,6 +14,10 @@ if BUILD_MACBOOKPRO
 dist_fdi_DATA += 10-macbookpro-utils.fdi
 endif
 
+if BUILD_MACBOOK
+dist_fdi_DATA += 10-macbook-backlight.fdi
+endif
+
 if BUILD_CPUFREQ
 dist_fdi_DATA += 10-cpufreq.fdi
 endif
diff --git a/hald/linux/addons/.gitignore b/hald/linux/addons/.gitignore
index 2b6fd5c..7ecd42a 100644
--- a/hald/linux/addons/.gitignore
+++ b/hald/linux/addons/.gitignore
@@ -11,6 +11,7 @@ hald-addon-storage
 hald-addon-usb-csr
 hald-addon-keyboard
 hald-addon-acpi-buttons-toshiba
+hald-addon-macbook-backlight
 hald-addon-macbookpro-backlight
 hald-addon-cpufreq
 hald-addon-dell-backlight
diff --git a/hald/linux/addons/Makefile.am b/hald/linux/addons/Makefile.am
index bea0a17..5d98709 100644
--- a/hald/linux/addons/Makefile.am
+++ b/hald/linux/addons/Makefile.am
@@ -38,6 +38,12 @@ hald_addon_macbookpro_backlight_SOURCES 
 hald_addon_macbookpro_backlight_LDADD = $(top_builddir)/libhal/libhal.la -lpci @GLIB_LIBS@
 endif
 
+if BUILD_MACBOOK
+libexec_PROGRAMS += hald-addon-macbook-backlight
+hald_addon_macbook_backlight_SOURCES = addon-macbook-backlight.c ../../logger.c ../../util_helper.c
+hald_addon_macbook_backlight_LDADD = $(top_builddir)/libhal/libhal.la -lpci @GLIB_LIBS@
+endif
+
 if BUILD_CPUFREQ
 libexec_PROGRAMS += hald-addon-cpufreq
 hald_addon_cpufreq_SOURCES = addon-cpufreq.c addon-cpufreq.h addon-cpufreq-userspace.h \
diff --git a/hald/linux/addons/addon-macbook-backlight.c b/hald/linux/addons/addon-macbook-backlight.c
new file mode 100644
index 0000000..5314f3c
--- /dev/null
+++ b/hald/linux/addons/addon-macbook-backlight.c
@@ -0,0 +1,274 @@
+/*
+ * Macbook Backlight Control
+ * Copyright © 2006 Ryan Lortie <desrt at desrt.ca>
+ * 
+ * HAL integration Copyright © 2007 Ryan Lortie <desrt at desrt.ca>
+ * using code Copyright © 2006 David Zeuthen <david at fubar.dk>
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of version 2 of the GNU General Public License as
+ *   published by the Free Software Foundation.
+ *
+ *   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., 59 Temple Place, Suite 330, Boston, MA  02110 USA
+ *
+ * This program was written after I reverse engineered the
+ * AppleIntelIntegratedFramebuffer.kext kernel extension in Mac OS X and
+ * played with the register at the memory location I found therein.
+ *
+ * From my experiments, the register appears to have two halves.
+ *
+ * yyyyyyyyyyyyyyy0xxxxxxxxxxxxxxx0
+ *
+ * The top (y) bits appear to be the maximum brightness level and the
+ * bottom (x) bits are the current brightness level.  0s are always 0.
+ * The brightness level is, therefore, x/y.
+ *
+ * As my Macbook boots, y is set to 0x94 and x is set to 0x1f.  Going below
+ * 0x1f produces odd results.  For example, if you come from above, the
+ * backlight will completely turn off at 0x12 (18).  Coming from below,
+ * however, you need to get to 0x15 (21) before the backlight comes back on.
+ *
+ * Since there is no clear cut boundry, I assume that this value specifies
+ * a raw voltage.  Also, it appears that the bootup value of 0x1f corresponds
+ * to the lowest level that Mac OS X will set the backlight I choose this
+ * value as a minimum.
+ *
+ * For the maximum I do not let the value exceed the value in the upper 15
+ * bits.
+ *
+ * Turning the backlight off entirely is not supported (as this is supported
+ * by the kernel itself).  This utility is only for setting the brightness
+ * of the backlight when it is enabled.
+ */
+
+#include <pci/pci.h>
+
+#include <glib.h>
+
+#include <stdio.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include "libhal/libhal.h"
+#include "../../util_helper.h"
+
+#define REGISTER_OFFSET       0x00061254
+#define PAGE_SIZE             4096
+#define PAGE_MASK             (PAGE_SIZE - 1)
+
+#define ACCESS_OFFSET         (REGISTER_OFFSET & PAGE_MASK)
+#define ACCESS_INDEX          (ACCESS_OFFSET >> 2)
+
+unsigned int *register_page;
+
+static unsigned long
+determine_video_base_address (void)
+{
+	struct pci_access *pacc;
+	struct pci_dev *pdev;
+	unsigned long address;
+	int i;
+
+	address = 0;
+
+	pacc = pci_alloc ();
+	pci_init (pacc);
+	pci_scan_bus (pacc);
+
+	for (pdev = pacc->devices; pdev; pdev = pdev->next) {
+		pci_fill_info (pdev, PCI_FILL_IDENT | PCI_FILL_BASES);
+
+		if (pdev->vendor_id == 0x8086 && pdev->device_id == 0x27a2)
+			for (i = 0; i < (int) G_N_ELEMENTS (pdev->base_addr); i++) {
+				if (pdev->size[i] == 512 * 1024) {
+					address = pdev->base_addr[i];
+					goto end;
+				}
+			}
+	}
+
+end:
+	pci_cleanup (pacc);
+
+	return address;
+}
+
+static gboolean
+map_register_page (void)
+{
+	long address;
+	int fd;
+
+	address = determine_video_base_address ();
+
+	if (address == 0) {
+		g_error ("Unable to locate video base address");
+		return FALSE;
+	}
+
+	fd = open ("/dev/mem", O_RDWR);
+
+	if (fd < 0) {
+		g_error ("failed to open /dev/mem");
+		return FALSE;
+	}
+
+	register_page = mmap (NULL, PAGE_SIZE, PROT_READ | PROT_WRITE,
+			      MAP_SHARED, fd, (address + REGISTER_OFFSET) & ~PAGE_MASK);
+
+	close (fd);
+
+	drop_privileges (FALSE);
+
+	if (register_page == MAP_FAILED) {
+		g_error ("failed to mmap");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static unsigned long
+register_get (void)
+{
+	return register_page[ACCESS_INDEX];
+}
+
+static void
+register_set (unsigned long value)
+{
+	register_page[ACCESS_INDEX] = value;
+}
+
+static gboolean
+backlight_set (long value)
+{
+	long max;
+
+	max = register_get () >> 17;
+
+	/* sanity check: this should always be 0x94 */
+	if (max != 0x94)
+		return FALSE;
+
+	value = CLAMP (value, 0x1f, max);
+
+	register_set ((max << 17) | (value << 1));
+
+	return TRUE;
+}
+
+static long
+backlight_get (void)
+{
+	return (register_get () >> 1) & 0x7fff;
+}
+
+#define BACKLIGHT_OBJECT \
+  "/org/freedesktop/Hal/devices/macbook_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;
+
+	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)) {
+			backlight_set (level + 0x1f);
+
+			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 () - 0x1f;
+			level = CLAMP (level, 0, 117);
+
+			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;
+
+	udi = getenv ("UDI");
+
+	if (udi == NULL)
+		g_error ("no device specified");
+
+	dbus_error_init (&err);
+	if ((halctx = libhal_ctx_init_direct (&err)) == NULL)
+		g_error ("cannot connect to hald");
+
+	dbus_error_init (&err);
+	if (!libhal_device_addon_is_ready (halctx, udi, &err))
+		return -4;
+
+	if (!map_register_page ())
+		g_error ("failed to gain access to the video card");
+
+	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))
+		g_error ("cannot claim interface");
+
+	main_loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (main_loop);
+
+	return 0;
+}
+


More information about the hal-commit mailing list