[Pkg-utopia-commits] r945 - in packages/unstable/hal/debian: . patches

Sjoerd Simons sjoerd at costa.debian.org
Tue Aug 15 13:27:01 UTC 2006


Author: sjoerd
Date: 2006-08-15 13:27:00 +0000 (Tue, 15 Aug 2006)
New Revision: 945

Added:
   packages/unstable/hal/debian/patches/19_sonypi_support.patch
Modified:
   packages/unstable/hal/debian/changelog
   packages/unstable/hal/debian/patches/07_suspend2.patch
Log:
* debian/patches/18_hald_runner_fd_leak.patch
* debian/patches/debian/patches/19_sonypi_support.patch:
  - Added. Support sonypi using laptops (Closes: #375144) (From upstream git)
* debian/patches/07_suspend2.patch:
  - Updated. Don't try to use suspend2 to suspend a pmu machine, which can
  crash the machine. (Closes: #366008)

Modified: packages/unstable/hal/debian/changelog
===================================================================
--- packages/unstable/hal/debian/changelog	2006-08-15 12:18:06 UTC (rev 944)
+++ packages/unstable/hal/debian/changelog	2006-08-15 13:27:00 UTC (rev 945)
@@ -36,8 +36,13 @@
       (Closes: #361785) (From upstream git)
   * debian/patches/17_fix_dbus_090_build.patch:
     - Added. Fix build with dbus >= 0.90 (From upstream git)
-  * debian/patches/18_hald_runner_fd_leak.patch 
+  * debian/patches/18_hald_runner_fd_leak.patch
     - Added. Fix fd leak in hald-runner. Patch by Mike Hommey (Closes: #375143)
+  * debian/patches/debian/patches/19_sonypi_support.patch:
+    - Added. Support sonypi using laptops (Closes: #375144) (From upstream git)
+  * debian/patches/07_suspend2.patch:
+    - Updated. Don't try to use suspend2 to suspend a pmu machine, which can
+    crash the machine. (Closes: #366008)
 
   [ Sebastian Dröge  ]
   * debian/pycompat,
@@ -48,7 +53,7 @@
     + Bump Standards-Version to 3.7.2
     + Add myself to Uploaders
 
- -- Sjoerd Simons <sjoerd at debian.org>  Tue, 15 Aug 2006 14:05:22 +0200
+ -- Sjoerd Simons <sjoerd at debian.org>  Tue, 15 Aug 2006 15:20:09 +0200
 
 hal (0.5.7-2) unstable; urgency=low
 

Modified: packages/unstable/hal/debian/patches/07_suspend2.patch
===================================================================
--- packages/unstable/hal/debian/patches/07_suspend2.patch	2006-08-15 12:18:06 UTC (rev 944)
+++ packages/unstable/hal/debian/patches/07_suspend2.patch	2006-08-15 13:27:00 UTC (rev 945)
@@ -1,14 +1,14 @@
-diff -ruN hal-0.5.7-old/tools/hal-system-power-suspend hal-0.5.7/tools/hal-system-power-suspend
---- hal-0.5.7-old/tools/hal-system-power-suspend	2006-05-01 22:22:24.000000000 +0200
-+++ hal-0.5.7/tools/hal-system-power-suspend	2006-05-01 22:23:30.000000000 +0200
-@@ -50,6 +50,10 @@
- 	if [ -x "/usr/bin/powersave" ] ; then
- 	    $POWERSAVED_SUSPEND2RAM
- 	    RET=$?
+diff -u hal-0.5.7/tools/hal-system-power-suspend hal-0.5.7.1/tools/hal-system-power-suspend
+--- hal-0.5.7/tools/hal-system-power-suspend	2006-03-01 15:03:53.000000000 +0100
++++ hal-0.5.7.1/tools/hal-system-power-suspend	2006-08-15 15:16:59.000000000 +0200
+@@ -57,6 +57,10 @@
+ 		#PMU systems cannot use /sys/power/state yet, so use a helper to issue an ioctl
+ 		hal-system-power-pmu sleep
+ 		RET=$?
 +	elif [ -x "/usr/sbin/hibernate" ] ; then
 +		# Use hibernate configured for suspend-to-ram
 +		/usr/sbin/hibernate -F/etc/hibernate/ram.conf
 +		RET=$?
- 	elif [ -x "/usr/sbin/pmi" ] ; then
- 	    /usr/sbin/pmi action suspend force
- 	    RET=$?
+ 	elif [ -w "/sys/power/state" ] ; then
+ 	    # Use the raw kernel sysfs interface
+ 	    echo "mem" > /sys/power/state

Added: packages/unstable/hal/debian/patches/19_sonypi_support.patch
===================================================================
--- packages/unstable/hal/debian/patches/19_sonypi_support.patch	2006-08-15 12:18:06 UTC (rev 944)
+++ packages/unstable/hal/debian/patches/19_sonypi_support.patch	2006-08-15 13:27:00 UTC (rev 945)
@@ -0,0 +1,1506 @@
+diff -u hal-0.5.7/tools/hal-system-lcd-get-brightness hal-0.5.7.1/tools/hal-system-lcd-get-brightness
+--- hal-0.5.7/tools/hal-system-lcd-get-brightness	2006-03-01 15:03:53.000000000 +0100
++++ hal-0.5.7.1/tools/hal-system-lcd-get-brightness	2006-08-15 15:03:50.000000000 +0200
+@@ -58,6 +58,17 @@
+ 	# cat /proc/omnibook/lcd
+ 	#  LCD brightness:  7
+ 	value="`cat $HAL_PROP_LINUX_ACPI_PATH | awk '{print $3;}'`"
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" == "sonypi" ]; then
++		# spicctrl -B
++		# 70
++		# 0..255
++		value="`/usr/sbin/spicctrl -B`"
++		RETVAL=$?
++		if [ $RETVAL != 0 ]; then
++			echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++			exit 1;
++		fi
++		exit ${value}
+ else
+ 	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
+ 	echo "No ACPI method found" >&2
+diff -u hal-0.5.7/tools/hal-system-lcd-set-brightness hal-0.5.7.1/tools/hal-system-lcd-set-brightness
+--- hal-0.5.7/tools/hal-system-lcd-set-brightness	2006-03-01 15:03:53.000000000 +0100
++++ hal-0.5.7.1/tools/hal-system-lcd-set-brightness	2006-08-15 15:07:52.000000000 +0200
+@@ -19,7 +19,7 @@
+ read value
+ 
+ # Check for values outside range
+-if [ ${value} -lt 0 ] || [ ${value} -gt $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS ]; then
++if [ ${value} -lt 0 ] || [ ${value} -ge $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS ]; then
+ 	echo "org.freedesktop.Hal.Device.LaptopPanel.Invalid" >&2
+ 	echo "Brightness has to be between 0 and $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS!" >&2
+ 	exit 1
+@@ -34,6 +34,12 @@
+ 	exit 0
+ fi
+ 
++if [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" == "sonypi" ]; then
++	# spicctrl -b "{0..255}"
++	/usr/sbin/spicctrl -b ${value}
++	exit 0
++fi
++
+ # Check for file existance and that it's writable
+ if [ ! -w "$HAL_PROP_LINUX_ACPI_PATH" ]; then
+ 	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
+only in patch2:
+unchanged:
+--- hal-0.5.7.1-old/hald/linux2/acpi.c	2006-02-19 00:11:23.000000000 +0100
++++ hal-0.5.7.1/hald/linux2/acpi.c	2006-08-15 15:03:50.000000000 +0200
+@@ -48,6 +48,7 @@
+ 	ACPI_TYPE_PANASONIC_DISPLAY,
+ 	ACPI_TYPE_SONY_DISPLAY,
+ 	ACPI_TYPE_OMNIBOOK_DISPLAY,
++	ACPI_TYPE_SONYPI_DISPLAY,
+ 	ACPI_TYPE_BUTTON
+ };
+ 
+@@ -698,6 +699,10 @@
+ 		type = "omnibook";
+ 		desc = "Omnibook LCD Panel";
+ 		br_levels = 8;
++	} else if (acpi_type == ACPI_TYPE_SONYPI_DISPLAY) {
++		type = "sonypi";
++		desc = "Sony LCD Panel";
++		br_levels = 256;
+ 	} else {
+ 		type = "unknown";
+ 		desc = "Unknown LCD Panel";
+@@ -851,6 +856,44 @@
+ 		acpi_synthesize_item (path, method);
+ }
+ 
++static int sonypi_irq_list[] = { 11, 10, 9, 6, 5 };
++
++/** Synthesizes a sonypi object.
++ */
++static void
++acpi_synthesize_sonypi_display (void)
++{
++	HotplugEvent *hotplug_event;
++	gboolean found = FALSE;
++	guint i;
++	gchar *path;
++
++	HAL_INFO (("Processing sonypi display"));
++
++	/* Find the sonypi device, this doesn't work
++	 * if the sonypi device doesn't have an IRQ, sorry */
++	for (i = 0; i < G_N_ELEMENTS (sonypi_irq_list); i++) {
++		path =  g_strdup_printf ("/proc/irq/%d/sonypi", sonypi_irq_list[i]);
++		if (g_file_test (path, G_FILE_TEST_IS_DIR)) {
++			found = TRUE;
++			break;
++		}
++		g_free (path);
++	}
++
++	if (!found)
++		return;
++
++	hotplug_event = g_new0 (HotplugEvent, 1);
++	hotplug_event->action = HOTPLUG_ACTION_ADD;
++	hotplug_event->type = HOTPLUG_EVENT_ACPI;
++	g_strlcpy (hotplug_event->acpi.acpi_path, path, sizeof (hotplug_event->acpi.acpi_path));
++	hotplug_event->acpi.acpi_type = ACPI_TYPE_SONYPI_DISPLAY;
++	hotplug_event_enqueue (hotplug_event);
++
++	g_free (path);
++}
++
+ /** Scan the data structures exported by the kernel and add hotplug
+  *  events for adding ACPI objects.
+  *
+@@ -913,8 +956,10 @@
+ 	acpi_synthesize_display ("acpi/pcc", "brightness", ACPI_TYPE_PANASONIC_DISPLAY);
+ 	acpi_synthesize_display ("acpi/ibm", "brightness", ACPI_TYPE_IBM_DISPLAY);
+ 	acpi_synthesize_display ("acpi/sony", "brightness", ACPI_TYPE_SONY_DISPLAY);
+-	/* onmibook does not live under acpi GNOME#331458 */
++	/* omnibook does not live under acpi GNOME#331458 */
+ 	acpi_synthesize_display ("omnibook", "lcd", ACPI_TYPE_OMNIBOOK_DISPLAY);
++	/* sonypi doesn't have an acpi object fd.o#6729 */
++	acpi_synthesize_sonypi_display ();
+ 
+ 	/* setup timer for things that we need to poll */
+ 	g_timeout_add (ACPI_POLL_INTERVAL,
+@@ -1037,6 +1082,14 @@
+ 	.remove      = acpi_generic_remove
+ };
+ 
++static ACPIDevHandler acpidev_handler_laptop_panel_sonypi = {
++	.acpi_type   = ACPI_TYPE_SONYPI_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
+ static ACPIDevHandler acpidev_handler_button = {
+ 	.acpi_type   = ACPI_TYPE_BUTTON,
+ 	.add         = acpi_generic_add,
+@@ -1065,6 +1118,7 @@
+ 	&acpidev_handler_laptop_panel_asus,
+ 	&acpidev_handler_laptop_panel_sony,
+ 	&acpidev_handler_laptop_panel_omnibook,
++	&acpidev_handler_laptop_panel_sonypi,
+ 	NULL
+ };
+ 
+only in patch2:
+unchanged:
+--- hal-0.5.7.1-old/hald/linux2/acpi.c.orig	1970-01-01 01:00:00.000000000 +0100
++++ hal-0.5.7.1/hald/linux2/acpi.c.orig	2006-08-15 15:03:27.000000000 +0200
+@@ -0,0 +1,1234 @@
++/***************************************************************************
++ * CVSID: $Id: acpi.c,v 1.47 2006/02/18 23:11:23 hughsient Exp $
++ *
++ * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
++ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.com>
++ * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at web.de>
++ *
++ * 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 <string.h>
++
++#include "../device_info.h"
++#include "../logger.h"
++#include "../hald_dbus.h"
++#include "../util.h"
++
++#include "osspec_linux.h"
++
++#include "acpi.h"
++#include "hotplug.h"
++
++enum {
++	ACPI_TYPE_BATTERY,
++	ACPI_TYPE_PROCESSOR,
++	ACPI_TYPE_FAN,
++	ACPI_TYPE_AC_ADAPTER,
++	ACPI_TYPE_TOSHIBA_DISPLAY,
++	ACPI_TYPE_ASUS_DISPLAY,
++	ACPI_TYPE_IBM_DISPLAY,
++	ACPI_TYPE_PANASONIC_DISPLAY,
++	ACPI_TYPE_SONY_DISPLAY,
++	ACPI_TYPE_OMNIBOOK_DISPLAY,
++	ACPI_TYPE_BUTTON
++};
++
++#define ACPI_POLL_INTERVAL 30000
++
++typedef struct ACPIDevHandler_s
++{
++	int acpi_type;
++	HalDevice *(*add) (const gchar *acpi_path, HalDevice *parent, struct ACPIDevHandler_s *handler);
++	gboolean (*compute_udi) (HalDevice *d, struct ACPIDevHandler_s *handler);
++	gboolean (*remove) (HalDevice *d, struct ACPIDevHandler_s *handler);
++	gboolean (*refresh) (HalDevice *d, struct ACPIDevHandler_s *handler);
++} ACPIDevHandler;
++
++/** Just sets the ac_adapter.present key when called
++ *
++ *  @param	d		valid ac_adaptor HalDevice
++ */
++static void
++ac_adapter_refresh_poll (HalDevice *d)
++{
++	const char *path;
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return;
++	hal_util_set_bool_elem_from_file (d, "ac_adapter.present", path, "state", "state", 0, "on-line", FALSE);
++}
++
++static void
++battery_refresh_poll (HalDevice *d)
++{
++	const char *path;
++	const char *reporting_unit;
++	int reporting_current;
++	int reporting_lastfull;
++	int reporting_rate;
++	int normalised_current;
++	int normalised_lastfull;
++	int normalised_rate;
++	int design_voltage;
++	int voltage;
++	int remaining_time;
++	int remaining_percentage;
++	gboolean charging;
++	gboolean discharging;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return;
++
++	hal_util_set_bool_elem_from_file (d, "battery.rechargeable.is_charging", path,
++					  "state", "charging state", 0, "charging", TRUE);
++	hal_util_set_bool_elem_from_file (d, "battery.rechargeable.is_discharging", path,
++					  "state", "charging state", 0, "discharging", TRUE);
++	hal_util_set_string_elem_from_file (d, "battery.charge_level.capacity_state", path, 
++					    "state", "capacity state", 0, TRUE);
++	/*
++	 * we'll use the .reporting prefix as we don't know
++	 * if this data is energy (mWh) or unit enery (mAh)
++	 */
++	if (!hal_util_set_int_elem_from_file (d, "battery.reporting.current", path,
++					      "state", "remaining capacity", 0, 10, TRUE))
++		hal_device_property_set_int (d, "battery.reporting.current", 0);
++	if (!hal_util_set_int_elem_from_file (d, "battery.reporting.rate", path,
++					      "state", "present rate", 0, 10, TRUE))
++		hal_device_property_set_int (d, "battery.reporting.rate", 0);
++	/*
++	 * we'll need this if we need to convert mAh to mWh, but we should
++	 * also update it here anyway as the value will have changed
++	 */
++	hal_util_set_int_elem_from_file (d, "battery.voltage.current", path,
++					 "state", "present voltage", 0, 10, TRUE);
++	/* get all the data we know */
++	reporting_unit = hal_device_property_get_string (d,
++					"battery.reporting.unit");
++	reporting_current = hal_device_property_get_int (d,
++					"battery.reporting.current");
++	reporting_lastfull = hal_device_property_get_int (d,
++					"battery.reporting.last_full");
++	reporting_rate = hal_device_property_get_int (d,
++					"battery.reporting.rate");
++
++	/*
++	 * We are converting the unknown units into mWh because of ACPI's nature
++	 * of not having a standard "energy" unit.
++	 *
++	 * full details here: http://bugzilla.gnome.org/show_bug.cgi?id=309944
++	 */
++	if (reporting_unit && strcmp (reporting_unit, "mWh") == 0) {
++		/* units do not need conversion */
++		normalised_current = reporting_current;
++		normalised_lastfull = reporting_lastfull;
++		normalised_rate = reporting_rate;
++	} else if (reporting_unit && strcmp (reporting_unit, "mAh") == 0) {
++		/* convert mAh to mWh by multiplying by voltage.  due to the
++		 * general wonkiness of ACPI implementations, this is a lot
++		 * harder than it should have to be...
++		 */
++
++		design_voltage = hal_device_property_get_int (d, "battery.voltage.design");
++		voltage = hal_device_property_get_int (d, "battery.voltage.current");
++
++		/* Just in case we don't get design voltage information, then
++		 * this will pretend that we have 1mV.  This degrades our
++		 * ability to report accurate times on multi-battery systems
++		 * but will always prevent negative charge levels and allow
++		 * accurate reporting on single-battery systems.
++		 */
++		if (design_voltage <= 0)
++			design_voltage = 1;
++
++		/* If the current voltage is unknown or greater than design,
++		 * then use design voltage.
++		 */
++		if (voltage <= 0 || voltage > design_voltage)
++			voltage = design_voltage;
++
++		normalised_current = reporting_current * voltage;
++		normalised_lastfull = reporting_lastfull * voltage;
++		normalised_rate = reporting_rate * voltage;
++	} else {
++		/*
++		 * handle as if mWh, which is the most common case.
++		 */
++		normalised_current = reporting_current;
++		normalised_lastfull = reporting_lastfull;
++		normalised_rate = reporting_rate;
++	}
++
++	/*
++	 * Set the normalised keys.
++	 */
++	if (normalised_current < 0)
++		normalised_current = 0;
++	if (normalised_lastfull < 0)
++		normalised_lastfull = 0;
++	if (normalised_rate < 0)
++		normalised_rate = 0;
++
++	/*
++	 * Some laptops report a rate even when not charging or discharging.
++	 * If not charging and not discharging force rate to be zero.
++         *
++         * http://bugzilla.gnome.org/show_bug.cgi?id=323186
++	 */
++	charging = hal_device_property_get_bool (d, "battery.rechargeable.is_charging");
++	discharging = hal_device_property_get_bool (d, "battery.rechargeable.is_discharging");
++
++	if (!charging && !discharging)
++		normalised_rate = 0;
++
++	/*
++	 * Some laptops report current charge much larger than
++	 * full charge when at 100%.  Clamp back down to 100%.
++	 */
++	if (normalised_current > normalised_lastfull)
++	  	normalised_current = normalised_lastfull;
++
++	hal_device_property_set_int (d, "battery.charge_level.current", normalised_current);
++	hal_device_property_set_int (d, "battery.charge_level.last_full", normalised_lastfull);
++	hal_device_property_set_int (d, "battery.charge_level.rate", normalised_rate);
++
++	remaining_time = util_compute_time_remaining (d->udi, normalised_rate, normalised_current, normalised_lastfull,
++				hal_device_property_get_bool (d, "battery.rechargeable.is_discharging"),
++				hal_device_property_get_bool (d, "battery.rechargeable.is_charging"),
++				hal_device_property_get_bool (d, "battery.remaining_time.calculate_per_time"));
++	remaining_percentage = util_compute_percentage_charge (d->udi, normalised_current, normalised_lastfull);
++	/*
++	 * Only set keys if no error (signified with negative return value)
++	 * Scrict checking is needed to ensure that the values presented by HAL
++	 * are 100% acurate.
++	 */
++
++	if (remaining_time > 0)
++		hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
++	else
++		hal_device_property_remove (d, "battery.remaining_time");
++
++	if (remaining_percentage > 0)
++		hal_device_property_set_int (d, "battery.charge_level.percentage", remaining_percentage);
++	else
++		hal_device_property_remove (d, "battery.charge_level.percentage");
++}
++
++/** Recalculates the battery.reporting.last_full key as this may drift
++ *  over time.
++ *
++ *  @param	data		Ignored
++ *  @return			TRUE if we updated values
++ *
++ *  @note	This is called 120x less often than battery_refresh_poll
++ */
++static gboolean
++battery_poll_infrequently (gpointer data) {
++	
++	GSList *i;
++	GSList *battery_devices;
++	HalDevice *d;
++	const char *path;
++
++	battery_devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
++								    "battery.type",
++								    "primary");
++	
++	for (i = battery_devices; i != NULL; i = g_slist_next (i)) {
++		d = HAL_DEVICE (i->data);
++		if (hal_device_has_property (d, "linux.acpi_type") &&
++		    hal_device_property_get_bool (d, "battery.present")) {
++			hal_util_grep_discard_existing_data ();
++			device_property_atomic_update_begin ();
++			path = hal_device_property_get_string (d, "linux.acpi_path");
++			if (path != NULL)
++				hal_util_set_int_elem_from_file (d, "battery.reporting.last_full", path,
++								 "info", "last full capacity", 0, 10, TRUE);
++			device_property_atomic_update_end ();		
++		}
++	}
++
++	g_slist_free (battery_devices);
++	return TRUE;
++}
++
++
++/** Fallback polling method to refresh battery objects is plugged in
++ *
++ *  @return			TRUE
++ *
++ *  @note	This just calls battery_refresh_poll for each battery
++ */
++static gboolean
++acpi_poll_battery (void)
++{
++	GSList *i;
++	GSList *battery_devices;
++	HalDevice *d;
++
++	battery_devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
++								    "battery.type",
++								    "primary");
++	/*
++	 * These forced updates take care of really broken BIOS's that don't
++	 * emit batt events.
++	 */
++	for (i = battery_devices; i != NULL; i = g_slist_next (i)) {
++		d = HAL_DEVICE (i->data);
++		if (hal_device_has_property (d, "linux.acpi_type") &&
++		    hal_device_property_get_bool (d, "battery.present")) {
++			hal_util_grep_discard_existing_data ();
++			device_property_atomic_update_begin ();
++			battery_refresh_poll (d);
++			device_property_atomic_update_end ();		
++		}
++	}
++
++	g_slist_free (battery_devices);
++	return TRUE;
++}
++
++/** Fallback polling method to detect if the ac_adaptor is plugged in
++ *
++ *  @return			TRUE
++ *
++ *  @note	This just calls ac_adapter_refresh_poll for each ac_adapter
++ */
++static gboolean
++acpi_poll_acadap (void)
++{
++	GSList *i;
++	GSList *acadap_devices;
++	HalDevice *d;
++
++	acadap_devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
++								    "info.category",
++								    "ac_adapter");
++	/*
++	 * These forced updates take care of really broken BIOS's that don't
++	 * emit acad events.
++	 */
++	for (i = acadap_devices; i != NULL; i = g_slist_next (i)) {
++		d = HAL_DEVICE (i->data);
++		if (hal_device_has_property (d, "linux.acpi_type")) {
++			hal_util_grep_discard_existing_data ();
++			device_property_atomic_update_begin ();
++			ac_adapter_refresh_poll (d);
++			device_property_atomic_update_end ();		
++		}
++	}
++	g_slist_free (acadap_devices);
++	return TRUE;
++}
++
++/** Fallback polling method called every minute.
++ *
++ *  @param	data		Ignored
++ *  @return			TRUE
++ *
++ *  @note	This just forces a poll refresh for *every* ac_adaptor
++ *		and primary battery in the system.
++ */
++static gboolean
++acpi_poll (gpointer data)
++{
++	/*
++	 * These forced updates take care of really broken BIOS's that don't
++	 * emit acad or acadapt events.
++	 */
++	acpi_poll_acadap ();
++	acpi_poll_battery ();
++	return TRUE;
++}
++
++static gboolean
++ac_adapter_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	device_property_atomic_update_begin ();
++	/* only set up device new if really needed */
++	if (!hal_device_has_capability (d, "ac_adapter")){
++		hal_device_property_set_string (d, "info.product", "AC Adapter");
++		hal_device_property_set_string (d, "info.category", "ac_adapter");
++		hal_device_add_capability (d, "ac_adapter");
++	}
++	/* get .present value */
++	ac_adapter_refresh_poll (d);
++	device_property_atomic_update_end ();
++
++	/* refresh last full if ac plugged in/out */
++	battery_poll_infrequently (NULL);
++
++	/*
++	 * Refresh all the data for each battery.
++	 * This is required as the batteries may go from charging->
++	 * discharging, or charged -> discharging state, and we don't
++	 * want to wait for the next random refresh from acpi_poll.
++	 */
++	acpi_poll_battery ();
++	
++	return TRUE;
++}
++
++/** Removes all the possible battery.* keys.
++ *
++ *  @param	d		Valid battery HalDevice
++ *
++ *  @note	Removing a key that doesn't exist is OK.
++ */
++static void
++battery_refresh_remove (HalDevice *d)
++{
++	hal_device_property_remove (d, "battery.is_rechargeable");
++	hal_device_property_remove (d, "battery.rechargeable.is_charging");
++	hal_device_property_remove (d, "battery.rechargeable.is_discharging");
++	hal_device_property_remove (d, "battery.vendor");
++	hal_device_property_remove (d, "battery.model");
++	hal_device_property_remove (d, "battery.serial");
++	hal_device_property_remove (d, "battery.technology");
++	hal_device_property_remove (d, "battery.vendor");
++	hal_device_property_remove (d, "battery.charge_level.unit");
++	hal_device_property_remove (d, "battery.charge_level.current");
++	hal_device_property_remove (d, "battery.charge_level.percentage");
++	hal_device_property_remove (d, "battery.charge_level.last_full");
++	hal_device_property_remove (d, "battery.charge_level.design");
++	hal_device_property_remove (d, "battery.charge_level.capacity_state");
++	hal_device_property_remove (d, "battery.charge_level.warning");
++	hal_device_property_remove (d, "battery.charge_level.low");
++	hal_device_property_remove (d, "battery.charge_level.granularity_1");
++	hal_device_property_remove (d, "battery.charge_level.granularity_2");
++	hal_device_property_remove (d, "battery.charge_level.rate");
++	hal_device_property_remove (d, "battery.voltage.unit");
++	hal_device_property_remove (d, "battery.voltage.design");
++	hal_device_property_remove (d, "battery.voltage.current");
++	hal_device_property_remove (d, "battery.alarm.unit");
++	hal_device_property_remove (d, "battery.alarm.design");
++	hal_device_property_remove (d, "battery.reporting.current");
++	hal_device_property_remove (d, "battery.reporting.last_full");
++	hal_device_property_remove (d, "battery.reporting.design");
++	hal_device_property_remove (d, "battery.reporting.rate");
++	hal_device_property_remove (d, "battery.reporting.warning");
++	hal_device_property_remove (d, "battery.reporting.low");
++	hal_device_property_remove (d, "battery.reporting.granularity_1");
++	hal_device_property_remove (d, "battery.reporting.granularity_2");
++	hal_device_property_remove (d, "battery.reporting.unit");
++	hal_device_property_remove (d, "battery.remaining_time");
++}
++
++/** Adds all the possible battery.* keys and does coldplug (slowpath)
++ *  type calculations.
++ *
++ *  @param	d		Valid battery HalDevice
++ */
++static gboolean
++battery_refresh_add (HalDevice *d, const char *path)
++{
++	int reporting_design;
++	int reporting_warning;
++	int reporting_low;
++	int reporting_gran1;
++	int reporting_gran2;
++	int voltage_design;
++
++	const char *reporting_unit;
++
++	hal_util_set_string_elem_from_file (d, "battery.vendor", path, "info",
++					    "OEM info", 0, TRUE);
++	hal_util_set_string_elem_from_file (d, "battery.model", path, "info",
++					    "model number", 0, TRUE);
++	hal_util_set_string_elem_from_file (d, "battery.serial", path, "info",
++					    "serial number", 0, TRUE);
++	hal_util_set_string_elem_from_file (d, "battery.technology", path, "info",
++					    "battery type", 0, TRUE);
++	hal_util_set_string_elem_from_file (d, "battery.vendor", path, "info",
++					    "OEM info", 0, TRUE);
++
++	/*
++	 * we'll use the .reporting prefix as we don't know
++	 * if this data is energy (mWh) or unit enery (mAh)
++	 */
++	hal_util_set_string_elem_from_file (d, "battery.reporting.unit", path,
++					 "info", "design capacity", 1, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.last_full", path,
++					 "info", "last full capacity", 0, 10, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.design", path,
++					 "info", "design capacity", 0, 10, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.warning", path,
++					 "info", "design capacity warning", 0, 10, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.low", path,
++					 "info", "design capacity low", 0, 10, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.granularity_1", path,
++					 "info", "capacity granularity 1", 0, 10, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.reporting.granularity_2", path,
++					 "info", "capacity granularity 2", 0, 10, TRUE);
++	/*
++	 * we'll need this is we want to convert mAh to mWh
++	 */
++	hal_util_set_string_elem_from_file (d, "battery.voltage.unit", path, "info",
++					    "design voltage", 1, TRUE);
++	hal_util_set_int_elem_from_file (d, "battery.voltage.design", path,
++					 "info", "design voltage", 0, 10, TRUE);
++	/*
++	 * Convert the mWh or mAh units into mWh...
++	 * We'll do as many as we can here as the values
++	 * are not going to change.
++	 * We'll set the correct unit (or unknown) also.
++	 */
++	reporting_unit = hal_device_property_get_string (d, "battery.reporting.unit");
++	reporting_design = hal_device_property_get_int (d, "battery.reporting.design");
++	reporting_warning = hal_device_property_get_int (d, "battery.reporting.warning");
++	reporting_low = hal_device_property_get_int (d, "battery.reporting.low");
++	reporting_gran1 = hal_device_property_get_int (d, "battery.reporting.granularity_1");
++	reporting_gran2 = hal_device_property_get_int (d, "battery.reporting.granularity_2");
++
++	if (reporting_unit && strcmp (reporting_unit, "mWh") == 0) {
++		/* do not scale */
++		hal_device_property_set_int (d, "battery.charge_level.design", reporting_design);
++		hal_device_property_set_int (d, "battery.charge_level.warning", reporting_warning);
++		hal_device_property_set_int (d, "battery.charge_level.low", reporting_low);
++		hal_device_property_set_int (d, "battery.charge_level.granularity_1", reporting_gran1);
++		hal_device_property_set_int (d, "battery.charge_level.granularity_2", reporting_gran2);
++
++		/* set unit */
++		hal_device_property_set_string (d, "battery.charge_level.unit", "mWh");
++	} else if (reporting_unit && strcmp (reporting_unit, "mAh") == 0) {
++		voltage_design = hal_device_property_get_int (d, "battery.voltage.design");
++	
++		/* If design voltage is unknown, use 1mV. */
++		if (voltage_design <= 0)
++			voltage_design = 1;
++
++		/* scale by factor battery.voltage.design */
++		hal_device_property_set_int (d, "battery.charge_level.design",
++			reporting_design * voltage_design);
++		hal_device_property_set_int (d, "battery.charge_level.warning",
++			reporting_warning * voltage_design);
++		hal_device_property_set_int (d, "battery.charge_level.low",
++			reporting_low * voltage_design);
++		hal_device_property_set_int (d, "battery.charge_level.granularity_1",
++			reporting_gran1 * voltage_design);
++		hal_device_property_set_int (d, "battery.charge_level.granularity_2",
++			reporting_gran2 * voltage_design);
++
++		/* set unit */
++		hal_device_property_set_string (d, "battery.charge_level.unit",
++			"mWh"); /* not mAh! */
++	} else {
++		/*
++		 * Some ACPI BIOS's do not report the unit,
++		 * so we'll assume they are mWh.
++		 * We will report the guessing with the
++		 * battery.charge_level.unit key.
++		 */
++		hal_device_property_set_int (d,
++			"battery.charge_level.design", reporting_design);
++		hal_device_property_set_int (d,
++			"battery.charge_level.warning", reporting_warning);
++		hal_device_property_set_int (d,
++			"battery.charge_level.low", reporting_low);
++		hal_device_property_set_int (d,
++			"battery.charge_level.granularity_1", reporting_gran1);
++		hal_device_property_set_int (d,
++			"battery.charge_level.granularity_2", reporting_gran2);
++
++		/* set "Unknown ACPI Unit" unit so we can debug */
++		HAL_WARNING (("Unknown ACPI Unit!"));
++		hal_device_property_set_string (d, "battery.charge_level.unit",
++			"unknown");
++	}
++
++	/* set alarm if present */
++	if (hal_util_set_int_elem_from_file (d, "battery.alarm.design", path,
++					     "alarm", "alarm", 0, 10, TRUE))
++		hal_util_set_string_elem_from_file (d, "battery.alarm.unit", path, "alarm",
++						    "alarm", 1, TRUE);
++
++	/* we are assuming a laptop battery is rechargeable */
++	hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
++	return TRUE;
++}
++
++static gboolean
++battery_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	hal_device_property_set_string (d, "info.product", "Battery Bay");
++	hal_device_property_set_string (d, "battery.type", "primary");
++	hal_device_property_set_string (d, "info.category", "battery");
++	hal_device_add_capability (d, "battery");
++
++	/* Since we're using reuse==TRUE make sure we get fresh data for first read */
++	hal_util_grep_discard_existing_data ();
++
++	hal_util_set_bool_elem_from_file (d, "battery.present", path, "state", "present", 0, "yes", TRUE);
++	if (!hal_device_property_get_bool (d, "battery.present")) {
++		/* remove battery.* tags as battery not present */
++		device_property_atomic_update_begin ();
++		battery_refresh_remove (d);
++		device_property_atomic_update_end ();		
++	} else {
++		/* battery is present */
++		device_property_atomic_update_begin ();
++
++		/* So, it's pretty expensive to read from
++		 * /proc/acpi/battery/BAT%d/[info|state] so don't read
++		 * static data that won't change
++		 */
++		if (!hal_device_has_property (d, "battery.vendor")) {
++			/* battery has no information, so coldplug */
++			battery_refresh_add (d, path);
++		}
++
++		/* fill in the fast-path refresh values */
++		battery_refresh_poll (d);
++
++		device_property_atomic_update_end ();
++
++		/* poll ac adapter for machines which never give ACAP events */
++		acpi_poll_acadap ();
++	}
++
++	return TRUE;
++}
++
++static gboolean
++processor_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	hal_device_property_set_string (d, "info.product", "Processor");
++	hal_device_property_set_string (d, "info.category", "processor");
++	hal_device_add_capability (d, "processor");
++	hal_util_set_int_elem_from_file (d, "processor.number", path,
++					 "info", "processor id", 0, 10, FALSE);
++	hal_util_set_bool_elem_from_file (d, "processor.can_throttle", path,
++					  "info", "throttling control", 0, "yes", FALSE);
++	return TRUE;
++}
++
++static gboolean
++fan_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	hal_device_property_set_string (d, "info.product", "Fan");
++	hal_device_property_set_string (d, "info.category", "fan");
++	hal_device_add_capability (d, "fan");
++	hal_util_set_bool_elem_from_file (d, "fan.enabled", path,
++					  "state", "status", 0, "on", FALSE);
++	return TRUE;
++}
++
++/*
++ * The different laptop_panel ACPI handling code is below. When a nice sysfs
++ * interface comes along, we'll use that instead of these hacks.
++ * Using /proc/acpi/video does not work, this method is much more reliable.
++ */
++static gboolean
++laptop_panel_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++	int acpi_type;
++	char *type = NULL;
++	char *desc = NULL;
++	int br_levels = -1;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	acpi_type = hal_device_property_get_int (d, "linux.acpi_type");
++	hal_device_property_set_string (d, "info.category", "laptop_panel");
++	if (acpi_type == ACPI_TYPE_TOSHIBA_DISPLAY) {
++		type = "toshiba";
++		desc = "Toshiba LCD Panel";
++		br_levels = 8;
++	} else if (acpi_type == ACPI_TYPE_ASUS_DISPLAY) {
++		type = "asus";
++		desc = "ASUS LCD Panel";
++		br_levels = 16;
++	} else if (acpi_type == ACPI_TYPE_IBM_DISPLAY) {
++		type = "ibm";
++		desc = "IBM LCD Panel";
++		br_levels = 8;
++	} else if (acpi_type == ACPI_TYPE_PANASONIC_DISPLAY) {
++		type = "panasonic";
++		desc = "Panasonic LCD Panel";
++		br_levels = 16;
++	} else if (acpi_type == ACPI_TYPE_SONY_DISPLAY) {
++		type = "sony";
++		desc = "Sony LCD Panel";
++		br_levels = 8;
++	} else if (acpi_type == ACPI_TYPE_OMNIBOOK_DISPLAY) {
++		type = "omnibook";
++		desc = "Omnibook LCD Panel";
++		br_levels = 8;
++	} else {
++		type = "unknown";
++		desc = "Unknown LCD Panel";
++		br_levels = 0;
++		HAL_WARNING (("acpi_type not recognised!"));
++	}
++
++	hal_device_property_set_string (d, "info.product", desc);
++	/*
++	 * We will set laptop_panel.access_method as the scripts can use this to
++	 * determine the set/get parameters.
++	 */
++	hal_device_property_set_string (d, "laptop_panel.access_method", type);
++	/*
++	 * We can set laptop_panel.num_levels as it will not change, and allows us
++	 * to work out the percentage in the scripts.
++	 */
++	hal_device_property_set_int (d, "laptop_panel.num_levels", br_levels);
++	hal_device_add_capability (d, "laptop_panel");
++	return TRUE;
++}
++
++static gboolean
++button_refresh (HalDevice *d, ACPIDevHandler *handler)
++{
++	const char *path;
++	gchar *parent_path;
++	const gchar *button_type;
++
++	path = hal_device_property_get_string (d, "linux.acpi_path");
++	if (path == NULL)
++		return FALSE;
++
++	parent_path = hal_util_get_parent_path (path);
++	button_type = hal_util_get_last_element (parent_path);
++
++	hal_device_property_set_string (d, "button.type", button_type);
++
++	if (strcmp (button_type, "power") == 0)  
++		hal_device_property_set_string (d, "info.product", "Power Button");
++	else if (strcmp (button_type, "lid") == 0)  
++		hal_device_property_set_string (d, "info.product", "Lid Switch");
++	else if (strcmp (button_type, "sleep") == 0)  
++		hal_device_property_set_string (d, "info.product", "Sleep Button");
++
++	hal_device_property_set_string (d, "info.category", "button");
++	hal_device_add_capability (d, "button");
++	if (!hal_util_set_bool_elem_from_file (d, "button.state.value", path, "state", "state", 0, "closed", FALSE)) {
++		hal_device_property_set_bool (d, "button.has_state", FALSE);
++	} else {
++		hal_device_property_set_bool (d, "button.has_state", TRUE);
++	}
++
++	g_free (parent_path);
++
++	return TRUE;
++}
++
++/** Synthesizes a *specific* acpi object.
++ *
++ *  @param	fullpath	The ACPI path, e.g. "/proc/acpi/battery/BAT1"
++ *  @param	acpi_type	The type of device, e.g. ACPI_TYPE_BATTERY
++ */
++static void
++acpi_synthesize_item (const gchar *fullpath, int acpi_type)
++{
++	HotplugEvent *hotplug_event;
++	HAL_INFO (("Processing %s", fullpath));
++	hotplug_event = g_new0 (HotplugEvent, 1);
++	hotplug_event->action = HOTPLUG_ACTION_ADD;
++	hotplug_event->type = HOTPLUG_EVENT_ACPI;
++	g_strlcpy (hotplug_event->acpi.acpi_path, fullpath, sizeof (hotplug_event->acpi.acpi_path));
++	hotplug_event->acpi.acpi_type = acpi_type;
++	hotplug_event_enqueue (hotplug_event);
++}
++
++/** Synthesizes generic acpi objects, i.e. registers all the objects of type
++ *  into HAL. This lets us have more than one type of device e.g. BATx
++ *  in the same battery class.
++ *
++ *  @param	path		The ACPI path, e.g. "/proc/acpi/battery"
++ *  @param	acpi_type	The type of device, e.g. ACPI_TYPE_BATTERY
++ */
++static void
++acpi_synthesize (const gchar *path, int acpi_type)
++{
++	const gchar *f;
++	gchar _path[HAL_PATH_MAX];
++	gboolean is_laptop = FALSE;
++	GDir *dir;
++	GError *error = NULL;
++
++	dir = g_dir_open (path, 0, &error);
++	if (dir == NULL) {
++		HAL_ERROR (("Couldn't open %s: %s", path, error->message));
++		g_error_free (error);
++		return;
++	}
++
++	/* do for each object in directory */
++	while ((f = g_dir_read_name (dir)) != NULL) {
++		gchar buf[HAL_PATH_MAX];
++		
++		/* check if there is a battery bay or a LID button */
++		if (!is_laptop) {
++			if ( acpi_type == ACPI_TYPE_BATTERY ) { 
++				is_laptop = TRUE;
++			} else if ( acpi_type == ACPI_TYPE_BUTTON ) {
++				snprintf (_path, sizeof (_path), "%s/acpi/button/lid", get_hal_proc_path ());
++				if ( strcmp (path, _path) == 0 )
++					is_laptop = TRUE;
++			}
++		}
++		/* if there is a battery bay or LID, this is a laptop -> set the formfactor */
++		if ( is_laptop ) {
++			HalDevice *computer;
++
++			if ((computer = hal_device_store_find (hald_get_gdl (), "/org/freedesktop/Hal/devices/computer")) == NULL &&
++			    (computer = hal_device_store_find (hald_get_tdl (), "/org/freedesktop/Hal/devices/computer")) == NULL) {
++				HAL_ERROR (("No computer object?"));
++        		} else {
++				hal_device_property_set_string (computer, "system.formfactor", "laptop");
++			}
++		}
++
++		snprintf (buf, sizeof (buf), "%s/%s", path, f);
++		acpi_synthesize_item (buf, acpi_type);
++	}
++
++	/* close directory */
++	g_dir_close (dir);
++}
++
++/** If {procfs_path}/acpi/{vendor}/{display} is found, then add the
++ *  LaptopPanel device.
++ *
++ *  @param	vendor		The vendor name, e.g. sony
++ *  @param	display		The *possible* name of the brightness file
++ *  @param	method		The HAL enumerated type.
++ */
++static void
++acpi_synthesize_display (char *vendor, char *display, int method)
++{
++	gchar path[HAL_PATH_MAX];
++	snprintf (path, sizeof (path), "%s/%s/%s", get_hal_proc_path (), vendor, display);
++	/*
++	 * We do not use acpi_synthesize as the target is not a directory full
++	 * of directories, but a flat file list.
++	 */
++	if (g_file_test (path, G_FILE_TEST_EXISTS))
++		acpi_synthesize_item (path, method);
++}
++
++/** Scan the data structures exported by the kernel and add hotplug
++ *  events for adding ACPI objects.
++ *
++ *  @return			TRUE if, and only if, ACPI capabilities
++ *				were detected
++ */
++gboolean
++acpi_synthesize_hotplug_events (void)
++{
++	HalDevice *computer;
++	gchar path[HAL_PATH_MAX];
++
++	if (!g_file_test ("/proc/acpi/info", G_FILE_TEST_EXISTS))
++		return FALSE;
++
++	if ((computer = hal_device_store_find (hald_get_gdl (), "/org/freedesktop/Hal/devices/computer")) == NULL &&
++	    (computer = hal_device_store_find (hald_get_tdl (), "/org/freedesktop/Hal/devices/computer")) == NULL) {
++		HAL_ERROR (("No computer object?"));
++		return TRUE;
++	}
++
++	/* Set appropriate properties on the computer object */
++	hal_device_property_set_string (computer, "power_management.type", "acpi");
++	hal_util_set_string_elem_from_file (computer, "power_management.acpi.linux.version",
++					    "/proc/acpi", "info", "version", 0, FALSE);
++
++	/* collect batteries */
++	snprintf (path, sizeof (path), "%s/acpi/battery", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_BATTERY);
++
++	/* collect processors */
++	snprintf (path, sizeof (path), "%s/acpi/processor", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_PROCESSOR);
++
++	/* collect fans */
++	snprintf (path, sizeof (path), "%s/acpi/fan", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_FAN);
++
++	/* collect AC adapters */
++	snprintf (path, sizeof (path), "%s/acpi/ac_adapter", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_AC_ADAPTER);
++
++	/* collect buttons */
++	snprintf (path, sizeof (path), "%s/acpi/button/lid", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_BUTTON);
++	snprintf (path, sizeof (path), "%s/acpi/button/power", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_BUTTON);
++	snprintf (path, sizeof (path), "%s/acpi/button/sleep", get_hal_proc_path ());
++	acpi_synthesize (path, ACPI_TYPE_BUTTON);
++
++	/*
++	 * Collect video adaptors (from vendor added modules)
++	 * I *know* we should use the /proc/acpi/video/LCD method, but this
++	 * doesn't work. And it's depreciated.
++	 * When the sysfs code comes into mainline, we can use that, but until
++	 * then we can supply an abstracted interface to the user.
++	 */
++	acpi_synthesize_display ("acpi/toshiba", "lcd", ACPI_TYPE_TOSHIBA_DISPLAY);
++	acpi_synthesize_display ("acpi/asus", "brn", ACPI_TYPE_ASUS_DISPLAY);
++	acpi_synthesize_display ("acpi/pcc", "brightness", ACPI_TYPE_PANASONIC_DISPLAY);
++	acpi_synthesize_display ("acpi/ibm", "brightness", ACPI_TYPE_IBM_DISPLAY);
++	acpi_synthesize_display ("acpi/sony", "brightness", ACPI_TYPE_SONY_DISPLAY);
++	/* onmibook does not live under acpi GNOME#331458 */
++	acpi_synthesize_display ("omnibook", "lcd", ACPI_TYPE_OMNIBOOK_DISPLAY);
++
++	/* setup timer for things that we need to poll */
++	g_timeout_add (ACPI_POLL_INTERVAL,
++		       acpi_poll,
++		       NULL);
++	/* setup timer for things that we need only to poll infrequently*/
++	g_timeout_add ((ACPI_POLL_INTERVAL*120),
++		       battery_poll_infrequently,
++		       NULL);
++
++	return TRUE;
++}
++
++static HalDevice *
++acpi_generic_add (const gchar *acpi_path, HalDevice *parent, ACPIDevHandler *handler)
++{
++	HalDevice *d;
++	d = hal_device_new ();
++	hal_device_property_set_string (d, "linux.acpi_path", acpi_path);
++	hal_device_property_set_int (d, "linux.acpi_type", handler->acpi_type);
++	if (parent != NULL)
++		hal_device_property_set_string (d, "info.parent", parent->udi);
++	else
++		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
++	if (handler->refresh == NULL || !handler->refresh (d, handler)) {
++		g_object_unref (d);
++		d = NULL;
++	}
++	return d;
++}
++
++static gboolean
++acpi_generic_compute_udi (HalDevice *d, ACPIDevHandler *handler)
++{
++	gchar udi[256];
++	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
++			      "/org/freedesktop/Hal/devices/acpi_%s",
++			      hal_util_get_last_element (hal_device_property_get_string (d, "linux.acpi_path")));
++	hal_device_set_udi (d, udi);
++	hal_device_property_set_string (d, "info.udi", udi);
++	return TRUE;
++}
++
++static gboolean
++acpi_generic_remove (HalDevice *d, ACPIDevHandler *handler)
++{
++	return TRUE;
++}
++
++
++static ACPIDevHandler acpidev_handler_battery = {
++	.acpi_type   = ACPI_TYPE_BATTERY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = battery_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_processor = {
++	.acpi_type   = ACPI_TYPE_PROCESSOR,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = processor_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_fan = {
++	.acpi_type   = ACPI_TYPE_FAN,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = fan_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_toshiba = {
++	.acpi_type   = ACPI_TYPE_TOSHIBA_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_asus = {
++	.acpi_type   = ACPI_TYPE_ASUS_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_panasonic = {
++	.acpi_type   = ACPI_TYPE_PANASONIC_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_ibm = {
++	.acpi_type   = ACPI_TYPE_IBM_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_sony = {
++	.acpi_type   = ACPI_TYPE_SONY_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_laptop_panel_omnibook = {
++	.acpi_type   = ACPI_TYPE_OMNIBOOK_DISPLAY,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = laptop_panel_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_button = {
++	.acpi_type   = ACPI_TYPE_BUTTON,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = button_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler acpidev_handler_ac_adapter = {
++	.acpi_type   = ACPI_TYPE_AC_ADAPTER,
++	.add         = acpi_generic_add,
++	.compute_udi = acpi_generic_compute_udi,
++	.refresh     = ac_adapter_refresh,
++	.remove      = acpi_generic_remove
++};
++
++static ACPIDevHandler *acpi_handlers[] = {
++	&acpidev_handler_battery,
++	&acpidev_handler_processor,
++	&acpidev_handler_fan,
++	&acpidev_handler_button,
++	&acpidev_handler_ac_adapter,
++	&acpidev_handler_laptop_panel_toshiba,
++	&acpidev_handler_laptop_panel_ibm,
++	&acpidev_handler_laptop_panel_panasonic,
++	&acpidev_handler_laptop_panel_asus,
++	&acpidev_handler_laptop_panel_sony,
++	&acpidev_handler_laptop_panel_omnibook,
++	NULL
++};
++
++static void
++acpi_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
++{
++	void *end_token = (void *) userdata1;
++
++	HAL_INFO (("Add callouts completed udi=%s", d->udi));
++
++	/* Move from temporary to global device store */
++	hal_device_store_remove (hald_get_tdl (), d);
++	hal_device_store_add (hald_get_gdl (), d);
++
++	hotplug_event_end (end_token);
++}
++
++static void
++acpi_callouts_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
++{
++	void *end_token = (void *) userdata1;
++
++	HAL_INFO (("Remove callouts completed udi=%s", d->udi));
++
++	if (!hal_device_store_remove (hald_get_gdl (), d)) {
++		HAL_WARNING (("Error removing device"));
++	}
++
++	hotplug_event_end (end_token);
++}
++
++void
++hotplug_event_begin_add_acpi (const gchar *acpi_path, int acpi_type, HalDevice *parent, void *end_token)
++{
++	guint i;
++
++	HAL_INFO (("acpi_add: acpi_path=%s acpi_type=%d, parent=0x%08x", acpi_path, acpi_type, parent));
++
++	for (i = 0; acpi_handlers [i] != NULL; i++) {
++		ACPIDevHandler *handler;
++
++		handler = acpi_handlers[i];
++		if (handler->acpi_type == acpi_type) {
++			HalDevice *d;
++
++			d = handler->add (acpi_path, parent, handler);
++			if (d == NULL) {
++				/* didn't find anything - thus, ignore this hotplug event */
++				hotplug_event_end (end_token);
++				return;
++			}
++
++			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_ACPI);
++
++			/* Add to temporary device store */
++			hal_device_store_add (hald_get_tdl (), d);
++
++			/* Merge properties from .fdi files */
++			di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
++			di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
++
++			
++			/* Compute UDI */
++			if (!handler->compute_udi (d, handler)) {
++				hal_device_store_remove (hald_get_tdl (), d);
++				hotplug_event_end (end_token);
++				return;
++			}
++
++			/* Run callouts */
++			hal_util_callout_device_add (d, acpi_callouts_add_done, end_token, NULL);
++			return;
++		}
++	}
++	
++	/* didn't find anything - thus, ignore this hotplug event */
++	hotplug_event_end (end_token);
++}
++
++void
++hotplug_event_begin_remove_acpi (const gchar *acpi_path, int acpi_type, void *end_token)
++{
++	guint i;
++	HalDevice *d;
++
++	HAL_INFO (("acpi_rem: acpi_path=%s acpi_type=%d", acpi_path, acpi_type));
++
++	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.acpi_path", acpi_path);
++	if (d == NULL) {
++		HAL_WARNING (("Couldn't remove device with acpi path %s - not found", acpi_path));
++		goto out;
++	}
++
++	for (i = 0; acpi_handlers [i] != NULL; i++) {
++		ACPIDevHandler *handler;
++
++		handler = acpi_handlers[i];
++		if (handler->acpi_type == acpi_type) {
++			if (handler->remove (d, handler)) {
++				hal_util_callout_device_remove (d, acpi_callouts_remove_done, end_token, NULL);
++				goto out2;
++			}
++		}
++	}
++out:
++	/* didn't find anything - thus, ignore this hotplug event */
++	hotplug_event_end (end_token);
++out2:
++	;
++}
++
++gboolean
++acpi_rescan_device (HalDevice *d)
++{
++	guint i;
++	int acpi_type;
++
++	acpi_type = hal_device_property_get_int (d, "linux.acpi_type");
++
++	for (i = 0; acpi_handlers [i] != NULL; i++) {
++		ACPIDevHandler *handler;
++
++		handler = acpi_handlers[i];
++		if (handler->acpi_type == acpi_type) {
++			return handler->refresh (d, handler);
++		}
++	}
++
++	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));
++	return TRUE;
++}
++
++HotplugEvent *
++acpi_generate_add_hotplug_event (HalDevice *d)
++{
++	int acpi_type;
++	const char *acpi_path;
++	HotplugEvent *hotplug_event;
++
++	acpi_path = hal_device_property_get_string (d, "linux.acpi_path");
++	acpi_type = hal_device_property_get_int (d, "linux.acpi_type");
++
++	hotplug_event = g_new0 (HotplugEvent, 1);
++	hotplug_event->action = HOTPLUG_ACTION_ADD;
++	hotplug_event->type = HOTPLUG_EVENT_ACPI;
++	g_strlcpy (hotplug_event->acpi.acpi_path, acpi_path, sizeof (hotplug_event->acpi.acpi_path));
++	hotplug_event->acpi.acpi_type = acpi_type;
++	return hotplug_event;
++}
++
++HotplugEvent *
++acpi_generate_remove_hotplug_event (HalDevice *d)
++{
++	int acpi_type;
++	const char *acpi_path;
++	HotplugEvent *hotplug_event;
++
++	acpi_path = hal_device_property_get_string (d, "linux.acpi_path");
++	acpi_type = hal_device_property_get_int (d, "linux.acpi_type");
++
++	hotplug_event = g_new0 (HotplugEvent, 1);
++	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
++	hotplug_event->type = HOTPLUG_EVENT_ACPI;
++	g_strlcpy (hotplug_event->acpi.acpi_path, acpi_path, sizeof (hotplug_event->acpi.acpi_path));
++	hotplug_event->acpi.acpi_type = acpi_type;
++	return hotplug_event;
++}
+only in patch2:
+unchanged:
+--- hal-0.5.7.1-old/tools/hal-system-lcd-set-brightness.orig	1970-01-01 01:00:00.000000000 +0100
++++ hal-0.5.7.1/tools/hal-system-lcd-set-brightness.orig	2006-08-15 15:03:44.000000000 +0200
+@@ -0,0 +1,74 @@
++#!/bin/sh
++#
++# Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
++#
++# 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.
++
++# Check for environment variables
++if [ -z "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" ] || 
++   [ -z "$HAL_PROP_LAPTOP_PANEL_NUM_LEVELS" ] ; then
++        echo "Missing or empty environment variable(s)." >&2
++        echo "This script should be started by hald." >&2
++        exit 1
++fi
++
++# read value for set brightness
++read value
++
++# Check for values outside range
++if [ ${value} -lt 0 ] || [ ${value} -gt $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS ]; then
++	echo "org.freedesktop.Hal.Device.LaptopPanel.Invalid" >&2
++	echo "Brightness has to be between 0 and $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS!" >&2
++	exit 1
++fi
++
++if [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "pmu" ]; then
++	hal-system-power-pmu setlcd $value
++	if [ $? -ne 0 ]; then
++		echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++		exit 1
++	fi
++	exit 0
++fi
++
++# Check for file existance and that it's writable
++if [ ! -w "$HAL_PROP_LINUX_ACPI_PATH" ]; then
++	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++	echo "$1 not writable!" >&2
++	exit 1
++fi
++
++
++if [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "toshiba" ]; then
++	# echo "brightness: {0..x}" >/proc/acpi/toshiba/lcd
++	echo "brightness: $value" > $HAL_PROP_LINUX_ACPI_PATH
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "asus" ]; then
++	# echo {0..15} > /proc/acpi/asus/brn
++	# http://www.taupro.com/wiki/ChemBook/LCDdisplayPowerConfiguration
++	echo "$value" > $HAL_PROP_LINUX_ACPI_PATH
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "panasonic" ]; then
++	# echo {0..15} > /proc/acpi/pcc/brightness
++	# http://readlist.com/lists/vger.kernel.org/linux-kernel/7/36405.html
++	echo "$value" > $HAL_PROP_LINUX_ACPI_PATH
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "ibm" ]; then
++	# echo "level {0..7}" > /proc/acpi/ibm/brightness
++	# http://ibm-acpi.sourceforge.net/README
++	echo "level $value" > $HAL_PROP_LINUX_ACPI_PATH
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "sony" ]; then
++	# echo "{1..8}" > /proc/acpi/sony/brightness
++	# http://popies.net/sonypi/2.6-sony_acpi4.patch
++	echo "$value" > $HAL_PROP_LINUX_ACPI_PATH
++elif [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" = "omnibook" ]; then
++	# echo "{0..7}" > /proc/omnibook/lcd
++	# http://bugzilla.gnome.org/show_bug.cgi?id=331458
++	echo "$value" > $HAL_PROP_LINUX_ACPI_PATH
++else
++	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++	echo "No ACPI method found" >&2
++	exit 1
++	fi
++
++exit 0
+only in patch2:
+unchanged:
+--- hal-0.5.7.1-old/tools/hal-system-lcd-set-brightness.rej	1970-01-01 01:00:00.000000000 +0100
++++ hal-0.5.7.1/tools/hal-system-lcd-set-brightness.rej	2006-08-15 15:03:50.000000000 +0200
+@@ -0,0 +1,34 @@
++*************** if [ "$HAL_PROP_LAPTOP_PANEL_ACCESS_METH
++*** 27,41 ****
++  	exit 0
++  fi
++  
++- # Check for file existance and that it's writable
++- if [ ! -w $HAL_PROP_LINUX_ACPI_PATH ]; then
++  	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++  	echo "$1 not writable!" >&2
++  	exit 1
++  fi
++  
++  # Check for values outside range
++- if [ ${value} -lt 0 ] || [ ${value} -gt $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS ]; then
++  	echo "org.freedesktop.Hal.Device.LaptopPanel.Invalid" >&2
++  	echo "Brightness has to be between 0 and $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS!" >&2
++  	exit 1
++--- 27,42 ----
++  	exit 0
++  fi
++  
+++ # Check for file existance and that it's writable and that we don't have a sonypi
+++ # access method
+++ if [ ! -w $HAL_PROP_LINUX_ACPI_PATH -a "$HAL_PROP_LAPTOP_PANEL_ACCESS_METHOD" != "sonypi" ]; then
++  	echo "org.freedesktop.Hal.Device.LaptopPanel.NotSupported" >&2
++  	echo "$1 not writable!" >&2
++  	exit 1
++  fi
++  
++  # Check for values outside range
+++ if [ ${value} -lt 0 ] || [ ${value} -ge $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS ]; then
++  	echo "org.freedesktop.Hal.Device.LaptopPanel.Invalid" >&2
++  	echo "Brightness has to be between 0 and $HAL_PROP_LAPTOP_PANEL_NUM_LEVELS!" >&2
++  	exit 1




More information about the Pkg-utopia-commits mailing list