hal: Branch 'master'

Danny Kukawka dkukawka at kemper.freedesktop.org
Mon Aug 21 12:02:07 PDT 2006


 configure.in                       |   12 ++++++------
 hald/Makefile.am                   |    2 +-
 hald/debug-hald.sh                 |    2 +-
 hald/linux/Makefile.am             |    6 +++---
 hald/linux/addons/Makefile.am      |    2 +-
 hald/linux/probing/Makefile.am     |    2 +-
 hald/linux/probing/probe-storage.c |    4 ++--
 hald/run-hald.sh                   |    2 +-
 hald/valgrind-hald.sh              |    2 +-
 tools/Makefile.am                  |    2 +-
 10 files changed, 18 insertions(+), 18 deletions(-)

New commits:
diff-tree 019898159cd064f33bce4082d26295f9e3e6a2ef (from 2f30228bd76dbddedd62486386d56e46e3b7cc54)
Author: Danny Kukawka <danny.kukawka at web.de>
Date:   Mon Aug 21 20:59:21 2006 +0200

    move hald/linux2 to hald/linux and renamed backend
    
    Since there is no longer a hald/linux dir in the repository, we can move
    hald/linux2 to hald/linux and rename the related HALD_BACKEND to linux.

diff --git a/configure.in b/configure.in
index 1d22924..be68d8f 100644
--- a/configure.in
+++ b/configure.in
@@ -213,7 +213,7 @@ AC_CHECK_HEADERS(pci/pci.h, [
 	USE_LIBPCI=no AM_CONDITIONAL(HAVE_LIBPCI,false)])
 
 
-AC_ARG_WITH(backend, [  --with-backend=<name>   backend to use (linux2/solaris/dummy)],
+AC_ARG_WITH(backend, [  --with-backend=<name>   backend to use (linux/solaris/dummy)],
                       [
                       backend=$withval
                       ]
@@ -229,7 +229,7 @@ else
                    HALD_BACKEND="freebsd"
                    ;;
 	*-linux*)
-		   HALD_BACKEND="linux2"
+		   HALD_BACKEND="linux"
       		   ;;
         *)
 		   HALD_BACKEND="dummy"
@@ -237,7 +237,7 @@ else
     esac
 fi
 AM_CONDITIONAL(HALD_COMPILE_DUMMY, test x$HALD_BACKEND = xdummy, [Compiling for Dummy backend])
-AM_CONDITIONAL(HALD_COMPILE_LINUX2, test x$HALD_BACKEND = xlinux2, [Compiling for Linux])
+AM_CONDITIONAL(HALD_COMPILE_LINUX, test x$HALD_BACKEND = xlinux, [Compiling for Linux])
 AM_CONDITIONAL(HALD_COMPILE_FREEBSD, test x$HALD_BACKEND = xfreebsd, [Compiling for FreeBSD])
 AM_CONDITIONAL(HALD_COMPILE_SOLARIS, test x$HALD_BACKEND = xsolaris, [Compiling for Solaris])
 AC_SUBST(HALD_BACKEND)
@@ -443,9 +443,9 @@ hal.conf
 Makefile
 hald/Makefile
 hald/dummy/Makefile
-hald/linux2/Makefile
-hald/linux2/probing/Makefile
-hald/linux2/addons/Makefile
+hald/linux/Makefile
+hald/linux/probing/Makefile
+hald/linux/addons/Makefile
 hald/solaris/Makefile
 hald/haldaemon
 hald-runner/Makefile
diff --git a/hald/Makefile.am b/hald/Makefile.am
index b332390..e02e321 100644
--- a/hald/Makefile.am
+++ b/hald/Makefile.am
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in
 
-SUBDIRS = dummy linux2 solaris .
+SUBDIRS = dummy linux solaris .
 
 INCLUDES = \
 	-DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \
diff --git a/hald/debug-hald.sh b/hald/debug-hald.sh
index beae466..49f460b 100755
--- a/hald/debug-hald.sh
+++ b/hald/debug-hald.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-export HALD_RUNNER_PATH=`pwd`/linux2:`pwd`/linux2/probing:`pwd`/linux2/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
+export HALD_RUNNER_PATH=`pwd`/linux:`pwd`/linux/probing:`pwd`/linux/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
 export PATH=`pwd`/../hald-runner:$PATH
 export HAL_FDI_SOURCE_PREPROBE=../fdi/preprobe
 export HAL_FDI_SOURCE_INFORMATION=../fdi/information
diff --git a/hald/linux/.gitignore b/hald/linux/.gitignore
new file mode 100644
index 0000000..4bec0e4
--- /dev/null
+++ b/hald/linux/.gitignore
@@ -0,0 +1,8 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
+*.o
+*~
diff --git a/hald/linux/Makefile.am b/hald/linux/Makefile.am
new file mode 100644
index 0000000..a3bf2bc
--- /dev/null
+++ b/hald/linux/Makefile.am
@@ -0,0 +1,37 @@
+
+SUBDIRS = probing addons .
+
+INCLUDES = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-I$(top_srcdir) -I.. \
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+if HALD_COMPILE_LINUX
+noinst_LTLIBRARIES = libhald_linux.la
+endif
+
+libhald_linux_la_SOURCES =					\
+				osspec.c			\
+	osspec_linux.h						\
+	hotplug.h		hotplug.c			\
+	hotplug_helper.h					\
+	coldplug.h		coldplug.c			\
+	physdev.h		physdev.c			\
+	classdev.h		classdev.c			\
+	blockdev.h		blockdev.c			\
+	acpi.h			acpi.c				\
+	apm.h			apm.c				\
+	pmu.h			pmu.c				\
+	ids.h			ids.c
+
+
+
+
+
+
+
+
diff --git a/hald/linux/acpi.c b/hald/linux/acpi.c
new file mode 100644
index 0000000..4274d77
--- /dev/null
+++ b/hald/linux/acpi.c
@@ -0,0 +1,1361 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * 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 "../hald_dbus.h"
+#include "../logger.h"
+#include "../util.h"
+#include "../util_pm.h"
+
+#include "osspec_linux.h"
+
+#include "acpi.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_SONYPI_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 1V.  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 = 1000; /* mV */
+
+		/* 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) / 1000;
+		normalised_lastfull = (reporting_lastfull * voltage) / 1000;
+		normalised_rate = (reporting_rate * voltage) / 1000;
+	} 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 1V. */
+		if (voltage_design <= 0)
+			voltage_design = 1000; /* mV */;
+
+		/* scale by factor battery.voltage.design */
+		hal_device_property_set_int (d, "battery.charge_level.design",
+			(reporting_design * voltage_design) / 1000);
+		hal_device_property_set_int (d, "battery.charge_level.warning",
+			(reporting_warning * voltage_design) / 1000);
+		hal_device_property_set_int (d, "battery.charge_level.low",
+			(reporting_low * voltage_design) / 1000);
+		hal_device_property_set_int (d, "battery.charge_level.granularity_1",
+			(reporting_gran1 * voltage_design) / 1000);
+		hal_device_property_set_int (d, "battery.charge_level.granularity_2",
+			(reporting_gran2 * voltage_design) / 1000);
+
+		/* 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 gchar *
+get_processor_model_name (gint proc_num)
+{
+	gchar *model_name;
+
+	gchar  *contents = NULL;
+	GError *error    = NULL;
+
+	gchar **lines;
+
+	gint proc_num_i;
+
+	gchar *cursor;
+	gint   i;
+
+
+	if (g_file_get_contents ("/proc/cpuinfo", & contents, NULL, & error)) {
+		lines = g_strsplit (contents, "\n", 0);
+
+		for (i = 0; lines [i]; ++i) {
+			if (strstr (lines [i], "processor\t:")) {
+				cursor = strstr (lines [i], ":");
+
+				proc_num_i = atoi (cursor + 1);
+
+				if (proc_num_i == proc_num) {
+					for (; lines [i]; ++i) {
+						if (strstr (lines [i], "model name\t:")) {
+							cursor = strstr (lines [i], ":");
+
+							g_strstrip (++ cursor);
+
+							model_name = g_strdup (cursor);
+
+							g_strfreev (lines);
+							g_free     (contents);
+
+							return model_name;
+						}
+					}
+				}
+			}
+		}
+	}
+	else {
+		HAL_ERROR (("Couldn't open /proc/cpuinfo: %s", error->message));
+
+		g_error_free (error);
+	}
+
+	return NULL;
+}
+
+static gboolean
+processor_refresh (HalDevice *d, ACPIDevHandler *handler)
+{
+	const char *path;
+
+	gchar *model_name;
+	gint   proc_num;
+
+	path = hal_device_property_get_string (d, "linux.acpi_path");
+	if (path == NULL)
+		return FALSE;
+
+	proc_num = hal_util_grep_int_elem_from_file (
+		path, "info", "processor id", 0, 10, FALSE
+	);
+
+	if ((model_name = get_processor_model_name (proc_num))) {
+		hal_device_property_set_string (d, "info.product", model_name);
+
+		g_free (model_name);
+	}
+	else
+		hal_device_property_set_string (d, "info.product", "Unknown 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 if (acpi_type == ACPI_TYPE_SONYPI_DISPLAY) {
+		type = "sonypi";
+		desc = "Sony LCD Panel";
+		br_levels = 256;
+	} 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);
+}
+
+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"));
+
+        /* Check that we don't support brightness change through ACPI,
+	 * for type3 VAIOs */
+	if (g_file_test ("/proc/acpi/sony/brightness", G_FILE_TEST_EXISTS))
+		return;
+
+	/* 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.
+ *
+ *  @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);
+	/* 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,
+		       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_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,
+	.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,
+	&acpidev_handler_laptop_panel_sonypi,
+	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;
+}
diff --git a/hald/linux/acpi.h b/hald/linux/acpi.h
new file mode 100644
index 0000000..f7ed07a
--- /dev/null
+++ b/hald/linux/acpi.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
+ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef ACPI_H
+#define ACPI_H
+
+#include "../hald.h"
+#include "hotplug.h"
+
+gboolean acpi_synthesize_hotplug_events (void);
+
+void hotplug_event_begin_add_acpi (const gchar *acpi_path, int acpi_type, HalDevice *parent, void *end_token);
+
+void hotplug_event_begin_remove_acpi (const gchar *acpi_path, int acpi_type, void *end_token);
+
+gboolean acpi_rescan_device (HalDevice *d);
+
+HotplugEvent *acpi_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *acpi_generate_remove_hotplug_event (HalDevice *d);
+
+#endif /* ACPI_H */
diff --git a/hald/linux/addons/.gitignore b/hald/linux/addons/.gitignore
new file mode 100644
index 0000000..6c2e509
--- /dev/null
+++ b/hald/linux/addons/.gitignore
@@ -0,0 +1,16 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
+hald-addon-acpi
+hald-addon-hid-ups
+hald-addon-pmu
+hald-addon-storage
+hald-addon-usb-csr
+hald-addon-keyboard
+hald-addon-acpi-buttons-toshiba
+hald-addon-macbookpro-backlight
+*.o
+*~
diff --git a/hald/linux/addons/Makefile.am b/hald/linux/addons/Makefile.am
new file mode 100644
index 0000000..65819f4
--- /dev/null
+++ b/hald/linux/addons/Makefile.am
@@ -0,0 +1,54 @@
+
+INCLUDES = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+        -I$(top_srcdir) -I$(top_srcdir)/hald \
+        @GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+if HALD_COMPILE_LINUX
+libexec_PROGRAMS  = 			\
+	hald-addon-acpi 		\
+	hald-addon-acpi-buttons-toshiba \
+	hald-addon-hid-ups 		\
+	hald-addon-keyboard 		\
+	hald-addon-pmu			\
+	hald-addon-storage
+
+if HAVE_LIBPCI
+libexec_PROGRAMS += hald-addon-macbookpro-backlight
+endif
+if HAVE_LIBUSB
+libexec_PROGRAMS += hald-addon-usb-csr
+endif
+endif
+
+hald_addon_acpi_SOURCES = addon-acpi.c ../../logger.c ../../util_helper.c
+hald_addon_acpi_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_addon_acpi_buttons_toshiba_SOURCES = addon-acpi-buttons-toshiba.c ../../logger.c ../../util_helper.c
+hald_addon_acpi_buttons_toshiba_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@
+
+hald_addon_hid_ups_SOURCES = addon-hid-ups.c ../../logger.c ../../util_helper.c
+hald_addon_hid_ups_LDADD = $(top_builddir)/libhal/libhal.la 
+
+hald_addon_keyboard_SOURCES = addon-keyboard.c ../../logger.c ../../util_helper.c
+hald_addon_keyboard_LDADD = $(top_builddir)/libhal/libhal.la 
+
+if HAVE_LIBPCI
+hald_addon_macbookpro_backlight_SOURCES = addon-macbookpro-backlight.c ../../logger.c
+hald_addon_macbookpro_backlight_LDADD = $(top_builddir)/libhal/libhal.la -lpci @GLIB_LIBS@
+endif
+
+hald_addon_pmu_SOURCES = addon-pmu.c ../../logger.c ../../util_helper.c
+hald_addon_pmu_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_addon_storage_SOURCES = addon-storage.c ../../logger.c ../../util_helper.c
+hald_addon_storage_LDADD = $(top_builddir)/libhal/libhal.la
+
+if HAVE_LIBUSB
+hald_addon_usb_csr_SOURCES = addon-usb-csr.c ../../logger.c ../../util_helper.c
+hald_addon_usb_csr_LDADD = $(top_builddir)/libhal/libhal.la -lusb @GLIB_LIBS@
+endif
diff --git a/hald/linux/addons/addon-acpi-buttons-toshiba.c b/hald/linux/addons/addon-acpi-buttons-toshiba.c
new file mode 100644
index 0000000..7252759
--- /dev/null
+++ b/hald/linux/addons/addon-acpi-buttons-toshiba.c
@@ -0,0 +1,184 @@
+/*! @file	addon-acpi-buttons-toshiba.c
+ *  @brief	Toshiba SMM Button Addon
+ *  @author	Richard Hughes <richard at hughsie.com>
+ *  @date	2005-10-15
+ *
+ *  @note	Low level routines from IAL, Copyright (C) 2004, 2005
+ *		Timo Hoenig <thoenig at nouse.net>
+ */
+/*
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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 Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <linux/input.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <glib/gmain.h>
+
+#include "libhal/libhal.h"
+#include "../../logger.h"
+
+/** Toshiba ACPI key interface */
+#define TOSHIBA_ACPI_KEYS		"/proc/acpi/toshiba/keys"
+
+/** Polling frequency in ms */
+#define TOSHIBA_POLL_FREQ       	250
+
+static LibHalContext *ctx = NULL;
+static char* udi;
+
+/** Flush keys from the Toshiba hotkey register */
+static void
+toshiba_key_flush (void)
+{
+	int hotkey_ready = 1;
+	int value;
+	FILE *fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
+	if (!fp) {
+		HAL_DEBUG (("Could not open %s!", TOSHIBA_ACPI_KEYS));
+		return;
+	}
+	while (hotkey_ready) {
+		fprintf (fp, "hotkey_ready:0\n");
+		fclose (fp);
+		fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
+		if (fscanf (fp, "hotkey_ready: %d\nhotkey: 0x%4x", &hotkey_ready, &value) < 2)
+			HAL_WARNING(("Warning: failure while parse %s", TOSHIBA_ACPI_KEYS));
+	}
+	if (fp)
+		fclose (fp);
+}
+
+/** Check whether there is a new event in the hotkey register
+ *
+ *  @param	value	The key id pressed, passed by reference
+ *  @returns		TRUE if there is an event pending, FALSE if no event pending.
+ */
+static gboolean
+toshiba_key_ready (int *value)
+{
+	FILE *fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
+	int hotkey_ready = -1;
+
+	if (!fp)
+		return FALSE;
+
+	if (fscanf (fp, "hotkey_ready: %1d\nhotkey: 0x%4x", &hotkey_ready, value) < 2)
+		HAL_WARNING (("Warning: failure while parse %s", TOSHIBA_ACPI_KEYS)); 
+
+	if (hotkey_ready) {
+		fprintf (fp, "hotkey_ready:0\n");
+		fclose (fp);
+		return TRUE;
+	}
+	fclose (fp);
+	return FALSE;
+}
+
+/** Callback to poll hotkey register and report occuring events.
+ *
+ *  @returns		TRUE on success, else FALSE.
+ */
+static gboolean
+toshiba_key_poll (void)
+{
+	char *result;
+	int value;
+	DBusError error;
+	dbus_error_init (&error);
+
+	/* for each key */
+	while (toshiba_key_ready (&value) == TRUE) {
+		result = NULL;
+		if (value == 0x101) /* FnESC */
+			result = "mute";
+		else if (value == 0x13b) /* FnF1 */
+			result = "lock";
+		else if (value == 0x13c) /* FnF2 */
+			result = "search";
+		else if (value == 0x13d) /* FnF3 */
+			result = "suspend";
+		else if (value == 0x13e) /* FnF4 */
+			result = "hibernate";
+		else if (value == 0x140) /* FnF6 */
+			result = "brightness-down";
+		else if (value == 0x141) /* FnF7 */
+			result = "brightness-up";
+		else if (value == 0x142) /* FnF8 */
+			result = "wifi-power";
+
+		if (result) {
+			HAL_DEBUG (("Sending condition '%s'", result));
+			libhal_device_emit_condition (ctx, udi, "ButtonPressed", result, &error);
+			if (dbus_error_is_set (&error)) {
+				HAL_ERROR (("Failed to send condition: %s", error.message));
+				dbus_error_free (&error);
+				return FALSE;
+			}
+		}
+	}
+	return TRUE;
+}
+
+/** Main program
+ */
+int
+main (int argc, char **argv)
+{
+	GMainLoop *loop = NULL;
+	DBusError error;
+	FILE *fp;
+
+	setup_logger ();
+
+	udi = getenv ("UDI");
+	if (udi == NULL) {
+		HAL_ERROR (("Failed to get UDI"));
+		return 1;
+	}
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		HAL_ERROR (("Unable to initialise libhal context: %s", error.message));
+		return 1;
+	}
+
+	/* Check for Toshiba ACPI interface /proc/acpi/toshiba/keys */
+	fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
+	if (!fp) {
+		HAL_ERROR (("Could not open %s! Aborting.", TOSHIBA_ACPI_KEYS));
+		return 0;
+	}
+	fclose (fp);
+
+	/* Flush keys as we may have some already in buffer */
+	toshiba_key_flush ();
+
+	/* Get the new input */
+	g_timeout_add (TOSHIBA_POLL_FREQ, (GSourceFunc) toshiba_key_poll, NULL);
+
+	loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (loop);
+	return 0;
+}
diff --git a/hald/linux/addons/addon-acpi.c b/hald/linux/addons/addon-acpi.c
new file mode 100644
index 0000000..4b19321
--- /dev/null
+++ b/hald/linux/addons/addon-acpi.c
@@ -0,0 +1,211 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-acpi.c : Listen to ACPI events and modify hal device objects
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005 Ryan Lortie <desrt at desrt.ca>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+#include "../../util_helper.h"
+
+#ifdef ACPI_PROC
+static FILE *
+acpi_get_event_fp_kernel (void)
+{
+	FILE *fp = NULL;
+
+	fp = fopen ("/proc/acpi/event", "r");
+
+	if (fp == NULL)
+		HAL_ERROR (("Cannot open /proc/acpi/event: %s", strerror (errno)));
+
+	return fp;
+}
+#endif
+
+#ifdef ACPI_ACPID
+static FILE *
+acpi_get_event_fp_acpid (void)
+{
+	FILE *fp = NULL;
+
+	struct sockaddr_un addr;
+	int fd;
+
+	if( (fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0 ) {
+		HAL_ERROR (("Cannot create socket: %s", strerror (errno)));
+		return NULL;
+	}
+
+	memset (&addr, 0, sizeof addr);
+	addr.sun_family = AF_UNIX;
+	strncpy (addr.sun_path, "/var/run/acpid.socket", sizeof addr.sun_path);
+
+	if (connect (fd, (struct sockaddr *) &addr, sizeof addr) < 0) {
+		HAL_ERROR (("Cannot connect to acpid socket: %s", strerror (errno)));
+		close (fd);
+	} else {
+		fp = fdopen (fd, "r");
+
+		if (fp == NULL) {
+			HAL_ERROR (("fdopen failed: %s", strerror (errno)));
+			close (fd);
+		}
+	}
+
+	return fp;
+}
+#endif
+
+
+static void
+main_loop (LibHalContext *ctx, FILE *eventfp)
+{
+	unsigned int acpi_num1;
+	unsigned int acpi_num2;
+	char acpi_path[256];
+	char acpi_name[256];
+	DBusError error;
+	char event[256];
+
+	dbus_error_init (&error);
+
+	while (fgets (event, sizeof event, eventfp))
+	{
+		HAL_DEBUG (("event is '%s'", event));
+
+		if (sscanf (event, "%s %s %x %x", acpi_path, acpi_name, &acpi_num1, &acpi_num2) == 4) {
+			char udi[256];
+
+			snprintf (udi, sizeof (udi), "/org/freedesktop/Hal/devices/acpi_%s", acpi_name);
+
+			if (strncmp (acpi_path, "button", sizeof ("button") - 1) == 0) {
+				char *type;
+
+				HAL_DEBUG (("button event"));
+
+				/* TODO: only rescan if button got state */
+				libhal_device_rescan (ctx, udi, &error);
+
+				type = libhal_device_get_property_string(ctx, udi, 
+									 "button.type",
+									 &error);
+				if (type != NULL) {
+					libhal_device_emit_condition (ctx, udi, "ButtonPressed",
+								      type, &error);
+					libhal_free_string(type);
+				} else {
+					libhal_device_emit_condition (ctx, udi, "ButtonPressed", "", &error);
+				}
+			} else if (strncmp (acpi_path, "ac_adapter", sizeof ("ac_adapter") - 1) == 0) {
+				HAL_DEBUG (("ac_adapter event"));
+				libhal_device_rescan (ctx, udi, &error);
+			} else if (strncmp (acpi_path, "battery", sizeof ("battery") - 1) == 0) {
+				HAL_DEBUG (("battery event"));
+				libhal_device_rescan (ctx, udi, &error);
+			}
+
+		} else {
+			HAL_DEBUG (("cannot parse event"));
+		}
+
+		if (dbus_error_is_set (&error)) {
+	        	/* Free the error (which include a dbus_error_init()) 
+			   This should prevent errors if a call above fails */
+			dbus_error_free (&error);
+		}
+	}
+
+	dbus_error_free (&error);
+	fclose (eventfp);
+}
+
+int
+main (int argc, char **argv)
+{
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	FILE *eventfp;
+
+	hal_set_proc_title_init (argc, argv);
+
+	/* If we don't even consider the /proc ACPI interface, drop privileges
+	 * right away */
+#ifndef ACPI_PROC
+	drop_privileges (0);
+#endif
+
+	setup_logger ();
+
+	dbus_error_init (&error);
+
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		HAL_ERROR (("Unable to initialise libhal context: %s", error.message));
+		return 1;
+	}
+
+#ifdef ACPI_PROC
+	/* If we can connect directly to the kernel then do so. */
+	eventfp = acpi_get_event_fp_kernel ();
+	drop_privileges (0);
+
+	if (eventfp) {
+		hal_set_proc_title ("hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event");
+		main_loop (ctx, eventfp);
+		HAL_ERROR (("Lost connection to kernel acpi event source - exiting"));
+		return 1;
+	}
+#endif
+
+	while (1)
+	{
+#ifdef ACPI_ACPID
+		/* Else, try to use acpid. */
+		if ((eventfp = acpi_get_event_fp_acpid ())) {
+			hal_set_proc_title ("hald-addon-acpi: listening on acpid socket /var/run/acpid.socket");
+			main_loop (ctx, eventfp);
+			HAL_DEBUG (("Cannot connect to acpid event socket - retry connect"));
+		}
+#endif
+		
+		/* If main_loop exits or we failed a reconnect attempt then
+		 * sleep for 5s and try to reconnect (again). */
+		sleep (5);
+	}
+
+	return 1;
+}
+
+/* vim:set sw=8 noet: */
diff --git a/hald/linux/addons/addon-hid-ups.c b/hald/linux/addons/addon-hid-ups.c
new file mode 100644
index 0000000..1361ed6
--- /dev/null
+++ b/hald/linux/addons/addon-hid-ups.c
@@ -0,0 +1,351 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-hid-ups.c : Detect UPS'es using the USB HID interface and
+ *                   add and maintain battery.* properties
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ *
+ * Based on hid-ups.c: Copyright (c) 2001 Vojtech Pavlik
+ *                     <vojtech at ucw.cz>, Copyright (c) 2001 Paul
+ *                     Stewart <hiddev at wetlogic.net>, Tweaked by Kern
+ *                     Sibbald <kern at sibbald.com> to learn about USB
+ *                     UPSes.  hid-ups.c is GPLv2 and available from
+ *                     examples directory of version 3.10.16 of the
+ *                     acpupsd project; see http://www.apcupsd.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.
+ *
+ * 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
+
+/* asm/types.h required for __s32 in linux/hiddev.h */
+#include <asm/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/hiddev.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../util_helper.h"
+#include "../../logger.h"
+
+#define UPS_USAGE		0x840000
+#define UPS_SERIAL		0x8400fe
+#define UPS_CHEMISTRY		0x850089
+#define UPS_CAPACITY_MODE	0x85002c
+#define UPS_BATTERY_VOLTAGE	0x840030
+#define UPS_BELOW_RCL		0x840042
+#define UPS_SHUTDOWN_IMMINENT	0x840069
+#define UPS_PRODUCT		0x8400fe
+#define UPS_SERIALNUMBER	0x8400ff
+#define UPS_CHARGING		0x850044
+#define UPS_DISCHARGING 	0x850045
+#define UPS_REMAINING_CAPACITY	0x850066
+#define UPS_RUNTIME_TO_EMPTY	0x850068
+#define UPS_AC_PRESENT		0x8500d0
+#define UPS_BATTERYPRESENT	0x8500d1
+#define UPS_DESIGNCAPACITY	0x850083
+#define UPS_DEVICENAME		0x850088
+#define UPS_DEVICECHEMISTRY	0x850089
+#define UPS_RECHARGEABLE	0x85008b
+#define UPS_OEMINFORMATION	0x85008f
+
+#define STATE_NORMAL 0		      /* unit powered */
+#define STATE_DEBOUNCE 1	      /* power failure */
+#define STATE_BATTERY 2 	      /* power failure confirmed */
+
+static dbus_bool_t
+is_ups (int fd)
+{
+	unsigned int i;
+	dbus_bool_t ret;
+	struct hiddev_devinfo device_info;
+
+	ret = FALSE;
+
+	if (ioctl (fd, HIDIOCGDEVINFO, &device_info) < 0)
+		goto out;
+
+	for (i = 0; i < device_info.num_applications; i++) {
+		if ((ioctl(fd, HIDIOCAPPLICATION, i) & 0xff0000) == UPS_USAGE) {
+			ret = TRUE;
+			goto out;
+		}			
+	}
+
+out:
+	return ret;
+}
+
+static char *
+ups_get_string (int fd, int sindex)
+{
+	static struct hiddev_string_descriptor sdesc;
+	
+	if (sindex == 0) {
+		return "";
+	}
+	sdesc.index = sindex;
+	if (ioctl (fd, HIDIOCGSTRING, &sdesc) < 0) {
+		return "";
+	}
+	HAL_DEBUG (("foo: '%s'", sdesc.value));
+	return sdesc.value;
+}
+
+
+static dbus_bool_t
+ups_get_static (LibHalContext *ctx, const char *udi, int fd)
+{
+	int ret;
+	struct hiddev_report_info rinfo;
+	struct hiddev_field_info finfo;
+	struct hiddev_usage_ref uref;
+	int rtype;
+	unsigned int i, j;
+	DBusError error;
+
+	/* set to failure */
+	ret = FALSE;
+
+	/* first check that we are an UPS */
+	if (!is_ups (fd))
+		goto out;
+
+	for (rtype = HID_REPORT_TYPE_MIN; rtype <= HID_REPORT_TYPE_MAX; rtype++) {
+		rinfo.report_type = rtype;
+		rinfo.report_id = HID_REPORT_ID_FIRST;
+		while (ioctl (fd, HIDIOCGREPORTINFO, &rinfo) >= 0) {
+			for (i = 0; i < rinfo.num_fields; i++) { 
+				memset (&finfo, 0, sizeof (finfo));
+				finfo.report_type = rinfo.report_type;
+				finfo.report_id = rinfo.report_id;
+				finfo.field_index = i;
+				ioctl (fd, HIDIOCGFIELDINFO, &finfo);
+				
+				memset (&uref, 0, sizeof (uref));
+				for (j = 0; j < finfo.maxusage; j++) {
+					uref.report_type = finfo.report_type;
+					uref.report_id = finfo.report_id;
+					uref.field_index = i;
+					uref.usage_index = j;
+					ioctl (fd, HIDIOCGUCODE, &uref);
+					ioctl (fd, HIDIOCGUSAGE, &uref);
+
+					dbus_error_init (&error);
+
+					switch (uref.usage_code) {
+
+					case UPS_REMAINING_CAPACITY:
+						libhal_device_set_property_int (
+							ctx, udi, "battery.charge_level.current", uref.value, &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.charge_level.percentage", uref.value, &error);
+						libhal_device_set_property_string (
+							ctx, udi, "battery.charge_level.unit", "percent", &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.reporting.current", uref.value, &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.reporting.percentage", uref.value, &error);
+						libhal_device_set_property_string (
+							ctx, udi, "battery.reporting.unit", "percent", &error);
+						break;
+
+					case UPS_RUNTIME_TO_EMPTY:
+						libhal_device_set_property_int (
+							ctx, udi, "battery.remaining_time", uref.value, &error);
+						break;
+
+					case UPS_CHARGING:
+						libhal_device_set_property_bool (
+							ctx, udi, "battery.rechargeable.is_charging", uref.value != 0, &error);
+						break;
+
+					case UPS_DISCHARGING:
+						libhal_device_set_property_bool (
+							ctx, udi, "battery.rechargeable.is_discharging", uref.value != 0, &error);
+						break;
+
+					case UPS_BATTERYPRESENT:
+						libhal_device_set_property_bool (
+							ctx, udi, "battery.present", uref.value != 0, &error);
+						break;
+
+					case UPS_DEVICENAME:
+						libhal_device_set_property_string (
+							ctx, udi, "foo", 
+							ups_get_string (fd, uref.value), &error);
+						break;
+
+					case UPS_CHEMISTRY:
+						libhal_device_set_property_string (
+							ctx, udi, "battery.technology", 
+							ups_get_string (fd, uref.value), &error);
+						break;
+
+					case UPS_RECHARGEABLE:
+						libhal_device_set_property_bool (
+							ctx, udi, "battery.is_rechargeable", uref.value != 0, &error);
+						break;
+
+					case UPS_OEMINFORMATION:
+						libhal_device_set_property_string (
+							ctx, udi, "battery.vendor", 
+							ups_get_string (fd, uref.value), &error);
+						break;
+
+					case UPS_PRODUCT:
+						libhal_device_set_property_string (
+							ctx, udi, "battery.model", 
+							ups_get_string (fd, uref.value), &error);
+						break;
+
+					case UPS_SERIALNUMBER:
+						libhal_device_set_property_string (
+							ctx, udi, "battery.serial", 
+							ups_get_string (fd, uref.value), &error);
+						break;
+
+					case UPS_DESIGNCAPACITY:
+						libhal_device_set_property_int (
+							ctx, udi, "battery.charge_level.design", uref.value, &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.charge_level.last_full", uref.value, &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.reporting.design", uref.value, &error);
+						libhal_device_set_property_int (
+							ctx, udi, "battery.reporting.last_full", uref.value, &error);
+						break;
+
+					default:
+						break;
+					}
+				}
+			}
+			rinfo.report_id |= HID_REPORT_ID_NEXT;
+		}
+	}
+
+	libhal_device_set_property_bool (ctx, udi, "battery.present", TRUE, &error);
+	libhal_device_set_property_string (ctx, udi, "battery.type", "ups", &error);
+	libhal_device_add_capability (ctx, udi, "battery", &error);
+
+	ret = TRUE;
+
+out:
+	return ret;
+}
+
+int
+main (int argc, char *argv[])
+{
+	int fd;
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	unsigned int i;
+	fd_set fdset;
+	struct hiddev_event ev[64];
+	int rd;
+
+	hal_set_proc_title_init (argc, argv);
+
+	setup_logger ();	
+
+	udi = getenv ("UDI");
+	if (udi == NULL)
+		goto out;
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	device_file = getenv ("HAL_PROP_HIDDEV_DEVICE");
+	if (device_file == NULL)
+		goto out;
+
+	fd = open (device_file, O_RDONLY);
+	if (fd < 0)
+		goto out;
+
+	if (!ups_get_static (ctx, udi, fd))
+		goto out;
+
+	hal_set_proc_title ("hald-addon-hid-ups: listening on %s", device_file);
+
+	FD_ZERO(&fdset);
+	while (1) {
+		FD_SET(fd, &fdset);
+		rd = select(fd+1, &fdset, NULL, NULL, NULL);
+		
+		if (rd > 0) {
+			rd = read(fd, ev, sizeof(ev));
+			if (rd < (int) sizeof(ev[0])) {
+				close(fd);
+				goto out;
+			}
+
+			for (i = 0; i < rd / sizeof(ev[0]); i++) {
+				DBusError error;
+				
+				dbus_error_init (&error);
+				switch (ev[i].hid) {
+				case UPS_REMAINING_CAPACITY:
+					libhal_device_set_property_int (
+						ctx, udi, "battery.charge_level.current", ev[i].value, &error);
+					libhal_device_set_property_int (
+						ctx, udi, "battery.charge_level.percentage", ev[i].value, &error);
+					libhal_device_set_property_int (
+						ctx, udi, "battery.reporting.current", ev[i].value, &error);
+					libhal_device_set_property_int (
+						ctx, udi, "battery.reporting.percentage", ev[i].value, &error);
+					break;
+					
+				case UPS_RUNTIME_TO_EMPTY:
+					libhal_device_set_property_int (
+						ctx, udi, "battery.remaining_time", ev[i].value, &error);
+					break;
+					
+				case UPS_CHARGING:
+					libhal_device_set_property_bool (
+						ctx, udi, "battery.rechargeable.is_charging", ev[i].value != 0, &error);
+					break;
+					
+				case UPS_DISCHARGING:
+					libhal_device_set_property_bool (
+						ctx, udi, "battery.rechargeable.is_discharging", ev[i].value != 0, &error);
+					break;
+					
+				default:
+					break;
+				}
+			}
+		}
+	}
+
+out:
+	return 0;
+}
diff --git a/hald/linux/addons/addon-keyboard.c b/hald/linux/addons/addon-keyboard.c
new file mode 100644
index 0000000..a054ac9
--- /dev/null
+++ b/hald/linux/addons/addon-keyboard.c
@@ -0,0 +1,233 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-keyboard.c : Listen to key events and modify hal device objects
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005 Ryan Lortie <desrt at desrt.ca>
+ * Copyright (C) 2006 Matthew Garrett <mjg59 at srcf.ucam.org>
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <linux/input.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+#include "../../util_helper.h"
+
+static char *udi;
+
+static char *key_name[KEY_MAX + 1] = {
+	[0 ... KEY_MAX] = NULL,
+	[KEY_STOP] = "stop",
+	[KEY_AGAIN] = "again",
+	[KEY_PROPS] = "props",
+	[KEY_UNDO] = "undo",
+	[KEY_FRONT] = "front",
+	[KEY_COPY] = "copy",
+	[KEY_OPEN] = "open",
+	[KEY_PASTE] = "paste",
+	[KEY_FIND] = "find",
+	[KEY_CUT] = "cut",
+	[KEY_HELP] = "help",
+	[KEY_MENU] = "menu",
+	[KEY_CALC] = "calc",
+	[KEY_SETUP] = "setup",
+	[KEY_SLEEP] = "sleep",
+	[KEY_WAKEUP] = "wake-up",
+	[KEY_FILE] = "file",
+	[KEY_SENDFILE] = "send-file",
+	[KEY_DELETEFILE] = "delete-file",
+	[KEY_XFER] = "xfer",
+	[KEY_PROG1] = "prog1",
+	[KEY_PROG2] = "prog2",
+	[KEY_WWW] = "www",
+	[KEY_MSDOS] = "msdos",
+	[KEY_COFFEE] = "coffee",
+	[KEY_DIRECTION] = "direction",
+	[KEY_CYCLEWINDOWS] = "cycle-windows",
+	[KEY_MAIL] = "mail",
+	[KEY_BOOKMARKS] = "bookmarks",
+	[KEY_COMPUTER] = "computer",
+	[KEY_BACK] = "back",
+	[KEY_FORWARD] = "forward",
+	[KEY_CLOSECD] = "close-cd",
+	[KEY_EJECTCD] = "eject-cd",
+	[KEY_EJECTCLOSECD] = "eject-close-cd",
+	[KEY_NEXTSONG] = "next-song",
+	[KEY_PLAYPAUSE] = "play-pause",
+	[KEY_PREVIOUSSONG] = "previous-song",
+	[KEY_STOPCD] = "stop-cd",
+	[KEY_RECORD] = "record",
+	[KEY_REWIND] = "rewind",
+	[KEY_PHONE] = "phone",
+	[KEY_ISO] = "iso",
+	[KEY_CONFIG] = "config",
+	[KEY_HOMEPAGE] = "homepage",
+	[KEY_REFRESH] = "refresh",
+	[KEY_EXIT] = "exit",
+	[KEY_MOVE] = "move",
+	[KEY_EDIT] = "edit",
+	[KEY_SCROLLUP] = "scroll-up",
+	[KEY_SCROLLDOWN] = "scroll-down",
+	[KEY_KPLEFTPAREN] = "kp-left-paren",
+	[KEY_KPRIGHTPAREN] = "kp-right-paren",
+	[KEY_F13] = "f13",
+	[KEY_F14] = "f14",
+	[KEY_F15] = "f15",
+	[KEY_F16] = "f16",
+	[KEY_F17] = "f17",
+	[KEY_F18] = "f18",
+	[KEY_F19] = "f19",
+	[KEY_F20] = "f20",
+	[KEY_F21] = "f21",
+	[KEY_F22] = "f22",
+	[KEY_F23] = "f23",
+	[KEY_F24] = "f24",
+	[KEY_PLAYCD] = "play-cd",
+	[KEY_PAUSECD] = "pause-cd",
+	[KEY_PROG3] = "prog3",
+	[KEY_PROG4] = "prog4",
+	[KEY_SUSPEND] = "hibernate",
+	[KEY_CLOSE] = "close",
+	[KEY_PLAY] = "play",
+	[KEY_FASTFORWARD] = "fast-forward",
+	[KEY_BASSBOOST] = "bass-boost",
+	[KEY_PRINT] = "print",
+	[KEY_HP] = "hp",
+	[KEY_CAMERA] = "camera",
+	[KEY_SOUND] = "sound",
+	[KEY_QUESTION] = "question",
+	[KEY_EMAIL] = "email",
+	[KEY_CHAT] = "chat",
+	[KEY_SEARCH] = "search",
+	[KEY_CONNECT] = "connect",
+	[KEY_FINANCE] = "finance",
+	[KEY_SPORT] = "sport",
+	[KEY_SHOP] = "shop",
+	[KEY_ALTERASE] = "alt-erase",
+	[KEY_CANCEL] = "cancel",
+	[KEY_BRIGHTNESSDOWN] = "brightness-down",
+	[KEY_BRIGHTNESSUP] = "brightness-up",
+	[KEY_MEDIA] = "media",
+	[KEY_POWER] = "power",
+	[KEY_MUTE] = "mute",
+	[KEY_VOLUMEDOWN] = "volume-down",
+	[KEY_VOLUMEUP] = "volume-up",
+#ifndef KEY_SWITCHVIDEOMODE
+#define KEY_SWITCHVIDEOMODE	227
+#endif
+	[KEY_SWITCHVIDEOMODE] = "switch-videomode",
+#ifndef KEY_KBDILLUMTOGGLE
+#define KEY_KBDILLUMTOGGLE	228
+#endif
+	[KEY_KBDILLUMTOGGLE] = "kbd-illum-toggle",
+#ifndef KEY_KBDILLUMDOWN
+#define KEY_KBDILLUMDOWN	229
+#endif
+	[KEY_KBDILLUMDOWN] = "kbd-illum-down",
+#ifndef KEY_KBDILLUMUP
+#define KEY_KBDILLUMUP		230
+#endif
+	[KEY_KBDILLUMUP] = "kbd-illum-up"
+};
+
+static void
+main_loop (LibHalContext *ctx, FILE* eventfp)
+{
+	DBusError error;
+	struct input_event event;
+
+	dbus_error_init (&error);
+
+	while (fread (&event, sizeof(event), 1, eventfp)) {
+		/* dbg ("event.code = %d (0x%02x)", event.code); */
+		if (key_name[event.code] && event.value == 1) {
+			libhal_device_emit_condition (ctx, udi, 
+						      "ButtonPressed",
+						      key_name[event.code],
+						      &error);
+		}
+	}
+	
+	dbus_error_free (&error);
+}
+
+int
+main (int argc, char **argv)
+{
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *device_file;
+	FILE *eventfp;
+
+	hal_set_proc_title_init (argc, argv);
+
+	/* setup_logger (); */
+
+	dbus_error_init (&error);
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	
+	if ((device_file = getenv ("HAL_PROP_INPUT_DEVICE")) == NULL)
+		goto out;
+
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+                goto out;
+
+	eventfp = fopen(device_file, "r");	
+
+	if (!eventfp)
+		goto out;
+
+	drop_privileges (0);
+
+	hal_set_proc_title ("hald-addon-keyboard: listening on %s", device_file);
+
+	while (1)
+	{
+		main_loop (ctx, eventfp);
+		
+		/* If main_loop exits sleep for 5s and try to reconnect (
+		   again). */
+		sleep (5);
+	}
+
+	return 0;
+
+ out:
+	if (ctx != NULL) {
+                dbus_error_init (&error);
+                libhal_ctx_shutdown (ctx, &error);
+                libhal_ctx_free (ctx);
+        }
+	
+	return 0;
+}
+
+/* vim:set sw=8 noet: */
diff --git a/hald/linux/addons/addon-macbookpro-backlight.c b/hald/linux/addons/addon-macbookpro-backlight.c
new file mode 100644
index 0000000..f25a555
--- /dev/null
+++ b/hald/linux/addons/addon-macbookpro-backlight.c
@@ -0,0 +1,521 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hal_addon_macbookpro-backlight.c : Set backlight for Macbook Pro
+ * laptops that uses the ATI X1600 chipset. Based on code from Nicolas
+ * Boichat found on the mactel-linux mailing list.
+ *
+ * Copyright (C) 2006 David Zeuthen <david at fubar.dk>
+ * Copyright (C) 2006 Nicolas Boichat <nicolas at 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#include <config.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/io.h>
+#include <sys/mman.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <pci/pci.h>
+#include <unistd.h> 
+
+#include <glib/gmain.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "libhal/libhal.h"
+#include "../../logger.h"
+
+static LibHalContext *halctx = NULL;
+static GMainLoop *main_loop;
+static char *udi;
+static DBusConnection *conn;
+
+static char* memory;
+ 
+static inline unsigned int readl(const volatile void *addr)
+{
+ 	return *(volatile unsigned int*) addr;
+}
+
+static inline void writel(unsigned int b, volatile void *addr)
+{
+ 	*(volatile unsigned int*) addr = b;
+}
+
+#define INREG(addr)		readl(memory+addr)
+#define OUTREG(addr,val)	writel(val, memory+addr)
+
+static unsigned char 
+read_backlight (void)
+{
+ 	return INREG(0x7af8) >> 8;
+}
+
+static void 
+write_backlight (unsigned char value)
+{
+ 	OUTREG(0x7af8, 0x00000001 | ((unsigned int)value << 8));
+}
+
+
+#define LIGHT_SENSOR_LEFT_KEY	"ALV0" //0x414c5630, r-o length 6
+#define LIGHT_SENSOR_RIGHT_KEY	"ALV1" //0x414c5631, r-o length 6
+#define BACKLIGHT_KEY 		"LKSB" //0x4c4b5342, w-o
+
+static int debug = 0;
+
+static struct timeval lasttv;
+static struct timeval newtv;
+
+
+static void
+ssleep (const int usec)
+{
+	gettimeofday(&lasttv, NULL);
+	while (1) {
+		gettimeofday(&newtv, NULL);
+		if (((newtv.tv_usec - lasttv.tv_usec) + ((newtv.tv_sec - lasttv.tv_sec)*1000000)) > usec) {
+			break;
+		}
+	}
+}
+
+static unsigned char 
+get_status (void)
+{
+	return inb(0x304);
+}
+
+static int 
+waitfree (char num)
+{
+	char c, pc = -1;
+	int retry = 100;
+	while (((c = get_status())&0x0F) != num && retry) {
+		ssleep(10);
+		retry--;
+		if (pc != c) {
+			//printf("%x-%d:", c, retry);
+			pc = c;
+		}
+	}
+	if (retry == 0) {
+		printf("Waitfree failed %x != %x.\n", c, num);
+		return 0;
+	}
+	/*else
+		printf("Waitfree ok %x.\n", c);*/
+
+	return 1;
+}
+
+
+static int
+writekey (char* key, char len, unsigned char* buffer)
+{
+	int i;
+
+	outb(0x11, 0x304);
+	if (!waitfree(0x0c)) return 0;
+	
+	for (i = 0; i < 4; i++) {
+		outb(key[i], 0x300);
+		if (!waitfree(0x04)) return 0;
+	}
+	if (debug) printf(">%s", key);
+
+	outb(len, 0x300);
+	if (debug) printf(">%x", len);
+
+	for (i = 0; i < len; i++) {
+		if (!waitfree(0x04)) return 0;
+		outb(buffer[i], 0x300);
+		if (debug) printf(">%x", buffer[i]);
+	}
+	if (debug) printf("\n");
+	return 1;
+}
+
+static int 
+readkey (char* key, char len, unsigned char* buffer)
+{
+	int i; unsigned char c;
+
+	outb(0x10, 0x304);
+	if (!waitfree(0x0c)) return 0;
+	
+	for (i = 0; i < 4; i++) {
+		outb(key[i], 0x300);
+		if (!waitfree(0x04)) return 0;
+	}
+	if (debug) printf("<%s", key);
+
+	outb(len, 0x300);
+	if (debug) printf(">%x", len);
+
+	for (i = 0; i < len; i++) {
+		if (!waitfree(0x05)) return 0;
+		c = inb(0x300);
+		buffer[i] = c;
+		if (debug) printf("<%x", c);
+	}
+	if (debug) printf("\n");
+	return 1;
+}
+
+static int 
+read_light_sensor (gboolean left)
+{
+	unsigned char buffer[6];
+
+	if (readkey (left ? LIGHT_SENSOR_LEFT_KEY : LIGHT_SENSOR_RIGHT_KEY, 6, buffer))
+		return buffer[2];
+	else
+		return -1;
+}
+
+static int
+set_keyboard_backlight (char value)
+{
+	unsigned char buffer[2];
+	buffer[0] = value;
+	buffer[1] = 0x00;
+	return writekey (BACKLIGHT_KEY, 2, buffer);	
+}
+
+
+#if 0
+static int
+read_keyboard_backlight (void)
+{
+	unsigned char buffer[6];
+
+	if (readkey (BACKLIGHT_KEY, 6, buffer))
+		return buffer[2];
+	else
+		return -1;
+}
+#endif
+
+static int last_keyboard_brightness = -1;
+
+static DBusHandlerResult
+filter_function (DBusConnection *connection, DBusMessage *message, void *userdata)
+{
+	DBusError err;
+	DBusMessage *reply;
+
+	/*dbg ("filter_function: sender=%s destination=%s obj_path=%s interface=%s method=%s", 
+	     dbus_message_get_sender (message), 
+	     dbus_message_get_destination (message), 
+	     dbus_message_get_path (message), 
+	     dbus_message_get_interface (message),
+	     dbus_message_get_member (message));*/
+
+	reply = NULL;
+
+	if (dbus_message_is_method_call (message, 
+					 "org.freedesktop.Hal.Device.LaptopPanel", 
+					 "SetBrightness")) {
+		int brightness;
+
+		dbus_error_init (&err);
+		if (dbus_message_get_args (message, 
+					   &err,
+					   DBUS_TYPE_INT32, &brightness,
+					   DBUS_TYPE_INVALID)) {
+			/* dbg ("setting brightness %d", brightness); */
+			if (brightness < 0 || brightness > 228) {
+				reply = dbus_message_new_error (message,
+								"org.freedesktop.Hal.Device.LaptopPanel.Invalid",
+								"Brightness has to be between 0 and 228!");
+
+			} else {
+				int return_code;
+
+				write_backlight (brightness + 27);
+
+				reply = dbus_message_new_method_return (message);
+				if (reply == NULL)
+					goto error;
+
+				return_code = 0;
+				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.LaptopPanel", 
+						"GetBrightness")) {
+		int brightness;
+
+		dbus_error_init (&err);
+		if (dbus_message_get_args (message, 
+					   &err,
+					   DBUS_TYPE_INVALID)) {
+
+			brightness = read_backlight () - 27;
+			if (brightness < 0)
+				brightness = 0;
+			if (brightness > 228)
+				brightness = 228;
+
+			/* dbg ("getting brightness, it's %d", brightness); */
+
+			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);
+		}
+		
+	} else if (dbus_message_is_method_call (message, 
+						"org.freedesktop.Hal.Device.LightSensor", 
+						"GetBrightness")) {
+		int brightness[2];
+
+		brightness[0] = read_light_sensor (FALSE); /* right */
+		brightness[1] = read_light_sensor (TRUE); /* left */
+
+		if (brightness[0] == -1 || brightness[1] == -1) {
+			reply = dbus_message_new_error (message,
+							"org.freedesktop.Hal.Device.LightSensors.Error",
+							"Error poking hardware");
+			dbus_connection_send (connection, reply, NULL);
+		} else {
+			int **pb = &brightness;
+
+			reply = dbus_message_new_method_return (message);
+			if (reply == NULL)
+				goto error;
+			
+			dbus_message_append_args (reply,
+						  DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &pb, 2,
+						  DBUS_TYPE_INVALID);
+			dbus_connection_send (connection, reply, NULL);
+		}
+	} else if (dbus_message_is_method_call (message, 
+						"org.freedesktop.Hal.Device.KeyboardBacklight", 
+						"GetBrightness")) {
+
+		/* I can't get this working so just cache last SetBrightness value :-/ */
+		if (last_keyboard_brightness == -1 ) {
+			reply = dbus_message_new_error (message,
+							"org.freedesktop.Hal.Device.KeyboardBacklight.Error",
+							"Error poking hardware");
+			dbus_connection_send (connection, reply, NULL);
+		} else {
+			reply = dbus_message_new_method_return (message);
+			if (reply == NULL)
+				goto error;
+			
+			dbus_message_append_args (reply,
+						  DBUS_TYPE_INT32, &last_keyboard_brightness,
+						  DBUS_TYPE_INVALID);
+			dbus_connection_send (connection, reply, NULL);
+		}
+#if 0
+		int brightness;
+
+		brightness = read_keyboard_backlight ();
+
+		if (brightness == -1) {
+			reply = dbus_message_new_error (message,
+							"org.freedesktop.Hal.Device.KeyboardBacklight.Error",
+							"Error poking hardware");
+			dbus_connection_send (connection, reply, NULL);
+		} else {
+			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);
+		}
+#endif
+	} else if (dbus_message_is_method_call (message, 
+						"org.freedesktop.Hal.Device.KeyboardBacklight", 
+						"SetBrightness")) {
+		int brightness;
+
+
+		dbus_error_init (&err);
+		if (dbus_message_get_args (message, 
+					   &err,
+					   DBUS_TYPE_INT32, &brightness,
+					   DBUS_TYPE_INVALID)) {
+			/*dbg ("setting keyboard brightness %d", brightness);*/
+			if (brightness < 0 || brightness > 255) {
+				reply = dbus_message_new_error (message,
+								"org.freedesktop.Hal.Device.KeyboardBacklight.Invalid",
+								"Brightness has to be between 0 and 255!");
+
+			} else {
+				set_keyboard_backlight (brightness);
+				last_keyboard_brightness = brightness;
+
+				reply = dbus_message_new_method_return (message);
+				if (reply == NULL)
+					goto error;
+			}
+
+			dbus_connection_send (connection, reply, NULL);
+		}
+
+	}
+	
+error:
+	if (reply != NULL)
+		dbus_message_unref (reply);
+
+	return DBUS_HANDLER_RESULT_HANDLED;
+}
+
+int
+main (int argc, char *argv[])
+{
+ 	off_t address = 0;
+ 	size_t length = 0;
+ 	int fd;
+ 	int state;
+	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;
+	}
+
+	conn = libhal_ctx_get_dbus_connection (halctx);
+	dbus_connection_setup_with_g_main (conn, NULL);
+
+	dbus_connection_add_filter (conn, filter_function, NULL, NULL);
+
+ 	/* Search for the graphics card. */
+ 	/* Default values: */
+ 	/* address = 0x90300000; */
+ 	/* length = 0x20000; */
+
+ 	struct pci_access *pacc = pci_alloc();
+ 	pci_init(pacc);
+ 	pci_scan_bus(pacc);
+ 	struct pci_dev *dev;
+ 	for(dev=pacc->devices; dev; dev=dev->next) {	/* Iterate over all devices */
+ 		pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
+ 		if ((dev->vendor_id == 0x1002) && (dev->device_id == 0x71c5)) { // ATI X1600
+ 			address = dev->base_addr[2];
+ 			length = dev->size[2];
+ 		}
+ 	}
+ 	pci_cleanup(pacc);
+
+	HAL_DEBUG (("addr 0x%x len=%d", address, length));
+ 
+ 	if (!address) {
+ 		HAL_DEBUG (("Failed to detect ATI X1600, aborting..."));
+ 		return 1;
+ 	}
+ 
+ 	fd = open ("/dev/mem", O_RDWR);
+ 	
+ 	if (fd < 0) {
+ 		HAL_DEBUG (("cannot open /dev/mem"));
+ 		return 1;
+ 	}
+ 
+ 	memory = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, address);
+ 
+ 	if (memory == MAP_FAILED) {
+ 		HAL_ERROR (("mmap failed"));
+ 		return 2;
+ 	}
+ 
+ 	/* Is it really necessary ? */
+ 	OUTREG(0x4dc, 0x00000005);
+ 	state = INREG(0x7ae4);
+ 	OUTREG(0x7ae4, state);
+
+	if (ioperm (0x300, 0x304, 1) < 0) {
+		HAL_ERROR (("ioperm failed (you should be root)."));
+		exit(1);
+	}
+
+	/* this works because we hardcoded the udi's in the <spawn> in the fdi files */
+	if (!libhal_device_claim_interface (halctx, 
+					    "/org/freedesktop/Hal/devices/macbook_pro_lcd_panel", 
+					    "org.freedesktop.Hal.Device.LaptopPanel", 
+					    "    <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.LaptopPanel'"));
+		return -4;
+	}
+	if (!libhal_device_claim_interface (halctx, 
+					    "/org/freedesktop/Hal/devices/macbook_pro_light_sensor",
+					    "org.freedesktop.Hal.Device.LightSensor", 
+					    "    <method name=\"GetBrightness\">\n"
+					    "      <arg name=\"brightness_value\" direction=\"out\" type=\"ai\"/>\n"
+					    "    </method>\n",
+					    &err)) {
+		HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.LightSensor'"));
+		return -4;
+	}
+	if (!libhal_device_claim_interface (halctx, 
+					    "/org/freedesktop/Hal/devices/macbook_pro_keyboard_backlight",
+					    "org.freedesktop.Hal.Device.KeyboardBacklight", 
+					    "    <method name=\"GetBrightness\">\n"
+					    "      <arg name=\"brightness_value\" direction=\"out\" type=\"i\"/>\n"
+					    "    </method>\n"
+					    "    <method name=\"SetBrightness\">\n"
+					    "      <arg name=\"brightness_value\" direction=\"in\" type=\"i\"/>\n"
+					    "    </method>\n",
+					    &err)) {
+		HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.KeyboardBacklight'"));
+		return -4;
+	}
+
+	main_loop = g_main_loop_new (NULL, FALSE);
+	g_main_loop_run (main_loop);
+	return 0;
+}
diff --git a/hald/linux/addons/addon-pmu.c b/hald/linux/addons/addon-pmu.c
new file mode 100644
index 0000000..68b59fe
--- /dev/null
+++ b/hald/linux/addons/addon-pmu.c
@@ -0,0 +1,137 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-pmu-lid.c : Poll the lid button for PMU on Apple computers
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <linux/adb.h>
+#include <linux/pmu.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+#include "../../util_helper.h"
+
+int
+main (int argc, char *argv[])
+{
+	int fd;
+	char *udi;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	int rd;
+	char buf[256];
+	int state;
+	int new_state;
+	char *strstate;
+
+	fd = -1;
+
+	setup_logger ();
+
+	udi = getenv ("UDI");
+	if (udi == NULL)
+		goto out;
+
+	dbus_error_init (&error);
+
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	/* initial state */
+	if ((strstate = getenv ("HAL_PROP_BUTTON_STATE_VALUE")) == NULL) {
+		HAL_ERROR (("Cannot get HAL_PROP_BUTTON_STATE_VALUE"));
+		goto out;
+	}
+	if (strcmp (strstate, "true") == 0)
+		state = TRUE;
+	else
+		state = FALSE;
+
+	if ((fd = open ("/dev/adb", O_RDWR)) < 0) {
+                HAL_ERROR (("Cannot open /dev/adb"));
+                goto out;
+	}
+
+        drop_privileges (0);
+
+	while (1) {
+		int n;
+
+		buf[0] = PMU_PACKET;
+		buf[1] = PMU_GET_COVER;
+
+		n = write (fd, buf, 2);
+		if (n == 2) {
+			rd = read (fd, buf, sizeof (buf));
+			if (rd <= 0) {
+				HAL_ERROR (("Error reading from fd; read returned %d; err=%s", errno, strerror (errno)));
+				goto out;
+			}
+
+#if 0
+			int i;
+			
+			HAL_DEBUG (("Read 0x%02x bytes", rd));				
+			for (i = 0; i < rd; i++) {
+				dbg ("%02x : 0x%02x", i, buf[i]);
+			}
+#endif
+
+			if (rd >= 2) {
+				new_state = (((buf[1]) & 0x01) != 0);
+
+				if (new_state != state) {
+					HAL_DEBUG (("lid state change: %d", new_state));
+					dbus_error_init (&error);
+					libhal_device_set_property_bool (
+						ctx, udi, "button.state.value", new_state, &error);
+					dbus_error_init (&error);
+					libhal_device_emit_condition (ctx, udi, "ButtonPressed", "", &error);
+				}
+
+				state = new_state;
+			}
+
+			
+		}
+		usleep (1000 * 1000);
+	}
+
+
+
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	return 0;
+}
diff --git a/hald/linux/addons/addon-storage.c b/hald/linux/addons/addon-storage.c
new file mode 100644
index 0000000..1660abc
--- /dev/null
+++ b/hald/linux/addons/addon-storage.c
@@ -0,0 +1,486 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * addon-storage.c : Poll storage devices for media changes
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <linux/cdrom.h>
+#include <linux/fs.h>
+#include <mntent.h>
+#include <scsi/sg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+#include "../../util_helper.h"
+
+static void 
+force_unmount (LibHalContext *ctx, const char *udi)
+{
+	DBusError error;
+	DBusMessage *msg = NULL;
+	DBusMessage *reply = NULL;
+	char **options = NULL;
+	unsigned int num_options = 0;
+	DBusConnection *dbus_connection;
+	char *device_file;
+
+	dbus_connection = libhal_ctx_get_dbus_connection (ctx);
+
+	msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
+					    "org.freedesktop.Hal.Device.Volume",
+					    "Unmount");
+	if (msg == NULL) {
+		HAL_ERROR (("Could not create dbus message for %s", udi));
+		goto out;
+	}
+
+
+	options = calloc (1, sizeof (char *));
+	if (options == NULL) {
+		HAL_ERROR (("Could not allocate options array"));
+		goto out;
+	}
+
+	options[0] = "lazy";
+	num_options = 1;
+
+	device_file = libhal_device_get_property_string (ctx, udi, "block.device", NULL);
+	if (device_file != NULL) {
+		HAL_INFO(("forcibly attempting to lazy unmount %s as media was removed", device_file));
+		libhal_free_string (device_file);
+	}
+
+	if (!dbus_message_append_args (msg, 
+				       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
+				       DBUS_TYPE_INVALID)) {
+		HAL_ERROR (("Could not append args to dbus message for %s", udi));
+		goto out;
+	}
+	
+	dbus_error_init (&error);
+	if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
+		HAL_ERROR (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
+		dbus_error_free (&error);
+		goto out;
+	}
+
+	if (dbus_error_is_set (&error)) {
+		HAL_ERROR (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
+		dbus_error_free (&error);
+		goto out;
+	}
+
+	HAL_DEBUG (("Succesfully unmounted udi '%s'", udi));
+
+out:
+	if (options != NULL)
+		free (options);
+	if (msg != NULL)
+		dbus_message_unref (msg);
+	if (reply != NULL)
+		dbus_message_unref (reply);
+}
+
+static dbus_bool_t
+unmount_cleartext_devices (LibHalContext *ctx, const char *udi)
+{
+	DBusError error;
+	char **clear_devices;
+	int num_clear_devices;
+	dbus_bool_t ret;
+
+	ret = FALSE;
+
+	/* check if the volume we back is mounted.. if it is.. unmount it */
+	dbus_error_init (&error);
+	clear_devices = libhal_manager_find_device_string_match (ctx,
+								 "volume.crypto_luks.clear.backing_volume",
+								 udi,
+								 &num_clear_devices,
+								 &error);
+
+	if (clear_devices != NULL && num_clear_devices > 0) {
+		int i;
+
+		ret = TRUE;
+
+		for (i = 0; i < num_clear_devices; i++) {
+			char *clear_udi;
+			clear_udi = clear_devices[i];
+			dbus_error_init (&error);
+			if (libhal_device_get_property_bool (ctx, clear_udi, "volume.is_mounted", &error)) {
+				HAL_DEBUG (("Forcing unmount of child '%s' (crypto)", clear_udi));
+				force_unmount (ctx, clear_udi);
+			}
+		}
+		libhal_free_string_array (clear_devices);
+	}
+
+	return ret;
+}
+
+static void 
+unmount_childs (LibHalContext *ctx, const char *udi)
+{
+	int num_volumes;
+	char **volumes;
+	DBusError error;
+
+	/* need to force unmount all partitions */
+	dbus_error_init (&error);
+	if ((volumes = libhal_manager_find_device_string_match (
+		     ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
+		int i;
+
+		for (i = 0; i < num_volumes; i++) {
+			char *vol_udi;
+
+			vol_udi = volumes[i];
+			dbus_error_init (&error);
+			if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
+				dbus_bool_t is_crypto;
+
+				/* unmount all cleartext devices associated with us */
+				is_crypto = unmount_cleartext_devices (ctx, vol_udi);
+
+				dbus_error_init (&error);
+				if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
+					HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
+					force_unmount (ctx, vol_udi);
+				}
+
+				/* teardown crypto */
+				if (is_crypto) {
+					DBusMessage *msg = NULL;
+					DBusMessage *reply = NULL;
+
+					/* tear down mapping */
+					HAL_DEBUG (("Teardown crypto for '%s'", vol_udi));
+
+					msg = dbus_message_new_method_call ("org.freedesktop.Hal", vol_udi,
+									    "org.freedesktop.Hal.Device.Volume.Crypto",
+									    "Teardown");
+					if (msg == NULL) {
+						HAL_ERROR (("Could not create dbus message for %s", vol_udi));
+						goto teardown_failed;
+					}
+
+					dbus_error_init (&error);
+					if (!(reply = dbus_connection_send_with_reply_and_block (
+						      libhal_ctx_get_dbus_connection (ctx), msg, -1, &error)) || 
+					    dbus_error_is_set (&error)) {
+						HAL_DEBUG (("Teardown failed for %s: %s : %s\n", 
+						     udi, error.name, error.message));
+						dbus_error_free (&error);
+					}
+
+				teardown_failed:
+					if (msg != NULL)
+						dbus_message_unref (msg);
+					if (reply != NULL)
+						dbus_message_unref (reply);
+				}
+
+			}
+
+		}
+		libhal_free_string_array (volumes);
+	}
+}
+
+/** Check if a filesystem on a special device file is mounted
+ *
+ *  @param  device_file         Special device file, e.g. /dev/cdrom
+ *  @return                     TRUE iff there is a filesystem system mounted
+ *                              on the special device file
+ */
+static dbus_bool_t
+is_mounted (const char *device_file)
+{
+	FILE *f;
+	dbus_bool_t rc;
+	struct mntent mnt;
+	struct mntent *mnte;
+	char buf[512];
+
+	rc = FALSE;
+
+	if ((f = setmntent ("/etc/mtab", "r")) == NULL)
+		goto out;
+
+	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
+		if (strcmp (device_file, mnt.mnt_fsname) == 0) {
+			rc = TRUE;
+			goto out1;
+		}
+	}
+
+out1:
+	endmntent (f);
+out:
+	return rc;
+}
+
+
+enum {
+	MEDIA_STATUS_UNKNOWN = 0,
+	MEDIA_STATUS_GOT_MEDIA = 1,
+	MEDIA_STATUS_NO_MEDIA = 2
+};
+
+int
+main (int argc, char *argv[])
+{
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *bus;
+	char *drive_type;
+	int is_cdrom;
+	int media_status;
+	char *support_media_changed_str;
+	int support_media_changed;
+
+	hal_set_proc_title_init (argc, argv);
+
+	/* We could drop privs if we know that the haldaemon user is
+	 * to be able to access block devices...
+	 */
+        /*drop_privileges (1);*/
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
+		goto out;
+	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
+		goto out;
+
+	setup_logger ();
+
+	support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
+	if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
+		support_media_changed = TRUE;
+	else
+		support_media_changed = FALSE;
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	HAL_DEBUG (("**************************************************"));
+	HAL_DEBUG (("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)", device_file, bus, drive_type, udi));
+	HAL_DEBUG (("**************************************************"));
+
+	hal_set_proc_title ("hald-addon-storage: polling %s", device_file);
+
+	if (strcmp (drive_type, "cdrom") == 0)
+		is_cdrom = 1;
+	else
+		is_cdrom = 0;
+
+	media_status = MEDIA_STATUS_UNKNOWN;
+
+	while (TRUE) {
+		int fd;
+		int got_media;
+
+		got_media = FALSE;
+
+		if (is_cdrom) {
+			int drive;
+
+			fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
+
+			if (fd < 0 && errno == EBUSY) {
+				/* this means the disc is mounted or some other app,
+				 * like a cd burner, has already opened O_EXCL */
+
+				/* HOWEVER, when starting hald, a disc may be
+				 * mounted; so check /etc/mtab to see if it
+				 * actually is mounted. If it is we retry to open
+				 * without O_EXCL
+				 */
+				if (!is_mounted (device_file))
+					goto skip_check;
+
+				fd = open (device_file, O_RDONLY | O_NONBLOCK);
+			}
+
+			if (fd < 0) {
+				HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
+				goto skip_check;
+			}
+
+
+			/* Check if a disc is in the drive
+			 *
+			 * @todo Use MMC-2 API if applicable
+			 */
+			drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+			switch (drive) {
+			case CDS_NO_INFO:
+			case CDS_NO_DISC:
+			case CDS_TRAY_OPEN:
+			case CDS_DRIVE_NOT_READY:
+				break;
+
+			case CDS_DISC_OK:
+				/* some CD-ROMs report CDS_DISK_OK even with an open
+				 * tray; if media check has the same value two times in
+				 * a row then this seems to be the case and we must not
+				 * report that there is a media in it. */
+				if (support_media_changed &&
+				    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
+				    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
+				} else {
+					got_media = TRUE;
+				}
+				break;
+
+			case -1:
+				HAL_ERROR (("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
+				break;
+
+			default:
+				break;
+			}
+
+			/* check if eject button was pressed */
+			if (got_media) {
+				unsigned char cdb[10] = { 0x4a, 1, 0, 0, 16, 0, 0, 0, 8, 0};
+				unsigned char buffer[8];
+				struct sg_io_hdr sg_h;
+				int retval;
+
+				memset(buffer, 0, sizeof(buffer));
+				memset(&sg_h, 0, sizeof(struct sg_io_hdr));
+				sg_h.interface_id = 'S';
+				sg_h.cmd_len = sizeof(cdb);
+				sg_h.dxfer_direction = SG_DXFER_FROM_DEV;
+				sg_h.dxfer_len = sizeof(buffer);
+				sg_h.dxferp = buffer;
+				sg_h.cmdp = cdb;
+				sg_h.timeout = 5000;
+				retval = ioctl(fd, SG_IO, &sg_h);
+				if (retval == 0 && sg_h.status == 0 && (buffer[4] & 0x0f) == 0x01) {
+					DBusError error;
+
+					/* emit signal from drive device object */
+					dbus_error_init (&error);
+					libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
+				}
+			}
+			close (fd);
+		} else {
+			fd = open (device_file, O_RDONLY);
+			if (fd < 0 && errno == ENOMEDIUM) {
+				got_media = FALSE;
+				close (fd);
+			} else if (fd >= 0) {
+				got_media = TRUE;
+				close (fd);
+			} else {
+				HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
+				close (fd);
+				goto skip_check;
+			}
+		}
+
+		switch (media_status) {
+		case MEDIA_STATUS_GOT_MEDIA:
+			if (!got_media) {
+				DBusError error;
+				
+				HAL_DEBUG (("Media removal detected on %s", device_file));
+				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
+				
+				/* attempt to unmount all childs */
+				unmount_childs (ctx, udi);
+				
+				/* could have a fs on the main block device; do a rescan to remove it */
+				dbus_error_init (&error);
+				libhal_device_rescan (ctx, udi, &error);
+				
+				/* have to this to trigger appropriate hotplug events */
+				fd = open (device_file, O_RDONLY | O_NONBLOCK);
+				if (fd >= 0)
+					ioctl (fd, BLKRRPART);
+				close (fd);
+			}
+			break;
+
+		case MEDIA_STATUS_NO_MEDIA:
+			if (got_media) {
+				DBusError error;
+
+				HAL_DEBUG (("Media insertion detected on %s", device_file));
+				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);				/* our probe will trigger the appropriate hotplug events */
+
+				/* could have a fs on the main block device; do a rescan to add it */
+				dbus_error_init (&error);
+				libhal_device_rescan (ctx, udi, &error);
+				
+			}
+			break;
+
+		case MEDIA_STATUS_UNKNOWN:
+		default:
+			break;
+		}
+
+		/* update our current status */
+		if (got_media)
+			media_status = MEDIA_STATUS_GOT_MEDIA;
+		else
+			media_status = MEDIA_STATUS_NO_MEDIA;
+
+		/*HAL_DEBUG (("polling %s; got media=%d", device_file, got_media));*/
+
+	skip_check:
+		sleep (2);
+	}
+
+out:
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return 0;
+}
diff --git a/hald/linux/addons/addon-usb-csr.c b/hald/linux/addons/addon-usb-csr.c
new file mode 100644
index 0000000..cd1747d
--- /dev/null
+++ b/hald/linux/addons/addon-usb-csr.c
@@ -0,0 +1,329 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hal_addon_usb_csr.c : daemon handling CSR-based wireless mice
+ *
+ * Copyright (C) 2004 Sergey V. Udaltsov <svu at gnome.org>
+ * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <usb.h>
+
+#include <glib/gmain.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "libhal/libhal.h"
+#include "../../logger.h"
+#include "../../util_helper.h"
+
+#define TIMEOUT         30L
+
+/* Internal CSR registered, I presume - for some reason not addressed directly */
+#define P6  (buf[0])
+#define P0  (buf[1])
+#define P4  (buf[2])
+#define P5  (buf[3])
+#define P8  (buf[4])
+#define P9  (buf[5])
+#define PB0 (buf[6])
+#define PB1 (buf[7])
+
+typedef struct _PropertyCacheItem
+{
+	gboolean bus_no_present;
+	int bus_no;
+	gboolean port_no_present;
+	int port_no;
+	gboolean csr_is_dual_present;
+	gboolean csr_is_dual;
+	gboolean current_charge_present;
+	int current_charge;
+} PropertyCacheItem;
+
+/* globals */
+static PropertyCacheItem *dev_props = NULL;
+static LibHalContext *halctx = NULL;
+static GMainLoop *main_loop;
+static const char *device_udi;
+
+/* prototypes */
+static struct usb_device *find_device (const char *hal_device_udi, PropertyCacheItem *pci);
+
+static PropertyCacheItem* 
+property_cache_item_get (const char *hal_device_udi)
+{
+	PropertyCacheItem * pci = g_new0 (PropertyCacheItem,1);
+	DBusError err;
+	dbus_error_init (&err);
+
+	pci->bus_no_present = libhal_device_property_exists (halctx, hal_device_udi, 
+			"usb_device.bus_number", &err);
+	if (dbus_error_is_set (&err))
+		HAL_ERROR (("Error: [%s]/[%s]", err.name, err.message));	
+
+	if (pci->bus_no_present)
+		pci->bus_no = libhal_device_get_property_int (halctx, hal_device_udi, 
+			"usb_device.bus_number", &err);
+
+	pci->port_no_present = libhal_device_property_exists (halctx, hal_device_udi, 
+			"usb_device.linux.device_number", &err);
+	if (pci->port_no_present)
+		pci->port_no = libhal_device_get_property_int (halctx, hal_device_udi, 
+			"usb_device.linux.device_number", &err);
+
+	pci->csr_is_dual_present = libhal_device_property_exists (halctx, hal_device_udi,
+			"battery.csr.is_dual",  &err);
+	if (pci->csr_is_dual_present)
+		pci->csr_is_dual = libhal_device_get_property_bool (halctx, hal_device_udi,
+			"battery.csr.is_dual",  &err);
+
+	pci->current_charge_present = libhal_device_property_exists (halctx, hal_device_udi, 
+			"battery.charge_level.current", &err);
+	if (pci->current_charge_present)
+		pci->current_charge = libhal_device_get_property_int (halctx, hal_device_udi, 
+			"battery.charge_level.current", &err);
+
+	return pci;
+}
+
+/* Thanks to lmctl code. I'd LOVE, REALLY LOVE to see some docs though... */
+static void 
+check_battery (const char *hal_device_udi, PropertyCacheItem *pci)
+{
+	struct usb_device *curr_device;
+	usb_dev_handle *handle;
+	char buf[80];
+	DBusError err;
+	unsigned int addr;
+	int is_dual = 0;
+	int percentage = 0;
+
+	if (pci == NULL)
+		return;
+
+	HAL_DEBUG (("CSR device: [%s]", hal_device_udi));
+	is_dual = pci->csr_is_dual;
+
+	/* Which of subdevices to address */
+	HAL_DEBUG (("Is dual: %d", is_dual));
+	addr = is_dual? 1<<8 : 0;
+
+	curr_device = find_device (hal_device_udi, pci);
+	if (curr_device == NULL)	{
+		HAL_ERROR (("Device %s not found", hal_device_udi));
+		return;
+	}
+
+	handle = usb_open (curr_device);
+	if (handle == NULL) {
+		HAL_ERROR (("Could not open usb device"));
+		return;
+	}
+
+	if (!usb_control_msg (handle, 0xc0, 0x09, 0x03|addr, 0x00|addr,
+			 buf, 8, TIMEOUT) != 8)	{
+		if ((P0 == 0x3b) && (P4 == 0)) {
+			HAL_DEBUG (("Receiver busy, trying again later"));
+		} else {
+			int current_charge = P5 & 0x07;
+
+			HAL_DEBUG (("Charge level: %d->%d", pci->current_charge, current_charge));
+			if (current_charge != pci->current_charge) { 
+			pci->current_charge = current_charge; dbus_error_init (&err);
+		 		libhal_device_set_property_int (halctx, hal_device_udi, 
+		 			"battery.charge_level.current", current_charge, &err);
+		 		if (current_charge != 0)
+		 			percentage = (100.0 / 7.0) * current_charge;
+		 		libhal_device_set_property_int (halctx, hal_device_udi, 
+		 			"battery.charge_level.percentage", percentage, &err);
+			}
+		}
+	} else
+		perror ("Writing to USB device");
+	usb_close (handle);
+}
+
+/* TODO: Is it linux-specific way to find the device? */
+static struct usb_device* 
+find_device (const char *hal_device_udi, PropertyCacheItem *pci)
+{
+	struct usb_bus* curr_bus;
+	char LUdirname[5];
+	char LUfname[5];
+
+	if (!(pci->bus_no_present && pci->port_no_present)) {
+		/* no sysfs path */
+		HAL_ERROR (("No hal bus number and/or port number"));
+		return NULL;
+	}
+	snprintf (LUdirname, sizeof (LUdirname), "%03d", pci->bus_no);
+	snprintf (LUfname, sizeof (LUfname), "%03d",pci->port_no);
+	HAL_DEBUG (("Looking for: [%s][%s]", LUdirname, LUfname));
+
+	for (curr_bus = usb_busses; curr_bus != NULL; curr_bus = curr_bus->next) {
+ 		struct usb_device *curr_device;
+		/* dbg ("Checking bus: [%s]", curr_bus->dirname); */
+		if (g_strcasecmp (LUdirname, curr_bus->dirname))
+			continue;
+
+ 		for (curr_device = curr_bus->devices; curr_device != NULL; 
+		     curr_device = curr_device->next) {
+			/* dbg ("Checking port: [%s]", curr_device->filename); */
+			if (g_strcasecmp (LUfname, curr_device->filename))
+				continue;
+			HAL_DEBUG (("Matched device: [%s][%s][%04X:%04X]", curr_bus->dirname, 
+				curr_device->filename, 
+				curr_device->descriptor.idVendor, 
+				curr_device->descriptor.idProduct));
+			return curr_device;
+		}
+	}
+	return NULL;
+}
+
+static gboolean
+check_all_batteries (gpointer data)
+{
+	HAL_DEBUG (("** Check batteries"));
+	/* TODO: make it configurable (not to rescan every time) */
+	usb_find_busses ();
+	usb_find_devices ();
+	check_battery (device_udi, dev_props);
+	return TRUE;
+}
+
+static gboolean 
+is_the_device (const char *hal_device_udi)
+{
+	return !g_ascii_strcasecmp (device_udi, hal_device_udi);
+}
+
+static void
+device_removed (LibHalContext *ctx, const char *hal_device_udi)
+{
+	/* this device is removed */
+	if (is_the_device (hal_device_udi)) {
+		HAL_DEBUG (("** The device %s removed, exit", device_udi));
+		g_main_loop_quit (main_loop);
+	}
+}
+
+static void 
+property_modified (LibHalContext *ctx,
+		 const char *hal_device_udi,
+		 const char *key,
+		 dbus_bool_t is_removed,
+		 dbus_bool_t is_added)
+{
+	/* "Key" property modified */
+	if (!g_ascii_strcasecmp (key, "battery.command_interface")) {
+		if (is_removed) {
+			HAL_DEBUG (("** Main Property %s removed: %s", key, hal_device_udi));
+			/* probably we'll have to exit if this is our device */
+			device_removed (ctx, hal_device_udi);
+		}
+	} else
+		/* "Secondary" property modified */
+		if (is_the_device (hal_device_udi))
+		{
+			if (!(g_ascii_strcasecmp (key, "usb_device.bus_number") &&
+			      g_ascii_strcasecmp (key, "usb_device.linux.device_number") &&
+	 		      g_ascii_strcasecmp (key, "battery.csr.is_dual"))) {
+				HAL_DEBUG (("** Property %s added/changed: %s", key, hal_device_udi));
+				if (dev_props)
+					g_free (dev_props);
+				dev_props = property_cache_item_get (hal_device_udi);
+			}
+		}
+}
+
+int
+main (int argc, char *argv[])
+{
+	DBusError err;
+
+	hal_set_proc_title_init (argc, argv);
+
+	setup_logger ();	
+
+	device_udi = getenv ("UDI");
+
+	HAL_DEBUG (("device:[%s]", device_udi));
+	if (device_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;
+	}
+
+	/* update_properties */
+	dbus_error_init (&err);
+	libhal_device_set_property_bool (halctx, device_udi, 
+			"battery.present", TRUE, &err);
+	if (!libhal_device_property_exists (halctx, device_udi, 
+			"battery.is_rechargeable", &err))
+		libhal_device_set_property_bool (halctx, device_udi, 
+			"battery.is_rechargeable", FALSE, &err);
+	libhal_device_set_property_int (halctx, device_udi, 
+			"battery.charge_level.design", 7, &err);
+	libhal_device_set_property_int (halctx, device_udi, 
+			"battery.charge_level.last_full", 7, &err);
+	libhal_device_set_property_string (halctx, device_udi, 
+			"info.category", "battery", &err);
+	libhal_device_set_property_string (halctx, device_udi, 
+			"battery.command_interface", "csr", &err);
+
+	/* monitor change */
+	libhal_ctx_set_device_property_modified (halctx, property_modified);
+
+	/* Initial fillup */
+	dev_props = property_cache_item_get (device_udi);
+	HAL_ERROR (("** Initial fillup done"));
+
+	/* init usb */
+	usb_init ();
+	
+	/* do coldplug */
+	check_all_batteries (NULL);
+
+	/* only add capability when initial charge_level key has been set */
+	dbus_error_init (&err);
+	libhal_device_add_capability (halctx, device_udi, "battery", &err);
+
+	hal_set_proc_title ("hald-addon-usb-csr: listening on '%s'", 
+			    libhal_device_get_property_string(halctx, device_udi,
+							      "info.product", &err));
+
+	main_loop = g_main_loop_new (NULL, FALSE);
+	g_timeout_add (1000L * TIMEOUT, check_all_batteries, NULL);
+	g_main_loop_run (main_loop);
+
+	libhal_ctx_shutdown (halctx, &err);
+	HAL_ERROR (("** Addon exits normally"));
+	return 0;
+}
diff --git a/hald/linux/apm.c b/hald/linux/apm.c
new file mode 100644
index 0000000..e855438
--- /dev/null
+++ b/hald/linux/apm.c
@@ -0,0 +1,542 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
+ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
+ *
+ * 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 "../hald_dbus.h"
+#include "../device_info.h"
+#include "../logger.h"
+#include "../util.h"
+#include "../util_pm.h"
+
+#include "osspec_linux.h"
+
+#include "apm.h"
+
+enum {
+	APM_TYPE_BATTERY,
+	APM_TYPE_AC_ADAPTER
+};
+
+int interval_poll_round = 0;
+
+typedef struct APMDevHandler_s
+{
+	int apm_type;
+	HalDevice *(*add) (const gchar *apm_path, HalDevice *parent, struct APMDevHandler_s *handler);
+	gboolean (*compute_udi) (HalDevice *d, struct APMDevHandler_s *handler);
+	gboolean (*remove) (HalDevice *d, struct APMDevHandler_s *handler);
+	gboolean (*refresh) (HalDevice *d, struct APMDevHandler_s *handler);
+} APMDevHandler;
+
+typedef struct {
+	char driver_version[256];
+	int version_major;
+	int version_minor;
+	int flags;
+	int ac_line_status;
+	int battery_status;
+	int battery_flags;
+	int battery_percentage;
+	int battery_time;
+} APMInfo;
+
+#define APM_POLL_INTERVAL 2000
+
+static gboolean
+apm_poll (gpointer data)
+{
+	GSList *i;
+	GSList *devices;
+
+	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
+								    "linux.apm_path",
+								    "/proc/apm");
+	for (i = devices; i != NULL; i = g_slist_next (i)) {
+		HalDevice *d;		
+		d = HAL_DEVICE (i->data);
+		apm_rescan_device (d);
+	}
+
+	return TRUE;
+}
+
+static gboolean 
+read_from_apm (const char *apm_file, APMInfo *i)
+{
+	char *buf;
+	gboolean ret;
+
+	ret = FALSE;
+
+	if ((buf = hal_util_get_string_from_file ("", apm_file)) == NULL)
+		goto out;
+
+	if (sscanf (buf, "%s %d.%d %x %x %x %x %d%% %d",
+		    i->driver_version,
+		    &i->version_major,
+		    &i->version_minor,
+		    &i->flags,
+		    &i->ac_line_status,
+		    &i->battery_status,
+		    &i->battery_flags,
+		    &i->battery_percentage,
+		    &i->battery_time) != 9)
+		goto out;
+
+	ret = TRUE;
+
+out:
+	return ret;
+}
+
+enum
+{
+	BATTERY_HIGH     = 0,
+	BATTERY_LOW      = 1,
+	BATTERY_CRITICAL = 2,
+	BATTERY_CHARGING = 3
+};
+
+static gboolean
+battery_refresh (HalDevice *d, APMDevHandler *handler)
+{
+	const char *path;
+	int remaining_percentage;
+	int remaining_time;
+	gboolean is_charging;
+	gboolean is_discharging;
+	HalDevice *computer;
+	APMInfo i;
+
+	path = hal_device_property_get_string (d, "linux.apm_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");
+
+	/* typical : 1.16ac 1.2 0x02 0x01 0x03 0x09 98% 88 min */
+
+	read_from_apm (path, &i);
+
+	/* we check this to know if there is a battery: 
+	 * - if i.battery_percentage < 0: no battery   
+	 * - if driver version starts with [B]: old style (pre-0.7), not supported -> no battery
+	 * - if battery status == 0xff : no battery present
+	 */
+	if (i.battery_percentage < 0 || i.driver_version[0] == 'B' || i.battery_status == 0xff ) {
+		device_property_atomic_update_begin ();
+		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.charge_level.unit");
+		hal_device_property_remove (d, "battery.charge_level.current");
+		/* Is this key really needed? We don't know the value of this key */
+		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.percentage");
+		hal_device_property_remove (d, "battery.remaining_time");
+		hal_device_property_set_bool (d, "battery.present", FALSE);
+		device_property_atomic_update_end ();		
+	} else {
+		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 {
+			if (!hal_device_has_property(computer, "system.formfactor")) {
+				hal_device_property_set_string (computer, "system.formfactor", "laptop");
+			}
+			else if (strcmp (hal_device_property_get_string (computer, "system.formfactor"), "laptop") != 0) {
+				hal_device_property_set_string (computer, "system.formfactor", "laptop");
+			}
+		}
+		
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
+		hal_device_property_set_bool (d, "battery.present", TRUE);
+		hal_device_property_set_int (d, "battery.charge_level.current", i.battery_percentage);
+		hal_device_property_set_string (d, "battery.charge_level.unit", "percent");
+
+		hal_device_property_set_int (d, "battery.charge_level.design", 100);
+		/* Is this key really needed? We don't know the value of this key */
+		hal_device_property_set_int (d, "battery.charge_level.last_full", 100); 
+
+		/* TODO: clean the logic below up; it appears my T41
+		 * with 2.6.10-1.1110_FC4 and acpi=off always report
+		 * BATTERY_CHARGING so look at ac_line_status
+		 * instead..
+		 */
+		if (i.battery_status == BATTERY_CHARGING) {
+			is_charging = TRUE;
+			is_discharging = FALSE;
+			remaining_time = 0; /* apm doesn't give info */
+		} else {
+			is_charging = FALSE;
+			is_discharging = (i.ac_line_status == FALSE);
+			/* apm returns time in minutes, not seconds */
+			remaining_time = i.battery_time * 60;
+		}
+
+		/* set the time to discharge, or remove key for charging */
+		if (remaining_time > 0) {
+			/* switched from charging to discharging, set key */
+			if (!is_charging && is_discharging && !hal_device_has_property(d,"battery.remaining_time")) {
+				hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
+				interval_poll_round = 0;
+			}
+			/* after 30 seconds (15*APM_POLL_INTERVAL) set key */
+			else if (interval_poll_round == 15) {
+				hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
+				interval_poll_round = 0;
+			}
+			/* else: only increment counter and set no key to avoid needless events/changes
+			   because APM produce with each read a new value for remaining time */
+			else
+				interval_poll_round++;
+		} else {
+			hal_device_property_remove (d, "battery.remaining_time");
+		}
+
+		/* set the correct charge states */
+		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", is_charging);
+		hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", is_discharging);
+
+		/* set the percentage charge, easy. */
+		remaining_percentage = util_compute_percentage_charge (d->udi, i.battery_percentage, 100);
+	
+		/* Only set keys if no error (signified with negative return value) */
+		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");
+
+		device_property_atomic_update_end ();
+	}
+
+	return TRUE;
+}
+
+static gboolean
+ac_adapter_refresh (HalDevice *d, APMDevHandler *handler)
+{
+	const char *path;
+	APMInfo i;
+
+	path = hal_device_property_get_string (d, "linux.apm_path");
+	if (path == NULL)
+		return FALSE;
+
+	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");
+
+	read_from_apm(path, &i);
+
+	if (i.ac_line_status)
+		hal_device_property_set_bool (d, "ac_adapter.present", TRUE);
+	else
+		hal_device_property_set_bool (d, "ac_adapter.present", FALSE);
+
+	return TRUE;
+}
+
+/** Scan the data structures exported by the kernel and add hotplug
+ *  events for adding APM objects.
+ *
+ *  @param                      TRUE if, and only if, APM capabilities
+ *                              were detected
+ */
+gboolean
+apm_synthesize_hotplug_events (void)
+{
+	gboolean ret;
+	HalDevice *computer;
+	gchar path[HAL_PATH_MAX];
+	HotplugEvent *hotplug_event;
+
+	ret = FALSE;
+
+	if (!g_file_test ("/proc/apm", G_FILE_TEST_EXISTS))
+		goto out;
+
+	ret = TRUE;
+
+	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?"));
+		goto out;
+	}
+
+	/* Set appropriate properties on the computer object */
+	hal_device_property_set_string (computer, "power_management.type", "apm");
+
+	snprintf (path, sizeof (path), "%s/apm", get_hal_proc_path ());
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_APM;
+	g_strlcpy (hotplug_event->apm.apm_path, path, sizeof (hotplug_event->apm.apm_path));
+	hotplug_event->apm.apm_type = APM_TYPE_BATTERY;
+	hotplug_event_enqueue (hotplug_event);
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->type = HOTPLUG_EVENT_APM;
+	g_strlcpy (hotplug_event->apm.apm_path, path, sizeof (hotplug_event->apm.apm_path));
+	hotplug_event->apm.apm_type = APM_TYPE_AC_ADAPTER;
+	hotplug_event_enqueue (hotplug_event);
+
+	g_timeout_add (APM_POLL_INTERVAL,
+		       apm_poll,
+		       NULL);
+
+out:
+	return ret;
+}
+
+static HalDevice *
+apm_generic_add (const gchar *apm_path, HalDevice *parent, APMDevHandler *handler)
+{
+	HalDevice *d;
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.apm_path", apm_path);
+	hal_device_property_set_int (d, "linux.apm_type", handler->apm_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
+apm_generic_compute_udi (HalDevice *d, APMDevHandler *handler)
+{
+	gchar udi[256];
+
+	if (handler->apm_type == APM_TYPE_BATTERY ) {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "/org/freedesktop/Hal/devices/apm_battery");
+	
+	} else if (handler->apm_type == APM_TYPE_AC_ADAPTER ) {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "/org/freedesktop/Hal/devices/apm_ac_adapter");
+	} else {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "/org/freedesktop/Hal/devices/apm_%d",
+				      hal_device_property_get_int (d, "info.category"));
+	}
+
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+static gboolean
+apm_generic_remove (HalDevice *d, APMDevHandler *handler)
+{
+	if (!hal_device_store_remove (hald_get_gdl (), d)) {
+		HAL_WARNING (("Error removing device"));
+	}
+
+	return TRUE;
+}
+
+static APMDevHandler apmdev_handler_battery = { 
+	.apm_type    = APM_TYPE_BATTERY,
+	.add         = apm_generic_add,
+	.compute_udi = apm_generic_compute_udi,
+	.refresh     = battery_refresh,
+	.remove      = apm_generic_remove
+};
+
+static APMDevHandler apmdev_handler_ac_adapter = { 
+	.apm_type    = APM_TYPE_AC_ADAPTER,
+	.add         = apm_generic_add,
+	.compute_udi = apm_generic_compute_udi,
+	.refresh     = ac_adapter_refresh,
+	.remove      = apm_generic_remove
+};
+
+static APMDevHandler *apm_handlers[] = {
+	&apmdev_handler_battery,
+	&apmdev_handler_ac_adapter,
+	NULL
+};
+
+void
+hotplug_event_begin_add_apm (const gchar *apm_path, int apm_type, HalDevice *parent, void *end_token)
+{
+	guint i;
+
+	HAL_INFO (("apm_add: apm_path=%s apm_type=%d, parent=0x%08x", apm_path, apm_type, parent));
+
+	for (i = 0; apm_handlers [i] != NULL; i++) {
+		APMDevHandler *handler;
+
+		handler = apm_handlers[i];
+		if (handler->apm_type == apm_type) {
+			HalDevice *d;
+
+			d = handler->add (apm_path, parent, handler);
+			if (d == NULL) {
+				/* didn't find anything - thus, ignore this hotplug event */
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_APM);
+
+			/* 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);
+
+			/* TODO: Run callouts */
+			
+			/* Compute UDI */
+			if (!handler->compute_udi (d, handler)) {
+				hal_device_store_remove (hald_get_tdl (), d);
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			/* 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);
+			goto out;
+		}
+	}
+	
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out:
+	;
+}
+
+void
+hotplug_event_begin_remove_apm (const gchar *apm_path, int apm_type, void *end_token)
+{
+	guint i;
+	HalDevice *d;
+
+	HAL_INFO (("apm_rem: apm_path=%s apm_type=%d", apm_path, apm_type));
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.apm_path", apm_path);
+	if (d == NULL) {
+		HAL_WARNING (("Couldn't remove device with apm path %s - not found", apm_path));
+		goto out;
+	}
+
+	for (i = 0; apm_handlers [i] != NULL; i++) {
+		APMDevHandler *handler;
+
+		handler = apm_handlers[i];
+		if (handler->apm_type == apm_type) {
+			if (handler->remove (d, handler)) {
+				hotplug_event_end (end_token);
+				goto out2;
+			}
+		}
+	}
+out:
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out2:
+	;
+}
+
+gboolean
+apm_rescan_device (HalDevice *d)
+{
+	guint i;
+	gboolean ret;
+	int apm_type;
+
+	ret = FALSE;
+
+	apm_type = hal_device_property_get_int (d, "linux.apm_type");
+
+	for (i = 0; apm_handlers [i] != NULL; i++) {
+		APMDevHandler *handler;
+
+		handler = apm_handlers[i];
+		if (handler->apm_type == apm_type) {
+			ret = handler->refresh (d, handler);
+			goto out;
+		}
+	}
+
+	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));
+
+out:
+	return ret;
+}
+
+HotplugEvent *
+apm_generate_add_hotplug_event (HalDevice *d)
+{
+	int apm_type;
+	const char *apm_path;
+	HotplugEvent *hotplug_event;
+
+	apm_path = hal_device_property_get_string (d, "linux.apm_path");
+	apm_type = hal_device_property_get_int (d, "linux.apm_type");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_APM;
+	g_strlcpy (hotplug_event->apm.apm_path, apm_path, sizeof (hotplug_event->apm.apm_path));
+	hotplug_event->apm.apm_type = apm_type;
+	return hotplug_event;
+}
+
+HotplugEvent *
+apm_generate_remove_hotplug_event (HalDevice *d)
+{
+	int apm_type;
+	const char *apm_path;
+	HotplugEvent *hotplug_event;
+
+	apm_path = hal_device_property_get_string (d, "linux.apm_path");
+	apm_type = hal_device_property_get_int (d, "linux.apm_type");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+	hotplug_event->type = HOTPLUG_EVENT_APM;
+	g_strlcpy (hotplug_event->apm.apm_path, apm_path, sizeof (hotplug_event->apm.apm_path));
+	hotplug_event->apm.apm_type = apm_type;
+	return hotplug_event;
+}
diff --git a/hald/linux/apm.h b/hald/linux/apm.h
new file mode 100644
index 0000000..80d0de6
--- /dev/null
+++ b/hald/linux/apm.h
@@ -0,0 +1,41 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
+ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef APM_H
+#define APM_H
+
+#include "../hald.h"
+#include "hotplug.h"
+
+gboolean apm_synthesize_hotplug_events (void);
+
+void hotplug_event_begin_add_apm (const gchar *apm_path, int apm_type, HalDevice *parent, void *end_token);
+
+void hotplug_event_begin_remove_apm (const gchar *apm_path, int apm_type, void *end_token);
+
+gboolean apm_rescan_device (HalDevice *d);
+
+HotplugEvent *apm_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *apm_generate_remove_hotplug_event (HalDevice *d);
+
+#endif /* APM_H */
diff --git a/hald/linux/blockdev.c b/hald/linux/blockdev.c
new file mode 100644
index 0000000..e40dd93
--- /dev/null
+++ b/hald/linux/blockdev.c
@@ -0,0 +1,1419 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * blockdev.c : Handling of block devices
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
+ *
+ * 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 <ctype.h>
+#include <limits.h>
+#include <linux/kdev_t.h>
+#include <mntent.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <syslog.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../hald_runner.h"
+#include "../logger.h"
+#include "../osspec.h"
+#include "../util.h"
+
+#include "coldplug.h"
+#include "hotplug.h"
+#include "hotplug_helper.h"
+#include "osspec_linux.h"
+
+#include "blockdev.h"
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static gboolean
+blockdev_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	if (hal_device_property_get_bool (d, "block.is_volume")) {
+		const char *label;
+		const char *uuid;
+
+		label = hal_device_property_get_string (d, "volume.label");
+		uuid = hal_device_property_get_string (d, "volume.uuid");
+
+		if (uuid != NULL && strlen (uuid) > 0) {
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "/org/freedesktop/Hal/devices/volume_uuid_%s", uuid);
+		} else if (label != NULL && strlen (label) > 0) {
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "/org/freedesktop/Hal/devices/volume_label_%s", label);
+		} else if (hal_device_property_get_bool(d, "volume.is_disc") &&
+			   hal_device_property_get_bool(d, "volume.disc.is_blank")) {
+			/* this should be a empty CD/DVD */
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+                                             "/org/freedesktop/Hal/devices/volume_empty_%s",
+					      hal_device_property_get_string (d, "volume.disc.type"));
+		} else {
+			/* fallback to partition number, size */
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "/org/freedesktop/Hal/devices/volume_part%d_size_%lld", 
+					      hal_device_property_get_int (d, "volume.partition.number"),
+					      hal_device_property_get_uint64 (d, "volume.size"));
+		}
+	} else {
+		const char *model;
+		const char *serial;
+
+		model = hal_device_property_get_string (d, "storage.model");
+		serial = hal_device_property_get_string (d, "storage.serial");
+
+		if (serial != NULL) {
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "/org/freedesktop/Hal/devices/storage_serial_%s", 
+					      serial);
+		} else if ((model != NULL) && (strlen(model) != 0) ) {
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "/org/freedesktop/Hal/devices/storage_model_%s", 
+					      model);
+		} else {
+			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+					      "%s_storage", 
+					      hal_device_property_get_string (d, "storage.physical_device"));
+		}
+	}
+
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+
+static void 
+blockdev_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 
+blockdev_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"));
+	}
+	g_object_unref (d);
+
+	hotplug_event_end (end_token);
+}
+
+static void
+cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type, 
+		       gint return_code, gchar **error,
+		       gpointer data1, gpointer data2)
+{
+	char *mount_point = (char *) data1;
+	HAL_INFO (("In cleanup_mountpoint_cb for '%s'", mount_point));
+	g_free (mount_point);
+}
+
+void
+blockdev_refresh_mount_state (HalDevice *d)
+{
+	FILE *f;
+	struct mntent mnt;
+	struct mntent *mnte;
+	char buf[1024];
+	unsigned int major;
+	unsigned int minor;
+	dev_t devt = makedev(0, 0);
+	GSList *volumes = NULL;
+	GSList *volume;
+        GSList *autofs_mounts = NULL;
+
+	/* open /proc/mounts */
+	g_snprintf (buf, sizeof (buf), "%s/mounts", get_hal_proc_path ());
+	if ((f = setmntent (buf, "r")) == NULL) {
+		HAL_ERROR (("Could not open /proc/mounts"));
+		return;
+	}
+
+	if (d)
+		volumes = g_slist_append (NULL, d);
+	else
+		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
+
+	if (!volumes)
+		goto exit;
+
+	/* loop over /proc/mounts */
+	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
+		struct stat statbuf;
+
+		/* If this is a nfs mount (fstype == 'nfs') ignore the mount. Reason:
+		 *  1. we don't list nfs devices in HAL
+		 *  2. more problematic: stat on mountpoints with 'stale nfs handle' never come
+		 *     back and block complete HAL and all applications using HAL fail.
+		 */
+		if (strcmp(mnt.mnt_type, "nfs") == 0)
+			continue;
+
+		/* If this is an autofs mount (fstype == 'autofs') 
+		 * store the mount in a list for later use. 
+		 * On mounts managed by autofs accessing files below the mount
+		 * point cause the mount point to be remounted after an 
+		 * unmount.  We keep the list so we do not check for
+		 * the .created-by-hal file on mounts under autofs mount points
+		 */
+		if (strcmp(mnt.mnt_type, "autofs") == 0) {
+			char *mnt_dir;
+
+			if (mnt.mnt_dir[strlen (mnt.mnt_dir) - 1] != '/')
+				mnt_dir = g_strdup_printf ("%s/", mnt.mnt_dir);
+			else
+				mnt_dir = g_strdup (mnt.mnt_dir);
+
+			autofs_mounts = g_slist_append (autofs_mounts,
+							mnt_dir);
+
+
+			continue;
+		}
+
+		/* check the underlying device of the mount point */
+		if (stat (mnt.mnt_dir, &statbuf) != 0)
+			continue;
+		if (major(statbuf.st_dev) == 0)
+			continue;
+
+		/*HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname, major(statbuf.st_dev), minor(statbuf.st_dev)));*/
+		/* match against all hal volumes */
+		for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
+			HalDevice *dev;
+
+			dev = HAL_DEVICE (volume->data);
+			major = hal_device_property_get_int (dev, "block.major");
+			if (major == 0)
+				continue;
+			minor = hal_device_property_get_int (dev, "block.minor");
+			devt = makedev(major, minor);
+			/*HAL_INFO (("  match %s (%i:%i)", hal_device_get_udi (dev), major, minor));*/
+
+			if (statbuf.st_dev == devt) {
+				/* found entry for this device in /proc/mounts */
+				device_property_atomic_update_begin ();
+				hal_device_property_set_bool (dev, "volume.is_mounted", TRUE);
+				hal_device_property_set_bool (dev, "volume.is_mounted_read_only",
+							      hasmntopt (&mnt, MNTOPT_RO) ? TRUE : FALSE);
+				hal_device_property_set_string (dev, "volume.mount_point", mnt.mnt_dir);
+				device_property_atomic_update_end ();
+				/*HAL_INFO (("  set %s to be mounted at %s (%s)",
+					   hal_device_get_udi (dev), mnt.mnt_dir,
+					   hasmntopt (&mnt, MNTOPT_RO) ? "ro" : "rw"));*/
+				volumes = g_slist_delete_link (volumes, volume);
+				break;
+			}
+		}
+	}
+
+	/* all remaining volumes are not mounted */
+	for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
+		HalDevice *dev;
+		char *mount_point;
+		GSList *autofs_node;
+
+		dev = HAL_DEVICE (volume->data);
+		mount_point = g_strdup (hal_device_property_get_string (dev, "volume.mount_point"));
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (dev, "volume.is_mounted", FALSE);
+		hal_device_property_set_bool (dev, "volume.is_mounted_read_only", FALSE);
+		hal_device_property_set_string (dev, "volume.mount_point", "");
+		device_property_atomic_update_end ();
+		/*HAL_INFO (("set %s to unmounted", hal_device_get_udi (dev)));*/
+
+		/* check to see if mount point falls under autofs */
+		autofs_node = autofs_mounts;
+		while (autofs_node != NULL) {
+			char *am = (char *)autofs_node->data;
+
+			if (strncmp (am, mount_point, strlen (am)) == 0);
+				break;
+
+			autofs_node = autofs_node->next;
+		}
+
+		/* look up in /media/.hal-mtab to see if we mounted this one */
+		if (mount_point != NULL && strlen (mount_point) > 0 && hal_util_is_mounted_by_hald (mount_point)) {
+			char *cleanup_stdin;
+			char *extra_env[2];
+
+			HAL_INFO (("Cleaning up directory '%s' since it was created by HAL's Mount()", mount_point));
+
+			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
+			extra_env[1] = NULL;
+			cleanup_stdin = "\n";
+
+			hald_runner_run_method (dev, 
+						"hal-storage-cleanup-mountpoint", 
+						extra_env, 
+						cleanup_stdin, TRUE,
+						0,
+						cleanup_mountpoint_cb,
+						g_strdup (mount_point), NULL);
+		}
+
+		g_free (mount_point);
+	}
+	g_slist_free (volumes);
+	g_slist_foreach (autofs_mounts, (GFunc) g_free, NULL);
+	g_slist_free (autofs_mounts);
+exit:
+	endmntent (f);
+}
+
+static void
+generate_fakevolume_hotplug_event_add_for_storage_device (HalDevice *d)
+{
+	const char *sysfs_path;
+	const char *device_file;
+	HotplugEvent *hotplug_event;
+	char fake_sysfs_path[HAL_PATH_MAX];
+
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+	device_file = hal_device_property_get_string (d, "block.device");
+
+	snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, fake_sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	if (device_file != NULL)
+		g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
+	else
+		hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	hotplug_event_enqueue (hotplug_event);
+	hotplug_event_process_queue ();
+}
+
+static void 
+add_blockdev_probing_helper_done (HalDevice *d, guint32 exit_type, 
+                                  gint return_code, char **error,
+                                  gpointer data1, gpointer data2) 
+{
+	void *end_token = (void *) data1;
+	gboolean is_volume;
+
+	/* helper_data may be null if probing is skipped */
+
+	HAL_INFO (("entering; exit_type=%d, return_code=%d", exit_type, return_code));
+
+	if (d == NULL) {
+		HAL_INFO (("Device object already removed"));
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	is_volume = hal_device_property_get_bool (d, "block.is_volume");
+
+	/* Discard device if probing reports failure 
+	 * 
+	 * (return code 2 means fs found on main block device (for non-volumes)) 
+	 */
+	if (exit_type != HALD_RUN_SUCCESS
+	    || !(return_code == 0 || (!is_volume && return_code == 2))) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	if (!blockdev_compute_udi (d)) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	/* set block.storage_device for storage devices since only now we know the UDI */
+	if (!is_volume) {
+		hal_device_copy_property (d, "info.udi", d, "block.storage_device");
+	} else {
+		/* check for mount point */
+		blockdev_refresh_mount_state (d);
+	}
+
+	/* Merge properties from .fdi files */
+	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
+	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
+
+	/* TODO: Merge persistent properties */
+
+	/* Run callouts */
+	hal_util_callout_device_add (d, blockdev_callouts_add_done, end_token, NULL);
+
+	/* Yay, got a file system on the main block device...
+	 *
+	 * Generate a fake hotplug event to get this added
+	 */
+	if (!is_volume && return_code == 2) {
+		generate_fakevolume_hotplug_event_add_for_storage_device (d);
+	}
+
+
+out:
+	return;
+}
+
+static void 
+blockdev_callouts_preprobing_storage_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	void *end_token = (void *) userdata1;
+
+	if (hal_device_property_get_bool (d, "info.ignore")) {
+		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
+		 * Also remove category and all capabilities
+		 */
+		hal_device_property_remove (d, "info.category");
+		hal_device_property_remove (d, "info.capabilities");
+		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
+		hal_device_property_set_string (d, "info.product", "Ignored Device");
+
+		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
+
+		/* 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);
+		goto out;
+	}
+
+	if (!hal_device_property_get_bool (d, "storage.media_check_enabled") &&
+	    hal_device_property_get_bool (d, "storage.no_partitions_hint")) {
+
+		/* special probe for PC floppy drives */
+		if (strcmp (hal_device_property_get_string (d, "storage.bus"), "platform") == 0 &&
+		    strcmp (hal_device_property_get_string (d, "storage.drive_type"), "floppy") == 0) {
+			HAL_INFO (("Probing PC floppy %s to see if it is present", 
+				   hal_device_property_get_string (d, "block.device")));
+
+			hald_runner_run(d, 
+			                    "hald-probe-pc-floppy", NULL,
+			                    HAL_HELPER_TIMEOUT,
+			                    add_blockdev_probing_helper_done,
+			                    (gpointer) end_token, NULL);
+			goto out;
+		} else {
+			char *synerror[1] = {NULL};
+
+			HAL_INFO (("Not probing storage device %s", 
+				   hal_device_property_get_string (d, "block.device")));
+
+			add_blockdev_probing_helper_done (d, FALSE, 0, synerror, (gpointer) end_token, NULL);
+			goto out;
+		}
+	}
+
+	/* run prober for 
+	 *
+	 *  - cdrom drive properties
+	 *  - non-partitioned filesystem on main block device
+	 */
+
+	HAL_INFO (("Probing storage device %s", hal_device_property_get_string (d, "block.device")));
+
+	/* probe the device */
+	hald_runner_run(d,
+			"hald-probe-storage", NULL,
+			HAL_HELPER_TIMEOUT,
+			add_blockdev_probing_helper_done,
+			(gpointer) end_token, NULL);
+
+out:
+	return;
+}
+
+static void
+blockdev_callouts_preprobing_volume_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	void *end_token = (void *) userdata1;
+
+	if (hal_device_property_get_bool (d, "info.ignore")) {
+		/* Leave the device here with info.ignore==TRUE so we won't pick up children
+		 * Also remove category and all capabilities
+		 */
+		hal_device_property_remove (d, "info.category");
+		hal_device_property_remove (d, "info.capabilities");
+		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
+		hal_device_property_set_string (d, "info.product", "Ignored Device");
+
+		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
+
+		/* 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);
+		goto out;
+	}
+
+	/* probe the device */
+	hald_runner_run (d,
+			 "hald-probe-volume", NULL, 
+			 HAL_HELPER_TIMEOUT,
+			 add_blockdev_probing_helper_done,
+			 (gpointer) end_token, NULL);
+out:
+	return;
+}
+
+/* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 
+ * (which is LGPL, so can't go into hald/utils.[ch] until it's relicensed)
+ */
+static void
+canonicalize_filename (gchar *filename)
+{
+	gchar *p, *q;
+	gboolean last_was_slash = FALSE;
+	
+	p = filename;
+	q = filename;
+	
+	while (*p)
+	{
+		if (*p == G_DIR_SEPARATOR)
+		{
+			if (!last_was_slash)
+				*q++ = G_DIR_SEPARATOR;
+			
+			last_was_slash = TRUE;
+		}
+		else
+		{
+			if (last_was_slash && *p == '.')
+			{
+				if (*(p + 1) == G_DIR_SEPARATOR ||
+				    *(p + 1) == '\0')
+				{
+					if (*(p + 1) == '\0')
+						break;
+					
+					p += 1;
+				}
+				else if (*(p + 1) == '.' &&
+					 (*(p + 2) == G_DIR_SEPARATOR ||
+					  *(p + 2) == '\0'))
+				{
+					if (q > filename + 1)
+					{
+						q--;
+						while (q > filename + 1 &&
+						       *(q - 1) != G_DIR_SEPARATOR)
+							q--;
+					}
+					
+					if (*(p + 2) == '\0')
+						break;
+					
+					p += 2;
+				}
+				else
+				{
+					*q++ = *p;
+					last_was_slash = FALSE;
+				}
+			}
+			else
+			{
+				*q++ = *p;
+				last_was_slash = FALSE;
+			}
+		}
+		
+		p++;
+	}
+	
+	if (q > filename + 1 && *(q - 1) == G_DIR_SEPARATOR)
+		q--;
+	
+	*q = '\0';
+}
+
+static char *
+resolve_symlink (const char *file)
+{
+	GError *error;
+	char *dir;
+	char *link;
+	char *f;
+	char *f1;
+
+	f = g_strdup (file);
+
+	while (g_file_test (f, G_FILE_TEST_IS_SYMLINK)) {
+		link = g_file_read_link (f, &error);
+		if (link == NULL) {
+			g_warning ("Cannot resolve symlink %s: %s", f, error->message);
+			g_error_free (error);
+			g_free (f);
+			f = NULL;
+			goto out;
+		}
+		
+		dir = g_path_get_dirname (f);
+		f1 = g_strdup_printf ("%s/%s", dir, link);
+		g_free (dir);
+		g_free (link);
+		g_free (f);
+		f = f1;
+	}
+
+out:
+	if (f != NULL)
+		canonicalize_filename (f);
+	return f;
+}
+
+void
+hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const gchar *device_file, gboolean is_partition,
+				  HalDevice *parent, void *end_token)
+{
+	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
+	gchar *major_minor;
+	HalDevice *d;
+	unsigned int major, minor;
+	gboolean is_fakevolume;
+	char *sysfs_path_real = NULL;
+	int floppy_num;
+	gboolean is_device_mapper;
+
+	is_device_mapper = FALSE;
+
+	HAL_INFO (("block_add: sysfs_path=%s dev=%s is_part=%d, parent=0x%08x", 
+		   sysfs_path, device_file, is_partition, parent));
+
+	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
+		HAL_INFO (("Ignoring block_add since parent has info.ignore==TRUE"));
+		goto out;
+	}
+
+	if (strcmp (hal_util_get_last_element (sysfs_path), "fakevolume") == 0) {
+		is_fakevolume = TRUE;
+		sysfs_path_real = hal_util_get_parent_path (sysfs_path);
+		HAL_INFO (("Handling %s as fakevolume - sysfs_path_real=%s", device_file, sysfs_path_real));
+	} else {
+		is_fakevolume = FALSE;
+		sysfs_path_real = g_strdup (sysfs_path);
+	}
+	
+	/* See if we already have device (which we may have as we're ignoring rem/add
+	 * for certain classes of devices - see hotplug_event_begin_remove_blockdev)
+	 */
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
+	if (d != NULL) {
+		HAL_INFO (("Ignoring hotplug event - device is already added"));
+		goto out;
+	}
+
+	d = hal_device_new ();
+
+	/* OK, no parent... it might a device-mapper device => check slaves/ subdir in sysfs */
+	if (parent == NULL && !is_partition && !is_fakevolume) {
+		GDir *dir;
+		GError *err = NULL;
+		char path[HAL_PATH_MAX];
+
+
+		/* sleep one second since device mapper needs additional
+		 * time before the device file is ready
+		 *
+		 * this is a hack and will only affect device mapper block
+		 * devices. It can go away once the kernel emits a "changed"
+		 * event for the device file (this is about to go upstream)
+		 * and we can depend on a released kernel with this feature.
+		 */
+		if (strncmp (hal_util_get_last_element (sysfs_path), "dm-", 3) == 0) {
+			HAL_INFO (("Waiting 1000ms to wait for device mapper to be ready", path));
+			usleep (1000 * 1000);
+		}
+
+		g_snprintf (path, HAL_PATH_MAX, "%s/slaves", sysfs_path);
+		HAL_INFO (("Looking in %s", path));
+		if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+			HAL_WARNING (("Unable to open %s: %s", path, err->message));
+			g_error_free (err);
+		} else {
+			const char *f;
+			while (((f = g_dir_read_name (dir)) != NULL) && (parent == NULL)) {
+				char *link;
+				char *target;
+
+				link = g_strdup_printf ("%s/%s", path, f);
+				target = resolve_symlink (link);
+				HAL_INFO ((" %s -> %s", link, target));
+
+				if (target != NULL) {
+					HalDevice *slave_volume;
+
+					slave_volume = hal_device_store_match_key_value_string (hald_get_gdl (),
+												"linux.sysfs_path", 
+												target);
+					if (slave_volume != NULL) {
+						const char *slave_volume_stordev_udi;
+						const char *slave_volume_fstype;
+
+						slave_volume_stordev_udi = hal_device_property_get_string (slave_volume, "block.storage_device");
+						slave_volume_fstype = hal_device_property_get_string (slave_volume, "volume.fstype");
+
+						/* Yup, we only support crypto_LUKS right now.
+						 *
+						 * In the future we can support other device-mapper mappings
+						 * such as LVM etc.
+						 */ 
+						if (slave_volume_stordev_udi != NULL &&
+						    slave_volume_fstype != NULL &&
+						    (strcmp (slave_volume_fstype, "crypto_LUKS") == 0)) {
+							HAL_INFO ((" slave_volume_stordev_udi='%s'!", slave_volume_stordev_udi));
+							parent = hal_device_store_find (hald_get_gdl (), slave_volume_stordev_udi);
+							if (parent != NULL) {
+								HAL_INFO ((" parent='%s'!", parent->udi));
+								hal_device_property_set_string (d, "volume.crypto_luks.clear.backing_volume", slave_volume->udi);
+								is_device_mapper = TRUE;
+							}
+						}
+					}
+				}
+				g_free (target);
+			}
+			g_dir_close (dir);
+			HAL_INFO (("Done looking in %s", path));
+		}
+		
+	}
+
+	if (parent == NULL) {
+		HAL_INFO (("Ignoring hotplug event - no parent"));
+		goto error;
+	}
+
+	if (!is_fakevolume && hal_device_property_get_bool (parent, "storage.no_partitions_hint")) {
+		HAL_INFO (("Ignoring blockdev since not a fakevolume and parent has "
+			   "storage.no_partitions_hint==TRUE"));
+		goto error;
+	}
+
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", parent->udi);
+	hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_BLOCK);
+
+	hal_device_property_set_string (d, "block.device", device_file);
+	if ((major_minor = hal_util_get_string_from_file (sysfs_path_real, "dev")) == NULL || 
+	    sscanf (major_minor, "%d:%d", &major, &minor) != 2) {
+		HAL_INFO (("Ignoring hotplug event - cannot read major:minor"));
+		goto error;
+	}
+
+	hal_device_property_set_int (d, "block.major", major);
+	hal_device_property_set_int (d, "block.minor", minor);
+	hal_device_property_set_bool (d, "block.is_volume", is_partition || is_device_mapper || is_fakevolume);
+
+	if (hal_device_has_property(parent, "info.bus") &&
+		(strcmp(hal_device_property_get_string(parent, "info.bus"), "platform") == 0) &&
+		(sscanf(hal_device_property_get_string(parent, "platform.id"), "floppy.%d", &floppy_num) == 1)) {
+		/* for now, just cheat here for floppy drives */
+
+		HAL_INFO (("doing floppy drive hack for floppy %d", floppy_num));
+
+		hal_device_property_set_string (d, "storage.bus", "platform");
+		hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
+		hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
+		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
+		hal_device_property_set_string (d, "storage.model", "");
+		hal_device_property_set_string (d, "storage.vendor", "PC Floppy Drive");
+		hal_device_property_set_string (d, "info.vendor", "");
+		hal_device_property_set_string (d, "info.product", "PC Floppy Drive");
+		hal_device_property_set_string (d, "storage.drive_type", "floppy");
+		hal_device_property_set_string (d, "storage.physical_device", parent->udi);
+		hal_device_property_set_bool (d, "storage.removable", TRUE);
+		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
+		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
+		hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
+		hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
+		hal_device_property_set_uint64 (d, "storage.size", 0);
+
+		hal_device_property_set_string (d, "info.category", "storage");
+		hal_device_add_capability (d, "storage");
+		hal_device_add_capability (d, "block");
+
+		/* add to TDL so preprobing callouts and prober can access it */
+		hal_device_store_add (hald_get_tdl (), d);
+
+		/* Process preprobe fdi files */
+		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+		/* Run preprobe callouts */
+		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_storage_done, end_token, NULL);
+		goto out2;
+	}
+
+	if (!is_partition && !is_device_mapper && !is_fakevolume) {
+		const char *udi_it;
+		const char *physdev_udi;
+		HalDevice *scsidev;
+		HalDevice *physdev;
+		gboolean is_hotpluggable;
+		gboolean is_removable;
+		gboolean requires_eject;
+		gboolean no_partitions_hint;
+		const gchar *bus;
+		const gchar *parent_bus;
+
+		/********************************
+		 * storage devices
+		 *******************************/
+
+		scsidev = NULL;
+		physdev = NULL;
+		physdev_udi = NULL;
+
+		is_removable = FALSE;
+		is_hotpluggable = FALSE;
+		requires_eject = FALSE;
+		no_partitions_hint = FALSE;
+
+		/* defaults */
+		hal_device_property_set_string (d, "storage.bus", "unknown");
+		hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
+		hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
+		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
+		hal_device_property_set_string (d, "storage.drive_type", "disk");
+
+		/* persistent properties from udev (may be empty) */
+		hal_device_property_set_string (d, "storage.model", hotplug_event->sysfs.model);
+		hal_device_property_set_string (d, "storage.vendor", hotplug_event->sysfs.vendor);
+		if (hotplug_event->sysfs.serial[0] != '\0')
+			hal_device_property_set_string (d, "storage.serial", hotplug_event->sysfs.serial);
+		if (hotplug_event->sysfs.revision[0] != '\0')
+			hal_device_property_set_string (d, "storage.firmware_version", hotplug_event->sysfs.revision);
+
+		/* walk up the device chain to find the physical device, 
+		 * start with our parent. On the way, optionally pick up
+		 * the scsi if it exists */
+		udi_it = parent->udi;
+		while (udi_it != NULL) {
+			HalDevice *d_it;
+
+			/*************************
+			 *
+			 * STORAGE
+			 *
+			 ************************/
+
+			/* Find device */
+			d_it = hal_device_store_find (hald_get_gdl (), udi_it);
+			g_assert (d_it != NULL);
+
+			/* Check info.bus */
+			if ((bus = hal_device_property_get_string (d_it, "info.bus")) != NULL) {
+				if (strcmp (bus, "scsi") == 0) {
+					scsidev = d_it;
+					physdev = d_it;
+					physdev_udi = udi_it;
+					hal_device_property_set_string (d, "storage.bus", "scsi");
+					hal_device_copy_property (scsidev, "scsi.lun", d, "storage.lun");
+					/* want to continue here, because it may be USB or IEEE1394 */
+				}
+
+				if (strcmp (bus, "usb") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					is_hotpluggable = TRUE;
+					hal_device_property_set_string (d, "storage.bus", "usb");
+					break;
+				} else if (strcmp (bus, "ieee1394") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					is_hotpluggable = TRUE;
+					hal_device_property_set_string (d, "storage.bus", "ieee1394");
+					break;
+				} else if (strcmp (bus, "ide") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					hal_device_property_set_string (d, "storage.bus", "ide");
+					/* want to continue here, because it may be pcmcia */
+				} else if (strcmp (bus, "pcmcia") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					is_hotpluggable = TRUE;
+					hal_device_property_set_string (d, "storage.bus", "pcmcia");
+					break;
+				} else if (strcmp (bus, "mmc") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					is_hotpluggable = TRUE;
+					hal_device_property_set_string (d, "storage.bus", "mmc");
+					break;
+				} else if (strcmp (bus, "ccw") == 0) {
+					physdev = d_it;
+					physdev_udi = udi_it;
+					is_hotpluggable = TRUE;
+					hal_device_property_set_string
+						(d, "storage.bus", "ccw");
+				}
+			}
+
+			/* Go to parent */
+			udi_it = hal_device_property_get_string (d_it, "info.parent");
+		}
+
+		/* needs physical device */
+		if (physdev_udi == NULL) {
+			HAL_WARNING (("No physical device?"));
+			goto error;
+		}
+
+		hal_device_property_set_string (d, "storage.physical_device", physdev_udi);
+
+		if (!hal_util_get_int_from_file (sysfs_path, "removable", (gint *) &is_removable, 10)) {
+			HAL_WARNING (("Cannot get 'removable' file"));
+			goto error;
+		}
+
+		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
+		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
+		hal_device_property_set_bool (d, "storage.removable", is_removable);
+		/* set storage.size only if we have fixed media */
+		if (!is_removable) {
+			guint64 num_blocks;
+			if (hal_util_get_uint64_from_file (sysfs_path, "size", &num_blocks, 0)) {
+				/* TODO: sane to assume this is always 512 for non-removable? 
+				 * I think genhd.c guarantees this... */
+				hal_device_property_set_uint64 (d, "storage.size", num_blocks * 512);
+			}
+		} else {
+			hal_device_property_set_uint64 (d, "storage.size", 0);
+		}
+
+		/* by default, do checks for media if, and only if, the removable file is set to 1
+		 *
+		 * Problematic buses, like IDE, may override this.
+		 */
+		hal_device_property_set_bool (d, "storage.media_check_enabled", is_removable);
+
+		parent_bus = hal_device_property_get_string (parent, "info.bus");
+		if (parent_bus == NULL) {
+			HAL_INFO (("parent_bus is NULL - wrong parent?"));
+			goto error;
+		}
+		HAL_INFO (("parent_bus is %s", parent_bus));
+
+		/* per-bus specific properties */
+		if (strcmp (parent_bus, "ide") == 0) {
+			char buf[256];
+			gchar *media;
+			gchar *model;
+
+			/* Be conservative and don't poll IDE drives at all (except CD-ROM's, see below) */
+			hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
+
+			/* according to kernel source, media can assume the following values:
+			 *
+			 * "disk", "cdrom", "tape", "floppy", "UNKNOWN"
+			 */
+			snprintf (buf, sizeof (buf), "%s/ide/%s", get_hal_proc_path (), hal_util_get_last_element (sysfs_path));
+			if ((media = hal_util_get_string_from_file (buf, "media")) != NULL) {
+				if (strcmp (media, "disk") == 0 ||
+				    strcmp (media, "cdrom") == 0 ||
+				    strcmp (media, "floppy") == 0) {
+					hal_device_property_set_string (d, "storage.drive_type", media);
+				} else {
+					HAL_WARNING (("Cannot determine IDE drive type from file %s/media", buf));
+					goto error;
+				}
+
+				if (strcmp (media, "cdrom") == 0) {
+					/* only optical drives are the only IDE devices that can safely be polled */
+					hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
+				}
+			}
+
+			if ((model = hal_util_get_string_from_file (buf, "model")) != NULL) {
+				hal_device_property_set_string (d, "storage.model", model);
+				hal_device_property_set_string (d, "info.product", model);
+			}
+
+		} else if (strcmp (parent_bus, "scsi") == 0) {
+			if (strcmp (hal_device_property_get_string (parent, "scsi.type"), "unknown") == 0) {
+				HAL_WARNING (("scsi.type is unknown"));
+				goto error;
+			}
+			hal_device_copy_property (parent, "scsi.type", d, "storage.drive_type");
+			hal_device_copy_property (parent, "scsi.vendor", d, "storage.vendor");
+			hal_device_copy_property (parent, "scsi.model", d, "storage.model");
+
+			hal_device_copy_property (d, "storage.vendor", d, "info.vendor");
+			hal_device_copy_property (d, "storage.model", d, "info.product");
+
+			/* Check for USB floppy drive by looking at USB Mass Storage interface class
+			 * instead of Protocol: Uniform Floppy Interface (UFI) in /proc as we did before.
+			 *
+			 * (should fix RH bug 133834)
+			 */
+			if (physdev != NULL) {
+				if (hal_device_property_get_int (physdev, "usb.interface.class") == 8 &&
+				    hal_device_property_get_int (physdev, "usb.interface.subclass") == 4 ) {
+					
+					hal_device_property_set_string (d, "storage.drive_type", "floppy");
+					
+					/* My experiments with my USB LaCie Floppy disk
+					 * drive is that polling indeed work (Yay!), so
+					 * we don't set storage.media_check_enabled to 
+					 * FALSE - for devices where this doesn't work,
+					 * we can override it with .fdi files
+					 */
+				}
+			}
+
+		} else if (strcmp (parent_bus, "mmc") == 0) {
+			hal_device_property_set_string (d, "storage.drive_type", "sd_mmc");
+		}
+
+		hal_device_property_set_string (d, "info.category", "storage");
+		hal_device_add_capability (d, "storage");
+		hal_device_add_capability (d, "block");
+
+		if (strcmp (hal_device_property_get_string (d, "storage.drive_type"), "cdrom") == 0) {
+			hal_device_add_capability (d, "storage.cdrom");
+			no_partitions_hint = TRUE;
+			requires_eject = TRUE;
+		}
+
+		if (strcmp (hal_device_property_get_string (d, "storage.drive_type"), "floppy") == 0) {
+			no_partitions_hint = TRUE;
+		}
+
+		hal_device_property_set_bool (d, "storage.hotpluggable", is_hotpluggable);
+		hal_device_property_set_bool (d, "storage.requires_eject", requires_eject);
+		hal_device_property_set_bool (d, "storage.no_partitions_hint", no_partitions_hint);
+
+		/* add to TDL so preprobing callouts and prober can access it */
+		hal_device_store_add (hald_get_tdl (), d);
+
+		/* Process preprobe fdi files */
+		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+		/* Run preprobe callouts */
+		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_storage_done, end_token, NULL);
+
+	} else {
+		guint sysfs_path_len;
+		gboolean is_physical_partition;
+
+		/*************************
+		 *
+		 * VOLUMES
+		 *
+		 ************************/
+		hal_device_property_set_string (d, "block.storage_device", parent->udi);
+
+		/* defaults */
+		hal_device_property_set_string (d, "storage.model", "");
+		hal_device_property_set_string (d, "volume.fstype", "");
+		hal_device_property_set_string (d, "volume.fsusage", "");
+		hal_device_property_set_string (d, "volume.fsversion", "");
+		hal_device_property_set_string (d, "volume.uuid", "");
+		hal_device_property_set_string (d, "volume.label", "");
+		hal_device_property_set_string (d, "volume.mount_point", "");
+		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
+		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
+		hal_device_property_set_bool (d, "volume.linux.is_device_mapper", is_device_mapper);
+		hal_device_property_set_bool (
+			d, "volume.is_disc", 
+			strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0);
+
+
+		is_physical_partition = TRUE;
+		if (is_fakevolume || is_device_mapper)
+			is_physical_partition = FALSE;
+
+		hal_device_property_set_bool (d, "volume.is_partition", is_physical_partition);
+
+		hal_device_property_set_string (d, "info.category", "volume");
+		if (strcmp(hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
+			hal_device_add_capability (d, "volume.disc");
+		}
+		hal_device_add_capability (d, "volume");
+		hal_device_add_capability (d, "block");
+
+		/* determine partition number */
+		sysfs_path_len = strlen (sysfs_path);
+		if (is_physical_partition) {
+			if (sysfs_path_len > 0 && isdigit (sysfs_path[sysfs_path_len - 1])) {
+				guint i;
+				for (i = sysfs_path_len - 1; isdigit (sysfs_path[i]); --i)
+					;
+				if (isdigit (sysfs_path[i+1])) {
+					guint partition_number;
+					partition_number = atoi (&sysfs_path[i+1]);
+					hal_device_property_set_int (d, "volume.partition.number", partition_number);
+				} else {
+					HAL_WARNING (("Cannot determine partition number?"));
+					goto error;
+				}
+			} else {
+				HAL_WARNING (("Cannot determine partition number"));
+				goto error;
+			}
+		}
+
+		/* first estimate - prober may override this...
+		 *
+		 * (block size requires opening the device file)
+		 */
+		hal_device_property_set_int (d, "volume.block_size", 512);
+		if (!hal_util_set_int_from_file (d, "volume.num_blocks", sysfs_path_real, "size", 0)) {
+			HAL_INFO (("Ignoring hotplug event - cannot read 'size'"));
+			goto error;
+		}
+		hal_device_property_set_uint64 (
+			d, "volume.size",
+			((dbus_uint64_t)(512)) * ((dbus_uint64_t)(hal_device_property_get_int (d, "volume.num_blocks"))));
+		/* TODO: move to prober? */
+		if (is_physical_partition) {
+			guint64 start_block;
+			guint64 parent_size;
+			if (hal_util_get_uint64_from_file (sysfs_path, "start", &start_block, 0)) {
+				hal_device_property_set_uint64 (d, "volume.partition.start", start_block * 512);
+			}
+			if (hal_util_get_uint64_from_file (sysfs_path, "../size", &parent_size, 0)) {
+				hal_device_property_set_uint64 (d, "volume.partition.media_size", parent_size * 512);
+			}
+		}
+
+
+		/* add to TDL so preprobing callouts and prober can access it */
+		hal_device_store_add (hald_get_tdl (), d);
+
+		/* Process preprobe fdi files */
+		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+		/* Run preprobe callouts */
+		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_volume_done, end_token, NULL);
+	}
+out2:
+	g_free (sysfs_path_real);
+	return;
+
+error:
+	HAL_WARNING (("Not adding device object"));
+	if (d != NULL)
+		g_object_unref (d);
+out:
+	hotplug_event_end (end_token);
+	g_free (sysfs_path_real);
+}
+
+static void
+force_unmount_cb (HalDevice *d, guint32 exit_type, 
+		  gint return_code, gchar **error,
+		  gpointer data1, gpointer data2)
+{
+	void *end_token = (void *) data1;
+
+	HAL_INFO (("force_unmount_cb for udi='%s', exit_type=%d, return_code=%d", d->udi, exit_type, return_code));
+
+	if (exit_type == HALD_RUN_SUCCESS && error != NULL && 
+	    error[0] != NULL && error[1] != NULL) {
+		char *exp_name = NULL;
+		char *exp_detail = NULL;
+
+		exp_name = error[0];
+		if (error[0] != NULL) {
+			exp_detail = error[1];
+		}
+		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
+	}
+
+	hal_util_callout_device_remove (d, blockdev_callouts_remove_done, end_token, NULL);
+
+}
+
+static void
+force_unmount (HalDevice *d, void *end_token)
+{
+	const char *device_file;
+	const char *mount_point;
+
+	device_file = hal_device_property_get_string (d, "block.device");
+	mount_point = hal_device_property_get_string (d, "volume.mount_point");
+
+	/* look up in /media/.hal-mtab to see if we mounted this one */
+	if (mount_point != NULL && strlen (mount_point) > 0 && hal_util_is_mounted_by_hald (mount_point)) {
+		char *unmount_stdin;
+		char *extra_env[2];
+
+		extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
+		extra_env[1] = NULL;
+		
+		HAL_INFO (("force_unmount for udi='%s'", d->udi));
+		syslog (LOG_NOTICE, "forcibly attempting to lazy unmount %s as enclosing drive was disconnected", device_file);
+		
+		unmount_stdin = "lazy\n";
+		
+		/* so, yea, calling the Unmount methods handler.. is cheating a bit :-) */
+		hald_runner_run_method (d, 
+					"hal-storage-unmount", 
+					extra_env, 
+					unmount_stdin, TRUE,
+					0,
+					force_unmount_cb,
+					end_token, NULL);
+
+/*
+		char *cleanup_stdin;
+		char *extra_env[2];
+		
+		HAL_INFO (("Cleaning up directory '%s' since it was created by HAL's Mount()", mount_point));
+		
+		extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
+		extra_env[1] = NULL;
+		cleanup_stdin = "\n";
+		
+		hald_runner_run_method (dev, 
+					"hal-storage-cleanup-mountpoint", 
+					extra_env, 
+					cleanup_stdin, TRUE,
+					0,
+					cleanup_mountpoint_cb,
+					g_strdup (mount_point), NULL);
+*/
+	}
+
+
+}
+
+void
+hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, void *end_token)
+{
+	HalDevice *d;
+
+	HAL_INFO (("block_rem: sysfs_path=%s is_part=%d", sysfs_path));
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
+	if (d == NULL) {
+		HAL_WARNING (("Device is not in the HAL database"));
+		hotplug_event_end (end_token);
+	} else {
+		HalDevice *fakevolume;
+		char fake_sysfs_path[HAL_PATH_MAX];
+
+		/* if we're a storage device synthesize hotplug rem event 
+		 * for the one potential fakevolume we've got 
+		 */
+		snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
+		fakevolume = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", fake_sysfs_path);
+		if (fakevolume != NULL) {
+			HotplugEvent *hotplug_event;
+			HAL_INFO (("Storage device with a fakevolume is going away; "
+				   "synthesizing hotplug rem for fakevolume %s", fakevolume->udi));
+			hotplug_event = blockdev_generate_remove_hotplug_event (fakevolume);
+			if (hotplug_event != NULL) {
+				/* push synthesized event at front of queue and repost this event... this is such that
+				 * the fakevolume event is processed before this one... because if we didn't make the
+				 * events to be processed in this order, the "lazy unmount" of the fakevolume would
+				 * fail...
+				 */
+				hotplug_event_enqueue_at_front ((HotplugEvent *) end_token);
+				hotplug_event_enqueue_at_front (hotplug_event);
+				hotplug_event_reposted (end_token);
+				goto out;
+			}
+
+		}
+		
+		/* if we're mounted, then do a lazy unmount so the system can gracefully recover */
+		if (hal_device_property_get_bool (d, "volume.is_mounted")) {
+			force_unmount (d, end_token);
+		} else {
+			hal_util_callout_device_remove (d, blockdev_callouts_remove_done, end_token, NULL);
+		}
+	}
+out:
+	;
+}
+
+static void 
+block_rescan_storage_done (HalDevice *d, guint32 exit_type, 
+                           gint return_code, gchar **error,
+                           gpointer data1, gpointer data2)
+{
+	const char *sysfs_path;
+	HalDevice *fakevolume;
+	char fake_sysfs_path[HAL_PATH_MAX];
+
+	HAL_INFO (("hald-probe-storage --only-check-for-media returned %d (exit_type=%d)", return_code, exit_type));
+
+	if (d == NULL) {
+		HAL_INFO (("Device object already removed"));
+		goto out;
+	}
+
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	/* see if we already got a fake volume */
+	snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
+	fakevolume = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", fake_sysfs_path);
+
+	if (return_code == 2) {
+		/* we've got something on the main block device - add fakevolume if we haven't got one already */
+		if (fakevolume == NULL) {
+			HAL_INFO (("Media insertion detected with file system on main block device; synthesizing hotplug add"));
+			generate_fakevolume_hotplug_event_add_for_storage_device (d);
+		}
+	} else {
+		/* no fs on the main block device - remove fakevolume if we have one */
+		if (fakevolume != NULL) {
+			/* generate hotplug event to remove the fakevolume */
+			HotplugEvent *hotplug_event;
+			HAL_INFO (("Media removal detected; synthesizing hotplug rem for fakevolume %s", fakevolume->udi));
+			hotplug_event = blockdev_generate_remove_hotplug_event (fakevolume);
+			if (hotplug_event != NULL) {
+				hotplug_event_enqueue (hotplug_event);
+				hotplug_event_process_queue ();
+			}
+		}
+	}
+
+out:
+	;
+}
+
+gboolean
+blockdev_rescan_device (HalDevice *d)
+{
+	gboolean ret;
+
+	ret = FALSE;
+
+	HAL_INFO (("Entering, udi=%s", d->udi));
+
+	/* This only makes sense on storage devices */
+	if (hal_device_property_get_bool (d, "block.is_volume")) {
+		HAL_INFO (("No action on volumes", d->udi));
+		goto out;
+	}
+
+	/* now see if we got a file system on the main block device */
+	hald_runner_run (d,
+	                 "hald-probe-storage --only-check-for-media", NULL, 
+	                 HAL_HELPER_TIMEOUT,
+	                 block_rescan_storage_done,
+	                 NULL, NULL);
+	ret = TRUE;
+
+out:
+	return ret;
+}
+
+
+HotplugEvent *
+blockdev_generate_add_hotplug_event (HalDevice *d)
+{
+	const char *sysfs_path;
+	const char *device_file;
+	const char *model;
+	const char *vendor;
+	const char *serial;
+	const char *revision;
+	HotplugEvent *hotplug_event;
+	const char *nul;
+
+	nul = "\0";
+
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	device_file = hal_device_property_get_string (d, "block.device");
+	model       = hal_device_property_get_string (d, "storage.model");
+	vendor      = hal_device_property_get_string (d, "storage.vendor");
+	serial      = hal_device_property_get_string (d, "storage.serial");
+	revision    = hal_device_property_get_string (d, "storage.firmware_revision");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+
+	g_strlcpy (hotplug_event->sysfs.device_file, device_file != NULL ? device_file : nul, HAL_NAME_MAX);
+	g_strlcpy (hotplug_event->sysfs.vendor,           vendor != NULL ?      vendor : nul, HAL_NAME_MAX);
+	g_strlcpy (hotplug_event->sysfs.model,             model != NULL ?       model : nul, HAL_NAME_MAX);
+	g_strlcpy (hotplug_event->sysfs.serial,           serial != NULL ?      serial : nul, HAL_NAME_MAX);
+	g_strlcpy (hotplug_event->sysfs.revision,       revision != NULL ?    revision : nul, HAL_NAME_MAX);
+
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
+
+HotplugEvent *
+blockdev_generate_remove_hotplug_event (HalDevice *d)
+{
+	const char *sysfs_path;
+	HotplugEvent *hotplug_event;
+
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
diff --git a/hald/linux/blockdev.h b/hald/linux/blockdev.h
new file mode 100644
index 0000000..9095d8c
--- /dev/null
+++ b/hald/linux/blockdev.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * blockdev.h : Handling of block devices 
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef BLOCKDEV_H
+#define BLOCKDEV_H
+
+#include <glib.h>
+
+void hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const char *device_file, gboolean is_partition, HalDevice *parent, void *end_token);
+
+void hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, void *end_token);
+
+gboolean blockdev_rescan_device (HalDevice *d);
+
+HotplugEvent *blockdev_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *blockdev_generate_remove_hotplug_event (HalDevice *d);
+
+void blockdev_refresh_mount_state (HalDevice *d);
+
+#endif /* BLOCKDEV_H */
diff --git a/hald/linux/classdev.c b/hald/linux/classdev.c
new file mode 100644
index 0000000..3e3a667
--- /dev/null
+++ b/hald/linux/classdev.c
@@ -0,0 +1,1495 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * classdev.c : Handling of functional kernel devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005 Richard Hughes, <richard at hughsie.com>
+ * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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 <ctype.h>
+#include <limits.h>
+#include <linux/types.h>
+#include <net/if_arp.h> /* for ARPHRD_... */
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../device_store.h"
+#include "../hald.h"
+#include "../hald_runner.h"
+#include "../logger.h"
+#include "../osspec.h"
+#include "../util.h"
+
+#include "coldplug.h"
+#include "hotplug_helper.h"
+#include "osspec_linux.h"
+
+#include "classdev.h"
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	if (physdev != NULL) {
+		hal_device_property_set_string (d, "input.physical_device", physdev->udi);
+		hal_device_property_set_string (d, "info.parent", physdev->udi);
+	} else {
+		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
+	}
+	hal_device_property_set_string (d, "info.category", "input");
+	hal_device_add_capability (d, "input");
+
+	hal_device_property_set_string (d, "input.device", device_file);
+
+	return d;
+}
+
+static const gchar *
+input_get_prober (HalDevice *d)
+{
+	return "hald-probe-input";
+}
+
+static gboolean
+input_post_probing (HalDevice *d)
+{
+	return TRUE;
+}
+
+static gboolean
+input_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_logicaldev_input",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+bluetooth_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, 
+	       const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = NULL;
+
+	if (physdev == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	hal_device_property_set_string (d, "info.category", "bluetooth_hci");
+	hal_device_add_capability (d, "bluetooth_hci");
+
+	hal_device_property_set_string (d, "bluetooth_hci.physical_device", physdev->udi);
+	hal_util_set_string_from_file (d, "bluetooth_hci.interface_name", sysfs_path, "name");
+
+	hal_device_property_set_string (d, "info.product", "Bluetooth Host Controller Interface");
+
+out:
+	return d;
+}
+
+static gboolean
+bluetooth_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_bluetooth_hci",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+net_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	const gchar *ifname;
+	guint media_type;
+	gint flags;
+
+	d = NULL;
+
+	if (physdev == NULL)
+		goto error;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	hal_device_property_set_string (d, "info.category", "net");
+	hal_device_add_capability (d, "net");
+
+	hal_device_property_set_string (d, "net.physical_device", physdev->udi);
+
+	ifname = hal_util_get_last_element (sysfs_path);
+	hal_device_property_set_string (d, "net.interface", ifname);
+
+	if (!hal_util_set_string_from_file (d, "net.address", sysfs_path, "address")) {
+		hal_device_property_set_string (d, "net.address", "00:00:00:00:00:00");	
+	}
+
+	if (!hal_util_set_int_from_file (d, "net.linux.ifindex", sysfs_path, "ifindex", 10))
+		goto error;
+
+	if (!hal_util_set_int_from_file (d, "net.arp_proto_hw_id", sysfs_path, "type", 10))
+		goto error;
+
+	if (!hal_util_get_int_from_file (sysfs_path, "flags", &flags, 16))
+		goto error;
+
+	media_type = hal_device_property_get_int (d, "net.arp_proto_hw_id");
+	if (media_type == ARPHRD_ETHER) {
+		FILE *f;
+		gboolean is_wireless;
+		const char *addr;
+
+		is_wireless = FALSE;
+
+		f = fopen ("/proc/net/wireless", "ro");
+		if (f != NULL) {
+			unsigned int i;
+			unsigned int ifname_len;
+			char buf[128];
+
+			ifname_len = strlen (ifname);
+
+			do {
+				if (fgets (buf, sizeof (buf), f) == NULL)
+					break;
+
+				for (i=0; i < sizeof (buf); i++) {
+					if (isspace (buf[i]))
+						continue;
+					else
+						break;
+				}
+
+				if (strncmp (ifname, buf + i, ifname_len) == 0) {
+					is_wireless = TRUE;
+					break;
+				}
+
+			} while (TRUE);
+			fclose (f);
+		}
+
+		if (is_wireless) {
+		/* Check to see if this interface supports wireless extensions */
+		/*
+		snprintf (wireless_path, SYSFS_PATH_MAX, "%s/wireless", sysfs_path);
+		if (stat (wireless_path, &statbuf) == 0) {
+		*/
+			hal_device_property_set_string (d, "info.product", "WLAN Interface");
+			hal_device_property_set_string (d, "info.category", "net.80211");
+			hal_device_add_capability (d, "net.80211");
+		} else {
+			hal_device_property_set_string (d, "info.product", "Networking Interface");
+			hal_device_property_set_string (d, "info.category", "net.80203");
+			hal_device_add_capability (d, "net.80203");
+		}
+
+		addr = hal_device_property_get_string (d, "net.address");
+		if (addr != NULL) {
+			unsigned int a5, a4, a3, a2, a1, a0;
+			
+			if (sscanf (addr, "%x:%x:%x:%x:%x:%x",
+				    &a5, &a4, &a3, &a2, &a1, &a0) == 6) {
+				dbus_uint64_t mac_address;
+				
+				mac_address = 
+					((dbus_uint64_t)a5<<40) |
+					((dbus_uint64_t)a4<<32) | 
+					((dbus_uint64_t)a3<<24) | 
+					((dbus_uint64_t)a2<<16) | 
+					((dbus_uint64_t)a1<< 8) | 
+					((dbus_uint64_t)a0<< 0);
+				
+				hal_device_property_set_uint64 (d, is_wireless ? "net.80211.mac_address" : 
+								"net.80203.mac_address",
+								mac_address);
+			}
+		}
+	}
+
+	return d;
+error:
+	if (d != NULL) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		d = NULL;
+	}
+
+	return d;
+}
+
+static gboolean
+net_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+	const gchar *id;
+
+	id = hal_device_property_get_string (d, "net.address");
+	if (id == NULL || (strcmp (id, "00:00:00:00:00:00") == 0)) {
+		/* Need to fall back to something else if mac not available. */
+		id = hal_util_get_last_element(hal_device_property_get_string(d, "net.physical_device"));
+	}
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/net_%s",
+			      id);
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+scsi_generic_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL)
+		goto out;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "scsi_generic");
+	hal_device_add_capability (d, "scsi_generic");
+	hal_device_property_set_string (d, "info.product", "SCSI Generic Interface");
+	hal_device_property_set_string (d, "scsi_generic.device", device_file);
+
+out:
+	return d;
+}
+
+static gboolean
+scsi_generic_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_scsi_generic",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+scsi_host_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	gint host_num;
+	const gchar *last_elem;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
+	
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	hal_device_property_set_string (d, "info.category", "scsi_host");
+	hal_device_add_capability (d, "scsi_host");
+
+	hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
+
+	last_elem = hal_util_get_last_element (sysfs_path);
+	sscanf (last_elem, "host%d", &host_num);
+	hal_device_property_set_int (d, "scsi_host.host", host_num);
+
+out:
+	return d;
+}
+
+static gboolean
+scsi_host_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_scsi_host",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+usbclass_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	gint host_num;
+	const gchar *last_elem;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL || device_file == NULL) {
+		goto out;
+	}
+
+	last_elem = hal_util_get_last_element (sysfs_path);
+	if (sscanf (last_elem, "hiddev%d", &host_num) == 1) {
+
+		d = hal_device_new ();
+		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+		hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
+		hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+		hal_device_property_set_string (d, "info.category", "hiddev");
+		hal_device_add_capability (d, "hiddev");
+
+		hal_device_property_set_string (d, "info.product", "USB HID Device");
+
+		hal_device_property_set_string (d, "hiddev.device", device_file);
+	} else if (sscanf (last_elem, "lp%d", &host_num) == 1) {
+
+		d = hal_device_new ();
+		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+		hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
+		hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+		hal_device_property_set_string (d, "info.category", "printer");
+		hal_device_add_capability (d, "printer");
+
+		hal_device_property_set_string (d, "info.product", "Printer");
+		hal_device_property_set_string (d, "printer.device", device_file);
+
+		hal_device_property_set_string (d, "printer.physical_device", physdev->udi);
+	}
+
+out:
+	return d;
+}
+
+static const gchar *
+usbclass_get_prober (HalDevice *d)
+{
+	if (hal_device_has_capability (d, "hiddev"))
+		return "hald-probe-hiddev";
+	else if (hal_device_has_capability (d, "printer"))
+		return "hald-probe-printer";
+	else
+		return NULL;
+}
+
+static gboolean
+usbclass_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	if (hal_device_has_capability (d, "hiddev")) {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_hiddev",
+				      hal_device_property_get_string (d, "info.parent"));
+		hal_device_set_udi (d, udi);
+		hal_device_property_set_string (d, "info.udi", udi);
+	} else if (hal_device_has_capability (d, "printer")) {
+		const char *serial;
+
+		serial = hal_device_property_get_string (d, "printer.serial");
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_printer_%s",
+				      hal_device_property_get_string (d, "info.parent"),
+				      serial != NULL ? serial : "noserial");
+		hal_device_set_udi (d, udi);
+		hal_device_property_set_string (d, "info.udi", udi);
+	}
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+usbraw_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL)
+		goto out;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "usbraw");
+	hal_device_add_capability (d, "usbraw");
+	hal_device_property_set_string (d, "info.product", "USB Raw Device Access");
+	hal_device_property_set_string (d, "usbraw.device", device_file);
+
+out:
+	return d;
+}
+
+static gboolean
+usbraw_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_usbraw",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+video4linux_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL)
+		goto out;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "video4linux");
+	hal_device_add_capability (d, "video4linux");
+	hal_device_property_set_string (d, "info.product", "Video Device");
+	hal_device_property_set_string (d, "video4linux.device", device_file);
+
+out:
+	return d;
+}
+
+static gboolean
+video4linux_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_video4linux",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+dvb_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL)
+		goto out;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "dvb");
+	hal_device_add_capability (d, "dvb");
+	hal_device_property_set_string (d, "info.product", "DVB Device");
+	hal_device_property_set_string (d, "dvb.device", device_file);
+
+out:
+	return d;
+}
+
+static gboolean
+dvb_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_dvb",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+sound_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	int cardnum, devicenum;
+	char type;
+	const gchar *device;
+	gchar *device_id;
+	char aprocdir[256];
+	char buf[256];
+
+	d = NULL;
+
+	if (device_file == NULL) 
+		goto out;	
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	device = hal_util_get_last_element(sysfs_path);
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL) {
+ 		/* handle global ALSA and OSS devices, these devices are for all ALSA/OSS Sound devices
+		   so we append them to /org/freedesktop/Hal/devices/computer */
+		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
+
+		if (!strncmp (device, "timer", 5)){
+			/* handle global ALSA Timer device */
+			hal_device_property_set_string (d, "info.category", "alsa");
+			hal_device_add_capability (d, "alsa");
+			hal_device_property_set_string (d, "alsa.type", "timer");
+			hal_device_property_set_string (d, "info.product", "ALSA Timer Device");
+			hal_device_property_set_string (d, "alsa.device_file", device_file);
+		} else if (!strncmp (device, "sequencer", 9)){
+			/* handle global OSS sequencer devices */
+			hal_device_property_set_string (d, "info.category", "oss");
+			hal_device_add_capability (d, "oss");
+			hal_device_property_set_string (d, "oss.type", "sequencer");
+			hal_device_property_set_string (d, "info.product", "OSS Sequencer Device");
+			hal_device_property_set_string (d, "oss.device_file", device_file);
+		} else if (!strncmp (device, "seq", 3) && strlen(device) == 3) { 
+			/* handle global ALSA sequencer devices */
+			hal_device_property_set_string (d, "info.category", "alsa");
+			hal_device_add_capability (d, "alsa");
+			hal_device_property_set_string (d, "alsa.type", "sequencer");
+			hal_device_property_set_string (d, "info.product", "ALSA Sequencer Device");
+			hal_device_property_set_string (d, "alsa.device_file", device_file);	
+		} else {
+			goto error;
+		}
+	} else {
+		/* handle ALSA and OSS devices with physdev link in sys */
+		if (sscanf (device, "controlC%d", &cardnum) == 1) {
+			
+			hal_device_property_set_string (d, "info.category", "alsa");
+			hal_device_add_capability (d, "alsa");
+			hal_device_property_set_string (d, "alsa.device_file", device_file);
+			hal_device_property_set_string (d, "info.parent", physdev->udi);
+			hal_device_property_set_string (d, "alsa.physical_device", physdev->udi);
+			hal_device_property_set_int (d, "alsa.card", cardnum);
+			hal_device_property_set_string (d, "alsa.type", "control");
+	
+			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
+			hal_util_set_string_from_file (d, "alsa.card_id", aprocdir, "id");
+	
+			snprintf (buf, sizeof (buf), "%s ALSA Control Device", 
+				hal_device_property_get_string (d, "alsa.card_id"));
+			hal_device_property_set_string (d, "info.product", buf);
+	
+		} else if (sscanf (device, "pcmC%dD%d%c", &cardnum, &devicenum, &type) == 3) {
+			
+			hal_device_property_set_string (d, "info.category", "alsa");
+			hal_device_add_capability (d, "alsa");
+			hal_device_property_set_string (d, "alsa.device_file", device_file);
+			hal_device_property_set_string (d, "info.parent", physdev->udi);
+			hal_device_property_set_string (d, "alsa.physical_device", physdev->udi);
+			hal_device_property_set_int (d, "alsa.card", cardnum);
+			hal_device_property_set_int (d, "alsa.device", devicenum);
+	
+			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
+			hal_util_set_string_from_file (d, "alsa.card_id", aprocdir, "id");
+	
+			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm%d%c", 
+				get_hal_proc_path (), cardnum, devicenum, type);
+			device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
+			if (device_id != NULL) {
+				hal_device_property_set_string (d, "alsa.device_id", device_id);
+			}
+	
+			if (type == 'p') {
+				hal_device_property_set_string (d, "alsa.type", "playback");
+				if (device_id != NULL) {
+					snprintf (buf, sizeof (buf), "%s ALSA Playback Device", device_id);
+					hal_device_property_set_string (d, "info.product", buf);
+				} else
+					hal_device_property_set_string (d, "info.product", "ALSA Playback Device");
+			} else if (type == 'c') {
+				hal_device_property_set_string (d, "alsa.type", "capture");
+				if (device_id != NULL) {
+					snprintf (buf, sizeof (buf), "%s ALSA Capture Device", device_id);
+					hal_device_property_set_string (d, "info.product", buf);
+				} else
+					hal_device_property_set_string (d, "info.product", "ALSA Capture Device");
+			} else {
+				hal_device_property_set_string (d, "alsa.type", "unknown");
+				if (device_id != NULL) {
+					snprintf (buf, sizeof (buf), "%s ALSA Device", device_id);
+					hal_device_property_set_string (d, "info.product", buf);
+				} else
+					hal_device_property_set_string (d, "info.product", "ALSA Device");
+			}
+		} else if (!strncmp (device, "dsp", 3) || !strncmp (device, "adsp", 4) || 
+			   !strncmp (device, "midi", 4) || !strncmp (device, "amidi", 5) ||
+			   !strncmp (device, "audio", 5) || !strncmp (device, "mixer", 5)) {
+			
+			/* handle OSS-Devices */
+			ClassDevOSSDeviceTypes type;
+	
+			if (!strncmp (device, "dsp", 3)) {
+				if(sscanf (device, "dsp%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_DSP;
+			} else if (!strncmp (device, "adsp", 4)) {
+				if(sscanf (device, "adsp%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_ADSP;
+			} else if (!strncmp (device, "midi", 4)) {
+				if(sscanf (device, "midi%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_MIDI;
+			} else if (!strncmp (device, "amidi", 5)) {
+				if(sscanf (device, "amidi%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_AMIDI;
+			} else if (!strncmp (device, "audio", 5)) {
+				if(sscanf (device, "audio%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_AUDIO;
+			} else if (!strncmp (device, "mixer", 5)) {
+				if(sscanf (device, "mixer%d", &cardnum) != 1) cardnum = 0;
+				type = OSS_DEVICE_TYPE_MIXER;
+			} else {
+				cardnum = 0;
+				type = OSS_DEVICE_TYPE_UNKNOWN;
+			}
+
+			hal_device_property_set_string (d, "info.category", "oss");
+			hal_device_add_capability (d, "oss");
+			hal_device_property_set_string (d, "oss.device_file", device_file);
+			hal_device_property_set_string (d, "info.parent", physdev->udi);
+			hal_device_property_set_string (d, "oss.physical_device", physdev->udi);
+			hal_device_property_set_int (d, "oss.card", cardnum);
+	
+			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
+			hal_util_set_string_from_file (d, "oss.card_id", aprocdir, "id");
+	
+			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm0p", 
+				get_hal_proc_path (), cardnum);
+			device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
+			if (device_id != NULL) {
+				hal_device_property_set_string (d, "oss.device_id", device_id);
+			} 
+
+			switch (type) { 
+				case OSS_DEVICE_TYPE_MIXER:
+					hal_device_property_set_string (d, "oss.type", "mixer");
+					if (device_id != NULL) 
+						snprintf (buf, sizeof (buf), "%s OSS Control Device", device_id); 
+					else
+						snprintf (buf, sizeof (buf), "%s OSS Control Device",
+						          hal_device_property_get_string (d, "oss.card_id"));
+					break;
+				case OSS_DEVICE_TYPE_DSP:
+				case OSS_DEVICE_TYPE_AUDIO:
+				case OSS_DEVICE_TYPE_ADSP:
+					if (type == OSS_DEVICE_TYPE_ADSP)
+						hal_device_property_set_int (d, "oss.device", 1);
+					else 
+						hal_device_property_set_int (d, "oss.device", 0);
+
+					hal_device_property_set_string (d, "oss.type", "pcm");
+					if (device_id != NULL) 
+						snprintf (buf, sizeof (buf), "%s OSS PCM Device", device_id); 
+					else
+						snprintf (buf, sizeof (buf), "%s OSS PCM Device",
+						          hal_device_property_get_string (d, "oss.card_id"));
+					break;
+				case OSS_DEVICE_TYPE_MIDI:
+				case OSS_DEVICE_TYPE_AMIDI:
+					if (type == OSS_DEVICE_TYPE_AMIDI)
+						hal_device_property_set_int (d, "oss.device", 1);
+					else
+						hal_device_property_set_int (d, "oss.device", 0);
+					hal_device_property_set_string (d, "oss.type", "midi");
+					if (device_id != NULL) 
+						snprintf (buf, sizeof (buf), "%s OSS MIDI Device", device_id); 
+					else
+						snprintf (buf, sizeof (buf), "%s OSS MIDI Device",
+						          hal_device_property_get_string (d, "oss.card_id"));
+					break;
+				case OSS_DEVICE_TYPE_UNKNOWN:
+				default:
+					hal_device_property_set_string (d, "oss.type", "unknown");
+					if (device_id != NULL) 
+						snprintf (buf, sizeof (buf), "%s OSS Device", device_id); 
+					else
+						snprintf (buf, sizeof (buf), "%s OSS Device",
+						          hal_device_property_get_string (d, "oss.card_id"));
+					break;
+			}
+			hal_device_property_set_string (d, "info.product", buf);
+		}
+		else {
+			goto error;
+		}
+	}
+out:
+	return d;
+
+error: 
+	g_object_unref (d);
+	d = NULL;
+	return d;
+}
+
+static gboolean
+sound_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	if (hal_device_has_property(d, "alsa.card")) {
+		/* don't include card number as it may not be persistent across reboots */
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_alsa_%s_%i",
+				      hal_device_property_get_string (d, "info.parent"),
+				      hal_device_property_get_string (d, "alsa.type"),
+				      hal_device_property_get_int (d, "alsa.device"));
+	} else if (hal_device_has_property(d, "oss.card")) {
+		/* don't include card number as it may not be persistent across reboots */
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_oss_%s_%i",
+				      hal_device_property_get_string (d, "info.parent"),
+				      hal_device_property_get_string (d, "oss.type"),
+				      hal_device_property_get_int (d, "oss.device"));
+	} else if (hal_device_has_property(d, "alsa.type")) {
+		/* handle global ALAS devices */
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_alsa_%s",
+				      hal_device_property_get_string (d, "info.parent"),
+				      hal_device_property_get_string (d, "alsa.type"));
+	} else if (hal_device_has_property(d, "oss.type")) {
+		/* handle global OSS devices */
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_oss_%s",
+				      hal_device_property_get_string (d, "info.parent"),
+				      hal_device_property_get_string (d, "oss.type"));
+	} else {
+		/* fallback */
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_sound_unknown",
+				      hal_device_property_get_string (d, "info.parent"));
+	} 
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+serial_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	int portnum;
+	HalDevice *d;
+	const gchar *last_elem;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL || device_file == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "serial");
+	hal_device_add_capability (d, "serial");
+	hal_device_property_set_string (d, "serial.physical_device", physdev->udi);
+	hal_device_property_set_string (d, "serial.device", device_file);
+
+	last_elem = hal_util_get_last_element(sysfs_path);
+	if (sscanf (last_elem, "ttyS%d", &portnum) == 1) {
+		hal_device_property_set_int (d, "serial.port", portnum);
+		hal_device_property_set_string (d, "serial.type", "platform");
+		hal_device_property_set_string (d, "info.product",
+						hal_device_property_get_string (physdev, "info.product"));
+	} else if (sscanf (last_elem, "ttyUSB%d", &portnum) == 1) {
+		HalDevice *usbdev;
+
+		hal_device_property_set_int (d, "serial.port", portnum);
+		hal_device_property_set_string (d, "serial.type", "usb");
+
+		usbdev = hal_device_store_find (hald_get_gdl (), 
+						hal_device_property_get_string (physdev, "info.parent"));
+		if (usbdev != NULL) {
+			hal_device_property_set_string (d, "info.product",
+							hal_device_property_get_string (usbdev, "info.product"));
+		} else {
+			hal_device_property_set_string (d, "info.product", "USB Serial Port");
+		}
+	} else {
+		int len;
+		int i;
+
+		len = strlen (last_elem);
+
+		for (i = len - 1; i >= 0 && isdigit (last_elem[i]); --i)
+			;
+		if (i == len - 1)
+			portnum = 0;
+		else
+			portnum = atoi (last_elem + i + 1);
+
+		hal_device_property_set_int (d, "serial.port", portnum);
+		hal_device_property_set_string (d, "serial.type", "unknown");
+		hal_device_property_set_string (d, "info.product", "Serial Port");
+	}
+
+out:
+	return d;
+}
+
+static const gchar *
+serial_get_prober (HalDevice *d)
+{
+	/* FIXME TODO: check if there is an other way, to call the porber only
+		 on ttyS* devices, than check the name of the device file */
+	if (!strncmp(hal_device_property_get_string (d, "linux.device_file"), "/dev/ttyS", 9))
+		return "hald-probe-serial";
+	else 
+		return NULL;
+}
+
+static gboolean
+serial_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_serial_%s_%d",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_string (d, "serial.type"),
+			      hal_device_property_get_int (d, "serial.port"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+tape_add (const gchar *sysfs_path, const gchar *device_file, 
+	  HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	const gchar *dev_entry;
+
+	if (physdev == NULL)
+		return NULL;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+	hal_device_property_set_string (d, "info.category", "tape");
+	hal_device_add_capability (d, "tape");
+	hal_device_add_capability (physdev, "tape");
+
+	dev_entry = hal_util_get_string_from_file (sysfs_path, "dev");
+	if (dev_entry != NULL) {
+		unsigned int major, minor;
+
+		if (sscanf (dev_entry, "%d:%d", &major, &minor) != 2) {
+			hal_device_property_set_int (d, "tape.major", major);
+			hal_device_property_set_int (d, "tape.minor", minor);
+		}
+	}
+	return d;
+}
+
+static gboolean
+tape_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+	const gchar *sysfs_name;
+
+	sysfs_name = hal_util_get_last_element (hal_device_property_get_string
+						(d, "linux.sysfs_path"));
+	if (!sysfs_name)
+		return FALSE;
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/tape_%s",
+			      sysfs_name);
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+mmc_host_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
+{
+	HalDevice *d;
+	gint host_num;
+	const gchar *last_elem;
+
+	d = NULL;
+
+	if (physdev == NULL || sysfs_path_in_devices == NULL) {
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
+
+	hal_device_property_set_string (d, "info.parent", physdev->udi);
+
+	hal_device_property_set_string (d, "info.category", "mmc_host");
+	hal_device_add_capability (d, "mmc_host");
+
+	hal_device_property_set_string (d, "info.product", "MMC/SD Host Adapter");
+
+	last_elem = hal_util_get_last_element (sysfs_path);
+	sscanf (last_elem, "mmc%d", &host_num);
+	hal_device_property_set_int (d, "mmc_host.host", host_num);
+
+out:
+	return d;
+}
+
+static gboolean
+mmc_host_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_mmc_host",
+			      hal_device_property_get_string (d, "info.parent"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static gboolean
+classdev_remove (HalDevice *d)
+{
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+struct ClassDevHandler_s;
+typedef struct ClassDevHandler_s ClassDevHandler;
+
+struct ClassDevHandler_s
+{
+	const gchar *subsystem;
+	HalDevice *(*add) (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent, const gchar *sysfs_path_in_devices);
+	const gchar *(*get_prober)(HalDevice *d);
+	gboolean (*post_probing) (HalDevice *d);
+	gboolean (*compute_udi) (HalDevice *d);
+	gboolean (*remove) (HalDevice *d);
+}; 
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static ClassDevHandler classdev_handler_input = 
+{ 
+	.subsystem    = "input",
+	.add          = input_add,
+	.get_prober   = input_get_prober,
+	.post_probing = input_post_probing,
+	.compute_udi  = input_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_bluetooth = 
+{ 
+	.subsystem    = "bluetooth",
+	.add          = bluetooth_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = bluetooth_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_net = 
+{ 
+	.subsystem    = "net",
+	.add          = net_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = net_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_scsi_generic =
+{ 
+	.subsystem    = "scsi_generic",
+	.add          = scsi_generic_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = scsi_generic_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_scsi_host = 
+{ 
+	.subsystem    = "scsi_host",
+	.add          = scsi_host_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = scsi_host_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_usbclass = 
+{ 
+	.subsystem    = "usb",
+	.add          = usbclass_add,
+	.get_prober   = usbclass_get_prober,
+	.post_probing = NULL,
+	.compute_udi  = usbclass_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_usbraw =
+{ 
+	.subsystem    = "usb_device",
+	.add          = usbraw_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = usbraw_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_video4linux =
+{ 
+	.subsystem    = "video4linux",
+	.add          = video4linux_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = video4linux_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_dvb =
+{ 
+	.subsystem    = "dvb",
+	.add          = dvb_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = dvb_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_sound = 
+{ 
+	.subsystem    = "sound",
+	.add          = sound_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = sound_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_serial = 
+{ 
+	.subsystem    = "tty",
+	.add          = serial_add,
+	.get_prober   = serial_get_prober,
+	.post_probing = NULL,
+	.compute_udi  = serial_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_tape =
+{
+	.subsystem    = "tape",
+	.add          = tape_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = tape_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_tape390 =
+{
+	.subsystem    = "tape390",
+	.add          = tape_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = tape_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler classdev_handler_mmc_host =
+{
+	.subsystem    = "mmc_host",
+	.add          = mmc_host_add,
+	.get_prober   = NULL,
+	.post_probing = NULL,
+	.compute_udi  = mmc_host_compute_udi,
+	.remove       = classdev_remove
+};
+
+static ClassDevHandler *classdev_handlers[] = {
+	&classdev_handler_input,
+	&classdev_handler_bluetooth,
+	&classdev_handler_net,
+	&classdev_handler_scsi_generic,
+	&classdev_handler_scsi_host,
+	&classdev_handler_usbclass,
+	&classdev_handler_usbraw,
+	&classdev_handler_video4linux,
+	&classdev_handler_dvb,
+	&classdev_handler_sound,
+	&classdev_handler_serial,
+	&classdev_handler_tape,
+	&classdev_handler_tape390,
+	&classdev_handler_mmc_host,
+	NULL
+};
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static void 
+classdev_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 
+classdev_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"));
+	}
+
+	g_object_unref (d);
+
+	hotplug_event_end (end_token);
+}
+
+static void 
+add_classdev_after_probing (HalDevice *d, ClassDevHandler *handler, void *end_token)
+{
+	/* 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)) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		hotplug_event_end (end_token);
+		goto out;
+	}
+	
+	/* TODO: Merge persistent properties */
+
+	/* Run callouts */
+	hal_util_callout_device_add (d, classdev_callouts_add_done, end_token, NULL);
+
+out:
+	;
+}
+
+static void 
+add_classdev_probing_helper_done (HalDevice *d, guint32 exit_type, 
+                                  gint return_code, char **error,
+                                  gpointer data1, gpointer data2) 
+{
+	void *end_token = (void *) data1;
+	ClassDevHandler *handler = (ClassDevHandler *) data2;
+
+	HAL_INFO (("entering; exit_type=%d, return_code=%d", exit_type, return_code));
+
+	if (d == NULL) {
+		HAL_INFO (("Device object already removed"));
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	/* Discard device if probing reports failure */
+	if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	/* Do things post probing */
+	if (handler->post_probing != NULL) {
+		if (!handler->post_probing (d)) {
+			hotplug_event_end (end_token);
+			goto out;
+		}
+	}
+
+	add_classdev_after_probing (d, handler, end_token);
+
+out:
+	;
+}
+
+static void 
+classdev_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	void *end_token = (void *) userdata1;
+	ClassDevHandler *handler = (ClassDevHandler *) userdata2;
+	const gchar *prober;
+
+	if (hal_device_property_get_bool (d, "info.ignore")) {
+		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
+		 * Also remove category and all capabilities
+		 */
+		hal_device_property_remove (d, "info.category");
+		hal_device_property_remove (d, "info.capabilities");
+		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
+		hal_device_property_set_string (d, "info.product", "Ignored Device");
+
+		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
+		
+		/* 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);
+		goto out;
+	}
+	
+	if (handler->get_prober != NULL)
+		prober = handler->get_prober (d);
+	else
+		prober = NULL;
+	if (prober != NULL) {
+		/* probe the device */
+		hald_runner_run(d, 
+		                    prober, NULL, 
+		                    HAL_HELPER_TIMEOUT, 
+		                    add_classdev_probing_helper_done,
+		                    (gpointer) end_token, (gpointer) handler);
+	} else {
+		add_classdev_after_probing (d, handler, end_token);
+	}
+out:
+  ;
+}
+
+void
+hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, 
+				  HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token)
+{
+	guint i;
+
+	HAL_INFO (("class_add: subsys=%s sysfs_path=%s dev=%s physdev=0x%08x", subsystem, sysfs_path, device_file, physdev));
+
+	/* update driver property of the physical device, cause manual driver bind/unbind
+	 * may change change this without sending events for the bus device
+	 */
+	if (physdev != NULL)
+		hal_util_set_driver (physdev, "info.linux.driver", sysfs_path_in_devices);
+
+	if (physdev != NULL && hal_device_property_get_bool (physdev, "info.ignore")) {
+		HAL_INFO (("Ignoring class_add since physdev has info.ignore==TRUE"));
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	for (i = 0; classdev_handlers [i] != NULL; i++) {
+		ClassDevHandler *handler;
+
+		handler = classdev_handlers[i];
+		if (strcmp (handler->subsystem, subsystem) == 0) {
+			HalDevice *d;
+
+			/* attempt to add the device */
+			d = handler->add (sysfs_path, device_file, physdev, sysfs_path_in_devices);
+			if (d == NULL) {
+				/* didn't find anything - thus, ignore this hotplug event */
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_CLASS);
+			hal_device_property_set_string (d, "linux.subsystem", subsystem);
+			
+			if (device_file != NULL && strlen (device_file) > 0)
+				hal_device_property_set_string (d, "linux.device_file", device_file);
+
+			/* Add to temporary device store */
+			hal_device_store_add (hald_get_tdl (), d);
+
+			/* Process preprobe fdi files */
+			di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+			/* Run preprobe callouts */
+			hal_util_callout_device_preprobe (d, classdev_callouts_preprobing_done, end_token, handler);
+			goto out;
+		}
+	}
+
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out:
+	;
+}
+
+void
+hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token)
+{
+	guint i;
+	HalDevice *d;
+
+
+	HAL_INFO (("class_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
+	if (d == NULL) {
+		HAL_WARNING (("Error removing device"));
+	} else {
+
+		for (i = 0; classdev_handlers [i] != NULL; i++) {
+			ClassDevHandler *handler;
+			
+			handler = classdev_handlers[i];
+			if (strcmp (handler->subsystem, subsystem) == 0) {
+				handler->remove (d);
+
+				hal_util_callout_device_remove (d, classdev_callouts_remove_done, end_token, NULL);
+				goto out;
+			}
+		}
+	}
+
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out:
+	;
+}
+
+gboolean
+classdev_rescan_device (HalDevice *d)
+{
+	return FALSE;
+}
+
+
+HotplugEvent *
+classdev_generate_add_hotplug_event (HalDevice *d)
+{
+	const char *subsystem;
+	const char *sysfs_path;
+	const char *device_file;
+	HotplugEvent *hotplug_event;
+
+	subsystem = hal_device_property_get_string (d, "linux.subsystem");
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+	device_file = hal_device_property_get_string (d, "linux.device_file");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	if (device_file != NULL)
+		g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
+	else
+		hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
+
+HotplugEvent *
+classdev_generate_remove_hotplug_event (HalDevice *d)
+{
+	const char *subsystem;
+	const char *sysfs_path;
+	HotplugEvent *hotplug_event;
+
+	subsystem = hal_device_property_get_string (d, "linux.subsystem");
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
diff --git a/hald/linux/classdev.h b/hald/linux/classdev.h
new file mode 100644
index 0000000..c88dc9b
--- /dev/null
+++ b/hald/linux/classdev.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * classdev.h : Handling of functional kernel devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef CLASSDEV_H
+#define CLASSDEV_H
+
+#include <glib.h>
+#include "hotplug.h"
+
+typedef enum {
+	OSS_DEVICE_TYPE_DSP,
+	OSS_DEVICE_TYPE_ADSP,
+	OSS_DEVICE_TYPE_MIDI,
+	OSS_DEVICE_TYPE_AMIDI,
+	OSS_DEVICE_TYPE_AUDIO,
+	OSS_DEVICE_TYPE_MIXER,
+	OSS_DEVICE_TYPE_UNKNOWN
+} ClassDevOSSDeviceTypes;
+
+void hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token);
+
+void hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
+
+gboolean classdev_rescan_device (HalDevice *d);
+
+HotplugEvent *classdev_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *classdev_generate_remove_hotplug_event (HalDevice *d);
+
+#endif /* CLASSDEV_H */
diff --git a/hald/linux/coldplug.c b/hald/linux/coldplug.c
new file mode 100644
index 0000000..e47a90f
--- /dev/null
+++ b/hald/linux/coldplug.c
@@ -0,0 +1,682 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * coldplug.c : Synthesize hotplug events when starting up
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../hald.h"
+#include "../logger.h"
+#include "../osspec.h"
+#include "../util.h"
+
+#include "osspec_linux.h"
+#include "hotplug.h"
+
+#include "coldplug.h"
+
+#define DMPREFIX "dm-"
+
+/* For debugging */
+#define HAL_COLDPLUG_VERBOSE
+
+static GHashTable *sysfs_to_udev_map;
+static char dev_root[HAL_PATH_MAX];
+
+/* Returns the path of the udevinfo program 
+ *
+ * @return                      Path or NULL if udevinfo program is not found
+ */
+static const gchar *
+hal_util_get_udevinfo_path (void)
+{
+	guint i;
+	struct stat s;
+	static gchar *path = NULL;
+	gchar *possible_paths[] = {
+		"/usr/bin/udevinfo",
+		"/bin/udevinfo",
+		"/usr/sbin/udevinfo",
+		"/sbin/udevinfo",
+	};
+
+	if (path != NULL)
+		 return path;
+
+	for (i = 0; i < sizeof (possible_paths) / sizeof (char *); i++) {
+		if (stat (possible_paths[i], &s) == 0 && S_ISREG (s.st_mode)) {
+			path = possible_paths[i];
+			break;
+		}
+	}
+	return path;
+}
+
+static gboolean
+hal_util_init_sysfs_to_udev_map (void)
+{
+	char *udevdb_export_argv[] = { "/usr/bin/udevinfo", "-e", NULL };
+	char *udevroot_argv[] = { "/usr/bin/udevinfo", "-r", NULL };
+	char *udevinfo_stdout;
+	int udevinfo_exitcode;
+	HotplugEvent *hotplug_event = NULL;
+	char *p;
+
+	sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	udevdb_export_argv[0] = (char *) hal_util_get_udevinfo_path ();
+	udevroot_argv[0] = (char *) hal_util_get_udevinfo_path ();
+
+	/* get udevroot */
+	if (g_spawn_sync ("/", udevroot_argv, NULL, 0, NULL, NULL,
+			  &udevinfo_stdout,
+			  NULL,
+			  &udevinfo_exitcode,
+			  NULL) != TRUE) {
+		HAL_ERROR (("Couldn't invoke %s", udevroot_argv[0]));
+		goto error;
+	}
+	if (udevinfo_exitcode != 0) {
+		HAL_ERROR (("%s returned %d", udevroot_argv[0], udevinfo_exitcode));
+		goto error;
+	}
+
+	g_strlcpy(dev_root, udevinfo_stdout, sizeof(dev_root));
+	p = strchr(dev_root, '\n');
+	if (p != NULL)
+		p[0] = '\0';
+	g_free(udevinfo_stdout);
+	HAL_INFO (("dev_root is %s", dev_root));
+
+	/* get udevdb export */
+	if (g_spawn_sync ("/", udevdb_export_argv, NULL, 0, NULL, NULL,
+			  &udevinfo_stdout,
+			  NULL,
+			  &udevinfo_exitcode,
+			  NULL) != TRUE) {
+		HAL_ERROR (("Couldn't invoke %s", udevdb_export_argv[0]));
+		g_free(udevinfo_stdout);
+		goto error;
+	}
+
+	if (udevinfo_exitcode != 0) {
+		HAL_ERROR (("%s returned %d", udevdb_export_argv[0], udevinfo_exitcode));
+		goto error;
+	}
+
+	/* read the export of the udev database */
+	p = udevinfo_stdout;
+	while (p[0] != '\0') {
+		char *line, *end;
+		gchar *str;
+
+		/* get line, terminate and move to next line */
+		line = p;
+		end = strchr(line, '\n');
+		if (end == NULL)
+			break;
+		end[0] = '\0';
+		p = &end[1];
+
+		/* insert device */
+		if (line[0] == '\0') {
+			if (hotplug_event != NULL) {
+				g_hash_table_insert (sysfs_to_udev_map, g_strdup (hotplug_event->sysfs.sysfs_path), hotplug_event);
+#ifdef HAL_COLDPLUG_VERBOSE
+				printf ("Got '%s' -> '%s'\n", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file);
+#endif
+				hotplug_event = NULL;
+			}
+			continue;
+		}
+
+		/* new device */
+		if (strncmp(line, "P: ", 3) == 0) {
+			hotplug_event = g_new0 (HotplugEvent, 1);
+			g_strlcpy (hotplug_event->sysfs.sysfs_path, get_hal_sysfs_path (), sizeof(hotplug_event->sysfs.sysfs_path));
+			g_strlcat (hotplug_event->sysfs.sysfs_path, &line[3], sizeof(hotplug_event->sysfs.sysfs_path));
+			continue;
+		}
+
+		/* only valid if we have an actual device */
+		if (hotplug_event == NULL)
+			continue;
+
+		if (strncmp(line, "N: ", 3) == 0) {
+			g_snprintf (hotplug_event->sysfs.device_file, sizeof(hotplug_event->sysfs.device_file),
+				    "%s/%s", dev_root, &line[3]);
+		} else if (strncmp(line, "E: ID_VENDOR=", 13) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[13]);
+			g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_MODEL=", 12) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[12]);
+			g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_REVISION=", 15) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[15]);
+			g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_SERIAL=", 13) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[13]);
+			g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_FS_USAGE=", 15) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[15]);
+			g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_FS_TYPE=", 14) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[14]);
+			g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_FS_VERSION=", 17) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[17]);
+			g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_FS_UUID=", 14) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[14]);
+			g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
+			g_free (str);
+		} else if (strncmp(line, "E: ID_FS_LABEL=", 15) == 0) {
+			str = hal_util_strdup_valid_utf8(&line[15]);
+			g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
+			g_free (str);
+		}
+	}
+
+	g_free(udevinfo_stdout);
+	return TRUE;
+
+error:
+	g_free(udevinfo_stdout);
+	g_hash_table_destroy (sysfs_to_udev_map);
+	return FALSE;
+}
+
+static HotplugEvent
+*coldplug_get_hotplug_event(const gchar *sysfs_path, const gchar *subsystem)
+{
+	HotplugEvent *hotplug_event, *hotplug_event_udev;
+	const char *pos;
+	gchar path[HAL_PATH_MAX];
+	struct stat statbuf;
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	if (hotplug_event == NULL)
+		return NULL;
+
+	/* lookup if udev has something stored in its database */
+	hotplug_event_udev = (HotplugEvent *) g_hash_table_lookup (sysfs_to_udev_map, sysfs_path);
+	if (hotplug_event_udev != NULL) {
+		memcpy(hotplug_event, hotplug_event_udev, sizeof(HotplugEvent));
+		HAL_INFO (("found in udevdb '%s' '%s'", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file));
+	} else {
+		/* device is not in udev database */
+		g_strlcpy(hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof(hotplug_event->sysfs.sysfs_path));
+
+		/* look if a device node is expected */
+		g_strlcpy(path, sysfs_path, sizeof(path));
+		g_strlcat(path, "/dev", sizeof(path));
+		if (stat (path, &statbuf) != 0)
+			goto no_node;
+
+		/* look if the node exists */
+		pos = strrchr(sysfs_path, '/');
+		if (pos == NULL)
+			goto no_node;
+		g_strlcpy(path, dev_root, sizeof(path));
+		g_strlcat(path, pos, sizeof(path));
+		if (stat (path, &statbuf) != 0)
+			goto no_node;
+		if (!S_ISBLK (statbuf.st_mode) && !S_ISCHR (statbuf.st_mode))
+			goto no_node;
+
+		HAL_INFO (("found device_file %s for sysfs_path %s", path, sysfs_path));
+		g_strlcpy(hotplug_event->sysfs.device_file, path, sizeof(hotplug_event->sysfs.device_file));
+	}
+
+no_node:
+	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	hotplug_event->sysfs.net_ifindex = -1;
+	return hotplug_event;
+}
+
+static gboolean
+coldplug_synthesize_block_event(const gchar *f);
+
+static void
+coldplug_compute_visit_device (const gchar *path, 
+			       GHashTable *sysfs_to_bus_map, 
+			       GHashTable *sysfs_to_class_in_devices_map);
+
+static void
+free_hash_sys_to_class_in_dev (gpointer key, gpointer value, gpointer user_data)
+{
+	GSList *i;
+	GSList *list = (GSList *) value;
+
+	for (i = list; i != NULL; i = g_slist_next (i))
+		g_free (i->data);
+	g_slist_free (list);
+}
+
+/** This function serves one major purpose : build an ordered list of
+ *  pairs (sysfs path, subsystem) to process when starting up:
+ *  coldplugging. The ordering is arranged such that all bus-devices
+ *  are visited in the same order as performing a traversal through
+ *  the tree; e.g. bus-device A is not processed before bus-device B
+ *  if B is a parent of A connection-wise.
+ *
+ *  After all bus-devices are added to the list, then all block devices are
+ *  processed in the order they appear.
+ *
+ *  Finally, all class devices are added to the list.
+ *
+ *  @return                     Ordered list of sysfs paths or NULL 
+ *                              if there was an error
+ */
+gboolean
+coldplug_synthesize_events (void)
+{
+	GDir *dir;
+	GError *err = NULL;
+	gchar path[HAL_PATH_MAX];
+	gchar path1[HAL_PATH_MAX];
+	gchar path2[HAL_PATH_MAX];
+	const gchar *f;
+	const gchar *f1;
+	const gchar *f2;
+	GSList *li;
+
+	/** Mapping from sysfs path to subsystem for bus devices. This is consulted
+	 *  when traversing /sys/devices
+	 *
+	 *  Example:
+	 *
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0/host7/7:0:0:0  -> scsi
+	 * /sys/devices/pci0000:00/0000:00:07.1/ide1/1.1                        -> ide
+	 * /sys/devices/pci0000:00/0000:00:07.1/ide1/1.0                        -> ide
+	 * /sys/devices/pci0000:00/0000:00:07.1/ide0/0.0                        -> ide
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0                -> usb
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1                        -> usb
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-0:1.0                    -> usb
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1                            -> usb
+	 * /sys/devices/pci0000:00/0000:00:04.1/0000:06:00.0                    -> pci
+	 * /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0                    -> pci
+	 * /sys/devices/pci0000:00/0000:00:08.0                                 -> pci
+	 * /sys/devices/platform/vesafb0                                        -> platform
+	 */
+	GHashTable *sysfs_to_bus_map = NULL;
+
+        /** Mapping from sysfs path in /sys/devices to the pairs (sysfs class path, classname)
+	 *  for class devices; note that more than one class device might map to a physical device
+	 *
+	 * Example:
+	 *
+	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0/host7  -> (/sys/class/scsi_host/host7, scsi_host)
+	 * /sys/devices/platform/i8042/serio0/serio2 -> (/sys/class/input/event2, input, /sys/class/input/mouse1, input)
+	 */
+	GHashTable *sysfs_to_class_in_devices_map = NULL;
+
+	/* Class devices without device links; string list; example
+	 *
+	 * (/sys/class/input/mice, mouse, /sys/class/mem/null, mem, ...)
+	 */
+	GSList *sysfs_other_class_dev = NULL;
+
+	/* Device mapper devices that should be added after all other block devices
+	 *
+	 * Example:
+	 *
+	 * (/sys/block/dm-0)
+	 */
+	GSList *sysfs_dm_dev = NULL;
+
+	if (hal_util_init_sysfs_to_udev_map () == FALSE) {
+		HAL_ERROR (("Unable to get sysfs to dev map"));
+		goto error;
+	}
+
+	/* build bus map */
+	sysfs_to_bus_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+	g_snprintf (path, HAL_PATH_MAX, "%s/bus", get_hal_sysfs_path ());
+	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+		HAL_ERROR (("Unable to open %/bus: %s", get_hal_sysfs_path (), err->message));
+		g_error_free (err);
+		goto error;
+	}
+	while ((f = g_dir_read_name (dir)) != NULL) {
+		GDir *dir1;
+
+		g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s", get_hal_sysfs_path (), f);
+		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
+			HAL_ERROR (("Unable to open %/bus/%s: %s", get_hal_sysfs_path (), f, err->message));
+			g_error_free (err);
+			goto error;
+		}
+		while ((f1 = g_dir_read_name (dir1)) != NULL) {
+
+			if (strcmp (f1, "devices") == 0) {
+				GDir *dir2;
+
+				g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s", 
+					    get_hal_sysfs_path (), f, f1);
+				if ((dir2 = g_dir_open (path, 0, &err)) == NULL) {
+					HAL_ERROR (("Unable to open %s/bus/%s/%s: %s", 
+						    get_hal_sysfs_path (), f, f1, err->message));
+					g_error_free (err);
+					goto error;
+				}
+				while ((f2 = g_dir_read_name (dir2)) != NULL) {
+					gchar *target;
+					gchar *normalized_target;
+					g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s/%s", 
+						    get_hal_sysfs_path (), f, f1, f2);
+					if ((target = g_file_read_link (path, &err)) == NULL) {
+						HAL_ERROR (("%s/bus/%s/%s/%s is not a symlink: %s!", 
+							    get_hal_sysfs_path (), 
+							    f, f1, f2, err->message));
+						g_error_free (err);
+						goto error;
+					}
+
+					g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s", get_hal_sysfs_path (), f, f1);
+					normalized_target = hal_util_get_normalized_path (path, target);
+					g_free (target);
+
+					g_hash_table_insert (sysfs_to_bus_map, normalized_target, g_strdup(f));
+
+				}
+				g_dir_close (dir2);
+			}
+		}
+		g_dir_close (dir1);
+	}
+	g_dir_close (dir);
+
+	/* build class map and class device map (values are free in separate foreach()) */
+	sysfs_to_class_in_devices_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+	g_snprintf (path, HAL_PATH_MAX, "%s/class" , get_hal_sysfs_path ());
+	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+		HAL_ERROR (("Unable to open %/class: %s", get_hal_sysfs_path (), err->message));
+		goto error;
+	}
+	while ((f = g_dir_read_name (dir)) != NULL) {
+		GDir *dir1;
+
+		g_snprintf (path, HAL_PATH_MAX, "%s/class/%s" , get_hal_sysfs_path (), f);
+		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
+			HAL_ERROR (("Unable to open %s/class/%s: %s", get_hal_sysfs_path (), f, err->message));
+			g_error_free (err);
+			goto error;
+		}
+		while ((f1 = g_dir_read_name (dir1)) != NULL) {
+			gchar *target;
+			gchar *normalized_target;
+
+			g_snprintf (path2, HAL_PATH_MAX, "%s/class/%s/%s", get_hal_sysfs_path (), f, f1);
+
+			/* check if we find a symlink here pointing to a device _inside_ a class device,
+			 * like "input" in 2.6.15. This kernel sysfs layout will change again in the future,
+			 * for now resolve the link to the "real" device path, like real hotplug events
+			 * devpath would have
+			 */
+			if ((target = g_file_read_link (path2, NULL)) != NULL) {
+				char *pos = strrchr(path2, '/');
+
+				if (pos)
+					pos[0] = '\0';
+				normalized_target = hal_util_get_normalized_path (path2, target);
+				g_free (target);
+				g_strlcpy(path2, normalized_target, sizeof(path2));
+				g_free (normalized_target);
+			}
+
+			/* Accept net devices without device links too, they may be coldplugged PCMCIA devices */
+			g_snprintf (path1, HAL_PATH_MAX, "%s/device", path2);
+			if (((target = g_file_read_link (path1, NULL)) == NULL)) {
+				/* no device link */
+				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (path2));
+				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (f));
+			} else {
+				GSList *classdev_strings;
+
+				normalized_target = hal_util_get_normalized_path (path2, target);
+				g_free (target);
+
+				classdev_strings = g_hash_table_lookup (sysfs_to_class_in_devices_map,
+									normalized_target);
+
+				classdev_strings = g_slist_append (classdev_strings, g_strdup (path2));
+				classdev_strings = g_slist_append (classdev_strings, g_strdup (f));
+				g_hash_table_replace (sysfs_to_class_in_devices_map,
+						      normalized_target, classdev_strings);
+			}				
+		}
+		g_dir_close (dir1);
+	}
+	g_dir_close (dir);
+
+	/* Now traverse /sys/devices and consult the map we've just
+	 * built; this includes adding a) bus devices; and b) class
+	 * devices that sit in /sys/devices */
+	g_snprintf (path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
+	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+		HAL_ERROR (("Unable to open %/devices: %s", get_hal_sysfs_path (), err->message));
+		g_error_free (err);
+		goto error;
+	}
+	while ((f = g_dir_read_name (dir)) != NULL) {
+		GDir *dir1;
+
+		g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s", get_hal_sysfs_path (), f);
+		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
+			HAL_ERROR (("Unable to open %/devices/%s: %s", get_hal_sysfs_path (), f, err->message));
+			g_error_free (err);
+			goto error;
+		}
+		while ((f1 = g_dir_read_name (dir1)) != NULL) {
+
+			g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s/%s", get_hal_sysfs_path (), f, f1);
+			coldplug_compute_visit_device (path, sysfs_to_bus_map, sysfs_to_class_in_devices_map);
+		}
+		g_dir_close (dir1);
+	}
+	g_dir_close (dir);
+
+	g_hash_table_destroy (sysfs_to_bus_map);
+	/* free keys and values in this complex hash */
+	g_hash_table_foreach (sysfs_to_class_in_devices_map, free_hash_sys_to_class_in_dev, NULL);
+	g_hash_table_destroy (sysfs_to_class_in_devices_map);
+
+	/* we are guaranteed, per construction, that the len of this list is even */
+	for (li = sysfs_other_class_dev; li != NULL; li = g_slist_next (g_slist_next (li))) {
+		gchar *sysfs_path;
+		gchar *subsystem;
+		HotplugEvent *hotplug_event;
+
+		sysfs_path = (gchar *) li->data;
+		subsystem = (gchar *) li->next->data;
+
+#ifdef HAL_COLDPLUG_VERBOSE
+		printf ("class: %s (%s) (no device link)\n", sysfs_path, subsystem);
+#endif
+		hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
+		hotplug_event_enqueue (hotplug_event);
+
+		g_free (li->data);
+		g_free (li->next->data);
+	}
+	g_slist_free (sysfs_other_class_dev);
+
+	/* add block devices */
+	g_snprintf (path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
+	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+		HAL_ERROR (("Unable to open %s: %s", path, err->message));
+		g_error_free (err);
+		goto error;
+	}
+	while ((f = g_dir_read_name (dir)) != NULL) {
+		if (g_str_has_prefix (f, DMPREFIX)) {
+			/* defer dm devices */
+			sysfs_dm_dev = g_slist_append(sysfs_dm_dev, g_strdup(f));
+			continue;
+		}
+		if (coldplug_synthesize_block_event(f) == FALSE)
+			goto error;
+	}
+	/* process all dm devices last so that their backing devices exist */
+	for (li = sysfs_dm_dev; li != NULL; li = g_slist_next (g_slist_next (li))) {
+		if (coldplug_synthesize_block_event (li->data) == FALSE)
+			goto error;
+		g_free (li->data);
+	}
+	g_slist_free (sysfs_dm_dev);
+	g_dir_close (dir);
+
+	g_hash_table_destroy (sysfs_to_udev_map);
+
+	return TRUE;
+error:
+	HAL_ERROR (("Error building the ordered list of sysfs paths"));
+	return FALSE;
+}
+
+static gboolean
+coldplug_synthesize_block_event(const gchar *f)
+{
+	GDir *dir1;
+	HotplugEvent *hotplug_event;
+	GError *err = NULL;
+	gchar path[HAL_PATH_MAX];
+	gchar path1[HAL_PATH_MAX];
+	const gchar *f1;
+
+	g_snprintf (path, HAL_PATH_MAX, "%s/block/%s", get_hal_sysfs_path (), f);
+#ifdef HAL_COLDPLUG_VERBOSE
+	printf ("block: %s (block)\n",  path);
+#endif
+	hotplug_event = coldplug_get_hotplug_event (path, "block");
+	hotplug_event_enqueue (hotplug_event);
+
+	if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
+		HAL_ERROR (("Unable to open %s: %s", path, err->message));
+		g_error_free (err);
+		goto error;
+	}
+	while ((f1 = g_dir_read_name (dir1)) != NULL) {
+		if (strncmp (f, f1, strlen (f)) == 0) {
+			g_snprintf (path1, HAL_PATH_MAX, "%s/%s", path, f1);
+#ifdef HAL_COLDPLUG_VERBOSE
+			printf ("block: %s (block)\n", path1);
+#endif
+			hotplug_event = coldplug_get_hotplug_event (path1, "block");
+			hotplug_event_enqueue (hotplug_event);
+		}
+	}
+	g_dir_close (dir1);
+       
+	return TRUE;
+error:
+	return FALSE;
+}
+
+static void
+coldplug_compute_visit_device (const gchar *path,
+			       GHashTable *sysfs_to_bus_map, 
+			       GHashTable *sysfs_to_class_in_devices_map)
+{
+	gchar *bus;
+	GError *err = NULL;
+	GDir *dir;
+	const gchar *f;
+	/*HStringPair *pair;*/
+	GSList *class_devs;
+	GSList *i;
+
+	bus = g_hash_table_lookup (sysfs_to_bus_map, path);
+	if (bus != NULL) {
+		HotplugEvent *hotplug_event;
+#ifdef HAL_COLDPLUG_VERBOSE
+		printf ("bus:   %s (%s)\n", path, bus);
+#endif
+		hotplug_event = coldplug_get_hotplug_event (path, bus);
+		hotplug_event_enqueue (hotplug_event);
+	}
+
+	/* we are guaranteed, per construction, that the len of this list is even */
+	class_devs = g_hash_table_lookup (sysfs_to_class_in_devices_map, path);
+	for (i = class_devs; i != NULL; i = g_slist_next (g_slist_next (i))) {
+		gchar *sysfs_path;
+		gchar *subsystem;
+		HotplugEvent *hotplug_event;
+
+		sysfs_path = (gchar *) i->data;
+		subsystem = (gchar *) i->next->data;
+#ifdef HAL_COLDPLUG_VERBOSE
+		printf ("class: %s (%s) (%s)\n", path, subsystem, sysfs_path);
+#endif
+		hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
+		hotplug_event_enqueue (hotplug_event);
+	}
+
+	/* visit children; dont follow symlinks though.. */
+	err = NULL;
+	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+		/*HAL_ERROR (("Unable to open directory: %s", path, err->message));*/
+		g_error_free (err);
+		goto error;
+	}
+	while ((f = g_dir_read_name (dir)) != NULL) {
+		gchar path_child[HAL_PATH_MAX];
+		struct stat statbuf;
+
+		g_snprintf (path_child, HAL_PATH_MAX, "%s/%s", path, f);
+		if (lstat (path_child, &statbuf) == 0) {
+			if (!S_ISLNK (statbuf.st_mode)) {
+				/* recursion fun */
+				coldplug_compute_visit_device (path_child, 
+							       sysfs_to_bus_map, 
+							       sysfs_to_class_in_devices_map);
+			}
+		}
+	}
+	g_dir_close (dir);
+
+error:
+	return;
+}
+
diff --git a/hald/linux/coldplug.h b/hald/linux/coldplug.h
new file mode 100644
index 0000000..7da868a
--- /dev/null
+++ b/hald/linux/coldplug.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * coldplug.h : Synthesize hotplug events when starting up
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef COLDPLUG_H
+#define COLDPLUG_H
+
+#include <glib.h>
+
+gboolean coldplug_synthesize_events (void);
+
+#endif /* COLDPLUG_H */
+
diff --git a/hald/linux/hotplug.c b/hald/linux/hotplug.c
new file mode 100644
index 0000000..4eac8b9
--- /dev/null
+++ b/hald/linux/hotplug.c
@@ -0,0 +1,618 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hotplug.c : Handling of hotplug events
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../hald.h"
+#include "../logger.h"
+#include "../osspec.h"
+
+#include "acpi.h"
+#include "apm.h"
+#include "blockdev.h"
+#include "classdev.h"
+#include "osspec_linux.h"
+#include "physdev.h"
+#include "pmu.h"
+
+#include "hotplug.h"
+
+/** Queue of ordered hotplug events */
+GQueue *hotplug_event_queue;
+
+/** List of HotplugEvent objects we are currently processing */
+GSList *hotplug_events_in_progress = NULL;
+
+void
+hotplug_event_end (void *end_token)
+{
+	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
+
+	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
+	g_free (hotplug_event);
+	hotplug_event_process_queue ();
+}
+
+void 
+hotplug_event_reposted (void *end_token)
+{
+	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
+
+	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
+	hotplug_event_process_queue ();
+}
+
+static void
+fixup_net_device_for_renaming (HotplugEvent *hotplug_event)
+{
+	/* fixup net devices by looking at ifindex */
+	if (strcmp (hotplug_event->sysfs.subsystem, "net") == 0 && hotplug_event->sysfs.net_ifindex != -1) {
+		int ifindex;
+		
+		if (!hal_util_get_int_from_file (hotplug_event->sysfs.sysfs_path, "ifindex", &ifindex, 10) ||
+		    (ifindex != hotplug_event->sysfs.net_ifindex)) {
+			GDir *dir;
+			char path[HAL_PATH_MAX];
+			char path1[HAL_PATH_MAX];
+			GError *err = NULL;
+			const gchar *f;
+			
+			/* search for new name */
+			HAL_WARNING (("Net interface @ %s with ifindex %d was probably renamed",
+				      hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.net_ifindex));
+			
+			g_snprintf (path, HAL_PATH_MAX, "%s/class/net" , get_hal_sysfs_path());
+			if ((dir = g_dir_open (path, 0, &err)) == NULL) {
+				HAL_ERROR (("Unable to open %s/class/net: %s", get_hal_sysfs_path(), err->message));
+				g_error_free (err);
+				goto out;
+			}
+			while ((f = g_dir_read_name (dir)) != NULL) {
+				g_snprintf (path1, HAL_PATH_MAX, "%s/class/net/%s" , get_hal_sysfs_path (), f);
+				if (hal_util_get_int_from_file (path1, "ifindex", &ifindex, 10)) {
+					if (ifindex == hotplug_event->sysfs.net_ifindex) {
+						HAL_INFO (("Using sysfs path %s for ifindex %d", path1, ifindex));
+						strncpy (hotplug_event->sysfs.sysfs_path, path1, HAL_PATH_MAX);
+						g_dir_close (dir);
+						goto out;
+					}
+				}
+				
+			}
+			g_dir_close (dir);
+		}
+	}
+out:
+	return;
+}
+
+
+static void
+hotplug_event_begin_sysfs (HotplugEvent *hotplug_event)
+{
+	HalDevice *d;
+	char subsystem[HAL_PATH_MAX];
+	gchar *subsystem_target;
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (),
+						     "linux.sysfs_path",
+						     hotplug_event->sysfs.sysfs_path);
+
+	/* FIXME: we should reprobe the device instead of skipping the event */
+	if (d != NULL && hotplug_event->action == HOTPLUG_ACTION_ADD) {
+		HAL_ERROR (("devpath %s already present in the store, ignore event", hotplug_event->sysfs.sysfs_path));
+		hotplug_event_end ((void *) hotplug_event);
+		return;
+	}
+
+	/* get device type from already known device object */
+	if (d != NULL) {
+		HotplugEventType type;
+
+		type = hal_device_property_get_int (d, "linux.hotplug_type");
+		if (type == HOTPLUG_EVENT_SYSFS_BUS) {
+			HAL_INFO (("%s is a bus device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+		} else if (type == HOTPLUG_EVENT_SYSFS_CLASS) {
+			HAL_INFO (("%s is a class device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+		} else if (type == HOTPLUG_EVENT_SYSFS_BLOCK) {
+			HAL_INFO (("%s is a block device (store)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+		}
+	}
+
+	/*
+	 * determine device type by "subsystem" link (from kernel 2.6.18, class devices
+	 * start to move from /class to /devices and have a "subsystem" link pointing
+	 * back to the "class" or "bus" directory
+	 */
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
+		g_snprintf (subsystem, HAL_PATH_MAX, "%s/subsystem", hotplug_event->sysfs.sysfs_path);
+		subsystem_target = g_file_read_link (subsystem, NULL);
+		if (subsystem_target != NULL) {
+			if (strstr(subsystem_target, "/bus/") != NULL) {
+				HAL_INFO (("%s is a bus device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+			} else if (strstr(subsystem_target, "/class/") != NULL) {
+				HAL_INFO (("%s is a class device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+			} else if (strstr(subsystem_target, "/block") != NULL) {
+				HAL_INFO (("%s is a block device (subsystem)", hotplug_event->sysfs.sysfs_path));
+				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+			}
+			g_free (subsystem_target);
+		}
+	}
+
+	/* older kernels get the device type from the devpath */
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
+		char sys_devices_path[HAL_PATH_MAX];
+		char sys_class_path[HAL_PATH_MAX];
+		char sys_block_path[HAL_PATH_MAX];
+		gsize sys_devices_path_len;
+		gsize sys_class_path_len;
+		gsize sys_block_path_len;
+
+		sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
+		sys_class_path_len   = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
+		sys_block_path_len   = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
+
+		if (strncmp (hotplug_event->sysfs.sysfs_path, sys_devices_path, sys_devices_path_len) == 0) {
+			HAL_INFO (("%s is a bus device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
+		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_class_path, sys_class_path_len) == 0) {
+			HAL_INFO (("%s is a class device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
+		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_block_path, sys_block_path_len) == 0) {
+			HAL_INFO (("%s is a block device (devpath)", hotplug_event->sysfs.sysfs_path));
+			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
+		}
+	}
+
+	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BUS) {
+		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+			HalDevice *parent;
+			parent = hal_util_find_closest_ancestor (hotplug_event->sysfs.sysfs_path);
+			hotplug_event_begin_add_physdev (hotplug_event->sysfs.subsystem, 
+							 hotplug_event->sysfs.sysfs_path, 
+							 parent,
+							 (void *) hotplug_event);
+		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+			hotplug_event_begin_remove_physdev (hotplug_event->sysfs.subsystem, 
+							    hotplug_event->sysfs.sysfs_path, 
+							    (void *) hotplug_event);
+		}
+	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_CLASS) {
+		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+			gchar *target;
+			HalDevice *physdev;
+			char physdevpath[HAL_PATH_MAX];
+			gchar *sysfs_path_in_devices;
+
+			sysfs_path_in_devices = NULL;
+
+			/* /sbin/ifrename may be called from a hotplug handler before we process this,
+			 * so if index doesn't match, go ahead and find a new sysfs path
+			 */
+			fixup_net_device_for_renaming (hotplug_event);
+
+			g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
+			if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
+				gchar *normalized_target;
+
+				normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs.sysfs_path, target);
+				g_free (target);
+
+				sysfs_path_in_devices = g_strdup (normalized_target);
+
+				/* there may be ''holes'' in /sys/devices so try hard to find the closest match */
+				do {
+					physdev = hal_device_store_match_key_value_string (hald_get_gdl (), 
+											   "linux.sysfs_path_device", 
+											   normalized_target);
+					if (physdev != NULL)
+						break;
+
+					/* go up one directory */
+					if (!hal_util_path_ascend (normalized_target))
+						break;
+				} while (physdev == NULL);
+				g_free (normalized_target);
+			} else {
+				physdev = NULL;
+			}
+
+			hotplug_event_begin_add_classdev (hotplug_event->sysfs.subsystem,
+							  hotplug_event->sysfs.sysfs_path,
+							  hotplug_event->sysfs.device_file,
+							  physdev,
+							  sysfs_path_in_devices,
+							  (void *) hotplug_event);
+
+			g_free (sysfs_path_in_devices);
+
+		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+			hotplug_event_begin_remove_classdev (hotplug_event->sysfs.subsystem,
+							     hotplug_event->sysfs.sysfs_path,
+							     (void *) hotplug_event);
+		}
+	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BLOCK) {
+		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+			HalDevice *parent = NULL;
+			int range;
+			gboolean is_partition;
+			gboolean is_fakevolume;
+			
+			/* it's a partition if and only if it doesn't have the range file...
+			 *
+			 * notably the device mapper partitions do have a range file, but that's
+			 * fine, we don't count them as partitions anyway...
+			 *
+			 * also, if the sysfs ends with "fakevolume" the hotplug event is synthesized
+			 * from within HAL for partitions on the main block device
+			 */
+			is_fakevolume = FALSE;
+			if (strcmp (hal_util_get_last_element (hotplug_event->sysfs.sysfs_path), "fakevolume") == 0) {
+				is_fakevolume = TRUE;
+			}
+			is_partition = TRUE;
+			if (is_fakevolume ||
+			    hal_util_get_int_from_file (hotplug_event->sysfs.sysfs_path, "range", &range, 0)) {
+				is_partition = FALSE;
+			}
+
+			if (is_partition || is_fakevolume) {
+				gchar *parent_path;
+
+				parent_path = hal_util_get_parent_path (hotplug_event->sysfs.sysfs_path);
+
+				parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+										  "linux.sysfs_path_device",
+										  parent_path);
+				g_free (parent_path);
+			} else {
+				gchar *target;
+				char physdevpath[HAL_PATH_MAX];
+
+				g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
+				if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
+					gchar *normalized_target;
+
+					normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs.sysfs_path, target);
+					g_free (target);
+					parent = hal_device_store_match_key_value_string (hald_get_gdl (),
+											  "linux.sysfs_path_device",
+											  normalized_target);
+					g_free (normalized_target);
+				}
+			}
+
+			hotplug_event_begin_add_blockdev (hotplug_event->sysfs.sysfs_path,
+							  hotplug_event->sysfs.device_file,
+							  is_partition,
+							  parent,
+							  (void *) hotplug_event);
+		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+			hotplug_event_begin_remove_blockdev (hotplug_event->sysfs.sysfs_path,
+							     (void *) hotplug_event);
+		}
+	} else {
+		/* just ignore this hotplug event */
+		hotplug_event_end ((void *) hotplug_event);
+	}
+}
+
+static void
+hotplug_event_begin_acpi (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+		hotplug_event_begin_add_acpi (hotplug_event->acpi.acpi_path, 
+					      hotplug_event->acpi.acpi_type,
+					      NULL,
+					      (void *) hotplug_event);
+	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+		hotplug_event_begin_remove_acpi (hotplug_event->acpi.acpi_path, 
+						 hotplug_event->acpi.acpi_type,
+						 (void *) hotplug_event);
+	}
+}
+
+static void
+hotplug_event_begin_apm (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+		hotplug_event_begin_add_apm (hotplug_event->apm.apm_path, 
+					     hotplug_event->apm.apm_type,
+					     NULL,
+					     (void *) hotplug_event);
+	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+		hotplug_event_begin_remove_apm (hotplug_event->apm.apm_path, 
+						hotplug_event->apm.apm_type,
+						(void *) hotplug_event);
+	}
+}
+
+static void
+hotplug_event_begin_pmu (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
+		hotplug_event_begin_add_pmu (hotplug_event->pmu.pmu_path, 
+					     hotplug_event->pmu.pmu_type,
+					     NULL,
+					     (void *) hotplug_event);
+	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
+		hotplug_event_begin_remove_pmu (hotplug_event->pmu.pmu_path, 
+						hotplug_event->pmu.pmu_type,
+						(void *) hotplug_event);
+	}
+}
+
+static void
+hotplug_event_begin (HotplugEvent *hotplug_event)
+{
+	switch (hotplug_event->type) {
+
+	/* explicit fallthrough */
+	case HOTPLUG_EVENT_SYSFS:
+	case HOTPLUG_EVENT_SYSFS_BUS:
+	case HOTPLUG_EVENT_SYSFS_CLASS:
+	case HOTPLUG_EVENT_SYSFS_BLOCK:
+		hotplug_event_begin_sysfs (hotplug_event);
+		break;
+
+	case HOTPLUG_EVENT_ACPI:
+		hotplug_event_begin_acpi (hotplug_event);
+		break;
+
+	case HOTPLUG_EVENT_APM:
+		hotplug_event_begin_apm (hotplug_event);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		hotplug_event_begin_pmu (hotplug_event);
+		break;
+
+	default:
+		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
+		hotplug_event_end ((void *) hotplug_event);
+		break;
+	}
+}
+
+void 
+hotplug_event_enqueue (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event_queue == NULL)
+		hotplug_event_queue = g_queue_new ();
+
+	g_queue_push_tail (hotplug_event_queue, hotplug_event);
+}
+
+void 
+hotplug_event_enqueue_at_front (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event_queue == NULL)
+		hotplug_event_queue = g_queue_new ();
+
+	g_queue_push_head (hotplug_event_queue, hotplug_event);
+}
+
+void 
+hotplug_event_process_queue (void)
+{
+	HotplugEvent *hotplug_event;
+
+	if (hotplug_events_in_progress == NULL && 
+	    (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
+		hotplug_queue_now_empty ();
+		goto out;
+	}
+
+	/* do not process events if some other event is in progress 
+	 *
+	 * TODO: optimize so we can do add events in parallel by inspecting the
+	 *       wait_for_sysfs_path parameter and hotplug_events_in_progress list
+	 */
+	if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
+		goto out;
+
+	hotplug_event = g_queue_pop_head (hotplug_event_queue);
+	if (hotplug_event == NULL)
+		goto out;
+
+	hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
+	hotplug_event_begin (hotplug_event);
+
+out:
+	;	
+}
+
+gboolean 
+hotplug_rescan_device (HalDevice *d)
+{
+	gboolean ret;
+
+	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
+	case HOTPLUG_EVENT_SYSFS_BUS:
+		ret = physdev_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_CLASS:
+		ret = classdev_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_BLOCK:
+		ret = blockdev_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_ACPI:
+		ret = acpi_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_APM:
+		ret = apm_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		ret = pmu_rescan_device (d);
+		break;
+
+	default:
+		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
+		ret = FALSE;
+		break;
+	}
+
+	return ret;
+}
+
+static void
+hotplug_reprobe_generate_remove_events (HalDevice *d)
+{
+	GSList *i;
+	GSList *childs;
+	HotplugEvent *e;
+
+	/* first remove childs */
+	childs = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.parent", d->udi);
+	for (i = childs; i != NULL; i = g_slist_next (i)) {
+		HalDevice *child;
+
+		child = HAL_DEVICE (i->data);
+		hotplug_reprobe_generate_remove_events (child);
+	}
+
+	/* then remove self */
+	HAL_INFO (("Generate remove event for udi %s", d->udi));
+	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
+	case HOTPLUG_EVENT_SYSFS_BUS:
+		e = physdev_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_CLASS:
+		e = classdev_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_BLOCK:
+		e = blockdev_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_ACPI:
+		e = acpi_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_APM:
+		e = apm_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		e = pmu_generate_remove_hotplug_event (d);
+		break;
+
+	default:
+		e = NULL;
+		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
+		break;
+	}
+
+	if (e != NULL) {
+		hotplug_event_enqueue (e);
+	}
+}
+
+static void
+hotplug_reprobe_generate_add_events (HalDevice *d)
+{
+	GSList *i;
+	GSList *childs;
+	HotplugEvent *e;
+
+	/* first add self */
+	HAL_INFO (("Generate add event for udi %s", d->udi));
+	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
+	case HOTPLUG_EVENT_SYSFS_BUS:
+		e = physdev_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_CLASS:
+		e = classdev_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_SYSFS_BLOCK:
+		e = blockdev_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_ACPI:
+		e = acpi_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_APM:
+		e = apm_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		e = pmu_generate_add_hotplug_event (d);
+		break;
+
+	default:
+		e = NULL;
+		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
+		break;
+	}
+
+	if (e != NULL) {
+		hotplug_event_enqueue (e);
+	}
+
+	/* then add childs */
+	childs = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.parent", d->udi);
+	for (i = childs; i != NULL; i = g_slist_next (i)) {
+		HalDevice *child;
+
+		child = HAL_DEVICE (i->data);
+		hotplug_reprobe_generate_add_events (child);
+	}
+}
+
+gboolean
+hotplug_reprobe_tree (HalDevice *d)
+{
+	hotplug_reprobe_generate_remove_events (d);
+	hotplug_reprobe_generate_add_events (d);
+	hotplug_event_process_queue ();
+	return FALSE;
+}
diff --git a/hald/linux/hotplug.h b/hald/linux/hotplug.h
new file mode 100644
index 0000000..d93d620
--- /dev/null
+++ b/hald/linux/hotplug.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * hotplug.h : Handling of hotplug events
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef HOTPLUG_H
+#define HOTPLUG_H
+
+#include <glib.h>
+
+#include "../device.h"
+#include "../util.h"
+
+typedef enum {
+	HOTPLUG_ACTION_ADD,
+	HOTPLUG_ACTION_REMOVE,
+	HOTPLUG_ACTION_ONLINE,
+	HOTPLUG_ACTION_OFFLINE,
+} HotplugActionType;
+
+typedef enum {
+	HOTPLUG_EVENT_SYSFS       = 0,
+	HOTPLUG_EVENT_SYSFS_BUS   = 1,
+	HOTPLUG_EVENT_SYSFS_CLASS = 2,
+	HOTPLUG_EVENT_SYSFS_BLOCK = 3,
+	HOTPLUG_EVENT_ACPI        = 4,
+	HOTPLUG_EVENT_APM         = 5,
+	HOTPLUG_EVENT_PMU         = 6
+} HotplugEventType;
+
+/** Data structure representing a hotplug event; also used for
+ *  coldplugging.
+ */
+typedef struct
+{
+	HotplugActionType action;				/* Whether the event is add or remove */
+	HotplugEventType type;					/* Type of event */
+
+	union {
+		struct {
+			char subsystem[HAL_NAME_MAX];		/* Kernel subsystem the device belongs to */
+			char sysfs_path[HAL_PATH_MAX];		/* Kernel device devpath */
+			char device_file[HAL_PATH_MAX];	/* Device node for the device */
+			unsigned long long seqnum;		/* kernel uevent sequence number */
+			int net_ifindex;			/* Kernel ifindex for network devices */
+
+			/* stuff udev may tell us about the device and we don't want to query */
+			char vendor[HAL_NAME_MAX];
+			char model[HAL_NAME_MAX];
+			char revision[HAL_NAME_MAX];
+			char serial[HAL_NAME_MAX];
+			char fsusage[HAL_NAME_MAX];
+			char fstype[HAL_NAME_MAX];
+			char fsversion[HAL_NAME_MAX];
+			char fslabel[HAL_NAME_MAX];
+			char fsuuid[HAL_NAME_MAX];
+		} sysfs;
+
+		struct {
+			int  acpi_type;				/* Type of ACPI object; see acpi.c */
+			char acpi_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/acpi/battery/BAT0/ */
+		} acpi;
+
+		struct {
+			int  apm_type;				/* Type of APM object; see apm.c */
+			char apm_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/apm */
+		} apm;
+
+		struct {
+			int  pmu_type;				/* Type of PMU object; see pmu.c */
+			char pmu_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/pmu/battery_0 */
+		} pmu;
+	};
+
+} HotplugEvent;
+
+void hotplug_event_enqueue (HotplugEvent *event);
+
+void hotplug_event_enqueue_at_front (HotplugEvent *hotplug_event);
+
+void hotplug_event_process_queue (void);
+
+void hotplug_event_end (void *end_token);
+
+void hotplug_event_reposted (void *end_token);
+
+gboolean hotplug_rescan_device (HalDevice *d);
+
+gboolean hotplug_reprobe_tree (HalDevice *d);
+
+void hotplug_queue_now_empty (void);
+
+#endif /* HOTPLUG_H */
diff --git a/hald/linux/hotplug_helper.h b/hald/linux/hotplug_helper.h
new file mode 100644
index 0000000..2767037
--- /dev/null
+++ b/hald/linux/hotplug_helper.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * HAL daemon hotplug.d and dev.d helper details
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef HALD_HELPER_H
+#define HALD_HELPER_H
+
+#define HALD_HELPER_MAGIC 0x68616c64
+#define HALD_HELPER_SOCKET_PATH "/var/run/hal/hotplug_socket2"
+#define HALD_HELPER_STRLEN 256
+
+struct hald_helper_msg
+{
+	unsigned int magic;			/**< magic */
+	unsigned long long seqnum;		/**< Sequence number (may be 0 if for dev if udev has no support) */
+	char action[HALD_HELPER_STRLEN];	/**< hotplug action */
+	char subsystem[HALD_HELPER_STRLEN];	/**< subsystem e.g. usb, pci (only for hotplug msg) */
+	char sysfs_path[HALD_HELPER_STRLEN];	/**< path into sysfs without sysfs mountpoint, e.g. /block/sda */
+	char device_name[HALD_HELPER_STRLEN];	/**< absolute path of device node (only for device msg) */
+	int net_ifindex;                        /**< For networking class devices only; the value of the ifindex file*/
+	time_t time_stamp;                      /**< Time of day we received the hotplug event */
+};
+
+#endif /* HALD_HELPER_H */
diff --git a/hald/linux/ids.c b/hald/linux/ids.c
new file mode 100644
index 0000000..7cb41f3
--- /dev/null
+++ b/hald/linux/ids.c
@@ -0,0 +1,973 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * classdev.c : Handling of functional kernel devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <ctype.h>
+#include <stdint.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../logger.h"
+
+#include "ids.h"
+
+/** Pointer to where the pci.ids file is loaded */
+static char *pci_ids = NULL;
+
+/** Length of data store at at pci_ids */
+static unsigned int pci_ids_len;
+
+/** Iterator position into pci_ids */
+static unsigned int pci_ids_iter_pos;
+
+/** Initialize the pci.ids line iterator to the beginning of the file */
+static void
+pci_ids_line_iter_init ()
+{
+	pci_ids_iter_pos = 0;
+}
+
+/** Maximum length of lines in pci.ids */
+#define PCI_IDS_MAX_LINE_LEN 512
+
+/** Get the next line from pci.ids
+ *
+ *  @param  line_len            Pointer to where number of bytes in line will
+ *                              be stored
+ *  @return                     Pointer to the line; only valid until the
+ *                              next invocation of this function
+ */
+static char *
+pci_ids_line_iter_get_line (unsigned int *line_len)
+{
+	unsigned int i;
+	static char line[PCI_IDS_MAX_LINE_LEN];
+
+	for (i = 0;
+	     pci_ids_iter_pos < pci_ids_len &&
+	     i < PCI_IDS_MAX_LINE_LEN - 1 &&
+	     pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
+		line[i] = pci_ids[pci_ids_iter_pos];
+	}
+
+	line[i] = '\0';
+	if (line_len != NULL)
+		*line_len = i;
+
+	pci_ids_iter_pos++;
+
+	return line;
+}
+
+/** See if there are more lines to process in pci.ids
+ *
+ *  @return                     #TRUE iff there are more lines to process
+ */
+static dbus_bool_t
+pci_ids_line_iter_has_more ()
+{
+	return pci_ids_iter_pos < pci_ids_len;
+}
+
+
+/** Find the names for a PCI device.
+ *
+ *  The pointers returned are only valid until the next invocation of this
+ *  function.
+ *
+ *  @param  vendor_id           PCI vendor id or 0 if unknown
+ *  @param  product_id          PCI product id or 0 if unknown
+ *  @param  subsys_vendor_id    PCI subsystem vendor id or 0 if unknown
+ *  @param  subsys_product_id   PCI subsystem product id or 0 if unknown
+ *  @param  vendor_name         Set to pointer of result or NULL
+ *  @param  product_name        Set to pointer of result or NULL
+ *  @param  subsys_vendor_name  Set to pointer of result or NULL
+ *  @param  subsys_product_name Set to pointer of result or NULL
+ */
+void
+ids_find_pci (int vendor_id, int product_id,
+	      int subsys_vendor_id, int subsys_product_id,
+	      char **vendor_name, char **product_name,
+	      char **subsys_vendor_name, char **subsys_product_name)
+{
+	char *line;
+	unsigned int i;
+	unsigned int line_len;
+	unsigned int num_tabs;
+	char rep_vi[8];
+	char rep_pi[8];
+	char rep_svi[8];
+	char rep_spi[8];
+	dbus_bool_t vendor_matched = FALSE;
+	dbus_bool_t product_matched = FALSE;
+	static char store_vn[PCI_IDS_MAX_LINE_LEN];
+	static char store_pn[PCI_IDS_MAX_LINE_LEN];
+	static char store_svn[PCI_IDS_MAX_LINE_LEN];
+	static char store_spn[PCI_IDS_MAX_LINE_LEN];
+
+	snprintf (rep_vi, 8, "%04x", vendor_id);
+	snprintf (rep_pi, 8, "%04x", product_id);
+	snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
+	snprintf (rep_spi, 8, "%04x", subsys_product_id);
+
+	*vendor_name = NULL;
+	*product_name = NULL;
+	*subsys_vendor_name = NULL;
+	*subsys_product_name = NULL;
+
+	for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
+		line = pci_ids_line_iter_get_line (&line_len);
+
+		/* skip lines with no content */
+		if (line_len < 4)
+			continue;
+
+		/* skip comments */
+		if (line[0] == '#')
+			continue;
+
+		/* count number of tabs */
+		num_tabs = 0;
+		for (i = 0; i < line_len; i++) {
+			if (line[i] != '\t')
+				break;
+			num_tabs++;
+		}
+
+		switch (num_tabs) {
+		case 0:
+			/* vendor names */
+			vendor_matched = FALSE;
+
+			/* first check subsys_vendor_id, if haven't done 
+			 * already */
+			if (*subsys_vendor_name == NULL
+			    && subsys_vendor_id != 0) {
+				if ((*((dbus_uint32_t *) line)) ==
+				    (*((dbus_uint32_t *) rep_svi))) {
+					/* found it */
+					for (i = 4; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_svn, line + i,
+						 PCI_IDS_MAX_LINE_LEN);
+					*subsys_vendor_name = store_svn;
+				}
+			}
+
+			/* check vendor_id */
+			if (vendor_id != 0) {
+				if (memcmp (line, rep_vi, 4) == 0) {
+					/* found it */
+					vendor_matched = TRUE;
+
+					for (i = 4; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_vn, line + i,
+						 PCI_IDS_MAX_LINE_LEN);
+					*vendor_name = store_vn;
+				}
+			}
+
+			break;
+
+		case 1:
+			product_matched = FALSE;
+
+			/* product names */
+			if (!vendor_matched)
+				continue;
+
+			/* check product_id */
+			if (product_id != 0) {
+				if (memcmp (line + 1, rep_pi, 4) == 0) {
+					/* found it */
+
+					product_matched = TRUE;
+
+					for (i = 5; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_pn, line + i,
+						 PCI_IDS_MAX_LINE_LEN);
+					*product_name = store_pn;
+				}
+			}
+			break;
+
+		case 2:
+			/* subsystem_vendor subsystem_product */
+			if (!vendor_matched || !product_matched)
+				continue;
+
+			/* check product_id */
+			if (subsys_vendor_id != 0
+			    && subsys_product_id != 0) {
+				if (memcmp (line + 2, rep_svi, 4) == 0
+				    && memcmp (line + 7, rep_spi,
+					       4) == 0) {
+					/* found it */
+					for (i = 11; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_spn, line + i,
+						 PCI_IDS_MAX_LINE_LEN);
+					*subsys_product_name = store_spn;
+				}
+			}
+
+			break;
+
+		default:
+			break;
+		}
+
+	}
+}
+
+/** Free resources used by to store the PCI database
+ *
+ *  @param                      #FALSE if the PCI database wasn't loaded
+ */
+static dbus_bool_t
+pci_ids_free ()
+{
+	if (pci_ids != NULL) {
+		free (pci_ids);
+		pci_ids = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/** Load the PCI database used for mapping vendor, product, subsys_vendor
+ *  and subsys_product numbers into names.
+ *
+ *  @param  path                Path of the pci.ids file, e.g. 
+ *                              /usr/share/hwdata/pci.ids
+ *  @return                     #TRUE if the file was succesfully loaded
+ */
+static dbus_bool_t
+pci_ids_load (const char *path)
+{
+	FILE *fp;
+	unsigned int num_read;
+
+	fp = fopen (path, "r");
+	if (fp == NULL) {
+		HAL_ERROR (("couldn't open PCI database at %s,", path));
+		return FALSE;
+	}
+
+	fseek (fp, 0, SEEK_END);
+	pci_ids_len = ftell (fp);
+	fseek (fp, 0, SEEK_SET);
+
+	pci_ids = malloc (pci_ids_len);
+	if (pci_ids == NULL) {
+		DIE (("Couldn't allocate %d bytes for PCI database file\n",
+		      pci_ids_len));
+	}
+
+	num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
+	if (pci_ids_len != num_read) {
+		HAL_ERROR (("Error loading PCI database file"));
+		pci_ids_free();
+		fclose(fp);
+		return FALSE;
+	}
+
+	fclose(fp);
+	return TRUE;
+}
+
+/*==========================================================================*/
+
+/** Pointer to where the usb.ids file is loaded */
+static char *usb_ids = NULL;
+
+/** Length of data store at at usb_ids */
+static unsigned int usb_ids_len;
+
+/** Iterator position into usb_ids */
+static unsigned int usb_ids_iter_pos;
+
+/** Initialize the usb.ids line iterator to the beginning of the file */
+static void
+usb_ids_line_iter_init ()
+{
+	usb_ids_iter_pos = 0;
+}
+
+/** Maximum length of lines in usb.ids */
+#define USB_IDS_MAX_LINE_LEN 512
+
+/** Get the next line from usb.ids
+ *
+ *  @param  line_len            Pointer to where number of bytes in line will
+ *                              be stored
+ *  @return                     Pointer to the line; only valid until the
+ *                              next invocation of this function
+ */
+static char *
+usb_ids_line_iter_get_line (unsigned int *line_len)
+{
+	unsigned int i;
+	static char line[USB_IDS_MAX_LINE_LEN];
+
+	for (i = 0;
+	     usb_ids_iter_pos < usb_ids_len &&
+	     i < USB_IDS_MAX_LINE_LEN - 1 &&
+	     usb_ids[usb_ids_iter_pos] != '\n'; i++, usb_ids_iter_pos++) {
+		line[i] = usb_ids[usb_ids_iter_pos];
+	}
+
+	line[i] = '\0';
+	if (line_len != NULL)
+		*line_len = i;
+
+	usb_ids_iter_pos++;
+
+	return line;
+}
+
+/** See if there are more lines to process in usb.ids
+ *
+ *  @return                     #TRUE iff there are more lines to process
+ */
+static dbus_bool_t
+usb_ids_line_iter_has_more ()
+{
+	return usb_ids_iter_pos < usb_ids_len;
+}
+
+/** Find the names for a USB device.
+ *
+ *  The pointers returned are only valid until the next invocation of this
+ *  function.
+ *
+ *  @param  vendor_id           USB vendor id or 0 if unknown
+ *  @param  product_id          USB product id or 0 if unknown
+ *  @param  vendor_name         Set to pointer of result or NULL
+ *  @param  product_name        Set to pointer of result or NULL
+ */
+void
+ids_find_usb (int vendor_id, int product_id,
+	      char **vendor_name, char **product_name)
+{
+	char *line;
+	unsigned int i;
+	unsigned int line_len;
+	unsigned int num_tabs;
+	char rep_vi[8];
+	char rep_pi[8];
+	static char store_vn[USB_IDS_MAX_LINE_LEN];
+	static char store_pn[USB_IDS_MAX_LINE_LEN];
+	dbus_bool_t vendor_matched = FALSE;
+
+	snprintf (rep_vi, 8, "%04x", vendor_id);
+	snprintf (rep_pi, 8, "%04x", product_id);
+
+	*vendor_name = NULL;
+	*product_name = NULL;
+
+	for (usb_ids_line_iter_init (); usb_ids_line_iter_has_more ();) {
+		line = usb_ids_line_iter_get_line (&line_len);
+
+		/* skip lines with no content */
+		if (line_len < 4)
+			continue;
+
+		/* skip comments */
+		if (line[0] == '#')
+			continue;
+
+		/* count number of tabs */
+		num_tabs = 0;
+		for (i = 0; i < line_len; i++) {
+			if (line[i] != '\t')
+				break;
+			num_tabs++;
+		}
+
+		switch (num_tabs) {
+		case 0:
+			/* vendor names */
+			vendor_matched = FALSE;
+
+			/* check vendor_id */
+			if (vendor_id != 0) {
+				if (memcmp (line, rep_vi, 4) == 0) {
+					/* found it */
+					vendor_matched = TRUE;
+
+					for (i = 4; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_vn, line + i,
+						 USB_IDS_MAX_LINE_LEN);
+					*vendor_name = store_vn;
+				}
+			}
+			break;
+
+		case 1:
+			/* product names */
+			if (!vendor_matched)
+				continue;
+
+			/* check product_id */
+			if (product_id != 0) {
+				if (memcmp (line + 1, rep_pi, 4) == 0) {
+					/* found it */
+					for (i = 5; i < line_len; i++) {
+						if (!isspace (line[i]))
+							break;
+					}
+					strncpy (store_pn, line + i,
+						 USB_IDS_MAX_LINE_LEN);
+					*product_name = store_pn;
+
+					/* no need to continue the search */
+					return;
+				}
+			}
+			break;
+
+		default:
+			break;
+		}
+
+	}
+}
+
+/** Free resources used by to store the USB database
+ *
+ *  @param                      #FALSE if the USB database wasn't loaded
+ */
+static dbus_bool_t
+usb_ids_free ()
+{
+	if (usb_ids != NULL) {
+		free (usb_ids);
+		usb_ids = NULL;
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/** Load the USB database used for mapping vendor, product, subsys_vendor
+ *  and subsys_product numbers into names.
+ *
+ *  @param  path                Path of the usb.ids file, e.g. 
+ *                              /usr/share/hwdata/usb.ids
+ *  @return                     #TRUE if the file was succesfully loaded
+ */
+static dbus_bool_t
+usb_ids_load (const char *path)
+{
+	FILE *fp;
+	unsigned int num_read;
+
+	fp = fopen (path, "r");
+	if (fp == NULL) {
+		printf ("couldn't open USB database at %s,", path);
+		return FALSE;
+	}
+
+	fseek (fp, 0, SEEK_END);
+	usb_ids_len = ftell (fp);
+	fseek (fp, 0, SEEK_SET);
+
+	usb_ids = malloc (usb_ids_len);
+	if (usb_ids == NULL) {
+		printf
+		    ("Couldn't allocate %d bytes for USB database file\n",
+		     usb_ids_len);
+		fclose(fp);
+		return FALSE;
+	}
+
+	num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
+	if (usb_ids_len != num_read) {
+		printf ("Error loading USB database file\n");
+		usb_ids_free ();
+		fclose(fp);
+		return FALSE;
+	}
+
+	fclose(fp);
+	return TRUE;
+}
+
+
+void 
+ids_init (void)
+{
+	/* Load /usr/share/hwdata/pci.ids */
+	pci_ids_load (HWDATA_DIR "/pci.ids");
+
+	/* Load /usr/share/hwdata/usb.ids */
+	usb_ids_load (HWDATA_DIR "/usb.ids");
+}
+
+
+/* This, somewhat incomplete, list is from this sources:
+ * http://www.plasma-online.de/english/identify/serial/pnp_id_pnp.html 
+ * http://www-pc.uni-regensburg.de/hardware/TECHNIK/PCI_PNP/pnpid.txt
+ *
+ * Keep this sorted!
+ */
+static char *pnp_ids_list[] = {
+	/* Crystal Semiconductor devices */
+	"CSC0000", "Crystal Semiconductor CS423x sound -- SB/WSS/OPL3 emulation",
+	"CSC0010", "Crystal Semiconductor CS423x sound -- control",
+	"CSC0001", "Crystal Semiconductor CS423x sound -- joystick",
+	"CSC0003", "Crystal Semiconductor CS423x sound -- MPU401",
+	/* IBM devices */
+	"IBM3780", "IBM pointing device",
+	"IBM0071", "IBM infrared communications device",
+	"IBM3760", "IBM DSP",
+	/* interrupt controllers */
+	"PNP0000", "AT Interrupt Controller",
+	"PNP0001", "EISA Interrupt Controller",
+	"PNP0002", "MCA Interrupt Controller",
+	"PNP0003", "APIC",
+	"PNP0004", "Cyrix SLiC MP interrupt controller",
+	/* timers */
+	"PNP0100", "AT Timer",
+	"PNP0101", "EISA Timer",
+	"PNP0102", "MCA Timer",
+	/* DMA controllers */
+	"PNP0200", "AT DMA Controller",
+	"PNP0201", "EISA DMA Controller",
+	"PNP0202", "MCA DMA Controller",
+	/* keyboards */
+	"PNP0300", "IBM PC/XT keyboard controller (83-key)",
+	"PNP0301", "IBM PC/AT keyboard controller (86-key)",
+	"PNP0302", "IBM PC/XT keyboard controller (84-key)",
+	"PNP0303", "IBM Enhanced (101/102-key, PS/2 mouse support)",
+	"PNP0304", "Olivetti Keyboard (83-key)",
+	"PNP0305", "Olivetti Keyboard (102-key)",
+	"PNP0306", "Olivetti Keyboard (86-key)",
+	"PNP0307", "Microsoft Windows(R) Keyboard",
+	"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy",
+	"PNP0309", "Olivetti Keyboard (A101/102 key)",
+	"PNP030A", "AT&T 302 keyboard",
+	"PNP030B", "Reserved by Microsoft",
+	"PNP0320", "Japanese 101-key keyboard",
+	"PNP0321", "Japanese AX keyboard",
+	"PNP0322", "Japanese 106-key keyboard A01",
+	"PNP0323", "Japanese 106-key keyboard 002/003",
+	"PNP0324", "Japanese 106-key keyboard 001",
+	"PNP0325", "Japanese Toshiba Desktop keyboard",
+	"PNP0326", "Japanese Toshiba Laptop keyboard",
+	"PNP0327", "Japanese Toshiba Notebook keyboard",
+	"PNP0340", "Korean 84-key keyboard",
+	"PNP0341", "Korean 86-key keyboard",
+	"PNP0342", "Korean Enhanced keyboard",
+	"PNP0343", "Korean Enhanced keyboard 101b",
+	"PNP0343", "Korean Enhanced keyboard 101c",
+	"PNP0344", "Korean Enhanced keyboard 103",
+	/* parallel ports */
+	"PNP0400", "Standard LPT printer port",
+	"PNP0401", "ECP printer port",
+	/* serial ports */
+	"PNP0500", "Standard PC COM port",
+	"PNP0501", "16550A-compatible COM port",
+	"PNP0502", "Multiport serial device (non-intelligent 16550)",
+	"PNP0510", "Generic IRDA-compatible device",
+	"PNP0511", "Generic IRDA-compatible device",
+	/* IDE controller */
+	"PNP0600", "Generic ESDI/IDE/ATA compatible hard disk controller",
+	"PNP0601", "Plus Hardcard II",
+	"PNP0602", "Plus Hardcard IIXL/EZ",
+	"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification",
+	"PNP0680", "Bus Master E-IDE controller",
+	/* floppy controllers */
+	"PNP0604", "PC standard floppy disk controller",
+	"PNP0605", "HP Omnibook floppy disk controller",
+	"PNP0700", "PC standard floppy disk controller",
+	"PNP0701", "Standard floppy controller supporting MS Device Bay Spec",
+	/* obsolete devices */
+	"PNP0802", "Microsoft Sound System compatible device (obsolete, use PNPB0xx instead)",
+	/* display adapters / graphic cards */
+	"PNP0900", "VGA Compatible",
+	"PNP0901", "Video Seven VRAM/VRAM II/1024i",
+	"PNP0902", "IBM 8514/A Compatible",
+	"PNP0903", "Trident VGA",
+	"PNP0904", "Cirrus Logic Laptop VGA",
+	"PNP0905", "Cirrus Logic VGA",
+	"PNP0906", "Tseng Labs ET4000",
+	"PNP0907", "Western Digital VGA",
+	"PNP0908", "Western Digital Laptop VGA",
+	"PNP0909", "S3 Inc. 911/924",
+	"PNP090A", "ATI Ultra Pro/Plus (Mach 32)",
+	"PNP090B", "ATI Ultra (Mach 8)",
+	"PNP090C", "IBM XGA Compatible",
+	"PNP090D", "ATI VGA Wonder",
+	"PNP090E", "Weitek P9000 Graphics Adapter",
+	"PNP090F", "Oak Technology VGA",
+	"PNP0910", "Compaq QVision",
+	"PNP0911", "IBM XGA/2",
+	"PNP0912", "Tseng Labs ET4000 W32/W32i/W32p",
+	"PNP0913", "S3 Inc. 801/928/964",
+	"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)",
+	"PNP0915", "Compaq Advanced VGA (AVGA)",
+	"PNP0916", "ATI Ultra Pro Turbo (Mach64)",
+	"PNP0917", "Reserved by Microsoft",
+	"PNP0918", "Matrox MGA",
+	"PNP0919", "Compaq QVision 2000",
+	"PNP091A", "Tseng Labs W128",
+	"PNP0930", "Chips & Technologies Super VGA",
+	"PNP0931", "Chips & Technologies Accelerator",
+	"PNP0940", "NCR 77c22e Super VGA",
+	"PNP0941", "NCR 77c32blt",
+	"PNP09FF", "Plug and Play Monitors (VESA DDC)",
+	/* peripheral buses */
+	"PNP0A00", "ISA Bus",
+	"PNP0A01", "EISA Bus",
+	"PNP0A02", "MCA Bus",
+	"PNP0A03", "PCI Bus",
+	"PNP0A04", "VESA/VL Bus",
+	"PNP0A05", "Generic ACPI Bus",
+	"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)",
+	/* system devices */
+	"PNP0800", "AT-style speaker sound",
+	"PNP0B00", "AT Real-Time Clock",
+	"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)",
+	"PNP0C01", "System Board",
+	"PNP0C02", "General ID for reserving resources required by PnP motherboard registers. (Not device specific.)",
+	"PNP0C03", "Plug and Play BIOS Event Notification Interrupt",
+	"PNP0C04", "Math Coprocessor",
+	"PNP0C05", "APM BIOS (Version independent)",
+	"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation",
+	"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation",
+	"PNP0C08", "ACPI system board hardware",
+	"PNP0C09", "ACPI Embedded Controller",
+	"PNP0C0A", "ACPI Control Method Battery",
+	"PNP0C0B", "ACPI Fan",
+	"PNP0C0C", "ACPI power button device",
+	"PNP0C0D", "ACPI lid device",
+	"PNP0C0E", "ACPI sleep button device",
+	"PNP0C0F", "PCI interrupt link device",
+	"PNP0C10", "ACPI system indicator device",
+	"PNP0C11", "ACPI thermal zone",
+	"PNP0C12", "Device Bay Controller",
+	"PNP0C13", "Plug and Play BIOS (used when ACPI mode cannot be used)",
+	"PNP0CF0", "Compaq LTE Lite Support",
+	"PNP0CF1", "Compaq LTE Elite Support",
+	/* PCMCIA controllers */
+	"PNP0E00", "Intel 82365-Compatible PCMCIA Controller",
+	"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller",
+	"PNP0E02", "VLSI VL82C146 PCMCIA Controller",
+	"PNP0E03", "Intel 82365-compatible CardBus controller",
+	/* mice */
+	"PNP0F00", "Microsoft Bus Mouse",
+	"PNP0F01", "Microsoft Serial Mouse",
+	"PNP0F02", "Microsoft InPort Mouse",
+	"PNP0F03", "Microsoft PS/2-style Mouse",
+	"PNP0F04", "Mouse Systems Mouse",
+	"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)",
+	"PNP0F06", "Genius Mouse (COM1)",
+	"PNP0F07", "Genius Mouse (COM2)",
+	"PNP0F08", "Logitech Serial Mouse",
+	"PNP0F09", "Microsoft BallPoint Serial Mouse",
+	"PNP0F0A", "Microsoft Plug and Play Mouse",
+	"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse",
+	"PNP0F0C", "Microsoft-compatible Serial Mouse",
+	"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse",
+	"PNP0F0E", "Microsoft-compatible PS/2-style Mouse",
+	"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse",
+	"PNP0F10", "Texas Instruments QuickPort Mouse",
+	"PNP0F11", "Microsoft-compatible Bus Mouse",
+	"PNP0F12", "Logitech PS/2-style Mouse",
+	"PNP0F13", "PS/2 Port for PS/2-style Mice",
+	"PNP0F14", "Microsoft Kids Mouse",
+	"PNP0F15", "Logitech bus mouse",
+	"PNP0F16", "Logitech SWIFT device",
+	"PNP0F17", "Logitech-compatible serial mouse",
+	"PNP0F18", "Logitech-compatible bus mouse",
+	"PNP0F19", "Logitech-compatible PS/2-style Mouse",
+	"PNP0F1A", "Logitech-compatible SWIFT Device",
+	"PNP0F1B", "HP Omnibook Mouse",
+	"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse",
+	"PNP0F1D", "Compaq LTE Trackball Serial Mouse",
+	"PNP0F1E", "Microsoft Kids Trackball Mouse",
+	"PNP0F1F", "Reserved by Microsoft Input Device Group",
+	"PNP0F20", "Reserved by Microsoft Input Device Group",
+	"PNP0F21", "Reserved by Microsoft Input Device Group",
+	"PNP0F22", "Reserved by Microsoft Input Device Group",
+	"PNP0F23", "Reserved by Microsoft Input Device Group",
+	"PNP0FFF", "Reserved by Microsoft Systems",
+	"PNP0XXX", "Unknown System Device",
+	/* network cards */
+	"PNP8000", "Network Adapter",
+	"PNP8001", "Novell/Anthem NE3200",
+	"PNP8004", "Compaq NE3200",
+	"PNP8006", "Intel EtherExpress/32",
+	"PNP8008", "HP EtherTwist EISA LAN Adapter/32 (HP27248A)",
+	"PNP8065", "Ungermann-Bass NIUps or NIUps/EOTP",
+	"PNP8072", "DEC (DE211) EtherWorks MC/TP",
+	"PNP8073", "DEC (DE212) EtherWorks MC/TP_BNC",
+	"PNP8074", "HP MC LAN Adapter/16 TP (PC27246)",
+	"PNP8078", "DCA 10 Mb MCA",
+	"PNP807F", "Racal NI9210",
+	"PNP8081", "Pure Data Ethernet",
+	"PNP8096", "Thomas-Conrad TC4046",
+	"PNP80C9", "IBM Token Ring",
+	"PNP80CA", "IBM Token Ring II",
+	"PNP80CB", "IBM Token Ring II/Short",
+	"PNP80CC", "IBM Token Ring 4/16Mbs",
+	"PNP80D3", "Novell/Anthem NE1000",
+	"PNP80D4", "Novell/Anthem NE2000",
+	"PNP80D5", "NE1000 Compatible",
+	"PNP80D6", "NE2000 Compatible",
+	"PNP80D7", "Novell/Anthem NE1500T",
+	"PNP80D8", "Novell/Anthem NE2100",
+	"PNP80D9", "NE2000 Plus",
+	"PNP80DD", "SMC ARCNETPC",
+	"PNP80DE", "SMC ARCNET PC100, PC200",
+	"PNP80DF", "SMC ARCNET PC110, PC210, PC250",
+	"PNP80E0", "SMC ARCNET PC130/E",
+	"PNP80E1", "SMC ARCNET PC120, PC220, PC260",
+	"PNP80E2", "SMC ARCNET PC270/E",
+	"PNP80E5", "SMC ARCNET PC600W, PC650W",
+	"PNP80E7", "DEC DEPCA",
+	"PNP80E8", "DEC (DE100) EtherWorks LC",
+	"PNP80E9", "DEC (DE200) EtherWorks Turbo",
+	"PNP80EA", "DEC (DE101) EtherWorks LC/TP",
+	"PNP80EB", "DEC (DE201) EtherWorks Turbo/TP",
+	"PNP80EC", "DEC (DE202) EtherWorks Turbo/TP_BNC",
+	"PNP80ED", "DEC (DE102) EtherWorks LC/TP_BNC",
+	"PNP80EE", "DEC EE101 (Built-In)",
+	"PNP80EF", "DEC PC 433 WS (Built-In)",
+	"PNP80F1", "3Com EtherLink Plus",
+	"PNP80F3", "3Com EtherLink II or IITP (8 or 16-bit)",
+	"PNP80F4", "3Com TokenLink",
+	"PNP80F6", "3Com EtherLink 16",
+	"PNP80F7", "3Com EtherLink III",
+	"PNP80F8", "3Com Generic Etherlink Plug and Play Device",
+	"PNP80FB", "Thomas Conrad TC6045",
+	"PNP80FC", "Thomas Conrad TC6042",
+	"PNP80FD", "Thomas Conrad TC6142",
+	"PNP80FE", "Thomas Conrad TC6145",
+	"PNP80FF", "Thomas Conrad TC6242",
+	"PNP8100", "Thomas Conrad TC6245",
+	"PNP8101", "Thomas-Conrad TC4045",
+	"PNP8104", "Thomas-Conrad TC4035",
+	"PNP8105", "DCA 10 MB",
+	"PNP8106", "DCA 10 MB Fiber Optic",
+	"PNP8107", "DCA 10 MB Twisted Pair",
+	"PNP8113", "Racal NI6510",
+	"PNP8114", "Racal NI5210/8 or NI5210/16",
+	"PNP8119", "Ungermann-Bass pcNIU",
+	"PNP811A", "Ungermann-Bass pcNIU/ex 128K",
+	"PNP811B", "Ungermann-Bass pcNIU/ex 512K", 
+	"PNP811C", "Ungermann-Bass NIUpc",
+	"PNP811D", "Ungermann-Bass NIUpc/3270",
+	"PNP8120", "Ungermann-Bass NIUpc/EOTP",
+	"PNP8123", "SMC StarCard PLUS (WD/8003S)",
+	"PNP8124", "SMC StarCard PLUS With On Board Hub (WD/8003SH)",
+	"PNP8125", "SMC EtherCard PLUS (WD/8003E)",
+	"PNP8126", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EBT)",
+	"PNP8127", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EB)",
+	"PNP8128", "SMC EtherCard PLUS TP (WD/8003WT)",
+	"PNP812A", "SMC EtherCard PLUS 16 With Boot ROM Socket (WD/8013EBT)",
+	"PNP812D", "Intel EtherExpress 16 or 16TP",
+	"PNP812F", "Intel TokenExpress 16/4",
+	"PNP8130", "Intel TokenExpress MCA 16/4",
+	"PNP8132", "Intel EtherExpress 16 (MCA)",
+	"PNP8133", "Compaq Ethernet 16E",
+	"PNP8137", "Artisoft AE-1",
+	"PNP8138", "Artisoft AE-2 or AE-3",
+	"PNP8141", "Amplicard AC 210/XT",
+	"PNP8142", "Amplicard AC 210/AT",
+	"PNP814B", "Everex SpeedLink /PC16 (EV2027)",
+	"PNP8155", "HP PC LAN Adapter/8 TP (HP27245)",
+	"PNP8156", "HP PC LAN Adapter/16 TP (HP27247A)",
+	"PNP8157", "HP PC LAN Adapter/8 TL (HP27250)",
+	"PNP8158", "HP PC LAN Adapter/16 TP Plus (HP27247B)",
+	"PNP8159", "HP PC LAN Adapter/16 TL Plus (HP27252)",
+	"PNP815F", "National Semiconductor Ethernode *16AT",
+	"PNP8160", "National Semiconductor AT/LANTIC EtherNODE 16-AT3",
+	"PNP8169", "NCR StarCard",
+	"PNP816A", "NCR Token-Ring 4 Mbs ISA",
+	"PNP816B", "NCR WaveLAN AT",
+	"PNP816C", "NCR WaveLan MC",
+	"PNP816D", "NCR Token-Ring 16/4 Mbs ISA",
+	"PNP8191", "Olicom 16/4 Token-Ring Adapter",
+	"PNP81A5", "Research Machines Ethernet",
+	"PNP81B9", "ToshibaLAN (internal)",
+	"PNP81C3", "SMC EtherCard PLUS Elite (WD/8003EP)",
+	"PNP81C4", "SMC EtherCard PLUS 10T (WD/8003W)",
+	"PNP81C5", "SMC EtherCard PLUS Elite 16 (WD/8013EP)",
+	"PNP81C6", "SMC EtherCard PLUS Elite 16T (WD/8013W)",
+	"PNP81C7", "SMC EtherCard PLUS Elite 16 Combo (WD/8013EW or 8013EWC)",
+	"PNP81C8", "SMC EtherElite Ultra 16",
+	"PNP81C9", "SMC TigerCard (8216L, 8216LC, 8216LT)",
+	"PNP81CA", "SMC EtherEZ (8416)",
+	"PNP81D7", "Madge Smart 16/4 PC Ringnode",
+	"PNP81D8", "Madge Smart 16/4 Ringnode ISA",
+	"PNP81E4", "Pure Data PDI9025-32 (Token Ring)",
+	"PNP81E6", "Pure Data PDI508+ (ArcNet)",
+	"PNP81E7", "Pure Data PDI516+ (ArcNet)",
+	"PNP81EB", "Proteon Token Ring (P1390)",
+	"PNP81EC", "Proteon Token Ring (P1392)",
+	"PNP81ED", "Proteon Token Ring ISA (P1340)",
+	"PNP81EE", "Proteon Token Ring ISA (P1342)",
+	"PNP81EF", "Proteon Token Ring ISA (P1346)",
+	"PNP81F0", "Proteon Token Ring ISA (P1347)",
+	"PNP81FF", "Cabletron E2000 Series DNI",
+	"PNP8200", "Cabletron E2100 Series DNI",
+	"PNP8201", "Cabletron T2015 4/16 Mbit/s DNI",
+	"PNP8209", "Zenith Data Systems Z-Note",
+	"PNP820A", "Zenith Data Systems NE2000-Compatible",
+	"PNP8213", "Xircom Pocket Ethernet II",
+	"PNP8214", "Xircom Pocket Ethernet I",
+	"PNP8215", "Xircom Pocket Ethernet III Adapter",
+	"PNP821D", "RadiSys EXM-10",
+	"PNP8227", "SMC 3000 Series",
+	"PNP8228", "SMC 91C2 controller",
+	"PNP8231", "AMD AM2100/AM1500T",
+	"PNP824F", "RCE 10Base-T (16 bit)",
+	"PNP8250", "RCE 10Base-T (8 bit)",
+	"PNP8263", "Tulip NCC-16",
+	"PNP8277", "Exos 105",
+	"PNP828A", "Intel '595 based Ethernet",
+	"PNP828B", "TI2000-style Token Ring",
+	"PNP828C", "AMD PCNet Family cards",
+	"PNP828D", "AMD PCNet32 (VL version)",
+	"PNP8294", "IrDA Infrared NDIS driver (Microsoft-supplied)",
+	"PNP82BD", "IBM PCMCIA-NIC",
+	"PNP82C0", "Eagle Technology NE200T",
+	"PNP82C2", "Xircom CE10",
+	"PNP82C3", "Xircom CEM2",
+	"PNP82C4", "Xircom CE2",
+	"PNP8321", "DEC Ethernet (All Types)",
+	"PNP8323", "SMC EtherCard (All Types except 8013/A)",
+	"PNP8324", "ARCNET Compatible",
+	"PNP8325", "SMC TokenCard PLUS (8115T)",
+	"PNP8326", "Thomas Conrad (All Arcnet Types)",
+	"PNP8327", "IBM Token Ring (All Types)",
+	"PNP8328", "Ungermann-Bass NIU",
+	"PNP8329", "Proteon ProNET-4/16 ISA Token Ring (P1392+,P1392,1390)",
+	"PNP8385", "Remote Network Access [RNA] Driver",
+	"PNP8387", "Remote Network Access [RNA] PPP Driver",
+	"PNP8388", "Reserved for Microsoft Networking components",
+	"PNP8389", "Peer IrLAN infrared driver (Microsoft-supplied)",
+	"PNP8390", "Generic network adapter",
+	"PNP8XXX", "Unknown Network Adapter",
+	"PNPD300", "SK-NET TR4/16+ Token-Ring",
+	"PNPE000", "SK-NET G16, G16/TP Ethernet",
+	"PNPF000", "SK-NET FDDI-FI FDDI LAN",
+	/* CD controller */
+	"PNPA000", "Adaptec 154x compatible SCSI controller",
+	"PNPA001", "Adaptec 174x compatible SCSI controller",
+	"PNPA002", "Future Domain 16-700 compatible controller",
+	"PNPA003", "Mitsumi CD-ROM adapter (Panasonic spec., used on SBPro/SB16)",
+	"PNPA01B", "Trantor 128 SCSI Controller",
+	"PNPA01D", "Trantor T160 SCSI Controller",
+	"PNPA01E", "Trantor T338 Parallel SCSI controller",
+	"PNPA01F", "Trantor T348 Parallel SCSI controller",
+	"PNPA020", "Trantor Media Vision SCSI controller",
+	"PNPA022", "Always IN-2000 SCSI controller",
+	"PNPA02B", "Sony proprietary CD-ROM controller",
+	"PNPA02D", "Trantor T13b 8-bit SCSI controller",
+	"PNPA02F", "Trantor T358 Parallel SCSI controller",
+	"PNPA030", "Mitsumi LU-005 Single Speed CD-ROM controller + drive",
+	"PNPA031", "Mitsumi FX-001 Single Speed CD-ROM controller + drive",
+	"PNPA032", "Mitsumi FX-001 Double Speed CD-ROM controller + drive",
+	"PNPAXXX", "Unknown SCSI, Proprietary CD Adapter",
+	/* multimedia devices */
+	"PNPB000", "Creative Labs Sound Blaster 1.5 (or compatible sound device)",
+	"PNPB001", "Creative Labs Sound Blaster 2.0 (or compatible sound device)",
+	"PNPB002", "Creative Labs Sound Blaster Pro (or compatible sound device)",
+	"PNPB003", "Creative Labs Sound Blaster 16 (or compatible sound device)",
+	"PNPB004", "MediaVision Thunderboard (or compatible sound device)",
+	"PNPB005", "Adlib-compatible FM synthesizer device",
+	"PNPB006", "MPU401 compatible",
+	"PNPB007", "Microsoft Windows Sound System-compatible sound device",
+	"PNPB008", "Compaq Business Audio",
+	"PNPB009", "Plug and Play Microsoft Windows Sound System Device",
+	"PNPB00A", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)",
+	"PNPB00B", "MediaVision Pro Audio 3D",
+	"PNPB00C", "MusicQuest MQX-32M",
+	"PNPB00D", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)",
+	"PNPB00E", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)",
+	"PNPB00F", "MediaVision Jazz-16 chipset (OEM Versions)",
+	"PNPB010", "Orchid Videola - Auravision VxP500 chipset",
+	"PNPB018", "MediaVision Pro Audio Spectrum 8-bit",
+	"PNPB019", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)",
+	"PNPB020", "Yamaha OPL3-compatible FM synthesizer device",
+	"PNPB02F", "Joystick/Game port",
+	"PNPB077", "OAK Mozart Sound System",
+	"PNPB078", "OAK Mozart Sound System MPU-401",
+	"PNPBXXX", "Unknown Multimedia Device",
+	/* modems */
+	"PNP9000", "Modem",
+	"PNPC000", "Compaq 14400 Modem (TBD)",
+	"PNPC001", "Compaq 2400/9600 Modem (TBD)",
+	"PNPCXXX", "Unknown Modem",
+	/* Toshiba devices */
+	"TOS6200", "Toshiba Notebook Extra HCI driver",
+	"TOS6202", "Toshiba Notebook Extra HCI driver",
+	"TOS6207", "Toshiba Notebook Extra HCI driver",
+	"TOS7400", "Toshiba AcuPoint",
+	/* Wacom devices */
+	"WACf004", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
+	"WACf005", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
+	"WACf006", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
+	NULL
+};
+
+
+void
+ids_find_pnp (const char *pnp_id, char **pnp_description)
+{
+	unsigned int i;
+
+	/* OK, so someone should optimize this lookup - send me patches */
+	for (i = 0; pnp_ids_list[2*i] != NULL; i++) {
+		if (strcasecmp (pnp_id, pnp_ids_list[2*i]) == 0) {
+			*pnp_description = pnp_ids_list[2*i + 1];
+			return;
+		}
+	}
+
+	*pnp_description = NULL;
+}
diff --git a/hald/linux/ids.h b/hald/linux/ids.h
new file mode 100644
index 0000000..c189320
--- /dev/null
+++ b/hald/linux/ids.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * ids.h : Lookup names from hardware identifiers
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef IDS_H
+#define IDS_H
+
+#include <glib.h>
+
+void ids_init (void);
+
+void
+ids_find_pci (int vendor_id, int product_id,
+	      int subsys_vendor_id, int subsys_product_id,
+	      char **vendor_name, char **product_name,
+	      char **subsys_vendor_name, char **subsys_product_name);
+
+void
+ids_find_usb (int vendor_id, int product_id,
+	      char **vendor_name, char **product_name);
+
+void
+ids_find_pnp (const char *pnp_id, char **pnp_description);
+
+
+#endif /* IDS_H */
diff --git a/hald/linux/osspec.c b/hald/linux/osspec.c
new file mode 100644
index 0000000..9571d25
--- /dev/null
+++ b/hald/linux/osspec.c
@@ -0,0 +1,632 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * osspec.c : New and improved HAL backend for Linux 2.6
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
+ * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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
+
+#define _GNU_SOURCE 1
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <linux/types.h>
+#include <net/if_arp.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../hald.h"
+#include "../hald_dbus.h"
+#include "../hald_runner.h"
+#include "../logger.h"
+#include "../osspec.h"
+#include "../util.h"
+
+#include "acpi.h"
+#include "apm.h"
+#include "blockdev.h"
+#include "coldplug.h"
+#include "hotplug.h"
+#include "ids.h"
+#include "pmu.h"
+
+#include "osspec_linux.h"
+
+static char *hal_sysfs_path;
+static char *hal_proc_path;
+
+const gchar *
+get_hal_sysfs_path (void)
+{
+	return hal_sysfs_path;
+}
+
+const gchar *
+get_hal_proc_path (void)
+{
+	return hal_proc_path;
+}
+
+static gboolean
+hald_udev_data (GIOChannel *source, GIOCondition condition, gpointer user_data)
+{
+	int fd;
+	int retval;
+	struct msghdr smsg;
+	struct cmsghdr *cmsg;
+	struct iovec iov;
+	struct ucred *cred;
+	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
+
+	char buf[4096];
+	size_t bufpos = 0;
+	const char *action = NULL;
+	HotplugEvent *hotplug_event;
+
+	memset(buf, 0x00, sizeof (buf));
+
+	fd = g_io_channel_unix_get_fd (source);
+
+	iov.iov_base = &buf;
+	iov.iov_len = sizeof (buf);
+
+	memset(&smsg, 0x00, sizeof (struct msghdr));
+	smsg.msg_iov = &iov;
+	smsg.msg_iovlen = 1;
+	smsg.msg_control = cred_msg;
+	smsg.msg_controllen = sizeof (cred_msg);
+
+	retval = recvmsg (fd, &smsg, 0);
+	if (retval <  0) {
+		if (errno != EINTR)
+			HAL_INFO (("Unable to receive message, errno=%d", errno));
+		goto out;
+	}
+	cmsg = CMSG_FIRSTHDR (&smsg);
+	cred = (struct ucred *) CMSG_DATA (cmsg);
+
+	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
+		HAL_INFO (("No sender credentials received, message ignored"));
+		goto out;
+	}
+
+	if (cred->uid != 0) {
+		HAL_INFO (("Sender uid=%i, message ignored", cred->uid));
+		goto out;
+	}
+
+	if (!strstr(buf, "@/")) {
+		HAL_INFO (("invalid message format"));
+		goto out;
+	}
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+
+	while (bufpos < sizeof (buf)) {
+		size_t keylen;
+		char *key;
+		char *str;
+
+		key = &buf[bufpos];
+		keylen = strlen(key);
+		if (keylen == 0)
+			break;
+		bufpos += keylen + 1;
+
+		if (strncmp(key, "ACTION=", 7) == 0)
+			action = &key[7];
+		else if (strncmp(key, "DEVPATH=", 8) == 0)
+			g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path),
+				    "%s%s", hal_sysfs_path, &key[8]);
+		else if (strncmp(key, "SUBSYSTEM=", 10) == 0)
+			g_strlcpy (hotplug_event->sysfs.subsystem, &key[10], sizeof (hotplug_event->sysfs.subsystem));
+		else if (strncmp(key, "DEVNAME=", 8) == 0)
+			g_strlcpy (hotplug_event->sysfs.device_file, &key[8], sizeof (hotplug_event->sysfs.device_file));
+		else if (strncmp(key, "SEQNUM=", 7) == 0)
+			hotplug_event->sysfs.seqnum = strtoull(&key[7], NULL, 10);
+		else if (strncmp(key, "IFINDEX=", 8) == 0)
+			hotplug_event->sysfs.net_ifindex = strtoul(&key[8], NULL, 10);
+		else if (strncmp(key, "ID_VENDOR=", 10) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[10]);
+			g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
+			g_free (str);
+		} else if (strncmp(key, "ID_MODEL=", 9) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[9]);
+			g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
+			g_free (str);
+		} else if (strncmp(key, "ID_REVISION=", 12) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[12]);
+			g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
+			g_free (str);
+		} else if (strncmp(key, "ID_SERIAL=", 10) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[10]);
+			g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
+			g_free (str);
+		} else if (strncmp(key, "ID_FS_USAGE=", 12) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[12]);
+			g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
+			g_free (str);
+		} else if (strncmp(key, "ID_FS_TYPE=", 11) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[11]);
+			g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
+			g_free (str);
+		} else if (strncmp(key, "ID_FS_VERSION=", 14) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[14]);
+			g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
+			g_free (str);
+		} else if (strncmp(key, "ID_FS_UUID=", 11) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[11]);
+			g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
+			g_free (str);
+		} else if (strncmp(key, "ID_FS_LABEL=", 12) == 0) {
+			str = hal_util_strdup_valid_utf8(&key[12]);
+			g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
+			g_free (str);
+		}
+	}
+
+	if (!action) {
+		HAL_INFO (("missing ACTION"));
+		goto invalid;
+	}
+	if (hotplug_event->sysfs.sysfs_path == NULL) {
+		HAL_INFO (("missing DEVPATH"));
+		goto invalid;
+	}
+	if (hotplug_event->sysfs.subsystem == NULL) {
+		HAL_INFO (("missing SUSBSYSTEM"));
+		goto invalid;
+	}
+
+	HAL_INFO (("SEQNUM=%lld, ACTION=%s, SUBSYSTEM=%s, DEVPATH=%s, DEVNAME=%s, IFINDEX=%d",
+		   hotplug_event->sysfs.seqnum, action, hotplug_event->sysfs.subsystem, hotplug_event->sysfs.sysfs_path,
+		   hotplug_event->sysfs.device_file, hotplug_event->sysfs.net_ifindex));
+
+	if (strcmp (action, "add") == 0) {
+		hotplug_event->action = HOTPLUG_ACTION_ADD;
+		hotplug_event_enqueue (hotplug_event);
+		hotplug_event_process_queue ();
+		goto out;
+	}
+
+	if (strcmp (action, "remove") == 0) {
+		hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+		hotplug_event_enqueue (hotplug_event);
+		hotplug_event_process_queue ();
+		goto out;
+	}
+
+invalid:
+	g_free (hotplug_event);
+
+out:
+	return TRUE;
+}
+
+static gboolean
+mount_tree_changed_event (GIOChannel *channel, GIOCondition cond,
+		    gpointer user_data)
+{
+	if (cond & ~G_IO_ERR)
+		return TRUE;
+
+	HAL_INFO (("/proc/mounts tells, that the mount has tree changed"));
+	blockdev_refresh_mount_state (NULL);
+
+	return TRUE;
+}
+
+void
+osspec_init (void)
+{
+	gchar path[HAL_PATH_MAX];
+	int udev_socket;
+	struct sockaddr_un saddr;
+	socklen_t addrlen;
+	const int on = 1;
+	GIOChannel *udev_channel;
+	GIOChannel *mounts_channel;
+
+	/*
+	 * setup socket for listening from messages from udev
+	 */
+	memset(&saddr, 0x00, sizeof(saddr));
+	saddr.sun_family = AF_LOCAL;
+	/* use abstract namespace for socket path */
+	strcpy(&saddr.sun_path[1], "/org/freedesktop/hal/udev_event");
+	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
+
+	udev_socket = socket(AF_LOCAL, SOCK_DGRAM, 0);
+	if (udev_socket == -1) {
+		DIE (("Couldn't open socket"));
+	}
+
+	if (bind(udev_socket, (struct sockaddr *) &saddr, addrlen) < 0) {
+		fprintf (stderr, "Error binding udev_event socket: %s\n", strerror(errno));
+		exit (1);
+	}
+	/* enable receiving of the sender credentials */
+	setsockopt(udev_socket, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
+
+	udev_channel = g_io_channel_unix_new (udev_socket);
+	g_io_add_watch (udev_channel, G_IO_IN, hald_udev_data, NULL);
+	g_io_channel_unref (udev_channel);
+
+	/*
+	 * set mount points for /proc and /sys, possibly overridden for testing
+	 */
+	hal_sysfs_path = getenv ("SYSFS_PATH");
+	if (hal_sysfs_path == NULL)
+		hal_sysfs_path = "/sys";
+
+	hal_proc_path = getenv ("PROC_PATH");
+	if (hal_proc_path == NULL)
+		hal_proc_path = "/proc";
+
+	/*
+	 * watch /proc/mounts for mount tree changes
+	 * kernel 2.6.15 vfs throws a POLLERR event for every change
+	 */
+	g_snprintf (path, sizeof (path), "%s/mounts", get_hal_proc_path ());
+	mounts_channel = g_io_channel_new_file (path, "r", NULL);
+	if (mounts_channel == NULL)
+		DIE (("Unable to read /proc/mounts"));
+	g_io_add_watch (mounts_channel, G_IO_ERR, mount_tree_changed_event, NULL);
+
+	/*
+	 *Load various hardware id databases
+	 */
+	ids_init ();
+}
+
+static void 
+computer_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	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);
+
+	/* start processing events */
+	hotplug_event_process_queue ();
+}
+
+void
+hotplug_queue_now_empty (void)
+{
+	if (hald_is_initialising)
+		osspec_probe_done ();
+}
+
+
+static void
+computer_probing_helper_done (HalDevice *d)
+{
+	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
+	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
+
+	hal_util_callout_device_add (d, computer_callouts_add_done, NULL, NULL);
+}
+
+static void 
+computer_probing_pcbios_helper_done (HalDevice *d, guint32 exit_type, 
+	                             gint return_code, gchar **error, 
+				     gpointer data1, gpointer data2)
+{
+	const char *chassis_type;
+	const char *system_manufacturer;
+	const char *system_product;
+	const char *system_version;
+
+	if (exit_type == HALD_RUN_FAILED) {
+		/* set a default value */
+		if (!hal_device_has_property (d, "system.formfactor"))
+			hal_device_property_set_string (d, "system.formfactor", "unknown");
+		goto out;
+	}
+
+	if ((system_manufacturer = hal_device_property_get_string (d, "smbios.system.manufacturer")) != NULL &&
+	    (system_product = hal_device_property_get_string (d, "smbios.system.product")) != NULL &&
+	    (system_version = hal_device_property_get_string (d, "smbios.system.version")) != NULL) {
+		char buf[128];
+
+		hal_device_property_set_string (d, "system.vendor", system_manufacturer);
+
+		if (strcmp(system_version, "Not Specified" ) != 0 ) {
+			g_snprintf (buf, sizeof (buf), "%s %s", system_product, system_version);
+			hal_device_property_set_string (d, "system.product", buf);
+		} else {
+			hal_device_property_set_string (d, "system.product", system_product);
+		}
+	}
+
+
+	if (!hal_device_has_property (d, "system.formfactor")) {
+		/* now map the smbios.* properties to our generic system.formfactor property */
+		if ((chassis_type = hal_device_property_get_string (d, "smbios.chassis.type")) != NULL) {
+			unsigned int i;
+
+			/* Map the chassis type from dmidecode.c to a sensible type used in hal 
+			 *
+			 * See also 3.3.4.1 of the "System Management BIOS Reference Specification, 
+			 * Version 2.3.4" document, available from http://www.dmtf.org/standards/smbios.
+			 *
+			 * TODO: figure out WTF the mapping should be; "Lunch Box"? Give me a break :-)
+			 */
+			static const char *chassis_map[] = {
+				"Other",                 "unknown",
+				"Unknown",               "unknown",
+				"Desktop",               "desktop",
+				"Low Profile Desktop",   "desktop",
+				"Pizza Box",             "server",
+				"Mini Tower",            "desktop",
+				"Tower",                 "desktop",
+				"Portable",              "laptop",
+				"Laptop",                "laptop",
+				"Notebook",              "laptop",
+				"Hand Held",             "handheld",
+				"Docking Station",       "laptop",
+				"All In One",            "unknown",
+				"Sub Notebook",          "laptop",
+				"Space-saving",          "unknown",
+				"Lunch Box",             "unknown",
+				"Main Server Chassis",   "server",
+				"Expansion Chassis",     "unknown",
+				"Sub Chassis",           "unknown",
+				"Bus Expansion Chassis", "unknown",
+				"Peripheral Chassis",    "unknown",
+				"RAID Chassis",          "unknown",
+				"Rack Mount Chassis",    "unknown",
+				"Sealed-case PC",        "unknown",
+				"Multi-system",          "unknown",
+				NULL
+			};
+			
+			for (i = 0; chassis_map[i] != NULL; i += 2) {
+				if (strcmp (chassis_map[i], chassis_type) == 0) {
+					hal_device_property_set_string (d, "system.formfactor", chassis_map[i+1]);
+					break;
+				}
+			}
+		       
+		} else {
+			/* set a default value */
+			hal_device_property_set_string (d, "system.formfactor", "unknown");
+		}
+	}
+out:
+	computer_probing_helper_done (d);
+}
+
+static void
+set_suspend_hibernate_keys (HalDevice *d)
+{
+	int can_suspend;
+	int can_hibernate;
+	ssize_t read;
+	size_t len;
+	char *poweroptions;
+	FILE *fp;
+
+	can_suspend = FALSE;
+	can_hibernate = FALSE;
+
+	/* try to find 'mem' and 'disk' in /sys/power/state */
+	fp = fopen ("/sys/power/state", "r");
+	if (fp == NULL) {
+		HAL_WARNING (("Could not open /sys/power/state"));
+		goto out;
+	}
+	poweroptions = NULL;
+	len = 0;
+	read = getline (&poweroptions, &len, fp);
+	fclose (fp);
+	if (poweroptions == NULL) {
+		HAL_WARNING (("Contents of /sys/power/state invalid"));
+		goto out;
+	}
+	if (strstr (poweroptions, "mem"))
+		can_suspend = TRUE;
+	if (strstr (poweroptions, "disk"))
+		can_hibernate = TRUE;
+	free (poweroptions);
+
+	/* check for the presence of suspend2 */
+	if (access ("/proc/software_suspend", F_OK) == 0)
+		can_hibernate = TRUE;
+	if (access ("/proc/suspend2", F_OK) == 0)
+		can_hibernate = TRUE;
+	if (access ("/sys/power/suspend2/version", F_OK) == 0)
+		can_hibernate = TRUE;
+out:
+	hal_device_property_set_bool (d, "power_management.can_suspend", can_suspend);
+	hal_device_property_set_bool (d, "power_management.can_hibernate", can_hibernate);
+
+	/* WARNING: These keys are depreciated and power_management.can_suspend
+	 * and power_management.can_hibernate should be used instead.
+	 * These properties will be removed, but not before May 1st 2007. */
+	hal_device_property_set_bool (d, "power_management.can_suspend_to_ram", can_suspend);
+	hal_device_property_set_bool (d, "power_management.can_suspend_to_disk", can_hibernate);
+}
+
+void 
+osspec_probe (void)
+{
+	HalDevice *root;
+	struct utsname un;
+	gboolean should_decode_dmi;
+
+	should_decode_dmi = FALSE;
+
+	root = hal_device_new ();
+	hal_device_property_set_string (root, "info.bus", "unknown");
+	hal_device_property_set_string (root, "linux.sysfs_path_device", "(none)");
+	hal_device_property_set_string (root, "info.product", "Computer");
+	hal_device_property_set_string (root, "info.udi", "/org/freedesktop/Hal/devices/computer");
+	hal_device_set_udi (root, "/org/freedesktop/Hal/devices/computer");
+
+	if (uname (&un) >= 0) {
+		hal_device_property_set_string (root, "system.kernel.name", un.sysname);
+		hal_device_property_set_string (root, "system.kernel.version", un.release);
+		hal_device_property_set_string (root, "system.kernel.machine", un.machine);
+	}
+
+	/* Let computer be in TDL while synthesizing all other events because some may write to the object */
+	hal_device_store_add (hald_get_tdl (), root);
+
+	/* will enqueue hotplug events for entire system */
+	HAL_INFO (("Synthesizing sysfs events..."));
+	coldplug_synthesize_events ();
+
+	HAL_INFO (("Synthesizing powermgmt events..."));
+	if (acpi_synthesize_hotplug_events ()) {
+		HAL_INFO (("ACPI capabilities found"));
+		should_decode_dmi = TRUE;
+	} else if (pmu_synthesize_hotplug_events ()) {
+		HAL_INFO (("PMU capabilities found"));		
+	} else if (apm_synthesize_hotplug_events ()) {
+		HAL_INFO (("APM capabilities found"));		
+		should_decode_dmi = TRUE;
+	} else {
+		HAL_INFO (("No powermgmt capabilities"));		
+	}
+	HAL_INFO (("Done synthesizing events"));
+
+	/*
+	 * Populate the powermgmt keys according to the kernel options.
+	 * NOTE: This may not mean the machine is able to suspend
+	 *	 or hibernate successfully, only that the machine has
+	 *	 support compiled into the kernel.
+	 */
+	set_suspend_hibernate_keys (root);
+
+	/* TODO: add prober for PowerMac's */
+	if (should_decode_dmi) {
+		hald_runner_run (root, "hald-probe-smbios", NULL, HAL_HELPER_TIMEOUT,
+        	                 computer_probing_pcbios_helper_done, NULL, NULL);
+	} else {
+		/* set a default value, can be overridden by others */
+		hal_device_property_set_string (root, "system.formfactor", "unknown");
+		/* no probing */
+		computer_probing_helper_done (root);
+  	}
+}
+
+DBusHandlerResult
+osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
+{
+	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+gboolean
+osspec_device_rescan (HalDevice *d)
+{
+	return hotplug_rescan_device (d);
+}
+
+gboolean
+osspec_device_reprobe (HalDevice *d)
+{
+	return hotplug_reprobe_tree (d);
+}
+
+gboolean
+hal_util_get_driver_name (const char *sysfs_path, gchar *driver_name)
+{
+	gchar driver_path[HAL_PATH_MAX];
+	struct stat statbuf;
+
+	g_snprintf (driver_path, sizeof (driver_path), "%s/driver", sysfs_path);
+	if (stat (driver_path, &statbuf) == 0) {
+		gchar buf[256];
+		memset (buf, '\0', sizeof (buf));
+		if (readlink (driver_path, buf, sizeof (buf) - 1) > 0) {
+			g_snprintf (driver_name, strlen(buf), "%s", hal_util_get_last_element(buf));
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+gboolean
+hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path)
+{
+	gboolean ret;
+	gchar driver_name[256];
+
+	memset (driver_name, '\0', sizeof (driver_name));
+	ret = hal_util_get_driver_name (sysfs_path, driver_name);
+	if (ret == TRUE)
+		hal_device_property_set_string (d, property_name, driver_name);
+
+	return ret;
+}
+
+/** Find the closest ancestor by looking at sysfs paths
+ *
+ *  @param  sysfs_path           Path into sysfs, e.g. /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-0:1.0
+ *  @return                      Parent Hal Device Object or #NULL if there is none
+ */
+HalDevice *
+hal_util_find_closest_ancestor (const gchar *sysfs_path)
+{	
+	gchar buf[512];
+	HalDevice *parent;
+
+	parent = NULL;
+
+	strncpy (buf, sysfs_path, sizeof (buf));
+	do {
+		char *p;
+
+		p = strrchr (buf, '/');
+		if (p == NULL)
+			break;
+		*p = '\0';
+
+		parent = hal_device_store_match_key_value_string (hald_get_gdl (), 
+								  "linux.sysfs_path_device", 
+								  buf);
+		if (parent != NULL)
+			break;
+
+	} while (TRUE);
+
+	return parent;
+}
+
diff --git a/hald/linux/osspec_linux.h b/hald/linux/osspec_linux.h
new file mode 100644
index 0000000..88d516c
--- /dev/null
+++ b/hald/linux/osspec_linux.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * osspec_linux.h : OS Specific interface
+ *
+ * Copyright (C) 2003 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef OSSPEC_LINUX_H
+#define OSSPEC_LINUX_H
+
+#include <glib.h>
+#include "../device.h"
+
+const gchar *get_hal_sysfs_path (void);
+
+const gchar *get_hal_proc_path (void);
+
+gboolean hal_util_get_driver_name (const char *sysfs_path, gchar *driver_name);
+
+gboolean hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path);
+
+HalDevice *hal_util_find_closest_ancestor (const gchar *sysfs_path);
+
+
+#endif /* OSSPEC_LINUX_H */
diff --git a/hald/linux/physdev.c b/hald/linux/physdev.c
new file mode 100644
index 0000000..c2ae795
--- /dev/null
+++ b/hald/linux/physdev.c
@@ -0,0 +1,1707 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * physdev.c : Handling of physical kernel devices 
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib.h>
+
+#include "../device_info.h"
+#include "../hald.h"
+#include "../logger.h"
+#include "../osspec.h"
+#include "../util.h"
+
+#include "coldplug.h"
+#include "hotplug.h"
+#include "hotplug_helper.h"
+#include "ids.h"
+#include "osspec_linux.h"
+
+#include "physdev.h"
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+pci_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	gint device_class;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "pci");
+	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");
+	}
+
+	hal_device_property_set_string (d, "pci.linux.sysfs_path", sysfs_path);
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_util_set_int_from_file (d, "pci.product_id", sysfs_path, "device", 16);
+	hal_util_set_int_from_file (d, "pci.vendor_id", sysfs_path, "vendor", 16);
+	hal_util_set_int_from_file (d, "pci.subsys_product_id", sysfs_path, "subsystem_device", 16);
+	hal_util_set_int_from_file (d, "pci.subsys_vendor_id", sysfs_path, "subsystem_vendor", 16);
+
+	if (hal_util_get_int_from_file (sysfs_path, "class", &device_class, 16)) {
+		hal_device_property_set_int (d, "pci.device_class", ((device_class >> 16) & 0xff));
+		hal_device_property_set_int (d, "pci.device_subclass", ((device_class >> 8) & 0xff));
+		hal_device_property_set_int (d, "pci.device_protocol", (device_class & 0xff));
+	}
+
+	{
+		gchar buf[64];
+		char *vendor_name;
+		char *product_name;
+		char *subsys_vendor_name;
+		char *subsys_product_name;
+
+		ids_find_pci (hal_device_property_get_int (d, "pci.vendor_id"), 
+			      hal_device_property_get_int (d, "pci.product_id"), 
+			      hal_device_property_get_int (d, "pci.subsys_vendor_id"), 
+			      hal_device_property_get_int (d, "pci.subsys_product_id"), 
+			      &vendor_name, &product_name, &subsys_vendor_name, &subsys_product_name);
+
+		if (vendor_name != NULL) {
+			hal_device_property_set_string (d, "pci.vendor", vendor_name);
+			hal_device_property_set_string (d, "info.vendor", vendor_name);
+		} else {
+			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+				    hal_device_property_get_int (d, "pci.vendor_id"));
+			hal_device_property_set_string (d, "pci.vendor", buf);
+			hal_device_property_set_string (d, "info.vendor", buf);
+		}
+
+		if (product_name != NULL) {
+			hal_device_property_set_string (d, "pci.product", product_name);
+			hal_device_property_set_string (d, "info.product", product_name);
+		} else {
+			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+				    hal_device_property_get_int (d, "pci.product_id"));
+			hal_device_property_set_string (d, "pci.product", buf);
+			hal_device_property_set_string (d, "info.product", buf);
+		}
+
+		if (subsys_vendor_name != NULL) {
+			hal_device_property_set_string (d, "pci.subsys_vendor", subsys_vendor_name);
+		} else {
+			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+				    hal_device_property_get_int (d, "pci.subsys_vendor_id"));
+			hal_device_property_set_string (d, "pci.subsys_vendor", buf);
+		}
+
+		if (subsys_product_name != NULL) {
+			hal_device_property_set_string (d, "pci.subsys_product", subsys_product_name);
+		} else {
+			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+				    hal_device_property_get_int (d, "pci.subsys_product_id"));
+			hal_device_property_set_string (d, "pci.subsys_product", buf);
+		}
+	}
+
+	return d;
+}
+
+static gboolean
+pci_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pci_%x_%x",
+			      hal_device_property_get_int (d, "pci.vendor_id"),
+			      hal_device_property_get_int (d, "pci.product_id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static void 
+usbif_set_name (HalDevice *d, int ifclass, int ifsubclass, int ifprotocol)
+{
+	const char *name;
+
+	switch (ifclass) {
+	default:
+	case 0x00:
+		name = "USB Interface";
+		break;
+	case 0x01:
+		name = "USB Audio Interface";
+		break;
+	case 0x02:
+		name = "USB Communications Interface";
+		break;
+	case 0x03:
+		name = "USB HID Interface";
+		break;
+	case 0x06:
+		name = "USB Imaging Interface";
+		break;
+	case 0x07:
+		name = "USB Printer Interface";
+		break;
+	case 0x08:
+		name = "USB Mass Storage Interface";
+		break;
+	case 0x09:
+		name = "USB Hub Interface";
+		break;
+	case 0x0a:
+		name = "USB Data Interface";
+		break;
+	case 0x0b:
+		name = "USB Chip/Smartcard Interface";
+		break;
+	case 0x0d:
+		name = "USB Content Security Interface";
+		break;
+	case 0x0e:
+		name = "USB Video Interface";
+		break;
+	case 0xdc:
+		name = "USB Diagnostic Interface";
+		break;
+	case 0xe0:
+		name = "USB Wireless Interface";
+		break;
+	case 0xef:
+		name = "USB Miscelleneous Interface";
+		break;
+	case 0xfe:
+		name = "USB Application Specific Interface";
+		break;
+	case 0xff:
+		name = "USB Vendor Specific Interface";
+		break;
+	}
+
+	hal_device_property_set_string (d, "usb.product", name);
+	hal_device_property_set_string (d, "info.product", name);
+}
+
+static HalDevice *
+usb_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	if (parent != NULL) {
+		hal_device_property_set_string (d, "info.parent", parent->udi);
+	}
+
+	/* only USB interfaces got a : in the bus_id */
+	bus_id = hal_util_get_last_element (sysfs_path);
+	if (strchr (bus_id, ':') == NULL) {
+		gint bmAttributes;
+
+		hal_device_property_set_string (d, "info.bus", "usb_device");
+
+		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+		hal_device_property_set_string (d, "usb_device.linux.sysfs_path", sysfs_path);
+
+		hal_util_set_int_from_file (d, "usb_device.configuration_value", sysfs_path, "bConfigurationValue", 10);
+		hal_util_set_int_from_file (d, "usb_device.num_configurations", sysfs_path, "bNumConfigurations", 10);
+		hal_util_set_int_from_file (d, "usb_device.num_interfaces", sysfs_path, "bNumInterfaces", 10);
+
+		hal_util_set_int_from_file (d, "usb_device.device_class", sysfs_path, "bDeviceClass", 16);
+		hal_util_set_int_from_file (d, "usb_device.device_subclass", sysfs_path, "bDeviceSubClass", 16);
+		hal_util_set_int_from_file (d, "usb_device.device_protocol", sysfs_path, "bDeviceProtocol", 16);
+
+		hal_util_set_int_from_file (d, "usb_device.vendor_id", sysfs_path, "idVendor", 16);
+		hal_util_set_int_from_file (d, "usb_device.product_id", sysfs_path, "idProduct", 16);
+
+		{
+			gchar buf[64];
+			char *vendor_name;
+			char *product_name;
+
+			ids_find_usb (hal_device_property_get_int (d, "usb_device.vendor_id"), 
+				      hal_device_property_get_int (d, "usb_device.product_id"), 
+				      &vendor_name, &product_name);
+
+			if (vendor_name != NULL) {
+				hal_device_property_set_string (d, "usb_device.vendor", vendor_name);
+			} else {
+				if (!hal_util_set_string_from_file (d, "usb_device.vendor", 
+								    sysfs_path, "manufacturer")) {
+					g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+						    hal_device_property_get_int (d, "usb_device.vendor_id"));
+					hal_device_property_set_string (d, "usb_device.vendor", buf); 
+				}
+			}
+			hal_device_property_set_string (d, "info.vendor",
+							hal_device_property_get_string (d, "usb_device.vendor"));
+
+			if (product_name != NULL) {
+				hal_device_property_set_string (d, "usb_device.product", product_name);
+			} else {
+				if (!hal_util_set_string_from_file (d, "usb_device.product", 
+								    sysfs_path, "product")) {
+					g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
+						    hal_device_property_get_int (d, "usb_device.product_id"));
+					hal_device_property_set_string (d, "usb_device.product", buf); 
+				}
+			}
+			hal_device_property_set_string (d, "info.product",
+							hal_device_property_get_string (d, "usb_device.product"));
+		}
+
+		hal_util_set_int_from_file (d, "usb_device.device_revision_bcd", sysfs_path, "bcdDevice", 16);
+
+		hal_util_set_int_from_file (d, "usb_device.max_power", sysfs_path, "bMaxPower", 10);
+		hal_util_set_int_from_file (d, "usb_device.num_ports", sysfs_path, "maxchild", 10);
+		hal_util_set_int_from_file (d, "usb_device.linux.device_number", sysfs_path, "devnum", 10);
+
+		hal_util_set_string_from_file (d, "usb_device.serial", sysfs_path, "serial");
+
+		hal_util_set_string_from_file (d, "usb_device.serial", sysfs_path, "serial");
+		hal_util_set_bcd2_from_file (d, "usb_device.speed_bcd", sysfs_path, "speed");
+		hal_util_set_bcd2_from_file (d, "usb_device.version_bcd", sysfs_path, "version");
+
+		hal_util_get_int_from_file (sysfs_path, "bmAttributes", &bmAttributes, 16);
+		hal_device_property_set_bool (d, "usb_device.is_self_powered", (bmAttributes & 0x40) != 0);
+		hal_device_property_set_bool (d, "usb_device.can_wake_up", (bmAttributes & 0x20) != 0);
+
+		if (strncmp (bus_id, "usb", 3) == 0)
+			hal_device_property_set_int (d, "usb_device.bus_number", atoi (bus_id + 3));
+		else
+			hal_device_property_set_int (d, "usb_device.bus_number", atoi (bus_id));
+
+		/* TODO:  .level_number .parent_number  */
+
+	} else {
+		hal_device_property_set_string (d, "info.bus", "usb");
+
+		/* take all usb_device.* properties from parent and make them usb.* on this object */
+		if (parent != NULL)
+			hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
+
+		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+		hal_device_property_set_string (d, "usb.linux.sysfs_path", sysfs_path);
+
+		hal_util_set_int_from_file (d, "usb.interface.number", sysfs_path, "bInterfaceNumber", 10);
+
+		hal_util_set_int_from_file (d, "usb.interface.class", sysfs_path, "bInterfaceClass", 16);
+		hal_util_set_int_from_file (d, "usb.interface.subclass", sysfs_path, "bInterfaceSubClass", 16);
+		hal_util_set_int_from_file (d, "usb.interface.protocol", sysfs_path, "bInterfaceProtocol", 16);
+
+		usbif_set_name (d, 
+				hal_device_property_get_int (d, "usb.interface.class"),
+				hal_device_property_get_int (d, "usb.interface.subclass"),
+				hal_device_property_get_int (d, "usb.interface.protocol"));
+	}
+
+	return d;
+}
+
+static gboolean
+usb_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	if (hal_device_has_property (d, "usb.interface.number")) {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "%s_if%d",
+				      hal_device_property_get_string (d, "info.parent"),
+				      hal_device_property_get_int (d, "usb.interface.number"));
+		hal_device_set_udi (d, udi);
+		hal_device_property_set_string (d, "info.udi", udi);
+	} else {
+		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+				      "/org/freedesktop/Hal/devices/usb_device_%x_%x_%s",
+				      hal_device_property_get_int (d, "usb_device.vendor_id"),
+				      hal_device_property_get_int (d, "usb_device.product_id"),
+				      hal_device_has_property (d, "usb_device.serial") ?
+				        hal_device_property_get_string (d, "usb_device.serial") :
+				        "noserial");
+		hal_device_set_udi (d, udi);
+		hal_device_property_set_string (d, "info.udi", udi);
+	}
+
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+ide_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	guint host, channel;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "ide");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	sscanf (bus_id, "%d.%d", &host, &channel);
+	hal_device_property_set_int (d, "ide.host", host);
+	hal_device_property_set_int (d, "ide.channel", channel);
+
+	if (channel == 0) {
+		hal_device_property_set_string (d, "info.product", "IDE device (master)");
+	} else {
+		hal_device_property_set_string (d, "info.product", "IDE device (slave)");
+	}
+	
+	return d;
+}
+
+static gboolean
+ide_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_ide_%d_%d",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_int (d, "ide.host"),
+			      hal_device_property_get_int (d, "ide.channel"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+pnp_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "pnp");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_util_set_string_from_file (d, "pnp.id", sysfs_path, "id");
+	if (hal_device_has_property (d, "pnp.id")) {
+		gchar *pnp_description;
+		ids_find_pnp (hal_device_property_get_string (d, "pnp.id"), &pnp_description);
+		if (pnp_description != NULL) {
+			hal_device_property_set_string (d, "pnp.description", pnp_description);
+			hal_device_property_set_string (d, "info.product", pnp_description);
+		}
+	}
+
+	if (!hal_device_has_property (d, "info.product")) {
+		gchar buf[64];
+		g_snprintf (buf, sizeof (buf), "PnP Device (%s)", hal_device_property_get_string (d, "pnp.id"));
+		hal_device_property_set_string (d, "info.product", buf);
+	}
+
+	
+	return d;
+}
+
+static gboolean
+pnp_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pnp_%s",
+			      hal_device_property_get_string (d, "pnp.id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+platform_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *dev_id;
+	gchar buf[64];
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "platform");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	dev_id = hal_util_get_last_element (sysfs_path);
+
+	hal_device_property_set_string (d, "platform.id", dev_id);
+
+	g_snprintf (buf, sizeof (buf), "Platform Device (%s)", hal_device_property_get_string (d, "platform.id"));
+	hal_device_property_set_string (d, "info.product", buf);
+
+	return d;
+}
+
+static gboolean
+platform_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/platform_%s",
+			      hal_device_property_get_string (d, "platform.id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+serio_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "serio");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+	hal_device_property_set_string (d, "serio.id", bus_id);
+	if (!hal_util_set_string_from_file (d, "serio.description", sysfs_path, "description")) {
+		hal_device_property_set_string (d, "serio.description", hal_device_property_get_string (d, "serio.id"));
+	}
+	hal_device_property_set_string (d, "info.product", hal_device_property_get_string (d, "serio.description"));
+	
+	return d;
+}
+
+static gboolean
+serio_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_%s",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_string (d, "serio.description"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+pcmcia_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	guint socket, function;
+	const char *prod_id1;
+	const char *prod_id2;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "pcmcia");
+	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");
+	}
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	/* not sure if %d.%d means socket function - need to revisit */
+	sscanf (bus_id, "%d.%d", &socket, &function);
+	hal_device_property_set_int (d, "pcmcia.socket_number", socket);
+
+	hal_util_set_string_from_file (d, "pcmcia.prod_id1", sysfs_path, "prod_id1");
+	hal_util_set_string_from_file (d, "pcmcia.prod_id2", sysfs_path, "prod_id2");
+	hal_util_set_string_from_file (d, "pcmcia.prod_id3", sysfs_path, "prod_id3");
+	hal_util_set_string_from_file (d, "pcmcia.prod_id4", sysfs_path, "prod_id4");
+
+	hal_util_set_int_from_file (d, "pcmcia.manf_id", sysfs_path, "manf_id", 16);
+	hal_util_set_int_from_file (d, "pcmcia.card_id", sysfs_path, "card_id", 16);
+	hal_util_set_int_from_file (d, "pcmcia.func_id", sysfs_path, "func_id", 16);
+
+	prod_id1 = hal_device_property_get_string (d, "pcmcia.prod_id1");
+	prod_id2 = hal_device_property_get_string (d, "pcmcia.prod_id2");
+
+	/* Provide best-guess of vendor, goes in Vendor property */
+	if (prod_id1 != NULL) {
+		hal_device_property_set_string (d, "info.vendor", prod_id1);
+	} else {
+		char buf[50];
+		g_snprintf (buf, sizeof(buf), "Unknown (0x%04x)", hal_device_property_get_int (d, "pcmcia.manf_id"));
+		hal_device_property_set_string (d, "info.vendor", buf);
+	}
+
+	/* Provide best-guess of name, goes in Product property */
+	if (prod_id2 != NULL) {
+		hal_device_property_set_string (d, "info.product", prod_id2);
+	} else {
+		char buf[50];
+		g_snprintf (buf, sizeof(buf), "Unknown (0x%04x)", hal_device_property_get_int (d, "pcmcia.card_id"));
+		hal_device_property_set_string (d, "info.product", buf);
+	}
+
+	return d;
+}
+
+static gboolean
+pcmcia_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pcmcia_%d_%d",
+			      hal_device_property_get_int (d, "pcmcia.manfid1"),
+			      hal_device_property_get_int (d, "pcmcia.manfid2"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+scsi_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	gint host_num, bus_num, target_num, lun_num;
+	int type;
+
+	if (parent == NULL) {
+		d = NULL;
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "scsi");
+	hal_device_property_set_string (d, "info.parent", parent->udi);
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+	sscanf (bus_id, "%d:%d:%d:%d", &host_num, &bus_num, &target_num, &lun_num);
+	hal_device_property_set_int (d, "scsi.host", host_num);
+	hal_device_property_set_int (d, "scsi.bus", bus_num);
+	hal_device_property_set_int (d, "scsi.target", target_num);
+	hal_device_property_set_int (d, "scsi.lun", lun_num);
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_string (d, "info.product", "SCSI Device");
+
+	hal_util_set_string_from_file (d, "scsi.model", sysfs_path, "model");
+	hal_util_set_string_from_file (d, "scsi.vendor", sysfs_path, "vendor");
+	hal_util_get_int_from_file (sysfs_path, "type", &type, 0);
+	HAL_INFO (("%s/type -> %d (-> scsi.type)", sysfs_path, type));
+	switch (type) {
+	case 0:  /* TYPE_DISK (disk) */
+	case 7:  /* TYPE_MOD (Magneto-optical disk) */
+	case 14: /* TYPE_RBC (Reduced Block Commands)
+		  * Simple Direct Access Device, set it to disk
+		  * (some Firewire Disks use it)
+		  */
+		hal_device_property_set_string (d, "scsi.type", "disk");
+		break;
+	case 1: /* TYPE_TAPE (Tape) */
+		hal_device_property_set_string (d, "scsi.type", "tape");
+		break;
+	case 2:
+		/* TYPE_PRINTER (Tape) */
+		hal_device_property_set_string (d, "scsi.type", "printer");
+		break;
+	case 3:  /* TYPE_PROCESSOR */
+		hal_device_property_set_string (d, "scsi.type", "processor");
+		break;
+	case 4: /* TYPE_WORM */
+	case 5: /* TYPE_ROM (CD-ROM) */
+		hal_device_property_set_string (d, "scsi.type", "cdrom");
+		break;
+	case 6: /* TYPE_SCANNER */
+		hal_device_property_set_string (d, "scsi.type", "scanner");
+		break;
+	case 8: /* TYPE_MEDIUM_CHANGER */
+		hal_device_property_set_string (d, "scsi.type", "medium_changer");
+		break;
+	case 9: /* TYPE_COMM */
+		hal_device_property_set_string (d, "scsi.type", "comm");
+		break;
+	case 12: /* TYPE_RAID */
+		hal_device_property_set_string (d, "scsi.type", "raid");
+		break;
+	default:
+		hal_device_property_set_string (d, "scsi.type", "unknown");
+	}
+
+out:
+	return d;
+}
+
+static gboolean
+scsi_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_scsi_device_lun%d",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_int (d, "scsi.lun"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+mmc_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	gint host_num, rca, manfid, oemid;
+	gchar *scr;
+
+	if (parent == NULL) {
+		d = NULL;
+		goto out;
+	}
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "mmc");
+	hal_device_property_set_string (d, "info.parent", parent->udi);
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+	sscanf (bus_id, "mmc%d:%x", &host_num, &rca);
+	hal_device_property_set_int (d, "mmc.rca", rca);
+	
+	hal_util_set_string_from_file (d, "mmc.cid", sysfs_path, "cid");
+	hal_util_set_string_from_file (d, "mmc.csd", sysfs_path, "csd");
+	
+	scr = hal_util_get_string_from_file (sysfs_path, "scr");
+	if (scr != NULL) {
+		if (strcmp (scr, "0000000000000000") == 0)
+			scr = NULL;
+		else
+			hal_device_property_set_string (d, "mmc.scr", scr);
+	}
+
+	if (!hal_util_set_string_from_file (d, "info.product", sysfs_path, "name")) {
+		if (scr != NULL)
+			hal_device_property_set_string (d, "info.product", "SD Card");
+		else
+			hal_device_property_set_string (d, "info.product", "MMC Card");
+	}
+	
+	if (hal_util_get_int_from_file (sysfs_path, "manfid", &manfid, 16)) {
+		/* Here we should have a mapping to a name */
+		char vendor[256];
+		snprintf(vendor, 256, "Unknown (%d)", manfid);
+		hal_device_property_set_string (d, "info.vendor", vendor);
+	}
+	if (hal_util_get_int_from_file (sysfs_path, "oemid", &oemid, 16)) {
+		/* Here we should have a mapping to a name */
+		char oem[256];
+		snprintf(oem, 256, "Unknown (%d)", oemid);
+		hal_device_property_set_string (d, "mmc.oem", oem);
+	}
+
+	hal_util_set_string_from_file (d, "mmc.date", sysfs_path, "date");
+	hal_util_set_int_from_file (d, "mmc.hwrev", sysfs_path, "hwrev", 16);
+	hal_util_set_int_from_file (d, "mmc.fwrev", sysfs_path, "fwrev", 16);
+	hal_util_set_int_from_file (d, "mmc.serial", sysfs_path, "serial", 16);
+
+out:
+	return d;
+}
+
+static gboolean
+mmc_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "%s_mmc_card_rca%d",
+			      hal_device_property_get_string (d, "info.parent"),
+			      hal_device_property_get_int (d, "mmc.rca"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+xen_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *devtype;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "xen");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_string (d, "xen.bus_id",
+					hal_util_get_last_element (sysfs_path));
+
+	hal_util_set_string_from_file (d, "xen.path", sysfs_path, "nodename");
+
+	devtype = hal_util_get_string_from_file (sysfs_path, "devtype");
+	hal_device_property_set_string (d, "xen.type", devtype);
+
+	if (strcmp (devtype, "pci") == 0) {
+		hal_device_property_set_string (d, "info.product", "Xen PCI Device");
+	} else if (strcmp (devtype, "vbd") == 0) {
+		hal_device_property_set_string (d, "info.product", "Xen Virtual Block Device");
+	} else if (strcmp (devtype, "vif") == 0) {
+		hal_device_property_set_string (d, "info.product", "Xen Virtual Network Device");
+	} else if (strcmp (devtype, "vtpm") == 0) {
+		hal_device_property_set_string (d, "info.product", "Xen Virtual Trusted Platform Module");
+	} else {
+		char buf[64];
+		g_snprintf (buf, sizeof (buf), "Xen Device (%s)", devtype);
+		hal_device_property_set_string (d, "info.product", buf);
+	}
+
+	return d;
+}
+
+static gboolean
+xen_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/xen_%s",
+			      hal_device_property_get_string (d, "xen.bus_id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+ieee1394_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	long long unsigned int guid;
+	gint host_id;
+	const gchar *bus_id;
+	gchar buf[64];
+
+	d = NULL;
+
+	if (parent == NULL)
+		goto out;
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	if (sscanf (bus_id, "fw-host%d", &host_id) == 1)
+		goto out;
+
+	if (sscanf (bus_id, "%llx-%d", &guid, &host_id) !=2 )
+		goto out;
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "ieee1394");
+	hal_device_property_set_string (d, "info.parent", parent->udi);
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_uint64 (d, "ieee1394.guid", guid);
+	hal_util_set_int_from_file    (d, "ieee1394.vendor_id", sysfs_path, "../vendor_id", 16);
+	hal_util_set_int_from_file    (d, "ieee1394.specifier_id", sysfs_path, "specifier_id", 16);
+	hal_util_set_int_from_file    (d, "ieee1394.version", sysfs_path, "version", 16);
+
+	if (!hal_util_set_string_from_file (d, "ieee1394.vendor", sysfs_path, "../vendor_oui")) {
+		g_snprintf (buf, sizeof (buf), "Unknown (0x%06x)", 
+			    hal_device_property_get_int (d, "ieee1394.vendor_id"));
+		hal_device_property_set_string (d, "ieee1394.vendor", buf);
+	}
+
+	/* not all devices have product_id */
+	if (hal_util_set_int_from_file    (d, "ieee1394.product_id", sysfs_path, "model_id", 16)) {
+		if (!hal_util_set_string_from_file (d, "ieee1394.product", sysfs_path, "model_name_kv")) {
+			g_snprintf (buf, sizeof (buf), "Unknown (0x%06x)", 
+				    hal_device_property_get_int (d, "ieee1394.product_id"));
+			hal_device_property_set_string (d, "ieee1394.product", buf);
+		}
+	} else {
+		hal_device_property_set_int (d, "ieee1394.product_id", 0x000000);
+		hal_device_property_set_string (d, "ieee1394.product",
+						hal_device_property_get_string (d, "ieee1394.vendor"));
+	}
+		
+	hal_device_property_set_string (d, "info.vendor",
+					hal_device_property_get_string (d, "ieee1394.vendor"));
+	hal_device_property_set_string (d, "info.product",
+					hal_device_property_get_string (d, "ieee1394.product"));
+
+out:
+	return d;
+}
+
+static gboolean
+ieee1394_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/ieee1394_guid_%0llx",
+			      hal_device_property_get_uint64 (d, "ieee1394.guid"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static inline void
+ccw_add_dasd_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	const gchar *disc;
+	
+	hal_util_set_int_from_file (d, "ccw.dasd.use_diag", sysfs_path,
+				    "use_diag", 2);
+	hal_util_set_int_from_file (d, "ccw.dasd.readonly", sysfs_path,
+				    "readonly", 2);
+	disc = hal_util_get_string_from_file (sysfs_path, "discipline");
+	if (disc)
+		hal_device_property_set_string(d, "ccw.dasd.discipline", disc);
+}
+
+static inline void
+ccw_add_zfcp_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	int online;
+
+	/* zfcp adapter properties are only valid for online devices. */
+	if (!hal_util_get_int_from_file (sysfs_path, "online", &online, 2))
+		return;
+	if (!online)
+		return;
+
+	hal_util_set_int_from_file (d, "ccw.zfcp.in_recovery", sysfs_path,
+				    "in_recovery", 2);
+	hal_util_set_int_from_file (d, "ccw.zfcp.failed", sysfs_path,
+				    "failed", 2);
+}
+
+static inline void
+ccw_add_tape_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	int medium_state, online;
+
+	const gchar *state_text[3] = {"unknown", "loaded", "no medium"};
+
+	hal_util_set_string_from_file (d, "ccw.tape.state", sysfs_path, "state");
+	hal_util_set_string_from_file (d, "ccw.tape.operation", sysfs_path,
+				       "operation");
+	/* The following properties are only valid for online devices. */
+	if (!hal_util_get_int_from_file (sysfs_path, "online", &online, 2))
+		return;
+	if (!online)
+		return;
+	hal_util_set_int_from_file (d, "ccw.tape.blocksize", sysfs_path,
+				    "blocksize", 10);
+	if (!hal_util_get_int_from_file (sysfs_path, "medium_state",
+					&medium_state, 10))
+		return;
+	hal_device_property_set_string (d, "ccw.tape.medium_state",
+					state_text[medium_state]);
+}
+
+static inline void
+ccw_add_3270_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	hal_util_set_int_from_file (d, "ccw.3270.model", sysfs_path,
+				    "model", 10);
+	hal_util_set_int_from_file (d, "ccw.3270.rows", sysfs_path, "rows", 10);
+	hal_util_set_int_from_file (d, "ccw.3270.columns", sysfs_path,
+				    "columns", 10);
+}
+
+static HalDevice *
+ccw_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	const gchar *pimpampom;
+	int pim, pam, pom;
+	const gchar *chpids;
+	int chpid[8];
+	gchar attr[25];
+	int i;
+	gchar driver_name[256];
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device",
+					sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "ccw");
+	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");
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_string (d, "ccw.bus_id", bus_id);
+	hal_util_set_int_from_file (d, "ccw.online", sysfs_path, "online", 2);
+	hal_util_set_string_from_file (d, "ccw.availablity", sysfs_path,
+				       "availability");
+	hal_util_set_int_from_file (d, "ccw.cmb_enable", sysfs_path,
+				    "cmb_enable", 2);
+	hal_util_set_string_from_file (d, "ccw.cutype", sysfs_path, "cutype");
+	hal_util_set_string_from_file (d, "ccw.devtype", sysfs_path, "devtype");
+
+	/* Get some values from the higher level subchannel structure.*/
+	pimpampom = hal_util_get_string_from_file (sysfs_path, "../pimpampom");
+	if (pimpampom) {
+		sscanf (pimpampom, "%x %x %x", &pim, &pam, &pom);
+		hal_device_property_set_int (d, "ccw.subchannel.pim", pim);
+		hal_device_property_set_int (d, "ccw.subchannel.pam", pam);
+		hal_device_property_set_int (d, "ccw.subchannel.pom", pom);
+	}
+
+	chpids = hal_util_get_string_from_file (sysfs_path, "../chpids");
+	if (chpids) {
+		sscanf (chpids, "%x %x %x %x %x %x %x %x", &chpid[0], &chpid[1],
+			&chpid[2], &chpid[3], &chpid[4], &chpid[5], &chpid[6],
+			&chpid[7]);
+		for (i=0; i<8 && (chpid[i] != 0); i++) {
+			g_snprintf (attr, sizeof (attr),
+				    "ccw.subchannel.chpid%x", i);
+			hal_device_property_set_int (d, attr, chpid[i]);
+		}
+	}
+
+	/* Add some special properties. */
+	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
+		if (!strncmp (driver_name, "dasd", 4))
+			/* Same attributes for dasd_eckd and dasd_fba. */
+			ccw_add_dasd_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "zfcp", 4))
+			ccw_add_zfcp_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "tape_3", 6))
+			/* For all channel attached tapes. */
+			ccw_add_tape_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "3270", 4))
+			ccw_add_3270_properties (d, sysfs_path);
+	}
+	return d;
+}
+
+static gboolean
+ccw_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/ccw_%s",
+			      hal_device_property_get_string
+			      (d, "ccw.bus_id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static inline void
+ccwgroup_add_qeth_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	int is_layer2;
+
+	/* Some attributes are not applicable for devices in layer2 mode. */
+	hal_util_get_int_from_file (sysfs_path, "layer2", &is_layer2, 2);
+
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.large_send",
+				       sysfs_path, "large_send");
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.card_type", sysfs_path,
+				       "card_type");
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.checksumming",
+				       sysfs_path, "checksumming");
+	if (!is_layer2) {
+		//CH: the next two are only valid for token ring devices
+		hal_util_set_int_from_file (d,
+					    "ccwgroup.qeth.canonical_macaddr",
+					    sysfs_path, "canonical_macaddr", 2);
+		hal_util_set_string_from_file (d,
+					       "ccwgroup.qeth.broadcast_mode",
+					       sysfs_path, "broadcast_mode");
+		hal_util_set_int_from_file (d, "ccwgroup.qeth.fake_broadcast",
+					    sysfs_path, "fake_broadcast", 2);
+		hal_util_set_int_from_file (d, "ccwgroup.qeth.fake_ll",
+					    sysfs_path, "fake_ll", 2);
+	}
+	hal_device_property_set_int (d, "ccwgroup.qeth.layer2", is_layer2);
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.portname", sysfs_path,
+				       "portname");
+	hal_util_set_int_from_file (d, "ccwgroup.qeth.portno", sysfs_path,
+				    "portno", 10);
+	hal_util_set_int_from_file (d, "ccwgroup.qeth.buffer_count", sysfs_path,
+				    "buffer_count", 10);
+	hal_util_set_int_from_file (d, "ccwgroup.qeth.add_hhlen", sysfs_path,
+				    "add_hhlen", 10);
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.priority_queueing",
+				       sysfs_path, "priority_queueing");
+	if (!is_layer2) {
+		hal_util_set_string_from_file (d, "ccwgroup.qeth.route4",
+					       sysfs_path, "route4");
+		hal_util_set_string_from_file (d, "ccwgroup.qeth.route6",
+					       sysfs_path, "route6");
+	}
+	hal_util_set_string_from_file (d, "ccwgroup.qeth.state", sysfs_path,
+				       "state");
+}
+
+static inline void
+ccwgroup_add_ctc_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	//CH: use protocol descriptions?
+	hal_util_set_int_from_file (d, "ccwgroup.ctc.protocol", sysfs_path,
+				    "protocol", 2);
+	hal_util_set_string_from_file (d, "ccwgroup.ctc.type", sysfs_path,
+				       "type");
+	hal_util_set_int_from_file (d, "ccwgroup.ctc.buffer", sysfs_path,
+				    "buffer", 10);
+}
+
+static inline void
+ccwgroup_add_lcs_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	hal_util_set_int_from_file (d, "ccwgroup.lcs.portnumber", sysfs_path,
+				    "portno", 10);
+	hal_util_set_string_from_file (d, "ccwgroup.lcs.type", sysfs_path,
+				       "type");
+	hal_util_set_int_from_file (d, "ccwgroup.lcs.lancmd_timeout",
+				    sysfs_path, "lancmd_timeout", 10);
+}
+
+static inline void
+ccwgroup_add_claw_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	hal_util_set_string_from_file (d, "ccwgroup.claw.api_type", sysfs_path,
+				       "api_type");
+	hal_util_set_string_from_file (d, "ccwgroup.claw.adapter_name",
+				       sysfs_path, "adapter_name");
+	hal_util_set_string_from_file (d, "ccwgroup.claw.host_name", sysfs_path,
+				       "host_name");
+	hal_util_set_int_from_file (d, "ccwgroup.claw.read_buffer", sysfs_path,
+				    "read_buffer", 10);
+	hal_util_set_int_from_file (d, "ccwgroup.claw.write_buffer", sysfs_path,
+				    "write_buffer", 10);
+}
+
+static HalDevice *
+ccwgroup_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	gchar driver_name[256];
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device",
+					sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "ccwgroup");
+	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");
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_string (d, "ccwgroup.bus_id", bus_id);
+	hal_util_set_int_from_file (d, "ccwgroup.online", sysfs_path,
+				    "online", 2);
+
+	/* Some devices have extra properties. */
+	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
+		if (!strncmp (driver_name, "qeth", 4))
+			ccwgroup_add_qeth_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "ctc", 3))
+			ccwgroup_add_ctc_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "lcs", 3))
+			ccwgroup_add_lcs_properties (d, sysfs_path);
+		if (!strncmp (driver_name, "claw", 4))
+			ccwgroup_add_claw_properties (d, sysfs_path);
+	}
+	return d;
+}
+
+static gboolean
+ccwgroup_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/ccwgroup_%s",
+			      hal_device_property_get_string
+			      (d, "ccwgroup.bus_id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static inline void
+iucv_add_netiucv_properties (HalDevice *d, const gchar *sysfs_path)
+{
+	hal_util_set_string_from_file (d, "iucv.netiucv.user", sysfs_path,
+				       "user");
+	hal_util_set_int_from_file (d, "iucv.netiucv.buffer", sysfs_path,
+				    "buffer", 10);
+}
+
+static HalDevice *
+iucv_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *bus_id;
+	gchar driver_name[256];
+
+	bus_id = hal_util_get_last_element (sysfs_path);
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device",
+					sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "iucv");
+	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");
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	hal_device_property_set_string (d, "iucv.bus_id", bus_id);
+
+	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
+		if (!strncmp (driver_name, "netiucv", 7))
+			iucv_add_netiucv_properties (d, sysfs_path);
+	}
+	return d;
+}
+
+static gboolean
+iucv_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/iucv_%s",
+			      hal_device_property_get_string
+			      (d, "iucv.bus_id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static HalDevice *
+pseudo_add (const gchar *sysfs_path, HalDevice *parent)
+{
+	HalDevice *d;
+	const gchar *dev_id;
+	gchar buf[64];
+
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
+	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
+	hal_device_property_set_string (d, "info.bus", "pseudo");
+	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");
+	}
+
+	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
+
+	dev_id = hal_util_get_last_element (sysfs_path);
+	hal_device_property_set_string (d, "pseudo.id", dev_id);
+
+	g_snprintf (buf, sizeof (buf), "SCSI Debug Device (%s)", hal_device_property_get_string (d, "pseudo.id"));
+	hal_device_property_set_string (d, "info.product", buf);
+
+	return d;
+}
+
+static gboolean
+pseudo_compute_udi (HalDevice *d)
+{
+	gchar udi[256];
+
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pseudo",
+			      hal_device_property_get_string (d, "platform.id"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+
+	return TRUE;
+
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static gboolean
+physdev_remove (HalDevice *d)
+{
+	return TRUE;
+}
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+typedef struct
+{
+	const gchar *subsystem;
+	HalDevice *(*add) (const gchar *sysfs_path, HalDevice *parent);
+	gboolean (*compute_udi) (HalDevice *d);
+	gboolean (*remove) (HalDevice *d);
+} PhysDevHandler;
+
+static PhysDevHandler physdev_handler_pci = { 
+	.subsystem   = "pci",
+	.add         = pci_add,
+	.compute_udi = pci_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_usb = { 
+	.subsystem   = "usb",
+	.add         = usb_add,
+	.compute_udi = usb_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_ide = { 
+	.subsystem   = "ide",
+	.add         = ide_add,
+	.compute_udi = ide_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_pnp = { 
+	.subsystem   = "pnp",
+	.add         = pnp_add,
+	.compute_udi = pnp_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_platform = {
+	.subsystem   = "platform",
+	.add         = platform_add,
+	.compute_udi = platform_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_serio = { 
+	.subsystem   = "serio",
+	.add         = serio_add,
+	.compute_udi = serio_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_pcmcia = { 
+	.subsystem   = "pcmcia",
+	.add         = pcmcia_add,
+	.compute_udi = pcmcia_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_scsi = { 
+	.subsystem   = "scsi",
+	.add         = scsi_add,
+	.compute_udi = scsi_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_mmc = { 
+	.subsystem   = "mmc",
+	.add         = mmc_add,
+	.compute_udi = mmc_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_ieee1394 = { 
+	.subsystem   = "ieee1394",
+	.add         = ieee1394_add,
+	.compute_udi = ieee1394_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_xen = {
+	.subsystem   = "xen",
+	.add         = xen_add,
+	.compute_udi = xen_compute_udi,
+	.remove      = physdev_remove
+};
+
+/* s390 specific busses */
+static PhysDevHandler physdev_handler_ccw = {
+	.subsystem   = "ccw",
+	.add         = ccw_add,
+	.compute_udi = ccw_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_ccwgroup = {
+	.subsystem   = "ccwgroup",
+	.add         = ccwgroup_add,
+	.compute_udi = ccwgroup_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler physdev_handler_iucv = {
+	.subsystem   = "iucv",
+	.add         = iucv_add,
+	.compute_udi = iucv_compute_udi,
+	.remove      = physdev_remove
+};
+
+/* SCSI debug, to test thousends of fake devices */
+static PhysDevHandler physdev_handler_pseudo = {
+	.subsystem   = "pseudo",
+	.add         = pseudo_add,
+	.compute_udi = pseudo_compute_udi,
+	.remove      = physdev_remove
+};
+
+static PhysDevHandler *phys_handlers[] = {
+	&physdev_handler_pci,
+	&physdev_handler_usb,
+	&physdev_handler_ide,
+	&physdev_handler_pnp,
+	&physdev_handler_platform,
+	&physdev_handler_serio,
+	&physdev_handler_pcmcia,
+	&physdev_handler_scsi,
+	&physdev_handler_mmc,
+	&physdev_handler_ieee1394,
+	&physdev_handler_xen,
+	&physdev_handler_ccw,
+	&physdev_handler_ccwgroup,
+	&physdev_handler_iucv,
+	&physdev_handler_pseudo,
+	NULL
+};
+
+/*--------------------------------------------------------------------------------------------------------------*/
+
+static void 
+physdev_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 
+physdev_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"));
+	}
+	g_object_unref (d);
+
+	hotplug_event_end (end_token);
+}
+
+
+static void 
+physdev_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
+{
+	void *end_token = (void *) userdata1;
+	PhysDevHandler *handler = (PhysDevHandler *) userdata2;
+
+	if (hal_device_property_get_bool (d, "info.ignore")) {
+		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
+		 * Also remove category and all capabilities
+		 */
+		hal_device_property_remove (d, "info.category");
+		hal_device_property_remove (d, "info.capabilities");
+		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
+		hal_device_property_set_string (d, "info.product", "Ignored Device");
+		
+		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
+		
+		/* 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);
+		goto out;
+	}
+	
+	
+	/* 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)) {
+		hal_device_store_remove (hald_get_tdl (), d);
+		g_object_unref (d);
+		hotplug_event_end (end_token);
+		goto out;
+	}
+	
+	/* Run callouts */
+	hal_util_callout_device_add (d, physdev_callouts_add_done, end_token, NULL);
+
+out:
+	;
+}
+
+void
+hotplug_event_begin_add_physdev (const gchar *subsystem, const gchar *sysfs_path, HalDevice *parent, void *end_token)
+{
+	guint i;
+
+	HAL_INFO (("phys_add: subsys=%s sysfs_path=%s, parent=0x%08x", subsystem, sysfs_path, parent));
+
+	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
+		HAL_INFO (("Ignoring phys_add since parent has info.ignore==TRUE"));
+		hotplug_event_end (end_token);
+		goto out;
+	}
+
+	for (i = 0; phys_handlers [i] != NULL; i++) {
+		PhysDevHandler *handler;
+
+		handler = phys_handlers[i];
+		if (strcmp (handler->subsystem, subsystem) == 0) {
+			HalDevice *d;
+
+			d = handler->add (sysfs_path, parent);
+			if (d == NULL) {
+				/* didn't find anything - thus, ignore this hotplug event */
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_BUS);
+			hal_device_property_set_string (d, "linux.subsystem", subsystem);
+
+			/* Add to temporary device store */
+			hal_device_store_add (hald_get_tdl (), d);
+
+			/* Process preprobe fdi files */
+			di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
+
+			/* Run preprobe callouts */
+			hal_util_callout_device_preprobe (d, physdev_callouts_preprobing_done, end_token, handler);
+			goto out;
+		}
+	}
+	
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out:
+	;
+}
+
+void
+hotplug_event_begin_remove_physdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token)
+{
+	guint i;
+	HalDevice *d;
+
+	HAL_INFO (("phys_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), 
+						     "linux.sysfs_path", 
+						     sysfs_path);
+	if (d == NULL) {
+		HAL_WARNING (("Couldn't remove device with sysfs path %s - not found", sysfs_path));
+		goto out;
+	}
+	
+	for (i = 0; phys_handlers [i] != NULL; i++) {
+		PhysDevHandler *handler;
+		
+		handler = phys_handlers[i];
+		if (strcmp (handler->subsystem, subsystem) == 0) {
+			handler->remove (d);
+			
+			hal_util_callout_device_remove (d, physdev_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
+physdev_rescan_device (HalDevice *d)
+{
+	return FALSE;
+}
+
+HotplugEvent *
+physdev_generate_add_hotplug_event (HalDevice *d)
+{
+	const char *subsystem;
+	const char *sysfs_path;
+	HotplugEvent *hotplug_event;
+
+	subsystem = hal_device_property_get_string (d, "linux.subsystem");
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
+
+HotplugEvent *
+physdev_generate_remove_hotplug_event (HalDevice *d)
+{
+	const char *subsystem;
+	const char *sysfs_path;
+	HotplugEvent *hotplug_event;
+
+	subsystem = hal_device_property_get_string (d, "linux.subsystem");
+	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
+	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
+	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
+	hotplug_event->sysfs.device_file[0] = '\0';
+	hotplug_event->sysfs.net_ifindex = -1;
+
+	return hotplug_event;
+}
diff --git a/hald/linux/physdev.h b/hald/linux/physdev.h
new file mode 100644
index 0000000..6c16cc2
--- /dev/null
+++ b/hald/linux/physdev.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * physdev.h : Handling of physical kernel devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef PHYSDEV_H
+#define PHYSDEV_H
+
+#include <glib.h>
+#include "hotplug.h"
+
+void hotplug_event_begin_add_physdev (const gchar *subsystem, const gchar *sysfs_path, HalDevice *parent, void *end_token);
+
+void hotplug_event_begin_remove_physdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
+
+gboolean physdev_rescan_device (HalDevice *d);
+
+HotplugEvent *physdev_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *physdev_generate_remove_hotplug_event (HalDevice *d);
+
+#endif /* PHYSDEV_H */
diff --git a/hald/linux/pmu.c b/hald/linux/pmu.c
new file mode 100644
index 0000000..892fff1
--- /dev/null
+++ b/hald/linux/pmu.c
@@ -0,0 +1,622 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 Sjoerd Simons <sjoerd at luon.net>
+ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../device_info.h"
+#include "../hald_dbus.h"
+#include "../logger.h"
+#include "../util.h"
+#include "../util_pm.h"
+
+#include "hotplug.h"
+#include "osspec_linux.h"
+
+#include "pmu.h"
+
+enum {
+	PMU_TYPE_BATTERY,
+	PMU_TYPE_AC_ADAPTER,
+	PMU_TYPE_LID_BUTTON,
+	PMU_TYPE_LAPTOP_PANEL
+};
+
+
+typedef struct PMUDevHandler_s
+{
+	int pmu_type;
+	HalDevice *(*add) (const gchar *pmu_path, HalDevice *parent, struct PMUDevHandler_s *handler);
+	gboolean (*compute_udi) (HalDevice *d, struct PMUDevHandler_s *handler);
+	gboolean (*remove) (HalDevice *d, struct PMUDevHandler_s *handler);
+	gboolean (*refresh) (HalDevice *d, struct PMUDevHandler_s *handler);
+} PMUDevHandler;
+
+
+/* defines from the kernel PMU driver (include/linux/pmu.h) */
+#define PMU_BATT_PRESENT	0x00000001
+#define PMU_BATT_CHARGING	0x00000002
+#define PMU_BATT_TYPE_MASK	0x000000f0
+#define PMU_BATT_TYPE_SMART	0x00000010	/* Smart battery */
+#define PMU_BATT_TYPE_HOOPER	0x00000020	/* 3400/3500 */
+#define PMU_BATT_TYPE_COMET	0x00000030	/* 2400 */
+
+#define PMU_POLL_INTERVAL	2000
+
+#define PMUDEV			"/dev/pmu"
+
+
+static gboolean
+battery_refresh (HalDevice *d, PMUDevHandler *handler)
+{
+	const char *path;
+	int flags;
+	int last_full;
+	int remaining_time;
+	int remaining_percentage;
+
+	path = hal_device_property_get_string (d, "linux.pmu_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");
+
+	flags = hal_util_grep_int_elem_from_file (path, "", "flags", 0, 16, FALSE);
+
+	hal_device_property_set_bool (d, "battery.present", flags & PMU_BATT_PRESENT);
+
+	if (flags & PMU_BATT_PRESENT) {
+		int current;
+
+		device_property_atomic_update_begin ();
+		hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
+
+		/* we don't know the unit here :-/ */
+		/*hal_device_property_set_string (d, "battery.charge_level.unit", "percent");*/
+
+		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", flags & PMU_BATT_CHARGING);
+		/* we're discharging if, and only if, we are not plugged into the wall */
+		{
+			char buf[HAL_PATH_MAX];
+			snprintf (buf, sizeof (buf), "%s/pmu/info", get_hal_proc_path ());
+			hal_util_set_bool_elem_from_file (d, "battery.rechargeable.is_discharging", buf, "", 
+							  "AC Power", 0, "0", FALSE);
+		}
+
+		hal_util_set_int_elem_from_file (d, "battery.charge_level.current", 
+						 path, "", "charge", 0, 10, FALSE);
+		hal_util_set_int_elem_from_file (d, "battery.charge_level.last_full", 
+						 path, "", "max_charge", 0, 10, FALSE);
+		hal_util_set_int_elem_from_file (d, "battery.charge_level.design", 
+						 path, "", "max_charge", 0, 10, FALSE);
+
+		current = hal_util_grep_int_elem_from_file (path, "", "current", 0, 10, FALSE);
+		if (current > 0)
+			hal_device_property_set_int (d, "battery.charge_level.rate", current);
+		else
+			hal_device_property_set_int (d, "battery.charge_level.rate", -current);
+
+		current = hal_device_property_get_int (d, "battery.charge_level.current");
+		last_full = hal_device_property_get_int (d, "battery.charge_level.last_full");
+
+		/* TODO: could read some pmu file? */
+		remaining_time = util_compute_time_remaining (
+					d->udi,
+					hal_device_property_get_int (d, "battery.charge_level.rate"),
+					current,
+					last_full,
+					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, current, last_full);
+		/*
+		 * 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");
+
+		device_property_atomic_update_end ();
+	} else {
+		device_property_atomic_update_begin ();
+		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.charge_level.unit");*/
+		hal_device_property_remove (d, "battery.charge_level.current");
+		hal_device_property_remove (d, "battery.charge_level.last_full");
+		hal_device_property_remove (d, "battery.charge_level.design");
+		device_property_atomic_update_end ();		
+	}
+
+	return TRUE;
+}
+
+static gboolean
+ac_adapter_refresh (HalDevice *d, PMUDevHandler *handler)
+{
+	const char *path;
+
+	path = hal_device_property_get_string (d, "linux.pmu_path");
+	if (path == NULL)
+		return FALSE;
+
+	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");
+
+	hal_util_set_bool_elem_from_file (d, "ac_adapter.present", path, "", "AC Power", 0, "1", FALSE);
+
+	return TRUE;
+}
+
+static gboolean
+lid_button_refresh (HalDevice *d, PMUDevHandler *handler)
+{
+	hal_device_property_set_string (d, "info.product", "Lid Switch");
+	hal_device_add_capability (d, "button");
+	hal_device_property_set_string (d, "info.category", "button");
+	hal_device_property_set_string (d, "button.type", "lid");
+	hal_device_property_set_bool (d, "button.has_state", TRUE);
+	hal_device_property_set_bool (d, "button.state.value", FALSE); 
+
+	/* assume lid is open, polling will tell us otherwise 
+	 * (TODO: figure out initial state)
+	 */
+	return TRUE;
+}
+
+/** Refreshes a laptop screen connected to a PMU controller.
+ *  This is much simpler than ACPI as we have a *standard* ioctl to use.
+ *
+ *  @param	d		The hal device
+ *  @param	handler		What to do
+ */
+static gboolean
+laptop_panel_refresh (HalDevice *d, PMUDevHandler *handler)
+{
+	hal_device_property_set_string (d, "info.category", "laptop_panel");
+	hal_device_property_set_string (d, "info.product", "Apple Laptop Panel");
+
+	hal_device_property_set_string (d, "laptop_panel.access_method", "pmu");
+	/*
+	 * We can set laptop_panel.num_levels as it will not change, 
+	 * all powerbooks have 15 steps for brightness, where state 0
+	 * is backlight disable.
+	 */
+	hal_device_property_set_int (d, "laptop_panel.num_levels", 14);
+	hal_device_add_capability (d, "laptop_panel");
+	return TRUE;
+}
+
+static gboolean
+pmu_lid_compute_udi (HalDevice *d, PMUDevHandler *handler)
+{
+	gchar udi[256];
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pmu_lid");
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+static gboolean
+pmu_laptop_panel_compute_udi (HalDevice *d, PMUDevHandler *handler)
+{
+	gchar udi[256];
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pmu_lcd");
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+static gboolean
+pmu_poll (gpointer data)
+{
+	GSList *i;
+	GSList *devices;
+
+	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
+								    "battery.type",
+								    "primary");
+	for (i = devices; i != NULL; i = g_slist_next (i)) {
+		HalDevice *d;
+		
+		d = HAL_DEVICE (i->data);
+		if (hal_device_has_property (d, "linux.pmu_type")) {
+			hal_util_grep_discard_existing_data ();
+			device_property_atomic_update_begin ();
+			battery_refresh (d, NULL);
+			device_property_atomic_update_end ();		
+		}
+	}
+
+	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
+								    "info.category",
+								    "ac_adapter");
+	for (i = devices; i != NULL; i = g_slist_next (i)) {
+		HalDevice *d;
+		
+		d = HAL_DEVICE (i->data);
+		if (hal_device_has_property (d, "linux.pmu_type")) {
+			hal_util_grep_discard_existing_data ();
+			device_property_atomic_update_begin ();
+			ac_adapter_refresh (d, NULL);
+			device_property_atomic_update_end ();		
+		}
+	}
+
+	return TRUE;
+}
+
+/** Synthesizes a *specific* PMU object.
+ *
+ *  @param	fullpath	The PMU path, e.g. "/dev/pmu/info"
+ *  @param	pmu_type	The type of device, e.g. PMU_TYPE_BATTERY
+ */
+static void
+pmu_synthesize_item (const gchar *fullpath, int pmu_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_PMU;
+	g_strlcpy (hotplug_event->pmu.pmu_path, fullpath, sizeof (hotplug_event->pmu.pmu_path));
+	hotplug_event->acpi.acpi_type = pmu_type;
+	hotplug_event_enqueue (hotplug_event);
+}
+
+/** Scan the data structures exported by the kernel and add hotplug
+ *  events for adding PMU objects.
+ *
+ *  @param                      TRUE if, and only if, PMU capabilities
+ *                              were detected
+ */
+gboolean
+pmu_synthesize_hotplug_events (void)
+{
+	gboolean ret;
+	HalDevice *computer;
+	gchar path[HAL_PATH_MAX];
+	GError *error;
+	GDir *dir;
+	gboolean has_battery_bays;
+
+	ret = FALSE;
+
+	has_battery_bays = FALSE;
+
+	if (!g_file_test ("/proc/pmu/info", G_FILE_TEST_EXISTS))
+		goto out;
+
+	ret = TRUE;
+
+	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?"));
+		goto out;
+	}
+
+	/* Set appropriate properties on the computer object */
+	hal_device_property_set_string (computer, "power_management.type", "pmu");
+
+	/* AC Adapter */
+	snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
+	pmu_synthesize_item (path, PMU_TYPE_AC_ADAPTER);
+
+	error = NULL;
+	snprintf (path, sizeof (path), "%s/pmu", get_hal_proc_path ());
+	dir = g_dir_open (path, 0, &error);
+	if (dir != NULL) {
+		const gchar *f;
+		while ((f = g_dir_read_name (dir)) != NULL) {
+			gchar buf[HAL_PATH_MAX];
+			int battery_num;
+
+			snprintf (buf, sizeof (buf), "%s/pmu/%s", get_hal_proc_path (), f);
+			if (sscanf (f, "battery_%d", &battery_num) == 1) {
+				has_battery_bays = TRUE;
+				pmu_synthesize_item (buf, PMU_TYPE_BATTERY);
+			}
+			
+		}
+	} else {
+		HAL_ERROR (("Couldn't open %s: %s", path, error->message));
+		g_error_free (error);
+	}
+
+	/* close directory */
+	g_dir_close (dir);
+
+	/* We need to make another assumption - that there is a lid button,
+	 * if, and only if, the machine has got battery bays
+	 */
+	if (has_battery_bays) {
+		/* Add lid button */
+		snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
+		pmu_synthesize_item (path, PMU_TYPE_LID_BUTTON);
+
+		/* Add Laptop Panel */
+		snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
+		pmu_synthesize_item (path, PMU_TYPE_LAPTOP_PANEL);
+
+		/* If the machine has got battery bays then this is a laptop. */
+		hal_device_property_set_string (computer, "system.formfactor", "laptop");
+	}
+
+	/* setup timer for things that we need to poll */
+	g_timeout_add (PMU_POLL_INTERVAL,
+		       pmu_poll,
+		       NULL);
+
+out:
+	return ret;
+}
+
+static HalDevice *
+pmu_generic_add (const gchar *pmu_path, HalDevice *parent, PMUDevHandler *handler)
+{
+	HalDevice *d;
+	d = hal_device_new ();
+	hal_device_property_set_string (d, "linux.pmu_path", pmu_path);
+	hal_device_property_set_int (d, "linux.pmu_type", handler->pmu_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
+pmu_generic_compute_udi (HalDevice *d, PMUDevHandler *handler)
+{
+	gchar udi[256];
+	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
+			      "/org/freedesktop/Hal/devices/pmu_%s_%d",
+			      hal_util_get_last_element (hal_device_property_get_string (d, "linux.pmu_path")),
+			      hal_device_property_get_int (d, "linux.pmu_type"));
+	hal_device_set_udi (d, udi);
+	hal_device_property_set_string (d, "info.udi", udi);
+	return TRUE;
+}
+
+static gboolean
+pmu_generic_remove (HalDevice *d, PMUDevHandler *handler)
+{
+	if (!hal_device_store_remove (hald_get_gdl (), d)) {
+		HAL_WARNING (("Error removing device"));
+	}
+
+	return TRUE;
+}
+
+static PMUDevHandler pmudev_handler_battery = { 
+	.pmu_type    = PMU_TYPE_BATTERY,
+	.add         = pmu_generic_add,
+	.compute_udi = pmu_generic_compute_udi,
+	.refresh     = battery_refresh,
+	.remove      = pmu_generic_remove
+};
+
+static PMUDevHandler pmudev_handler_ac_adapter = { 
+	.pmu_type    = PMU_TYPE_AC_ADAPTER,
+	.add         = pmu_generic_add,
+	.compute_udi = pmu_generic_compute_udi,
+	.refresh     = ac_adapter_refresh,
+	.remove      = pmu_generic_remove
+};
+
+static PMUDevHandler pmudev_handler_lid_button = { 
+	.pmu_type    = PMU_TYPE_LID_BUTTON,
+	.add         = pmu_generic_add,
+	.compute_udi = pmu_lid_compute_udi,
+	.refresh     = lid_button_refresh,
+	.remove      = pmu_generic_remove
+};
+
+static PMUDevHandler pmudev_handler_laptop_panel = { 
+	.pmu_type    = PMU_TYPE_LAPTOP_PANEL,
+	.add         = pmu_generic_add,
+	.compute_udi = pmu_laptop_panel_compute_udi,
+	.refresh     = laptop_panel_refresh,
+	.remove      = pmu_generic_remove
+};
+
+static PMUDevHandler *pmu_handlers[] = {
+	&pmudev_handler_battery,
+	&pmudev_handler_ac_adapter,
+	&pmudev_handler_lid_button,
+	&pmudev_handler_laptop_panel,
+	NULL
+};
+
+void
+hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token)
+{
+	guint i;
+
+	HAL_INFO (("pmu_add: pmu_path=%s pmu_type=%d, parent=0x%08x", pmu_path, pmu_type, parent));
+
+	for (i = 0; pmu_handlers [i] != NULL; i++) {
+		PMUDevHandler *handler;
+
+		handler = pmu_handlers[i];
+		if (handler->pmu_type == pmu_type) {
+			HalDevice *d;
+
+			d = handler->add (pmu_path, parent, handler);
+			if (d == NULL) {
+				/* didn't find anything - thus, ignore this hotplug event */
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_PMU);
+
+			/* 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);
+
+			/* TODO: Run callouts */
+			
+			/* Compute UDI */
+			if (!handler->compute_udi (d, handler)) {
+				hal_device_store_remove (hald_get_tdl (), d);
+				hotplug_event_end (end_token);
+				goto out;
+			}
+
+			/* 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);
+			goto out;
+		}
+	}
+	
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out:
+	;
+}
+
+void
+hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token)
+{
+	guint i;
+	HalDevice *d;
+
+	HAL_INFO (("pmu_rem: pmu_path=%s pmu_type=%d", pmu_path, pmu_type));
+
+	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.pmu_path", pmu_path);
+	if (d == NULL) {
+		HAL_WARNING (("Couldn't remove device with pmu path %s - not found", pmu_path));
+		goto out;
+	}
+
+	for (i = 0; pmu_handlers [i] != NULL; i++) {
+		PMUDevHandler *handler;
+
+		handler = pmu_handlers[i];
+		if (handler->pmu_type == pmu_type) {
+			if (handler->remove (d, handler)) {
+				hotplug_event_end (end_token);
+				goto out2;
+			}
+		}
+	}
+out:
+	/* didn't find anything - thus, ignore this hotplug event */
+	hotplug_event_end (end_token);
+out2:
+	;
+}
+
+gboolean
+pmu_rescan_device (HalDevice *d)
+{
+	guint i;
+	gboolean ret;
+	int pmu_type;
+
+	ret = FALSE;
+
+	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
+
+	for (i = 0; pmu_handlers [i] != NULL; i++) {
+		PMUDevHandler *handler;
+
+		handler = pmu_handlers[i];
+		if (handler->pmu_type == pmu_type) {
+			ret = handler->refresh (d, handler);
+			goto out;
+		}
+	}
+
+	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));
+
+out:
+	return ret;
+}
+
+HotplugEvent *
+pmu_generate_add_hotplug_event (HalDevice *d)
+{
+	int pmu_type;
+	const char *pmu_path;
+	HotplugEvent *hotplug_event;
+
+	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
+	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_ADD;
+	hotplug_event->type = HOTPLUG_EVENT_PMU;
+	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
+	hotplug_event->pmu.pmu_type = pmu_type;
+	return hotplug_event;
+}
+
+HotplugEvent *
+pmu_generate_remove_hotplug_event (HalDevice *d)
+{
+	int pmu_type;
+	const char *pmu_path;
+	HotplugEvent *hotplug_event;
+
+	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
+	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
+
+	hotplug_event = g_new0 (HotplugEvent, 1);
+	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
+	hotplug_event->type = HOTPLUG_EVENT_PMU;
+	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
+	hotplug_event->pmu.pmu_type = pmu_type;
+	return hotplug_event;
+}
diff --git a/hald/linux/pmu.h b/hald/linux/pmu.h
new file mode 100644
index 0000000..c8304b3
--- /dev/null
+++ b/hald/linux/pmu.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
+ *
+ * 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
+ *
+ **************************************************************************/
+
+#ifndef PMU_H
+#define PMU_H
+
+#include "../hald.h"
+#include "hotplug.h"
+
+gboolean pmu_synthesize_hotplug_events (void);
+
+void hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token);
+
+void hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token);
+
+gboolean pmu_rescan_device (HalDevice *d);
+
+HotplugEvent *pmu_generate_add_hotplug_event (HalDevice *d);
+
+HotplugEvent *pmu_generate_remove_hotplug_event (HalDevice *d);
+
+#endif /* PMU_H */
diff --git a/hald/linux/probing/.gitignore b/hald/linux/probing/.gitignore
new file mode 100644
index 0000000..226a9db
--- /dev/null
+++ b/hald/linux/probing/.gitignore
@@ -0,0 +1,16 @@
+.deps
+.libs
+Makefile
+Makefile.in
+*.lo
+*.la
+hald-probe-hiddev
+hald-probe-input
+hald-probe-pc-floppy
+hald-probe-printer
+hald-probe-smbios
+hald-probe-storage
+hald-probe-volume
+hald-probe-serial
+*.o
+*~
diff --git a/hald/linux/probing/Makefile.am b/hald/linux/probing/Makefile.am
new file mode 100644
index 0000000..a66d858
--- /dev/null
+++ b/hald/linux/probing/Makefile.am
@@ -0,0 +1,39 @@
+
+INCLUDES = \
+	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
+	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
+	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
+	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
+	-I$(top_srcdir) \
+	@GLIB_CFLAGS@ @DBUS_CFLAGS@
+
+if HALD_COMPILE_LINUX
+libexec_PROGRAMS = hald-probe-input hald-probe-hiddev hald-probe-storage hald-probe-volume hald-probe-printer \
+	           hald-probe-pc-floppy hald-probe-smbios hald-probe-serial
+endif
+
+hald_probe_smbios_SOURCES = probe-smbios.c ../../logger.c
+hald_probe_smbios_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_probe_printer_SOURCES = probe-printer.c ../../logger.c
+hald_probe_printer_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@
+#TODO : get rid of glib in hald_probe_printer
+
+hald_probe_input_SOURCES = probe-input.c ../../logger.c
+hald_probe_input_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_probe_hiddev_SOURCES = probe-hiddev.c ../../logger.c
+hald_probe_hiddev_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_probe_serial_SOURCES = probe-serial.c ../../logger.c
+hald_probe_serial_LDADD = $(top_builddir)/libhal/libhal.la
+
+hald_probe_storage_SOURCES = probe-storage.c linux_dvd_rw_utils.c linux_dvd_rw_utils.h ../../logger.c
+hald_probe_storage_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ @VOLUME_ID_LIBS@
+
+hald_probe_pc_floppy_SOURCES = probe-pc-floppy.c ../../logger.c
+
+hald_probe_volume_SOURCES = probe-volume.c linux_dvd_rw_utils.c ../../logger.c 
+hald_probe_volume_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ @VOLUME_ID_LIBS@
+
diff --git a/hald/linux/probing/linux_dvd_rw_utils.c b/hald/linux/probing/linux_dvd_rw_utils.c
new file mode 100644
index 0000000..a75a091
--- /dev/null
+++ b/hald/linux/probing/linux_dvd_rw_utils.c
@@ -0,0 +1,818 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ *
+ * This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
+ *
+ * Use-it-on-your-own-risk, GPL bless...
+ *
+ * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
+*/
+
+#include <glib.h>
+
+#define CREAM_ON_ERRNO(s)	do {				\
+    switch ((s)[2]&0x0F)					\
+    {	case 2:	if ((s)[12]==4) errno=EAGAIN;	break;		\
+	case 5:	errno=EINVAL;					\
+		if ((s)[13]==0)					\
+		{   if ((s)[12]==0x21)		errno=ENOSPC;	\
+		    else if ((s)[12]==0x20)	errno=ENODEV;	\
+		}						\
+		break;						\
+    }								\
+} while(0)
+#define ERRCODE(s)	((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13]))
+#define	SK(errcode)	(((errcode)>>16)&0xF)
+#define	ASC(errcode)	(((errcode)>>8)&0xFF)
+#define ASCQ(errcode)	((errcode)&0xFF)
+
+#ifndef _LARGEFILE_SOURCE
+#define _LARGEFILE_SOURCE
+#endif
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/cdrom.h>
+#include <errno.h>
+#include <string.h>
+#include <mntent.h>
+#include <sys/wait.h>
+#include <sys/utsname.h>
+#include <scsi/scsi.h>
+#include <scsi/sg.h>
+#include <poll.h>
+#include <sys/time.h>
+
+#include "linux_dvd_rw_utils.h"
+
+typedef enum {
+	NONE = CGC_DATA_NONE,	// 3
+	READ = CGC_DATA_READ,	// 2
+	WRITE = CGC_DATA_WRITE	// 1
+} Direction;
+
+typedef struct ScsiCommand ScsiCommand;
+
+struct ScsiCommand {
+	int fd;
+	int autoclose;
+	char *filename;
+	struct cdrom_generic_command cgc;
+	union {
+		struct request_sense s;
+		unsigned char u[18];
+	} _sense;
+	struct sg_io_hdr sg_io;
+};
+
+#define DIRECTION(i) (Dir_xlate[i]);
+
+/* 1,CGC_DATA_WRITE
+ * 2,CGC_DATA_READ
+ * 3,CGC_DATA_NONE
+ */
+const int Dir_xlate[4] = {
+	0,			// implementation-dependent...
+	SG_DXFER_TO_DEV,	// 1,CGC_DATA_WRITE
+	SG_DXFER_FROM_DEV,	// 2,CGC_DATA_READ
+	SG_DXFER_NONE		// 3,CGC_DATA_NONE
+};
+
+static ScsiCommand *
+scsi_command_new (void)
+{
+	ScsiCommand *cmd;
+
+	cmd = (ScsiCommand *) malloc (sizeof (ScsiCommand));
+	memset (cmd, 0, sizeof (ScsiCommand));
+	cmd->fd = -1;
+	cmd->filename = NULL;
+	cmd->autoclose = 1;
+
+	return cmd;
+}
+
+static ScsiCommand *
+scsi_command_new_from_fd (int f)
+{
+	ScsiCommand *cmd;
+
+	cmd = scsi_command_new ();
+	cmd->fd = f;
+	cmd->autoclose = 0;
+
+	return cmd;
+}
+
+static void
+scsi_command_free (ScsiCommand * cmd)
+{
+	if (cmd->fd >= 0 && cmd->autoclose) {
+		close (cmd->fd);
+		cmd->fd = -1;
+	}
+	if (cmd->filename) {
+		free (cmd->filename);
+		cmd->filename = NULL;
+	}
+
+	free (cmd);
+}
+
+static int
+scsi_command_transport (ScsiCommand * cmd, Direction dir, void *buf,
+			size_t sz)
+{
+	int ret = 0;
+
+	cmd->sg_io.dxferp = buf;
+	cmd->sg_io.dxfer_len = sz;
+	cmd->sg_io.dxfer_direction = DIRECTION (dir);
+
+	if (ioctl (cmd->fd, SG_IO, &cmd->sg_io))
+		return -1;
+
+	if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
+		errno = EIO;
+		ret = -1;
+		if (cmd->sg_io.masked_status & CHECK_CONDITION) {
+			CREAM_ON_ERRNO (cmd->sg_io.sbp);
+			ret = ERRCODE (cmd->sg_io.sbp);
+			if (ret == 0)
+				ret = -1;
+		}
+	}
+
+	return ret;
+}
+
+static void
+scsi_command_init (ScsiCommand * cmd, size_t i, int arg)
+{
+	if (i == 0) {
+		memset (&cmd->cgc, 0, sizeof (cmd->cgc));
+		memset (&cmd->_sense, 0, sizeof (cmd->_sense));
+		cmd->cgc.quiet = 1;
+		cmd->cgc.sense = &cmd->_sense.s;
+		memset (&cmd->sg_io, 0, sizeof (cmd->sg_io));
+		cmd->sg_io.interface_id = 'S';
+		cmd->sg_io.mx_sb_len = sizeof (cmd->_sense);
+		cmd->sg_io.cmdp = cmd->cgc.cmd;
+		cmd->sg_io.sbp = cmd->_sense.u;
+		cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO;
+	}
+	cmd->sg_io.cmd_len = i + 1;
+	cmd->cgc.cmd[i] = arg;
+}
+
+int
+get_dvd_r_rw_profile (int fd)
+{
+	ScsiCommand *cmd;
+	int retval = 0;
+	unsigned char page[20];
+	unsigned char *list;
+	int i, len;
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	scsi_command_init (cmd, 0, 0x46);
+	scsi_command_init (cmd, 1, 2);
+	scsi_command_init (cmd, 8, 8);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, page, 8)) {
+		/* GET CONFIGURATION failed */
+		scsi_command_free (cmd);
+		return -1;
+	}
+
+	/* See if it's 2 gen drive by checking if DVD+R profile is an option */
+	len = 4 + (page[0] << 24 | page[1] << 16 | page[2] << 8 | page[3]);
+	if (len > 264) {
+		scsi_command_free (cmd);
+		/* insane profile list length */
+		return -1;
+	}
+
+	list = (unsigned char *) malloc (len);
+
+	scsi_command_init (cmd, 0, 0x46);
+	scsi_command_init (cmd, 1, 2);
+	scsi_command_init (cmd, 7, len >> 8);
+	scsi_command_init (cmd, 8, len);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, list, len)) {
+		/* GET CONFIGURATION failed */
+		scsi_command_free (cmd);
+		free (list);
+		return -1;
+	}
+
+	for (i = 12; i < list[11]; i += 4) {
+		int profile = (list[i] << 8 | list[i + 1]);
+		/* 0x13: DVD-RW Restricted Overwrite
+		 * 0x14: DVD-RW Sequential
+		 * 0x1B: DVD+R 
+		 * 0x1A: DVD+RW  
+		 * 0x2A: DVD+RW DL
+		 * 0x2B: DVD+R DL 
+		 */
+
+		switch (profile) {
+			case 0x13:
+			case 0x14:
+				retval |= DRIVE_CDROM_CAPS_DVDRW;
+				break;
+			case 0x1B:
+				retval |= DRIVE_CDROM_CAPS_DVDPLUSR;
+				break;
+			case 0x1A:
+				retval |= DRIVE_CDROM_CAPS_DVDPLUSRW;
+				break;
+			case 0x2A:
+				retval |= DRIVE_CDROM_CAPS_DVDPLUSRWDL;
+				break;
+			case 0x2B:
+				retval |= DRIVE_CDROM_CAPS_DVDPLUSRDL;
+				break;
+			default:
+				break;
+		}
+	}
+
+	scsi_command_free (cmd);
+	free (list);
+	
+	return retval;
+	
+}
+
+static unsigned char *
+pull_page2a_from_fd (int fd)
+{
+	ScsiCommand *cmd;
+	unsigned char header[12], *page2A;
+	unsigned int len, bdlen;
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
+	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
+	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
+	scsi_command_init (cmd, 8, sizeof (header));	/* header only to start with */
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, header, sizeof (header))) {
+		/* MODE SENSE failed */
+		scsi_command_free (cmd);
+		return NULL;
+	}
+
+	len = (header[0] << 8 | header[1]) + 2;
+	bdlen = header[6] << 8 | header[7];
+
+	/* should never happen as we set "DBD" above */
+	if (bdlen) {
+		if (len < (8 + bdlen + 30)) {
+			/* LUN impossible to bear with */
+			scsi_command_free (cmd);
+			return NULL;
+		}
+	} else if (len < (8 + 2 + (unsigned int) header[9])) {
+		/* SANYO does this. */
+		len = 8 + 2 + header[9];
+	}
+
+	page2A = (unsigned char *) malloc (len);
+	if (page2A == NULL) {
+		/* ENOMEM */
+		scsi_command_free (cmd);
+		return NULL;
+	}
+
+	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
+	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
+	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
+	scsi_command_init (cmd, 7, len >> 8);
+	scsi_command_init (cmd, 8, len);	/* Real length */
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, page2A, len)) {
+		/* MODE SENSE failed */
+		scsi_command_free (cmd);
+		free (page2A);
+		return NULL;
+	}
+
+	scsi_command_free (cmd);
+
+	len -= 2;
+	/* paranoia */
+	if (len < ((unsigned int) page2A[0] << 8 | page2A[1])) {
+		page2A[0] = len >> 8;
+		page2A[1] = len;
+	}
+
+	return page2A;
+}
+
+static int
+int_compare (const void *a, const void *b)
+{
+	/* descending order */
+	return *((int *) b) - *((int *) a);
+}
+
+/* gets the list of supported write speeds.  in the event
+ * that anything goes wrong, returns NULL.
+ */
+static char *
+get_write_speeds (const unsigned char *p, int length, int max_speed)
+{
+	char *result, *str;
+	int nr_records;
+	int *tmpspeeds;
+	int i, j;
+
+	result = NULL;
+
+	/* paranoia */
+	if (length < 32)
+		return NULL;
+
+	nr_records = p[30] << 8 | p[31];
+
+	/* paranoia */
+	if (length < 32 + 4 * nr_records)
+		return NULL;
+
+	tmpspeeds = malloc (nr_records * sizeof (int));
+
+	for (i = 0; i < nr_records; i++)
+	{
+		tmpspeeds[i] = p[4*i + 34] << 8 | p[4*i + 35];
+
+		/* i'm not sure how likely this is to show up, but it's
+		 * definitely wrong.  if we see it, abort.
+		 */
+		if (tmpspeeds[i] == 0)
+			goto free_tmpspeeds;
+	}
+
+	/* sort */
+	qsort (tmpspeeds, nr_records, sizeof (int), int_compare);
+
+	/* uniq */
+	for (i = j = 0; i < nr_records; i++)
+	{
+		tmpspeeds[j] = tmpspeeds[i];
+
+		/* make sure we don't look past the end of the array */
+		if (i >= (nr_records - 1) || tmpspeeds[i+1] != tmpspeeds[i])
+			j++;
+	}
+
+	/* j is now the number of unique entries in the array */
+	if (j == 0)
+		/* no entries?  this isn't right. */
+		goto free_tmpspeeds;
+
+	/* sanity check: the first item in the descending order
+	 * list ought to be the highest speed as detected through
+	 * other means
+	 */
+	if (tmpspeeds[0] != max_speed)
+		/* sanity check failed. */
+		goto free_tmpspeeds;
+
+	/* our values are 16-bit.  8 bytes per value
+	 * is more than enough including space for
+	 * ',' and '\0'.  we know j is not zero.
+	 */
+	result = str = malloc (8 * j);
+
+	for (i = 0; i < j; i++)
+	{
+		if (i > 0)
+			*(str++) = ',';
+
+		str += sprintf (str, "%d", tmpspeeds[i]);
+	}
+
+free_tmpspeeds:
+	free (tmpspeeds);
+
+	return result;
+}
+
+int
+get_read_write_speed (int fd, int *read_speed, int *write_speed, char **write_speeds)
+{
+	unsigned char *page2A;
+	int len, hlen;
+	unsigned char *p;
+
+	*read_speed = 0;
+	*write_speed = 0;
+	*write_speeds = NULL;
+
+	page2A = pull_page2a_from_fd (fd);
+	if (page2A == NULL) {
+		printf ("Failed to get Page 2A\n");
+		/* Failed to get Page 2A */
+		return -1;
+	}
+
+	len = (page2A[0] << 8 | page2A[1]) + 2;
+	hlen = 8 + (page2A[6] << 8 | page2A[7]);
+	p = page2A + hlen;
+
+	/* Values guessed from the cd_mode_page_2A struct
+	 * in cdrecord's libscg/scg/scsireg.h */
+	if (len < (hlen + 30) || p[1] < (30 - 2)) {
+		/* no MMC-3 "Current Write Speed" present,
+		 * try to use the MMC-2 one */
+		if (len < (hlen + 20) || p[1] < (20 - 2))
+			*write_speed = 0;
+		else
+			*write_speed = p[18] << 8 | p[19];
+	} else {
+		*write_speed = p[28] << 8 | p[29];
+	}
+
+	if (len >= hlen+9)
+	    *read_speed = p[8] << 8 | p[9];
+	else
+	    *read_speed = 0;
+
+	*write_speeds = get_write_speeds (p, len, *write_speed);
+
+	free (page2A);
+
+	return 0;
+}
+
+
+static int
+get_disc_capacity_cd (int fd,
+		      guint64 *size)
+{
+	ScsiCommand *cmd;
+	int retval;
+	guint64 block_size;
+	guint64 num_blocks;
+	unsigned char header [8];
+
+	retval = -1;
+
+	cmd = scsi_command_new_from_fd (fd);
+	scsi_command_init (cmd, 0, 0x25);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, header, 8)) {
+		/* READ CDROM CAPACITY failed */
+		goto done;
+	}
+
+	num_blocks = (header [0] << 24) | (header [1] << 16) | (header [2] << 8) | header [3];
+	num_blocks++;
+	block_size = header [4] << 24 | header [5] << 16 | header [6] << 8 | header [7];
+
+	if (size) {
+		*size = num_blocks * block_size;
+	}
+	retval = 0;
+
+ done:
+	scsi_command_free (cmd);
+
+	return retval;
+}
+
+static int
+get_disc_capacity_cdr (int fd,
+		       guint64 *size)
+{
+	ScsiCommand *cmd;
+	int retval;
+	guint64 secs;
+	unsigned char toc [8];
+	unsigned char *atip;
+	int len;
+
+	retval = -1;
+
+	cmd = scsi_command_new_from_fd (fd);
+	/* READ_TOC */
+	scsi_command_init (cmd, 0, 0x43);
+	/* FMT_ATIP */
+	scsi_command_init (cmd, 2, 4 & 0x0F);
+	scsi_command_init (cmd, 6, 0);
+	scsi_command_init (cmd, 8, 4);
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, toc, 4)) {
+		/* READ TOC failed */
+		goto done;
+	}
+
+	len = 2 + (toc [0] << 8 | toc [1]);
+
+	atip = (unsigned char *) malloc (len);
+
+	scsi_command_init (cmd, 0, 0x43);
+	scsi_command_init (cmd, 2, 4 & 0x0F);
+	scsi_command_init (cmd, 6, 0);
+	scsi_command_init (cmd, 7, len >> 8);
+	scsi_command_init (cmd, 8, len);
+	scsi_command_init (cmd, 9, 0);
+
+	if (scsi_command_transport (cmd, READ, atip, len)) {
+		/* READ TOC failed */
+		free (atip);
+		goto done;
+	}
+
+	secs = atip [12] * 60 + atip [13] + (atip [14] / 75 + 1);
+
+	if (size) {
+		*size = (1 + secs * 7 / 48) * 1024 * 1024;
+	}
+	retval = 0;
+
+	free (atip);
+ done:
+	scsi_command_free (cmd);
+
+	return retval;
+}
+
+static int
+get_disc_capacity_dvdr_from_type (int fd,
+				  int type,
+				  guint64 *size)
+{
+	ScsiCommand *cmd;
+	unsigned char formats [260];
+	unsigned char buf [32];
+	guint64 blocks;
+	guint64 nwa;
+	int i;
+	int len;
+	int obligatory;
+	int retval;
+	int next_track;
+
+	retval = -1;
+	blocks = 0;
+	next_track = 1;
+
+	cmd = scsi_command_new_from_fd (fd);
+
+ retry:
+	if (type == 0x1A || type == 0x14 || type == 0x13 || type == 0x12) {
+
+		/* READ FORMAT CAPACITIES */
+		scsi_command_init (cmd, 0, 0x23);
+		scsi_command_init (cmd, 8, 12);
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, formats, 12)) {
+			/* READ FORMAT CAPACITIES failed */
+			goto done;
+		}
+
+		len = formats [3];
+		if (len & 7 || len < 16) {
+			/* Length isn't sane */
+			goto done;
+		}
+
+		scsi_command_init (cmd, 0, 0x23);
+		scsi_command_init (cmd, 7, (4 + len) >> 8);
+		scsi_command_init (cmd, 8, (4 + len) & 0xFF);
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, formats, 4 + len)) {
+			/* READ FORMAT CAPACITIES failed */
+			goto done;
+		}
+
+		if (len != formats [3]) {
+			/* Parameter length inconsistency */
+			goto done;
+		}
+	}
+
+	obligatory = 0x00;
+
+	switch (type) {
+    	case 0x1A:		/* DVD+RW */
+		obligatory = 0x26;
+	case 0x13:		/* DVD-RW Restricted Overwrite */
+	case 0x14:		/* DVD-RW Sequential */
+		for (i = 8, len = formats [3]; i < len; i += 8) {
+			if ((formats [4 + i + 4] >> 2) == obligatory) {
+				break;
+			}
+		}
+
+		if (i == len) {
+			/* Can't find obligatory format descriptor */
+			goto done;
+		}
+
+		blocks  = formats [4 + i + 0] << 24;
+		blocks |= formats [4 + i + 1] << 16;
+		blocks |= formats [4 + i + 2] << 8;
+		blocks |= formats [4 + i + 3];
+		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
+		if (nwa > 2048) {
+			blocks *= nwa / 2048;
+		} else if (nwa < 2048) {
+			blocks /= 2048 / nwa;
+		}
+
+		retval = 0;
+		break;
+
+	case 0x12:		/* DVD-RAM */
+
+		blocks  = formats [4 + 0] << 24;
+		blocks |= formats [4 + 1] << 16;
+		blocks |= formats [4 + 2] << 8;
+		blocks |= formats [4 + 3];
+		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
+		if (nwa > 2048) {
+			blocks *= nwa / 2048;
+		} else if (nwa < 2048) {
+			blocks /= 2048 / nwa;
+		}
+
+		retval = 0;
+		break;
+
+	case 0x11:		/* DVD-R */
+	case 0x1B:		/* DVD+R */
+	case 0x2B:		/* DVD+R Double Layer */
+
+		/* READ TRACK INFORMATION */
+		scsi_command_init (cmd, 0, 0x52);
+		scsi_command_init (cmd, 1, 1);
+		scsi_command_init (cmd, 4, next_track >> 8);
+		scsi_command_init (cmd, 5, next_track & 0xFF);
+		scsi_command_init (cmd, 8, sizeof (buf));
+		scsi_command_init (cmd, 9, 0);
+		if (scsi_command_transport (cmd, READ, buf, sizeof (buf))) {
+			/* READ TRACK INFORMATION failed */
+			if (next_track > 0) {
+				goto done;
+			} else {
+				next_track = 1;
+				goto retry;
+			}
+		}
+
+		blocks = buf [24] << 24;
+		blocks |= buf [25] << 16;
+		blocks |= buf [26] << 8;
+		blocks |= buf [27];
+
+		retval = 0;
+		break;
+	default:
+		blocks = 0;
+		break;
+	}
+
+ done:
+	scsi_command_free (cmd);
+
+	if (size) {
+		*size = blocks * 2048;
+	}
+
+	return retval;
+}
+
+int
+get_disc_capacity_for_type (int fd,
+			    int type,
+			    guint64 *size)
+{
+	int retval;
+
+	retval = -1;
+
+	switch (type) {
+	case 0x8:
+		retval = get_disc_capacity_cd (fd, size);
+		break;
+	case 0x9:
+	case 0xa:
+		retval = get_disc_capacity_cdr (fd, size);
+		break;
+	case 0x10:
+		retval = get_disc_capacity_cd (fd, size);
+		break;
+	case 0x11:
+	case 0x13:
+	case 0x14:
+	case 0x1B:
+	case 0x2B:
+	case 0x1A:
+	case 0x12:
+		retval = get_disc_capacity_dvdr_from_type (fd, type, size);
+		break;
+	default:
+		retval = -1;
+	}
+
+	return retval;
+}
+
+int
+get_disc_type (int fd)
+{
+	ScsiCommand *cmd;
+	int retval = -1;
+	unsigned char header[8];
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	scsi_command_init (cmd, 0, 0x46);
+	scsi_command_init (cmd, 1, 1);
+	scsi_command_init (cmd, 8, 8);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, header, 8)) {
+		/* GET CONFIGURATION failed */
+		scsi_command_free (cmd);
+		return -1;
+	}
+	
+	retval = (header[6]<<8)|(header[7]);
+
+
+	scsi_command_free (cmd);
+	return retval;
+}
+
+
+int
+disc_is_appendable (int fd)
+{
+	ScsiCommand *cmd;
+	int retval = -1;
+	unsigned char header[32];
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
+	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
+	scsi_command_init (cmd, 8, 32);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, header, 32)) {
+		/* READ_DISC_INFORMATION failed */
+		scsi_command_free (cmd);
+		return 0;
+	}
+	
+	retval = ((header[2]&0x03) == 0x01);
+
+	scsi_command_free (cmd);
+	return retval;
+}
+
+int
+disc_is_rewritable (int fd)
+{
+	ScsiCommand *cmd;
+	int retval = -1;
+	unsigned char header[32];
+
+	cmd = scsi_command_new_from_fd (fd);
+
+	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
+	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
+	scsi_command_init (cmd, 8, 32);
+	scsi_command_init (cmd, 9, 0);
+	if (scsi_command_transport (cmd, READ, header, 32)) {
+		/* READ_DISC_INFORMATION failed */
+		scsi_command_free (cmd);
+		return 0;
+	}
+	
+	retval = ((header[2]&0x10) != 0);
+
+	scsi_command_free (cmd);
+	return retval;
+}
diff --git a/hald/linux/probing/linux_dvd_rw_utils.h b/hald/linux/probing/linux_dvd_rw_utils.h
new file mode 100644
index 0000000..5b6105a
--- /dev/null
+++ b/hald/linux/probing/linux_dvd_rw_utils.h
@@ -0,0 +1,27 @@
+//
+// This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
+//
+// Use-it-on-your-own-risk, GPL bless...
+//
+// For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
+//
+
+#ifndef LINUX_DVD_RW_UTILS_H
+#define LINUX_DVD_RW_UTILS_H
+
+#include <glib.h>
+
+#define DRIVE_CDROM_CAPS_DVDRW        1
+#define DRIVE_CDROM_CAPS_DVDPLUSR     2
+#define DRIVE_CDROM_CAPS_DVDPLUSRW    4
+#define DRIVE_CDROM_CAPS_DVDPLUSRWDL  8
+#define DRIVE_CDROM_CAPS_DVDPLUSRDL  16
+
+int get_dvd_r_rw_profile (int fd);
+int get_read_write_speed (int fd, int *read_speed, int *write_speed, char **write_speeds);
+int get_disc_capacity_for_type (int fd, int type, guint64 *capacity);
+int get_disc_type (int fd);
+int disc_is_appendable (int fd);
+int disc_is_rewritable (int fd);
+
+#endif				/* LINUX_DVD_RW_UTILS_H */
diff --git a/hald/linux/probing/probe-hiddev.c b/hald/linux/probing/probe-hiddev.c
new file mode 100644
index 0000000..fbc1861
--- /dev/null
+++ b/hald/linux/probing/probe-hiddev.c
@@ -0,0 +1,171 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-input.c : Probe input devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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
+
+/* asm/types.h required for __s32 in linux/hiddev.h */
+#include <asm/types.h>
+#include <fcntl.h>
+#include <linux/hiddev.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char name[256] = "Unknown HID device";
+	unsigned int i;
+	struct hiddev_devinfo device_info;
+
+	fd = -1;
+
+	/* assume failure */
+	ret = 1;
+
+	udi = getenv ("UDI");
+	if (udi == NULL)
+		goto out;
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	device_file = getenv ("HAL_PROP_HIDDEV_DEVICE");
+	if (device_file == NULL)
+		goto out;
+
+	fd = open (device_file, O_RDONLY);
+	if (fd < 0)
+		goto out;
+
+	if (ioctl (fd, HIDIOCGNAME(sizeof (name)), name) >= 0) {
+		if (!libhal_device_set_property_string (ctx, udi, "hiddev.product", name, &error))
+			goto out;
+		if (!libhal_device_set_property_string (ctx, udi, "info.product", name, &error))
+			goto out;
+	}
+
+	if (ioctl (fd, HIDIOCGDEVINFO, &device_info) < 0)
+		goto out;
+
+	for (i = 0; i < device_info.num_applications; i++) {
+		int appl;
+		const char *appl_name;
+		char buf[256];
+
+		if ((appl = ioctl(fd, HIDIOCAPPLICATION, i)) < 0)
+			goto out;
+
+		/* The magic values come from various usage table specs */
+		switch (appl >> 16)
+		{
+		case 0x01 :
+			appl_name = "Generic Desktop Page";
+			break;
+		case 0x0c :
+			appl_name = "Consumer Product Page";
+			break;
+		case 0x80 :
+			appl_name = "USB Monitor Page";
+			break;
+		case 0x81 :
+			appl_name = "USB Enumerated Values Page";
+			break;
+		case 0x82 :
+			appl_name = "VESA Virtual Controls Page";
+			break;
+		case 0x83 :
+			appl_name = "Reserved Monitor Page";
+			break;
+		case 0x84 :
+			appl_name = "Power Device Page";
+			break;
+		case 0x85 :
+			appl_name = "Battery System Page";
+			break;
+		case 0x86 :
+		case 0x87 :
+			appl_name = "Reserved Power Device Page";
+			break;
+		default :
+			snprintf (buf, sizeof (buf), "Unknown page 0x%02x", appl);
+			appl_name = buf;
+		}
+
+		if (!libhal_device_property_strlist_append (ctx, udi, "hiddev.application_pages", appl_name, &error))
+			goto out;
+	}
+
+#if 0
+	DBusConnection *conn;
+
+	if (fork () == 0) {
+		sleep (10);
+
+		dbus_error_init (&error);
+		if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
+			goto out;
+		
+		if ((ctx = libhal_ctx_new ()) == NULL)
+			goto out;
+		if (!libhal_ctx_set_dbus_connection (ctx, conn))
+			goto out;
+		if (!libhal_ctx_init (ctx, &error))
+			goto out;
+
+		main2 (ctx, "/org/freedesktop/Hal/devices/usb_device_51d_2_QB0435136106  _if0_hiddev", fd);
+	}
+	else
+		sleep (2);
+#endif
+
+	/* success */
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-input.c b/hald/linux/probing/probe-input.c
new file mode 100644
index 0000000..6a18990
--- /dev/null
+++ b/hald/linux/probing/probe-input.c
@@ -0,0 +1,230 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-input.c : Probe input devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <linux/input.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+
+/* we must use this kernel-compatible implementation */
+#define BITS_PER_LONG (sizeof(long) * 8)
+#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
+#define OFF(x)  ((x)%BITS_PER_LONG)
+#define BIT(x)  (1UL<<OFF(x))
+#define LONG(x) ((x)/BITS_PER_LONG)
+#define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
+
+static void 
+check_abs (int fd, LibHalContext *ctx, const char *udi)
+{
+	long bitmask[NBITS(ABS_MAX)];
+	long bitmask_touch[NBITS(KEY_MAX)];
+	DBusError error;
+
+	if (ioctl (fd, EVIOCGBIT(EV_ABS, sizeof (bitmask)), bitmask) < 0) {
+		HAL_DEBUG (("ioctl EVIOCGBIT for EV_ABS failed"));
+		goto out;
+	}
+
+	if (ioctl (fd, EVIOCGBIT(EV_KEY, sizeof (bitmask_touch)), bitmask_touch) < 0) {
+		HAL_DEBUG (("ioctl EVIOCGBIT for EV_KEY failed"));
+		goto out;
+	}
+	
+	if (!test_bit(ABS_X, bitmask) || !test_bit(ABS_Y, bitmask)) {
+		HAL_DEBUG (("missing x or y absolute axes"));
+		goto out;
+	}
+
+	dbus_error_init (&error);
+	if (test_bit(BTN_TOUCH, bitmask_touch) != 0) {
+		libhal_device_add_capability (ctx, udi, "input.tablet", &error);
+		goto out;
+	}
+	libhal_device_add_capability (ctx, udi, "input.joystick", &error);
+
+out:
+	;
+}
+
+static void 
+check_key (int fd, LibHalContext *ctx, const char *udi)
+{
+	unsigned int i;
+	long bitmask[NBITS(KEY_MAX)];
+	int is_keyboard;
+	DBusError error;
+
+	if (ioctl (fd, EVIOCGBIT(EV_KEY, sizeof (bitmask)), bitmask) < 0) {
+		HAL_DEBUG (("ioctl EVIOCGBIT for EV_KEY failed"));
+		goto out;
+	}
+
+	is_keyboard = FALSE;
+
+	/* All keys that are not buttons are less than BTN_MISC */
+	for (i = KEY_RESERVED + 1; i < BTN_MISC; i++) {
+		if (test_bit (i, bitmask)) {
+			is_keyboard = TRUE;
+			break;
+		}
+	}
+
+	if (is_keyboard) {
+		dbus_error_init (&error);
+		libhal_device_add_capability (ctx, udi, "input.keyboard", &error);
+	}
+
+out:
+	;
+}
+
+static void 
+check_rel (int fd, LibHalContext *ctx, const char *udi)
+{
+	long bitmask[NBITS(REL_MAX)];
+	DBusError error;
+
+	if (ioctl (fd, EVIOCGBIT(EV_REL, sizeof (bitmask)), bitmask) < 0) {
+		HAL_DEBUG (("ioctl EVIOCGBIT for EV_REL failed"));
+		goto out;
+	}
+
+	if (!test_bit (REL_X, bitmask) || !test_bit (REL_Y, bitmask)) {
+		HAL_DEBUG (("missing x or y relative axes"));
+		goto out;
+	}
+
+	dbus_error_init (&error);
+	libhal_device_add_capability (ctx, udi, "input.mouse", &error);
+
+out:
+	;
+}
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	char *physical_device;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char name[128];
+	struct input_id id;
+
+	setup_logger ();
+
+	fd = -1;
+
+	/* assume failure */
+	ret = 1;
+
+	udi = getenv ("UDI");
+	if (udi == NULL)
+		goto out;
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	device_file = getenv ("HAL_PROP_INPUT_DEVICE");
+	if (device_file == NULL)
+		goto out;
+
+	HAL_DEBUG (("Doing probe-input for %s (udi=%s)", device_file, udi));
+
+	fd = open (device_file, O_RDONLY);
+	if (fd < 0) {
+		HAL_ERROR (("Cannot open %s: %s", device_file, strerror (errno)));
+		goto out;
+	}
+
+	/* if we don't have a physical device then only accept input buses
+	 * that we now aren't hotpluggable
+	 */
+	if (ioctl (fd, EVIOCGID, &id) < 0) {
+		HAL_ERROR (("Error: EVIOCGID failed: %s\n", strerror(errno)));
+		goto out;
+	}
+	physical_device = getenv ("HAL_PROP_INPUT_PHYSICAL_DEVICE");
+
+	HAL_DEBUG (("probe-input: id.bustype=%i", id.bustype));
+	if (physical_device == NULL) {
+		switch (id.bustype) {
+		case BUS_I8042: /* x86 legacy port */
+		case BUS_HOST: /* not hotpluggable */
+		case BUS_PARPORT: /* XXX: really needed? */
+		case BUS_ADB: /* ADB on Apple computers */
+			break;
+
+		default:
+			goto out;
+		}
+	}
+
+	/* only consider devices with the event interface */
+	if (ioctl (fd, EVIOCGNAME(sizeof (name)), name) < 0) {
+		HAL_ERROR (("Error: EVIOCGNAME failed: %s\n", strerror(errno)));
+		goto out;
+	}
+	if (!libhal_device_set_property_string (ctx, udi, "info.product", name, &error))
+		goto out;
+	if (!libhal_device_set_property_string (ctx, udi, "input.product", name, &error))
+		goto out;
+
+	check_abs (fd, ctx, udi);
+	check_rel (fd, ctx, udi);
+	check_key (fd, ctx, udi);
+
+	/* success */
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-pc-floppy.c b/hald/linux/probing/probe-pc-floppy.c
new file mode 100644
index 0000000..7a66987
--- /dev/null
+++ b/hald/linux/probing/probe-pc-floppy.c
@@ -0,0 +1,101 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-storage.c : Probe storage devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <fcntl.h>
+#include <linux/fd.h>
+#include <linux/kdev_t.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	char name[256];
+	struct floppy_drive_struct ds;
+
+	fd = -1;
+
+	/* assume failure */
+	ret = 1;
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+
+	setup_logger ();
+	
+	HAL_DEBUG (("Checking if %s is actually present", device_file));
+	
+	/* Check that there actually is a drive at the other end */
+	fd = open (device_file, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		HAL_ERROR (("Could not open %s", device_file));
+		goto out;
+	}
+	
+	/* @todo Could use the name here */
+	ioctl (fd, FDRESET, NULL);
+	if (ioctl (fd, FDGETDRVTYP, name) != 0) {
+		HAL_ERROR (("FDGETDRVTYP failed for %s", device_file));
+		goto out;
+	}
+	HAL_DEBUG (("floppy drive name is '%s'", name));
+
+	if (ioctl (fd, FDPOLLDRVSTAT, &ds)) {
+		HAL_ERROR (("FDPOLLDRVSTAT failed for %s", device_file));
+		goto out;
+	}
+	
+	if (ds.track < 0) {
+		HAL_ERROR (("floppy drive %s seems not to exist", device_file));
+		goto out;
+	}
+
+	/* works */
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-printer.c b/hald/linux/probing/probe-printer.c
new file mode 100644
index 0000000..bec6e9b
--- /dev/null
+++ b/hald/linux/probing/probe-printer.c
@@ -0,0 +1,176 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <glib.h>
+
+#include "libhal/libhal.h"
+#include "../../logger.h"
+
+/* Stolen from kernel 2.6.4, drivers/usb/class/usblp.c */
+#define IOCNR_GET_DEVICE_ID 1
+#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char device_id[1024];
+	char **props;
+	char **iter;
+	char *mfg;
+	char *model;
+	char *serial;
+	char *desc;
+	char *cmd;
+
+	fd = -1;
+
+	/* assume failure */
+	ret = 1;
+
+	setup_logger ();
+	
+	udi = getenv ("UDI");
+	if (udi == NULL) {
+		HAL_ERROR (("UDI not set"));	
+		goto out;
+	}
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		HAL_ERROR (("ctx init failed"));
+		goto out;
+	}
+
+	device_file = getenv ("HAL_PROP_PRINTER_DEVICE");
+	if (device_file == NULL) {
+		HAL_ERROR (("device_file == NULL"));
+		goto out;
+	}
+
+	fd = open (device_file, O_RDONLY);
+	if (fd < 0) {
+		HAL_ERROR (("Cannot open %s", device_file));
+		goto out;
+	}
+
+	if (ioctl (fd, LPIOC_GET_DEVICE_ID (sizeof (device_id)), device_id) < 0) {
+		HAL_ERROR (("Cannot do LPIOC_GET_DEVICE_ID on %s", device_file));
+		goto out;
+	} else
+
+	mfg = NULL;
+	model = NULL;
+	serial = NULL;
+	desc = NULL;
+	cmd = NULL;
+
+	HAL_DEBUG (("device_id = %s", device_id + 2));
+
+	props = g_strsplit (device_id+2, ";", 0);
+	for (iter = props; *iter != NULL; iter++) {
+		if (strncmp (*iter, "MANUFACTURER:", 13) == 0)
+			mfg = *iter + 13;
+		else if (strncmp (*iter, "MFG:", 4) == 0)
+			mfg = *iter + 4;
+		else if (strncmp (*iter, "MODEL:", 6) == 0)
+			model = *iter + 6;
+		else if (strncmp (*iter, "MDL:", 4) == 0)
+			model = *iter + 4;
+		else if (strncmp (*iter, "SN:", 3) == 0)
+			serial = *iter + 3;
+		else if (strncmp (*iter, "SERN:", 5) == 0)
+			serial = *iter + 5;
+		else if (strncmp (*iter, "SERIALNUMBER:", 13) == 0)
+			serial = *iter + 13;
+		else if (strncmp (*iter, "DES:", 4) == 0)
+			desc = *iter + 4;
+		else if (strncmp (*iter, "DESCRIPTION:", 12) == 0)
+			desc = *iter + 12;
+		else if (strncmp (*iter, "COMMAND SET:", 12) == 0)
+			cmd = *iter + 12;
+		else if (strncmp (*iter, "COMMANDSET:", 11) == 0)
+			cmd = *iter + 11;
+		else if (strncmp (*iter, "CMD:", 4) == 0)
+			cmd = *iter + 4;
+	}
+
+	dbus_error_init (&error);
+
+	if (mfg != NULL) {
+		libhal_device_set_property_string (ctx, udi, "info.vendor", mfg, &error);
+		libhal_device_set_property_string (ctx, udi, "printer.vendor", mfg, &error);
+	}		
+
+	if (model != NULL) {
+		libhal_device_set_property_string (ctx, udi, "info.product", model, &error);
+		libhal_device_set_property_string (ctx, udi, "printer.product", model, &error);
+	}
+
+	if (serial != NULL)
+		libhal_device_set_property_string (ctx, udi, "printer.serial", serial, &error);
+
+	if (desc != NULL) {
+		libhal_device_set_property_string (ctx, udi, "printer.description", desc, &error);
+	}
+
+	if (cmd != NULL) {
+		char **cmdset = g_strsplit (cmd, ",", 0);
+		for (iter = cmdset; *iter != NULL; iter++)
+			libhal_device_property_strlist_append (ctx, udi, "printer.commandset", *iter, &error);
+		g_strfreev (cmdset);
+	}
+
+	g_strfreev (props);
+
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-serial.c b/hald/linux/probing/probe-serial.c
new file mode 100644
index 0000000..b70f82b
--- /dev/null
+++ b/hald/linux/probing/probe-serial.c
@@ -0,0 +1,97 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-serial.c : Probe serial ports
+ *
+ * Copyright (C) 2005 Pierre Ossman <drzeus at drzeus.cx>
+ *
+ * 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 <fcntl.h>
+#include <linux/serial.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+
+#include "../../logger.h"
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	struct serial_struct ss;
+
+	fd = -1;
+
+	/* assume failure */
+	ret = 1;
+	
+	setup_logger ();
+
+	if ((udi = getenv ("UDI")) == NULL) {
+		HAL_ERROR (("UDI not set"));
+		goto out;
+	}
+
+	if ((device_file = getenv ("HAL_PROP_SERIAL_DEVICE")) == NULL) {
+		HAL_ERROR (("HAL_PROP_SERIAL_DEVICE not set"));
+		goto out;
+	}
+
+	HAL_DEBUG (("Checking if %s is actually present", device_file));
+	
+	/* Check that there actually is a drive at the other end */
+	fd = open (device_file, O_RDONLY | O_NONBLOCK);
+	if (fd < 0) {
+		HAL_ERROR (("Could not open %s", device_file));
+		goto out;
+	}
+	
+	if (ioctl (fd, TIOCGSERIAL, &ss)) {
+		HAL_ERROR (("TIOCGSERIAL failed for %s", device_file));
+		goto out;
+	}
+	
+	if (ss.type == 0) {
+		HAL_ERROR (("serial port %s seems not to exist", device_file));
+		goto out;
+	}
+
+	/* works */
+	ret = 0;
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-smbios.c b/hald/linux/probing/probe-smbios.c
new file mode 100644
index 0000000..2beb809
--- /dev/null
+++ b/hald/linux/probing/probe-smbios.c
@@ -0,0 +1,243 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-smbios.c : Probe system BIOS according to the SMBIOS/DMI standard
+ *
+ * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005 Richard Hughes, <richard at hughsie.com>
+ *
+ * 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 <ctype.h>
+#include <fcntl.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "libhal/libhal.h"
+#include "../../logger.h"
+
+#define DMIPARSER_STATE_IGNORE		0
+#define DMIPARSER_STATE_BIOS		1
+#define DMIPARSER_STATE_SYSTEM		2
+#define DMIPARSER_STATE_CHASSIS		3
+
+#define strbegin(buf, str) (strncmp (buf, str, strlen (str)) == 0)
+
+/* global */
+char *udi = NULL;
+LibHalContext *ctx = NULL;
+
+/** Finds the start of a null terminated string and sets HAL
+ *  property if valid.
+ *
+ *  @param	buf		The non tabbed prefixed, null terminated string
+ *  @param	str		The strings to compare with e.g. "Vendor:"
+ *  @param	prop		The HAL property to set
+ *  @return			TRUE is found, FALSE otherwise.
+ */
+static int
+setstr (char *buf, char *str, char *prop)
+{
+	DBusError error;
+	char *value;
+
+	if (strbegin (buf, str)) {
+		dbus_error_init (&error);
+		value = buf + strlen (str) + 1;
+		libhal_device_set_property_string (ctx, udi, prop, value, &error);
+		HAL_DEBUG (("Setting %s='%s'", prop, value));
+		return TRUE;
+	}
+	return FALSE;
+}
+
+/** Main entry point
+ *
+ *  @param	argc		Number of arguments given to program
+ *  @param	argv		Arguments given to program
+ *  @return			Return code
+ */
+int 
+main (int argc, char *argv[])
+{
+	int ret;
+	DBusError error;
+	char buf[512];
+	char *nbuf;
+	int dmipipe[2];
+	int nullfd;
+	int tmp_ret;
+	FILE *f;
+	int dmiparser_state = DMIPARSER_STATE_IGNORE;
+
+	/* on some system chassis pops up several times,
+	 * so only take the first entry for each
+	 */
+	int dmiparser_done_bios = FALSE;
+	int dmiparser_done_system = FALSE;
+	int dmiparser_done_chassis = FALSE;
+
+	/* assume failure */
+	ret = 1;
+
+	setup_logger ();
+	
+	udi = getenv ("UDI");
+	if (udi == NULL) {
+		HAL_ERROR (("UDI not set"));
+		goto out;
+	}
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
+		HAL_ERROR (("ctx init failed"));
+		goto out;
+	}
+
+	tmp_ret = pipe (dmipipe);	
+	f = fdopen (dmipipe[0], "r");
+	nullfd = open ("/dev/null", O_RDONLY);
+	
+	/* fork the child process */
+	switch (fork ()) {
+	case 0:
+		/* child */
+		
+		dup2 (nullfd, STDIN_FILENO);
+		dup2 (dmipipe[1], STDOUT_FILENO);
+		close (dmipipe[0]);
+		close (dmipipe[1]);
+		
+		/* execute the child */
+		execl ("/usr/sbin/dmidecode", "/usr/sbin/dmidecode", NULL);
+		
+		/* throw an error if we ever reach this point */
+		HAL_ERROR (("Failed to execute dmidecode!"));
+		exit (1);
+		break;
+	case -1:
+		HAL_ERROR (("Cannot fork!"));
+		break;
+	}
+	
+	/* parent continues from here */
+	
+	/* close unused descriptor */
+	close (dmipipe[1]);
+	
+	/* read the output of the child */
+	while(fgets (buf, sizeof(buf), f) != NULL)
+	{
+		unsigned int i;
+		unsigned int len;
+		unsigned int tabs = 0;
+
+		/* trim whitespace */
+		len = strlen (buf);
+
+		/* check that will fit in buffer */
+		if (len >= sizeof (buf))
+			continue;
+
+		/* not big enough for data, and protects us from underflow */
+		if (len < 3) {
+			dmiparser_state = DMIPARSER_STATE_IGNORE;
+			continue;
+		}
+
+		/* find out number of leading tabs */
+		if (buf[0] == '\t' && buf[1] == '\t')
+			tabs = 2; /* this is list data */
+		else if (buf[0] == '\t')
+			tabs = 1; /* this is data, 0 is section type */
+
+		if (tabs == 2)
+			/* we do not proccess data at depth 2 */
+			continue;
+			
+		/* set the section type */
+		if (tabs == 0) {
+			if (!dmiparser_done_bios && strbegin (buf, "BIOS Information"))
+				dmiparser_state = DMIPARSER_STATE_BIOS;
+			else if (!dmiparser_done_system && strbegin (buf, "System Information"))
+				dmiparser_state = DMIPARSER_STATE_SYSTEM;
+			else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information"))
+				dmiparser_state = DMIPARSER_STATE_CHASSIS;
+			else
+				/*
+				 * We do not match the other sections,
+				 * or sections we have processed before
+				 */
+				dmiparser_state = DMIPARSER_STATE_IGNORE;
+			continue; /* next line */
+		}
+
+		/* we are not in a section we know, no point continueing */
+		if (dmiparser_state == DMIPARSER_STATE_IGNORE)
+			continue;
+
+		/* removes the leading tab */
+		nbuf = &buf[1];
+
+		/* removes the trailing spaces */
+		for (i = len - 2; isspace (nbuf[i]) && i >= 0; --i)
+			nbuf[i] = '\0';
+
+		if (dmiparser_state == DMIPARSER_STATE_BIOS) {
+			setstr (nbuf, "Vendor:", "smbios.bios.vendor");
+			setstr (nbuf, "Version:", "smbios.bios.version");
+			setstr (nbuf, "Release Date:", "smbios.bios.release_date");
+			dmiparser_done_bios = TRUE;
+		} else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) {
+			setstr (nbuf, "Manufacturer:", "smbios.system.manufacturer");
+			setstr (nbuf, "Product Name:", "smbios.system.product");
+			setstr (nbuf, "Version:", "smbios.system.version");
+			setstr (nbuf, "Serial Number:", "smbios.system.serial");
+			setstr (nbuf, "UUID:", "smbios.system.uuid");
+			dmiparser_done_system = TRUE;
+		} else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) {
+			setstr (nbuf, "Manufacturer:", "smbios.chassis.manufacturer");
+			setstr (nbuf, "Type:", "smbios.chassis.type");
+			dmiparser_done_chassis = TRUE;
+		}
+	}
+
+	/* as read to EOF, close */
+	fclose (f);
+
+	/* return success */
+	ret = 0;
+
+out:
+	/* free ctx */
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-storage.c b/hald/linux/probing/probe-storage.c
new file mode 100644
index 0000000..7b84a64
--- /dev/null
+++ b/hald/linux/probing/probe-storage.c
@@ -0,0 +1,427 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-storage.c : Probe storage devices
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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 <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/kdev_t.h>
+#include <linux/cdrom.h>
+#include <linux/fs.h>
+#include <mntent.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <libvolume_id.h>
+
+#include "libhal/libhal.h"
+#include "linux_dvd_rw_utils.h"
+
+#include "../../logger.h"
+
+static void vid_log(int priority, const char *file, int line, const char *format, ...)
+{
+	char log_str[1024];
+	va_list args;
+
+	va_start(args, format);
+	vsnprintf(log_str, sizeof(log_str), format, args);
+	logger_forward_debug("%s:%i %s", file, line, log_str);
+	va_end(args);
+}
+
+
+/** Check if a filesystem on a special device file is mounted
+ *
+ *  @param  device_file         Special device file, e.g. /dev/cdrom
+ *  @return                     TRUE iff there is a filesystem system mounted
+ *                              on the special device file
+ */
+static dbus_bool_t
+is_mounted (const char *device_file)
+{
+	FILE *f;
+	dbus_bool_t rc;
+	struct mntent mnt;
+	struct mntent *mnte;
+	char buf[512];
+
+	rc = FALSE;
+
+	if ((f = setmntent ("/etc/mtab", "r")) == NULL)
+		goto out;
+
+	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
+		if (strcmp (device_file, mnt.mnt_fsname) == 0) {
+			rc = TRUE;
+			goto out1;
+		}
+	}
+
+out1:
+	endmntent (f);
+out:
+	return rc;
+}
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *bus;
+	char *drive_type;
+	char *sysfs_path;
+	dbus_bool_t only_check_for_fs;
+
+	fd = -1;
+
+	/* hook in our debug into libvolume_id */
+	volume_id_log_fn = vid_log;
+
+	/* assume failure */
+	ret = 1;
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
+		goto out;
+	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
+		goto out;
+	if ((sysfs_path = getenv ("HAL_PROP_LINUX_SYSFS_PATH")) == NULL)
+		goto out;
+
+	setup_logger ();
+
+	if (argc == 2 && strcmp (argv[1], "--only-check-for-media") == 0)
+		only_check_for_fs = TRUE;
+	else
+		only_check_for_fs = FALSE;
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	HAL_DEBUG (("Doing probe-storage for %s (bus %s) (drive_type %s) (udi=%s) (--only-check-for-fs==%d)", 
+	     device_file, bus, drive_type, udi, only_check_for_fs));
+
+	if (!only_check_for_fs) {
+		/* Get properties for CD-ROM drive */
+		if (strcmp (drive_type, "cdrom") == 0) {
+			int capabilities;
+			int read_speed, write_speed;
+			char *write_speeds;
+			
+			HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file));
+			fd = open (device_file, O_RDONLY | O_NONBLOCK);
+			if (fd < 0) {
+				HAL_ERROR (("Cannot open %s: %s", device_file, strerror (errno)));
+				goto out;
+			}
+			HAL_DEBUG (("Returned from open(2)"));
+
+			if (ioctl (fd, CDROM_SET_OPTIONS, CDO_USE_FFLAGS) < 0) {
+				HAL_ERROR (("Error: CDROM_SET_OPTIONS failed: %s\n", strerror(errno)));
+				close (fd);
+				goto out;
+			}
+			
+			capabilities = ioctl (fd, CDROM_GET_CAPABILITY, 0);
+			if (capabilities < 0) {
+				close (fd);
+				goto out;
+			}
+			
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrwdl", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrdl", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bd", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bdre", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvd", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvdr", FALSE, &error);
+			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvdrw", FALSE, &error);
+			
+			if (capabilities & CDC_CD_R) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", TRUE, &error);
+			}
+			
+			if (capabilities & CDC_CD_RW) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", TRUE, &error);
+			}
+			if (capabilities & CDC_DVD) {
+				int profile;
+				
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", TRUE, &error);
+
+				profile = get_dvd_r_rw_profile (fd);
+				HAL_DEBUG (("get_dvd_r_rw_profile returned: %d", profile));
+
+				if (profile & DRIVE_CDROM_CAPS_DVDRW)
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", TRUE, &error);
+				if (profile & DRIVE_CDROM_CAPS_DVDPLUSR)
+					libhal_device_set_property_bool(ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
+				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRW)
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
+				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRWDL)
+					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrwdl", TRUE, &error);
+				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRDL)
+                                        libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrdl", TRUE, &error);
+			}
+			if (capabilities & CDC_DVD_R) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", TRUE, &error);
+			}
+			if (capabilities & CDC_DVD_RAM) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", TRUE, &error);
+			}
+			
+			/* while we're at it, check if we support media changed */
+			if (capabilities & CDC_MEDIA_CHANGED) {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", TRUE, &error);
+			} else {
+				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", FALSE, &error);
+			}
+			
+			if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds) >= 0) {
+				libhal_device_set_property_int (ctx, udi, "storage.cdrom.read_speed", read_speed, &error);
+				if (write_speed > 0) {
+					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", write_speed, &error);
+					if (write_speeds != NULL)
+					{
+						gchar **wspeeds;
+						int i;
+						wspeeds = g_strsplit_set (write_speeds, ",", -1);
+						for (i = 0 ; wspeeds[i] != NULL; i++) {
+					                if (strlen (wspeeds[i]) > 0)
+								libhal_device_property_strlist_append (ctx, udi, "storage.cdrom.write_speeds", wspeeds[i], &error);
+						}
+						free (write_speeds);
+					}
+				}	
+				else
+					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", 0, &error);
+			}
+
+			close (fd);
+		}
+		
+	} /* !only_check_for_fs */
+
+	ret = 0;
+
+	/* Also return 2 if we're a cdrom and we got a disc */
+	if (strcmp (drive_type, "cdrom") == 0) {
+		char *support_media_changed_str;
+		int support_media_changed;
+		int got_media;
+		int drive;
+
+		HAL_DEBUG (("Checking for optical disc on %s", device_file));
+
+		support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
+		if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
+			support_media_changed = TRUE;
+		else
+			support_media_changed = FALSE;
+
+		HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK | O_EXCL)", device_file));
+		fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
+
+		if (fd < 0 && errno == EBUSY) {
+			/* this means the disc is mounted or some other app,
+			 * like a cd burner, has already opened O_EXCL */
+				
+			/* HOWEVER, when starting hald, a disc may be
+			 * mounted; so check /etc/mtab to see if it
+			 * actually is mounted. If it is we retry to open
+			 * without O_EXCL
+			 */
+			if (!is_mounted (device_file))
+				goto out;
+
+			HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file));
+			fd = open (device_file, O_RDONLY | O_NONBLOCK);
+		}
+
+		if (fd < 0) {
+			HAL_DEBUG (("open failed for %s: %s", device_file, strerror (errno)));
+			goto out;
+		}
+
+		got_media = FALSE;
+
+		/* Check if a disc is in the drive
+		 *
+		 * @todo Use MMC-2 API if applicable
+		 */
+		drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
+		switch (drive) {
+			/* explicit fallthrough */
+		case CDS_NO_INFO:
+		case CDS_NO_DISC:
+		case CDS_TRAY_OPEN:
+		case CDS_DRIVE_NOT_READY:
+			break;
+			
+		case CDS_DISC_OK:
+			/* some CD-ROMs report CDS_DISK_OK even with an open
+			 * tray; if media check has the same value two times in
+			 * a row then this seems to be the case and we must not
+			 * report that there is a media in it. */
+			if (support_media_changed &&
+			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
+			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
+			} else {
+				got_media = TRUE;
+			}
+			break;
+			
+		case -1:
+			HAL_ERROR (("Error: CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
+			break;
+			
+		default:
+			break;
+		}
+
+		if (got_media) {
+			uint64_t size;
+			ret = 2;
+			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
+			if (ioctl (fd, BLKGETSIZE64, &size) == 0) {
+				HAL_DEBUG (("media size = %llu", size));
+				libhal_device_set_property_uint64 (ctx, udi, "storage.removable.media_size", size, &error);
+			}
+		} else {
+			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
+		}
+
+		close (fd);
+	} else {
+		struct volume_id *vid;
+		GDir *dir;
+		const gchar *partition;
+		const gchar *main_device;
+		size_t main_device_len;
+		uint64_t size;
+
+		HAL_DEBUG (("Checking for file system on %s", device_file));
+
+		/* See if we got a file system on the main block device - which 
+		 * means doing a data (non O_NONBLOCK) open - this might fail, 
+		 * especially if we don't have any media...
+		 */
+		HAL_DEBUG (("Doing open (\"%s\", O_RDONLY)", device_file));
+		fd = open (device_file, O_RDONLY);
+		if (fd < 0) {
+			HAL_DEBUG (("Cannot open %s: %s", device_file, strerror (errno)));
+			/* no media */
+			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
+			goto out;
+		}
+		HAL_DEBUG (("Returned from open(2)"));
+
+		/* if we get to here, we have media */
+		libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
+
+		if (ioctl (fd, BLKGETSIZE64, &size) != 0)
+			size = 0;
+		
+		libhal_device_set_property_uint64 (ctx, udi, "storage.removable.media_size", size, &error);
+
+		/* if the kernel has created partitions, we don't look for a filesystem */
+		main_device = strrchr (sysfs_path, '/');
+		if (main_device == NULL)
+			goto out;
+		main_device = &main_device[1];
+		main_device_len = strlen (main_device);
+		HAL_DEBUG (("look for existing partitions for %s", main_device));
+		if ((dir = g_dir_open (sysfs_path, 0, NULL)) == NULL) {
+			HAL_DEBUG (("failed to open sysfs dir"));
+			goto out;
+		}
+		while ((partition = g_dir_read_name (dir)) != NULL) {
+			if (strncmp (main_device, partition, main_device_len) == 0 &&
+			    isdigit (partition[main_device_len])) {
+				HAL_DEBUG (("partition %s found, skip probing for filesystem", partition));
+				g_dir_close (dir);
+				goto out;
+			}
+		}
+		g_dir_close (dir);
+
+		/* probe for file system */
+		vid = volume_id_open_fd (fd);
+		if (vid != NULL) {
+			if (volume_id_probe_all (vid, 0, size) == 0) {
+				/* signal to hald that we've found something and a fakevolume
+				 * should be added - see hald/linux/blockdev.c:add_blockdev_probing_helper_done()
+				 * and hald/linux/blockdev.c:block_rescan_storage_done().
+				 */
+				if (vid->usage_id == VOLUME_ID_FILESYSTEM ||
+				    vid->usage_id == VOLUME_ID_RAID ||
+				    vid->usage_id == VOLUME_ID_OTHER ||
+				    vid->usage_id == VOLUME_ID_CRYPTO)
+					ret = 2;
+			} else {
+				;
+			}
+			volume_id_close(vid);
+		}
+		close (fd);
+	}
+	
+out:
+
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+}
diff --git a/hald/linux/probing/probe-volume.c b/hald/linux/probing/probe-volume.c
new file mode 100644
index 0000000..8a57e52
--- /dev/null
+++ b/hald/linux/probing/probe-volume.c
@@ -0,0 +1,812 @@
+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
+ ***************************************************************************
+ * CVSID: $Id$
+ *
+ * probe-volume.c : Probe for volume type (filesystems etc.)
+ *
+ * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
+ *
+ * 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 <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/cdrom.h>
+#include <linux/fs.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <libvolume_id.h>
+
+#include "libhal/libhal.h"
+#include "linux_dvd_rw_utils.h"
+#include "../../logger.h"
+
+static void vid_log(int priority, const char *file, int line, const char *format, ...)
+{
+	char log_str[1024];
+	va_list args;
+
+	va_start(args, format);
+	vsnprintf(log_str, sizeof(log_str), format, args);
+	logger_forward_debug("%s:%i %s", file, line, log_str);
+	va_end(args);
+}
+
+static gchar *
+strdup_valid_utf8 (const char *str)
+{
+	char *endchar;
+	char *newstr;
+	unsigned int fixes;
+
+	if (str == NULL)
+		return NULL;
+
+	newstr = g_strdup (str);
+
+	fixes = 0;
+	while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
+		*endchar = '_';
+		++fixes;
+	}
+
+	/* If we had to fix more than 20% of the characters, give up */
+	if (fixes > 0 && g_utf8_strlen (newstr, -1) / fixes < 5) {
+	    g_free (newstr);
+	    newstr = g_strdup("");
+	}
+
+	return newstr;
+}
+
+/* probe_msdos_part_table: return array of partiton type numbers */
+#define BSIZE				0x200
+#define MSDOS_MAGIC			"\x55\xaa"
+#define MSDOS_PARTTABLE_OFFSET		0x1be
+#define MSDOS_SIG_OFF			0x1fe
+#define DOS_EXTENDED_PARTITION		0x05
+#define LINUX_EXTENDED_PARTITION	0x85
+#define WIN98_EXTENDED_PARTITION	0x0f
+#define is_extended(type) \
+	(type == DOS_EXTENDED_PARTITION ||	\
+	 type == WIN98_EXTENDED_PARTITION ||	\
+	 type == LINUX_EXTENDED_PARTITION)
+
+struct msdos_part_entry {
+	uint8_t part_type;
+	uint64_t start;
+	uint64_t size;
+};
+
+static struct msdos_part_entry *
+probe_msdos_part_table(int fd)
+{
+	static struct msdos_part_entry partition_id_index[256];
+	unsigned int partition_count;
+	const uint8_t buf[BSIZE];
+	int i;
+	uint64_t poff;
+	uint64_t plen;
+	uint64_t extended = 0;
+	uint64_t next;
+	int limit;
+	int empty = 1;
+	struct msdos_partition_entry {
+		uint8_t		boot_ind;
+		uint8_t		head;
+		uint8_t		sector;
+		uint8_t		cyl;
+		uint8_t		sys_ind;
+		uint8_t		end_head;
+		uint8_t		end_sector;
+		uint8_t		end_cyl;
+		uint32_t	start_sect;
+		uint32_t	nr_sects;
+	} __attribute__((packed)) *part;
+
+	if (lseek(fd, 0, SEEK_SET) < 0) {
+		HAL_DEBUG (("lseek failed (%s)", strerror(errno)));
+		return NULL;
+	}
+	if (read(fd, &buf, BSIZE) < BSIZE) {
+		HAL_DEBUG (("read failed (%s)", strerror(errno)));
+		return NULL;
+	}
+	if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
+		return NULL;
+
+	part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
+	/* check flags on all entries for a valid partition table */
+	for (i = 0; i < 4; i++) {
+		if (part[i].boot_ind != 0 &&
+		    part[i].boot_ind != 0x80)
+			return NULL;
+
+		if (GINT32_FROM_LE(part[i].nr_sects) != 0)
+			empty = 0;
+	}
+	if (empty == 1)
+		return NULL;
+
+	memset(partition_id_index, 0x00, sizeof(partition_id_index));
+
+	for (i = 0; i < 4; i++) {
+		poff = (uint64_t) GINT32_FROM_LE(part[i].start_sect) * BSIZE;
+		plen = (uint64_t) GINT32_FROM_LE(part[i].nr_sects) * BSIZE;
+
+		if (plen == 0)
+			continue;
+
+		partition_id_index[i].part_type = part[i].sys_ind;
+		partition_id_index[i].start = poff;
+		partition_id_index[i].size = plen;
+		HAL_DEBUG (("part %d -> type=%d off=%lld size=%lld", i, part[i].sys_ind, poff, plen));
+
+		if (is_extended(part[i].sys_ind)) {
+			HAL_DEBUG (("found extended partition at 0x%llx", (unsigned long long) poff));
+			if (extended == 0)
+				extended = poff;
+		} else {
+			HAL_DEBUG (("found 0x%x primary data partition at 0x%llx, len 0x%llx",
+			    part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen));
+		}
+	}
+
+	/* follow extended partition chain and add data partitions */
+	partition_count = 4;
+	limit = 255;
+	next = extended;
+	while (next != 0) {
+		uint64_t oldnext;
+
+		if (limit-- == 0) {
+			HAL_DEBUG(("extended chain limit reached"));
+			break;
+		}
+
+		HAL_DEBUG (("read 0x%llx (%llu)", next, next));
+		if (lseek(fd, next, SEEK_SET) < 0) {
+			HAL_DEBUG(("lseek failed (%s)", strerror(errno)));
+			return NULL;
+		}
+		if (read(fd, &buf, BSIZE) < BSIZE) {
+			HAL_DEBUG(("read failed (%s)", strerror(errno)));
+			return NULL;
+		}
+		if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
+			break;
+
+		oldnext = next;
+		next = 0;
+
+		part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
+		for (i = 0; i < 4; i++) {
+			poff = (uint64_t) GINT32_FROM_LE(part[i].start_sect) * BSIZE;
+			plen = (uint64_t) GINT32_FROM_LE(part[i].nr_sects) * BSIZE;
+
+			if (plen == 0)
+				continue;
+
+			if (is_extended(part[i].sys_ind)) {
+				HAL_DEBUG(("found extended partition (chain) at 0x%llx", (unsigned long long) poff));
+				if (next == 0)
+					next = extended + poff;
+			} else {
+				HAL_DEBUG(("found 0x%x logical data partition at 0x%llx, len 0x%llx",
+					part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen));
+
+				partition_id_index[partition_count].part_type = part[i].sys_ind;
+				partition_id_index[partition_count].start = oldnext + poff;
+				partition_id_index[partition_count].size = plen;
+
+				partition_count++;
+			}
+		}
+	}
+
+	return partition_id_index;
+}
+
+static void
+set_volume_id_values (LibHalContext *ctx, const char *udi, LibHalChangeSet *changes, struct volume_id *vid)
+{
+	char buf[256];
+	const char *usage;
+	char *volume_label;
+	DBusError error;
+
+	dbus_error_init (&error);
+
+	switch (vid->usage_id) {
+	case VOLUME_ID_FILESYSTEM:
+		usage = "filesystem";
+		break;
+	case VOLUME_ID_OTHER:
+		usage = "other";
+		break;
+	case VOLUME_ID_RAID:
+		usage = "raid";
+		break;
+	case VOLUME_ID_CRYPTO:
+		usage = "crypto";
+		break;
+	case VOLUME_ID_UNUSED:
+		libhal_changeset_set_property_string (changes, "info.product", "Volume (unused)");
+		usage = "unused";
+		return;
+	default:
+		usage = "";
+	}
+
+	libhal_changeset_set_property_string (changes, "volume.fsusage", usage);
+	HAL_DEBUG (("volume.fsusage = '%s'", usage));
+
+	libhal_changeset_set_property_string (changes, "volume.fstype", vid->type);
+	HAL_DEBUG(("volume.fstype = '%s'", vid->type));
+	if (vid->type_version[0] != '\0') {
+		libhal_changeset_set_property_string (changes, "volume.fsversion", vid->type_version);
+		HAL_DEBUG(("volume.fsversion = '%s'", vid->type_version));
+	}
+	libhal_changeset_set_property_string (changes, "volume.uuid", vid->uuid);
+	HAL_DEBUG(("volume.uuid = '%s'", vid->uuid));
+
+	/* we need to be sure for a utf8 valid label, because dbus accept only utf8 valid strings */
+	volume_label = strdup_valid_utf8 (vid->label);
+	if( volume_label != NULL ) {
+		libhal_changeset_set_property_string (changes, "volume.label", volume_label);
+		HAL_DEBUG(("volume.label = '%s'", volume_label));
+		
+		if (strlen(volume_label) > 0) {	
+			libhal_changeset_set_property_string (changes, "info.product", volume_label);
+		}
+		else {
+			snprintf (buf, sizeof (buf), "Volume (%s)", vid->type);
+			libhal_changeset_set_property_string (changes, "info.product", buf);
+		}
+		g_free(volume_label);
+	} else {
+		snprintf (buf, sizeof (buf), "Volume (%s)", vid->type);
+		libhal_changeset_set_property_string (changes, "info.product", buf);
+	}
+}
+
+static void
+advanced_disc_detect (LibHalContext *ctx, const char *udi, LibHalChangeSet *changes,
+                      int fd, const char *device_file)
+{
+	/* the discs block size */
+	unsigned short bs; 
+	/* the path table size */
+	unsigned short ts;
+	/* the path table location (in blocks) */
+	unsigned int tl;
+	/* length of the directory name in current path table entry */
+	unsigned char len_di = 0;
+	/* the number of the parent directory's path table entry */
+	unsigned int parent = 0; 
+	/* filename for the current path table entry */
+	char dirname[256];
+	/* our position into the path table */
+	int pos = 0; 
+	/* the path table record we're on */
+	int curr_record = 1; 
+	/* loop counter */
+	int i; 
+	DBusError error;
+	
+	dbus_error_init (&error);
+	
+	/* set defaults */
+	libhal_changeset_set_property_bool (changes, "volume.disc.is_videodvd", FALSE);
+	libhal_changeset_set_property_bool (changes, "volume.disc.is_vcd", FALSE);
+	libhal_changeset_set_property_bool (changes, "volume.disc.is_svcd", FALSE);
+	
+	/* read the block size */
+	lseek (fd, 0x8080, SEEK_CUR);
+	if (read (fd, &bs, 2) != 2)
+	{
+		HAL_DEBUG(("Advanced probing on %s failed while reading block size", device_file));
+		goto out;
+	}
+
+	/* read in size of path table */
+	lseek (fd, 2, SEEK_CUR);
+	if (read (fd, &ts, 2) != 2)
+	{
+		HAL_DEBUG(("Advanced probing on %s failed while reading path table size", device_file));
+		goto out;
+	}
+
+	/* read in which block path table is in */
+	lseek (fd, 6, SEEK_CUR);
+	if (read (fd, &tl, 4) != 4)
+	{
+		HAL_DEBUG(("Advanced probing on %s failed while reading path table block", device_file));
+		goto out;
+	}
+
+	/* seek to the path table */
+	lseek (fd, GUINT16_FROM_LE (bs) * GUINT32_FROM_LE (tl), SEEK_SET);
+
+	/* loop through the path table entriesi */
+	while (pos < GUINT16_FROM_LE (ts))
+	{
+		/* get the length of the filename of the current entry */
+		if (read (fd, &len_di, 1) != 1)
+		{
+			HAL_DEBUG(("Advanced probing on %s failed, cannot read more entries", device_file));
+			break;
+		}
+
+		/* get the record number of this entry's parent
+		   i'm pretty sure that the 1st entry is always the top directory */
+		lseek (fd, 5, SEEK_CUR);
+		if (read (fd, &parent, 2) != 2)
+		{
+			HAL_DEBUG(("Advanced probing on %s failed, couldn't read parent entry", device_file));
+			break;
+		}
+		
+		/* read the name */
+		if (read (fd, dirname, len_di) != len_di)
+		{
+			HAL_DEBUG(("Advanced probing on %s failed, couldn't read the entry name", device_file));
+			break;
+		}
+		dirname[len_di] = 0;
+
+		/* strcasecmp is not POSIX or ANSI C unfortunately */
+		i=0;
+		while (dirname[i]!=0)
+		{
+			dirname[i] = (char)toupper (dirname[i]);
+			i++;
+		}
+
+		/* if we found a folder that has the root as a parent, and the directory name matches 
+		   one of the special directories then set the properties accordingly */
+		if (GUINT16_FROM_LE (parent) == 1)
+		{
+			if (!strcmp (dirname, "VIDEO_TS"))
+			{
+				libhal_changeset_set_property_bool (changes, "volume.disc.is_videodvd", TRUE);
+				HAL_DEBUG(("Disc in %s is a Video DVD", device_file));
+				break;
+			}
+			else if (!strcmp (dirname, "VCD"))
+			{
+				libhal_changeset_set_property_bool (changes, "volume.disc.is_vcd", TRUE);
+				HAL_DEBUG(("Disc in %s is a Video CD", device_file));
+				break;
+			}
+			else if (!strcmp (dirname, "SVCD"))
+			{
+				libhal_changeset_set_property_bool (changes, "volume.disc.is_svcd", TRUE);
+				HAL_DEBUG(("Disc in %s is a Super Video CD", device_file));
+				break;
+			}
+		}
+
+		/* all path table entries are padded to be even, 
+		   so if this is an odd-length table, seek a byte to fix it */
+		if (len_di%2 == 1)
+		{
+			lseek (fd, 1, SEEK_CUR);
+			pos++;
+		}
+
+		/* update our position */
+		pos += 8 + len_di;
+		curr_record++;
+	}
+
+out:
+	/* go back to the start of the file */
+	lseek (fd, 0, SEEK_SET);
+}
+
+int 
+main (int argc, char *argv[])
+{
+	int fd;
+	int ret;
+	char *udi;
+	char *device_file;
+	LibHalContext *ctx = NULL;
+	DBusError error;
+	char *parent_udi;
+	char *sysfs_path;
+	struct volume_id *vid;
+	char *stordev_dev_file;
+	char *partition_number_str;
+	char *is_disc_str;
+	dbus_bool_t is_disc;
+	unsigned int partition_number;
+	unsigned int block_size;
+	dbus_uint64_t vol_size;
+	dbus_bool_t should_probe_for_fs;
+	dbus_uint64_t vol_probe_offset = 0;
+	LibHalChangeSet *changeset;
+	fd = -1;
+
+	/* hook in our debug into libvolume_id */
+	volume_id_log_fn = vid_log;
+
+	/* assume failure */
+	ret = 1;
+
+	if ((udi = getenv ("UDI")) == NULL)
+		goto out;
+	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
+		goto out;
+	if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL)
+		goto out;
+	if ((sysfs_path = getenv ("HAL_PROP_LINUX_SYSFS_PATH")) == NULL)
+		goto out;
+	partition_number_str = getenv ("HAL_PROP_VOLUME_PARTITION_NUMBER");
+	if (partition_number_str != NULL)
+		partition_number = (unsigned int) atoi (partition_number_str);
+	else
+		partition_number = (unsigned int) -1;
+
+	is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC");
+	if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0)
+		is_disc = TRUE;
+	else
+		is_disc = FALSE;
+
+	setup_logger ();
+
+	dbus_error_init (&error);
+	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
+		goto out;
+
+	changeset = libhal_device_new_changeset (udi);
+	if (changeset == NULL) {
+		HAL_DEBUG(("Cannot initialize changeset"));
+		goto out;
+	}
+
+	HAL_DEBUG(("Doing probe-volume for %s\n", device_file));
+
+	fd = open (device_file, O_RDONLY);
+	if (fd < 0)
+		goto out;
+
+	/* block size and total size */
+	if (ioctl (fd, BLKSSZGET, &block_size) == 0) {
+		HAL_DEBUG(("volume.block_size = %d", block_size));
+		libhal_changeset_set_property_int (changeset, "volume.block_size", block_size);
+	}
+	if (ioctl (fd, BLKGETSIZE64, &vol_size) == 0) {
+		HAL_DEBUG(("volume.size = %llu", vol_size));
+		libhal_changeset_set_property_uint64 (changeset, "volume.size", vol_size);
+	} else
+		vol_size = 0;
+
+	should_probe_for_fs = TRUE;
+
+	if (is_disc) {
+		int type;
+		guint64 capacity;
+		struct cdrom_tochdr; /* toc_hdr; */
+
+		/* defaults */
+		libhal_changeset_set_property_string (changeset, "volume.disc.type", "unknown");
+		libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", FALSE);
+		libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", FALSE);
+		libhal_changeset_set_property_bool (changeset, "volume.disc.is_blank", FALSE);
+		libhal_changeset_set_property_bool (changeset, "volume.disc.is_appendable", FALSE);
+		libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", FALSE);
+
+		/* Suggested by Alex Larsson to get rid of log spewage
+		 * on Alan's cd changer (RH bug 130649) */
+		if (ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) {
+			goto out;
+		}
+
+		/* check for audio/data/blank */
+		type = ioctl (fd, CDROM_DISC_STATUS, CDSL_CURRENT);
+		switch (type) {
+		case CDS_AUDIO:		/* audio CD */
+			libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", TRUE);
+			HAL_DEBUG(("Disc in %s has audio", device_file));
+			should_probe_for_fs = FALSE;
+			break;
+		case CDS_MIXED:		/* mixed mode CD */
+			libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", TRUE);
+			libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", TRUE);
+			HAL_DEBUG(("Disc in %s has audio+data", device_file));
+			break;
+		case CDS_DATA_1:	/* data CD */
+		case CDS_DATA_2:
+		case CDS_XA_2_1:
+		case CDS_XA_2_2:
+			libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", TRUE);
+			HAL_DEBUG(("Disc in %s has data", device_file));
+			advanced_disc_detect (ctx, udi, changeset, fd, device_file);
+			break;
+		case CDS_NO_INFO:	/* blank or invalid CD */
+			libhal_changeset_set_property_bool (changeset, "volume.disc.is_blank", TRUE);
+			/* set the volume size to 0 if disc is blank and not as 4 from BLKGETSIZE64 */
+			libhal_changeset_set_property_int (changeset, "volume.block_size", 0);
+			HAL_DEBUG(("Disc in %s is blank", device_file));
+			should_probe_for_fs = FALSE;
+			break;
+			
+		default:		/* should never see this */
+			libhal_changeset_set_property_string (changeset, "volume.disc_type", "unknown");
+			HAL_DEBUG(("Disc in %s returned unknown CDROM_DISC_STATUS", device_file));
+			should_probe_for_fs = FALSE;
+			break;
+		}
+		
+		/* see table 87 - Profile List in MMC-5 for details on disc type
+		 * http://www.t10.org/drafts.htm#mmc5
+		 */
+		type = get_disc_type (fd);
+		HAL_DEBUG(("get_disc_type returned 0x%02x", type));
+		if (type != -1) {
+			switch (type) {
+			case 0x08: /* CD-ROM */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_rom");
+				break;
+			case 0x09: /* CD-R */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_r");
+				break;
+			case 0x0a: /* CD-RW */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_rw");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x10: /* DVD-ROM */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rom");
+				break;
+			case 0x11: /* DVD-R Sequential */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_r");
+				break;
+			case 0x12: /* DVD-RAM */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_ram");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x13: /* DVD-RW Restricted Overwrite */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rw");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x14: /* DVD-RW Sequential */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rw");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x1A: /* DVD+RW */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_rw");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x1B: /* DVD+R */
+				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_r");
+				break;
+			case 0x2B: /* DVD+R Double Layer */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_r_dl");
+				break;
+			case 0x40: /* BD-ROM  */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_rom");
+				break;
+			case 0x41: /* BD-R Sequential */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_r");
+				break;
+			case 0x42: /* BD-R Random */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_r");
+				break;
+			case 0x43: /* BD-RE */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_re");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			case 0x50: /* HD DVD-ROM */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_rom");
+				break;
+			case 0x51: /* HD DVD-R */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_r");
+				break;
+			case 0x52: /* HD DVD-Rewritable */
+                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_rw");
+				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+				break;
+			default: 
+				break;
+			}
+		}
+
+		if (get_disc_capacity_for_type (fd, type, &capacity) == 0) {
+			HAL_DEBUG(("volume.disc.capacity = %llu", capacity));
+			libhal_changeset_set_property_uint64 (changeset, "volume.disc.capacity", capacity);
+		}
+
+		/* On some hardware the get_disc_type call fails, so we use this as a backup */
+		if (disc_is_rewritable (fd)) {
+			libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
+		}
+		
+		if (disc_is_appendable (fd)) {
+			libhal_changeset_set_property_bool (changeset, "volume.disc.is_appendable", TRUE);
+		}
+
+#if 0
+		/* This seems to cause problems on some drives with broken firmware,
+		 * comment it out until we really need multisession support */
+
+		/* check for multisession disks */
+		if (ioctl (fd, CDROMREADTOCHDR, &toc_hdr) == 0) {
+			struct cdrom_tocentry toc_entr;
+			unsigned int vol_session_count = 0;
+
+			vol_session_count = toc_hdr.cdth_trk1;
+			HAL_DEBUG(("volume_session_count = %u", vol_session_count));
+
+			/* read session header */
+			memset (&toc_entr, 0x00, sizeof (toc_entr));
+			toc_entr.cdte_track = vol_session_count;
+			toc_entr.cdte_format = CDROM_LBA;
+			if (ioctl (fd, CDROMREADTOCENTRY, &toc_entr) == 0)
+				if ((toc_entr.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
+					HAL_DEBUG(("last session starts at block = %u", toc_entr.cdte_addr.lba));
+					vol_probe_offset = toc_entr.cdte_addr.lba * block_size;
+				}
+		}
+#endif
+
+		/* try again, to get last session that way */
+		if (vol_probe_offset == 0) {
+			struct cdrom_multisession ms_info;
+
+			memset(&ms_info, 0x00, sizeof(ms_info));
+			ms_info.addr_format = CDROM_LBA;
+			if (ioctl(fd, CDROMMULTISESSION, &ms_info) == 0)
+				if (!ms_info.xa_flag)
+					vol_probe_offset = ms_info.addr.lba * block_size;
+		}
+	}
+
+	if (should_probe_for_fs) {
+
+		/* Optical discs have problems reporting the exact
+		 * size so we should never look for data there since
+		 * it causes problems with the broken ide-cd driver
+		 */
+		if (is_disc)
+			vol_size = 0;
+
+		/* probe for file system */
+		vid = volume_id_open_fd (fd);
+		if (vid != NULL) {
+			if (volume_id_probe_all (vid, vol_probe_offset , vol_size) == 0) {
+				set_volume_id_values(ctx, udi, changeset, vid);
+			} else {
+				libhal_changeset_set_property_string (changeset, "info.product", "Volume");
+			}
+
+			/* VOLUME_ID_UNUSED means vol_id didn't detect anything that it knows about - look if 
+			 * it's an extended msdos partition table 
+			 */
+			if (vid->usage_id == VOLUME_ID_UNUSED) {
+				unsigned char buf[2];
+
+				HAL_DEBUG (("looking whether partition is an extended msdos partition table", vid->usage_id));
+
+				/* TODO: Is it good enough to just look for this magic? Kay? */
+				lseek (fd, MSDOS_SIG_OFF, SEEK_SET);
+				if (read (fd, &buf, 2) != 2) {
+					HAL_DEBUG (("read failed (%s)", strerror (errno)));
+				} else {
+					if (memcmp (buf, MSDOS_MAGIC, 2) == 0) {
+						HAL_DEBUG (("partition is an extended msdos partition table"));
+
+						libhal_changeset_set_property_string (changeset, "volume.fsusage", "partitiontable");
+						libhal_changeset_set_property_string (changeset, "volume.fstype", "msdos_extended_partitiontable");
+						libhal_changeset_set_property_string (changeset, "volume.fsversion", "");
+						
+					}
+				}
+				
+			}
+
+			volume_id_close(vid);
+		}
+
+		/* get partition type number, if we find a msdos partition table */
+		if (partition_number_str != NULL && partition_number <= 256 && partition_number > 0) {
+			struct msdos_part_entry *idx;
+			int fd;
+
+			if ((stordev_dev_file = libhal_device_get_property_string (
+					ctx, parent_udi, "block.device", &error)) == NULL) {
+				goto out;
+			}
+			fd = open(stordev_dev_file, O_RDONLY);
+			if (fd >= 0) {
+				idx = probe_msdos_part_table(fd);
+				if (idx != NULL) {
+					uint64_t start;
+					uint64_t size;
+					unsigned char type;
+
+					type = idx[partition_number - 1].part_type;
+					start = idx[partition_number - 1].start;
+					size = idx[partition_number - 1].size;
+					if (type > 0) {
+						libhal_changeset_set_property_int (
+							changeset, "volume.partition.msdos_part_table_type", type);
+						libhal_changeset_set_property_uint64 (
+							changeset, "volume.partition.msdos_part_table_start", start);
+						libhal_changeset_set_property_uint64 (
+							changeset, "volume.partition.msdos_part_table_size", size);
+
+						/* NOTE: We trust the type from the partition table
+						 * if it explicitly got correct entries for RAID and
+						 * LVM partitions.
+						 *
+						 * But in general it's not a good idea to trust the
+						 * partition table type as many geek^Wexpert users use 
+						 * FAT filesystems on type 0x83 which is Linux.
+						 *
+						 * Linux RAID autodetect is 0xfd and Linux LVM is 0x8e
+						 */
+						if (type == 0xfd || type == 0x8e ) {
+							libhal_changeset_set_property_string (
+								changeset, "volume.fsusage", "raid");
+						}
+					}
+				}
+				close (fd);
+			}
+			libhal_free_string (stordev_dev_file);
+		}
+	}
+
+	/* good so far */
+	ret = 0;
+
+	/* for testing...
+	  char *values[4] = {"foo", "bar", "baz", NULL};
+	  libhal_changeset_set_property_strlist (changeset, "foo.bar", values);
+	*/
+
+	libhal_device_commit_changeset (ctx, changeset, &error);
+	libhal_device_free_changeset (changeset);
+
+out:
+	if (fd >= 0)
+		close (fd);
+
+	if (ctx != NULL) {
+		dbus_error_init (&error);
+		libhal_ctx_shutdown (ctx, &error);
+		libhal_ctx_free (ctx);
+	}
+
+	return ret;
+
+}
diff --git a/hald/linux2/.gitignore b/hald/linux2/.gitignore
deleted file mode 100644
index 4bec0e4..0000000
--- a/hald/linux2/.gitignore
+++ /dev/null
@@ -1,8 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.lo
-*.la
-*.o
-*~
diff --git a/hald/linux2/Makefile.am b/hald/linux2/Makefile.am
deleted file mode 100644
index d7b90a3..0000000
--- a/hald/linux2/Makefile.am
+++ /dev/null
@@ -1,37 +0,0 @@
-
-SUBDIRS = probing addons .
-
-INCLUDES = \
-	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
-	-I$(top_srcdir) -I.. \
-	@GLIB_CFLAGS@ @DBUS_CFLAGS@
-
-if HALD_COMPILE_LINUX2
-noinst_LTLIBRARIES = libhald_linux2.la
-endif
-
-libhald_linux2_la_SOURCES =					\
-				osspec.c			\
-	osspec_linux.h						\
-	hotplug.h		hotplug.c			\
-	hotplug_helper.h					\
-	coldplug.h		coldplug.c			\
-	physdev.h		physdev.c			\
-	classdev.h		classdev.c			\
-	blockdev.h		blockdev.c			\
-	acpi.h			acpi.c				\
-	apm.h			apm.c				\
-	pmu.h			pmu.c				\
-	ids.h			ids.c
-
-
-
-
-
-
-
-
diff --git a/hald/linux2/acpi.c b/hald/linux2/acpi.c
deleted file mode 100644
index 4274d77..0000000
--- a/hald/linux2/acpi.c
+++ /dev/null
@@ -1,1361 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * 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 "../hald_dbus.h"
-#include "../logger.h"
-#include "../util.h"
-#include "../util_pm.h"
-
-#include "osspec_linux.h"
-
-#include "acpi.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_SONYPI_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 1V.  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 = 1000; /* mV */
-
-		/* 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) / 1000;
-		normalised_lastfull = (reporting_lastfull * voltage) / 1000;
-		normalised_rate = (reporting_rate * voltage) / 1000;
-	} 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 1V. */
-		if (voltage_design <= 0)
-			voltage_design = 1000; /* mV */;
-
-		/* scale by factor battery.voltage.design */
-		hal_device_property_set_int (d, "battery.charge_level.design",
-			(reporting_design * voltage_design) / 1000);
-		hal_device_property_set_int (d, "battery.charge_level.warning",
-			(reporting_warning * voltage_design) / 1000);
-		hal_device_property_set_int (d, "battery.charge_level.low",
-			(reporting_low * voltage_design) / 1000);
-		hal_device_property_set_int (d, "battery.charge_level.granularity_1",
-			(reporting_gran1 * voltage_design) / 1000);
-		hal_device_property_set_int (d, "battery.charge_level.granularity_2",
-			(reporting_gran2 * voltage_design) / 1000);
-
-		/* 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 gchar *
-get_processor_model_name (gint proc_num)
-{
-	gchar *model_name;
-
-	gchar  *contents = NULL;
-	GError *error    = NULL;
-
-	gchar **lines;
-
-	gint proc_num_i;
-
-	gchar *cursor;
-	gint   i;
-
-
-	if (g_file_get_contents ("/proc/cpuinfo", & contents, NULL, & error)) {
-		lines = g_strsplit (contents, "\n", 0);
-
-		for (i = 0; lines [i]; ++i) {
-			if (strstr (lines [i], "processor\t:")) {
-				cursor = strstr (lines [i], ":");
-
-				proc_num_i = atoi (cursor + 1);
-
-				if (proc_num_i == proc_num) {
-					for (; lines [i]; ++i) {
-						if (strstr (lines [i], "model name\t:")) {
-							cursor = strstr (lines [i], ":");
-
-							g_strstrip (++ cursor);
-
-							model_name = g_strdup (cursor);
-
-							g_strfreev (lines);
-							g_free     (contents);
-
-							return model_name;
-						}
-					}
-				}
-			}
-		}
-	}
-	else {
-		HAL_ERROR (("Couldn't open /proc/cpuinfo: %s", error->message));
-
-		g_error_free (error);
-	}
-
-	return NULL;
-}
-
-static gboolean
-processor_refresh (HalDevice *d, ACPIDevHandler *handler)
-{
-	const char *path;
-
-	gchar *model_name;
-	gint   proc_num;
-
-	path = hal_device_property_get_string (d, "linux.acpi_path");
-	if (path == NULL)
-		return FALSE;
-
-	proc_num = hal_util_grep_int_elem_from_file (
-		path, "info", "processor id", 0, 10, FALSE
-	);
-
-	if ((model_name = get_processor_model_name (proc_num))) {
-		hal_device_property_set_string (d, "info.product", model_name);
-
-		g_free (model_name);
-	}
-	else
-		hal_device_property_set_string (d, "info.product", "Unknown 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 if (acpi_type == ACPI_TYPE_SONYPI_DISPLAY) {
-		type = "sonypi";
-		desc = "Sony LCD Panel";
-		br_levels = 256;
-	} 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);
-}
-
-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"));
-
-        /* Check that we don't support brightness change through ACPI,
-	 * for type3 VAIOs */
-	if (g_file_test ("/proc/acpi/sony/brightness", G_FILE_TEST_EXISTS))
-		return;
-
-	/* 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.
- *
- *  @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);
-	/* 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,
-		       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_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,
-	.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,
-	&acpidev_handler_laptop_panel_sonypi,
-	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;
-}
diff --git a/hald/linux2/acpi.h b/hald/linux2/acpi.h
deleted file mode 100644
index f7ed07a..0000000
--- a/hald/linux2/acpi.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
- * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef ACPI_H
-#define ACPI_H
-
-#include "../hald.h"
-#include "hotplug.h"
-
-gboolean acpi_synthesize_hotplug_events (void);
-
-void hotplug_event_begin_add_acpi (const gchar *acpi_path, int acpi_type, HalDevice *parent, void *end_token);
-
-void hotplug_event_begin_remove_acpi (const gchar *acpi_path, int acpi_type, void *end_token);
-
-gboolean acpi_rescan_device (HalDevice *d);
-
-HotplugEvent *acpi_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *acpi_generate_remove_hotplug_event (HalDevice *d);
-
-#endif /* ACPI_H */
diff --git a/hald/linux2/addons/.gitignore b/hald/linux2/addons/.gitignore
deleted file mode 100644
index 6c2e509..0000000
--- a/hald/linux2/addons/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.lo
-*.la
-hald-addon-acpi
-hald-addon-hid-ups
-hald-addon-pmu
-hald-addon-storage
-hald-addon-usb-csr
-hald-addon-keyboard
-hald-addon-acpi-buttons-toshiba
-hald-addon-macbookpro-backlight
-*.o
-*~
diff --git a/hald/linux2/addons/Makefile.am b/hald/linux2/addons/Makefile.am
deleted file mode 100644
index 19c229d..0000000
--- a/hald/linux2/addons/Makefile.am
+++ /dev/null
@@ -1,54 +0,0 @@
-
-INCLUDES = \
-	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
-        -I$(top_srcdir) -I$(top_srcdir)/hald \
-        @GLIB_CFLAGS@ @DBUS_CFLAGS@
-
-if HALD_COMPILE_LINUX2
-libexec_PROGRAMS  = 			\
-	hald-addon-acpi 		\
-	hald-addon-acpi-buttons-toshiba \
-	hald-addon-hid-ups 		\
-	hald-addon-keyboard 		\
-	hald-addon-pmu			\
-	hald-addon-storage
-
-if HAVE_LIBPCI
-libexec_PROGRAMS += hald-addon-macbookpro-backlight
-endif
-if HAVE_LIBUSB
-libexec_PROGRAMS += hald-addon-usb-csr
-endif
-endif
-
-hald_addon_acpi_SOURCES = addon-acpi.c ../../logger.c ../../util_helper.c
-hald_addon_acpi_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_addon_acpi_buttons_toshiba_SOURCES = addon-acpi-buttons-toshiba.c ../../logger.c ../../util_helper.c
-hald_addon_acpi_buttons_toshiba_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@
-
-hald_addon_hid_ups_SOURCES = addon-hid-ups.c ../../logger.c ../../util_helper.c
-hald_addon_hid_ups_LDADD = $(top_builddir)/libhal/libhal.la 
-
-hald_addon_keyboard_SOURCES = addon-keyboard.c ../../logger.c ../../util_helper.c
-hald_addon_keyboard_LDADD = $(top_builddir)/libhal/libhal.la 
-
-if HAVE_LIBPCI
-hald_addon_macbookpro_backlight_SOURCES = addon-macbookpro-backlight.c ../../logger.c
-hald_addon_macbookpro_backlight_LDADD = $(top_builddir)/libhal/libhal.la -lpci @GLIB_LIBS@
-endif
-
-hald_addon_pmu_SOURCES = addon-pmu.c ../../logger.c ../../util_helper.c
-hald_addon_pmu_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_addon_storage_SOURCES = addon-storage.c ../../logger.c ../../util_helper.c
-hald_addon_storage_LDADD = $(top_builddir)/libhal/libhal.la
-
-if HAVE_LIBUSB
-hald_addon_usb_csr_SOURCES = addon-usb-csr.c ../../logger.c ../../util_helper.c
-hald_addon_usb_csr_LDADD = $(top_builddir)/libhal/libhal.la -lusb @GLIB_LIBS@
-endif
diff --git a/hald/linux2/addons/addon-acpi-buttons-toshiba.c b/hald/linux2/addons/addon-acpi-buttons-toshiba.c
deleted file mode 100644
index 7252759..0000000
--- a/hald/linux2/addons/addon-acpi-buttons-toshiba.c
+++ /dev/null
@@ -1,184 +0,0 @@
-/*! @file	addon-acpi-buttons-toshiba.c
- *  @brief	Toshiba SMM Button Addon
- *  @author	Richard Hughes <richard at hughsie.com>
- *  @date	2005-10-15
- *
- *  @note	Low level routines from IAL, Copyright (C) 2004, 2005
- *		Timo Hoenig <thoenig at nouse.net>
- */
-/*
- * Licensed under the GNU General Public License Version 2
- *
- * 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 Street, Fifth Floor, Boston, MA
- * 02110-1301, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#  include <config.h>
-#endif
-
-#include <linux/input.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <glib/gmain.h>
-
-#include "libhal/libhal.h"
-#include "../../logger.h"
-
-/** Toshiba ACPI key interface */
-#define TOSHIBA_ACPI_KEYS		"/proc/acpi/toshiba/keys"
-
-/** Polling frequency in ms */
-#define TOSHIBA_POLL_FREQ       	250
-
-static LibHalContext *ctx = NULL;
-static char* udi;
-
-/** Flush keys from the Toshiba hotkey register */
-static void
-toshiba_key_flush (void)
-{
-	int hotkey_ready = 1;
-	int value;
-	FILE *fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
-	if (!fp) {
-		HAL_DEBUG (("Could not open %s!", TOSHIBA_ACPI_KEYS));
-		return;
-	}
-	while (hotkey_ready) {
-		fprintf (fp, "hotkey_ready:0\n");
-		fclose (fp);
-		fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
-		if (fscanf (fp, "hotkey_ready: %d\nhotkey: 0x%4x", &hotkey_ready, &value) < 2)
-			HAL_WARNING(("Warning: failure while parse %s", TOSHIBA_ACPI_KEYS));
-	}
-	if (fp)
-		fclose (fp);
-}
-
-/** Check whether there is a new event in the hotkey register
- *
- *  @param	value	The key id pressed, passed by reference
- *  @returns		TRUE if there is an event pending, FALSE if no event pending.
- */
-static gboolean
-toshiba_key_ready (int *value)
-{
-	FILE *fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
-	int hotkey_ready = -1;
-
-	if (!fp)
-		return FALSE;
-
-	if (fscanf (fp, "hotkey_ready: %1d\nhotkey: 0x%4x", &hotkey_ready, value) < 2)
-		HAL_WARNING (("Warning: failure while parse %s", TOSHIBA_ACPI_KEYS)); 
-
-	if (hotkey_ready) {
-		fprintf (fp, "hotkey_ready:0\n");
-		fclose (fp);
-		return TRUE;
-	}
-	fclose (fp);
-	return FALSE;
-}
-
-/** Callback to poll hotkey register and report occuring events.
- *
- *  @returns		TRUE on success, else FALSE.
- */
-static gboolean
-toshiba_key_poll (void)
-{
-	char *result;
-	int value;
-	DBusError error;
-	dbus_error_init (&error);
-
-	/* for each key */
-	while (toshiba_key_ready (&value) == TRUE) {
-		result = NULL;
-		if (value == 0x101) /* FnESC */
-			result = "mute";
-		else if (value == 0x13b) /* FnF1 */
-			result = "lock";
-		else if (value == 0x13c) /* FnF2 */
-			result = "search";
-		else if (value == 0x13d) /* FnF3 */
-			result = "suspend";
-		else if (value == 0x13e) /* FnF4 */
-			result = "hibernate";
-		else if (value == 0x140) /* FnF6 */
-			result = "brightness-down";
-		else if (value == 0x141) /* FnF7 */
-			result = "brightness-up";
-		else if (value == 0x142) /* FnF8 */
-			result = "wifi-power";
-
-		if (result) {
-			HAL_DEBUG (("Sending condition '%s'", result));
-			libhal_device_emit_condition (ctx, udi, "ButtonPressed", result, &error);
-			if (dbus_error_is_set (&error)) {
-				HAL_ERROR (("Failed to send condition: %s", error.message));
-				dbus_error_free (&error);
-				return FALSE;
-			}
-		}
-	}
-	return TRUE;
-}
-
-/** Main program
- */
-int
-main (int argc, char **argv)
-{
-	GMainLoop *loop = NULL;
-	DBusError error;
-	FILE *fp;
-
-	setup_logger ();
-
-	udi = getenv ("UDI");
-	if (udi == NULL) {
-		HAL_ERROR (("Failed to get UDI"));
-		return 1;
-	}
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
-		HAL_ERROR (("Unable to initialise libhal context: %s", error.message));
-		return 1;
-	}
-
-	/* Check for Toshiba ACPI interface /proc/acpi/toshiba/keys */
-	fp = fopen (TOSHIBA_ACPI_KEYS, "r+");
-	if (!fp) {
-		HAL_ERROR (("Could not open %s! Aborting.", TOSHIBA_ACPI_KEYS));
-		return 0;
-	}
-	fclose (fp);
-
-	/* Flush keys as we may have some already in buffer */
-	toshiba_key_flush ();
-
-	/* Get the new input */
-	g_timeout_add (TOSHIBA_POLL_FREQ, (GSourceFunc) toshiba_key_poll, NULL);
-
-	loop = g_main_loop_new (NULL, FALSE);
-	g_main_loop_run (loop);
-	return 0;
-}
diff --git a/hald/linux2/addons/addon-acpi.c b/hald/linux2/addons/addon-acpi.c
deleted file mode 100644
index 4b19321..0000000
--- a/hald/linux2/addons/addon-acpi.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * addon-acpi.c : Listen to ACPI events and modify hal device objects
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005 Ryan Lortie <desrt at desrt.ca>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-#include "../../util_helper.h"
-
-#ifdef ACPI_PROC
-static FILE *
-acpi_get_event_fp_kernel (void)
-{
-	FILE *fp = NULL;
-
-	fp = fopen ("/proc/acpi/event", "r");
-
-	if (fp == NULL)
-		HAL_ERROR (("Cannot open /proc/acpi/event: %s", strerror (errno)));
-
-	return fp;
-}
-#endif
-
-#ifdef ACPI_ACPID
-static FILE *
-acpi_get_event_fp_acpid (void)
-{
-	FILE *fp = NULL;
-
-	struct sockaddr_un addr;
-	int fd;
-
-	if( (fd = socket (AF_UNIX, SOCK_STREAM, 0)) < 0 ) {
-		HAL_ERROR (("Cannot create socket: %s", strerror (errno)));
-		return NULL;
-	}
-
-	memset (&addr, 0, sizeof addr);
-	addr.sun_family = AF_UNIX;
-	strncpy (addr.sun_path, "/var/run/acpid.socket", sizeof addr.sun_path);
-
-	if (connect (fd, (struct sockaddr *) &addr, sizeof addr) < 0) {
-		HAL_ERROR (("Cannot connect to acpid socket: %s", strerror (errno)));
-		close (fd);
-	} else {
-		fp = fdopen (fd, "r");
-
-		if (fp == NULL) {
-			HAL_ERROR (("fdopen failed: %s", strerror (errno)));
-			close (fd);
-		}
-	}
-
-	return fp;
-}
-#endif
-
-
-static void
-main_loop (LibHalContext *ctx, FILE *eventfp)
-{
-	unsigned int acpi_num1;
-	unsigned int acpi_num2;
-	char acpi_path[256];
-	char acpi_name[256];
-	DBusError error;
-	char event[256];
-
-	dbus_error_init (&error);
-
-	while (fgets (event, sizeof event, eventfp))
-	{
-		HAL_DEBUG (("event is '%s'", event));
-
-		if (sscanf (event, "%s %s %x %x", acpi_path, acpi_name, &acpi_num1, &acpi_num2) == 4) {
-			char udi[256];
-
-			snprintf (udi, sizeof (udi), "/org/freedesktop/Hal/devices/acpi_%s", acpi_name);
-
-			if (strncmp (acpi_path, "button", sizeof ("button") - 1) == 0) {
-				char *type;
-
-				HAL_DEBUG (("button event"));
-
-				/* TODO: only rescan if button got state */
-				libhal_device_rescan (ctx, udi, &error);
-
-				type = libhal_device_get_property_string(ctx, udi, 
-									 "button.type",
-									 &error);
-				if (type != NULL) {
-					libhal_device_emit_condition (ctx, udi, "ButtonPressed",
-								      type, &error);
-					libhal_free_string(type);
-				} else {
-					libhal_device_emit_condition (ctx, udi, "ButtonPressed", "", &error);
-				}
-			} else if (strncmp (acpi_path, "ac_adapter", sizeof ("ac_adapter") - 1) == 0) {
-				HAL_DEBUG (("ac_adapter event"));
-				libhal_device_rescan (ctx, udi, &error);
-			} else if (strncmp (acpi_path, "battery", sizeof ("battery") - 1) == 0) {
-				HAL_DEBUG (("battery event"));
-				libhal_device_rescan (ctx, udi, &error);
-			}
-
-		} else {
-			HAL_DEBUG (("cannot parse event"));
-		}
-
-		if (dbus_error_is_set (&error)) {
-	        	/* Free the error (which include a dbus_error_init()) 
-			   This should prevent errors if a call above fails */
-			dbus_error_free (&error);
-		}
-	}
-
-	dbus_error_free (&error);
-	fclose (eventfp);
-}
-
-int
-main (int argc, char **argv)
-{
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	FILE *eventfp;
-
-	hal_set_proc_title_init (argc, argv);
-
-	/* If we don't even consider the /proc ACPI interface, drop privileges
-	 * right away */
-#ifndef ACPI_PROC
-	drop_privileges (0);
-#endif
-
-	setup_logger ();
-
-	dbus_error_init (&error);
-
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
-		HAL_ERROR (("Unable to initialise libhal context: %s", error.message));
-		return 1;
-	}
-
-#ifdef ACPI_PROC
-	/* If we can connect directly to the kernel then do so. */
-	eventfp = acpi_get_event_fp_kernel ();
-	drop_privileges (0);
-
-	if (eventfp) {
-		hal_set_proc_title ("hald-addon-acpi: listening on acpi kernel interface /proc/acpi/event");
-		main_loop (ctx, eventfp);
-		HAL_ERROR (("Lost connection to kernel acpi event source - exiting"));
-		return 1;
-	}
-#endif
-
-	while (1)
-	{
-#ifdef ACPI_ACPID
-		/* Else, try to use acpid. */
-		if ((eventfp = acpi_get_event_fp_acpid ())) {
-			hal_set_proc_title ("hald-addon-acpi: listening on acpid socket /var/run/acpid.socket");
-			main_loop (ctx, eventfp);
-			HAL_DEBUG (("Cannot connect to acpid event socket - retry connect"));
-		}
-#endif
-		
-		/* If main_loop exits or we failed a reconnect attempt then
-		 * sleep for 5s and try to reconnect (again). */
-		sleep (5);
-	}
-
-	return 1;
-}
-
-/* vim:set sw=8 noet: */
diff --git a/hald/linux2/addons/addon-hid-ups.c b/hald/linux2/addons/addon-hid-ups.c
deleted file mode 100644
index 1361ed6..0000000
--- a/hald/linux2/addons/addon-hid-ups.c
+++ /dev/null
@@ -1,351 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * addon-hid-ups.c : Detect UPS'es using the USB HID interface and
- *                   add and maintain battery.* properties
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- *
- * Based on hid-ups.c: Copyright (c) 2001 Vojtech Pavlik
- *                     <vojtech at ucw.cz>, Copyright (c) 2001 Paul
- *                     Stewart <hiddev at wetlogic.net>, Tweaked by Kern
- *                     Sibbald <kern at sibbald.com> to learn about USB
- *                     UPSes.  hid-ups.c is GPLv2 and available from
- *                     examples directory of version 3.10.16 of the
- *                     acpupsd project; see http://www.apcupsd.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.
- *
- * 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
-
-/* asm/types.h required for __s32 in linux/hiddev.h */
-#include <asm/types.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/hiddev.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../util_helper.h"
-#include "../../logger.h"
-
-#define UPS_USAGE		0x840000
-#define UPS_SERIAL		0x8400fe
-#define UPS_CHEMISTRY		0x850089
-#define UPS_CAPACITY_MODE	0x85002c
-#define UPS_BATTERY_VOLTAGE	0x840030
-#define UPS_BELOW_RCL		0x840042
-#define UPS_SHUTDOWN_IMMINENT	0x840069
-#define UPS_PRODUCT		0x8400fe
-#define UPS_SERIALNUMBER	0x8400ff
-#define UPS_CHARGING		0x850044
-#define UPS_DISCHARGING 	0x850045
-#define UPS_REMAINING_CAPACITY	0x850066
-#define UPS_RUNTIME_TO_EMPTY	0x850068
-#define UPS_AC_PRESENT		0x8500d0
-#define UPS_BATTERYPRESENT	0x8500d1
-#define UPS_DESIGNCAPACITY	0x850083
-#define UPS_DEVICENAME		0x850088
-#define UPS_DEVICECHEMISTRY	0x850089
-#define UPS_RECHARGEABLE	0x85008b
-#define UPS_OEMINFORMATION	0x85008f
-
-#define STATE_NORMAL 0		      /* unit powered */
-#define STATE_DEBOUNCE 1	      /* power failure */
-#define STATE_BATTERY 2 	      /* power failure confirmed */
-
-static dbus_bool_t
-is_ups (int fd)
-{
-	unsigned int i;
-	dbus_bool_t ret;
-	struct hiddev_devinfo device_info;
-
-	ret = FALSE;
-
-	if (ioctl (fd, HIDIOCGDEVINFO, &device_info) < 0)
-		goto out;
-
-	for (i = 0; i < device_info.num_applications; i++) {
-		if ((ioctl(fd, HIDIOCAPPLICATION, i) & 0xff0000) == UPS_USAGE) {
-			ret = TRUE;
-			goto out;
-		}			
-	}
-
-out:
-	return ret;
-}
-
-static char *
-ups_get_string (int fd, int sindex)
-{
-	static struct hiddev_string_descriptor sdesc;
-	
-	if (sindex == 0) {
-		return "";
-	}
-	sdesc.index = sindex;
-	if (ioctl (fd, HIDIOCGSTRING, &sdesc) < 0) {
-		return "";
-	}
-	HAL_DEBUG (("foo: '%s'", sdesc.value));
-	return sdesc.value;
-}
-
-
-static dbus_bool_t
-ups_get_static (LibHalContext *ctx, const char *udi, int fd)
-{
-	int ret;
-	struct hiddev_report_info rinfo;
-	struct hiddev_field_info finfo;
-	struct hiddev_usage_ref uref;
-	int rtype;
-	unsigned int i, j;
-	DBusError error;
-
-	/* set to failure */
-	ret = FALSE;
-
-	/* first check that we are an UPS */
-	if (!is_ups (fd))
-		goto out;
-
-	for (rtype = HID_REPORT_TYPE_MIN; rtype <= HID_REPORT_TYPE_MAX; rtype++) {
-		rinfo.report_type = rtype;
-		rinfo.report_id = HID_REPORT_ID_FIRST;
-		while (ioctl (fd, HIDIOCGREPORTINFO, &rinfo) >= 0) {
-			for (i = 0; i < rinfo.num_fields; i++) { 
-				memset (&finfo, 0, sizeof (finfo));
-				finfo.report_type = rinfo.report_type;
-				finfo.report_id = rinfo.report_id;
-				finfo.field_index = i;
-				ioctl (fd, HIDIOCGFIELDINFO, &finfo);
-				
-				memset (&uref, 0, sizeof (uref));
-				for (j = 0; j < finfo.maxusage; j++) {
-					uref.report_type = finfo.report_type;
-					uref.report_id = finfo.report_id;
-					uref.field_index = i;
-					uref.usage_index = j;
-					ioctl (fd, HIDIOCGUCODE, &uref);
-					ioctl (fd, HIDIOCGUSAGE, &uref);
-
-					dbus_error_init (&error);
-
-					switch (uref.usage_code) {
-
-					case UPS_REMAINING_CAPACITY:
-						libhal_device_set_property_int (
-							ctx, udi, "battery.charge_level.current", uref.value, &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.charge_level.percentage", uref.value, &error);
-						libhal_device_set_property_string (
-							ctx, udi, "battery.charge_level.unit", "percent", &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.reporting.current", uref.value, &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.reporting.percentage", uref.value, &error);
-						libhal_device_set_property_string (
-							ctx, udi, "battery.reporting.unit", "percent", &error);
-						break;
-
-					case UPS_RUNTIME_TO_EMPTY:
-						libhal_device_set_property_int (
-							ctx, udi, "battery.remaining_time", uref.value, &error);
-						break;
-
-					case UPS_CHARGING:
-						libhal_device_set_property_bool (
-							ctx, udi, "battery.rechargeable.is_charging", uref.value != 0, &error);
-						break;
-
-					case UPS_DISCHARGING:
-						libhal_device_set_property_bool (
-							ctx, udi, "battery.rechargeable.is_discharging", uref.value != 0, &error);
-						break;
-
-					case UPS_BATTERYPRESENT:
-						libhal_device_set_property_bool (
-							ctx, udi, "battery.present", uref.value != 0, &error);
-						break;
-
-					case UPS_DEVICENAME:
-						libhal_device_set_property_string (
-							ctx, udi, "foo", 
-							ups_get_string (fd, uref.value), &error);
-						break;
-
-					case UPS_CHEMISTRY:
-						libhal_device_set_property_string (
-							ctx, udi, "battery.technology", 
-							ups_get_string (fd, uref.value), &error);
-						break;
-
-					case UPS_RECHARGEABLE:
-						libhal_device_set_property_bool (
-							ctx, udi, "battery.is_rechargeable", uref.value != 0, &error);
-						break;
-
-					case UPS_OEMINFORMATION:
-						libhal_device_set_property_string (
-							ctx, udi, "battery.vendor", 
-							ups_get_string (fd, uref.value), &error);
-						break;
-
-					case UPS_PRODUCT:
-						libhal_device_set_property_string (
-							ctx, udi, "battery.model", 
-							ups_get_string (fd, uref.value), &error);
-						break;
-
-					case UPS_SERIALNUMBER:
-						libhal_device_set_property_string (
-							ctx, udi, "battery.serial", 
-							ups_get_string (fd, uref.value), &error);
-						break;
-
-					case UPS_DESIGNCAPACITY:
-						libhal_device_set_property_int (
-							ctx, udi, "battery.charge_level.design", uref.value, &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.charge_level.last_full", uref.value, &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.reporting.design", uref.value, &error);
-						libhal_device_set_property_int (
-							ctx, udi, "battery.reporting.last_full", uref.value, &error);
-						break;
-
-					default:
-						break;
-					}
-				}
-			}
-			rinfo.report_id |= HID_REPORT_ID_NEXT;
-		}
-	}
-
-	libhal_device_set_property_bool (ctx, udi, "battery.present", TRUE, &error);
-	libhal_device_set_property_string (ctx, udi, "battery.type", "ups", &error);
-	libhal_device_add_capability (ctx, udi, "battery", &error);
-
-	ret = TRUE;
-
-out:
-	return ret;
-}
-
-int
-main (int argc, char *argv[])
-{
-	int fd;
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	unsigned int i;
-	fd_set fdset;
-	struct hiddev_event ev[64];
-	int rd;
-
-	hal_set_proc_title_init (argc, argv);
-
-	setup_logger ();	
-
-	udi = getenv ("UDI");
-	if (udi == NULL)
-		goto out;
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	device_file = getenv ("HAL_PROP_HIDDEV_DEVICE");
-	if (device_file == NULL)
-		goto out;
-
-	fd = open (device_file, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	if (!ups_get_static (ctx, udi, fd))
-		goto out;
-
-	hal_set_proc_title ("hald-addon-hid-ups: listening on %s", device_file);
-
-	FD_ZERO(&fdset);
-	while (1) {
-		FD_SET(fd, &fdset);
-		rd = select(fd+1, &fdset, NULL, NULL, NULL);
-		
-		if (rd > 0) {
-			rd = read(fd, ev, sizeof(ev));
-			if (rd < (int) sizeof(ev[0])) {
-				close(fd);
-				goto out;
-			}
-
-			for (i = 0; i < rd / sizeof(ev[0]); i++) {
-				DBusError error;
-				
-				dbus_error_init (&error);
-				switch (ev[i].hid) {
-				case UPS_REMAINING_CAPACITY:
-					libhal_device_set_property_int (
-						ctx, udi, "battery.charge_level.current", ev[i].value, &error);
-					libhal_device_set_property_int (
-						ctx, udi, "battery.charge_level.percentage", ev[i].value, &error);
-					libhal_device_set_property_int (
-						ctx, udi, "battery.reporting.current", ev[i].value, &error);
-					libhal_device_set_property_int (
-						ctx, udi, "battery.reporting.percentage", ev[i].value, &error);
-					break;
-					
-				case UPS_RUNTIME_TO_EMPTY:
-					libhal_device_set_property_int (
-						ctx, udi, "battery.remaining_time", ev[i].value, &error);
-					break;
-					
-				case UPS_CHARGING:
-					libhal_device_set_property_bool (
-						ctx, udi, "battery.rechargeable.is_charging", ev[i].value != 0, &error);
-					break;
-					
-				case UPS_DISCHARGING:
-					libhal_device_set_property_bool (
-						ctx, udi, "battery.rechargeable.is_discharging", ev[i].value != 0, &error);
-					break;
-					
-				default:
-					break;
-				}
-			}
-		}
-	}
-
-out:
-	return 0;
-}
diff --git a/hald/linux2/addons/addon-keyboard.c b/hald/linux2/addons/addon-keyboard.c
deleted file mode 100644
index a054ac9..0000000
--- a/hald/linux2/addons/addon-keyboard.c
+++ /dev/null
@@ -1,233 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * addon-keyboard.c : Listen to key events and modify hal device objects
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005 Ryan Lortie <desrt at desrt.ca>
- * Copyright (C) 2006 Matthew Garrett <mjg59 at srcf.ucam.org>
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <linux/input.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-#include "../../util_helper.h"
-
-static char *udi;
-
-static char *key_name[KEY_MAX + 1] = {
-	[0 ... KEY_MAX] = NULL,
-	[KEY_STOP] = "stop",
-	[KEY_AGAIN] = "again",
-	[KEY_PROPS] = "props",
-	[KEY_UNDO] = "undo",
-	[KEY_FRONT] = "front",
-	[KEY_COPY] = "copy",
-	[KEY_OPEN] = "open",
-	[KEY_PASTE] = "paste",
-	[KEY_FIND] = "find",
-	[KEY_CUT] = "cut",
-	[KEY_HELP] = "help",
-	[KEY_MENU] = "menu",
-	[KEY_CALC] = "calc",
-	[KEY_SETUP] = "setup",
-	[KEY_SLEEP] = "sleep",
-	[KEY_WAKEUP] = "wake-up",
-	[KEY_FILE] = "file",
-	[KEY_SENDFILE] = "send-file",
-	[KEY_DELETEFILE] = "delete-file",
-	[KEY_XFER] = "xfer",
-	[KEY_PROG1] = "prog1",
-	[KEY_PROG2] = "prog2",
-	[KEY_WWW] = "www",
-	[KEY_MSDOS] = "msdos",
-	[KEY_COFFEE] = "coffee",
-	[KEY_DIRECTION] = "direction",
-	[KEY_CYCLEWINDOWS] = "cycle-windows",
-	[KEY_MAIL] = "mail",
-	[KEY_BOOKMARKS] = "bookmarks",
-	[KEY_COMPUTER] = "computer",
-	[KEY_BACK] = "back",
-	[KEY_FORWARD] = "forward",
-	[KEY_CLOSECD] = "close-cd",
-	[KEY_EJECTCD] = "eject-cd",
-	[KEY_EJECTCLOSECD] = "eject-close-cd",
-	[KEY_NEXTSONG] = "next-song",
-	[KEY_PLAYPAUSE] = "play-pause",
-	[KEY_PREVIOUSSONG] = "previous-song",
-	[KEY_STOPCD] = "stop-cd",
-	[KEY_RECORD] = "record",
-	[KEY_REWIND] = "rewind",
-	[KEY_PHONE] = "phone",
-	[KEY_ISO] = "iso",
-	[KEY_CONFIG] = "config",
-	[KEY_HOMEPAGE] = "homepage",
-	[KEY_REFRESH] = "refresh",
-	[KEY_EXIT] = "exit",
-	[KEY_MOVE] = "move",
-	[KEY_EDIT] = "edit",
-	[KEY_SCROLLUP] = "scroll-up",
-	[KEY_SCROLLDOWN] = "scroll-down",
-	[KEY_KPLEFTPAREN] = "kp-left-paren",
-	[KEY_KPRIGHTPAREN] = "kp-right-paren",
-	[KEY_F13] = "f13",
-	[KEY_F14] = "f14",
-	[KEY_F15] = "f15",
-	[KEY_F16] = "f16",
-	[KEY_F17] = "f17",
-	[KEY_F18] = "f18",
-	[KEY_F19] = "f19",
-	[KEY_F20] = "f20",
-	[KEY_F21] = "f21",
-	[KEY_F22] = "f22",
-	[KEY_F23] = "f23",
-	[KEY_F24] = "f24",
-	[KEY_PLAYCD] = "play-cd",
-	[KEY_PAUSECD] = "pause-cd",
-	[KEY_PROG3] = "prog3",
-	[KEY_PROG4] = "prog4",
-	[KEY_SUSPEND] = "hibernate",
-	[KEY_CLOSE] = "close",
-	[KEY_PLAY] = "play",
-	[KEY_FASTFORWARD] = "fast-forward",
-	[KEY_BASSBOOST] = "bass-boost",
-	[KEY_PRINT] = "print",
-	[KEY_HP] = "hp",
-	[KEY_CAMERA] = "camera",
-	[KEY_SOUND] = "sound",
-	[KEY_QUESTION] = "question",
-	[KEY_EMAIL] = "email",
-	[KEY_CHAT] = "chat",
-	[KEY_SEARCH] = "search",
-	[KEY_CONNECT] = "connect",
-	[KEY_FINANCE] = "finance",
-	[KEY_SPORT] = "sport",
-	[KEY_SHOP] = "shop",
-	[KEY_ALTERASE] = "alt-erase",
-	[KEY_CANCEL] = "cancel",
-	[KEY_BRIGHTNESSDOWN] = "brightness-down",
-	[KEY_BRIGHTNESSUP] = "brightness-up",
-	[KEY_MEDIA] = "media",
-	[KEY_POWER] = "power",
-	[KEY_MUTE] = "mute",
-	[KEY_VOLUMEDOWN] = "volume-down",
-	[KEY_VOLUMEUP] = "volume-up",
-#ifndef KEY_SWITCHVIDEOMODE
-#define KEY_SWITCHVIDEOMODE	227
-#endif
-	[KEY_SWITCHVIDEOMODE] = "switch-videomode",
-#ifndef KEY_KBDILLUMTOGGLE
-#define KEY_KBDILLUMTOGGLE	228
-#endif
-	[KEY_KBDILLUMTOGGLE] = "kbd-illum-toggle",
-#ifndef KEY_KBDILLUMDOWN
-#define KEY_KBDILLUMDOWN	229
-#endif
-	[KEY_KBDILLUMDOWN] = "kbd-illum-down",
-#ifndef KEY_KBDILLUMUP
-#define KEY_KBDILLUMUP		230
-#endif
-	[KEY_KBDILLUMUP] = "kbd-illum-up"
-};
-
-static void
-main_loop (LibHalContext *ctx, FILE* eventfp)
-{
-	DBusError error;
-	struct input_event event;
-
-	dbus_error_init (&error);
-
-	while (fread (&event, sizeof(event), 1, eventfp)) {
-		/* dbg ("event.code = %d (0x%02x)", event.code); */
-		if (key_name[event.code] && event.value == 1) {
-			libhal_device_emit_condition (ctx, udi, 
-						      "ButtonPressed",
-						      key_name[event.code],
-						      &error);
-		}
-	}
-	
-	dbus_error_free (&error);
-}
-
-int
-main (int argc, char **argv)
-{
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char *device_file;
-	FILE *eventfp;
-
-	hal_set_proc_title_init (argc, argv);
-
-	/* setup_logger (); */
-
-	dbus_error_init (&error);
-
-	if ((udi = getenv ("UDI")) == NULL)
-		goto out;
-	
-	if ((device_file = getenv ("HAL_PROP_INPUT_DEVICE")) == NULL)
-		goto out;
-
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-                goto out;
-
-	eventfp = fopen(device_file, "r");	
-
-	if (!eventfp)
-		goto out;
-
-	drop_privileges (0);
-
-	hal_set_proc_title ("hald-addon-keyboard: listening on %s", device_file);
-
-	while (1)
-	{
-		main_loop (ctx, eventfp);
-		
-		/* If main_loop exits sleep for 5s and try to reconnect (
-		   again). */
-		sleep (5);
-	}
-
-	return 0;
-
- out:
-	if (ctx != NULL) {
-                dbus_error_init (&error);
-                libhal_ctx_shutdown (ctx, &error);
-                libhal_ctx_free (ctx);
-        }
-	
-	return 0;
-}
-
-/* vim:set sw=8 noet: */
diff --git a/hald/linux2/addons/addon-macbookpro-backlight.c b/hald/linux2/addons/addon-macbookpro-backlight.c
deleted file mode 100644
index f25a555..0000000
--- a/hald/linux2/addons/addon-macbookpro-backlight.c
+++ /dev/null
@@ -1,521 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * hal_addon_macbookpro-backlight.c : Set backlight for Macbook Pro
- * laptops that uses the ATI X1600 chipset. Based on code from Nicolas
- * Boichat found on the mactel-linux mailing list.
- *
- * Copyright (C) 2006 David Zeuthen <david at fubar.dk>
- * Copyright (C) 2006 Nicolas Boichat <nicolas at 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- **************************************************************************/
-
-#include <config.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/io.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <pci/pci.h>
-#include <unistd.h> 
-
-#include <glib/gmain.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include "libhal/libhal.h"
-#include "../../logger.h"
-
-static LibHalContext *halctx = NULL;
-static GMainLoop *main_loop;
-static char *udi;
-static DBusConnection *conn;
-
-static char* memory;
- 
-static inline unsigned int readl(const volatile void *addr)
-{
- 	return *(volatile unsigned int*) addr;
-}
-
-static inline void writel(unsigned int b, volatile void *addr)
-{
- 	*(volatile unsigned int*) addr = b;
-}
-
-#define INREG(addr)		readl(memory+addr)
-#define OUTREG(addr,val)	writel(val, memory+addr)
-
-static unsigned char 
-read_backlight (void)
-{
- 	return INREG(0x7af8) >> 8;
-}
-
-static void 
-write_backlight (unsigned char value)
-{
- 	OUTREG(0x7af8, 0x00000001 | ((unsigned int)value << 8));
-}
-
-
-#define LIGHT_SENSOR_LEFT_KEY	"ALV0" //0x414c5630, r-o length 6
-#define LIGHT_SENSOR_RIGHT_KEY	"ALV1" //0x414c5631, r-o length 6
-#define BACKLIGHT_KEY 		"LKSB" //0x4c4b5342, w-o
-
-static int debug = 0;
-
-static struct timeval lasttv;
-static struct timeval newtv;
-
-
-static void
-ssleep (const int usec)
-{
-	gettimeofday(&lasttv, NULL);
-	while (1) {
-		gettimeofday(&newtv, NULL);
-		if (((newtv.tv_usec - lasttv.tv_usec) + ((newtv.tv_sec - lasttv.tv_sec)*1000000)) > usec) {
-			break;
-		}
-	}
-}
-
-static unsigned char 
-get_status (void)
-{
-	return inb(0x304);
-}
-
-static int 
-waitfree (char num)
-{
-	char c, pc = -1;
-	int retry = 100;
-	while (((c = get_status())&0x0F) != num && retry) {
-		ssleep(10);
-		retry--;
-		if (pc != c) {
-			//printf("%x-%d:", c, retry);
-			pc = c;
-		}
-	}
-	if (retry == 0) {
-		printf("Waitfree failed %x != %x.\n", c, num);
-		return 0;
-	}
-	/*else
-		printf("Waitfree ok %x.\n", c);*/
-
-	return 1;
-}
-
-
-static int
-writekey (char* key, char len, unsigned char* buffer)
-{
-	int i;
-
-	outb(0x11, 0x304);
-	if (!waitfree(0x0c)) return 0;
-	
-	for (i = 0; i < 4; i++) {
-		outb(key[i], 0x300);
-		if (!waitfree(0x04)) return 0;
-	}
-	if (debug) printf(">%s", key);
-
-	outb(len, 0x300);
-	if (debug) printf(">%x", len);
-
-	for (i = 0; i < len; i++) {
-		if (!waitfree(0x04)) return 0;
-		outb(buffer[i], 0x300);
-		if (debug) printf(">%x", buffer[i]);
-	}
-	if (debug) printf("\n");
-	return 1;
-}
-
-static int 
-readkey (char* key, char len, unsigned char* buffer)
-{
-	int i; unsigned char c;
-
-	outb(0x10, 0x304);
-	if (!waitfree(0x0c)) return 0;
-	
-	for (i = 0; i < 4; i++) {
-		outb(key[i], 0x300);
-		if (!waitfree(0x04)) return 0;
-	}
-	if (debug) printf("<%s", key);
-
-	outb(len, 0x300);
-	if (debug) printf(">%x", len);
-
-	for (i = 0; i < len; i++) {
-		if (!waitfree(0x05)) return 0;
-		c = inb(0x300);
-		buffer[i] = c;
-		if (debug) printf("<%x", c);
-	}
-	if (debug) printf("\n");
-	return 1;
-}
-
-static int 
-read_light_sensor (gboolean left)
-{
-	unsigned char buffer[6];
-
-	if (readkey (left ? LIGHT_SENSOR_LEFT_KEY : LIGHT_SENSOR_RIGHT_KEY, 6, buffer))
-		return buffer[2];
-	else
-		return -1;
-}
-
-static int
-set_keyboard_backlight (char value)
-{
-	unsigned char buffer[2];
-	buffer[0] = value;
-	buffer[1] = 0x00;
-	return writekey (BACKLIGHT_KEY, 2, buffer);	
-}
-
-
-#if 0
-static int
-read_keyboard_backlight (void)
-{
-	unsigned char buffer[6];
-
-	if (readkey (BACKLIGHT_KEY, 6, buffer))
-		return buffer[2];
-	else
-		return -1;
-}
-#endif
-
-static int last_keyboard_brightness = -1;
-
-static DBusHandlerResult
-filter_function (DBusConnection *connection, DBusMessage *message, void *userdata)
-{
-	DBusError err;
-	DBusMessage *reply;
-
-	/*dbg ("filter_function: sender=%s destination=%s obj_path=%s interface=%s method=%s", 
-	     dbus_message_get_sender (message), 
-	     dbus_message_get_destination (message), 
-	     dbus_message_get_path (message), 
-	     dbus_message_get_interface (message),
-	     dbus_message_get_member (message));*/
-
-	reply = NULL;
-
-	if (dbus_message_is_method_call (message, 
-					 "org.freedesktop.Hal.Device.LaptopPanel", 
-					 "SetBrightness")) {
-		int brightness;
-
-		dbus_error_init (&err);
-		if (dbus_message_get_args (message, 
-					   &err,
-					   DBUS_TYPE_INT32, &brightness,
-					   DBUS_TYPE_INVALID)) {
-			/* dbg ("setting brightness %d", brightness); */
-			if (brightness < 0 || brightness > 228) {
-				reply = dbus_message_new_error (message,
-								"org.freedesktop.Hal.Device.LaptopPanel.Invalid",
-								"Brightness has to be between 0 and 228!");
-
-			} else {
-				int return_code;
-
-				write_backlight (brightness + 27);
-
-				reply = dbus_message_new_method_return (message);
-				if (reply == NULL)
-					goto error;
-
-				return_code = 0;
-				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.LaptopPanel", 
-						"GetBrightness")) {
-		int brightness;
-
-		dbus_error_init (&err);
-		if (dbus_message_get_args (message, 
-					   &err,
-					   DBUS_TYPE_INVALID)) {
-
-			brightness = read_backlight () - 27;
-			if (brightness < 0)
-				brightness = 0;
-			if (brightness > 228)
-				brightness = 228;
-
-			/* dbg ("getting brightness, it's %d", brightness); */
-
-			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);
-		}
-		
-	} else if (dbus_message_is_method_call (message, 
-						"org.freedesktop.Hal.Device.LightSensor", 
-						"GetBrightness")) {
-		int brightness[2];
-
-		brightness[0] = read_light_sensor (FALSE); /* right */
-		brightness[1] = read_light_sensor (TRUE); /* left */
-
-		if (brightness[0] == -1 || brightness[1] == -1) {
-			reply = dbus_message_new_error (message,
-							"org.freedesktop.Hal.Device.LightSensors.Error",
-							"Error poking hardware");
-			dbus_connection_send (connection, reply, NULL);
-		} else {
-			int **pb = &brightness;
-
-			reply = dbus_message_new_method_return (message);
-			if (reply == NULL)
-				goto error;
-			
-			dbus_message_append_args (reply,
-						  DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &pb, 2,
-						  DBUS_TYPE_INVALID);
-			dbus_connection_send (connection, reply, NULL);
-		}
-	} else if (dbus_message_is_method_call (message, 
-						"org.freedesktop.Hal.Device.KeyboardBacklight", 
-						"GetBrightness")) {
-
-		/* I can't get this working so just cache last SetBrightness value :-/ */
-		if (last_keyboard_brightness == -1 ) {
-			reply = dbus_message_new_error (message,
-							"org.freedesktop.Hal.Device.KeyboardBacklight.Error",
-							"Error poking hardware");
-			dbus_connection_send (connection, reply, NULL);
-		} else {
-			reply = dbus_message_new_method_return (message);
-			if (reply == NULL)
-				goto error;
-			
-			dbus_message_append_args (reply,
-						  DBUS_TYPE_INT32, &last_keyboard_brightness,
-						  DBUS_TYPE_INVALID);
-			dbus_connection_send (connection, reply, NULL);
-		}
-#if 0
-		int brightness;
-
-		brightness = read_keyboard_backlight ();
-
-		if (brightness == -1) {
-			reply = dbus_message_new_error (message,
-							"org.freedesktop.Hal.Device.KeyboardBacklight.Error",
-							"Error poking hardware");
-			dbus_connection_send (connection, reply, NULL);
-		} else {
-			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);
-		}
-#endif
-	} else if (dbus_message_is_method_call (message, 
-						"org.freedesktop.Hal.Device.KeyboardBacklight", 
-						"SetBrightness")) {
-		int brightness;
-
-
-		dbus_error_init (&err);
-		if (dbus_message_get_args (message, 
-					   &err,
-					   DBUS_TYPE_INT32, &brightness,
-					   DBUS_TYPE_INVALID)) {
-			/*dbg ("setting keyboard brightness %d", brightness);*/
-			if (brightness < 0 || brightness > 255) {
-				reply = dbus_message_new_error (message,
-								"org.freedesktop.Hal.Device.KeyboardBacklight.Invalid",
-								"Brightness has to be between 0 and 255!");
-
-			} else {
-				set_keyboard_backlight (brightness);
-				last_keyboard_brightness = brightness;
-
-				reply = dbus_message_new_method_return (message);
-				if (reply == NULL)
-					goto error;
-			}
-
-			dbus_connection_send (connection, reply, NULL);
-		}
-
-	}
-	
-error:
-	if (reply != NULL)
-		dbus_message_unref (reply);
-
-	return DBUS_HANDLER_RESULT_HANDLED;
-}
-
-int
-main (int argc, char *argv[])
-{
- 	off_t address = 0;
- 	size_t length = 0;
- 	int fd;
- 	int state;
-	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;
-	}
-
-	conn = libhal_ctx_get_dbus_connection (halctx);
-	dbus_connection_setup_with_g_main (conn, NULL);
-
-	dbus_connection_add_filter (conn, filter_function, NULL, NULL);
-
- 	/* Search for the graphics card. */
- 	/* Default values: */
- 	/* address = 0x90300000; */
- 	/* length = 0x20000; */
-
- 	struct pci_access *pacc = pci_alloc();
- 	pci_init(pacc);
- 	pci_scan_bus(pacc);
- 	struct pci_dev *dev;
- 	for(dev=pacc->devices; dev; dev=dev->next) {	/* Iterate over all devices */
- 		pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES);
- 		if ((dev->vendor_id == 0x1002) && (dev->device_id == 0x71c5)) { // ATI X1600
- 			address = dev->base_addr[2];
- 			length = dev->size[2];
- 		}
- 	}
- 	pci_cleanup(pacc);
-
-	HAL_DEBUG (("addr 0x%x len=%d", address, length));
- 
- 	if (!address) {
- 		HAL_DEBUG (("Failed to detect ATI X1600, aborting..."));
- 		return 1;
- 	}
- 
- 	fd = open ("/dev/mem", O_RDWR);
- 	
- 	if (fd < 0) {
- 		HAL_DEBUG (("cannot open /dev/mem"));
- 		return 1;
- 	}
- 
- 	memory = mmap (NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, address);
- 
- 	if (memory == MAP_FAILED) {
- 		HAL_ERROR (("mmap failed"));
- 		return 2;
- 	}
- 
- 	/* Is it really necessary ? */
- 	OUTREG(0x4dc, 0x00000005);
- 	state = INREG(0x7ae4);
- 	OUTREG(0x7ae4, state);
-
-	if (ioperm (0x300, 0x304, 1) < 0) {
-		HAL_ERROR (("ioperm failed (you should be root)."));
-		exit(1);
-	}
-
-	/* this works because we hardcoded the udi's in the <spawn> in the fdi files */
-	if (!libhal_device_claim_interface (halctx, 
-					    "/org/freedesktop/Hal/devices/macbook_pro_lcd_panel", 
-					    "org.freedesktop.Hal.Device.LaptopPanel", 
-					    "    <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.LaptopPanel'"));
-		return -4;
-	}
-	if (!libhal_device_claim_interface (halctx, 
-					    "/org/freedesktop/Hal/devices/macbook_pro_light_sensor",
-					    "org.freedesktop.Hal.Device.LightSensor", 
-					    "    <method name=\"GetBrightness\">\n"
-					    "      <arg name=\"brightness_value\" direction=\"out\" type=\"ai\"/>\n"
-					    "    </method>\n",
-					    &err)) {
-		HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.LightSensor'"));
-		return -4;
-	}
-	if (!libhal_device_claim_interface (halctx, 
-					    "/org/freedesktop/Hal/devices/macbook_pro_keyboard_backlight",
-					    "org.freedesktop.Hal.Device.KeyboardBacklight", 
-					    "    <method name=\"GetBrightness\">\n"
-					    "      <arg name=\"brightness_value\" direction=\"out\" type=\"i\"/>\n"
-					    "    </method>\n"
-					    "    <method name=\"SetBrightness\">\n"
-					    "      <arg name=\"brightness_value\" direction=\"in\" type=\"i\"/>\n"
-					    "    </method>\n",
-					    &err)) {
-		HAL_ERROR (("Cannot claim interface 'org.freedesktop.Hal.Device.KeyboardBacklight'"));
-		return -4;
-	}
-
-	main_loop = g_main_loop_new (NULL, FALSE);
-	g_main_loop_run (main_loop);
-	return 0;
-}
diff --git a/hald/linux2/addons/addon-pmu.c b/hald/linux2/addons/addon-pmu.c
deleted file mode 100644
index 68b59fe..0000000
--- a/hald/linux2/addons/addon-pmu.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * addon-pmu-lid.c : Poll the lid button for PMU on Apple computers
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- *
- * 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 <linux/adb.h>
-#include <linux/pmu.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-#include "../../util_helper.h"
-
-int
-main (int argc, char *argv[])
-{
-	int fd;
-	char *udi;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	int rd;
-	char buf[256];
-	int state;
-	int new_state;
-	char *strstate;
-
-	fd = -1;
-
-	setup_logger ();
-
-	udi = getenv ("UDI");
-	if (udi == NULL)
-		goto out;
-
-	dbus_error_init (&error);
-
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	/* initial state */
-	if ((strstate = getenv ("HAL_PROP_BUTTON_STATE_VALUE")) == NULL) {
-		HAL_ERROR (("Cannot get HAL_PROP_BUTTON_STATE_VALUE"));
-		goto out;
-	}
-	if (strcmp (strstate, "true") == 0)
-		state = TRUE;
-	else
-		state = FALSE;
-
-	if ((fd = open ("/dev/adb", O_RDWR)) < 0) {
-                HAL_ERROR (("Cannot open /dev/adb"));
-                goto out;
-	}
-
-        drop_privileges (0);
-
-	while (1) {
-		int n;
-
-		buf[0] = PMU_PACKET;
-		buf[1] = PMU_GET_COVER;
-
-		n = write (fd, buf, 2);
-		if (n == 2) {
-			rd = read (fd, buf, sizeof (buf));
-			if (rd <= 0) {
-				HAL_ERROR (("Error reading from fd; read returned %d; err=%s", errno, strerror (errno)));
-				goto out;
-			}
-
-#if 0
-			int i;
-			
-			HAL_DEBUG (("Read 0x%02x bytes", rd));				
-			for (i = 0; i < rd; i++) {
-				dbg ("%02x : 0x%02x", i, buf[i]);
-			}
-#endif
-
-			if (rd >= 2) {
-				new_state = (((buf[1]) & 0x01) != 0);
-
-				if (new_state != state) {
-					HAL_DEBUG (("lid state change: %d", new_state));
-					dbus_error_init (&error);
-					libhal_device_set_property_bool (
-						ctx, udi, "button.state.value", new_state, &error);
-					dbus_error_init (&error);
-					libhal_device_emit_condition (ctx, udi, "ButtonPressed", "", &error);
-				}
-
-				state = new_state;
-			}
-
-			
-		}
-		usleep (1000 * 1000);
-	}
-
-
-
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	return 0;
-}
diff --git a/hald/linux2/addons/addon-storage.c b/hald/linux2/addons/addon-storage.c
deleted file mode 100644
index 1660abc..0000000
--- a/hald/linux2/addons/addon-storage.c
+++ /dev/null
@@ -1,486 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * addon-storage.c : Poll storage devices for media changes
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <linux/cdrom.h>
-#include <linux/fs.h>
-#include <mntent.h>
-#include <scsi/sg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-#include "../../util_helper.h"
-
-static void 
-force_unmount (LibHalContext *ctx, const char *udi)
-{
-	DBusError error;
-	DBusMessage *msg = NULL;
-	DBusMessage *reply = NULL;
-	char **options = NULL;
-	unsigned int num_options = 0;
-	DBusConnection *dbus_connection;
-	char *device_file;
-
-	dbus_connection = libhal_ctx_get_dbus_connection (ctx);
-
-	msg = dbus_message_new_method_call ("org.freedesktop.Hal", udi,
-					    "org.freedesktop.Hal.Device.Volume",
-					    "Unmount");
-	if (msg == NULL) {
-		HAL_ERROR (("Could not create dbus message for %s", udi));
-		goto out;
-	}
-
-
-	options = calloc (1, sizeof (char *));
-	if (options == NULL) {
-		HAL_ERROR (("Could not allocate options array"));
-		goto out;
-	}
-
-	options[0] = "lazy";
-	num_options = 1;
-
-	device_file = libhal_device_get_property_string (ctx, udi, "block.device", NULL);
-	if (device_file != NULL) {
-		HAL_INFO(("forcibly attempting to lazy unmount %s as media was removed", device_file));
-		libhal_free_string (device_file);
-	}
-
-	if (!dbus_message_append_args (msg, 
-				       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &options, num_options,
-				       DBUS_TYPE_INVALID)) {
-		HAL_ERROR (("Could not append args to dbus message for %s", udi));
-		goto out;
-	}
-	
-	dbus_error_init (&error);
-	if (!(reply = dbus_connection_send_with_reply_and_block (dbus_connection, msg, -1, &error))) {
-		HAL_ERROR (("Unmount failed for %s: %s : %s\n", udi, error.name, error.message));
-		dbus_error_free (&error);
-		goto out;
-	}
-
-	if (dbus_error_is_set (&error)) {
-		HAL_ERROR (("Unmount failed for %s\n%s : %s\n", udi, error.name, error.message));
-		dbus_error_free (&error);
-		goto out;
-	}
-
-	HAL_DEBUG (("Succesfully unmounted udi '%s'", udi));
-
-out:
-	if (options != NULL)
-		free (options);
-	if (msg != NULL)
-		dbus_message_unref (msg);
-	if (reply != NULL)
-		dbus_message_unref (reply);
-}
-
-static dbus_bool_t
-unmount_cleartext_devices (LibHalContext *ctx, const char *udi)
-{
-	DBusError error;
-	char **clear_devices;
-	int num_clear_devices;
-	dbus_bool_t ret;
-
-	ret = FALSE;
-
-	/* check if the volume we back is mounted.. if it is.. unmount it */
-	dbus_error_init (&error);
-	clear_devices = libhal_manager_find_device_string_match (ctx,
-								 "volume.crypto_luks.clear.backing_volume",
-								 udi,
-								 &num_clear_devices,
-								 &error);
-
-	if (clear_devices != NULL && num_clear_devices > 0) {
-		int i;
-
-		ret = TRUE;
-
-		for (i = 0; i < num_clear_devices; i++) {
-			char *clear_udi;
-			clear_udi = clear_devices[i];
-			dbus_error_init (&error);
-			if (libhal_device_get_property_bool (ctx, clear_udi, "volume.is_mounted", &error)) {
-				HAL_DEBUG (("Forcing unmount of child '%s' (crypto)", clear_udi));
-				force_unmount (ctx, clear_udi);
-			}
-		}
-		libhal_free_string_array (clear_devices);
-	}
-
-	return ret;
-}
-
-static void 
-unmount_childs (LibHalContext *ctx, const char *udi)
-{
-	int num_volumes;
-	char **volumes;
-	DBusError error;
-
-	/* need to force unmount all partitions */
-	dbus_error_init (&error);
-	if ((volumes = libhal_manager_find_device_string_match (
-		     ctx, "block.storage_device", udi, &num_volumes, &error)) != NULL) {
-		int i;
-
-		for (i = 0; i < num_volumes; i++) {
-			char *vol_udi;
-
-			vol_udi = volumes[i];
-			dbus_error_init (&error);
-			if (libhal_device_get_property_bool (ctx, vol_udi, "block.is_volume", &error)) {
-				dbus_bool_t is_crypto;
-
-				/* unmount all cleartext devices associated with us */
-				is_crypto = unmount_cleartext_devices (ctx, vol_udi);
-
-				dbus_error_init (&error);
-				if (libhal_device_get_property_bool (ctx, vol_udi, "volume.is_mounted", &error)) {
-					HAL_DEBUG (("Forcing unmount of child '%s'", vol_udi));
-					force_unmount (ctx, vol_udi);
-				}
-
-				/* teardown crypto */
-				if (is_crypto) {
-					DBusMessage *msg = NULL;
-					DBusMessage *reply = NULL;
-
-					/* tear down mapping */
-					HAL_DEBUG (("Teardown crypto for '%s'", vol_udi));
-
-					msg = dbus_message_new_method_call ("org.freedesktop.Hal", vol_udi,
-									    "org.freedesktop.Hal.Device.Volume.Crypto",
-									    "Teardown");
-					if (msg == NULL) {
-						HAL_ERROR (("Could not create dbus message for %s", vol_udi));
-						goto teardown_failed;
-					}
-
-					dbus_error_init (&error);
-					if (!(reply = dbus_connection_send_with_reply_and_block (
-						      libhal_ctx_get_dbus_connection (ctx), msg, -1, &error)) || 
-					    dbus_error_is_set (&error)) {
-						HAL_DEBUG (("Teardown failed for %s: %s : %s\n", 
-						     udi, error.name, error.message));
-						dbus_error_free (&error);
-					}
-
-				teardown_failed:
-					if (msg != NULL)
-						dbus_message_unref (msg);
-					if (reply != NULL)
-						dbus_message_unref (reply);
-				}
-
-			}
-
-		}
-		libhal_free_string_array (volumes);
-	}
-}
-
-/** Check if a filesystem on a special device file is mounted
- *
- *  @param  device_file         Special device file, e.g. /dev/cdrom
- *  @return                     TRUE iff there is a filesystem system mounted
- *                              on the special device file
- */
-static dbus_bool_t
-is_mounted (const char *device_file)
-{
-	FILE *f;
-	dbus_bool_t rc;
-	struct mntent mnt;
-	struct mntent *mnte;
-	char buf[512];
-
-	rc = FALSE;
-
-	if ((f = setmntent ("/etc/mtab", "r")) == NULL)
-		goto out;
-
-	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
-		if (strcmp (device_file, mnt.mnt_fsname) == 0) {
-			rc = TRUE;
-			goto out1;
-		}
-	}
-
-out1:
-	endmntent (f);
-out:
-	return rc;
-}
-
-
-enum {
-	MEDIA_STATUS_UNKNOWN = 0,
-	MEDIA_STATUS_GOT_MEDIA = 1,
-	MEDIA_STATUS_NO_MEDIA = 2
-};
-
-int
-main (int argc, char *argv[])
-{
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char *bus;
-	char *drive_type;
-	int is_cdrom;
-	int media_status;
-	char *support_media_changed_str;
-	int support_media_changed;
-
-	hal_set_proc_title_init (argc, argv);
-
-	/* We could drop privs if we know that the haldaemon user is
-	 * to be able to access block devices...
-	 */
-        /*drop_privileges (1);*/
-
-	if ((udi = getenv ("UDI")) == NULL)
-		goto out;
-	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
-		goto out;
-	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
-		goto out;
-	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
-		goto out;
-
-	setup_logger ();
-
-	support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
-	if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
-		support_media_changed = TRUE;
-	else
-		support_media_changed = FALSE;
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	HAL_DEBUG (("**************************************************"));
-	HAL_DEBUG (("Doing addon-storage for %s (bus %s) (drive_type %s) (udi %s)", device_file, bus, drive_type, udi));
-	HAL_DEBUG (("**************************************************"));
-
-	hal_set_proc_title ("hald-addon-storage: polling %s", device_file);
-
-	if (strcmp (drive_type, "cdrom") == 0)
-		is_cdrom = 1;
-	else
-		is_cdrom = 0;
-
-	media_status = MEDIA_STATUS_UNKNOWN;
-
-	while (TRUE) {
-		int fd;
-		int got_media;
-
-		got_media = FALSE;
-
-		if (is_cdrom) {
-			int drive;
-
-			fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
-
-			if (fd < 0 && errno == EBUSY) {
-				/* this means the disc is mounted or some other app,
-				 * like a cd burner, has already opened O_EXCL */
-
-				/* HOWEVER, when starting hald, a disc may be
-				 * mounted; so check /etc/mtab to see if it
-				 * actually is mounted. If it is we retry to open
-				 * without O_EXCL
-				 */
-				if (!is_mounted (device_file))
-					goto skip_check;
-
-				fd = open (device_file, O_RDONLY | O_NONBLOCK);
-			}
-
-			if (fd < 0) {
-				HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
-				goto skip_check;
-			}
-
-
-			/* Check if a disc is in the drive
-			 *
-			 * @todo Use MMC-2 API if applicable
-			 */
-			drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
-			switch (drive) {
-			case CDS_NO_INFO:
-			case CDS_NO_DISC:
-			case CDS_TRAY_OPEN:
-			case CDS_DRIVE_NOT_READY:
-				break;
-
-			case CDS_DISC_OK:
-				/* some CD-ROMs report CDS_DISK_OK even with an open
-				 * tray; if media check has the same value two times in
-				 * a row then this seems to be the case and we must not
-				 * report that there is a media in it. */
-				if (support_media_changed &&
-				    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
-				    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
-				} else {
-					got_media = TRUE;
-				}
-				break;
-
-			case -1:
-				HAL_ERROR (("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
-				break;
-
-			default:
-				break;
-			}
-
-			/* check if eject button was pressed */
-			if (got_media) {
-				unsigned char cdb[10] = { 0x4a, 1, 0, 0, 16, 0, 0, 0, 8, 0};
-				unsigned char buffer[8];
-				struct sg_io_hdr sg_h;
-				int retval;
-
-				memset(buffer, 0, sizeof(buffer));
-				memset(&sg_h, 0, sizeof(struct sg_io_hdr));
-				sg_h.interface_id = 'S';
-				sg_h.cmd_len = sizeof(cdb);
-				sg_h.dxfer_direction = SG_DXFER_FROM_DEV;
-				sg_h.dxfer_len = sizeof(buffer);
-				sg_h.dxferp = buffer;
-				sg_h.cmdp = cdb;
-				sg_h.timeout = 5000;
-				retval = ioctl(fd, SG_IO, &sg_h);
-				if (retval == 0 && sg_h.status == 0 && (buffer[4] & 0x0f) == 0x01) {
-					DBusError error;
-
-					/* emit signal from drive device object */
-					dbus_error_init (&error);
-					libhal_device_emit_condition (ctx, udi, "EjectPressed", "", &error);
-				}
-			}
-			close (fd);
-		} else {
-			fd = open (device_file, O_RDONLY);
-			if (fd < 0 && errno == ENOMEDIUM) {
-				got_media = FALSE;
-				close (fd);
-			} else if (fd >= 0) {
-				got_media = TRUE;
-				close (fd);
-			} else {
-				HAL_ERROR (("open failed for %s: %s", device_file, strerror (errno))); 
-				close (fd);
-				goto skip_check;
-			}
-		}
-
-		switch (media_status) {
-		case MEDIA_STATUS_GOT_MEDIA:
-			if (!got_media) {
-				DBusError error;
-				
-				HAL_DEBUG (("Media removal detected on %s", device_file));
-				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
-				
-				/* attempt to unmount all childs */
-				unmount_childs (ctx, udi);
-				
-				/* could have a fs on the main block device; do a rescan to remove it */
-				dbus_error_init (&error);
-				libhal_device_rescan (ctx, udi, &error);
-				
-				/* have to this to trigger appropriate hotplug events */
-				fd = open (device_file, O_RDONLY | O_NONBLOCK);
-				if (fd >= 0)
-					ioctl (fd, BLKRRPART);
-				close (fd);
-			}
-			break;
-
-		case MEDIA_STATUS_NO_MEDIA:
-			if (got_media) {
-				DBusError error;
-
-				HAL_DEBUG (("Media insertion detected on %s", device_file));
-				libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);				/* our probe will trigger the appropriate hotplug events */
-
-				/* could have a fs on the main block device; do a rescan to add it */
-				dbus_error_init (&error);
-				libhal_device_rescan (ctx, udi, &error);
-				
-			}
-			break;
-
-		case MEDIA_STATUS_UNKNOWN:
-		default:
-			break;
-		}
-
-		/* update our current status */
-		if (got_media)
-			media_status = MEDIA_STATUS_GOT_MEDIA;
-		else
-			media_status = MEDIA_STATUS_NO_MEDIA;
-
-		/*HAL_DEBUG (("polling %s; got media=%d", device_file, got_media));*/
-
-	skip_check:
-		sleep (2);
-	}
-
-out:
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return 0;
-}
diff --git a/hald/linux2/addons/addon-usb-csr.c b/hald/linux2/addons/addon-usb-csr.c
deleted file mode 100644
index cd1747d..0000000
--- a/hald/linux2/addons/addon-usb-csr.c
+++ /dev/null
@@ -1,329 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * hal_addon_usb_csr.c : daemon handling CSR-based wireless mice
- *
- * Copyright (C) 2004 Sergey V. Udaltsov <svu at gnome.org>
- * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
- *
- * 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
- *
- **************************************************************************/
-
-#include <config.h>
-#include <stdio.h>
-#include <string.h>
-#include <usb.h>
-
-#include <glib/gmain.h>
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-
-#include "libhal/libhal.h"
-#include "../../logger.h"
-#include "../../util_helper.h"
-
-#define TIMEOUT         30L
-
-/* Internal CSR registered, I presume - for some reason not addressed directly */
-#define P6  (buf[0])
-#define P0  (buf[1])
-#define P4  (buf[2])
-#define P5  (buf[3])
-#define P8  (buf[4])
-#define P9  (buf[5])
-#define PB0 (buf[6])
-#define PB1 (buf[7])
-
-typedef struct _PropertyCacheItem
-{
-	gboolean bus_no_present;
-	int bus_no;
-	gboolean port_no_present;
-	int port_no;
-	gboolean csr_is_dual_present;
-	gboolean csr_is_dual;
-	gboolean current_charge_present;
-	int current_charge;
-} PropertyCacheItem;
-
-/* globals */
-static PropertyCacheItem *dev_props = NULL;
-static LibHalContext *halctx = NULL;
-static GMainLoop *main_loop;
-static const char *device_udi;
-
-/* prototypes */
-static struct usb_device *find_device (const char *hal_device_udi, PropertyCacheItem *pci);
-
-static PropertyCacheItem* 
-property_cache_item_get (const char *hal_device_udi)
-{
-	PropertyCacheItem * pci = g_new0 (PropertyCacheItem,1);
-	DBusError err;
-	dbus_error_init (&err);
-
-	pci->bus_no_present = libhal_device_property_exists (halctx, hal_device_udi, 
-			"usb_device.bus_number", &err);
-	if (dbus_error_is_set (&err))
-		HAL_ERROR (("Error: [%s]/[%s]", err.name, err.message));	
-
-	if (pci->bus_no_present)
-		pci->bus_no = libhal_device_get_property_int (halctx, hal_device_udi, 
-			"usb_device.bus_number", &err);
-
-	pci->port_no_present = libhal_device_property_exists (halctx, hal_device_udi, 
-			"usb_device.linux.device_number", &err);
-	if (pci->port_no_present)
-		pci->port_no = libhal_device_get_property_int (halctx, hal_device_udi, 
-			"usb_device.linux.device_number", &err);
-
-	pci->csr_is_dual_present = libhal_device_property_exists (halctx, hal_device_udi,
-			"battery.csr.is_dual",  &err);
-	if (pci->csr_is_dual_present)
-		pci->csr_is_dual = libhal_device_get_property_bool (halctx, hal_device_udi,
-			"battery.csr.is_dual",  &err);
-
-	pci->current_charge_present = libhal_device_property_exists (halctx, hal_device_udi, 
-			"battery.charge_level.current", &err);
-	if (pci->current_charge_present)
-		pci->current_charge = libhal_device_get_property_int (halctx, hal_device_udi, 
-			"battery.charge_level.current", &err);
-
-	return pci;
-}
-
-/* Thanks to lmctl code. I'd LOVE, REALLY LOVE to see some docs though... */
-static void 
-check_battery (const char *hal_device_udi, PropertyCacheItem *pci)
-{
-	struct usb_device *curr_device;
-	usb_dev_handle *handle;
-	char buf[80];
-	DBusError err;
-	unsigned int addr;
-	int is_dual = 0;
-	int percentage = 0;
-
-	if (pci == NULL)
-		return;
-
-	HAL_DEBUG (("CSR device: [%s]", hal_device_udi));
-	is_dual = pci->csr_is_dual;
-
-	/* Which of subdevices to address */
-	HAL_DEBUG (("Is dual: %d", is_dual));
-	addr = is_dual? 1<<8 : 0;
-
-	curr_device = find_device (hal_device_udi, pci);
-	if (curr_device == NULL)	{
-		HAL_ERROR (("Device %s not found", hal_device_udi));
-		return;
-	}
-
-	handle = usb_open (curr_device);
-	if (handle == NULL) {
-		HAL_ERROR (("Could not open usb device"));
-		return;
-	}
-
-	if (!usb_control_msg (handle, 0xc0, 0x09, 0x03|addr, 0x00|addr,
-			 buf, 8, TIMEOUT) != 8)	{
-		if ((P0 == 0x3b) && (P4 == 0)) {
-			HAL_DEBUG (("Receiver busy, trying again later"));
-		} else {
-			int current_charge = P5 & 0x07;
-
-			HAL_DEBUG (("Charge level: %d->%d", pci->current_charge, current_charge));
-			if (current_charge != pci->current_charge) { 
-			pci->current_charge = current_charge; dbus_error_init (&err);
-		 		libhal_device_set_property_int (halctx, hal_device_udi, 
-		 			"battery.charge_level.current", current_charge, &err);
-		 		if (current_charge != 0)
-		 			percentage = (100.0 / 7.0) * current_charge;
-		 		libhal_device_set_property_int (halctx, hal_device_udi, 
-		 			"battery.charge_level.percentage", percentage, &err);
-			}
-		}
-	} else
-		perror ("Writing to USB device");
-	usb_close (handle);
-}
-
-/* TODO: Is it linux-specific way to find the device? */
-static struct usb_device* 
-find_device (const char *hal_device_udi, PropertyCacheItem *pci)
-{
-	struct usb_bus* curr_bus;
-	char LUdirname[5];
-	char LUfname[5];
-
-	if (!(pci->bus_no_present && pci->port_no_present)) {
-		/* no sysfs path */
-		HAL_ERROR (("No hal bus number and/or port number"));
-		return NULL;
-	}
-	snprintf (LUdirname, sizeof (LUdirname), "%03d", pci->bus_no);
-	snprintf (LUfname, sizeof (LUfname), "%03d",pci->port_no);
-	HAL_DEBUG (("Looking for: [%s][%s]", LUdirname, LUfname));
-
-	for (curr_bus = usb_busses; curr_bus != NULL; curr_bus = curr_bus->next) {
- 		struct usb_device *curr_device;
-		/* dbg ("Checking bus: [%s]", curr_bus->dirname); */
-		if (g_strcasecmp (LUdirname, curr_bus->dirname))
-			continue;
-
- 		for (curr_device = curr_bus->devices; curr_device != NULL; 
-		     curr_device = curr_device->next) {
-			/* dbg ("Checking port: [%s]", curr_device->filename); */
-			if (g_strcasecmp (LUfname, curr_device->filename))
-				continue;
-			HAL_DEBUG (("Matched device: [%s][%s][%04X:%04X]", curr_bus->dirname, 
-				curr_device->filename, 
-				curr_device->descriptor.idVendor, 
-				curr_device->descriptor.idProduct));
-			return curr_device;
-		}
-	}
-	return NULL;
-}
-
-static gboolean
-check_all_batteries (gpointer data)
-{
-	HAL_DEBUG (("** Check batteries"));
-	/* TODO: make it configurable (not to rescan every time) */
-	usb_find_busses ();
-	usb_find_devices ();
-	check_battery (device_udi, dev_props);
-	return TRUE;
-}
-
-static gboolean 
-is_the_device (const char *hal_device_udi)
-{
-	return !g_ascii_strcasecmp (device_udi, hal_device_udi);
-}
-
-static void
-device_removed (LibHalContext *ctx, const char *hal_device_udi)
-{
-	/* this device is removed */
-	if (is_the_device (hal_device_udi)) {
-		HAL_DEBUG (("** The device %s removed, exit", device_udi));
-		g_main_loop_quit (main_loop);
-	}
-}
-
-static void 
-property_modified (LibHalContext *ctx,
-		 const char *hal_device_udi,
-		 const char *key,
-		 dbus_bool_t is_removed,
-		 dbus_bool_t is_added)
-{
-	/* "Key" property modified */
-	if (!g_ascii_strcasecmp (key, "battery.command_interface")) {
-		if (is_removed) {
-			HAL_DEBUG (("** Main Property %s removed: %s", key, hal_device_udi));
-			/* probably we'll have to exit if this is our device */
-			device_removed (ctx, hal_device_udi);
-		}
-	} else
-		/* "Secondary" property modified */
-		if (is_the_device (hal_device_udi))
-		{
-			if (!(g_ascii_strcasecmp (key, "usb_device.bus_number") &&
-			      g_ascii_strcasecmp (key, "usb_device.linux.device_number") &&
-	 		      g_ascii_strcasecmp (key, "battery.csr.is_dual"))) {
-				HAL_DEBUG (("** Property %s added/changed: %s", key, hal_device_udi));
-				if (dev_props)
-					g_free (dev_props);
-				dev_props = property_cache_item_get (hal_device_udi);
-			}
-		}
-}
-
-int
-main (int argc, char *argv[])
-{
-	DBusError err;
-
-	hal_set_proc_title_init (argc, argv);
-
-	setup_logger ();	
-
-	device_udi = getenv ("UDI");
-
-	HAL_DEBUG (("device:[%s]", device_udi));
-	if (device_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;
-	}
-
-	/* update_properties */
-	dbus_error_init (&err);
-	libhal_device_set_property_bool (halctx, device_udi, 
-			"battery.present", TRUE, &err);
-	if (!libhal_device_property_exists (halctx, device_udi, 
-			"battery.is_rechargeable", &err))
-		libhal_device_set_property_bool (halctx, device_udi, 
-			"battery.is_rechargeable", FALSE, &err);
-	libhal_device_set_property_int (halctx, device_udi, 
-			"battery.charge_level.design", 7, &err);
-	libhal_device_set_property_int (halctx, device_udi, 
-			"battery.charge_level.last_full", 7, &err);
-	libhal_device_set_property_string (halctx, device_udi, 
-			"info.category", "battery", &err);
-	libhal_device_set_property_string (halctx, device_udi, 
-			"battery.command_interface", "csr", &err);
-
-	/* monitor change */
-	libhal_ctx_set_device_property_modified (halctx, property_modified);
-
-	/* Initial fillup */
-	dev_props = property_cache_item_get (device_udi);
-	HAL_ERROR (("** Initial fillup done"));
-
-	/* init usb */
-	usb_init ();
-	
-	/* do coldplug */
-	check_all_batteries (NULL);
-
-	/* only add capability when initial charge_level key has been set */
-	dbus_error_init (&err);
-	libhal_device_add_capability (halctx, device_udi, "battery", &err);
-
-	hal_set_proc_title ("hald-addon-usb-csr: listening on '%s'", 
-			    libhal_device_get_property_string(halctx, device_udi,
-							      "info.product", &err));
-
-	main_loop = g_main_loop_new (NULL, FALSE);
-	g_timeout_add (1000L * TIMEOUT, check_all_batteries, NULL);
-	g_main_loop_run (main_loop);
-
-	libhal_ctx_shutdown (halctx, &err);
-	HAL_ERROR (("** Addon exits normally"));
-	return 0;
-}
diff --git a/hald/linux2/apm.c b/hald/linux2/apm.c
deleted file mode 100644
index e855438..0000000
--- a/hald/linux2/apm.c
+++ /dev/null
@@ -1,542 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
- * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
- *
- * 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 "../hald_dbus.h"
-#include "../device_info.h"
-#include "../logger.h"
-#include "../util.h"
-#include "../util_pm.h"
-
-#include "osspec_linux.h"
-
-#include "apm.h"
-
-enum {
-	APM_TYPE_BATTERY,
-	APM_TYPE_AC_ADAPTER
-};
-
-int interval_poll_round = 0;
-
-typedef struct APMDevHandler_s
-{
-	int apm_type;
-	HalDevice *(*add) (const gchar *apm_path, HalDevice *parent, struct APMDevHandler_s *handler);
-	gboolean (*compute_udi) (HalDevice *d, struct APMDevHandler_s *handler);
-	gboolean (*remove) (HalDevice *d, struct APMDevHandler_s *handler);
-	gboolean (*refresh) (HalDevice *d, struct APMDevHandler_s *handler);
-} APMDevHandler;
-
-typedef struct {
-	char driver_version[256];
-	int version_major;
-	int version_minor;
-	int flags;
-	int ac_line_status;
-	int battery_status;
-	int battery_flags;
-	int battery_percentage;
-	int battery_time;
-} APMInfo;
-
-#define APM_POLL_INTERVAL 2000
-
-static gboolean
-apm_poll (gpointer data)
-{
-	GSList *i;
-	GSList *devices;
-
-	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
-								    "linux.apm_path",
-								    "/proc/apm");
-	for (i = devices; i != NULL; i = g_slist_next (i)) {
-		HalDevice *d;		
-		d = HAL_DEVICE (i->data);
-		apm_rescan_device (d);
-	}
-
-	return TRUE;
-}
-
-static gboolean 
-read_from_apm (const char *apm_file, APMInfo *i)
-{
-	char *buf;
-	gboolean ret;
-
-	ret = FALSE;
-
-	if ((buf = hal_util_get_string_from_file ("", apm_file)) == NULL)
-		goto out;
-
-	if (sscanf (buf, "%s %d.%d %x %x %x %x %d%% %d",
-		    i->driver_version,
-		    &i->version_major,
-		    &i->version_minor,
-		    &i->flags,
-		    &i->ac_line_status,
-		    &i->battery_status,
-		    &i->battery_flags,
-		    &i->battery_percentage,
-		    &i->battery_time) != 9)
-		goto out;
-
-	ret = TRUE;
-
-out:
-	return ret;
-}
-
-enum
-{
-	BATTERY_HIGH     = 0,
-	BATTERY_LOW      = 1,
-	BATTERY_CRITICAL = 2,
-	BATTERY_CHARGING = 3
-};
-
-static gboolean
-battery_refresh (HalDevice *d, APMDevHandler *handler)
-{
-	const char *path;
-	int remaining_percentage;
-	int remaining_time;
-	gboolean is_charging;
-	gboolean is_discharging;
-	HalDevice *computer;
-	APMInfo i;
-
-	path = hal_device_property_get_string (d, "linux.apm_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");
-
-	/* typical : 1.16ac 1.2 0x02 0x01 0x03 0x09 98% 88 min */
-
-	read_from_apm (path, &i);
-
-	/* we check this to know if there is a battery: 
-	 * - if i.battery_percentage < 0: no battery   
-	 * - if driver version starts with [B]: old style (pre-0.7), not supported -> no battery
-	 * - if battery status == 0xff : no battery present
-	 */
-	if (i.battery_percentage < 0 || i.driver_version[0] == 'B' || i.battery_status == 0xff ) {
-		device_property_atomic_update_begin ();
-		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.charge_level.unit");
-		hal_device_property_remove (d, "battery.charge_level.current");
-		/* Is this key really needed? We don't know the value of this key */
-		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.percentage");
-		hal_device_property_remove (d, "battery.remaining_time");
-		hal_device_property_set_bool (d, "battery.present", FALSE);
-		device_property_atomic_update_end ();		
-	} else {
-		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 {
-			if (!hal_device_has_property(computer, "system.formfactor")) {
-				hal_device_property_set_string (computer, "system.formfactor", "laptop");
-			}
-			else if (strcmp (hal_device_property_get_string (computer, "system.formfactor"), "laptop") != 0) {
-				hal_device_property_set_string (computer, "system.formfactor", "laptop");
-			}
-		}
-		
-		device_property_atomic_update_begin ();
-		hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
-		hal_device_property_set_bool (d, "battery.present", TRUE);
-		hal_device_property_set_int (d, "battery.charge_level.current", i.battery_percentage);
-		hal_device_property_set_string (d, "battery.charge_level.unit", "percent");
-
-		hal_device_property_set_int (d, "battery.charge_level.design", 100);
-		/* Is this key really needed? We don't know the value of this key */
-		hal_device_property_set_int (d, "battery.charge_level.last_full", 100); 
-
-		/* TODO: clean the logic below up; it appears my T41
-		 * with 2.6.10-1.1110_FC4 and acpi=off always report
-		 * BATTERY_CHARGING so look at ac_line_status
-		 * instead..
-		 */
-		if (i.battery_status == BATTERY_CHARGING) {
-			is_charging = TRUE;
-			is_discharging = FALSE;
-			remaining_time = 0; /* apm doesn't give info */
-		} else {
-			is_charging = FALSE;
-			is_discharging = (i.ac_line_status == FALSE);
-			/* apm returns time in minutes, not seconds */
-			remaining_time = i.battery_time * 60;
-		}
-
-		/* set the time to discharge, or remove key for charging */
-		if (remaining_time > 0) {
-			/* switched from charging to discharging, set key */
-			if (!is_charging && is_discharging && !hal_device_has_property(d,"battery.remaining_time")) {
-				hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
-				interval_poll_round = 0;
-			}
-			/* after 30 seconds (15*APM_POLL_INTERVAL) set key */
-			else if (interval_poll_round == 15) {
-				hal_device_property_set_int (d, "battery.remaining_time", remaining_time);
-				interval_poll_round = 0;
-			}
-			/* else: only increment counter and set no key to avoid needless events/changes
-			   because APM produce with each read a new value for remaining time */
-			else
-				interval_poll_round++;
-		} else {
-			hal_device_property_remove (d, "battery.remaining_time");
-		}
-
-		/* set the correct charge states */
-		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", is_charging);
-		hal_device_property_set_bool (d, "battery.rechargeable.is_discharging", is_discharging);
-
-		/* set the percentage charge, easy. */
-		remaining_percentage = util_compute_percentage_charge (d->udi, i.battery_percentage, 100);
-	
-		/* Only set keys if no error (signified with negative return value) */
-		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");
-
-		device_property_atomic_update_end ();
-	}
-
-	return TRUE;
-}
-
-static gboolean
-ac_adapter_refresh (HalDevice *d, APMDevHandler *handler)
-{
-	const char *path;
-	APMInfo i;
-
-	path = hal_device_property_get_string (d, "linux.apm_path");
-	if (path == NULL)
-		return FALSE;
-
-	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");
-
-	read_from_apm(path, &i);
-
-	if (i.ac_line_status)
-		hal_device_property_set_bool (d, "ac_adapter.present", TRUE);
-	else
-		hal_device_property_set_bool (d, "ac_adapter.present", FALSE);
-
-	return TRUE;
-}
-
-/** Scan the data structures exported by the kernel and add hotplug
- *  events for adding APM objects.
- *
- *  @param                      TRUE if, and only if, APM capabilities
- *                              were detected
- */
-gboolean
-apm_synthesize_hotplug_events (void)
-{
-	gboolean ret;
-	HalDevice *computer;
-	gchar path[HAL_PATH_MAX];
-	HotplugEvent *hotplug_event;
-
-	ret = FALSE;
-
-	if (!g_file_test ("/proc/apm", G_FILE_TEST_EXISTS))
-		goto out;
-
-	ret = TRUE;
-
-	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?"));
-		goto out;
-	}
-
-	/* Set appropriate properties on the computer object */
-	hal_device_property_set_string (computer, "power_management.type", "apm");
-
-	snprintf (path, sizeof (path), "%s/apm", get_hal_proc_path ());
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_APM;
-	g_strlcpy (hotplug_event->apm.apm_path, path, sizeof (hotplug_event->apm.apm_path));
-	hotplug_event->apm.apm_type = APM_TYPE_BATTERY;
-	hotplug_event_enqueue (hotplug_event);
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->type = HOTPLUG_EVENT_APM;
-	g_strlcpy (hotplug_event->apm.apm_path, path, sizeof (hotplug_event->apm.apm_path));
-	hotplug_event->apm.apm_type = APM_TYPE_AC_ADAPTER;
-	hotplug_event_enqueue (hotplug_event);
-
-	g_timeout_add (APM_POLL_INTERVAL,
-		       apm_poll,
-		       NULL);
-
-out:
-	return ret;
-}
-
-static HalDevice *
-apm_generic_add (const gchar *apm_path, HalDevice *parent, APMDevHandler *handler)
-{
-	HalDevice *d;
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.apm_path", apm_path);
-	hal_device_property_set_int (d, "linux.apm_type", handler->apm_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
-apm_generic_compute_udi (HalDevice *d, APMDevHandler *handler)
-{
-	gchar udi[256];
-
-	if (handler->apm_type == APM_TYPE_BATTERY ) {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "/org/freedesktop/Hal/devices/apm_battery");
-	
-	} else if (handler->apm_type == APM_TYPE_AC_ADAPTER ) {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "/org/freedesktop/Hal/devices/apm_ac_adapter");
-	} else {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "/org/freedesktop/Hal/devices/apm_%d",
-				      hal_device_property_get_int (d, "info.category"));
-	}
-
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-static gboolean
-apm_generic_remove (HalDevice *d, APMDevHandler *handler)
-{
-	if (!hal_device_store_remove (hald_get_gdl (), d)) {
-		HAL_WARNING (("Error removing device"));
-	}
-
-	return TRUE;
-}
-
-static APMDevHandler apmdev_handler_battery = { 
-	.apm_type    = APM_TYPE_BATTERY,
-	.add         = apm_generic_add,
-	.compute_udi = apm_generic_compute_udi,
-	.refresh     = battery_refresh,
-	.remove      = apm_generic_remove
-};
-
-static APMDevHandler apmdev_handler_ac_adapter = { 
-	.apm_type    = APM_TYPE_AC_ADAPTER,
-	.add         = apm_generic_add,
-	.compute_udi = apm_generic_compute_udi,
-	.refresh     = ac_adapter_refresh,
-	.remove      = apm_generic_remove
-};
-
-static APMDevHandler *apm_handlers[] = {
-	&apmdev_handler_battery,
-	&apmdev_handler_ac_adapter,
-	NULL
-};
-
-void
-hotplug_event_begin_add_apm (const gchar *apm_path, int apm_type, HalDevice *parent, void *end_token)
-{
-	guint i;
-
-	HAL_INFO (("apm_add: apm_path=%s apm_type=%d, parent=0x%08x", apm_path, apm_type, parent));
-
-	for (i = 0; apm_handlers [i] != NULL; i++) {
-		APMDevHandler *handler;
-
-		handler = apm_handlers[i];
-		if (handler->apm_type == apm_type) {
-			HalDevice *d;
-
-			d = handler->add (apm_path, parent, handler);
-			if (d == NULL) {
-				/* didn't find anything - thus, ignore this hotplug event */
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_APM);
-
-			/* 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);
-
-			/* TODO: Run callouts */
-			
-			/* Compute UDI */
-			if (!handler->compute_udi (d, handler)) {
-				hal_device_store_remove (hald_get_tdl (), d);
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			/* 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);
-			goto out;
-		}
-	}
-	
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out:
-	;
-}
-
-void
-hotplug_event_begin_remove_apm (const gchar *apm_path, int apm_type, void *end_token)
-{
-	guint i;
-	HalDevice *d;
-
-	HAL_INFO (("apm_rem: apm_path=%s apm_type=%d", apm_path, apm_type));
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.apm_path", apm_path);
-	if (d == NULL) {
-		HAL_WARNING (("Couldn't remove device with apm path %s - not found", apm_path));
-		goto out;
-	}
-
-	for (i = 0; apm_handlers [i] != NULL; i++) {
-		APMDevHandler *handler;
-
-		handler = apm_handlers[i];
-		if (handler->apm_type == apm_type) {
-			if (handler->remove (d, handler)) {
-				hotplug_event_end (end_token);
-				goto out2;
-			}
-		}
-	}
-out:
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out2:
-	;
-}
-
-gboolean
-apm_rescan_device (HalDevice *d)
-{
-	guint i;
-	gboolean ret;
-	int apm_type;
-
-	ret = FALSE;
-
-	apm_type = hal_device_property_get_int (d, "linux.apm_type");
-
-	for (i = 0; apm_handlers [i] != NULL; i++) {
-		APMDevHandler *handler;
-
-		handler = apm_handlers[i];
-		if (handler->apm_type == apm_type) {
-			ret = handler->refresh (d, handler);
-			goto out;
-		}
-	}
-
-	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));
-
-out:
-	return ret;
-}
-
-HotplugEvent *
-apm_generate_add_hotplug_event (HalDevice *d)
-{
-	int apm_type;
-	const char *apm_path;
-	HotplugEvent *hotplug_event;
-
-	apm_path = hal_device_property_get_string (d, "linux.apm_path");
-	apm_type = hal_device_property_get_int (d, "linux.apm_type");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_APM;
-	g_strlcpy (hotplug_event->apm.apm_path, apm_path, sizeof (hotplug_event->apm.apm_path));
-	hotplug_event->apm.apm_type = apm_type;
-	return hotplug_event;
-}
-
-HotplugEvent *
-apm_generate_remove_hotplug_event (HalDevice *d)
-{
-	int apm_type;
-	const char *apm_path;
-	HotplugEvent *hotplug_event;
-
-	apm_path = hal_device_property_get_string (d, "linux.apm_path");
-	apm_type = hal_device_property_get_int (d, "linux.apm_type");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-	hotplug_event->type = HOTPLUG_EVENT_APM;
-	g_strlcpy (hotplug_event->apm.apm_path, apm_path, sizeof (hotplug_event->apm.apm_path));
-	hotplug_event->apm.apm_type = apm_type;
-	return hotplug_event;
-}
diff --git a/hald/linux2/apm.h b/hald/linux2/apm.h
deleted file mode 100644
index 80d0de6..0000000
--- a/hald/linux2/apm.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 Richard Hughes <richard at hughsie.com>
- * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef APM_H
-#define APM_H
-
-#include "../hald.h"
-#include "hotplug.h"
-
-gboolean apm_synthesize_hotplug_events (void);
-
-void hotplug_event_begin_add_apm (const gchar *apm_path, int apm_type, HalDevice *parent, void *end_token);
-
-void hotplug_event_begin_remove_apm (const gchar *apm_path, int apm_type, void *end_token);
-
-gboolean apm_rescan_device (HalDevice *d);
-
-HotplugEvent *apm_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *apm_generate_remove_hotplug_event (HalDevice *d);
-
-#endif /* APM_H */
diff --git a/hald/linux2/blockdev.c b/hald/linux2/blockdev.c
deleted file mode 100644
index e40dd93..0000000
--- a/hald/linux2/blockdev.c
+++ /dev/null
@@ -1,1419 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * blockdev.c : Handling of block devices
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
- *
- * 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 <ctype.h>
-#include <limits.h>
-#include <linux/kdev_t.h>
-#include <mntent.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <syslog.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../hald.h"
-#include "../hald_dbus.h"
-#include "../hald_runner.h"
-#include "../logger.h"
-#include "../osspec.h"
-#include "../util.h"
-
-#include "coldplug.h"
-#include "hotplug.h"
-#include "hotplug_helper.h"
-#include "osspec_linux.h"
-
-#include "blockdev.h"
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static gboolean
-blockdev_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	if (hal_device_property_get_bool (d, "block.is_volume")) {
-		const char *label;
-		const char *uuid;
-
-		label = hal_device_property_get_string (d, "volume.label");
-		uuid = hal_device_property_get_string (d, "volume.uuid");
-
-		if (uuid != NULL && strlen (uuid) > 0) {
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "/org/freedesktop/Hal/devices/volume_uuid_%s", uuid);
-		} else if (label != NULL && strlen (label) > 0) {
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "/org/freedesktop/Hal/devices/volume_label_%s", label);
-		} else if (hal_device_property_get_bool(d, "volume.is_disc") &&
-			   hal_device_property_get_bool(d, "volume.disc.is_blank")) {
-			/* this should be a empty CD/DVD */
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-                                             "/org/freedesktop/Hal/devices/volume_empty_%s",
-					      hal_device_property_get_string (d, "volume.disc.type"));
-		} else {
-			/* fallback to partition number, size */
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "/org/freedesktop/Hal/devices/volume_part%d_size_%lld", 
-					      hal_device_property_get_int (d, "volume.partition.number"),
-					      hal_device_property_get_uint64 (d, "volume.size"));
-		}
-	} else {
-		const char *model;
-		const char *serial;
-
-		model = hal_device_property_get_string (d, "storage.model");
-		serial = hal_device_property_get_string (d, "storage.serial");
-
-		if (serial != NULL) {
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "/org/freedesktop/Hal/devices/storage_serial_%s", 
-					      serial);
-		} else if ((model != NULL) && (strlen(model) != 0) ) {
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "/org/freedesktop/Hal/devices/storage_model_%s", 
-					      model);
-		} else {
-			hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-					      "%s_storage", 
-					      hal_device_property_get_string (d, "storage.physical_device"));
-		}
-	}
-
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-
-static void 
-blockdev_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 
-blockdev_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"));
-	}
-	g_object_unref (d);
-
-	hotplug_event_end (end_token);
-}
-
-static void
-cleanup_mountpoint_cb (HalDevice *d, guint32 exit_type, 
-		       gint return_code, gchar **error,
-		       gpointer data1, gpointer data2)
-{
-	char *mount_point = (char *) data1;
-	HAL_INFO (("In cleanup_mountpoint_cb for '%s'", mount_point));
-	g_free (mount_point);
-}
-
-void
-blockdev_refresh_mount_state (HalDevice *d)
-{
-	FILE *f;
-	struct mntent mnt;
-	struct mntent *mnte;
-	char buf[1024];
-	unsigned int major;
-	unsigned int minor;
-	dev_t devt = makedev(0, 0);
-	GSList *volumes = NULL;
-	GSList *volume;
-        GSList *autofs_mounts = NULL;
-
-	/* open /proc/mounts */
-	g_snprintf (buf, sizeof (buf), "%s/mounts", get_hal_proc_path ());
-	if ((f = setmntent (buf, "r")) == NULL) {
-		HAL_ERROR (("Could not open /proc/mounts"));
-		return;
-	}
-
-	if (d)
-		volumes = g_slist_append (NULL, d);
-	else
-		volumes = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.category", "volume");
-
-	if (!volumes)
-		goto exit;
-
-	/* loop over /proc/mounts */
-	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
-		struct stat statbuf;
-
-		/* If this is a nfs mount (fstype == 'nfs') ignore the mount. Reason:
-		 *  1. we don't list nfs devices in HAL
-		 *  2. more problematic: stat on mountpoints with 'stale nfs handle' never come
-		 *     back and block complete HAL and all applications using HAL fail.
-		 */
-		if (strcmp(mnt.mnt_type, "nfs") == 0)
-			continue;
-
-		/* If this is an autofs mount (fstype == 'autofs') 
-		 * store the mount in a list for later use. 
-		 * On mounts managed by autofs accessing files below the mount
-		 * point cause the mount point to be remounted after an 
-		 * unmount.  We keep the list so we do not check for
-		 * the .created-by-hal file on mounts under autofs mount points
-		 */
-		if (strcmp(mnt.mnt_type, "autofs") == 0) {
-			char *mnt_dir;
-
-			if (mnt.mnt_dir[strlen (mnt.mnt_dir) - 1] != '/')
-				mnt_dir = g_strdup_printf ("%s/", mnt.mnt_dir);
-			else
-				mnt_dir = g_strdup (mnt.mnt_dir);
-
-			autofs_mounts = g_slist_append (autofs_mounts,
-							mnt_dir);
-
-
-			continue;
-		}
-
-		/* check the underlying device of the mount point */
-		if (stat (mnt.mnt_dir, &statbuf) != 0)
-			continue;
-		if (major(statbuf.st_dev) == 0)
-			continue;
-
-		/*HAL_INFO (("* found mounts dev %s (%i:%i)", mnt.mnt_fsname, major(statbuf.st_dev), minor(statbuf.st_dev)));*/
-		/* match against all hal volumes */
-		for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
-			HalDevice *dev;
-
-			dev = HAL_DEVICE (volume->data);
-			major = hal_device_property_get_int (dev, "block.major");
-			if (major == 0)
-				continue;
-			minor = hal_device_property_get_int (dev, "block.minor");
-			devt = makedev(major, minor);
-			/*HAL_INFO (("  match %s (%i:%i)", hal_device_get_udi (dev), major, minor));*/
-
-			if (statbuf.st_dev == devt) {
-				/* found entry for this device in /proc/mounts */
-				device_property_atomic_update_begin ();
-				hal_device_property_set_bool (dev, "volume.is_mounted", TRUE);
-				hal_device_property_set_bool (dev, "volume.is_mounted_read_only",
-							      hasmntopt (&mnt, MNTOPT_RO) ? TRUE : FALSE);
-				hal_device_property_set_string (dev, "volume.mount_point", mnt.mnt_dir);
-				device_property_atomic_update_end ();
-				/*HAL_INFO (("  set %s to be mounted at %s (%s)",
-					   hal_device_get_udi (dev), mnt.mnt_dir,
-					   hasmntopt (&mnt, MNTOPT_RO) ? "ro" : "rw"));*/
-				volumes = g_slist_delete_link (volumes, volume);
-				break;
-			}
-		}
-	}
-
-	/* all remaining volumes are not mounted */
-	for (volume = volumes; volume != NULL; volume = g_slist_next (volume)) {
-		HalDevice *dev;
-		char *mount_point;
-		GSList *autofs_node;
-
-		dev = HAL_DEVICE (volume->data);
-		mount_point = g_strdup (hal_device_property_get_string (dev, "volume.mount_point"));
-		device_property_atomic_update_begin ();
-		hal_device_property_set_bool (dev, "volume.is_mounted", FALSE);
-		hal_device_property_set_bool (dev, "volume.is_mounted_read_only", FALSE);
-		hal_device_property_set_string (dev, "volume.mount_point", "");
-		device_property_atomic_update_end ();
-		/*HAL_INFO (("set %s to unmounted", hal_device_get_udi (dev)));*/
-
-		/* check to see if mount point falls under autofs */
-		autofs_node = autofs_mounts;
-		while (autofs_node != NULL) {
-			char *am = (char *)autofs_node->data;
-
-			if (strncmp (am, mount_point, strlen (am)) == 0);
-				break;
-
-			autofs_node = autofs_node->next;
-		}
-
-		/* look up in /media/.hal-mtab to see if we mounted this one */
-		if (mount_point != NULL && strlen (mount_point) > 0 && hal_util_is_mounted_by_hald (mount_point)) {
-			char *cleanup_stdin;
-			char *extra_env[2];
-
-			HAL_INFO (("Cleaning up directory '%s' since it was created by HAL's Mount()", mount_point));
-
-			extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
-			extra_env[1] = NULL;
-			cleanup_stdin = "\n";
-
-			hald_runner_run_method (dev, 
-						"hal-storage-cleanup-mountpoint", 
-						extra_env, 
-						cleanup_stdin, TRUE,
-						0,
-						cleanup_mountpoint_cb,
-						g_strdup (mount_point), NULL);
-		}
-
-		g_free (mount_point);
-	}
-	g_slist_free (volumes);
-	g_slist_foreach (autofs_mounts, (GFunc) g_free, NULL);
-	g_slist_free (autofs_mounts);
-exit:
-	endmntent (f);
-}
-
-static void
-generate_fakevolume_hotplug_event_add_for_storage_device (HalDevice *d)
-{
-	const char *sysfs_path;
-	const char *device_file;
-	HotplugEvent *hotplug_event;
-	char fake_sysfs_path[HAL_PATH_MAX];
-
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-	device_file = hal_device_property_get_string (d, "block.device");
-
-	snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, fake_sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	if (device_file != NULL)
-		g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
-	else
-		hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	hotplug_event_enqueue (hotplug_event);
-	hotplug_event_process_queue ();
-}
-
-static void 
-add_blockdev_probing_helper_done (HalDevice *d, guint32 exit_type, 
-                                  gint return_code, char **error,
-                                  gpointer data1, gpointer data2) 
-{
-	void *end_token = (void *) data1;
-	gboolean is_volume;
-
-	/* helper_data may be null if probing is skipped */
-
-	HAL_INFO (("entering; exit_type=%d, return_code=%d", exit_type, return_code));
-
-	if (d == NULL) {
-		HAL_INFO (("Device object already removed"));
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	is_volume = hal_device_property_get_bool (d, "block.is_volume");
-
-	/* Discard device if probing reports failure 
-	 * 
-	 * (return code 2 means fs found on main block device (for non-volumes)) 
-	 */
-	if (exit_type != HALD_RUN_SUCCESS
-	    || !(return_code == 0 || (!is_volume && return_code == 2))) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	if (!blockdev_compute_udi (d)) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	/* set block.storage_device for storage devices since only now we know the UDI */
-	if (!is_volume) {
-		hal_device_copy_property (d, "info.udi", d, "block.storage_device");
-	} else {
-		/* check for mount point */
-		blockdev_refresh_mount_state (d);
-	}
-
-	/* Merge properties from .fdi files */
-	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
-	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
-
-	/* TODO: Merge persistent properties */
-
-	/* Run callouts */
-	hal_util_callout_device_add (d, blockdev_callouts_add_done, end_token, NULL);
-
-	/* Yay, got a file system on the main block device...
-	 *
-	 * Generate a fake hotplug event to get this added
-	 */
-	if (!is_volume && return_code == 2) {
-		generate_fakevolume_hotplug_event_add_for_storage_device (d);
-	}
-
-
-out:
-	return;
-}
-
-static void 
-blockdev_callouts_preprobing_storage_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
-{
-	void *end_token = (void *) userdata1;
-
-	if (hal_device_property_get_bool (d, "info.ignore")) {
-		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
-		 * Also remove category and all capabilities
-		 */
-		hal_device_property_remove (d, "info.category");
-		hal_device_property_remove (d, "info.capabilities");
-		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
-		hal_device_property_set_string (d, "info.product", "Ignored Device");
-
-		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-
-		/* 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);
-		goto out;
-	}
-
-	if (!hal_device_property_get_bool (d, "storage.media_check_enabled") &&
-	    hal_device_property_get_bool (d, "storage.no_partitions_hint")) {
-
-		/* special probe for PC floppy drives */
-		if (strcmp (hal_device_property_get_string (d, "storage.bus"), "platform") == 0 &&
-		    strcmp (hal_device_property_get_string (d, "storage.drive_type"), "floppy") == 0) {
-			HAL_INFO (("Probing PC floppy %s to see if it is present", 
-				   hal_device_property_get_string (d, "block.device")));
-
-			hald_runner_run(d, 
-			                    "hald-probe-pc-floppy", NULL,
-			                    HAL_HELPER_TIMEOUT,
-			                    add_blockdev_probing_helper_done,
-			                    (gpointer) end_token, NULL);
-			goto out;
-		} else {
-			char *synerror[1] = {NULL};
-
-			HAL_INFO (("Not probing storage device %s", 
-				   hal_device_property_get_string (d, "block.device")));
-
-			add_blockdev_probing_helper_done (d, FALSE, 0, synerror, (gpointer) end_token, NULL);
-			goto out;
-		}
-	}
-
-	/* run prober for 
-	 *
-	 *  - cdrom drive properties
-	 *  - non-partitioned filesystem on main block device
-	 */
-
-	HAL_INFO (("Probing storage device %s", hal_device_property_get_string (d, "block.device")));
-
-	/* probe the device */
-	hald_runner_run(d,
-			"hald-probe-storage", NULL,
-			HAL_HELPER_TIMEOUT,
-			add_blockdev_probing_helper_done,
-			(gpointer) end_token, NULL);
-
-out:
-	return;
-}
-
-static void
-blockdev_callouts_preprobing_volume_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
-{
-	void *end_token = (void *) userdata1;
-
-	if (hal_device_property_get_bool (d, "info.ignore")) {
-		/* Leave the device here with info.ignore==TRUE so we won't pick up children
-		 * Also remove category and all capabilities
-		 */
-		hal_device_property_remove (d, "info.category");
-		hal_device_property_remove (d, "info.capabilities");
-		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
-		hal_device_property_set_string (d, "info.product", "Ignored Device");
-
-		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-
-		/* 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);
-		goto out;
-	}
-
-	/* probe the device */
-	hald_runner_run (d,
-			 "hald-probe-volume", NULL, 
-			 HAL_HELPER_TIMEOUT,
-			 add_blockdev_probing_helper_done,
-			 (gpointer) end_token, NULL);
-out:
-	return;
-}
-
-/* borrowed from gtk/gtkfilesystemunix.c in GTK+ on 02/23/2006 
- * (which is LGPL, so can't go into hald/utils.[ch] until it's relicensed)
- */
-static void
-canonicalize_filename (gchar *filename)
-{
-	gchar *p, *q;
-	gboolean last_was_slash = FALSE;
-	
-	p = filename;
-	q = filename;
-	
-	while (*p)
-	{
-		if (*p == G_DIR_SEPARATOR)
-		{
-			if (!last_was_slash)
-				*q++ = G_DIR_SEPARATOR;
-			
-			last_was_slash = TRUE;
-		}
-		else
-		{
-			if (last_was_slash && *p == '.')
-			{
-				if (*(p + 1) == G_DIR_SEPARATOR ||
-				    *(p + 1) == '\0')
-				{
-					if (*(p + 1) == '\0')
-						break;
-					
-					p += 1;
-				}
-				else if (*(p + 1) == '.' &&
-					 (*(p + 2) == G_DIR_SEPARATOR ||
-					  *(p + 2) == '\0'))
-				{
-					if (q > filename + 1)
-					{
-						q--;
-						while (q > filename + 1 &&
-						       *(q - 1) != G_DIR_SEPARATOR)
-							q--;
-					}
-					
-					if (*(p + 2) == '\0')
-						break;
-					
-					p += 2;
-				}
-				else
-				{
-					*q++ = *p;
-					last_was_slash = FALSE;
-				}
-			}
-			else
-			{
-				*q++ = *p;
-				last_was_slash = FALSE;
-			}
-		}
-		
-		p++;
-	}
-	
-	if (q > filename + 1 && *(q - 1) == G_DIR_SEPARATOR)
-		q--;
-	
-	*q = '\0';
-}
-
-static char *
-resolve_symlink (const char *file)
-{
-	GError *error;
-	char *dir;
-	char *link;
-	char *f;
-	char *f1;
-
-	f = g_strdup (file);
-
-	while (g_file_test (f, G_FILE_TEST_IS_SYMLINK)) {
-		link = g_file_read_link (f, &error);
-		if (link == NULL) {
-			g_warning ("Cannot resolve symlink %s: %s", f, error->message);
-			g_error_free (error);
-			g_free (f);
-			f = NULL;
-			goto out;
-		}
-		
-		dir = g_path_get_dirname (f);
-		f1 = g_strdup_printf ("%s/%s", dir, link);
-		g_free (dir);
-		g_free (link);
-		g_free (f);
-		f = f1;
-	}
-
-out:
-	if (f != NULL)
-		canonicalize_filename (f);
-	return f;
-}
-
-void
-hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const gchar *device_file, gboolean is_partition,
-				  HalDevice *parent, void *end_token)
-{
-	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
-	gchar *major_minor;
-	HalDevice *d;
-	unsigned int major, minor;
-	gboolean is_fakevolume;
-	char *sysfs_path_real = NULL;
-	int floppy_num;
-	gboolean is_device_mapper;
-
-	is_device_mapper = FALSE;
-
-	HAL_INFO (("block_add: sysfs_path=%s dev=%s is_part=%d, parent=0x%08x", 
-		   sysfs_path, device_file, is_partition, parent));
-
-	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
-		HAL_INFO (("Ignoring block_add since parent has info.ignore==TRUE"));
-		goto out;
-	}
-
-	if (strcmp (hal_util_get_last_element (sysfs_path), "fakevolume") == 0) {
-		is_fakevolume = TRUE;
-		sysfs_path_real = hal_util_get_parent_path (sysfs_path);
-		HAL_INFO (("Handling %s as fakevolume - sysfs_path_real=%s", device_file, sysfs_path_real));
-	} else {
-		is_fakevolume = FALSE;
-		sysfs_path_real = g_strdup (sysfs_path);
-	}
-	
-	/* See if we already have device (which we may have as we're ignoring rem/add
-	 * for certain classes of devices - see hotplug_event_begin_remove_blockdev)
-	 */
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
-	if (d != NULL) {
-		HAL_INFO (("Ignoring hotplug event - device is already added"));
-		goto out;
-	}
-
-	d = hal_device_new ();
-
-	/* OK, no parent... it might a device-mapper device => check slaves/ subdir in sysfs */
-	if (parent == NULL && !is_partition && !is_fakevolume) {
-		GDir *dir;
-		GError *err = NULL;
-		char path[HAL_PATH_MAX];
-
-
-		/* sleep one second since device mapper needs additional
-		 * time before the device file is ready
-		 *
-		 * this is a hack and will only affect device mapper block
-		 * devices. It can go away once the kernel emits a "changed"
-		 * event for the device file (this is about to go upstream)
-		 * and we can depend on a released kernel with this feature.
-		 */
-		if (strncmp (hal_util_get_last_element (sysfs_path), "dm-", 3) == 0) {
-			HAL_INFO (("Waiting 1000ms to wait for device mapper to be ready", path));
-			usleep (1000 * 1000);
-		}
-
-		g_snprintf (path, HAL_PATH_MAX, "%s/slaves", sysfs_path);
-		HAL_INFO (("Looking in %s", path));
-		if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_WARNING (("Unable to open %s: %s", path, err->message));
-			g_error_free (err);
-		} else {
-			const char *f;
-			while (((f = g_dir_read_name (dir)) != NULL) && (parent == NULL)) {
-				char *link;
-				char *target;
-
-				link = g_strdup_printf ("%s/%s", path, f);
-				target = resolve_symlink (link);
-				HAL_INFO ((" %s -> %s", link, target));
-
-				if (target != NULL) {
-					HalDevice *slave_volume;
-
-					slave_volume = hal_device_store_match_key_value_string (hald_get_gdl (),
-												"linux.sysfs_path", 
-												target);
-					if (slave_volume != NULL) {
-						const char *slave_volume_stordev_udi;
-						const char *slave_volume_fstype;
-
-						slave_volume_stordev_udi = hal_device_property_get_string (slave_volume, "block.storage_device");
-						slave_volume_fstype = hal_device_property_get_string (slave_volume, "volume.fstype");
-
-						/* Yup, we only support crypto_LUKS right now.
-						 *
-						 * In the future we can support other device-mapper mappings
-						 * such as LVM etc.
-						 */ 
-						if (slave_volume_stordev_udi != NULL &&
-						    slave_volume_fstype != NULL &&
-						    (strcmp (slave_volume_fstype, "crypto_LUKS") == 0)) {
-							HAL_INFO ((" slave_volume_stordev_udi='%s'!", slave_volume_stordev_udi));
-							parent = hal_device_store_find (hald_get_gdl (), slave_volume_stordev_udi);
-							if (parent != NULL) {
-								HAL_INFO ((" parent='%s'!", parent->udi));
-								hal_device_property_set_string (d, "volume.crypto_luks.clear.backing_volume", slave_volume->udi);
-								is_device_mapper = TRUE;
-							}
-						}
-					}
-				}
-				g_free (target);
-			}
-			g_dir_close (dir);
-			HAL_INFO (("Done looking in %s", path));
-		}
-		
-	}
-
-	if (parent == NULL) {
-		HAL_INFO (("Ignoring hotplug event - no parent"));
-		goto error;
-	}
-
-	if (!is_fakevolume && hal_device_property_get_bool (parent, "storage.no_partitions_hint")) {
-		HAL_INFO (("Ignoring blockdev since not a fakevolume and parent has "
-			   "storage.no_partitions_hint==TRUE"));
-		goto error;
-	}
-
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", parent->udi);
-	hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_BLOCK);
-
-	hal_device_property_set_string (d, "block.device", device_file);
-	if ((major_minor = hal_util_get_string_from_file (sysfs_path_real, "dev")) == NULL || 
-	    sscanf (major_minor, "%d:%d", &major, &minor) != 2) {
-		HAL_INFO (("Ignoring hotplug event - cannot read major:minor"));
-		goto error;
-	}
-
-	hal_device_property_set_int (d, "block.major", major);
-	hal_device_property_set_int (d, "block.minor", minor);
-	hal_device_property_set_bool (d, "block.is_volume", is_partition || is_device_mapper || is_fakevolume);
-
-	if (hal_device_has_property(parent, "info.bus") &&
-		(strcmp(hal_device_property_get_string(parent, "info.bus"), "platform") == 0) &&
-		(sscanf(hal_device_property_get_string(parent, "platform.id"), "floppy.%d", &floppy_num) == 1)) {
-		/* for now, just cheat here for floppy drives */
-
-		HAL_INFO (("doing floppy drive hack for floppy %d", floppy_num));
-
-		hal_device_property_set_string (d, "storage.bus", "platform");
-		hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
-		hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
-		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
-		hal_device_property_set_string (d, "storage.model", "");
-		hal_device_property_set_string (d, "storage.vendor", "PC Floppy Drive");
-		hal_device_property_set_string (d, "info.vendor", "");
-		hal_device_property_set_string (d, "info.product", "PC Floppy Drive");
-		hal_device_property_set_string (d, "storage.drive_type", "floppy");
-		hal_device_property_set_string (d, "storage.physical_device", parent->udi);
-		hal_device_property_set_bool (d, "storage.removable", TRUE);
-		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
-		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
-		hal_device_property_set_bool (d, "storage.hotpluggable", FALSE);
-		hal_device_property_set_bool (d, "storage.requires_eject", FALSE);
-		hal_device_property_set_uint64 (d, "storage.size", 0);
-
-		hal_device_property_set_string (d, "info.category", "storage");
-		hal_device_add_capability (d, "storage");
-		hal_device_add_capability (d, "block");
-
-		/* add to TDL so preprobing callouts and prober can access it */
-		hal_device_store_add (hald_get_tdl (), d);
-
-		/* Process preprobe fdi files */
-		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
-
-		/* Run preprobe callouts */
-		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_storage_done, end_token, NULL);
-		goto out2;
-	}
-
-	if (!is_partition && !is_device_mapper && !is_fakevolume) {
-		const char *udi_it;
-		const char *physdev_udi;
-		HalDevice *scsidev;
-		HalDevice *physdev;
-		gboolean is_hotpluggable;
-		gboolean is_removable;
-		gboolean requires_eject;
-		gboolean no_partitions_hint;
-		const gchar *bus;
-		const gchar *parent_bus;
-
-		/********************************
-		 * storage devices
-		 *******************************/
-
-		scsidev = NULL;
-		physdev = NULL;
-		physdev_udi = NULL;
-
-		is_removable = FALSE;
-		is_hotpluggable = FALSE;
-		requires_eject = FALSE;
-		no_partitions_hint = FALSE;
-
-		/* defaults */
-		hal_device_property_set_string (d, "storage.bus", "unknown");
-		hal_device_property_set_bool (d, "storage.no_partitions_hint", TRUE);
-		hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
-		hal_device_property_set_bool (d, "storage.automount_enabled_hint", TRUE);
-		hal_device_property_set_string (d, "storage.drive_type", "disk");
-
-		/* persistent properties from udev (may be empty) */
-		hal_device_property_set_string (d, "storage.model", hotplug_event->sysfs.model);
-		hal_device_property_set_string (d, "storage.vendor", hotplug_event->sysfs.vendor);
-		if (hotplug_event->sysfs.serial[0] != '\0')
-			hal_device_property_set_string (d, "storage.serial", hotplug_event->sysfs.serial);
-		if (hotplug_event->sysfs.revision[0] != '\0')
-			hal_device_property_set_string (d, "storage.firmware_version", hotplug_event->sysfs.revision);
-
-		/* walk up the device chain to find the physical device, 
-		 * start with our parent. On the way, optionally pick up
-		 * the scsi if it exists */
-		udi_it = parent->udi;
-		while (udi_it != NULL) {
-			HalDevice *d_it;
-
-			/*************************
-			 *
-			 * STORAGE
-			 *
-			 ************************/
-
-			/* Find device */
-			d_it = hal_device_store_find (hald_get_gdl (), udi_it);
-			g_assert (d_it != NULL);
-
-			/* Check info.bus */
-			if ((bus = hal_device_property_get_string (d_it, "info.bus")) != NULL) {
-				if (strcmp (bus, "scsi") == 0) {
-					scsidev = d_it;
-					physdev = d_it;
-					physdev_udi = udi_it;
-					hal_device_property_set_string (d, "storage.bus", "scsi");
-					hal_device_copy_property (scsidev, "scsi.lun", d, "storage.lun");
-					/* want to continue here, because it may be USB or IEEE1394 */
-				}
-
-				if (strcmp (bus, "usb") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					is_hotpluggable = TRUE;
-					hal_device_property_set_string (d, "storage.bus", "usb");
-					break;
-				} else if (strcmp (bus, "ieee1394") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					is_hotpluggable = TRUE;
-					hal_device_property_set_string (d, "storage.bus", "ieee1394");
-					break;
-				} else if (strcmp (bus, "ide") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					hal_device_property_set_string (d, "storage.bus", "ide");
-					/* want to continue here, because it may be pcmcia */
-				} else if (strcmp (bus, "pcmcia") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					is_hotpluggable = TRUE;
-					hal_device_property_set_string (d, "storage.bus", "pcmcia");
-					break;
-				} else if (strcmp (bus, "mmc") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					is_hotpluggable = TRUE;
-					hal_device_property_set_string (d, "storage.bus", "mmc");
-					break;
-				} else if (strcmp (bus, "ccw") == 0) {
-					physdev = d_it;
-					physdev_udi = udi_it;
-					is_hotpluggable = TRUE;
-					hal_device_property_set_string
-						(d, "storage.bus", "ccw");
-				}
-			}
-
-			/* Go to parent */
-			udi_it = hal_device_property_get_string (d_it, "info.parent");
-		}
-
-		/* needs physical device */
-		if (physdev_udi == NULL) {
-			HAL_WARNING (("No physical device?"));
-			goto error;
-		}
-
-		hal_device_property_set_string (d, "storage.physical_device", physdev_udi);
-
-		if (!hal_util_get_int_from_file (sysfs_path, "removable", (gint *) &is_removable, 10)) {
-			HAL_WARNING (("Cannot get 'removable' file"));
-			goto error;
-		}
-
-		hal_device_property_set_bool (d, "storage.removable.media_available", FALSE);
-		hal_device_property_set_uint64 (d, "storage.removable.media_size", 0);
-		hal_device_property_set_bool (d, "storage.removable", is_removable);
-		/* set storage.size only if we have fixed media */
-		if (!is_removable) {
-			guint64 num_blocks;
-			if (hal_util_get_uint64_from_file (sysfs_path, "size", &num_blocks, 0)) {
-				/* TODO: sane to assume this is always 512 for non-removable? 
-				 * I think genhd.c guarantees this... */
-				hal_device_property_set_uint64 (d, "storage.size", num_blocks * 512);
-			}
-		} else {
-			hal_device_property_set_uint64 (d, "storage.size", 0);
-		}
-
-		/* by default, do checks for media if, and only if, the removable file is set to 1
-		 *
-		 * Problematic buses, like IDE, may override this.
-		 */
-		hal_device_property_set_bool (d, "storage.media_check_enabled", is_removable);
-
-		parent_bus = hal_device_property_get_string (parent, "info.bus");
-		if (parent_bus == NULL) {
-			HAL_INFO (("parent_bus is NULL - wrong parent?"));
-			goto error;
-		}
-		HAL_INFO (("parent_bus is %s", parent_bus));
-
-		/* per-bus specific properties */
-		if (strcmp (parent_bus, "ide") == 0) {
-			char buf[256];
-			gchar *media;
-			gchar *model;
-
-			/* Be conservative and don't poll IDE drives at all (except CD-ROM's, see below) */
-			hal_device_property_set_bool (d, "storage.media_check_enabled", FALSE);
-
-			/* according to kernel source, media can assume the following values:
-			 *
-			 * "disk", "cdrom", "tape", "floppy", "UNKNOWN"
-			 */
-			snprintf (buf, sizeof (buf), "%s/ide/%s", get_hal_proc_path (), hal_util_get_last_element (sysfs_path));
-			if ((media = hal_util_get_string_from_file (buf, "media")) != NULL) {
-				if (strcmp (media, "disk") == 0 ||
-				    strcmp (media, "cdrom") == 0 ||
-				    strcmp (media, "floppy") == 0) {
-					hal_device_property_set_string (d, "storage.drive_type", media);
-				} else {
-					HAL_WARNING (("Cannot determine IDE drive type from file %s/media", buf));
-					goto error;
-				}
-
-				if (strcmp (media, "cdrom") == 0) {
-					/* only optical drives are the only IDE devices that can safely be polled */
-					hal_device_property_set_bool (d, "storage.media_check_enabled", TRUE);
-				}
-			}
-
-			if ((model = hal_util_get_string_from_file (buf, "model")) != NULL) {
-				hal_device_property_set_string (d, "storage.model", model);
-				hal_device_property_set_string (d, "info.product", model);
-			}
-
-		} else if (strcmp (parent_bus, "scsi") == 0) {
-			if (strcmp (hal_device_property_get_string (parent, "scsi.type"), "unknown") == 0) {
-				HAL_WARNING (("scsi.type is unknown"));
-				goto error;
-			}
-			hal_device_copy_property (parent, "scsi.type", d, "storage.drive_type");
-			hal_device_copy_property (parent, "scsi.vendor", d, "storage.vendor");
-			hal_device_copy_property (parent, "scsi.model", d, "storage.model");
-
-			hal_device_copy_property (d, "storage.vendor", d, "info.vendor");
-			hal_device_copy_property (d, "storage.model", d, "info.product");
-
-			/* Check for USB floppy drive by looking at USB Mass Storage interface class
-			 * instead of Protocol: Uniform Floppy Interface (UFI) in /proc as we did before.
-			 *
-			 * (should fix RH bug 133834)
-			 */
-			if (physdev != NULL) {
-				if (hal_device_property_get_int (physdev, "usb.interface.class") == 8 &&
-				    hal_device_property_get_int (physdev, "usb.interface.subclass") == 4 ) {
-					
-					hal_device_property_set_string (d, "storage.drive_type", "floppy");
-					
-					/* My experiments with my USB LaCie Floppy disk
-					 * drive is that polling indeed work (Yay!), so
-					 * we don't set storage.media_check_enabled to 
-					 * FALSE - for devices where this doesn't work,
-					 * we can override it with .fdi files
-					 */
-				}
-			}
-
-		} else if (strcmp (parent_bus, "mmc") == 0) {
-			hal_device_property_set_string (d, "storage.drive_type", "sd_mmc");
-		}
-
-		hal_device_property_set_string (d, "info.category", "storage");
-		hal_device_add_capability (d, "storage");
-		hal_device_add_capability (d, "block");
-
-		if (strcmp (hal_device_property_get_string (d, "storage.drive_type"), "cdrom") == 0) {
-			hal_device_add_capability (d, "storage.cdrom");
-			no_partitions_hint = TRUE;
-			requires_eject = TRUE;
-		}
-
-		if (strcmp (hal_device_property_get_string (d, "storage.drive_type"), "floppy") == 0) {
-			no_partitions_hint = TRUE;
-		}
-
-		hal_device_property_set_bool (d, "storage.hotpluggable", is_hotpluggable);
-		hal_device_property_set_bool (d, "storage.requires_eject", requires_eject);
-		hal_device_property_set_bool (d, "storage.no_partitions_hint", no_partitions_hint);
-
-		/* add to TDL so preprobing callouts and prober can access it */
-		hal_device_store_add (hald_get_tdl (), d);
-
-		/* Process preprobe fdi files */
-		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
-
-		/* Run preprobe callouts */
-		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_storage_done, end_token, NULL);
-
-	} else {
-		guint sysfs_path_len;
-		gboolean is_physical_partition;
-
-		/*************************
-		 *
-		 * VOLUMES
-		 *
-		 ************************/
-		hal_device_property_set_string (d, "block.storage_device", parent->udi);
-
-		/* defaults */
-		hal_device_property_set_string (d, "storage.model", "");
-		hal_device_property_set_string (d, "volume.fstype", "");
-		hal_device_property_set_string (d, "volume.fsusage", "");
-		hal_device_property_set_string (d, "volume.fsversion", "");
-		hal_device_property_set_string (d, "volume.uuid", "");
-		hal_device_property_set_string (d, "volume.label", "");
-		hal_device_property_set_string (d, "volume.mount_point", "");
-		hal_device_property_set_bool (d, "volume.is_mounted", FALSE);
-		hal_device_property_set_bool (d, "volume.is_mounted_read_only", FALSE);
-		hal_device_property_set_bool (d, "volume.linux.is_device_mapper", is_device_mapper);
-		hal_device_property_set_bool (
-			d, "volume.is_disc", 
-			strcmp (hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0);
-
-
-		is_physical_partition = TRUE;
-		if (is_fakevolume || is_device_mapper)
-			is_physical_partition = FALSE;
-
-		hal_device_property_set_bool (d, "volume.is_partition", is_physical_partition);
-
-		hal_device_property_set_string (d, "info.category", "volume");
-		if (strcmp(hal_device_property_get_string (parent, "storage.drive_type"), "cdrom") == 0) {
-			hal_device_add_capability (d, "volume.disc");
-		}
-		hal_device_add_capability (d, "volume");
-		hal_device_add_capability (d, "block");
-
-		/* determine partition number */
-		sysfs_path_len = strlen (sysfs_path);
-		if (is_physical_partition) {
-			if (sysfs_path_len > 0 && isdigit (sysfs_path[sysfs_path_len - 1])) {
-				guint i;
-				for (i = sysfs_path_len - 1; isdigit (sysfs_path[i]); --i)
-					;
-				if (isdigit (sysfs_path[i+1])) {
-					guint partition_number;
-					partition_number = atoi (&sysfs_path[i+1]);
-					hal_device_property_set_int (d, "volume.partition.number", partition_number);
-				} else {
-					HAL_WARNING (("Cannot determine partition number?"));
-					goto error;
-				}
-			} else {
-				HAL_WARNING (("Cannot determine partition number"));
-				goto error;
-			}
-		}
-
-		/* first estimate - prober may override this...
-		 *
-		 * (block size requires opening the device file)
-		 */
-		hal_device_property_set_int (d, "volume.block_size", 512);
-		if (!hal_util_set_int_from_file (d, "volume.num_blocks", sysfs_path_real, "size", 0)) {
-			HAL_INFO (("Ignoring hotplug event - cannot read 'size'"));
-			goto error;
-		}
-		hal_device_property_set_uint64 (
-			d, "volume.size",
-			((dbus_uint64_t)(512)) * ((dbus_uint64_t)(hal_device_property_get_int (d, "volume.num_blocks"))));
-		/* TODO: move to prober? */
-		if (is_physical_partition) {
-			guint64 start_block;
-			guint64 parent_size;
-			if (hal_util_get_uint64_from_file (sysfs_path, "start", &start_block, 0)) {
-				hal_device_property_set_uint64 (d, "volume.partition.start", start_block * 512);
-			}
-			if (hal_util_get_uint64_from_file (sysfs_path, "../size", &parent_size, 0)) {
-				hal_device_property_set_uint64 (d, "volume.partition.media_size", parent_size * 512);
-			}
-		}
-
-
-		/* add to TDL so preprobing callouts and prober can access it */
-		hal_device_store_add (hald_get_tdl (), d);
-
-		/* Process preprobe fdi files */
-		di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
-
-		/* Run preprobe callouts */
-		hal_util_callout_device_preprobe (d, blockdev_callouts_preprobing_volume_done, end_token, NULL);
-	}
-out2:
-	g_free (sysfs_path_real);
-	return;
-
-error:
-	HAL_WARNING (("Not adding device object"));
-	if (d != NULL)
-		g_object_unref (d);
-out:
-	hotplug_event_end (end_token);
-	g_free (sysfs_path_real);
-}
-
-static void
-force_unmount_cb (HalDevice *d, guint32 exit_type, 
-		  gint return_code, gchar **error,
-		  gpointer data1, gpointer data2)
-{
-	void *end_token = (void *) data1;
-
-	HAL_INFO (("force_unmount_cb for udi='%s', exit_type=%d, return_code=%d", d->udi, exit_type, return_code));
-
-	if (exit_type == HALD_RUN_SUCCESS && error != NULL && 
-	    error[0] != NULL && error[1] != NULL) {
-		char *exp_name = NULL;
-		char *exp_detail = NULL;
-
-		exp_name = error[0];
-		if (error[0] != NULL) {
-			exp_detail = error[1];
-		}
-		HAL_INFO (("failed with '%s' '%s'", exp_name, exp_detail));
-	}
-
-	hal_util_callout_device_remove (d, blockdev_callouts_remove_done, end_token, NULL);
-
-}
-
-static void
-force_unmount (HalDevice *d, void *end_token)
-{
-	const char *device_file;
-	const char *mount_point;
-
-	device_file = hal_device_property_get_string (d, "block.device");
-	mount_point = hal_device_property_get_string (d, "volume.mount_point");
-
-	/* look up in /media/.hal-mtab to see if we mounted this one */
-	if (mount_point != NULL && strlen (mount_point) > 0 && hal_util_is_mounted_by_hald (mount_point)) {
-		char *unmount_stdin;
-		char *extra_env[2];
-
-		extra_env[0] = "HAL_METHOD_INVOKED_BY_UID=0";
-		extra_env[1] = NULL;
-		
-		HAL_INFO (("force_unmount for udi='%s'", d->udi));
-		syslog (LOG_NOTICE, "forcibly attempting to lazy unmount %s as enclosing drive was disconnected", device_file);
-		
-		unmount_stdin = "lazy\n";
-		
-		/* so, yea, calling the Unmount methods handler.. is cheating a bit :-) */
-		hald_runner_run_method (d, 
-					"hal-storage-unmount", 
-					extra_env, 
-					unmount_stdin, TRUE,
-					0,
-					force_unmount_cb,
-					end_token, NULL);
-
-/*
-		char *cleanup_stdin;
-		char *extra_env[2];
-		
-		HAL_INFO (("Cleaning up directory '%s' since it was created by HAL's Mount()", mount_point));
-		
-		extra_env[0] = g_strdup_printf ("HALD_CLEANUP=%s", mount_point);
-		extra_env[1] = NULL;
-		cleanup_stdin = "\n";
-		
-		hald_runner_run_method (dev, 
-					"hal-storage-cleanup-mountpoint", 
-					extra_env, 
-					cleanup_stdin, TRUE,
-					0,
-					cleanup_mountpoint_cb,
-					g_strdup (mount_point), NULL);
-*/
-	}
-
-
-}
-
-void
-hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, void *end_token)
-{
-	HalDevice *d;
-
-	HAL_INFO (("block_rem: sysfs_path=%s is_part=%d", sysfs_path));
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
-	if (d == NULL) {
-		HAL_WARNING (("Device is not in the HAL database"));
-		hotplug_event_end (end_token);
-	} else {
-		HalDevice *fakevolume;
-		char fake_sysfs_path[HAL_PATH_MAX];
-
-		/* if we're a storage device synthesize hotplug rem event 
-		 * for the one potential fakevolume we've got 
-		 */
-		snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
-		fakevolume = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", fake_sysfs_path);
-		if (fakevolume != NULL) {
-			HotplugEvent *hotplug_event;
-			HAL_INFO (("Storage device with a fakevolume is going away; "
-				   "synthesizing hotplug rem for fakevolume %s", fakevolume->udi));
-			hotplug_event = blockdev_generate_remove_hotplug_event (fakevolume);
-			if (hotplug_event != NULL) {
-				/* push synthesized event at front of queue and repost this event... this is such that
-				 * the fakevolume event is processed before this one... because if we didn't make the
-				 * events to be processed in this order, the "lazy unmount" of the fakevolume would
-				 * fail...
-				 */
-				hotplug_event_enqueue_at_front ((HotplugEvent *) end_token);
-				hotplug_event_enqueue_at_front (hotplug_event);
-				hotplug_event_reposted (end_token);
-				goto out;
-			}
-
-		}
-		
-		/* if we're mounted, then do a lazy unmount so the system can gracefully recover */
-		if (hal_device_property_get_bool (d, "volume.is_mounted")) {
-			force_unmount (d, end_token);
-		} else {
-			hal_util_callout_device_remove (d, blockdev_callouts_remove_done, end_token, NULL);
-		}
-	}
-out:
-	;
-}
-
-static void 
-block_rescan_storage_done (HalDevice *d, guint32 exit_type, 
-                           gint return_code, gchar **error,
-                           gpointer data1, gpointer data2)
-{
-	const char *sysfs_path;
-	HalDevice *fakevolume;
-	char fake_sysfs_path[HAL_PATH_MAX];
-
-	HAL_INFO (("hald-probe-storage --only-check-for-media returned %d (exit_type=%d)", return_code, exit_type));
-
-	if (d == NULL) {
-		HAL_INFO (("Device object already removed"));
-		goto out;
-	}
-
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	/* see if we already got a fake volume */
-	snprintf (fake_sysfs_path, sizeof(fake_sysfs_path), "%s/fakevolume", sysfs_path);
-	fakevolume = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", fake_sysfs_path);
-
-	if (return_code == 2) {
-		/* we've got something on the main block device - add fakevolume if we haven't got one already */
-		if (fakevolume == NULL) {
-			HAL_INFO (("Media insertion detected with file system on main block device; synthesizing hotplug add"));
-			generate_fakevolume_hotplug_event_add_for_storage_device (d);
-		}
-	} else {
-		/* no fs on the main block device - remove fakevolume if we have one */
-		if (fakevolume != NULL) {
-			/* generate hotplug event to remove the fakevolume */
-			HotplugEvent *hotplug_event;
-			HAL_INFO (("Media removal detected; synthesizing hotplug rem for fakevolume %s", fakevolume->udi));
-			hotplug_event = blockdev_generate_remove_hotplug_event (fakevolume);
-			if (hotplug_event != NULL) {
-				hotplug_event_enqueue (hotplug_event);
-				hotplug_event_process_queue ();
-			}
-		}
-	}
-
-out:
-	;
-}
-
-gboolean
-blockdev_rescan_device (HalDevice *d)
-{
-	gboolean ret;
-
-	ret = FALSE;
-
-	HAL_INFO (("Entering, udi=%s", d->udi));
-
-	/* This only makes sense on storage devices */
-	if (hal_device_property_get_bool (d, "block.is_volume")) {
-		HAL_INFO (("No action on volumes", d->udi));
-		goto out;
-	}
-
-	/* now see if we got a file system on the main block device */
-	hald_runner_run (d,
-	                 "hald-probe-storage --only-check-for-media", NULL, 
-	                 HAL_HELPER_TIMEOUT,
-	                 block_rescan_storage_done,
-	                 NULL, NULL);
-	ret = TRUE;
-
-out:
-	return ret;
-}
-
-
-HotplugEvent *
-blockdev_generate_add_hotplug_event (HalDevice *d)
-{
-	const char *sysfs_path;
-	const char *device_file;
-	const char *model;
-	const char *vendor;
-	const char *serial;
-	const char *revision;
-	HotplugEvent *hotplug_event;
-	const char *nul;
-
-	nul = "\0";
-
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	device_file = hal_device_property_get_string (d, "block.device");
-	model       = hal_device_property_get_string (d, "storage.model");
-	vendor      = hal_device_property_get_string (d, "storage.vendor");
-	serial      = hal_device_property_get_string (d, "storage.serial");
-	revision    = hal_device_property_get_string (d, "storage.firmware_revision");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-
-	g_strlcpy (hotplug_event->sysfs.device_file, device_file != NULL ? device_file : nul, HAL_NAME_MAX);
-	g_strlcpy (hotplug_event->sysfs.vendor,           vendor != NULL ?      vendor : nul, HAL_NAME_MAX);
-	g_strlcpy (hotplug_event->sysfs.model,             model != NULL ?       model : nul, HAL_NAME_MAX);
-	g_strlcpy (hotplug_event->sysfs.serial,           serial != NULL ?      serial : nul, HAL_NAME_MAX);
-	g_strlcpy (hotplug_event->sysfs.revision,       revision != NULL ?    revision : nul, HAL_NAME_MAX);
-
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
-
-HotplugEvent *
-blockdev_generate_remove_hotplug_event (HalDevice *d)
-{
-	const char *sysfs_path;
-	HotplugEvent *hotplug_event;
-
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, "block", sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
diff --git a/hald/linux2/blockdev.h b/hald/linux2/blockdev.h
deleted file mode 100644
index 9095d8c..0000000
--- a/hald/linux2/blockdev.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * blockdev.h : Handling of block devices 
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef BLOCKDEV_H
-#define BLOCKDEV_H
-
-#include <glib.h>
-
-void hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const char *device_file, gboolean is_partition, HalDevice *parent, void *end_token);
-
-void hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, void *end_token);
-
-gboolean blockdev_rescan_device (HalDevice *d);
-
-HotplugEvent *blockdev_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *blockdev_generate_remove_hotplug_event (HalDevice *d);
-
-void blockdev_refresh_mount_state (HalDevice *d);
-
-#endif /* BLOCKDEV_H */
diff --git a/hald/linux2/classdev.c b/hald/linux2/classdev.c
deleted file mode 100644
index 3e3a667..0000000
--- a/hald/linux2/classdev.c
+++ /dev/null
@@ -1,1495 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * classdev.c : Handling of functional kernel devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005 Richard Hughes, <richard at hughsie.com>
- * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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 <ctype.h>
-#include <limits.h>
-#include <linux/types.h>
-#include <net/if_arp.h> /* for ARPHRD_... */
-#include <stdlib.h>
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../device_store.h"
-#include "../hald.h"
-#include "../hald_runner.h"
-#include "../logger.h"
-#include "../osspec.h"
-#include "../util.h"
-
-#include "coldplug.h"
-#include "hotplug_helper.h"
-#include "osspec_linux.h"
-
-#include "classdev.h"
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	if (physdev != NULL) {
-		hal_device_property_set_string (d, "input.physical_device", physdev->udi);
-		hal_device_property_set_string (d, "info.parent", physdev->udi);
-	} else {
-		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
-	}
-	hal_device_property_set_string (d, "info.category", "input");
-	hal_device_add_capability (d, "input");
-
-	hal_device_property_set_string (d, "input.device", device_file);
-
-	return d;
-}
-
-static const gchar *
-input_get_prober (HalDevice *d)
-{
-	return "hald-probe-input";
-}
-
-static gboolean
-input_post_probing (HalDevice *d)
-{
-	return TRUE;
-}
-
-static gboolean
-input_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_logicaldev_input",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-bluetooth_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, 
-	       const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = NULL;
-
-	if (physdev == NULL) {
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-	hal_device_property_set_string (d, "info.category", "bluetooth_hci");
-	hal_device_add_capability (d, "bluetooth_hci");
-
-	hal_device_property_set_string (d, "bluetooth_hci.physical_device", physdev->udi);
-	hal_util_set_string_from_file (d, "bluetooth_hci.interface_name", sysfs_path, "name");
-
-	hal_device_property_set_string (d, "info.product", "Bluetooth Host Controller Interface");
-
-out:
-	return d;
-}
-
-static gboolean
-bluetooth_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_bluetooth_hci",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-net_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	const gchar *ifname;
-	guint media_type;
-	gint flags;
-
-	d = NULL;
-
-	if (physdev == NULL)
-		goto error;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-	hal_device_property_set_string (d, "info.category", "net");
-	hal_device_add_capability (d, "net");
-
-	hal_device_property_set_string (d, "net.physical_device", physdev->udi);
-
-	ifname = hal_util_get_last_element (sysfs_path);
-	hal_device_property_set_string (d, "net.interface", ifname);
-
-	if (!hal_util_set_string_from_file (d, "net.address", sysfs_path, "address")) {
-		hal_device_property_set_string (d, "net.address", "00:00:00:00:00:00");	
-	}
-
-	if (!hal_util_set_int_from_file (d, "net.linux.ifindex", sysfs_path, "ifindex", 10))
-		goto error;
-
-	if (!hal_util_set_int_from_file (d, "net.arp_proto_hw_id", sysfs_path, "type", 10))
-		goto error;
-
-	if (!hal_util_get_int_from_file (sysfs_path, "flags", &flags, 16))
-		goto error;
-
-	media_type = hal_device_property_get_int (d, "net.arp_proto_hw_id");
-	if (media_type == ARPHRD_ETHER) {
-		FILE *f;
-		gboolean is_wireless;
-		const char *addr;
-
-		is_wireless = FALSE;
-
-		f = fopen ("/proc/net/wireless", "ro");
-		if (f != NULL) {
-			unsigned int i;
-			unsigned int ifname_len;
-			char buf[128];
-
-			ifname_len = strlen (ifname);
-
-			do {
-				if (fgets (buf, sizeof (buf), f) == NULL)
-					break;
-
-				for (i=0; i < sizeof (buf); i++) {
-					if (isspace (buf[i]))
-						continue;
-					else
-						break;
-				}
-
-				if (strncmp (ifname, buf + i, ifname_len) == 0) {
-					is_wireless = TRUE;
-					break;
-				}
-
-			} while (TRUE);
-			fclose (f);
-		}
-
-		if (is_wireless) {
-		/* Check to see if this interface supports wireless extensions */
-		/*
-		snprintf (wireless_path, SYSFS_PATH_MAX, "%s/wireless", sysfs_path);
-		if (stat (wireless_path, &statbuf) == 0) {
-		*/
-			hal_device_property_set_string (d, "info.product", "WLAN Interface");
-			hal_device_property_set_string (d, "info.category", "net.80211");
-			hal_device_add_capability (d, "net.80211");
-		} else {
-			hal_device_property_set_string (d, "info.product", "Networking Interface");
-			hal_device_property_set_string (d, "info.category", "net.80203");
-			hal_device_add_capability (d, "net.80203");
-		}
-
-		addr = hal_device_property_get_string (d, "net.address");
-		if (addr != NULL) {
-			unsigned int a5, a4, a3, a2, a1, a0;
-			
-			if (sscanf (addr, "%x:%x:%x:%x:%x:%x",
-				    &a5, &a4, &a3, &a2, &a1, &a0) == 6) {
-				dbus_uint64_t mac_address;
-				
-				mac_address = 
-					((dbus_uint64_t)a5<<40) |
-					((dbus_uint64_t)a4<<32) | 
-					((dbus_uint64_t)a3<<24) | 
-					((dbus_uint64_t)a2<<16) | 
-					((dbus_uint64_t)a1<< 8) | 
-					((dbus_uint64_t)a0<< 0);
-				
-				hal_device_property_set_uint64 (d, is_wireless ? "net.80211.mac_address" : 
-								"net.80203.mac_address",
-								mac_address);
-			}
-		}
-	}
-
-	return d;
-error:
-	if (d != NULL) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		d = NULL;
-	}
-
-	return d;
-}
-
-static gboolean
-net_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-	const gchar *id;
-
-	id = hal_device_property_get_string (d, "net.address");
-	if (id == NULL || (strcmp (id, "00:00:00:00:00:00") == 0)) {
-		/* Need to fall back to something else if mac not available. */
-		id = hal_util_get_last_element(hal_device_property_get_string(d, "net.physical_device"));
-	}
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/net_%s",
-			      id);
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-scsi_generic_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL)
-		goto out;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "scsi_generic");
-	hal_device_add_capability (d, "scsi_generic");
-	hal_device_property_set_string (d, "info.product", "SCSI Generic Interface");
-	hal_device_property_set_string (d, "scsi_generic.device", device_file);
-
-out:
-	return d;
-}
-
-static gboolean
-scsi_generic_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_scsi_generic",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-scsi_host_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	gint host_num;
-	const gchar *last_elem;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL) {
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
-	
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-	hal_device_property_set_string (d, "info.category", "scsi_host");
-	hal_device_add_capability (d, "scsi_host");
-
-	hal_device_property_set_string (d, "info.product", "SCSI Host Adapter");
-
-	last_elem = hal_util_get_last_element (sysfs_path);
-	sscanf (last_elem, "host%d", &host_num);
-	hal_device_property_set_int (d, "scsi_host.host", host_num);
-
-out:
-	return d;
-}
-
-static gboolean
-scsi_host_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_scsi_host",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-usbclass_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	gint host_num;
-	const gchar *last_elem;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL || device_file == NULL) {
-		goto out;
-	}
-
-	last_elem = hal_util_get_last_element (sysfs_path);
-	if (sscanf (last_elem, "hiddev%d", &host_num) == 1) {
-
-		d = hal_device_new ();
-		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-		hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
-		hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-		hal_device_property_set_string (d, "info.category", "hiddev");
-		hal_device_add_capability (d, "hiddev");
-
-		hal_device_property_set_string (d, "info.product", "USB HID Device");
-
-		hal_device_property_set_string (d, "hiddev.device", device_file);
-	} else if (sscanf (last_elem, "lp%d", &host_num) == 1) {
-
-		d = hal_device_new ();
-		hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-		hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
-		hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-		hal_device_property_set_string (d, "info.category", "printer");
-		hal_device_add_capability (d, "printer");
-
-		hal_device_property_set_string (d, "info.product", "Printer");
-		hal_device_property_set_string (d, "printer.device", device_file);
-
-		hal_device_property_set_string (d, "printer.physical_device", physdev->udi);
-	}
-
-out:
-	return d;
-}
-
-static const gchar *
-usbclass_get_prober (HalDevice *d)
-{
-	if (hal_device_has_capability (d, "hiddev"))
-		return "hald-probe-hiddev";
-	else if (hal_device_has_capability (d, "printer"))
-		return "hald-probe-printer";
-	else
-		return NULL;
-}
-
-static gboolean
-usbclass_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	if (hal_device_has_capability (d, "hiddev")) {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_hiddev",
-				      hal_device_property_get_string (d, "info.parent"));
-		hal_device_set_udi (d, udi);
-		hal_device_property_set_string (d, "info.udi", udi);
-	} else if (hal_device_has_capability (d, "printer")) {
-		const char *serial;
-
-		serial = hal_device_property_get_string (d, "printer.serial");
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_printer_%s",
-				      hal_device_property_get_string (d, "info.parent"),
-				      serial != NULL ? serial : "noserial");
-		hal_device_set_udi (d, udi);
-		hal_device_property_set_string (d, "info.udi", udi);
-	}
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-usbraw_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL)
-		goto out;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "usbraw");
-	hal_device_add_capability (d, "usbraw");
-	hal_device_property_set_string (d, "info.product", "USB Raw Device Access");
-	hal_device_property_set_string (d, "usbraw.device", device_file);
-
-out:
-	return d;
-}
-
-static gboolean
-usbraw_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_usbraw",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-video4linux_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL)
-		goto out;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "video4linux");
-	hal_device_add_capability (d, "video4linux");
-	hal_device_property_set_string (d, "info.product", "Video Device");
-	hal_device_property_set_string (d, "video4linux.device", device_file);
-
-out:
-	return d;
-}
-
-static gboolean
-video4linux_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_video4linux",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-dvb_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL)
-		goto out;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "dvb");
-	hal_device_add_capability (d, "dvb");
-	hal_device_property_set_string (d, "info.product", "DVB Device");
-	hal_device_property_set_string (d, "dvb.device", device_file);
-
-out:
-	return d;
-}
-
-static gboolean
-dvb_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_dvb",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-sound_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	int cardnum, devicenum;
-	char type;
-	const gchar *device;
-	gchar *device_id;
-	char aprocdir[256];
-	char buf[256];
-
-	d = NULL;
-
-	if (device_file == NULL) 
-		goto out;	
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	device = hal_util_get_last_element(sysfs_path);
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL) {
- 		/* handle global ALSA and OSS devices, these devices are for all ALSA/OSS Sound devices
-		   so we append them to /org/freedesktop/Hal/devices/computer */
-		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
-
-		if (!strncmp (device, "timer", 5)){
-			/* handle global ALSA Timer device */
-			hal_device_property_set_string (d, "info.category", "alsa");
-			hal_device_add_capability (d, "alsa");
-			hal_device_property_set_string (d, "alsa.type", "timer");
-			hal_device_property_set_string (d, "info.product", "ALSA Timer Device");
-			hal_device_property_set_string (d, "alsa.device_file", device_file);
-		} else if (!strncmp (device, "sequencer", 9)){
-			/* handle global OSS sequencer devices */
-			hal_device_property_set_string (d, "info.category", "oss");
-			hal_device_add_capability (d, "oss");
-			hal_device_property_set_string (d, "oss.type", "sequencer");
-			hal_device_property_set_string (d, "info.product", "OSS Sequencer Device");
-			hal_device_property_set_string (d, "oss.device_file", device_file);
-		} else if (!strncmp (device, "seq", 3) && strlen(device) == 3) { 
-			/* handle global ALSA sequencer devices */
-			hal_device_property_set_string (d, "info.category", "alsa");
-			hal_device_add_capability (d, "alsa");
-			hal_device_property_set_string (d, "alsa.type", "sequencer");
-			hal_device_property_set_string (d, "info.product", "ALSA Sequencer Device");
-			hal_device_property_set_string (d, "alsa.device_file", device_file);	
-		} else {
-			goto error;
-		}
-	} else {
-		/* handle ALSA and OSS devices with physdev link in sys */
-		if (sscanf (device, "controlC%d", &cardnum) == 1) {
-			
-			hal_device_property_set_string (d, "info.category", "alsa");
-			hal_device_add_capability (d, "alsa");
-			hal_device_property_set_string (d, "alsa.device_file", device_file);
-			hal_device_property_set_string (d, "info.parent", physdev->udi);
-			hal_device_property_set_string (d, "alsa.physical_device", physdev->udi);
-			hal_device_property_set_int (d, "alsa.card", cardnum);
-			hal_device_property_set_string (d, "alsa.type", "control");
-	
-			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
-			hal_util_set_string_from_file (d, "alsa.card_id", aprocdir, "id");
-	
-			snprintf (buf, sizeof (buf), "%s ALSA Control Device", 
-				hal_device_property_get_string (d, "alsa.card_id"));
-			hal_device_property_set_string (d, "info.product", buf);
-	
-		} else if (sscanf (device, "pcmC%dD%d%c", &cardnum, &devicenum, &type) == 3) {
-			
-			hal_device_property_set_string (d, "info.category", "alsa");
-			hal_device_add_capability (d, "alsa");
-			hal_device_property_set_string (d, "alsa.device_file", device_file);
-			hal_device_property_set_string (d, "info.parent", physdev->udi);
-			hal_device_property_set_string (d, "alsa.physical_device", physdev->udi);
-			hal_device_property_set_int (d, "alsa.card", cardnum);
-			hal_device_property_set_int (d, "alsa.device", devicenum);
-	
-			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
-			hal_util_set_string_from_file (d, "alsa.card_id", aprocdir, "id");
-	
-			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm%d%c", 
-				get_hal_proc_path (), cardnum, devicenum, type);
-			device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
-			if (device_id != NULL) {
-				hal_device_property_set_string (d, "alsa.device_id", device_id);
-			}
-	
-			if (type == 'p') {
-				hal_device_property_set_string (d, "alsa.type", "playback");
-				if (device_id != NULL) {
-					snprintf (buf, sizeof (buf), "%s ALSA Playback Device", device_id);
-					hal_device_property_set_string (d, "info.product", buf);
-				} else
-					hal_device_property_set_string (d, "info.product", "ALSA Playback Device");
-			} else if (type == 'c') {
-				hal_device_property_set_string (d, "alsa.type", "capture");
-				if (device_id != NULL) {
-					snprintf (buf, sizeof (buf), "%s ALSA Capture Device", device_id);
-					hal_device_property_set_string (d, "info.product", buf);
-				} else
-					hal_device_property_set_string (d, "info.product", "ALSA Capture Device");
-			} else {
-				hal_device_property_set_string (d, "alsa.type", "unknown");
-				if (device_id != NULL) {
-					snprintf (buf, sizeof (buf), "%s ALSA Device", device_id);
-					hal_device_property_set_string (d, "info.product", buf);
-				} else
-					hal_device_property_set_string (d, "info.product", "ALSA Device");
-			}
-		} else if (!strncmp (device, "dsp", 3) || !strncmp (device, "adsp", 4) || 
-			   !strncmp (device, "midi", 4) || !strncmp (device, "amidi", 5) ||
-			   !strncmp (device, "audio", 5) || !strncmp (device, "mixer", 5)) {
-			
-			/* handle OSS-Devices */
-			ClassDevOSSDeviceTypes type;
-	
-			if (!strncmp (device, "dsp", 3)) {
-				if(sscanf (device, "dsp%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_DSP;
-			} else if (!strncmp (device, "adsp", 4)) {
-				if(sscanf (device, "adsp%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_ADSP;
-			} else if (!strncmp (device, "midi", 4)) {
-				if(sscanf (device, "midi%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_MIDI;
-			} else if (!strncmp (device, "amidi", 5)) {
-				if(sscanf (device, "amidi%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_AMIDI;
-			} else if (!strncmp (device, "audio", 5)) {
-				if(sscanf (device, "audio%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_AUDIO;
-			} else if (!strncmp (device, "mixer", 5)) {
-				if(sscanf (device, "mixer%d", &cardnum) != 1) cardnum = 0;
-				type = OSS_DEVICE_TYPE_MIXER;
-			} else {
-				cardnum = 0;
-				type = OSS_DEVICE_TYPE_UNKNOWN;
-			}
-
-			hal_device_property_set_string (d, "info.category", "oss");
-			hal_device_add_capability (d, "oss");
-			hal_device_property_set_string (d, "oss.device_file", device_file);
-			hal_device_property_set_string (d, "info.parent", physdev->udi);
-			hal_device_property_set_string (d, "oss.physical_device", physdev->udi);
-			hal_device_property_set_int (d, "oss.card", cardnum);
-	
-			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d", get_hal_proc_path (), cardnum);
-			hal_util_set_string_from_file (d, "oss.card_id", aprocdir, "id");
-	
-			snprintf (aprocdir, sizeof (aprocdir), "%s/asound/card%d/pcm0p", 
-				get_hal_proc_path (), cardnum);
-			device_id = hal_util_grep_file (aprocdir, "info", "name: ", FALSE);
-			if (device_id != NULL) {
-				hal_device_property_set_string (d, "oss.device_id", device_id);
-			} 
-
-			switch (type) { 
-				case OSS_DEVICE_TYPE_MIXER:
-					hal_device_property_set_string (d, "oss.type", "mixer");
-					if (device_id != NULL) 
-						snprintf (buf, sizeof (buf), "%s OSS Control Device", device_id); 
-					else
-						snprintf (buf, sizeof (buf), "%s OSS Control Device",
-						          hal_device_property_get_string (d, "oss.card_id"));
-					break;
-				case OSS_DEVICE_TYPE_DSP:
-				case OSS_DEVICE_TYPE_AUDIO:
-				case OSS_DEVICE_TYPE_ADSP:
-					if (type == OSS_DEVICE_TYPE_ADSP)
-						hal_device_property_set_int (d, "oss.device", 1);
-					else 
-						hal_device_property_set_int (d, "oss.device", 0);
-
-					hal_device_property_set_string (d, "oss.type", "pcm");
-					if (device_id != NULL) 
-						snprintf (buf, sizeof (buf), "%s OSS PCM Device", device_id); 
-					else
-						snprintf (buf, sizeof (buf), "%s OSS PCM Device",
-						          hal_device_property_get_string (d, "oss.card_id"));
-					break;
-				case OSS_DEVICE_TYPE_MIDI:
-				case OSS_DEVICE_TYPE_AMIDI:
-					if (type == OSS_DEVICE_TYPE_AMIDI)
-						hal_device_property_set_int (d, "oss.device", 1);
-					else
-						hal_device_property_set_int (d, "oss.device", 0);
-					hal_device_property_set_string (d, "oss.type", "midi");
-					if (device_id != NULL) 
-						snprintf (buf, sizeof (buf), "%s OSS MIDI Device", device_id); 
-					else
-						snprintf (buf, sizeof (buf), "%s OSS MIDI Device",
-						          hal_device_property_get_string (d, "oss.card_id"));
-					break;
-				case OSS_DEVICE_TYPE_UNKNOWN:
-				default:
-					hal_device_property_set_string (d, "oss.type", "unknown");
-					if (device_id != NULL) 
-						snprintf (buf, sizeof (buf), "%s OSS Device", device_id); 
-					else
-						snprintf (buf, sizeof (buf), "%s OSS Device",
-						          hal_device_property_get_string (d, "oss.card_id"));
-					break;
-			}
-			hal_device_property_set_string (d, "info.product", buf);
-		}
-		else {
-			goto error;
-		}
-	}
-out:
-	return d;
-
-error: 
-	g_object_unref (d);
-	d = NULL;
-	return d;
-}
-
-static gboolean
-sound_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	if (hal_device_has_property(d, "alsa.card")) {
-		/* don't include card number as it may not be persistent across reboots */
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_alsa_%s_%i",
-				      hal_device_property_get_string (d, "info.parent"),
-				      hal_device_property_get_string (d, "alsa.type"),
-				      hal_device_property_get_int (d, "alsa.device"));
-	} else if (hal_device_has_property(d, "oss.card")) {
-		/* don't include card number as it may not be persistent across reboots */
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_oss_%s_%i",
-				      hal_device_property_get_string (d, "info.parent"),
-				      hal_device_property_get_string (d, "oss.type"),
-				      hal_device_property_get_int (d, "oss.device"));
-	} else if (hal_device_has_property(d, "alsa.type")) {
-		/* handle global ALAS devices */
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_alsa_%s",
-				      hal_device_property_get_string (d, "info.parent"),
-				      hal_device_property_get_string (d, "alsa.type"));
-	} else if (hal_device_has_property(d, "oss.type")) {
-		/* handle global OSS devices */
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_oss_%s",
-				      hal_device_property_get_string (d, "info.parent"),
-				      hal_device_property_get_string (d, "oss.type"));
-	} else {
-		/* fallback */
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi), "%s_sound_unknown",
-				      hal_device_property_get_string (d, "info.parent"));
-	} 
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-serial_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	int portnum;
-	HalDevice *d;
-	const gchar *last_elem;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL || device_file == NULL) {
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "serial");
-	hal_device_add_capability (d, "serial");
-	hal_device_property_set_string (d, "serial.physical_device", physdev->udi);
-	hal_device_property_set_string (d, "serial.device", device_file);
-
-	last_elem = hal_util_get_last_element(sysfs_path);
-	if (sscanf (last_elem, "ttyS%d", &portnum) == 1) {
-		hal_device_property_set_int (d, "serial.port", portnum);
-		hal_device_property_set_string (d, "serial.type", "platform");
-		hal_device_property_set_string (d, "info.product",
-						hal_device_property_get_string (physdev, "info.product"));
-	} else if (sscanf (last_elem, "ttyUSB%d", &portnum) == 1) {
-		HalDevice *usbdev;
-
-		hal_device_property_set_int (d, "serial.port", portnum);
-		hal_device_property_set_string (d, "serial.type", "usb");
-
-		usbdev = hal_device_store_find (hald_get_gdl (), 
-						hal_device_property_get_string (physdev, "info.parent"));
-		if (usbdev != NULL) {
-			hal_device_property_set_string (d, "info.product",
-							hal_device_property_get_string (usbdev, "info.product"));
-		} else {
-			hal_device_property_set_string (d, "info.product", "USB Serial Port");
-		}
-	} else {
-		int len;
-		int i;
-
-		len = strlen (last_elem);
-
-		for (i = len - 1; i >= 0 && isdigit (last_elem[i]); --i)
-			;
-		if (i == len - 1)
-			portnum = 0;
-		else
-			portnum = atoi (last_elem + i + 1);
-
-		hal_device_property_set_int (d, "serial.port", portnum);
-		hal_device_property_set_string (d, "serial.type", "unknown");
-		hal_device_property_set_string (d, "info.product", "Serial Port");
-	}
-
-out:
-	return d;
-}
-
-static const gchar *
-serial_get_prober (HalDevice *d)
-{
-	/* FIXME TODO: check if there is an other way, to call the porber only
-		 on ttyS* devices, than check the name of the device file */
-	if (!strncmp(hal_device_property_get_string (d, "linux.device_file"), "/dev/ttyS", 9))
-		return "hald-probe-serial";
-	else 
-		return NULL;
-}
-
-static gboolean
-serial_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_serial_%s_%d",
-			      hal_device_property_get_string (d, "info.parent"),
-			      hal_device_property_get_string (d, "serial.type"),
-			      hal_device_property_get_int (d, "serial.port"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-tape_add (const gchar *sysfs_path, const gchar *device_file, 
-	  HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	const gchar *dev_entry;
-
-	if (physdev == NULL)
-		return NULL;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-	hal_device_property_set_string (d, "info.category", "tape");
-	hal_device_add_capability (d, "tape");
-	hal_device_add_capability (physdev, "tape");
-
-	dev_entry = hal_util_get_string_from_file (sysfs_path, "dev");
-	if (dev_entry != NULL) {
-		unsigned int major, minor;
-
-		if (sscanf (dev_entry, "%d:%d", &major, &minor) != 2) {
-			hal_device_property_set_int (d, "tape.major", major);
-			hal_device_property_set_int (d, "tape.minor", minor);
-		}
-	}
-	return d;
-}
-
-static gboolean
-tape_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-	const gchar *sysfs_name;
-
-	sysfs_name = hal_util_get_last_element (hal_device_property_get_string
-						(d, "linux.sysfs_path"));
-	if (!sysfs_name)
-		return FALSE;
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/tape_%s",
-			      sysfs_name);
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-mmc_host_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices)
-{
-	HalDevice *d;
-	gint host_num;
-	const gchar *last_elem;
-
-	d = NULL;
-
-	if (physdev == NULL || sysfs_path_in_devices == NULL) {
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path_in_devices);
-
-	hal_device_property_set_string (d, "info.parent", physdev->udi);
-
-	hal_device_property_set_string (d, "info.category", "mmc_host");
-	hal_device_add_capability (d, "mmc_host");
-
-	hal_device_property_set_string (d, "info.product", "MMC/SD Host Adapter");
-
-	last_elem = hal_util_get_last_element (sysfs_path);
-	sscanf (last_elem, "mmc%d", &host_num);
-	hal_device_property_set_int (d, "mmc_host.host", host_num);
-
-out:
-	return d;
-}
-
-static gboolean
-mmc_host_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_mmc_host",
-			      hal_device_property_get_string (d, "info.parent"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static gboolean
-classdev_remove (HalDevice *d)
-{
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-struct ClassDevHandler_s;
-typedef struct ClassDevHandler_s ClassDevHandler;
-
-struct ClassDevHandler_s
-{
-	const gchar *subsystem;
-	HalDevice *(*add) (const gchar *sysfs_path, const gchar *device_file, HalDevice *parent, const gchar *sysfs_path_in_devices);
-	const gchar *(*get_prober)(HalDevice *d);
-	gboolean (*post_probing) (HalDevice *d);
-	gboolean (*compute_udi) (HalDevice *d);
-	gboolean (*remove) (HalDevice *d);
-}; 
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static ClassDevHandler classdev_handler_input = 
-{ 
-	.subsystem    = "input",
-	.add          = input_add,
-	.get_prober   = input_get_prober,
-	.post_probing = input_post_probing,
-	.compute_udi  = input_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_bluetooth = 
-{ 
-	.subsystem    = "bluetooth",
-	.add          = bluetooth_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = bluetooth_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_net = 
-{ 
-	.subsystem    = "net",
-	.add          = net_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = net_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_scsi_generic =
-{ 
-	.subsystem    = "scsi_generic",
-	.add          = scsi_generic_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = scsi_generic_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_scsi_host = 
-{ 
-	.subsystem    = "scsi_host",
-	.add          = scsi_host_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = scsi_host_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_usbclass = 
-{ 
-	.subsystem    = "usb",
-	.add          = usbclass_add,
-	.get_prober   = usbclass_get_prober,
-	.post_probing = NULL,
-	.compute_udi  = usbclass_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_usbraw =
-{ 
-	.subsystem    = "usb_device",
-	.add          = usbraw_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = usbraw_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_video4linux =
-{ 
-	.subsystem    = "video4linux",
-	.add          = video4linux_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = video4linux_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_dvb =
-{ 
-	.subsystem    = "dvb",
-	.add          = dvb_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = dvb_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_sound = 
-{ 
-	.subsystem    = "sound",
-	.add          = sound_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = sound_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_serial = 
-{ 
-	.subsystem    = "tty",
-	.add          = serial_add,
-	.get_prober   = serial_get_prober,
-	.post_probing = NULL,
-	.compute_udi  = serial_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_tape =
-{
-	.subsystem    = "tape",
-	.add          = tape_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = tape_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_tape390 =
-{
-	.subsystem    = "tape390",
-	.add          = tape_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = tape_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler classdev_handler_mmc_host =
-{
-	.subsystem    = "mmc_host",
-	.add          = mmc_host_add,
-	.get_prober   = NULL,
-	.post_probing = NULL,
-	.compute_udi  = mmc_host_compute_udi,
-	.remove       = classdev_remove
-};
-
-static ClassDevHandler *classdev_handlers[] = {
-	&classdev_handler_input,
-	&classdev_handler_bluetooth,
-	&classdev_handler_net,
-	&classdev_handler_scsi_generic,
-	&classdev_handler_scsi_host,
-	&classdev_handler_usbclass,
-	&classdev_handler_usbraw,
-	&classdev_handler_video4linux,
-	&classdev_handler_dvb,
-	&classdev_handler_sound,
-	&classdev_handler_serial,
-	&classdev_handler_tape,
-	&classdev_handler_tape390,
-	&classdev_handler_mmc_host,
-	NULL
-};
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static void 
-classdev_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 
-classdev_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"));
-	}
-
-	g_object_unref (d);
-
-	hotplug_event_end (end_token);
-}
-
-static void 
-add_classdev_after_probing (HalDevice *d, ClassDevHandler *handler, void *end_token)
-{
-	/* 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)) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		hotplug_event_end (end_token);
-		goto out;
-	}
-	
-	/* TODO: Merge persistent properties */
-
-	/* Run callouts */
-	hal_util_callout_device_add (d, classdev_callouts_add_done, end_token, NULL);
-
-out:
-	;
-}
-
-static void 
-add_classdev_probing_helper_done (HalDevice *d, guint32 exit_type, 
-                                  gint return_code, char **error,
-                                  gpointer data1, gpointer data2) 
-{
-	void *end_token = (void *) data1;
-	ClassDevHandler *handler = (ClassDevHandler *) data2;
-
-	HAL_INFO (("entering; exit_type=%d, return_code=%d", exit_type, return_code));
-
-	if (d == NULL) {
-		HAL_INFO (("Device object already removed"));
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	/* Discard device if probing reports failure */
-	if (exit_type != HALD_RUN_SUCCESS || return_code != 0) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	/* Do things post probing */
-	if (handler->post_probing != NULL) {
-		if (!handler->post_probing (d)) {
-			hotplug_event_end (end_token);
-			goto out;
-		}
-	}
-
-	add_classdev_after_probing (d, handler, end_token);
-
-out:
-	;
-}
-
-static void 
-classdev_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
-{
-	void *end_token = (void *) userdata1;
-	ClassDevHandler *handler = (ClassDevHandler *) userdata2;
-	const gchar *prober;
-
-	if (hal_device_property_get_bool (d, "info.ignore")) {
-		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
-		 * Also remove category and all capabilities
-		 */
-		hal_device_property_remove (d, "info.category");
-		hal_device_property_remove (d, "info.capabilities");
-		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
-		hal_device_property_set_string (d, "info.product", "Ignored Device");
-
-		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-		
-		/* 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);
-		goto out;
-	}
-	
-	if (handler->get_prober != NULL)
-		prober = handler->get_prober (d);
-	else
-		prober = NULL;
-	if (prober != NULL) {
-		/* probe the device */
-		hald_runner_run(d, 
-		                    prober, NULL, 
-		                    HAL_HELPER_TIMEOUT, 
-		                    add_classdev_probing_helper_done,
-		                    (gpointer) end_token, (gpointer) handler);
-	} else {
-		add_classdev_after_probing (d, handler, end_token);
-	}
-out:
-  ;
-}
-
-void
-hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, 
-				  HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token)
-{
-	guint i;
-
-	HAL_INFO (("class_add: subsys=%s sysfs_path=%s dev=%s physdev=0x%08x", subsystem, sysfs_path, device_file, physdev));
-
-	/* update driver property of the physical device, cause manual driver bind/unbind
-	 * may change change this without sending events for the bus device
-	 */
-	if (physdev != NULL)
-		hal_util_set_driver (physdev, "info.linux.driver", sysfs_path_in_devices);
-
-	if (physdev != NULL && hal_device_property_get_bool (physdev, "info.ignore")) {
-		HAL_INFO (("Ignoring class_add since physdev has info.ignore==TRUE"));
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	for (i = 0; classdev_handlers [i] != NULL; i++) {
-		ClassDevHandler *handler;
-
-		handler = classdev_handlers[i];
-		if (strcmp (handler->subsystem, subsystem) == 0) {
-			HalDevice *d;
-
-			/* attempt to add the device */
-			d = handler->add (sysfs_path, device_file, physdev, sysfs_path_in_devices);
-			if (d == NULL) {
-				/* didn't find anything - thus, ignore this hotplug event */
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_CLASS);
-			hal_device_property_set_string (d, "linux.subsystem", subsystem);
-			
-			if (device_file != NULL && strlen (device_file) > 0)
-				hal_device_property_set_string (d, "linux.device_file", device_file);
-
-			/* Add to temporary device store */
-			hal_device_store_add (hald_get_tdl (), d);
-
-			/* Process preprobe fdi files */
-			di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
-
-			/* Run preprobe callouts */
-			hal_util_callout_device_preprobe (d, classdev_callouts_preprobing_done, end_token, handler);
-			goto out;
-		}
-	}
-
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out:
-	;
-}
-
-void
-hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token)
-{
-	guint i;
-	HalDevice *d;
-
-
-	HAL_INFO (("class_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.sysfs_path", sysfs_path);
-	if (d == NULL) {
-		HAL_WARNING (("Error removing device"));
-	} else {
-
-		for (i = 0; classdev_handlers [i] != NULL; i++) {
-			ClassDevHandler *handler;
-			
-			handler = classdev_handlers[i];
-			if (strcmp (handler->subsystem, subsystem) == 0) {
-				handler->remove (d);
-
-				hal_util_callout_device_remove (d, classdev_callouts_remove_done, end_token, NULL);
-				goto out;
-			}
-		}
-	}
-
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out:
-	;
-}
-
-gboolean
-classdev_rescan_device (HalDevice *d)
-{
-	return FALSE;
-}
-
-
-HotplugEvent *
-classdev_generate_add_hotplug_event (HalDevice *d)
-{
-	const char *subsystem;
-	const char *sysfs_path;
-	const char *device_file;
-	HotplugEvent *hotplug_event;
-
-	subsystem = hal_device_property_get_string (d, "linux.subsystem");
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-	device_file = hal_device_property_get_string (d, "linux.device_file");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	if (device_file != NULL)
-		g_strlcpy (hotplug_event->sysfs.device_file, device_file, sizeof (hotplug_event->sysfs.device_file));
-	else
-		hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
-
-HotplugEvent *
-classdev_generate_remove_hotplug_event (HalDevice *d)
-{
-	const char *subsystem;
-	const char *sysfs_path;
-	HotplugEvent *hotplug_event;
-
-	subsystem = hal_device_property_get_string (d, "linux.subsystem");
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
diff --git a/hald/linux2/classdev.h b/hald/linux2/classdev.h
deleted file mode 100644
index c88dc9b..0000000
--- a/hald/linux2/classdev.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * classdev.h : Handling of functional kernel devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef CLASSDEV_H
-#define CLASSDEV_H
-
-#include <glib.h>
-#include "hotplug.h"
-
-typedef enum {
-	OSS_DEVICE_TYPE_DSP,
-	OSS_DEVICE_TYPE_ADSP,
-	OSS_DEVICE_TYPE_MIDI,
-	OSS_DEVICE_TYPE_AMIDI,
-	OSS_DEVICE_TYPE_AUDIO,
-	OSS_DEVICE_TYPE_MIXER,
-	OSS_DEVICE_TYPE_UNKNOWN
-} ClassDevOSSDeviceTypes;
-
-void hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, const gchar *sysfs_path_in_devices, void *end_token);
-
-void hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
-
-gboolean classdev_rescan_device (HalDevice *d);
-
-HotplugEvent *classdev_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *classdev_generate_remove_hotplug_event (HalDevice *d);
-
-#endif /* CLASSDEV_H */
diff --git a/hald/linux2/coldplug.c b/hald/linux2/coldplug.c
deleted file mode 100644
index e47a90f..0000000
--- a/hald/linux2/coldplug.c
+++ /dev/null
@@ -1,682 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * coldplug.c : Synthesize hotplug events when starting up
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <stdint.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../hald.h"
-#include "../logger.h"
-#include "../osspec.h"
-#include "../util.h"
-
-#include "osspec_linux.h"
-#include "hotplug.h"
-
-#include "coldplug.h"
-
-#define DMPREFIX "dm-"
-
-/* For debugging */
-#define HAL_COLDPLUG_VERBOSE
-
-static GHashTable *sysfs_to_udev_map;
-static char dev_root[HAL_PATH_MAX];
-
-/* Returns the path of the udevinfo program 
- *
- * @return                      Path or NULL if udevinfo program is not found
- */
-static const gchar *
-hal_util_get_udevinfo_path (void)
-{
-	guint i;
-	struct stat s;
-	static gchar *path = NULL;
-	gchar *possible_paths[] = {
-		"/usr/bin/udevinfo",
-		"/bin/udevinfo",
-		"/usr/sbin/udevinfo",
-		"/sbin/udevinfo",
-	};
-
-	if (path != NULL)
-		 return path;
-
-	for (i = 0; i < sizeof (possible_paths) / sizeof (char *); i++) {
-		if (stat (possible_paths[i], &s) == 0 && S_ISREG (s.st_mode)) {
-			path = possible_paths[i];
-			break;
-		}
-	}
-	return path;
-}
-
-static gboolean
-hal_util_init_sysfs_to_udev_map (void)
-{
-	char *udevdb_export_argv[] = { "/usr/bin/udevinfo", "-e", NULL };
-	char *udevroot_argv[] = { "/usr/bin/udevinfo", "-r", NULL };
-	char *udevinfo_stdout;
-	int udevinfo_exitcode;
-	HotplugEvent *hotplug_event = NULL;
-	char *p;
-
-	sysfs_to_udev_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	udevdb_export_argv[0] = (char *) hal_util_get_udevinfo_path ();
-	udevroot_argv[0] = (char *) hal_util_get_udevinfo_path ();
-
-	/* get udevroot */
-	if (g_spawn_sync ("/", udevroot_argv, NULL, 0, NULL, NULL,
-			  &udevinfo_stdout,
-			  NULL,
-			  &udevinfo_exitcode,
-			  NULL) != TRUE) {
-		HAL_ERROR (("Couldn't invoke %s", udevroot_argv[0]));
-		goto error;
-	}
-	if (udevinfo_exitcode != 0) {
-		HAL_ERROR (("%s returned %d", udevroot_argv[0], udevinfo_exitcode));
-		goto error;
-	}
-
-	g_strlcpy(dev_root, udevinfo_stdout, sizeof(dev_root));
-	p = strchr(dev_root, '\n');
-	if (p != NULL)
-		p[0] = '\0';
-	g_free(udevinfo_stdout);
-	HAL_INFO (("dev_root is %s", dev_root));
-
-	/* get udevdb export */
-	if (g_spawn_sync ("/", udevdb_export_argv, NULL, 0, NULL, NULL,
-			  &udevinfo_stdout,
-			  NULL,
-			  &udevinfo_exitcode,
-			  NULL) != TRUE) {
-		HAL_ERROR (("Couldn't invoke %s", udevdb_export_argv[0]));
-		g_free(udevinfo_stdout);
-		goto error;
-	}
-
-	if (udevinfo_exitcode != 0) {
-		HAL_ERROR (("%s returned %d", udevdb_export_argv[0], udevinfo_exitcode));
-		goto error;
-	}
-
-	/* read the export of the udev database */
-	p = udevinfo_stdout;
-	while (p[0] != '\0') {
-		char *line, *end;
-		gchar *str;
-
-		/* get line, terminate and move to next line */
-		line = p;
-		end = strchr(line, '\n');
-		if (end == NULL)
-			break;
-		end[0] = '\0';
-		p = &end[1];
-
-		/* insert device */
-		if (line[0] == '\0') {
-			if (hotplug_event != NULL) {
-				g_hash_table_insert (sysfs_to_udev_map, g_strdup (hotplug_event->sysfs.sysfs_path), hotplug_event);
-#ifdef HAL_COLDPLUG_VERBOSE
-				printf ("Got '%s' -> '%s'\n", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file);
-#endif
-				hotplug_event = NULL;
-			}
-			continue;
-		}
-
-		/* new device */
-		if (strncmp(line, "P: ", 3) == 0) {
-			hotplug_event = g_new0 (HotplugEvent, 1);
-			g_strlcpy (hotplug_event->sysfs.sysfs_path, get_hal_sysfs_path (), sizeof(hotplug_event->sysfs.sysfs_path));
-			g_strlcat (hotplug_event->sysfs.sysfs_path, &line[3], sizeof(hotplug_event->sysfs.sysfs_path));
-			continue;
-		}
-
-		/* only valid if we have an actual device */
-		if (hotplug_event == NULL)
-			continue;
-
-		if (strncmp(line, "N: ", 3) == 0) {
-			g_snprintf (hotplug_event->sysfs.device_file, sizeof(hotplug_event->sysfs.device_file),
-				    "%s/%s", dev_root, &line[3]);
-		} else if (strncmp(line, "E: ID_VENDOR=", 13) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[13]);
-			g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_MODEL=", 12) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[12]);
-			g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_REVISION=", 15) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[15]);
-			g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_SERIAL=", 13) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[13]);
-			g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_FS_USAGE=", 15) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[15]);
-			g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_FS_TYPE=", 14) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[14]);
-			g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_FS_VERSION=", 17) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[17]);
-			g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_FS_UUID=", 14) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[14]);
-			g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
-			g_free (str);
-		} else if (strncmp(line, "E: ID_FS_LABEL=", 15) == 0) {
-			str = hal_util_strdup_valid_utf8(&line[15]);
-			g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
-			g_free (str);
-		}
-	}
-
-	g_free(udevinfo_stdout);
-	return TRUE;
-
-error:
-	g_free(udevinfo_stdout);
-	g_hash_table_destroy (sysfs_to_udev_map);
-	return FALSE;
-}
-
-static HotplugEvent
-*coldplug_get_hotplug_event(const gchar *sysfs_path, const gchar *subsystem)
-{
-	HotplugEvent *hotplug_event, *hotplug_event_udev;
-	const char *pos;
-	gchar path[HAL_PATH_MAX];
-	struct stat statbuf;
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	if (hotplug_event == NULL)
-		return NULL;
-
-	/* lookup if udev has something stored in its database */
-	hotplug_event_udev = (HotplugEvent *) g_hash_table_lookup (sysfs_to_udev_map, sysfs_path);
-	if (hotplug_event_udev != NULL) {
-		memcpy(hotplug_event, hotplug_event_udev, sizeof(HotplugEvent));
-		HAL_INFO (("found in udevdb '%s' '%s'", hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.device_file));
-	} else {
-		/* device is not in udev database */
-		g_strlcpy(hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof(hotplug_event->sysfs.sysfs_path));
-
-		/* look if a device node is expected */
-		g_strlcpy(path, sysfs_path, sizeof(path));
-		g_strlcat(path, "/dev", sizeof(path));
-		if (stat (path, &statbuf) != 0)
-			goto no_node;
-
-		/* look if the node exists */
-		pos = strrchr(sysfs_path, '/');
-		if (pos == NULL)
-			goto no_node;
-		g_strlcpy(path, dev_root, sizeof(path));
-		g_strlcat(path, pos, sizeof(path));
-		if (stat (path, &statbuf) != 0)
-			goto no_node;
-		if (!S_ISBLK (statbuf.st_mode) && !S_ISCHR (statbuf.st_mode))
-			goto no_node;
-
-		HAL_INFO (("found device_file %s for sysfs_path %s", path, sysfs_path));
-		g_strlcpy(hotplug_event->sysfs.device_file, path, sizeof(hotplug_event->sysfs.device_file));
-	}
-
-no_node:
-	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	hotplug_event->sysfs.net_ifindex = -1;
-	return hotplug_event;
-}
-
-static gboolean
-coldplug_synthesize_block_event(const gchar *f);
-
-static void
-coldplug_compute_visit_device (const gchar *path, 
-			       GHashTable *sysfs_to_bus_map, 
-			       GHashTable *sysfs_to_class_in_devices_map);
-
-static void
-free_hash_sys_to_class_in_dev (gpointer key, gpointer value, gpointer user_data)
-{
-	GSList *i;
-	GSList *list = (GSList *) value;
-
-	for (i = list; i != NULL; i = g_slist_next (i))
-		g_free (i->data);
-	g_slist_free (list);
-}
-
-/** This function serves one major purpose : build an ordered list of
- *  pairs (sysfs path, subsystem) to process when starting up:
- *  coldplugging. The ordering is arranged such that all bus-devices
- *  are visited in the same order as performing a traversal through
- *  the tree; e.g. bus-device A is not processed before bus-device B
- *  if B is a parent of A connection-wise.
- *
- *  After all bus-devices are added to the list, then all block devices are
- *  processed in the order they appear.
- *
- *  Finally, all class devices are added to the list.
- *
- *  @return                     Ordered list of sysfs paths or NULL 
- *                              if there was an error
- */
-gboolean
-coldplug_synthesize_events (void)
-{
-	GDir *dir;
-	GError *err = NULL;
-	gchar path[HAL_PATH_MAX];
-	gchar path1[HAL_PATH_MAX];
-	gchar path2[HAL_PATH_MAX];
-	const gchar *f;
-	const gchar *f1;
-	const gchar *f2;
-	GSList *li;
-
-	/** Mapping from sysfs path to subsystem for bus devices. This is consulted
-	 *  when traversing /sys/devices
-	 *
-	 *  Example:
-	 *
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0/host7/7:0:0:0  -> scsi
-	 * /sys/devices/pci0000:00/0000:00:07.1/ide1/1.1                        -> ide
-	 * /sys/devices/pci0000:00/0000:00:07.1/ide1/1.0                        -> ide
-	 * /sys/devices/pci0000:00/0000:00:07.1/ide0/0.0                        -> ide
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0                -> usb
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1                        -> usb
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-0:1.0                    -> usb
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1                            -> usb
-	 * /sys/devices/pci0000:00/0000:00:04.1/0000:06:00.0                    -> pci
-	 * /sys/devices/pci0000:00/0000:00:01.0/0000:01:00.0                    -> pci
-	 * /sys/devices/pci0000:00/0000:00:08.0                                 -> pci
-	 * /sys/devices/platform/vesafb0                                        -> platform
-	 */
-	GHashTable *sysfs_to_bus_map = NULL;
-
-        /** Mapping from sysfs path in /sys/devices to the pairs (sysfs class path, classname)
-	 *  for class devices; note that more than one class device might map to a physical device
-	 *
-	 * Example:
-	 *
-	 * /sys/devices/pci0000:00/0000:00:07.2/usb1/1-1/1-1:1.0/host7  -> (/sys/class/scsi_host/host7, scsi_host)
-	 * /sys/devices/platform/i8042/serio0/serio2 -> (/sys/class/input/event2, input, /sys/class/input/mouse1, input)
-	 */
-	GHashTable *sysfs_to_class_in_devices_map = NULL;
-
-	/* Class devices without device links; string list; example
-	 *
-	 * (/sys/class/input/mice, mouse, /sys/class/mem/null, mem, ...)
-	 */
-	GSList *sysfs_other_class_dev = NULL;
-
-	/* Device mapper devices that should be added after all other block devices
-	 *
-	 * Example:
-	 *
-	 * (/sys/block/dm-0)
-	 */
-	GSList *sysfs_dm_dev = NULL;
-
-	if (hal_util_init_sysfs_to_udev_map () == FALSE) {
-		HAL_ERROR (("Unable to get sysfs to dev map"));
-		goto error;
-	}
-
-	/* build bus map */
-	sysfs_to_bus_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
-	g_snprintf (path, HAL_PATH_MAX, "%s/bus", get_hal_sysfs_path ());
-	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %/bus: %s", get_hal_sysfs_path (), err->message));
-		g_error_free (err);
-		goto error;
-	}
-	while ((f = g_dir_read_name (dir)) != NULL) {
-		GDir *dir1;
-
-		g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s", get_hal_sysfs_path (), f);
-		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_ERROR (("Unable to open %/bus/%s: %s", get_hal_sysfs_path (), f, err->message));
-			g_error_free (err);
-			goto error;
-		}
-		while ((f1 = g_dir_read_name (dir1)) != NULL) {
-
-			if (strcmp (f1, "devices") == 0) {
-				GDir *dir2;
-
-				g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s", 
-					    get_hal_sysfs_path (), f, f1);
-				if ((dir2 = g_dir_open (path, 0, &err)) == NULL) {
-					HAL_ERROR (("Unable to open %s/bus/%s/%s: %s", 
-						    get_hal_sysfs_path (), f, f1, err->message));
-					g_error_free (err);
-					goto error;
-				}
-				while ((f2 = g_dir_read_name (dir2)) != NULL) {
-					gchar *target;
-					gchar *normalized_target;
-					g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s/%s", 
-						    get_hal_sysfs_path (), f, f1, f2);
-					if ((target = g_file_read_link (path, &err)) == NULL) {
-						HAL_ERROR (("%s/bus/%s/%s/%s is not a symlink: %s!", 
-							    get_hal_sysfs_path (), 
-							    f, f1, f2, err->message));
-						g_error_free (err);
-						goto error;
-					}
-
-					g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s", get_hal_sysfs_path (), f, f1);
-					normalized_target = hal_util_get_normalized_path (path, target);
-					g_free (target);
-
-					g_hash_table_insert (sysfs_to_bus_map, normalized_target, g_strdup(f));
-
-				}
-				g_dir_close (dir2);
-			}
-		}
-		g_dir_close (dir1);
-	}
-	g_dir_close (dir);
-
-	/* build class map and class device map (values are free in separate foreach()) */
-	sysfs_to_class_in_devices_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-	g_snprintf (path, HAL_PATH_MAX, "%s/class" , get_hal_sysfs_path ());
-	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %/class: %s", get_hal_sysfs_path (), err->message));
-		goto error;
-	}
-	while ((f = g_dir_read_name (dir)) != NULL) {
-		GDir *dir1;
-
-		g_snprintf (path, HAL_PATH_MAX, "%s/class/%s" , get_hal_sysfs_path (), f);
-		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_ERROR (("Unable to open %s/class/%s: %s", get_hal_sysfs_path (), f, err->message));
-			g_error_free (err);
-			goto error;
-		}
-		while ((f1 = g_dir_read_name (dir1)) != NULL) {
-			gchar *target;
-			gchar *normalized_target;
-
-			g_snprintf (path2, HAL_PATH_MAX, "%s/class/%s/%s", get_hal_sysfs_path (), f, f1);
-
-			/* check if we find a symlink here pointing to a device _inside_ a class device,
-			 * like "input" in 2.6.15. This kernel sysfs layout will change again in the future,
-			 * for now resolve the link to the "real" device path, like real hotplug events
-			 * devpath would have
-			 */
-			if ((target = g_file_read_link (path2, NULL)) != NULL) {
-				char *pos = strrchr(path2, '/');
-
-				if (pos)
-					pos[0] = '\0';
-				normalized_target = hal_util_get_normalized_path (path2, target);
-				g_free (target);
-				g_strlcpy(path2, normalized_target, sizeof(path2));
-				g_free (normalized_target);
-			}
-
-			/* Accept net devices without device links too, they may be coldplugged PCMCIA devices */
-			g_snprintf (path1, HAL_PATH_MAX, "%s/device", path2);
-			if (((target = g_file_read_link (path1, NULL)) == NULL)) {
-				/* no device link */
-				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (path2));
-				sysfs_other_class_dev = g_slist_append (sysfs_other_class_dev, g_strdup (f));
-			} else {
-				GSList *classdev_strings;
-
-				normalized_target = hal_util_get_normalized_path (path2, target);
-				g_free (target);
-
-				classdev_strings = g_hash_table_lookup (sysfs_to_class_in_devices_map,
-									normalized_target);
-
-				classdev_strings = g_slist_append (classdev_strings, g_strdup (path2));
-				classdev_strings = g_slist_append (classdev_strings, g_strdup (f));
-				g_hash_table_replace (sysfs_to_class_in_devices_map,
-						      normalized_target, classdev_strings);
-			}				
-		}
-		g_dir_close (dir1);
-	}
-	g_dir_close (dir);
-
-	/* Now traverse /sys/devices and consult the map we've just
-	 * built; this includes adding a) bus devices; and b) class
-	 * devices that sit in /sys/devices */
-	g_snprintf (path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
-	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %/devices: %s", get_hal_sysfs_path (), err->message));
-		g_error_free (err);
-		goto error;
-	}
-	while ((f = g_dir_read_name (dir)) != NULL) {
-		GDir *dir1;
-
-		g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s", get_hal_sysfs_path (), f);
-		if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-			HAL_ERROR (("Unable to open %/devices/%s: %s", get_hal_sysfs_path (), f, err->message));
-			g_error_free (err);
-			goto error;
-		}
-		while ((f1 = g_dir_read_name (dir1)) != NULL) {
-
-			g_snprintf (path, HAL_PATH_MAX, "%s/devices/%s/%s", get_hal_sysfs_path (), f, f1);
-			coldplug_compute_visit_device (path, sysfs_to_bus_map, sysfs_to_class_in_devices_map);
-		}
-		g_dir_close (dir1);
-	}
-	g_dir_close (dir);
-
-	g_hash_table_destroy (sysfs_to_bus_map);
-	/* free keys and values in this complex hash */
-	g_hash_table_foreach (sysfs_to_class_in_devices_map, free_hash_sys_to_class_in_dev, NULL);
-	g_hash_table_destroy (sysfs_to_class_in_devices_map);
-
-	/* we are guaranteed, per construction, that the len of this list is even */
-	for (li = sysfs_other_class_dev; li != NULL; li = g_slist_next (g_slist_next (li))) {
-		gchar *sysfs_path;
-		gchar *subsystem;
-		HotplugEvent *hotplug_event;
-
-		sysfs_path = (gchar *) li->data;
-		subsystem = (gchar *) li->next->data;
-
-#ifdef HAL_COLDPLUG_VERBOSE
-		printf ("class: %s (%s) (no device link)\n", sysfs_path, subsystem);
-#endif
-		hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
-		hotplug_event_enqueue (hotplug_event);
-
-		g_free (li->data);
-		g_free (li->next->data);
-	}
-	g_slist_free (sysfs_other_class_dev);
-
-	/* add block devices */
-	g_snprintf (path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
-	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %s: %s", path, err->message));
-		g_error_free (err);
-		goto error;
-	}
-	while ((f = g_dir_read_name (dir)) != NULL) {
-		if (g_str_has_prefix (f, DMPREFIX)) {
-			/* defer dm devices */
-			sysfs_dm_dev = g_slist_append(sysfs_dm_dev, g_strdup(f));
-			continue;
-		}
-		if (coldplug_synthesize_block_event(f) == FALSE)
-			goto error;
-	}
-	/* process all dm devices last so that their backing devices exist */
-	for (li = sysfs_dm_dev; li != NULL; li = g_slist_next (g_slist_next (li))) {
-		if (coldplug_synthesize_block_event (li->data) == FALSE)
-			goto error;
-		g_free (li->data);
-	}
-	g_slist_free (sysfs_dm_dev);
-	g_dir_close (dir);
-
-	g_hash_table_destroy (sysfs_to_udev_map);
-
-	return TRUE;
-error:
-	HAL_ERROR (("Error building the ordered list of sysfs paths"));
-	return FALSE;
-}
-
-static gboolean
-coldplug_synthesize_block_event(const gchar *f)
-{
-	GDir *dir1;
-	HotplugEvent *hotplug_event;
-	GError *err = NULL;
-	gchar path[HAL_PATH_MAX];
-	gchar path1[HAL_PATH_MAX];
-	const gchar *f1;
-
-	g_snprintf (path, HAL_PATH_MAX, "%s/block/%s", get_hal_sysfs_path (), f);
-#ifdef HAL_COLDPLUG_VERBOSE
-	printf ("block: %s (block)\n",  path);
-#endif
-	hotplug_event = coldplug_get_hotplug_event (path, "block");
-	hotplug_event_enqueue (hotplug_event);
-
-	if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
-		HAL_ERROR (("Unable to open %s: %s", path, err->message));
-		g_error_free (err);
-		goto error;
-	}
-	while ((f1 = g_dir_read_name (dir1)) != NULL) {
-		if (strncmp (f, f1, strlen (f)) == 0) {
-			g_snprintf (path1, HAL_PATH_MAX, "%s/%s", path, f1);
-#ifdef HAL_COLDPLUG_VERBOSE
-			printf ("block: %s (block)\n", path1);
-#endif
-			hotplug_event = coldplug_get_hotplug_event (path1, "block");
-			hotplug_event_enqueue (hotplug_event);
-		}
-	}
-	g_dir_close (dir1);
-       
-	return TRUE;
-error:
-	return FALSE;
-}
-
-static void
-coldplug_compute_visit_device (const gchar *path,
-			       GHashTable *sysfs_to_bus_map, 
-			       GHashTable *sysfs_to_class_in_devices_map)
-{
-	gchar *bus;
-	GError *err = NULL;
-	GDir *dir;
-	const gchar *f;
-	/*HStringPair *pair;*/
-	GSList *class_devs;
-	GSList *i;
-
-	bus = g_hash_table_lookup (sysfs_to_bus_map, path);
-	if (bus != NULL) {
-		HotplugEvent *hotplug_event;
-#ifdef HAL_COLDPLUG_VERBOSE
-		printf ("bus:   %s (%s)\n", path, bus);
-#endif
-		hotplug_event = coldplug_get_hotplug_event (path, bus);
-		hotplug_event_enqueue (hotplug_event);
-	}
-
-	/* we are guaranteed, per construction, that the len of this list is even */
-	class_devs = g_hash_table_lookup (sysfs_to_class_in_devices_map, path);
-	for (i = class_devs; i != NULL; i = g_slist_next (g_slist_next (i))) {
-		gchar *sysfs_path;
-		gchar *subsystem;
-		HotplugEvent *hotplug_event;
-
-		sysfs_path = (gchar *) i->data;
-		subsystem = (gchar *) i->next->data;
-#ifdef HAL_COLDPLUG_VERBOSE
-		printf ("class: %s (%s) (%s)\n", path, subsystem, sysfs_path);
-#endif
-		hotplug_event = coldplug_get_hotplug_event (sysfs_path, subsystem);
-		hotplug_event_enqueue (hotplug_event);
-	}
-
-	/* visit children; dont follow symlinks though.. */
-	err = NULL;
-	if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-		/*HAL_ERROR (("Unable to open directory: %s", path, err->message));*/
-		g_error_free (err);
-		goto error;
-	}
-	while ((f = g_dir_read_name (dir)) != NULL) {
-		gchar path_child[HAL_PATH_MAX];
-		struct stat statbuf;
-
-		g_snprintf (path_child, HAL_PATH_MAX, "%s/%s", path, f);
-		if (lstat (path_child, &statbuf) == 0) {
-			if (!S_ISLNK (statbuf.st_mode)) {
-				/* recursion fun */
-				coldplug_compute_visit_device (path_child, 
-							       sysfs_to_bus_map, 
-							       sysfs_to_class_in_devices_map);
-			}
-		}
-	}
-	g_dir_close (dir);
-
-error:
-	return;
-}
-
diff --git a/hald/linux2/coldplug.h b/hald/linux2/coldplug.h
deleted file mode 100644
index 7da868a..0000000
--- a/hald/linux2/coldplug.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * coldplug.h : Synthesize hotplug events when starting up
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef COLDPLUG_H
-#define COLDPLUG_H
-
-#include <glib.h>
-
-gboolean coldplug_synthesize_events (void);
-
-#endif /* COLDPLUG_H */
-
diff --git a/hald/linux2/hotplug.c b/hald/linux2/hotplug.c
deleted file mode 100644
index 4eac8b9..0000000
--- a/hald/linux2/hotplug.c
+++ /dev/null
@@ -1,618 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * hotplug.c : Handling of hotplug events
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <ctype.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../hald.h"
-#include "../logger.h"
-#include "../osspec.h"
-
-#include "acpi.h"
-#include "apm.h"
-#include "blockdev.h"
-#include "classdev.h"
-#include "osspec_linux.h"
-#include "physdev.h"
-#include "pmu.h"
-
-#include "hotplug.h"
-
-/** Queue of ordered hotplug events */
-GQueue *hotplug_event_queue;
-
-/** List of HotplugEvent objects we are currently processing */
-GSList *hotplug_events_in_progress = NULL;
-
-void
-hotplug_event_end (void *end_token)
-{
-	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
-
-	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
-	g_free (hotplug_event);
-	hotplug_event_process_queue ();
-}
-
-void 
-hotplug_event_reposted (void *end_token)
-{
-	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
-
-	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
-	hotplug_event_process_queue ();
-}
-
-static void
-fixup_net_device_for_renaming (HotplugEvent *hotplug_event)
-{
-	/* fixup net devices by looking at ifindex */
-	if (strcmp (hotplug_event->sysfs.subsystem, "net") == 0 && hotplug_event->sysfs.net_ifindex != -1) {
-		int ifindex;
-		
-		if (!hal_util_get_int_from_file (hotplug_event->sysfs.sysfs_path, "ifindex", &ifindex, 10) ||
-		    (ifindex != hotplug_event->sysfs.net_ifindex)) {
-			GDir *dir;
-			char path[HAL_PATH_MAX];
-			char path1[HAL_PATH_MAX];
-			GError *err = NULL;
-			const gchar *f;
-			
-			/* search for new name */
-			HAL_WARNING (("Net interface @ %s with ifindex %d was probably renamed",
-				      hotplug_event->sysfs.sysfs_path, hotplug_event->sysfs.net_ifindex));
-			
-			g_snprintf (path, HAL_PATH_MAX, "%s/class/net" , get_hal_sysfs_path());
-			if ((dir = g_dir_open (path, 0, &err)) == NULL) {
-				HAL_ERROR (("Unable to open %s/class/net: %s", get_hal_sysfs_path(), err->message));
-				g_error_free (err);
-				goto out;
-			}
-			while ((f = g_dir_read_name (dir)) != NULL) {
-				g_snprintf (path1, HAL_PATH_MAX, "%s/class/net/%s" , get_hal_sysfs_path (), f);
-				if (hal_util_get_int_from_file (path1, "ifindex", &ifindex, 10)) {
-					if (ifindex == hotplug_event->sysfs.net_ifindex) {
-						HAL_INFO (("Using sysfs path %s for ifindex %d", path1, ifindex));
-						strncpy (hotplug_event->sysfs.sysfs_path, path1, HAL_PATH_MAX);
-						g_dir_close (dir);
-						goto out;
-					}
-				}
-				
-			}
-			g_dir_close (dir);
-		}
-	}
-out:
-	return;
-}
-
-
-static void
-hotplug_event_begin_sysfs (HotplugEvent *hotplug_event)
-{
-	HalDevice *d;
-	char subsystem[HAL_PATH_MAX];
-	gchar *subsystem_target;
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (),
-						     "linux.sysfs_path",
-						     hotplug_event->sysfs.sysfs_path);
-
-	/* FIXME: we should reprobe the device instead of skipping the event */
-	if (d != NULL && hotplug_event->action == HOTPLUG_ACTION_ADD) {
-		HAL_ERROR (("devpath %s already present in the store, ignore event", hotplug_event->sysfs.sysfs_path));
-		hotplug_event_end ((void *) hotplug_event);
-		return;
-	}
-
-	/* get device type from already known device object */
-	if (d != NULL) {
-		HotplugEventType type;
-
-		type = hal_device_property_get_int (d, "linux.hotplug_type");
-		if (type == HOTPLUG_EVENT_SYSFS_BUS) {
-			HAL_INFO (("%s is a bus device (store)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
-		} else if (type == HOTPLUG_EVENT_SYSFS_CLASS) {
-			HAL_INFO (("%s is a class device (store)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
-		} else if (type == HOTPLUG_EVENT_SYSFS_BLOCK) {
-			HAL_INFO (("%s is a block device (store)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
-		}
-	}
-
-	/*
-	 * determine device type by "subsystem" link (from kernel 2.6.18, class devices
-	 * start to move from /class to /devices and have a "subsystem" link pointing
-	 * back to the "class" or "bus" directory
-	 */
-	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
-		g_snprintf (subsystem, HAL_PATH_MAX, "%s/subsystem", hotplug_event->sysfs.sysfs_path);
-		subsystem_target = g_file_read_link (subsystem, NULL);
-		if (subsystem_target != NULL) {
-			if (strstr(subsystem_target, "/bus/") != NULL) {
-				HAL_INFO (("%s is a bus device (subsystem)", hotplug_event->sysfs.sysfs_path));
-				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
-			} else if (strstr(subsystem_target, "/class/") != NULL) {
-				HAL_INFO (("%s is a class device (subsystem)", hotplug_event->sysfs.sysfs_path));
-				hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
-			} else if (strstr(subsystem_target, "/block") != NULL) {
-				HAL_INFO (("%s is a block device (subsystem)", hotplug_event->sysfs.sysfs_path));
-				hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
-			}
-			g_free (subsystem_target);
-		}
-	}
-
-	/* older kernels get the device type from the devpath */
-	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS) {
-		char sys_devices_path[HAL_PATH_MAX];
-		char sys_class_path[HAL_PATH_MAX];
-		char sys_block_path[HAL_PATH_MAX];
-		gsize sys_devices_path_len;
-		gsize sys_class_path_len;
-		gsize sys_block_path_len;
-
-		sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", get_hal_sysfs_path ());
-		sys_class_path_len   = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", get_hal_sysfs_path ());
-		sys_block_path_len   = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", get_hal_sysfs_path ());
-
-		if (strncmp (hotplug_event->sysfs.sysfs_path, sys_devices_path, sys_devices_path_len) == 0) {
-			HAL_INFO (("%s is a bus device (devpath)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BUS;
-		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_class_path, sys_class_path_len) == 0) {
-			HAL_INFO (("%s is a class device (devpath)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_CLASS;
-		} else if (strncmp (hotplug_event->sysfs.sysfs_path, sys_block_path, sys_block_path_len) == 0) {
-			HAL_INFO (("%s is a block device (devpath)", hotplug_event->sysfs.sysfs_path));
-			hotplug_event->type = HOTPLUG_EVENT_SYSFS_BLOCK;
-		}
-	}
-
-	if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BUS) {
-		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-			HalDevice *parent;
-			parent = hal_util_find_closest_ancestor (hotplug_event->sysfs.sysfs_path);
-			hotplug_event_begin_add_physdev (hotplug_event->sysfs.subsystem, 
-							 hotplug_event->sysfs.sysfs_path, 
-							 parent,
-							 (void *) hotplug_event);
-		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-			hotplug_event_begin_remove_physdev (hotplug_event->sysfs.subsystem, 
-							    hotplug_event->sysfs.sysfs_path, 
-							    (void *) hotplug_event);
-		}
-	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_CLASS) {
-		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-			gchar *target;
-			HalDevice *physdev;
-			char physdevpath[HAL_PATH_MAX];
-			gchar *sysfs_path_in_devices;
-
-			sysfs_path_in_devices = NULL;
-
-			/* /sbin/ifrename may be called from a hotplug handler before we process this,
-			 * so if index doesn't match, go ahead and find a new sysfs path
-			 */
-			fixup_net_device_for_renaming (hotplug_event);
-
-			g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
-			if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
-				gchar *normalized_target;
-
-				normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs.sysfs_path, target);
-				g_free (target);
-
-				sysfs_path_in_devices = g_strdup (normalized_target);
-
-				/* there may be ''holes'' in /sys/devices so try hard to find the closest match */
-				do {
-					physdev = hal_device_store_match_key_value_string (hald_get_gdl (), 
-											   "linux.sysfs_path_device", 
-											   normalized_target);
-					if (physdev != NULL)
-						break;
-
-					/* go up one directory */
-					if (!hal_util_path_ascend (normalized_target))
-						break;
-				} while (physdev == NULL);
-				g_free (normalized_target);
-			} else {
-				physdev = NULL;
-			}
-
-			hotplug_event_begin_add_classdev (hotplug_event->sysfs.subsystem,
-							  hotplug_event->sysfs.sysfs_path,
-							  hotplug_event->sysfs.device_file,
-							  physdev,
-							  sysfs_path_in_devices,
-							  (void *) hotplug_event);
-
-			g_free (sysfs_path_in_devices);
-
-		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-			hotplug_event_begin_remove_classdev (hotplug_event->sysfs.subsystem,
-							     hotplug_event->sysfs.sysfs_path,
-							     (void *) hotplug_event);
-		}
-	} else if (hotplug_event->type == HOTPLUG_EVENT_SYSFS_BLOCK) {
-		if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-			HalDevice *parent = NULL;
-			int range;
-			gboolean is_partition;
-			gboolean is_fakevolume;
-			
-			/* it's a partition if and only if it doesn't have the range file...
-			 *
-			 * notably the device mapper partitions do have a range file, but that's
-			 * fine, we don't count them as partitions anyway...
-			 *
-			 * also, if the sysfs ends with "fakevolume" the hotplug event is synthesized
-			 * from within HAL for partitions on the main block device
-			 */
-			is_fakevolume = FALSE;
-			if (strcmp (hal_util_get_last_element (hotplug_event->sysfs.sysfs_path), "fakevolume") == 0) {
-				is_fakevolume = TRUE;
-			}
-			is_partition = TRUE;
-			if (is_fakevolume ||
-			    hal_util_get_int_from_file (hotplug_event->sysfs.sysfs_path, "range", &range, 0)) {
-				is_partition = FALSE;
-			}
-
-			if (is_partition || is_fakevolume) {
-				gchar *parent_path;
-
-				parent_path = hal_util_get_parent_path (hotplug_event->sysfs.sysfs_path);
-
-				parent = hal_device_store_match_key_value_string (hald_get_gdl (),
-										  "linux.sysfs_path_device",
-										  parent_path);
-				g_free (parent_path);
-			} else {
-				gchar *target;
-				char physdevpath[HAL_PATH_MAX];
-
-				g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs.sysfs_path);
-				if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
-					gchar *normalized_target;
-
-					normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs.sysfs_path, target);
-					g_free (target);
-					parent = hal_device_store_match_key_value_string (hald_get_gdl (),
-											  "linux.sysfs_path_device",
-											  normalized_target);
-					g_free (normalized_target);
-				}
-			}
-
-			hotplug_event_begin_add_blockdev (hotplug_event->sysfs.sysfs_path,
-							  hotplug_event->sysfs.device_file,
-							  is_partition,
-							  parent,
-							  (void *) hotplug_event);
-		} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-			hotplug_event_begin_remove_blockdev (hotplug_event->sysfs.sysfs_path,
-							     (void *) hotplug_event);
-		}
-	} else {
-		/* just ignore this hotplug event */
-		hotplug_event_end ((void *) hotplug_event);
-	}
-}
-
-static void
-hotplug_event_begin_acpi (HotplugEvent *hotplug_event)
-{
-	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-		hotplug_event_begin_add_acpi (hotplug_event->acpi.acpi_path, 
-					      hotplug_event->acpi.acpi_type,
-					      NULL,
-					      (void *) hotplug_event);
-	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-		hotplug_event_begin_remove_acpi (hotplug_event->acpi.acpi_path, 
-						 hotplug_event->acpi.acpi_type,
-						 (void *) hotplug_event);
-	}
-}
-
-static void
-hotplug_event_begin_apm (HotplugEvent *hotplug_event)
-{
-	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-		hotplug_event_begin_add_apm (hotplug_event->apm.apm_path, 
-					     hotplug_event->apm.apm_type,
-					     NULL,
-					     (void *) hotplug_event);
-	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-		hotplug_event_begin_remove_apm (hotplug_event->apm.apm_path, 
-						hotplug_event->apm.apm_type,
-						(void *) hotplug_event);
-	}
-}
-
-static void
-hotplug_event_begin_pmu (HotplugEvent *hotplug_event)
-{
-	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
-		hotplug_event_begin_add_pmu (hotplug_event->pmu.pmu_path, 
-					     hotplug_event->pmu.pmu_type,
-					     NULL,
-					     (void *) hotplug_event);
-	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
-		hotplug_event_begin_remove_pmu (hotplug_event->pmu.pmu_path, 
-						hotplug_event->pmu.pmu_type,
-						(void *) hotplug_event);
-	}
-}
-
-static void
-hotplug_event_begin (HotplugEvent *hotplug_event)
-{
-	switch (hotplug_event->type) {
-
-	/* explicit fallthrough */
-	case HOTPLUG_EVENT_SYSFS:
-	case HOTPLUG_EVENT_SYSFS_BUS:
-	case HOTPLUG_EVENT_SYSFS_CLASS:
-	case HOTPLUG_EVENT_SYSFS_BLOCK:
-		hotplug_event_begin_sysfs (hotplug_event);
-		break;
-
-	case HOTPLUG_EVENT_ACPI:
-		hotplug_event_begin_acpi (hotplug_event);
-		break;
-
-	case HOTPLUG_EVENT_APM:
-		hotplug_event_begin_apm (hotplug_event);
-		break;
-
-	case HOTPLUG_EVENT_PMU:
-		hotplug_event_begin_pmu (hotplug_event);
-		break;
-
-	default:
-		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
-		hotplug_event_end ((void *) hotplug_event);
-		break;
-	}
-}
-
-void 
-hotplug_event_enqueue (HotplugEvent *hotplug_event)
-{
-	if (hotplug_event_queue == NULL)
-		hotplug_event_queue = g_queue_new ();
-
-	g_queue_push_tail (hotplug_event_queue, hotplug_event);
-}
-
-void 
-hotplug_event_enqueue_at_front (HotplugEvent *hotplug_event)
-{
-	if (hotplug_event_queue == NULL)
-		hotplug_event_queue = g_queue_new ();
-
-	g_queue_push_head (hotplug_event_queue, hotplug_event);
-}
-
-void 
-hotplug_event_process_queue (void)
-{
-	HotplugEvent *hotplug_event;
-
-	if (hotplug_events_in_progress == NULL && 
-	    (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
-		hotplug_queue_now_empty ();
-		goto out;
-	}
-
-	/* do not process events if some other event is in progress 
-	 *
-	 * TODO: optimize so we can do add events in parallel by inspecting the
-	 *       wait_for_sysfs_path parameter and hotplug_events_in_progress list
-	 */
-	if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
-		goto out;
-
-	hotplug_event = g_queue_pop_head (hotplug_event_queue);
-	if (hotplug_event == NULL)
-		goto out;
-
-	hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
-	hotplug_event_begin (hotplug_event);
-
-out:
-	;	
-}
-
-gboolean 
-hotplug_rescan_device (HalDevice *d)
-{
-	gboolean ret;
-
-	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
-	case HOTPLUG_EVENT_SYSFS_BUS:
-		ret = physdev_rescan_device (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_CLASS:
-		ret = classdev_rescan_device (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_BLOCK:
-		ret = blockdev_rescan_device (d);
-		break;
-
-	case HOTPLUG_EVENT_ACPI:
-		ret = acpi_rescan_device (d);
-		break;
-
-	case HOTPLUG_EVENT_APM:
-		ret = apm_rescan_device (d);
-		break;
-
-	case HOTPLUG_EVENT_PMU:
-		ret = pmu_rescan_device (d);
-		break;
-
-	default:
-		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
-		ret = FALSE;
-		break;
-	}
-
-	return ret;
-}
-
-static void
-hotplug_reprobe_generate_remove_events (HalDevice *d)
-{
-	GSList *i;
-	GSList *childs;
-	HotplugEvent *e;
-
-	/* first remove childs */
-	childs = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.parent", d->udi);
-	for (i = childs; i != NULL; i = g_slist_next (i)) {
-		HalDevice *child;
-
-		child = HAL_DEVICE (i->data);
-		hotplug_reprobe_generate_remove_events (child);
-	}
-
-	/* then remove self */
-	HAL_INFO (("Generate remove event for udi %s", d->udi));
-	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
-	case HOTPLUG_EVENT_SYSFS_BUS:
-		e = physdev_generate_remove_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_CLASS:
-		e = classdev_generate_remove_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_BLOCK:
-		e = blockdev_generate_remove_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_ACPI:
-		e = acpi_generate_remove_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_APM:
-		e = apm_generate_remove_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_PMU:
-		e = pmu_generate_remove_hotplug_event (d);
-		break;
-
-	default:
-		e = NULL;
-		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
-		break;
-	}
-
-	if (e != NULL) {
-		hotplug_event_enqueue (e);
-	}
-}
-
-static void
-hotplug_reprobe_generate_add_events (HalDevice *d)
-{
-	GSList *i;
-	GSList *childs;
-	HotplugEvent *e;
-
-	/* first add self */
-	HAL_INFO (("Generate add event for udi %s", d->udi));
-	switch (hal_device_property_get_int (d, "linux.hotplug_type")) {
-	case HOTPLUG_EVENT_SYSFS_BUS:
-		e = physdev_generate_add_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_CLASS:
-		e = classdev_generate_add_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_SYSFS_BLOCK:
-		e = blockdev_generate_add_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_ACPI:
-		e = acpi_generate_add_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_APM:
-		e = apm_generate_add_hotplug_event (d);
-		break;
-
-	case HOTPLUG_EVENT_PMU:
-		e = pmu_generate_add_hotplug_event (d);
-		break;
-
-	default:
-		e = NULL;
-		HAL_INFO (("Unknown hotplug type for udi=%s", d->udi));
-		break;
-	}
-
-	if (e != NULL) {
-		hotplug_event_enqueue (e);
-	}
-
-	/* then add childs */
-	childs = hal_device_store_match_multiple_key_value_string (hald_get_gdl (), "info.parent", d->udi);
-	for (i = childs; i != NULL; i = g_slist_next (i)) {
-		HalDevice *child;
-
-		child = HAL_DEVICE (i->data);
-		hotplug_reprobe_generate_add_events (child);
-	}
-}
-
-gboolean
-hotplug_reprobe_tree (HalDevice *d)
-{
-	hotplug_reprobe_generate_remove_events (d);
-	hotplug_reprobe_generate_add_events (d);
-	hotplug_event_process_queue ();
-	return FALSE;
-}
diff --git a/hald/linux2/hotplug.h b/hald/linux2/hotplug.h
deleted file mode 100644
index d93d620..0000000
--- a/hald/linux2/hotplug.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * hotplug.h : Handling of hotplug events
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef HOTPLUG_H
-#define HOTPLUG_H
-
-#include <glib.h>
-
-#include "../device.h"
-#include "../util.h"
-
-typedef enum {
-	HOTPLUG_ACTION_ADD,
-	HOTPLUG_ACTION_REMOVE,
-	HOTPLUG_ACTION_ONLINE,
-	HOTPLUG_ACTION_OFFLINE,
-} HotplugActionType;
-
-typedef enum {
-	HOTPLUG_EVENT_SYSFS       = 0,
-	HOTPLUG_EVENT_SYSFS_BUS   = 1,
-	HOTPLUG_EVENT_SYSFS_CLASS = 2,
-	HOTPLUG_EVENT_SYSFS_BLOCK = 3,
-	HOTPLUG_EVENT_ACPI        = 4,
-	HOTPLUG_EVENT_APM         = 5,
-	HOTPLUG_EVENT_PMU         = 6
-} HotplugEventType;
-
-/** Data structure representing a hotplug event; also used for
- *  coldplugging.
- */
-typedef struct
-{
-	HotplugActionType action;				/* Whether the event is add or remove */
-	HotplugEventType type;					/* Type of event */
-
-	union {
-		struct {
-			char subsystem[HAL_NAME_MAX];		/* Kernel subsystem the device belongs to */
-			char sysfs_path[HAL_PATH_MAX];		/* Kernel device devpath */
-			char device_file[HAL_PATH_MAX];	/* Device node for the device */
-			unsigned long long seqnum;		/* kernel uevent sequence number */
-			int net_ifindex;			/* Kernel ifindex for network devices */
-
-			/* stuff udev may tell us about the device and we don't want to query */
-			char vendor[HAL_NAME_MAX];
-			char model[HAL_NAME_MAX];
-			char revision[HAL_NAME_MAX];
-			char serial[HAL_NAME_MAX];
-			char fsusage[HAL_NAME_MAX];
-			char fstype[HAL_NAME_MAX];
-			char fsversion[HAL_NAME_MAX];
-			char fslabel[HAL_NAME_MAX];
-			char fsuuid[HAL_NAME_MAX];
-		} sysfs;
-
-		struct {
-			int  acpi_type;				/* Type of ACPI object; see acpi.c */
-			char acpi_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/acpi/battery/BAT0/ */
-		} acpi;
-
-		struct {
-			int  apm_type;				/* Type of APM object; see apm.c */
-			char apm_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/apm */
-		} apm;
-
-		struct {
-			int  pmu_type;				/* Type of PMU object; see pmu.c */
-			char pmu_path[HAL_PATH_MAX];		/* Path into procfs, e.g. /proc/pmu/battery_0 */
-		} pmu;
-	};
-
-} HotplugEvent;
-
-void hotplug_event_enqueue (HotplugEvent *event);
-
-void hotplug_event_enqueue_at_front (HotplugEvent *hotplug_event);
-
-void hotplug_event_process_queue (void);
-
-void hotplug_event_end (void *end_token);
-
-void hotplug_event_reposted (void *end_token);
-
-gboolean hotplug_rescan_device (HalDevice *d);
-
-gboolean hotplug_reprobe_tree (HalDevice *d);
-
-void hotplug_queue_now_empty (void);
-
-#endif /* HOTPLUG_H */
diff --git a/hald/linux2/hotplug_helper.h b/hald/linux2/hotplug_helper.h
deleted file mode 100644
index 2767037..0000000
--- a/hald/linux2/hotplug_helper.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * HAL daemon hotplug.d and dev.d helper details
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef HALD_HELPER_H
-#define HALD_HELPER_H
-
-#define HALD_HELPER_MAGIC 0x68616c64
-#define HALD_HELPER_SOCKET_PATH "/var/run/hal/hotplug_socket2"
-#define HALD_HELPER_STRLEN 256
-
-struct hald_helper_msg
-{
-	unsigned int magic;			/**< magic */
-	unsigned long long seqnum;		/**< Sequence number (may be 0 if for dev if udev has no support) */
-	char action[HALD_HELPER_STRLEN];	/**< hotplug action */
-	char subsystem[HALD_HELPER_STRLEN];	/**< subsystem e.g. usb, pci (only for hotplug msg) */
-	char sysfs_path[HALD_HELPER_STRLEN];	/**< path into sysfs without sysfs mountpoint, e.g. /block/sda */
-	char device_name[HALD_HELPER_STRLEN];	/**< absolute path of device node (only for device msg) */
-	int net_ifindex;                        /**< For networking class devices only; the value of the ifindex file*/
-	time_t time_stamp;                      /**< Time of day we received the hotplug event */
-};
-
-#endif /* HALD_HELPER_H */
diff --git a/hald/linux2/ids.c b/hald/linux2/ids.c
deleted file mode 100644
index 7cb41f3..0000000
--- a/hald/linux2/ids.c
+++ /dev/null
@@ -1,973 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * classdev.c : Handling of functional kernel devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <ctype.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../logger.h"
-
-#include "ids.h"
-
-/** Pointer to where the pci.ids file is loaded */
-static char *pci_ids = NULL;
-
-/** Length of data store at at pci_ids */
-static unsigned int pci_ids_len;
-
-/** Iterator position into pci_ids */
-static unsigned int pci_ids_iter_pos;
-
-/** Initialize the pci.ids line iterator to the beginning of the file */
-static void
-pci_ids_line_iter_init ()
-{
-	pci_ids_iter_pos = 0;
-}
-
-/** Maximum length of lines in pci.ids */
-#define PCI_IDS_MAX_LINE_LEN 512
-
-/** Get the next line from pci.ids
- *
- *  @param  line_len            Pointer to where number of bytes in line will
- *                              be stored
- *  @return                     Pointer to the line; only valid until the
- *                              next invocation of this function
- */
-static char *
-pci_ids_line_iter_get_line (unsigned int *line_len)
-{
-	unsigned int i;
-	static char line[PCI_IDS_MAX_LINE_LEN];
-
-	for (i = 0;
-	     pci_ids_iter_pos < pci_ids_len &&
-	     i < PCI_IDS_MAX_LINE_LEN - 1 &&
-	     pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
-		line[i] = pci_ids[pci_ids_iter_pos];
-	}
-
-	line[i] = '\0';
-	if (line_len != NULL)
-		*line_len = i;
-
-	pci_ids_iter_pos++;
-
-	return line;
-}
-
-/** See if there are more lines to process in pci.ids
- *
- *  @return                     #TRUE iff there are more lines to process
- */
-static dbus_bool_t
-pci_ids_line_iter_has_more ()
-{
-	return pci_ids_iter_pos < pci_ids_len;
-}
-
-
-/** Find the names for a PCI device.
- *
- *  The pointers returned are only valid until the next invocation of this
- *  function.
- *
- *  @param  vendor_id           PCI vendor id or 0 if unknown
- *  @param  product_id          PCI product id or 0 if unknown
- *  @param  subsys_vendor_id    PCI subsystem vendor id or 0 if unknown
- *  @param  subsys_product_id   PCI subsystem product id or 0 if unknown
- *  @param  vendor_name         Set to pointer of result or NULL
- *  @param  product_name        Set to pointer of result or NULL
- *  @param  subsys_vendor_name  Set to pointer of result or NULL
- *  @param  subsys_product_name Set to pointer of result or NULL
- */
-void
-ids_find_pci (int vendor_id, int product_id,
-	      int subsys_vendor_id, int subsys_product_id,
-	      char **vendor_name, char **product_name,
-	      char **subsys_vendor_name, char **subsys_product_name)
-{
-	char *line;
-	unsigned int i;
-	unsigned int line_len;
-	unsigned int num_tabs;
-	char rep_vi[8];
-	char rep_pi[8];
-	char rep_svi[8];
-	char rep_spi[8];
-	dbus_bool_t vendor_matched = FALSE;
-	dbus_bool_t product_matched = FALSE;
-	static char store_vn[PCI_IDS_MAX_LINE_LEN];
-	static char store_pn[PCI_IDS_MAX_LINE_LEN];
-	static char store_svn[PCI_IDS_MAX_LINE_LEN];
-	static char store_spn[PCI_IDS_MAX_LINE_LEN];
-
-	snprintf (rep_vi, 8, "%04x", vendor_id);
-	snprintf (rep_pi, 8, "%04x", product_id);
-	snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
-	snprintf (rep_spi, 8, "%04x", subsys_product_id);
-
-	*vendor_name = NULL;
-	*product_name = NULL;
-	*subsys_vendor_name = NULL;
-	*subsys_product_name = NULL;
-
-	for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
-		line = pci_ids_line_iter_get_line (&line_len);
-
-		/* skip lines with no content */
-		if (line_len < 4)
-			continue;
-
-		/* skip comments */
-		if (line[0] == '#')
-			continue;
-
-		/* count number of tabs */
-		num_tabs = 0;
-		for (i = 0; i < line_len; i++) {
-			if (line[i] != '\t')
-				break;
-			num_tabs++;
-		}
-
-		switch (num_tabs) {
-		case 0:
-			/* vendor names */
-			vendor_matched = FALSE;
-
-			/* first check subsys_vendor_id, if haven't done 
-			 * already */
-			if (*subsys_vendor_name == NULL
-			    && subsys_vendor_id != 0) {
-				if ((*((dbus_uint32_t *) line)) ==
-				    (*((dbus_uint32_t *) rep_svi))) {
-					/* found it */
-					for (i = 4; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_svn, line + i,
-						 PCI_IDS_MAX_LINE_LEN);
-					*subsys_vendor_name = store_svn;
-				}
-			}
-
-			/* check vendor_id */
-			if (vendor_id != 0) {
-				if (memcmp (line, rep_vi, 4) == 0) {
-					/* found it */
-					vendor_matched = TRUE;
-
-					for (i = 4; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_vn, line + i,
-						 PCI_IDS_MAX_LINE_LEN);
-					*vendor_name = store_vn;
-				}
-			}
-
-			break;
-
-		case 1:
-			product_matched = FALSE;
-
-			/* product names */
-			if (!vendor_matched)
-				continue;
-
-			/* check product_id */
-			if (product_id != 0) {
-				if (memcmp (line + 1, rep_pi, 4) == 0) {
-					/* found it */
-
-					product_matched = TRUE;
-
-					for (i = 5; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_pn, line + i,
-						 PCI_IDS_MAX_LINE_LEN);
-					*product_name = store_pn;
-				}
-			}
-			break;
-
-		case 2:
-			/* subsystem_vendor subsystem_product */
-			if (!vendor_matched || !product_matched)
-				continue;
-
-			/* check product_id */
-			if (subsys_vendor_id != 0
-			    && subsys_product_id != 0) {
-				if (memcmp (line + 2, rep_svi, 4) == 0
-				    && memcmp (line + 7, rep_spi,
-					       4) == 0) {
-					/* found it */
-					for (i = 11; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_spn, line + i,
-						 PCI_IDS_MAX_LINE_LEN);
-					*subsys_product_name = store_spn;
-				}
-			}
-
-			break;
-
-		default:
-			break;
-		}
-
-	}
-}
-
-/** Free resources used by to store the PCI database
- *
- *  @param                      #FALSE if the PCI database wasn't loaded
- */
-static dbus_bool_t
-pci_ids_free ()
-{
-	if (pci_ids != NULL) {
-		free (pci_ids);
-		pci_ids = NULL;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/** Load the PCI database used for mapping vendor, product, subsys_vendor
- *  and subsys_product numbers into names.
- *
- *  @param  path                Path of the pci.ids file, e.g. 
- *                              /usr/share/hwdata/pci.ids
- *  @return                     #TRUE if the file was succesfully loaded
- */
-static dbus_bool_t
-pci_ids_load (const char *path)
-{
-	FILE *fp;
-	unsigned int num_read;
-
-	fp = fopen (path, "r");
-	if (fp == NULL) {
-		HAL_ERROR (("couldn't open PCI database at %s,", path));
-		return FALSE;
-	}
-
-	fseek (fp, 0, SEEK_END);
-	pci_ids_len = ftell (fp);
-	fseek (fp, 0, SEEK_SET);
-
-	pci_ids = malloc (pci_ids_len);
-	if (pci_ids == NULL) {
-		DIE (("Couldn't allocate %d bytes for PCI database file\n",
-		      pci_ids_len));
-	}
-
-	num_read = fread (pci_ids, sizeof (char), pci_ids_len, fp);
-	if (pci_ids_len != num_read) {
-		HAL_ERROR (("Error loading PCI database file"));
-		pci_ids_free();
-		fclose(fp);
-		return FALSE;
-	}
-
-	fclose(fp);
-	return TRUE;
-}
-
-/*==========================================================================*/
-
-/** Pointer to where the usb.ids file is loaded */
-static char *usb_ids = NULL;
-
-/** Length of data store at at usb_ids */
-static unsigned int usb_ids_len;
-
-/** Iterator position into usb_ids */
-static unsigned int usb_ids_iter_pos;
-
-/** Initialize the usb.ids line iterator to the beginning of the file */
-static void
-usb_ids_line_iter_init ()
-{
-	usb_ids_iter_pos = 0;
-}
-
-/** Maximum length of lines in usb.ids */
-#define USB_IDS_MAX_LINE_LEN 512
-
-/** Get the next line from usb.ids
- *
- *  @param  line_len            Pointer to where number of bytes in line will
- *                              be stored
- *  @return                     Pointer to the line; only valid until the
- *                              next invocation of this function
- */
-static char *
-usb_ids_line_iter_get_line (unsigned int *line_len)
-{
-	unsigned int i;
-	static char line[USB_IDS_MAX_LINE_LEN];
-
-	for (i = 0;
-	     usb_ids_iter_pos < usb_ids_len &&
-	     i < USB_IDS_MAX_LINE_LEN - 1 &&
-	     usb_ids[usb_ids_iter_pos] != '\n'; i++, usb_ids_iter_pos++) {
-		line[i] = usb_ids[usb_ids_iter_pos];
-	}
-
-	line[i] = '\0';
-	if (line_len != NULL)
-		*line_len = i;
-
-	usb_ids_iter_pos++;
-
-	return line;
-}
-
-/** See if there are more lines to process in usb.ids
- *
- *  @return                     #TRUE iff there are more lines to process
- */
-static dbus_bool_t
-usb_ids_line_iter_has_more ()
-{
-	return usb_ids_iter_pos < usb_ids_len;
-}
-
-/** Find the names for a USB device.
- *
- *  The pointers returned are only valid until the next invocation of this
- *  function.
- *
- *  @param  vendor_id           USB vendor id or 0 if unknown
- *  @param  product_id          USB product id or 0 if unknown
- *  @param  vendor_name         Set to pointer of result or NULL
- *  @param  product_name        Set to pointer of result or NULL
- */
-void
-ids_find_usb (int vendor_id, int product_id,
-	      char **vendor_name, char **product_name)
-{
-	char *line;
-	unsigned int i;
-	unsigned int line_len;
-	unsigned int num_tabs;
-	char rep_vi[8];
-	char rep_pi[8];
-	static char store_vn[USB_IDS_MAX_LINE_LEN];
-	static char store_pn[USB_IDS_MAX_LINE_LEN];
-	dbus_bool_t vendor_matched = FALSE;
-
-	snprintf (rep_vi, 8, "%04x", vendor_id);
-	snprintf (rep_pi, 8, "%04x", product_id);
-
-	*vendor_name = NULL;
-	*product_name = NULL;
-
-	for (usb_ids_line_iter_init (); usb_ids_line_iter_has_more ();) {
-		line = usb_ids_line_iter_get_line (&line_len);
-
-		/* skip lines with no content */
-		if (line_len < 4)
-			continue;
-
-		/* skip comments */
-		if (line[0] == '#')
-			continue;
-
-		/* count number of tabs */
-		num_tabs = 0;
-		for (i = 0; i < line_len; i++) {
-			if (line[i] != '\t')
-				break;
-			num_tabs++;
-		}
-
-		switch (num_tabs) {
-		case 0:
-			/* vendor names */
-			vendor_matched = FALSE;
-
-			/* check vendor_id */
-			if (vendor_id != 0) {
-				if (memcmp (line, rep_vi, 4) == 0) {
-					/* found it */
-					vendor_matched = TRUE;
-
-					for (i = 4; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_vn, line + i,
-						 USB_IDS_MAX_LINE_LEN);
-					*vendor_name = store_vn;
-				}
-			}
-			break;
-
-		case 1:
-			/* product names */
-			if (!vendor_matched)
-				continue;
-
-			/* check product_id */
-			if (product_id != 0) {
-				if (memcmp (line + 1, rep_pi, 4) == 0) {
-					/* found it */
-					for (i = 5; i < line_len; i++) {
-						if (!isspace (line[i]))
-							break;
-					}
-					strncpy (store_pn, line + i,
-						 USB_IDS_MAX_LINE_LEN);
-					*product_name = store_pn;
-
-					/* no need to continue the search */
-					return;
-				}
-			}
-			break;
-
-		default:
-			break;
-		}
-
-	}
-}
-
-/** Free resources used by to store the USB database
- *
- *  @param                      #FALSE if the USB database wasn't loaded
- */
-static dbus_bool_t
-usb_ids_free ()
-{
-	if (usb_ids != NULL) {
-		free (usb_ids);
-		usb_ids = NULL;
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/** Load the USB database used for mapping vendor, product, subsys_vendor
- *  and subsys_product numbers into names.
- *
- *  @param  path                Path of the usb.ids file, e.g. 
- *                              /usr/share/hwdata/usb.ids
- *  @return                     #TRUE if the file was succesfully loaded
- */
-static dbus_bool_t
-usb_ids_load (const char *path)
-{
-	FILE *fp;
-	unsigned int num_read;
-
-	fp = fopen (path, "r");
-	if (fp == NULL) {
-		printf ("couldn't open USB database at %s,", path);
-		return FALSE;
-	}
-
-	fseek (fp, 0, SEEK_END);
-	usb_ids_len = ftell (fp);
-	fseek (fp, 0, SEEK_SET);
-
-	usb_ids = malloc (usb_ids_len);
-	if (usb_ids == NULL) {
-		printf
-		    ("Couldn't allocate %d bytes for USB database file\n",
-		     usb_ids_len);
-		fclose(fp);
-		return FALSE;
-	}
-
-	num_read = fread (usb_ids, sizeof (char), usb_ids_len, fp);
-	if (usb_ids_len != num_read) {
-		printf ("Error loading USB database file\n");
-		usb_ids_free ();
-		fclose(fp);
-		return FALSE;
-	}
-
-	fclose(fp);
-	return TRUE;
-}
-
-
-void 
-ids_init (void)
-{
-	/* Load /usr/share/hwdata/pci.ids */
-	pci_ids_load (HWDATA_DIR "/pci.ids");
-
-	/* Load /usr/share/hwdata/usb.ids */
-	usb_ids_load (HWDATA_DIR "/usb.ids");
-}
-
-
-/* This, somewhat incomplete, list is from this sources:
- * http://www.plasma-online.de/english/identify/serial/pnp_id_pnp.html 
- * http://www-pc.uni-regensburg.de/hardware/TECHNIK/PCI_PNP/pnpid.txt
- *
- * Keep this sorted!
- */
-static char *pnp_ids_list[] = {
-	/* Crystal Semiconductor devices */
-	"CSC0000", "Crystal Semiconductor CS423x sound -- SB/WSS/OPL3 emulation",
-	"CSC0010", "Crystal Semiconductor CS423x sound -- control",
-	"CSC0001", "Crystal Semiconductor CS423x sound -- joystick",
-	"CSC0003", "Crystal Semiconductor CS423x sound -- MPU401",
-	/* IBM devices */
-	"IBM3780", "IBM pointing device",
-	"IBM0071", "IBM infrared communications device",
-	"IBM3760", "IBM DSP",
-	/* interrupt controllers */
-	"PNP0000", "AT Interrupt Controller",
-	"PNP0001", "EISA Interrupt Controller",
-	"PNP0002", "MCA Interrupt Controller",
-	"PNP0003", "APIC",
-	"PNP0004", "Cyrix SLiC MP interrupt controller",
-	/* timers */
-	"PNP0100", "AT Timer",
-	"PNP0101", "EISA Timer",
-	"PNP0102", "MCA Timer",
-	/* DMA controllers */
-	"PNP0200", "AT DMA Controller",
-	"PNP0201", "EISA DMA Controller",
-	"PNP0202", "MCA DMA Controller",
-	/* keyboards */
-	"PNP0300", "IBM PC/XT keyboard controller (83-key)",
-	"PNP0301", "IBM PC/AT keyboard controller (86-key)",
-	"PNP0302", "IBM PC/XT keyboard controller (84-key)",
-	"PNP0303", "IBM Enhanced (101/102-key, PS/2 mouse support)",
-	"PNP0304", "Olivetti Keyboard (83-key)",
-	"PNP0305", "Olivetti Keyboard (102-key)",
-	"PNP0306", "Olivetti Keyboard (86-key)",
-	"PNP0307", "Microsoft Windows(R) Keyboard",
-	"PNP0308", "General Input Device Emulation Interface (GIDEI) legacy",
-	"PNP0309", "Olivetti Keyboard (A101/102 key)",
-	"PNP030A", "AT&T 302 keyboard",
-	"PNP030B", "Reserved by Microsoft",
-	"PNP0320", "Japanese 101-key keyboard",
-	"PNP0321", "Japanese AX keyboard",
-	"PNP0322", "Japanese 106-key keyboard A01",
-	"PNP0323", "Japanese 106-key keyboard 002/003",
-	"PNP0324", "Japanese 106-key keyboard 001",
-	"PNP0325", "Japanese Toshiba Desktop keyboard",
-	"PNP0326", "Japanese Toshiba Laptop keyboard",
-	"PNP0327", "Japanese Toshiba Notebook keyboard",
-	"PNP0340", "Korean 84-key keyboard",
-	"PNP0341", "Korean 86-key keyboard",
-	"PNP0342", "Korean Enhanced keyboard",
-	"PNP0343", "Korean Enhanced keyboard 101b",
-	"PNP0343", "Korean Enhanced keyboard 101c",
-	"PNP0344", "Korean Enhanced keyboard 103",
-	/* parallel ports */
-	"PNP0400", "Standard LPT printer port",
-	"PNP0401", "ECP printer port",
-	/* serial ports */
-	"PNP0500", "Standard PC COM port",
-	"PNP0501", "16550A-compatible COM port",
-	"PNP0502", "Multiport serial device (non-intelligent 16550)",
-	"PNP0510", "Generic IRDA-compatible device",
-	"PNP0511", "Generic IRDA-compatible device",
-	/* IDE controller */
-	"PNP0600", "Generic ESDI/IDE/ATA compatible hard disk controller",
-	"PNP0601", "Plus Hardcard II",
-	"PNP0602", "Plus Hardcard IIXL/EZ",
-	"PNP0603", "Generic IDE supporting Microsoft Device Bay Specification",
-	"PNP0680", "Bus Master E-IDE controller",
-	/* floppy controllers */
-	"PNP0604", "PC standard floppy disk controller",
-	"PNP0605", "HP Omnibook floppy disk controller",
-	"PNP0700", "PC standard floppy disk controller",
-	"PNP0701", "Standard floppy controller supporting MS Device Bay Spec",
-	/* obsolete devices */
-	"PNP0802", "Microsoft Sound System compatible device (obsolete, use PNPB0xx instead)",
-	/* display adapters / graphic cards */
-	"PNP0900", "VGA Compatible",
-	"PNP0901", "Video Seven VRAM/VRAM II/1024i",
-	"PNP0902", "IBM 8514/A Compatible",
-	"PNP0903", "Trident VGA",
-	"PNP0904", "Cirrus Logic Laptop VGA",
-	"PNP0905", "Cirrus Logic VGA",
-	"PNP0906", "Tseng Labs ET4000",
-	"PNP0907", "Western Digital VGA",
-	"PNP0908", "Western Digital Laptop VGA",
-	"PNP0909", "S3 Inc. 911/924",
-	"PNP090A", "ATI Ultra Pro/Plus (Mach 32)",
-	"PNP090B", "ATI Ultra (Mach 8)",
-	"PNP090C", "IBM XGA Compatible",
-	"PNP090D", "ATI VGA Wonder",
-	"PNP090E", "Weitek P9000 Graphics Adapter",
-	"PNP090F", "Oak Technology VGA",
-	"PNP0910", "Compaq QVision",
-	"PNP0911", "IBM XGA/2",
-	"PNP0912", "Tseng Labs ET4000 W32/W32i/W32p",
-	"PNP0913", "S3 Inc. 801/928/964",
-	"PNP0914", "Cirrus Logic 5429/5434 (memory mapped)",
-	"PNP0915", "Compaq Advanced VGA (AVGA)",
-	"PNP0916", "ATI Ultra Pro Turbo (Mach64)",
-	"PNP0917", "Reserved by Microsoft",
-	"PNP0918", "Matrox MGA",
-	"PNP0919", "Compaq QVision 2000",
-	"PNP091A", "Tseng Labs W128",
-	"PNP0930", "Chips & Technologies Super VGA",
-	"PNP0931", "Chips & Technologies Accelerator",
-	"PNP0940", "NCR 77c22e Super VGA",
-	"PNP0941", "NCR 77c32blt",
-	"PNP09FF", "Plug and Play Monitors (VESA DDC)",
-	/* peripheral buses */
-	"PNP0A00", "ISA Bus",
-	"PNP0A01", "EISA Bus",
-	"PNP0A02", "MCA Bus",
-	"PNP0A03", "PCI Bus",
-	"PNP0A04", "VESA/VL Bus",
-	"PNP0A05", "Generic ACPI Bus",
-	"PNP0A06", "Generic ACPI Extended-IO Bus (EIO bus)",
-	/* system devices */
-	"PNP0800", "AT-style speaker sound",
-	"PNP0B00", "AT Real-Time Clock",
-	"PNP0C00", "Plug and Play BIOS (only created by the root enumerator)",
-	"PNP0C01", "System Board",
-	"PNP0C02", "General ID for reserving resources required by PnP motherboard registers. (Not device specific.)",
-	"PNP0C03", "Plug and Play BIOS Event Notification Interrupt",
-	"PNP0C04", "Math Coprocessor",
-	"PNP0C05", "APM BIOS (Version independent)",
-	"PNP0C06", "Reserved for identification of early Plug and Play BIOS implementation",
-	"PNP0C07", "Reserved for identification of early Plug and Play BIOS implementation",
-	"PNP0C08", "ACPI system board hardware",
-	"PNP0C09", "ACPI Embedded Controller",
-	"PNP0C0A", "ACPI Control Method Battery",
-	"PNP0C0B", "ACPI Fan",
-	"PNP0C0C", "ACPI power button device",
-	"PNP0C0D", "ACPI lid device",
-	"PNP0C0E", "ACPI sleep button device",
-	"PNP0C0F", "PCI interrupt link device",
-	"PNP0C10", "ACPI system indicator device",
-	"PNP0C11", "ACPI thermal zone",
-	"PNP0C12", "Device Bay Controller",
-	"PNP0C13", "Plug and Play BIOS (used when ACPI mode cannot be used)",
-	"PNP0CF0", "Compaq LTE Lite Support",
-	"PNP0CF1", "Compaq LTE Elite Support",
-	/* PCMCIA controllers */
-	"PNP0E00", "Intel 82365-Compatible PCMCIA Controller",
-	"PNP0E01", "Cirrus Logic CL-PD6720 PCMCIA Controller",
-	"PNP0E02", "VLSI VL82C146 PCMCIA Controller",
-	"PNP0E03", "Intel 82365-compatible CardBus controller",
-	/* mice */
-	"PNP0F00", "Microsoft Bus Mouse",
-	"PNP0F01", "Microsoft Serial Mouse",
-	"PNP0F02", "Microsoft InPort Mouse",
-	"PNP0F03", "Microsoft PS/2-style Mouse",
-	"PNP0F04", "Mouse Systems Mouse",
-	"PNP0F05", "Mouse Systems 3-Button Mouse (COM2)",
-	"PNP0F06", "Genius Mouse (COM1)",
-	"PNP0F07", "Genius Mouse (COM2)",
-	"PNP0F08", "Logitech Serial Mouse",
-	"PNP0F09", "Microsoft BallPoint Serial Mouse",
-	"PNP0F0A", "Microsoft Plug and Play Mouse",
-	"PNP0F0B", "Microsoft Plug and Play BallPoint Mouse",
-	"PNP0F0C", "Microsoft-compatible Serial Mouse",
-	"PNP0F0D", "Microsoft-compatible InPort-compatible Mouse",
-	"PNP0F0E", "Microsoft-compatible PS/2-style Mouse",
-	"PNP0F0F", "Microsoft-compatible Serial BallPoint-compatible Mouse",
-	"PNP0F10", "Texas Instruments QuickPort Mouse",
-	"PNP0F11", "Microsoft-compatible Bus Mouse",
-	"PNP0F12", "Logitech PS/2-style Mouse",
-	"PNP0F13", "PS/2 Port for PS/2-style Mice",
-	"PNP0F14", "Microsoft Kids Mouse",
-	"PNP0F15", "Logitech bus mouse",
-	"PNP0F16", "Logitech SWIFT device",
-	"PNP0F17", "Logitech-compatible serial mouse",
-	"PNP0F18", "Logitech-compatible bus mouse",
-	"PNP0F19", "Logitech-compatible PS/2-style Mouse",
-	"PNP0F1A", "Logitech-compatible SWIFT Device",
-	"PNP0F1B", "HP Omnibook Mouse",
-	"PNP0F1C", "Compaq LTE Trackball PS/2-style Mouse",
-	"PNP0F1D", "Compaq LTE Trackball Serial Mouse",
-	"PNP0F1E", "Microsoft Kids Trackball Mouse",
-	"PNP0F1F", "Reserved by Microsoft Input Device Group",
-	"PNP0F20", "Reserved by Microsoft Input Device Group",
-	"PNP0F21", "Reserved by Microsoft Input Device Group",
-	"PNP0F22", "Reserved by Microsoft Input Device Group",
-	"PNP0F23", "Reserved by Microsoft Input Device Group",
-	"PNP0FFF", "Reserved by Microsoft Systems",
-	"PNP0XXX", "Unknown System Device",
-	/* network cards */
-	"PNP8000", "Network Adapter",
-	"PNP8001", "Novell/Anthem NE3200",
-	"PNP8004", "Compaq NE3200",
-	"PNP8006", "Intel EtherExpress/32",
-	"PNP8008", "HP EtherTwist EISA LAN Adapter/32 (HP27248A)",
-	"PNP8065", "Ungermann-Bass NIUps or NIUps/EOTP",
-	"PNP8072", "DEC (DE211) EtherWorks MC/TP",
-	"PNP8073", "DEC (DE212) EtherWorks MC/TP_BNC",
-	"PNP8074", "HP MC LAN Adapter/16 TP (PC27246)",
-	"PNP8078", "DCA 10 Mb MCA",
-	"PNP807F", "Racal NI9210",
-	"PNP8081", "Pure Data Ethernet",
-	"PNP8096", "Thomas-Conrad TC4046",
-	"PNP80C9", "IBM Token Ring",
-	"PNP80CA", "IBM Token Ring II",
-	"PNP80CB", "IBM Token Ring II/Short",
-	"PNP80CC", "IBM Token Ring 4/16Mbs",
-	"PNP80D3", "Novell/Anthem NE1000",
-	"PNP80D4", "Novell/Anthem NE2000",
-	"PNP80D5", "NE1000 Compatible",
-	"PNP80D6", "NE2000 Compatible",
-	"PNP80D7", "Novell/Anthem NE1500T",
-	"PNP80D8", "Novell/Anthem NE2100",
-	"PNP80D9", "NE2000 Plus",
-	"PNP80DD", "SMC ARCNETPC",
-	"PNP80DE", "SMC ARCNET PC100, PC200",
-	"PNP80DF", "SMC ARCNET PC110, PC210, PC250",
-	"PNP80E0", "SMC ARCNET PC130/E",
-	"PNP80E1", "SMC ARCNET PC120, PC220, PC260",
-	"PNP80E2", "SMC ARCNET PC270/E",
-	"PNP80E5", "SMC ARCNET PC600W, PC650W",
-	"PNP80E7", "DEC DEPCA",
-	"PNP80E8", "DEC (DE100) EtherWorks LC",
-	"PNP80E9", "DEC (DE200) EtherWorks Turbo",
-	"PNP80EA", "DEC (DE101) EtherWorks LC/TP",
-	"PNP80EB", "DEC (DE201) EtherWorks Turbo/TP",
-	"PNP80EC", "DEC (DE202) EtherWorks Turbo/TP_BNC",
-	"PNP80ED", "DEC (DE102) EtherWorks LC/TP_BNC",
-	"PNP80EE", "DEC EE101 (Built-In)",
-	"PNP80EF", "DEC PC 433 WS (Built-In)",
-	"PNP80F1", "3Com EtherLink Plus",
-	"PNP80F3", "3Com EtherLink II or IITP (8 or 16-bit)",
-	"PNP80F4", "3Com TokenLink",
-	"PNP80F6", "3Com EtherLink 16",
-	"PNP80F7", "3Com EtherLink III",
-	"PNP80F8", "3Com Generic Etherlink Plug and Play Device",
-	"PNP80FB", "Thomas Conrad TC6045",
-	"PNP80FC", "Thomas Conrad TC6042",
-	"PNP80FD", "Thomas Conrad TC6142",
-	"PNP80FE", "Thomas Conrad TC6145",
-	"PNP80FF", "Thomas Conrad TC6242",
-	"PNP8100", "Thomas Conrad TC6245",
-	"PNP8101", "Thomas-Conrad TC4045",
-	"PNP8104", "Thomas-Conrad TC4035",
-	"PNP8105", "DCA 10 MB",
-	"PNP8106", "DCA 10 MB Fiber Optic",
-	"PNP8107", "DCA 10 MB Twisted Pair",
-	"PNP8113", "Racal NI6510",
-	"PNP8114", "Racal NI5210/8 or NI5210/16",
-	"PNP8119", "Ungermann-Bass pcNIU",
-	"PNP811A", "Ungermann-Bass pcNIU/ex 128K",
-	"PNP811B", "Ungermann-Bass pcNIU/ex 512K", 
-	"PNP811C", "Ungermann-Bass NIUpc",
-	"PNP811D", "Ungermann-Bass NIUpc/3270",
-	"PNP8120", "Ungermann-Bass NIUpc/EOTP",
-	"PNP8123", "SMC StarCard PLUS (WD/8003S)",
-	"PNP8124", "SMC StarCard PLUS With On Board Hub (WD/8003SH)",
-	"PNP8125", "SMC EtherCard PLUS (WD/8003E)",
-	"PNP8126", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EBT)",
-	"PNP8127", "SMC EtherCard PLUS With Boot ROM Socket (WD/8003EB)",
-	"PNP8128", "SMC EtherCard PLUS TP (WD/8003WT)",
-	"PNP812A", "SMC EtherCard PLUS 16 With Boot ROM Socket (WD/8013EBT)",
-	"PNP812D", "Intel EtherExpress 16 or 16TP",
-	"PNP812F", "Intel TokenExpress 16/4",
-	"PNP8130", "Intel TokenExpress MCA 16/4",
-	"PNP8132", "Intel EtherExpress 16 (MCA)",
-	"PNP8133", "Compaq Ethernet 16E",
-	"PNP8137", "Artisoft AE-1",
-	"PNP8138", "Artisoft AE-2 or AE-3",
-	"PNP8141", "Amplicard AC 210/XT",
-	"PNP8142", "Amplicard AC 210/AT",
-	"PNP814B", "Everex SpeedLink /PC16 (EV2027)",
-	"PNP8155", "HP PC LAN Adapter/8 TP (HP27245)",
-	"PNP8156", "HP PC LAN Adapter/16 TP (HP27247A)",
-	"PNP8157", "HP PC LAN Adapter/8 TL (HP27250)",
-	"PNP8158", "HP PC LAN Adapter/16 TP Plus (HP27247B)",
-	"PNP8159", "HP PC LAN Adapter/16 TL Plus (HP27252)",
-	"PNP815F", "National Semiconductor Ethernode *16AT",
-	"PNP8160", "National Semiconductor AT/LANTIC EtherNODE 16-AT3",
-	"PNP8169", "NCR StarCard",
-	"PNP816A", "NCR Token-Ring 4 Mbs ISA",
-	"PNP816B", "NCR WaveLAN AT",
-	"PNP816C", "NCR WaveLan MC",
-	"PNP816D", "NCR Token-Ring 16/4 Mbs ISA",
-	"PNP8191", "Olicom 16/4 Token-Ring Adapter",
-	"PNP81A5", "Research Machines Ethernet",
-	"PNP81B9", "ToshibaLAN (internal)",
-	"PNP81C3", "SMC EtherCard PLUS Elite (WD/8003EP)",
-	"PNP81C4", "SMC EtherCard PLUS 10T (WD/8003W)",
-	"PNP81C5", "SMC EtherCard PLUS Elite 16 (WD/8013EP)",
-	"PNP81C6", "SMC EtherCard PLUS Elite 16T (WD/8013W)",
-	"PNP81C7", "SMC EtherCard PLUS Elite 16 Combo (WD/8013EW or 8013EWC)",
-	"PNP81C8", "SMC EtherElite Ultra 16",
-	"PNP81C9", "SMC TigerCard (8216L, 8216LC, 8216LT)",
-	"PNP81CA", "SMC EtherEZ (8416)",
-	"PNP81D7", "Madge Smart 16/4 PC Ringnode",
-	"PNP81D8", "Madge Smart 16/4 Ringnode ISA",
-	"PNP81E4", "Pure Data PDI9025-32 (Token Ring)",
-	"PNP81E6", "Pure Data PDI508+ (ArcNet)",
-	"PNP81E7", "Pure Data PDI516+ (ArcNet)",
-	"PNP81EB", "Proteon Token Ring (P1390)",
-	"PNP81EC", "Proteon Token Ring (P1392)",
-	"PNP81ED", "Proteon Token Ring ISA (P1340)",
-	"PNP81EE", "Proteon Token Ring ISA (P1342)",
-	"PNP81EF", "Proteon Token Ring ISA (P1346)",
-	"PNP81F0", "Proteon Token Ring ISA (P1347)",
-	"PNP81FF", "Cabletron E2000 Series DNI",
-	"PNP8200", "Cabletron E2100 Series DNI",
-	"PNP8201", "Cabletron T2015 4/16 Mbit/s DNI",
-	"PNP8209", "Zenith Data Systems Z-Note",
-	"PNP820A", "Zenith Data Systems NE2000-Compatible",
-	"PNP8213", "Xircom Pocket Ethernet II",
-	"PNP8214", "Xircom Pocket Ethernet I",
-	"PNP8215", "Xircom Pocket Ethernet III Adapter",
-	"PNP821D", "RadiSys EXM-10",
-	"PNP8227", "SMC 3000 Series",
-	"PNP8228", "SMC 91C2 controller",
-	"PNP8231", "AMD AM2100/AM1500T",
-	"PNP824F", "RCE 10Base-T (16 bit)",
-	"PNP8250", "RCE 10Base-T (8 bit)",
-	"PNP8263", "Tulip NCC-16",
-	"PNP8277", "Exos 105",
-	"PNP828A", "Intel '595 based Ethernet",
-	"PNP828B", "TI2000-style Token Ring",
-	"PNP828C", "AMD PCNet Family cards",
-	"PNP828D", "AMD PCNet32 (VL version)",
-	"PNP8294", "IrDA Infrared NDIS driver (Microsoft-supplied)",
-	"PNP82BD", "IBM PCMCIA-NIC",
-	"PNP82C0", "Eagle Technology NE200T",
-	"PNP82C2", "Xircom CE10",
-	"PNP82C3", "Xircom CEM2",
-	"PNP82C4", "Xircom CE2",
-	"PNP8321", "DEC Ethernet (All Types)",
-	"PNP8323", "SMC EtherCard (All Types except 8013/A)",
-	"PNP8324", "ARCNET Compatible",
-	"PNP8325", "SMC TokenCard PLUS (8115T)",
-	"PNP8326", "Thomas Conrad (All Arcnet Types)",
-	"PNP8327", "IBM Token Ring (All Types)",
-	"PNP8328", "Ungermann-Bass NIU",
-	"PNP8329", "Proteon ProNET-4/16 ISA Token Ring (P1392+,P1392,1390)",
-	"PNP8385", "Remote Network Access [RNA] Driver",
-	"PNP8387", "Remote Network Access [RNA] PPP Driver",
-	"PNP8388", "Reserved for Microsoft Networking components",
-	"PNP8389", "Peer IrLAN infrared driver (Microsoft-supplied)",
-	"PNP8390", "Generic network adapter",
-	"PNP8XXX", "Unknown Network Adapter",
-	"PNPD300", "SK-NET TR4/16+ Token-Ring",
-	"PNPE000", "SK-NET G16, G16/TP Ethernet",
-	"PNPF000", "SK-NET FDDI-FI FDDI LAN",
-	/* CD controller */
-	"PNPA000", "Adaptec 154x compatible SCSI controller",
-	"PNPA001", "Adaptec 174x compatible SCSI controller",
-	"PNPA002", "Future Domain 16-700 compatible controller",
-	"PNPA003", "Mitsumi CD-ROM adapter (Panasonic spec., used on SBPro/SB16)",
-	"PNPA01B", "Trantor 128 SCSI Controller",
-	"PNPA01D", "Trantor T160 SCSI Controller",
-	"PNPA01E", "Trantor T338 Parallel SCSI controller",
-	"PNPA01F", "Trantor T348 Parallel SCSI controller",
-	"PNPA020", "Trantor Media Vision SCSI controller",
-	"PNPA022", "Always IN-2000 SCSI controller",
-	"PNPA02B", "Sony proprietary CD-ROM controller",
-	"PNPA02D", "Trantor T13b 8-bit SCSI controller",
-	"PNPA02F", "Trantor T358 Parallel SCSI controller",
-	"PNPA030", "Mitsumi LU-005 Single Speed CD-ROM controller + drive",
-	"PNPA031", "Mitsumi FX-001 Single Speed CD-ROM controller + drive",
-	"PNPA032", "Mitsumi FX-001 Double Speed CD-ROM controller + drive",
-	"PNPAXXX", "Unknown SCSI, Proprietary CD Adapter",
-	/* multimedia devices */
-	"PNPB000", "Creative Labs Sound Blaster 1.5 (or compatible sound device)",
-	"PNPB001", "Creative Labs Sound Blaster 2.0 (or compatible sound device)",
-	"PNPB002", "Creative Labs Sound Blaster Pro (or compatible sound device)",
-	"PNPB003", "Creative Labs Sound Blaster 16 (or compatible sound device)",
-	"PNPB004", "MediaVision Thunderboard (or compatible sound device)",
-	"PNPB005", "Adlib-compatible FM synthesizer device",
-	"PNPB006", "MPU401 compatible",
-	"PNPB007", "Microsoft Windows Sound System-compatible sound device",
-	"PNPB008", "Compaq Business Audio",
-	"PNPB009", "Plug and Play Microsoft Windows Sound System Device",
-	"PNPB00A", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)",
-	"PNPB00B", "MediaVision Pro Audio 3D",
-	"PNPB00C", "MusicQuest MQX-32M",
-	"PNPB00D", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)",
-	"PNPB00E", "MediaVision Pro Audio Spectrum (Trantor SCSI enabled, Thunder Chip Disabled)",
-	"PNPB00F", "MediaVision Jazz-16 chipset (OEM Versions)",
-	"PNPB010", "Orchid Videola - Auravision VxP500 chipset",
-	"PNPB018", "MediaVision Pro Audio Spectrum 8-bit",
-	"PNPB019", "MediaVision Pro Audio Spectrum Basic (No Trantor SCSI, Thunder Chip Enabled)",
-	"PNPB020", "Yamaha OPL3-compatible FM synthesizer device",
-	"PNPB02F", "Joystick/Game port",
-	"PNPB077", "OAK Mozart Sound System",
-	"PNPB078", "OAK Mozart Sound System MPU-401",
-	"PNPBXXX", "Unknown Multimedia Device",
-	/* modems */
-	"PNP9000", "Modem",
-	"PNPC000", "Compaq 14400 Modem (TBD)",
-	"PNPC001", "Compaq 2400/9600 Modem (TBD)",
-	"PNPCXXX", "Unknown Modem",
-	/* Toshiba devices */
-	"TOS6200", "Toshiba Notebook Extra HCI driver",
-	"TOS6202", "Toshiba Notebook Extra HCI driver",
-	"TOS6207", "Toshiba Notebook Extra HCI driver",
-	"TOS7400", "Toshiba AcuPoint",
-	/* Wacom devices */
-	"WACf004", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
-	"WACf005", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
-	"WACf006", "Wacom Serial Tablet PC Pen Tablet/Digitizer",
-	NULL
-};
-
-
-void
-ids_find_pnp (const char *pnp_id, char **pnp_description)
-{
-	unsigned int i;
-
-	/* OK, so someone should optimize this lookup - send me patches */
-	for (i = 0; pnp_ids_list[2*i] != NULL; i++) {
-		if (strcasecmp (pnp_id, pnp_ids_list[2*i]) == 0) {
-			*pnp_description = pnp_ids_list[2*i + 1];
-			return;
-		}
-	}
-
-	*pnp_description = NULL;
-}
diff --git a/hald/linux2/ids.h b/hald/linux2/ids.h
deleted file mode 100644
index c189320..0000000
--- a/hald/linux2/ids.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * ids.h : Lookup names from hardware identifiers
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef IDS_H
-#define IDS_H
-
-#include <glib.h>
-
-void ids_init (void);
-
-void
-ids_find_pci (int vendor_id, int product_id,
-	      int subsys_vendor_id, int subsys_product_id,
-	      char **vendor_name, char **product_name,
-	      char **subsys_vendor_name, char **subsys_product_name);
-
-void
-ids_find_usb (int vendor_id, int product_id,
-	      char **vendor_name, char **product_name);
-
-void
-ids_find_pnp (const char *pnp_id, char **pnp_description);
-
-
-#endif /* IDS_H */
diff --git a/hald/linux2/osspec.c b/hald/linux2/osspec.c
deleted file mode 100644
index 9571d25..0000000
--- a/hald/linux2/osspec.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * osspec.c : New and improved HAL backend for Linux 2.6
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005,2006 Kay Sievers, <kay.sievers at vrfy.org>
- * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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
-
-#define _GNU_SOURCE 1
-
-#include <ctype.h>
-#include <errno.h>
-#include <limits.h>
-#include <linux/types.h>
-#include <net/if_arp.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <sys/utsname.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../hald.h"
-#include "../hald_dbus.h"
-#include "../hald_runner.h"
-#include "../logger.h"
-#include "../osspec.h"
-#include "../util.h"
-
-#include "acpi.h"
-#include "apm.h"
-#include "blockdev.h"
-#include "coldplug.h"
-#include "hotplug.h"
-#include "ids.h"
-#include "pmu.h"
-
-#include "osspec_linux.h"
-
-static char *hal_sysfs_path;
-static char *hal_proc_path;
-
-const gchar *
-get_hal_sysfs_path (void)
-{
-	return hal_sysfs_path;
-}
-
-const gchar *
-get_hal_proc_path (void)
-{
-	return hal_proc_path;
-}
-
-static gboolean
-hald_udev_data (GIOChannel *source, GIOCondition condition, gpointer user_data)
-{
-	int fd;
-	int retval;
-	struct msghdr smsg;
-	struct cmsghdr *cmsg;
-	struct iovec iov;
-	struct ucred *cred;
-	char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
-
-	char buf[4096];
-	size_t bufpos = 0;
-	const char *action = NULL;
-	HotplugEvent *hotplug_event;
-
-	memset(buf, 0x00, sizeof (buf));
-
-	fd = g_io_channel_unix_get_fd (source);
-
-	iov.iov_base = &buf;
-	iov.iov_len = sizeof (buf);
-
-	memset(&smsg, 0x00, sizeof (struct msghdr));
-	smsg.msg_iov = &iov;
-	smsg.msg_iovlen = 1;
-	smsg.msg_control = cred_msg;
-	smsg.msg_controllen = sizeof (cred_msg);
-
-	retval = recvmsg (fd, &smsg, 0);
-	if (retval <  0) {
-		if (errno != EINTR)
-			HAL_INFO (("Unable to receive message, errno=%d", errno));
-		goto out;
-	}
-	cmsg = CMSG_FIRSTHDR (&smsg);
-	cred = (struct ucred *) CMSG_DATA (cmsg);
-
-	if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) {
-		HAL_INFO (("No sender credentials received, message ignored"));
-		goto out;
-	}
-
-	if (cred->uid != 0) {
-		HAL_INFO (("Sender uid=%i, message ignored", cred->uid));
-		goto out;
-	}
-
-	if (!strstr(buf, "@/")) {
-		HAL_INFO (("invalid message format"));
-		goto out;
-	}
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-
-	while (bufpos < sizeof (buf)) {
-		size_t keylen;
-		char *key;
-		char *str;
-
-		key = &buf[bufpos];
-		keylen = strlen(key);
-		if (keylen == 0)
-			break;
-		bufpos += keylen + 1;
-
-		if (strncmp(key, "ACTION=", 7) == 0)
-			action = &key[7];
-		else if (strncmp(key, "DEVPATH=", 8) == 0)
-			g_snprintf (hotplug_event->sysfs.sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path),
-				    "%s%s", hal_sysfs_path, &key[8]);
-		else if (strncmp(key, "SUBSYSTEM=", 10) == 0)
-			g_strlcpy (hotplug_event->sysfs.subsystem, &key[10], sizeof (hotplug_event->sysfs.subsystem));
-		else if (strncmp(key, "DEVNAME=", 8) == 0)
-			g_strlcpy (hotplug_event->sysfs.device_file, &key[8], sizeof (hotplug_event->sysfs.device_file));
-		else if (strncmp(key, "SEQNUM=", 7) == 0)
-			hotplug_event->sysfs.seqnum = strtoull(&key[7], NULL, 10);
-		else if (strncmp(key, "IFINDEX=", 8) == 0)
-			hotplug_event->sysfs.net_ifindex = strtoul(&key[8], NULL, 10);
-		else if (strncmp(key, "ID_VENDOR=", 10) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[10]);
-			g_strlcpy (hotplug_event->sysfs.vendor, str, sizeof(hotplug_event->sysfs.vendor));
-			g_free (str);
-		} else if (strncmp(key, "ID_MODEL=", 9) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[9]);
-			g_strlcpy (hotplug_event->sysfs.model, str, sizeof(hotplug_event->sysfs.model));
-			g_free (str);
-		} else if (strncmp(key, "ID_REVISION=", 12) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[12]);
-			g_strlcpy (hotplug_event->sysfs.revision, str, sizeof(hotplug_event->sysfs.revision));
-			g_free (str);
-		} else if (strncmp(key, "ID_SERIAL=", 10) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[10]);
-			g_strlcpy (hotplug_event->sysfs.serial, str, sizeof(hotplug_event->sysfs.serial));
-			g_free (str);
-		} else if (strncmp(key, "ID_FS_USAGE=", 12) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[12]);
-			g_strlcpy (hotplug_event->sysfs.fsusage, str, sizeof(hotplug_event->sysfs.fsusage));
-			g_free (str);
-		} else if (strncmp(key, "ID_FS_TYPE=", 11) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[11]);
-			g_strlcpy (hotplug_event->sysfs.fstype, str, sizeof(hotplug_event->sysfs.fstype));
-			g_free (str);
-		} else if (strncmp(key, "ID_FS_VERSION=", 14) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[14]);
-			g_strlcpy (hotplug_event->sysfs.fsversion, str, sizeof(hotplug_event->sysfs.fsversion));
-			g_free (str);
-		} else if (strncmp(key, "ID_FS_UUID=", 11) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[11]);
-			g_strlcpy (hotplug_event->sysfs.fsuuid, str, sizeof(hotplug_event->sysfs.fsuuid));
-			g_free (str);
-		} else if (strncmp(key, "ID_FS_LABEL=", 12) == 0) {
-			str = hal_util_strdup_valid_utf8(&key[12]);
-			g_strlcpy (hotplug_event->sysfs.fslabel, str, sizeof(hotplug_event->sysfs.fslabel));
-			g_free (str);
-		}
-	}
-
-	if (!action) {
-		HAL_INFO (("missing ACTION"));
-		goto invalid;
-	}
-	if (hotplug_event->sysfs.sysfs_path == NULL) {
-		HAL_INFO (("missing DEVPATH"));
-		goto invalid;
-	}
-	if (hotplug_event->sysfs.subsystem == NULL) {
-		HAL_INFO (("missing SUSBSYSTEM"));
-		goto invalid;
-	}
-
-	HAL_INFO (("SEQNUM=%lld, ACTION=%s, SUBSYSTEM=%s, DEVPATH=%s, DEVNAME=%s, IFINDEX=%d",
-		   hotplug_event->sysfs.seqnum, action, hotplug_event->sysfs.subsystem, hotplug_event->sysfs.sysfs_path,
-		   hotplug_event->sysfs.device_file, hotplug_event->sysfs.net_ifindex));
-
-	if (strcmp (action, "add") == 0) {
-		hotplug_event->action = HOTPLUG_ACTION_ADD;
-		hotplug_event_enqueue (hotplug_event);
-		hotplug_event_process_queue ();
-		goto out;
-	}
-
-	if (strcmp (action, "remove") == 0) {
-		hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-		hotplug_event_enqueue (hotplug_event);
-		hotplug_event_process_queue ();
-		goto out;
-	}
-
-invalid:
-	g_free (hotplug_event);
-
-out:
-	return TRUE;
-}
-
-static gboolean
-mount_tree_changed_event (GIOChannel *channel, GIOCondition cond,
-		    gpointer user_data)
-{
-	if (cond & ~G_IO_ERR)
-		return TRUE;
-
-	HAL_INFO (("/proc/mounts tells, that the mount has tree changed"));
-	blockdev_refresh_mount_state (NULL);
-
-	return TRUE;
-}
-
-void
-osspec_init (void)
-{
-	gchar path[HAL_PATH_MAX];
-	int udev_socket;
-	struct sockaddr_un saddr;
-	socklen_t addrlen;
-	const int on = 1;
-	GIOChannel *udev_channel;
-	GIOChannel *mounts_channel;
-
-	/*
-	 * setup socket for listening from messages from udev
-	 */
-	memset(&saddr, 0x00, sizeof(saddr));
-	saddr.sun_family = AF_LOCAL;
-	/* use abstract namespace for socket path */
-	strcpy(&saddr.sun_path[1], "/org/freedesktop/hal/udev_event");
-	addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
-
-	udev_socket = socket(AF_LOCAL, SOCK_DGRAM, 0);
-	if (udev_socket == -1) {
-		DIE (("Couldn't open socket"));
-	}
-
-	if (bind(udev_socket, (struct sockaddr *) &saddr, addrlen) < 0) {
-		fprintf (stderr, "Error binding udev_event socket: %s\n", strerror(errno));
-		exit (1);
-	}
-	/* enable receiving of the sender credentials */
-	setsockopt(udev_socket, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
-
-	udev_channel = g_io_channel_unix_new (udev_socket);
-	g_io_add_watch (udev_channel, G_IO_IN, hald_udev_data, NULL);
-	g_io_channel_unref (udev_channel);
-
-	/*
-	 * set mount points for /proc and /sys, possibly overridden for testing
-	 */
-	hal_sysfs_path = getenv ("SYSFS_PATH");
-	if (hal_sysfs_path == NULL)
-		hal_sysfs_path = "/sys";
-
-	hal_proc_path = getenv ("PROC_PATH");
-	if (hal_proc_path == NULL)
-		hal_proc_path = "/proc";
-
-	/*
-	 * watch /proc/mounts for mount tree changes
-	 * kernel 2.6.15 vfs throws a POLLERR event for every change
-	 */
-	g_snprintf (path, sizeof (path), "%s/mounts", get_hal_proc_path ());
-	mounts_channel = g_io_channel_new_file (path, "r", NULL);
-	if (mounts_channel == NULL)
-		DIE (("Unable to read /proc/mounts"));
-	g_io_add_watch (mounts_channel, G_IO_ERR, mount_tree_changed_event, NULL);
-
-	/*
-	 *Load various hardware id databases
-	 */
-	ids_init ();
-}
-
-static void 
-computer_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
-{
-	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);
-
-	/* start processing events */
-	hotplug_event_process_queue ();
-}
-
-void
-hotplug_queue_now_empty (void)
-{
-	if (hald_is_initialising)
-		osspec_probe_done ();
-}
-
-
-static void
-computer_probing_helper_done (HalDevice *d)
-{
-	di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
-	di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
-
-	hal_util_callout_device_add (d, computer_callouts_add_done, NULL, NULL);
-}
-
-static void 
-computer_probing_pcbios_helper_done (HalDevice *d, guint32 exit_type, 
-	                             gint return_code, gchar **error, 
-				     gpointer data1, gpointer data2)
-{
-	const char *chassis_type;
-	const char *system_manufacturer;
-	const char *system_product;
-	const char *system_version;
-
-	if (exit_type == HALD_RUN_FAILED) {
-		/* set a default value */
-		if (!hal_device_has_property (d, "system.formfactor"))
-			hal_device_property_set_string (d, "system.formfactor", "unknown");
-		goto out;
-	}
-
-	if ((system_manufacturer = hal_device_property_get_string (d, "smbios.system.manufacturer")) != NULL &&
-	    (system_product = hal_device_property_get_string (d, "smbios.system.product")) != NULL &&
-	    (system_version = hal_device_property_get_string (d, "smbios.system.version")) != NULL) {
-		char buf[128];
-
-		hal_device_property_set_string (d, "system.vendor", system_manufacturer);
-
-		if (strcmp(system_version, "Not Specified" ) != 0 ) {
-			g_snprintf (buf, sizeof (buf), "%s %s", system_product, system_version);
-			hal_device_property_set_string (d, "system.product", buf);
-		} else {
-			hal_device_property_set_string (d, "system.product", system_product);
-		}
-	}
-
-
-	if (!hal_device_has_property (d, "system.formfactor")) {
-		/* now map the smbios.* properties to our generic system.formfactor property */
-		if ((chassis_type = hal_device_property_get_string (d, "smbios.chassis.type")) != NULL) {
-			unsigned int i;
-
-			/* Map the chassis type from dmidecode.c to a sensible type used in hal 
-			 *
-			 * See also 3.3.4.1 of the "System Management BIOS Reference Specification, 
-			 * Version 2.3.4" document, available from http://www.dmtf.org/standards/smbios.
-			 *
-			 * TODO: figure out WTF the mapping should be; "Lunch Box"? Give me a break :-)
-			 */
-			static const char *chassis_map[] = {
-				"Other",                 "unknown",
-				"Unknown",               "unknown",
-				"Desktop",               "desktop",
-				"Low Profile Desktop",   "desktop",
-				"Pizza Box",             "server",
-				"Mini Tower",            "desktop",
-				"Tower",                 "desktop",
-				"Portable",              "laptop",
-				"Laptop",                "laptop",
-				"Notebook",              "laptop",
-				"Hand Held",             "handheld",
-				"Docking Station",       "laptop",
-				"All In One",            "unknown",
-				"Sub Notebook",          "laptop",
-				"Space-saving",          "unknown",
-				"Lunch Box",             "unknown",
-				"Main Server Chassis",   "server",
-				"Expansion Chassis",     "unknown",
-				"Sub Chassis",           "unknown",
-				"Bus Expansion Chassis", "unknown",
-				"Peripheral Chassis",    "unknown",
-				"RAID Chassis",          "unknown",
-				"Rack Mount Chassis",    "unknown",
-				"Sealed-case PC",        "unknown",
-				"Multi-system",          "unknown",
-				NULL
-			};
-			
-			for (i = 0; chassis_map[i] != NULL; i += 2) {
-				if (strcmp (chassis_map[i], chassis_type) == 0) {
-					hal_device_property_set_string (d, "system.formfactor", chassis_map[i+1]);
-					break;
-				}
-			}
-		       
-		} else {
-			/* set a default value */
-			hal_device_property_set_string (d, "system.formfactor", "unknown");
-		}
-	}
-out:
-	computer_probing_helper_done (d);
-}
-
-static void
-set_suspend_hibernate_keys (HalDevice *d)
-{
-	int can_suspend;
-	int can_hibernate;
-	ssize_t read;
-	size_t len;
-	char *poweroptions;
-	FILE *fp;
-
-	can_suspend = FALSE;
-	can_hibernate = FALSE;
-
-	/* try to find 'mem' and 'disk' in /sys/power/state */
-	fp = fopen ("/sys/power/state", "r");
-	if (fp == NULL) {
-		HAL_WARNING (("Could not open /sys/power/state"));
-		goto out;
-	}
-	poweroptions = NULL;
-	len = 0;
-	read = getline (&poweroptions, &len, fp);
-	fclose (fp);
-	if (poweroptions == NULL) {
-		HAL_WARNING (("Contents of /sys/power/state invalid"));
-		goto out;
-	}
-	if (strstr (poweroptions, "mem"))
-		can_suspend = TRUE;
-	if (strstr (poweroptions, "disk"))
-		can_hibernate = TRUE;
-	free (poweroptions);
-
-	/* check for the presence of suspend2 */
-	if (access ("/proc/software_suspend", F_OK) == 0)
-		can_hibernate = TRUE;
-	if (access ("/proc/suspend2", F_OK) == 0)
-		can_hibernate = TRUE;
-	if (access ("/sys/power/suspend2/version", F_OK) == 0)
-		can_hibernate = TRUE;
-out:
-	hal_device_property_set_bool (d, "power_management.can_suspend", can_suspend);
-	hal_device_property_set_bool (d, "power_management.can_hibernate", can_hibernate);
-
-	/* WARNING: These keys are depreciated and power_management.can_suspend
-	 * and power_management.can_hibernate should be used instead.
-	 * These properties will be removed, but not before May 1st 2007. */
-	hal_device_property_set_bool (d, "power_management.can_suspend_to_ram", can_suspend);
-	hal_device_property_set_bool (d, "power_management.can_suspend_to_disk", can_hibernate);
-}
-
-void 
-osspec_probe (void)
-{
-	HalDevice *root;
-	struct utsname un;
-	gboolean should_decode_dmi;
-
-	should_decode_dmi = FALSE;
-
-	root = hal_device_new ();
-	hal_device_property_set_string (root, "info.bus", "unknown");
-	hal_device_property_set_string (root, "linux.sysfs_path_device", "(none)");
-	hal_device_property_set_string (root, "info.product", "Computer");
-	hal_device_property_set_string (root, "info.udi", "/org/freedesktop/Hal/devices/computer");
-	hal_device_set_udi (root, "/org/freedesktop/Hal/devices/computer");
-
-	if (uname (&un) >= 0) {
-		hal_device_property_set_string (root, "system.kernel.name", un.sysname);
-		hal_device_property_set_string (root, "system.kernel.version", un.release);
-		hal_device_property_set_string (root, "system.kernel.machine", un.machine);
-	}
-
-	/* Let computer be in TDL while synthesizing all other events because some may write to the object */
-	hal_device_store_add (hald_get_tdl (), root);
-
-	/* will enqueue hotplug events for entire system */
-	HAL_INFO (("Synthesizing sysfs events..."));
-	coldplug_synthesize_events ();
-
-	HAL_INFO (("Synthesizing powermgmt events..."));
-	if (acpi_synthesize_hotplug_events ()) {
-		HAL_INFO (("ACPI capabilities found"));
-		should_decode_dmi = TRUE;
-	} else if (pmu_synthesize_hotplug_events ()) {
-		HAL_INFO (("PMU capabilities found"));		
-	} else if (apm_synthesize_hotplug_events ()) {
-		HAL_INFO (("APM capabilities found"));		
-		should_decode_dmi = TRUE;
-	} else {
-		HAL_INFO (("No powermgmt capabilities"));		
-	}
-	HAL_INFO (("Done synthesizing events"));
-
-	/*
-	 * Populate the powermgmt keys according to the kernel options.
-	 * NOTE: This may not mean the machine is able to suspend
-	 *	 or hibernate successfully, only that the machine has
-	 *	 support compiled into the kernel.
-	 */
-	set_suspend_hibernate_keys (root);
-
-	/* TODO: add prober for PowerMac's */
-	if (should_decode_dmi) {
-		hald_runner_run (root, "hald-probe-smbios", NULL, HAL_HELPER_TIMEOUT,
-        	                 computer_probing_pcbios_helper_done, NULL, NULL);
-	} else {
-		/* set a default value, can be overridden by others */
-		hal_device_property_set_string (root, "system.formfactor", "unknown");
-		/* no probing */
-		computer_probing_helper_done (root);
-  	}
-}
-
-DBusHandlerResult
-osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
-{
-	return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-gboolean
-osspec_device_rescan (HalDevice *d)
-{
-	return hotplug_rescan_device (d);
-}
-
-gboolean
-osspec_device_reprobe (HalDevice *d)
-{
-	return hotplug_reprobe_tree (d);
-}
-
-gboolean
-hal_util_get_driver_name (const char *sysfs_path, gchar *driver_name)
-{
-	gchar driver_path[HAL_PATH_MAX];
-	struct stat statbuf;
-
-	g_snprintf (driver_path, sizeof (driver_path), "%s/driver", sysfs_path);
-	if (stat (driver_path, &statbuf) == 0) {
-		gchar buf[256];
-		memset (buf, '\0', sizeof (buf));
-		if (readlink (driver_path, buf, sizeof (buf) - 1) > 0) {
-			g_snprintf (driver_name, strlen(buf), "%s", hal_util_get_last_element(buf));
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-gboolean
-hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path)
-{
-	gboolean ret;
-	gchar driver_name[256];
-
-	memset (driver_name, '\0', sizeof (driver_name));
-	ret = hal_util_get_driver_name (sysfs_path, driver_name);
-	if (ret == TRUE)
-		hal_device_property_set_string (d, property_name, driver_name);
-
-	return ret;
-}
-
-/** Find the closest ancestor by looking at sysfs paths
- *
- *  @param  sysfs_path           Path into sysfs, e.g. /sys/devices/pci0000:00/0000:00:1d.7/usb1/1-0:1.0
- *  @return                      Parent Hal Device Object or #NULL if there is none
- */
-HalDevice *
-hal_util_find_closest_ancestor (const gchar *sysfs_path)
-{	
-	gchar buf[512];
-	HalDevice *parent;
-
-	parent = NULL;
-
-	strncpy (buf, sysfs_path, sizeof (buf));
-	do {
-		char *p;
-
-		p = strrchr (buf, '/');
-		if (p == NULL)
-			break;
-		*p = '\0';
-
-		parent = hal_device_store_match_key_value_string (hald_get_gdl (), 
-								  "linux.sysfs_path_device", 
-								  buf);
-		if (parent != NULL)
-			break;
-
-	} while (TRUE);
-
-	return parent;
-}
-
diff --git a/hald/linux2/osspec_linux.h b/hald/linux2/osspec_linux.h
deleted file mode 100644
index 88d516c..0000000
--- a/hald/linux2/osspec_linux.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * osspec_linux.h : OS Specific interface
- *
- * Copyright (C) 2003 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef OSSPEC_LINUX_H
-#define OSSPEC_LINUX_H
-
-#include <glib.h>
-#include "../device.h"
-
-const gchar *get_hal_sysfs_path (void);
-
-const gchar *get_hal_proc_path (void);
-
-gboolean hal_util_get_driver_name (const char *sysfs_path, gchar *driver_name);
-
-gboolean hal_util_set_driver (HalDevice *d, const char *property_name, const char *sysfs_path);
-
-HalDevice *hal_util_find_closest_ancestor (const gchar *sysfs_path);
-
-
-#endif /* OSSPEC_LINUX_H */
diff --git a/hald/linux2/physdev.c b/hald/linux2/physdev.c
deleted file mode 100644
index c2ae795..0000000
--- a/hald/linux2/physdev.c
+++ /dev/null
@@ -1,1707 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * physdev.c : Handling of physical kernel devices 
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <string.h>
-#include <stdint.h>
-#include <unistd.h>
-
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib.h>
-
-#include "../device_info.h"
-#include "../hald.h"
-#include "../logger.h"
-#include "../osspec.h"
-#include "../util.h"
-
-#include "coldplug.h"
-#include "hotplug.h"
-#include "hotplug_helper.h"
-#include "ids.h"
-#include "osspec_linux.h"
-
-#include "physdev.h"
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-pci_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	gint device_class;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "pci");
-	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");
-	}
-
-	hal_device_property_set_string (d, "pci.linux.sysfs_path", sysfs_path);
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_util_set_int_from_file (d, "pci.product_id", sysfs_path, "device", 16);
-	hal_util_set_int_from_file (d, "pci.vendor_id", sysfs_path, "vendor", 16);
-	hal_util_set_int_from_file (d, "pci.subsys_product_id", sysfs_path, "subsystem_device", 16);
-	hal_util_set_int_from_file (d, "pci.subsys_vendor_id", sysfs_path, "subsystem_vendor", 16);
-
-	if (hal_util_get_int_from_file (sysfs_path, "class", &device_class, 16)) {
-		hal_device_property_set_int (d, "pci.device_class", ((device_class >> 16) & 0xff));
-		hal_device_property_set_int (d, "pci.device_subclass", ((device_class >> 8) & 0xff));
-		hal_device_property_set_int (d, "pci.device_protocol", (device_class & 0xff));
-	}
-
-	{
-		gchar buf[64];
-		char *vendor_name;
-		char *product_name;
-		char *subsys_vendor_name;
-		char *subsys_product_name;
-
-		ids_find_pci (hal_device_property_get_int (d, "pci.vendor_id"), 
-			      hal_device_property_get_int (d, "pci.product_id"), 
-			      hal_device_property_get_int (d, "pci.subsys_vendor_id"), 
-			      hal_device_property_get_int (d, "pci.subsys_product_id"), 
-			      &vendor_name, &product_name, &subsys_vendor_name, &subsys_product_name);
-
-		if (vendor_name != NULL) {
-			hal_device_property_set_string (d, "pci.vendor", vendor_name);
-			hal_device_property_set_string (d, "info.vendor", vendor_name);
-		} else {
-			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-				    hal_device_property_get_int (d, "pci.vendor_id"));
-			hal_device_property_set_string (d, "pci.vendor", buf);
-			hal_device_property_set_string (d, "info.vendor", buf);
-		}
-
-		if (product_name != NULL) {
-			hal_device_property_set_string (d, "pci.product", product_name);
-			hal_device_property_set_string (d, "info.product", product_name);
-		} else {
-			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-				    hal_device_property_get_int (d, "pci.product_id"));
-			hal_device_property_set_string (d, "pci.product", buf);
-			hal_device_property_set_string (d, "info.product", buf);
-		}
-
-		if (subsys_vendor_name != NULL) {
-			hal_device_property_set_string (d, "pci.subsys_vendor", subsys_vendor_name);
-		} else {
-			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-				    hal_device_property_get_int (d, "pci.subsys_vendor_id"));
-			hal_device_property_set_string (d, "pci.subsys_vendor", buf);
-		}
-
-		if (subsys_product_name != NULL) {
-			hal_device_property_set_string (d, "pci.subsys_product", subsys_product_name);
-		} else {
-			g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-				    hal_device_property_get_int (d, "pci.subsys_product_id"));
-			hal_device_property_set_string (d, "pci.subsys_product", buf);
-		}
-	}
-
-	return d;
-}
-
-static gboolean
-pci_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pci_%x_%x",
-			      hal_device_property_get_int (d, "pci.vendor_id"),
-			      hal_device_property_get_int (d, "pci.product_id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static void 
-usbif_set_name (HalDevice *d, int ifclass, int ifsubclass, int ifprotocol)
-{
-	const char *name;
-
-	switch (ifclass) {
-	default:
-	case 0x00:
-		name = "USB Interface";
-		break;
-	case 0x01:
-		name = "USB Audio Interface";
-		break;
-	case 0x02:
-		name = "USB Communications Interface";
-		break;
-	case 0x03:
-		name = "USB HID Interface";
-		break;
-	case 0x06:
-		name = "USB Imaging Interface";
-		break;
-	case 0x07:
-		name = "USB Printer Interface";
-		break;
-	case 0x08:
-		name = "USB Mass Storage Interface";
-		break;
-	case 0x09:
-		name = "USB Hub Interface";
-		break;
-	case 0x0a:
-		name = "USB Data Interface";
-		break;
-	case 0x0b:
-		name = "USB Chip/Smartcard Interface";
-		break;
-	case 0x0d:
-		name = "USB Content Security Interface";
-		break;
-	case 0x0e:
-		name = "USB Video Interface";
-		break;
-	case 0xdc:
-		name = "USB Diagnostic Interface";
-		break;
-	case 0xe0:
-		name = "USB Wireless Interface";
-		break;
-	case 0xef:
-		name = "USB Miscelleneous Interface";
-		break;
-	case 0xfe:
-		name = "USB Application Specific Interface";
-		break;
-	case 0xff:
-		name = "USB Vendor Specific Interface";
-		break;
-	}
-
-	hal_device_property_set_string (d, "usb.product", name);
-	hal_device_property_set_string (d, "info.product", name);
-}
-
-static HalDevice *
-usb_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	if (parent != NULL) {
-		hal_device_property_set_string (d, "info.parent", parent->udi);
-	}
-
-	/* only USB interfaces got a : in the bus_id */
-	bus_id = hal_util_get_last_element (sysfs_path);
-	if (strchr (bus_id, ':') == NULL) {
-		gint bmAttributes;
-
-		hal_device_property_set_string (d, "info.bus", "usb_device");
-
-		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-		hal_device_property_set_string (d, "usb_device.linux.sysfs_path", sysfs_path);
-
-		hal_util_set_int_from_file (d, "usb_device.configuration_value", sysfs_path, "bConfigurationValue", 10);
-		hal_util_set_int_from_file (d, "usb_device.num_configurations", sysfs_path, "bNumConfigurations", 10);
-		hal_util_set_int_from_file (d, "usb_device.num_interfaces", sysfs_path, "bNumInterfaces", 10);
-
-		hal_util_set_int_from_file (d, "usb_device.device_class", sysfs_path, "bDeviceClass", 16);
-		hal_util_set_int_from_file (d, "usb_device.device_subclass", sysfs_path, "bDeviceSubClass", 16);
-		hal_util_set_int_from_file (d, "usb_device.device_protocol", sysfs_path, "bDeviceProtocol", 16);
-
-		hal_util_set_int_from_file (d, "usb_device.vendor_id", sysfs_path, "idVendor", 16);
-		hal_util_set_int_from_file (d, "usb_device.product_id", sysfs_path, "idProduct", 16);
-
-		{
-			gchar buf[64];
-			char *vendor_name;
-			char *product_name;
-
-			ids_find_usb (hal_device_property_get_int (d, "usb_device.vendor_id"), 
-				      hal_device_property_get_int (d, "usb_device.product_id"), 
-				      &vendor_name, &product_name);
-
-			if (vendor_name != NULL) {
-				hal_device_property_set_string (d, "usb_device.vendor", vendor_name);
-			} else {
-				if (!hal_util_set_string_from_file (d, "usb_device.vendor", 
-								    sysfs_path, "manufacturer")) {
-					g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-						    hal_device_property_get_int (d, "usb_device.vendor_id"));
-					hal_device_property_set_string (d, "usb_device.vendor", buf); 
-				}
-			}
-			hal_device_property_set_string (d, "info.vendor",
-							hal_device_property_get_string (d, "usb_device.vendor"));
-
-			if (product_name != NULL) {
-				hal_device_property_set_string (d, "usb_device.product", product_name);
-			} else {
-				if (!hal_util_set_string_from_file (d, "usb_device.product", 
-								    sysfs_path, "product")) {
-					g_snprintf (buf, sizeof (buf), "Unknown (0x%04x)", 
-						    hal_device_property_get_int (d, "usb_device.product_id"));
-					hal_device_property_set_string (d, "usb_device.product", buf); 
-				}
-			}
-			hal_device_property_set_string (d, "info.product",
-							hal_device_property_get_string (d, "usb_device.product"));
-		}
-
-		hal_util_set_int_from_file (d, "usb_device.device_revision_bcd", sysfs_path, "bcdDevice", 16);
-
-		hal_util_set_int_from_file (d, "usb_device.max_power", sysfs_path, "bMaxPower", 10);
-		hal_util_set_int_from_file (d, "usb_device.num_ports", sysfs_path, "maxchild", 10);
-		hal_util_set_int_from_file (d, "usb_device.linux.device_number", sysfs_path, "devnum", 10);
-
-		hal_util_set_string_from_file (d, "usb_device.serial", sysfs_path, "serial");
-
-		hal_util_set_string_from_file (d, "usb_device.serial", sysfs_path, "serial");
-		hal_util_set_bcd2_from_file (d, "usb_device.speed_bcd", sysfs_path, "speed");
-		hal_util_set_bcd2_from_file (d, "usb_device.version_bcd", sysfs_path, "version");
-
-		hal_util_get_int_from_file (sysfs_path, "bmAttributes", &bmAttributes, 16);
-		hal_device_property_set_bool (d, "usb_device.is_self_powered", (bmAttributes & 0x40) != 0);
-		hal_device_property_set_bool (d, "usb_device.can_wake_up", (bmAttributes & 0x20) != 0);
-
-		if (strncmp (bus_id, "usb", 3) == 0)
-			hal_device_property_set_int (d, "usb_device.bus_number", atoi (bus_id + 3));
-		else
-			hal_device_property_set_int (d, "usb_device.bus_number", atoi (bus_id));
-
-		/* TODO:  .level_number .parent_number  */
-
-	} else {
-		hal_device_property_set_string (d, "info.bus", "usb");
-
-		/* take all usb_device.* properties from parent and make them usb.* on this object */
-		if (parent != NULL)
-			hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
-
-		hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-		hal_device_property_set_string (d, "usb.linux.sysfs_path", sysfs_path);
-
-		hal_util_set_int_from_file (d, "usb.interface.number", sysfs_path, "bInterfaceNumber", 10);
-
-		hal_util_set_int_from_file (d, "usb.interface.class", sysfs_path, "bInterfaceClass", 16);
-		hal_util_set_int_from_file (d, "usb.interface.subclass", sysfs_path, "bInterfaceSubClass", 16);
-		hal_util_set_int_from_file (d, "usb.interface.protocol", sysfs_path, "bInterfaceProtocol", 16);
-
-		usbif_set_name (d, 
-				hal_device_property_get_int (d, "usb.interface.class"),
-				hal_device_property_get_int (d, "usb.interface.subclass"),
-				hal_device_property_get_int (d, "usb.interface.protocol"));
-	}
-
-	return d;
-}
-
-static gboolean
-usb_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	if (hal_device_has_property (d, "usb.interface.number")) {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "%s_if%d",
-				      hal_device_property_get_string (d, "info.parent"),
-				      hal_device_property_get_int (d, "usb.interface.number"));
-		hal_device_set_udi (d, udi);
-		hal_device_property_set_string (d, "info.udi", udi);
-	} else {
-		hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-				      "/org/freedesktop/Hal/devices/usb_device_%x_%x_%s",
-				      hal_device_property_get_int (d, "usb_device.vendor_id"),
-				      hal_device_property_get_int (d, "usb_device.product_id"),
-				      hal_device_has_property (d, "usb_device.serial") ?
-				        hal_device_property_get_string (d, "usb_device.serial") :
-				        "noserial");
-		hal_device_set_udi (d, udi);
-		hal_device_property_set_string (d, "info.udi", udi);
-	}
-
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-ide_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	guint host, channel;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "ide");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	sscanf (bus_id, "%d.%d", &host, &channel);
-	hal_device_property_set_int (d, "ide.host", host);
-	hal_device_property_set_int (d, "ide.channel", channel);
-
-	if (channel == 0) {
-		hal_device_property_set_string (d, "info.product", "IDE device (master)");
-	} else {
-		hal_device_property_set_string (d, "info.product", "IDE device (slave)");
-	}
-	
-	return d;
-}
-
-static gboolean
-ide_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_ide_%d_%d",
-			      hal_device_property_get_string (d, "info.parent"),
-			      hal_device_property_get_int (d, "ide.host"),
-			      hal_device_property_get_int (d, "ide.channel"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-pnp_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "pnp");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_util_set_string_from_file (d, "pnp.id", sysfs_path, "id");
-	if (hal_device_has_property (d, "pnp.id")) {
-		gchar *pnp_description;
-		ids_find_pnp (hal_device_property_get_string (d, "pnp.id"), &pnp_description);
-		if (pnp_description != NULL) {
-			hal_device_property_set_string (d, "pnp.description", pnp_description);
-			hal_device_property_set_string (d, "info.product", pnp_description);
-		}
-	}
-
-	if (!hal_device_has_property (d, "info.product")) {
-		gchar buf[64];
-		g_snprintf (buf, sizeof (buf), "PnP Device (%s)", hal_device_property_get_string (d, "pnp.id"));
-		hal_device_property_set_string (d, "info.product", buf);
-	}
-
-	
-	return d;
-}
-
-static gboolean
-pnp_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pnp_%s",
-			      hal_device_property_get_string (d, "pnp.id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-platform_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *dev_id;
-	gchar buf[64];
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "platform");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	dev_id = hal_util_get_last_element (sysfs_path);
-
-	hal_device_property_set_string (d, "platform.id", dev_id);
-
-	g_snprintf (buf, sizeof (buf), "Platform Device (%s)", hal_device_property_get_string (d, "platform.id"));
-	hal_device_property_set_string (d, "info.product", buf);
-
-	return d;
-}
-
-static gboolean
-platform_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/platform_%s",
-			      hal_device_property_get_string (d, "platform.id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-serio_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "serio");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-	hal_device_property_set_string (d, "serio.id", bus_id);
-	if (!hal_util_set_string_from_file (d, "serio.description", sysfs_path, "description")) {
-		hal_device_property_set_string (d, "serio.description", hal_device_property_get_string (d, "serio.id"));
-	}
-	hal_device_property_set_string (d, "info.product", hal_device_property_get_string (d, "serio.description"));
-	
-	return d;
-}
-
-static gboolean
-serio_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_%s",
-			      hal_device_property_get_string (d, "info.parent"),
-			      hal_device_property_get_string (d, "serio.description"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-pcmcia_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	guint socket, function;
-	const char *prod_id1;
-	const char *prod_id2;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "pcmcia");
-	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");
-	}
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	/* not sure if %d.%d means socket function - need to revisit */
-	sscanf (bus_id, "%d.%d", &socket, &function);
-	hal_device_property_set_int (d, "pcmcia.socket_number", socket);
-
-	hal_util_set_string_from_file (d, "pcmcia.prod_id1", sysfs_path, "prod_id1");
-	hal_util_set_string_from_file (d, "pcmcia.prod_id2", sysfs_path, "prod_id2");
-	hal_util_set_string_from_file (d, "pcmcia.prod_id3", sysfs_path, "prod_id3");
-	hal_util_set_string_from_file (d, "pcmcia.prod_id4", sysfs_path, "prod_id4");
-
-	hal_util_set_int_from_file (d, "pcmcia.manf_id", sysfs_path, "manf_id", 16);
-	hal_util_set_int_from_file (d, "pcmcia.card_id", sysfs_path, "card_id", 16);
-	hal_util_set_int_from_file (d, "pcmcia.func_id", sysfs_path, "func_id", 16);
-
-	prod_id1 = hal_device_property_get_string (d, "pcmcia.prod_id1");
-	prod_id2 = hal_device_property_get_string (d, "pcmcia.prod_id2");
-
-	/* Provide best-guess of vendor, goes in Vendor property */
-	if (prod_id1 != NULL) {
-		hal_device_property_set_string (d, "info.vendor", prod_id1);
-	} else {
-		char buf[50];
-		g_snprintf (buf, sizeof(buf), "Unknown (0x%04x)", hal_device_property_get_int (d, "pcmcia.manf_id"));
-		hal_device_property_set_string (d, "info.vendor", buf);
-	}
-
-	/* Provide best-guess of name, goes in Product property */
-	if (prod_id2 != NULL) {
-		hal_device_property_set_string (d, "info.product", prod_id2);
-	} else {
-		char buf[50];
-		g_snprintf (buf, sizeof(buf), "Unknown (0x%04x)", hal_device_property_get_int (d, "pcmcia.card_id"));
-		hal_device_property_set_string (d, "info.product", buf);
-	}
-
-	return d;
-}
-
-static gboolean
-pcmcia_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pcmcia_%d_%d",
-			      hal_device_property_get_int (d, "pcmcia.manfid1"),
-			      hal_device_property_get_int (d, "pcmcia.manfid2"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-scsi_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	gint host_num, bus_num, target_num, lun_num;
-	int type;
-
-	if (parent == NULL) {
-		d = NULL;
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "scsi");
-	hal_device_property_set_string (d, "info.parent", parent->udi);
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-	sscanf (bus_id, "%d:%d:%d:%d", &host_num, &bus_num, &target_num, &lun_num);
-	hal_device_property_set_int (d, "scsi.host", host_num);
-	hal_device_property_set_int (d, "scsi.bus", bus_num);
-	hal_device_property_set_int (d, "scsi.target", target_num);
-	hal_device_property_set_int (d, "scsi.lun", lun_num);
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_string (d, "info.product", "SCSI Device");
-
-	hal_util_set_string_from_file (d, "scsi.model", sysfs_path, "model");
-	hal_util_set_string_from_file (d, "scsi.vendor", sysfs_path, "vendor");
-	hal_util_get_int_from_file (sysfs_path, "type", &type, 0);
-	HAL_INFO (("%s/type -> %d (-> scsi.type)", sysfs_path, type));
-	switch (type) {
-	case 0:  /* TYPE_DISK (disk) */
-	case 7:  /* TYPE_MOD (Magneto-optical disk) */
-	case 14: /* TYPE_RBC (Reduced Block Commands)
-		  * Simple Direct Access Device, set it to disk
-		  * (some Firewire Disks use it)
-		  */
-		hal_device_property_set_string (d, "scsi.type", "disk");
-		break;
-	case 1: /* TYPE_TAPE (Tape) */
-		hal_device_property_set_string (d, "scsi.type", "tape");
-		break;
-	case 2:
-		/* TYPE_PRINTER (Tape) */
-		hal_device_property_set_string (d, "scsi.type", "printer");
-		break;
-	case 3:  /* TYPE_PROCESSOR */
-		hal_device_property_set_string (d, "scsi.type", "processor");
-		break;
-	case 4: /* TYPE_WORM */
-	case 5: /* TYPE_ROM (CD-ROM) */
-		hal_device_property_set_string (d, "scsi.type", "cdrom");
-		break;
-	case 6: /* TYPE_SCANNER */
-		hal_device_property_set_string (d, "scsi.type", "scanner");
-		break;
-	case 8: /* TYPE_MEDIUM_CHANGER */
-		hal_device_property_set_string (d, "scsi.type", "medium_changer");
-		break;
-	case 9: /* TYPE_COMM */
-		hal_device_property_set_string (d, "scsi.type", "comm");
-		break;
-	case 12: /* TYPE_RAID */
-		hal_device_property_set_string (d, "scsi.type", "raid");
-		break;
-	default:
-		hal_device_property_set_string (d, "scsi.type", "unknown");
-	}
-
-out:
-	return d;
-}
-
-static gboolean
-scsi_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_scsi_device_lun%d",
-			      hal_device_property_get_string (d, "info.parent"),
-			      hal_device_property_get_int (d, "scsi.lun"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-mmc_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	gint host_num, rca, manfid, oemid;
-	gchar *scr;
-
-	if (parent == NULL) {
-		d = NULL;
-		goto out;
-	}
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "mmc");
-	hal_device_property_set_string (d, "info.parent", parent->udi);
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-	sscanf (bus_id, "mmc%d:%x", &host_num, &rca);
-	hal_device_property_set_int (d, "mmc.rca", rca);
-	
-	hal_util_set_string_from_file (d, "mmc.cid", sysfs_path, "cid");
-	hal_util_set_string_from_file (d, "mmc.csd", sysfs_path, "csd");
-	
-	scr = hal_util_get_string_from_file (sysfs_path, "scr");
-	if (scr != NULL) {
-		if (strcmp (scr, "0000000000000000") == 0)
-			scr = NULL;
-		else
-			hal_device_property_set_string (d, "mmc.scr", scr);
-	}
-
-	if (!hal_util_set_string_from_file (d, "info.product", sysfs_path, "name")) {
-		if (scr != NULL)
-			hal_device_property_set_string (d, "info.product", "SD Card");
-		else
-			hal_device_property_set_string (d, "info.product", "MMC Card");
-	}
-	
-	if (hal_util_get_int_from_file (sysfs_path, "manfid", &manfid, 16)) {
-		/* Here we should have a mapping to a name */
-		char vendor[256];
-		snprintf(vendor, 256, "Unknown (%d)", manfid);
-		hal_device_property_set_string (d, "info.vendor", vendor);
-	}
-	if (hal_util_get_int_from_file (sysfs_path, "oemid", &oemid, 16)) {
-		/* Here we should have a mapping to a name */
-		char oem[256];
-		snprintf(oem, 256, "Unknown (%d)", oemid);
-		hal_device_property_set_string (d, "mmc.oem", oem);
-	}
-
-	hal_util_set_string_from_file (d, "mmc.date", sysfs_path, "date");
-	hal_util_set_int_from_file (d, "mmc.hwrev", sysfs_path, "hwrev", 16);
-	hal_util_set_int_from_file (d, "mmc.fwrev", sysfs_path, "fwrev", 16);
-	hal_util_set_int_from_file (d, "mmc.serial", sysfs_path, "serial", 16);
-
-out:
-	return d;
-}
-
-static gboolean
-mmc_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "%s_mmc_card_rca%d",
-			      hal_device_property_get_string (d, "info.parent"),
-			      hal_device_property_get_int (d, "mmc.rca"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-xen_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *devtype;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "xen");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_string (d, "xen.bus_id",
-					hal_util_get_last_element (sysfs_path));
-
-	hal_util_set_string_from_file (d, "xen.path", sysfs_path, "nodename");
-
-	devtype = hal_util_get_string_from_file (sysfs_path, "devtype");
-	hal_device_property_set_string (d, "xen.type", devtype);
-
-	if (strcmp (devtype, "pci") == 0) {
-		hal_device_property_set_string (d, "info.product", "Xen PCI Device");
-	} else if (strcmp (devtype, "vbd") == 0) {
-		hal_device_property_set_string (d, "info.product", "Xen Virtual Block Device");
-	} else if (strcmp (devtype, "vif") == 0) {
-		hal_device_property_set_string (d, "info.product", "Xen Virtual Network Device");
-	} else if (strcmp (devtype, "vtpm") == 0) {
-		hal_device_property_set_string (d, "info.product", "Xen Virtual Trusted Platform Module");
-	} else {
-		char buf[64];
-		g_snprintf (buf, sizeof (buf), "Xen Device (%s)", devtype);
-		hal_device_property_set_string (d, "info.product", buf);
-	}
-
-	return d;
-}
-
-static gboolean
-xen_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/xen_%s",
-			      hal_device_property_get_string (d, "xen.bus_id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-ieee1394_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	long long unsigned int guid;
-	gint host_id;
-	const gchar *bus_id;
-	gchar buf[64];
-
-	d = NULL;
-
-	if (parent == NULL)
-		goto out;
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	if (sscanf (bus_id, "fw-host%d", &host_id) == 1)
-		goto out;
-
-	if (sscanf (bus_id, "%llx-%d", &guid, &host_id) !=2 )
-		goto out;
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "ieee1394");
-	hal_device_property_set_string (d, "info.parent", parent->udi);
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_uint64 (d, "ieee1394.guid", guid);
-	hal_util_set_int_from_file    (d, "ieee1394.vendor_id", sysfs_path, "../vendor_id", 16);
-	hal_util_set_int_from_file    (d, "ieee1394.specifier_id", sysfs_path, "specifier_id", 16);
-	hal_util_set_int_from_file    (d, "ieee1394.version", sysfs_path, "version", 16);
-
-	if (!hal_util_set_string_from_file (d, "ieee1394.vendor", sysfs_path, "../vendor_oui")) {
-		g_snprintf (buf, sizeof (buf), "Unknown (0x%06x)", 
-			    hal_device_property_get_int (d, "ieee1394.vendor_id"));
-		hal_device_property_set_string (d, "ieee1394.vendor", buf);
-	}
-
-	/* not all devices have product_id */
-	if (hal_util_set_int_from_file    (d, "ieee1394.product_id", sysfs_path, "model_id", 16)) {
-		if (!hal_util_set_string_from_file (d, "ieee1394.product", sysfs_path, "model_name_kv")) {
-			g_snprintf (buf, sizeof (buf), "Unknown (0x%06x)", 
-				    hal_device_property_get_int (d, "ieee1394.product_id"));
-			hal_device_property_set_string (d, "ieee1394.product", buf);
-		}
-	} else {
-		hal_device_property_set_int (d, "ieee1394.product_id", 0x000000);
-		hal_device_property_set_string (d, "ieee1394.product",
-						hal_device_property_get_string (d, "ieee1394.vendor"));
-	}
-		
-	hal_device_property_set_string (d, "info.vendor",
-					hal_device_property_get_string (d, "ieee1394.vendor"));
-	hal_device_property_set_string (d, "info.product",
-					hal_device_property_get_string (d, "ieee1394.product"));
-
-out:
-	return d;
-}
-
-static gboolean
-ieee1394_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/ieee1394_guid_%0llx",
-			      hal_device_property_get_uint64 (d, "ieee1394.guid"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static inline void
-ccw_add_dasd_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	const gchar *disc;
-	
-	hal_util_set_int_from_file (d, "ccw.dasd.use_diag", sysfs_path,
-				    "use_diag", 2);
-	hal_util_set_int_from_file (d, "ccw.dasd.readonly", sysfs_path,
-				    "readonly", 2);
-	disc = hal_util_get_string_from_file (sysfs_path, "discipline");
-	if (disc)
-		hal_device_property_set_string(d, "ccw.dasd.discipline", disc);
-}
-
-static inline void
-ccw_add_zfcp_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	int online;
-
-	/* zfcp adapter properties are only valid for online devices. */
-	if (!hal_util_get_int_from_file (sysfs_path, "online", &online, 2))
-		return;
-	if (!online)
-		return;
-
-	hal_util_set_int_from_file (d, "ccw.zfcp.in_recovery", sysfs_path,
-				    "in_recovery", 2);
-	hal_util_set_int_from_file (d, "ccw.zfcp.failed", sysfs_path,
-				    "failed", 2);
-}
-
-static inline void
-ccw_add_tape_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	int medium_state, online;
-
-	const gchar *state_text[3] = {"unknown", "loaded", "no medium"};
-
-	hal_util_set_string_from_file (d, "ccw.tape.state", sysfs_path, "state");
-	hal_util_set_string_from_file (d, "ccw.tape.operation", sysfs_path,
-				       "operation");
-	/* The following properties are only valid for online devices. */
-	if (!hal_util_get_int_from_file (sysfs_path, "online", &online, 2))
-		return;
-	if (!online)
-		return;
-	hal_util_set_int_from_file (d, "ccw.tape.blocksize", sysfs_path,
-				    "blocksize", 10);
-	if (!hal_util_get_int_from_file (sysfs_path, "medium_state",
-					&medium_state, 10))
-		return;
-	hal_device_property_set_string (d, "ccw.tape.medium_state",
-					state_text[medium_state]);
-}
-
-static inline void
-ccw_add_3270_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	hal_util_set_int_from_file (d, "ccw.3270.model", sysfs_path,
-				    "model", 10);
-	hal_util_set_int_from_file (d, "ccw.3270.rows", sysfs_path, "rows", 10);
-	hal_util_set_int_from_file (d, "ccw.3270.columns", sysfs_path,
-				    "columns", 10);
-}
-
-static HalDevice *
-ccw_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	const gchar *pimpampom;
-	int pim, pam, pom;
-	const gchar *chpids;
-	int chpid[8];
-	gchar attr[25];
-	int i;
-	gchar driver_name[256];
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device",
-					sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "ccw");
-	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");
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_string (d, "ccw.bus_id", bus_id);
-	hal_util_set_int_from_file (d, "ccw.online", sysfs_path, "online", 2);
-	hal_util_set_string_from_file (d, "ccw.availablity", sysfs_path,
-				       "availability");
-	hal_util_set_int_from_file (d, "ccw.cmb_enable", sysfs_path,
-				    "cmb_enable", 2);
-	hal_util_set_string_from_file (d, "ccw.cutype", sysfs_path, "cutype");
-	hal_util_set_string_from_file (d, "ccw.devtype", sysfs_path, "devtype");
-
-	/* Get some values from the higher level subchannel structure.*/
-	pimpampom = hal_util_get_string_from_file (sysfs_path, "../pimpampom");
-	if (pimpampom) {
-		sscanf (pimpampom, "%x %x %x", &pim, &pam, &pom);
-		hal_device_property_set_int (d, "ccw.subchannel.pim", pim);
-		hal_device_property_set_int (d, "ccw.subchannel.pam", pam);
-		hal_device_property_set_int (d, "ccw.subchannel.pom", pom);
-	}
-
-	chpids = hal_util_get_string_from_file (sysfs_path, "../chpids");
-	if (chpids) {
-		sscanf (chpids, "%x %x %x %x %x %x %x %x", &chpid[0], &chpid[1],
-			&chpid[2], &chpid[3], &chpid[4], &chpid[5], &chpid[6],
-			&chpid[7]);
-		for (i=0; i<8 && (chpid[i] != 0); i++) {
-			g_snprintf (attr, sizeof (attr),
-				    "ccw.subchannel.chpid%x", i);
-			hal_device_property_set_int (d, attr, chpid[i]);
-		}
-	}
-
-	/* Add some special properties. */
-	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
-		if (!strncmp (driver_name, "dasd", 4))
-			/* Same attributes for dasd_eckd and dasd_fba. */
-			ccw_add_dasd_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "zfcp", 4))
-			ccw_add_zfcp_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "tape_3", 6))
-			/* For all channel attached tapes. */
-			ccw_add_tape_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "3270", 4))
-			ccw_add_3270_properties (d, sysfs_path);
-	}
-	return d;
-}
-
-static gboolean
-ccw_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/ccw_%s",
-			      hal_device_property_get_string
-			      (d, "ccw.bus_id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static inline void
-ccwgroup_add_qeth_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	int is_layer2;
-
-	/* Some attributes are not applicable for devices in layer2 mode. */
-	hal_util_get_int_from_file (sysfs_path, "layer2", &is_layer2, 2);
-
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.large_send",
-				       sysfs_path, "large_send");
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.card_type", sysfs_path,
-				       "card_type");
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.checksumming",
-				       sysfs_path, "checksumming");
-	if (!is_layer2) {
-		//CH: the next two are only valid for token ring devices
-		hal_util_set_int_from_file (d,
-					    "ccwgroup.qeth.canonical_macaddr",
-					    sysfs_path, "canonical_macaddr", 2);
-		hal_util_set_string_from_file (d,
-					       "ccwgroup.qeth.broadcast_mode",
-					       sysfs_path, "broadcast_mode");
-		hal_util_set_int_from_file (d, "ccwgroup.qeth.fake_broadcast",
-					    sysfs_path, "fake_broadcast", 2);
-		hal_util_set_int_from_file (d, "ccwgroup.qeth.fake_ll",
-					    sysfs_path, "fake_ll", 2);
-	}
-	hal_device_property_set_int (d, "ccwgroup.qeth.layer2", is_layer2);
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.portname", sysfs_path,
-				       "portname");
-	hal_util_set_int_from_file (d, "ccwgroup.qeth.portno", sysfs_path,
-				    "portno", 10);
-	hal_util_set_int_from_file (d, "ccwgroup.qeth.buffer_count", sysfs_path,
-				    "buffer_count", 10);
-	hal_util_set_int_from_file (d, "ccwgroup.qeth.add_hhlen", sysfs_path,
-				    "add_hhlen", 10);
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.priority_queueing",
-				       sysfs_path, "priority_queueing");
-	if (!is_layer2) {
-		hal_util_set_string_from_file (d, "ccwgroup.qeth.route4",
-					       sysfs_path, "route4");
-		hal_util_set_string_from_file (d, "ccwgroup.qeth.route6",
-					       sysfs_path, "route6");
-	}
-	hal_util_set_string_from_file (d, "ccwgroup.qeth.state", sysfs_path,
-				       "state");
-}
-
-static inline void
-ccwgroup_add_ctc_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	//CH: use protocol descriptions?
-	hal_util_set_int_from_file (d, "ccwgroup.ctc.protocol", sysfs_path,
-				    "protocol", 2);
-	hal_util_set_string_from_file (d, "ccwgroup.ctc.type", sysfs_path,
-				       "type");
-	hal_util_set_int_from_file (d, "ccwgroup.ctc.buffer", sysfs_path,
-				    "buffer", 10);
-}
-
-static inline void
-ccwgroup_add_lcs_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	hal_util_set_int_from_file (d, "ccwgroup.lcs.portnumber", sysfs_path,
-				    "portno", 10);
-	hal_util_set_string_from_file (d, "ccwgroup.lcs.type", sysfs_path,
-				       "type");
-	hal_util_set_int_from_file (d, "ccwgroup.lcs.lancmd_timeout",
-				    sysfs_path, "lancmd_timeout", 10);
-}
-
-static inline void
-ccwgroup_add_claw_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	hal_util_set_string_from_file (d, "ccwgroup.claw.api_type", sysfs_path,
-				       "api_type");
-	hal_util_set_string_from_file (d, "ccwgroup.claw.adapter_name",
-				       sysfs_path, "adapter_name");
-	hal_util_set_string_from_file (d, "ccwgroup.claw.host_name", sysfs_path,
-				       "host_name");
-	hal_util_set_int_from_file (d, "ccwgroup.claw.read_buffer", sysfs_path,
-				    "read_buffer", 10);
-	hal_util_set_int_from_file (d, "ccwgroup.claw.write_buffer", sysfs_path,
-				    "write_buffer", 10);
-}
-
-static HalDevice *
-ccwgroup_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	gchar driver_name[256];
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device",
-					sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "ccwgroup");
-	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");
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_string (d, "ccwgroup.bus_id", bus_id);
-	hal_util_set_int_from_file (d, "ccwgroup.online", sysfs_path,
-				    "online", 2);
-
-	/* Some devices have extra properties. */
-	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
-		if (!strncmp (driver_name, "qeth", 4))
-			ccwgroup_add_qeth_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "ctc", 3))
-			ccwgroup_add_ctc_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "lcs", 3))
-			ccwgroup_add_lcs_properties (d, sysfs_path);
-		if (!strncmp (driver_name, "claw", 4))
-			ccwgroup_add_claw_properties (d, sysfs_path);
-	}
-	return d;
-}
-
-static gboolean
-ccwgroup_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/ccwgroup_%s",
-			      hal_device_property_get_string
-			      (d, "ccwgroup.bus_id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static inline void
-iucv_add_netiucv_properties (HalDevice *d, const gchar *sysfs_path)
-{
-	hal_util_set_string_from_file (d, "iucv.netiucv.user", sysfs_path,
-				       "user");
-	hal_util_set_int_from_file (d, "iucv.netiucv.buffer", sysfs_path,
-				    "buffer", 10);
-}
-
-static HalDevice *
-iucv_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *bus_id;
-	gchar driver_name[256];
-
-	bus_id = hal_util_get_last_element (sysfs_path);
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device",
-					sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "iucv");
-	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");
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	hal_device_property_set_string (d, "iucv.bus_id", bus_id);
-
-	if (hal_util_get_driver_name (sysfs_path, driver_name)) {
-		if (!strncmp (driver_name, "netiucv", 7))
-			iucv_add_netiucv_properties (d, sysfs_path);
-	}
-	return d;
-}
-
-static gboolean
-iucv_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/iucv_%s",
-			      hal_device_property_get_string
-			      (d, "iucv.bus_id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static HalDevice *
-pseudo_add (const gchar *sysfs_path, HalDevice *parent)
-{
-	HalDevice *d;
-	const gchar *dev_id;
-	gchar buf[64];
-
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.sysfs_path", sysfs_path);
-	hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
-	hal_device_property_set_string (d, "info.bus", "pseudo");
-	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");
-	}
-
-	hal_util_set_driver (d, "info.linux.driver", sysfs_path);
-
-	dev_id = hal_util_get_last_element (sysfs_path);
-	hal_device_property_set_string (d, "pseudo.id", dev_id);
-
-	g_snprintf (buf, sizeof (buf), "SCSI Debug Device (%s)", hal_device_property_get_string (d, "pseudo.id"));
-	hal_device_property_set_string (d, "info.product", buf);
-
-	return d;
-}
-
-static gboolean
-pseudo_compute_udi (HalDevice *d)
-{
-	gchar udi[256];
-
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pseudo",
-			      hal_device_property_get_string (d, "platform.id"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-
-	return TRUE;
-
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static gboolean
-physdev_remove (HalDevice *d)
-{
-	return TRUE;
-}
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-typedef struct
-{
-	const gchar *subsystem;
-	HalDevice *(*add) (const gchar *sysfs_path, HalDevice *parent);
-	gboolean (*compute_udi) (HalDevice *d);
-	gboolean (*remove) (HalDevice *d);
-} PhysDevHandler;
-
-static PhysDevHandler physdev_handler_pci = { 
-	.subsystem   = "pci",
-	.add         = pci_add,
-	.compute_udi = pci_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_usb = { 
-	.subsystem   = "usb",
-	.add         = usb_add,
-	.compute_udi = usb_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_ide = { 
-	.subsystem   = "ide",
-	.add         = ide_add,
-	.compute_udi = ide_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_pnp = { 
-	.subsystem   = "pnp",
-	.add         = pnp_add,
-	.compute_udi = pnp_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_platform = {
-	.subsystem   = "platform",
-	.add         = platform_add,
-	.compute_udi = platform_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_serio = { 
-	.subsystem   = "serio",
-	.add         = serio_add,
-	.compute_udi = serio_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_pcmcia = { 
-	.subsystem   = "pcmcia",
-	.add         = pcmcia_add,
-	.compute_udi = pcmcia_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_scsi = { 
-	.subsystem   = "scsi",
-	.add         = scsi_add,
-	.compute_udi = scsi_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_mmc = { 
-	.subsystem   = "mmc",
-	.add         = mmc_add,
-	.compute_udi = mmc_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_ieee1394 = { 
-	.subsystem   = "ieee1394",
-	.add         = ieee1394_add,
-	.compute_udi = ieee1394_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_xen = {
-	.subsystem   = "xen",
-	.add         = xen_add,
-	.compute_udi = xen_compute_udi,
-	.remove      = physdev_remove
-};
-
-/* s390 specific busses */
-static PhysDevHandler physdev_handler_ccw = {
-	.subsystem   = "ccw",
-	.add         = ccw_add,
-	.compute_udi = ccw_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_ccwgroup = {
-	.subsystem   = "ccwgroup",
-	.add         = ccwgroup_add,
-	.compute_udi = ccwgroup_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler physdev_handler_iucv = {
-	.subsystem   = "iucv",
-	.add         = iucv_add,
-	.compute_udi = iucv_compute_udi,
-	.remove      = physdev_remove
-};
-
-/* SCSI debug, to test thousends of fake devices */
-static PhysDevHandler physdev_handler_pseudo = {
-	.subsystem   = "pseudo",
-	.add         = pseudo_add,
-	.compute_udi = pseudo_compute_udi,
-	.remove      = physdev_remove
-};
-
-static PhysDevHandler *phys_handlers[] = {
-	&physdev_handler_pci,
-	&physdev_handler_usb,
-	&physdev_handler_ide,
-	&physdev_handler_pnp,
-	&physdev_handler_platform,
-	&physdev_handler_serio,
-	&physdev_handler_pcmcia,
-	&physdev_handler_scsi,
-	&physdev_handler_mmc,
-	&physdev_handler_ieee1394,
-	&physdev_handler_xen,
-	&physdev_handler_ccw,
-	&physdev_handler_ccwgroup,
-	&physdev_handler_iucv,
-	&physdev_handler_pseudo,
-	NULL
-};
-
-/*--------------------------------------------------------------------------------------------------------------*/
-
-static void 
-physdev_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 
-physdev_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"));
-	}
-	g_object_unref (d);
-
-	hotplug_event_end (end_token);
-}
-
-
-static void 
-physdev_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
-{
-	void *end_token = (void *) userdata1;
-	PhysDevHandler *handler = (PhysDevHandler *) userdata2;
-
-	if (hal_device_property_get_bool (d, "info.ignore")) {
-		/* Leave the device here with info.ignore==TRUE so we won't pick up children 
-		 * Also remove category and all capabilities
-		 */
-		hal_device_property_remove (d, "info.category");
-		hal_device_property_remove (d, "info.capabilities");
-		hal_device_property_set_string (d, "info.udi", "/org/freedesktop/Hal/devices/ignored-device");
-		hal_device_property_set_string (d, "info.product", "Ignored Device");
-		
-		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
-		
-		/* 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);
-		goto out;
-	}
-	
-	
-	/* 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)) {
-		hal_device_store_remove (hald_get_tdl (), d);
-		g_object_unref (d);
-		hotplug_event_end (end_token);
-		goto out;
-	}
-	
-	/* Run callouts */
-	hal_util_callout_device_add (d, physdev_callouts_add_done, end_token, NULL);
-
-out:
-	;
-}
-
-void
-hotplug_event_begin_add_physdev (const gchar *subsystem, const gchar *sysfs_path, HalDevice *parent, void *end_token)
-{
-	guint i;
-
-	HAL_INFO (("phys_add: subsys=%s sysfs_path=%s, parent=0x%08x", subsystem, sysfs_path, parent));
-
-	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
-		HAL_INFO (("Ignoring phys_add since parent has info.ignore==TRUE"));
-		hotplug_event_end (end_token);
-		goto out;
-	}
-
-	for (i = 0; phys_handlers [i] != NULL; i++) {
-		PhysDevHandler *handler;
-
-		handler = phys_handlers[i];
-		if (strcmp (handler->subsystem, subsystem) == 0) {
-			HalDevice *d;
-
-			d = handler->add (sysfs_path, parent);
-			if (d == NULL) {
-				/* didn't find anything - thus, ignore this hotplug event */
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_BUS);
-			hal_device_property_set_string (d, "linux.subsystem", subsystem);
-
-			/* Add to temporary device store */
-			hal_device_store_add (hald_get_tdl (), d);
-
-			/* Process preprobe fdi files */
-			di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
-
-			/* Run preprobe callouts */
-			hal_util_callout_device_preprobe (d, physdev_callouts_preprobing_done, end_token, handler);
-			goto out;
-		}
-	}
-	
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out:
-	;
-}
-
-void
-hotplug_event_begin_remove_physdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token)
-{
-	guint i;
-	HalDevice *d;
-
-	HAL_INFO (("phys_rem: subsys=%s sysfs_path=%s", subsystem, sysfs_path));
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), 
-						     "linux.sysfs_path", 
-						     sysfs_path);
-	if (d == NULL) {
-		HAL_WARNING (("Couldn't remove device with sysfs path %s - not found", sysfs_path));
-		goto out;
-	}
-	
-	for (i = 0; phys_handlers [i] != NULL; i++) {
-		PhysDevHandler *handler;
-		
-		handler = phys_handlers[i];
-		if (strcmp (handler->subsystem, subsystem) == 0) {
-			handler->remove (d);
-			
-			hal_util_callout_device_remove (d, physdev_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
-physdev_rescan_device (HalDevice *d)
-{
-	return FALSE;
-}
-
-HotplugEvent *
-physdev_generate_add_hotplug_event (HalDevice *d)
-{
-	const char *subsystem;
-	const char *sysfs_path;
-	HotplugEvent *hotplug_event;
-
-	subsystem = hal_device_property_get_string (d, "linux.subsystem");
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
-
-HotplugEvent *
-physdev_generate_remove_hotplug_event (HalDevice *d)
-{
-	const char *subsystem;
-	const char *sysfs_path;
-	HotplugEvent *hotplug_event;
-
-	subsystem = hal_device_property_get_string (d, "linux.subsystem");
-	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-	hotplug_event->type = HOTPLUG_EVENT_SYSFS;
-	g_strlcpy (hotplug_event->sysfs.subsystem, subsystem, sizeof (hotplug_event->sysfs.subsystem));
-	g_strlcpy (hotplug_event->sysfs.sysfs_path, sysfs_path, sizeof (hotplug_event->sysfs.sysfs_path));
-	hotplug_event->sysfs.device_file[0] = '\0';
-	hotplug_event->sysfs.net_ifindex = -1;
-
-	return hotplug_event;
-}
diff --git a/hald/linux2/physdev.h b/hald/linux2/physdev.h
deleted file mode 100644
index 6c16cc2..0000000
--- a/hald/linux2/physdev.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * physdev.h : Handling of physical kernel devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef PHYSDEV_H
-#define PHYSDEV_H
-
-#include <glib.h>
-#include "hotplug.h"
-
-void hotplug_event_begin_add_physdev (const gchar *subsystem, const gchar *sysfs_path, HalDevice *parent, void *end_token);
-
-void hotplug_event_begin_remove_physdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
-
-gboolean physdev_rescan_device (HalDevice *d);
-
-HotplugEvent *physdev_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *physdev_generate_remove_hotplug_event (HalDevice *d);
-
-#endif /* PHYSDEV_H */
diff --git a/hald/linux2/pmu.c b/hald/linux2/pmu.c
deleted file mode 100644
index 892fff1..0000000
--- a/hald/linux2/pmu.c
+++ /dev/null
@@ -1,622 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 Sjoerd Simons <sjoerd at luon.net>
- * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
- *
- * 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 <stdio.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "../device_info.h"
-#include "../hald_dbus.h"
-#include "../logger.h"
-#include "../util.h"
-#include "../util_pm.h"
-
-#include "hotplug.h"
-#include "osspec_linux.h"
-
-#include "pmu.h"
-
-enum {
-	PMU_TYPE_BATTERY,
-	PMU_TYPE_AC_ADAPTER,
-	PMU_TYPE_LID_BUTTON,
-	PMU_TYPE_LAPTOP_PANEL
-};
-
-
-typedef struct PMUDevHandler_s
-{
-	int pmu_type;
-	HalDevice *(*add) (const gchar *pmu_path, HalDevice *parent, struct PMUDevHandler_s *handler);
-	gboolean (*compute_udi) (HalDevice *d, struct PMUDevHandler_s *handler);
-	gboolean (*remove) (HalDevice *d, struct PMUDevHandler_s *handler);
-	gboolean (*refresh) (HalDevice *d, struct PMUDevHandler_s *handler);
-} PMUDevHandler;
-
-
-/* defines from the kernel PMU driver (include/linux/pmu.h) */
-#define PMU_BATT_PRESENT	0x00000001
-#define PMU_BATT_CHARGING	0x00000002
-#define PMU_BATT_TYPE_MASK	0x000000f0
-#define PMU_BATT_TYPE_SMART	0x00000010	/* Smart battery */
-#define PMU_BATT_TYPE_HOOPER	0x00000020	/* 3400/3500 */
-#define PMU_BATT_TYPE_COMET	0x00000030	/* 2400 */
-
-#define PMU_POLL_INTERVAL	2000
-
-#define PMUDEV			"/dev/pmu"
-
-
-static gboolean
-battery_refresh (HalDevice *d, PMUDevHandler *handler)
-{
-	const char *path;
-	int flags;
-	int last_full;
-	int remaining_time;
-	int remaining_percentage;
-
-	path = hal_device_property_get_string (d, "linux.pmu_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");
-
-	flags = hal_util_grep_int_elem_from_file (path, "", "flags", 0, 16, FALSE);
-
-	hal_device_property_set_bool (d, "battery.present", flags & PMU_BATT_PRESENT);
-
-	if (flags & PMU_BATT_PRESENT) {
-		int current;
-
-		device_property_atomic_update_begin ();
-		hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);
-
-		/* we don't know the unit here :-/ */
-		/*hal_device_property_set_string (d, "battery.charge_level.unit", "percent");*/
-
-		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", flags & PMU_BATT_CHARGING);
-		/* we're discharging if, and only if, we are not plugged into the wall */
-		{
-			char buf[HAL_PATH_MAX];
-			snprintf (buf, sizeof (buf), "%s/pmu/info", get_hal_proc_path ());
-			hal_util_set_bool_elem_from_file (d, "battery.rechargeable.is_discharging", buf, "", 
-							  "AC Power", 0, "0", FALSE);
-		}
-
-		hal_util_set_int_elem_from_file (d, "battery.charge_level.current", 
-						 path, "", "charge", 0, 10, FALSE);
-		hal_util_set_int_elem_from_file (d, "battery.charge_level.last_full", 
-						 path, "", "max_charge", 0, 10, FALSE);
-		hal_util_set_int_elem_from_file (d, "battery.charge_level.design", 
-						 path, "", "max_charge", 0, 10, FALSE);
-
-		current = hal_util_grep_int_elem_from_file (path, "", "current", 0, 10, FALSE);
-		if (current > 0)
-			hal_device_property_set_int (d, "battery.charge_level.rate", current);
-		else
-			hal_device_property_set_int (d, "battery.charge_level.rate", -current);
-
-		current = hal_device_property_get_int (d, "battery.charge_level.current");
-		last_full = hal_device_property_get_int (d, "battery.charge_level.last_full");
-
-		/* TODO: could read some pmu file? */
-		remaining_time = util_compute_time_remaining (
-					d->udi,
-					hal_device_property_get_int (d, "battery.charge_level.rate"),
-					current,
-					last_full,
-					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, current, last_full);
-		/*
-		 * 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");
-
-		device_property_atomic_update_end ();
-	} else {
-		device_property_atomic_update_begin ();
-		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.charge_level.unit");*/
-		hal_device_property_remove (d, "battery.charge_level.current");
-		hal_device_property_remove (d, "battery.charge_level.last_full");
-		hal_device_property_remove (d, "battery.charge_level.design");
-		device_property_atomic_update_end ();		
-	}
-
-	return TRUE;
-}
-
-static gboolean
-ac_adapter_refresh (HalDevice *d, PMUDevHandler *handler)
-{
-	const char *path;
-
-	path = hal_device_property_get_string (d, "linux.pmu_path");
-	if (path == NULL)
-		return FALSE;
-
-	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");
-
-	hal_util_set_bool_elem_from_file (d, "ac_adapter.present", path, "", "AC Power", 0, "1", FALSE);
-
-	return TRUE;
-}
-
-static gboolean
-lid_button_refresh (HalDevice *d, PMUDevHandler *handler)
-{
-	hal_device_property_set_string (d, "info.product", "Lid Switch");
-	hal_device_add_capability (d, "button");
-	hal_device_property_set_string (d, "info.category", "button");
-	hal_device_property_set_string (d, "button.type", "lid");
-	hal_device_property_set_bool (d, "button.has_state", TRUE);
-	hal_device_property_set_bool (d, "button.state.value", FALSE); 
-
-	/* assume lid is open, polling will tell us otherwise 
-	 * (TODO: figure out initial state)
-	 */
-	return TRUE;
-}
-
-/** Refreshes a laptop screen connected to a PMU controller.
- *  This is much simpler than ACPI as we have a *standard* ioctl to use.
- *
- *  @param	d		The hal device
- *  @param	handler		What to do
- */
-static gboolean
-laptop_panel_refresh (HalDevice *d, PMUDevHandler *handler)
-{
-	hal_device_property_set_string (d, "info.category", "laptop_panel");
-	hal_device_property_set_string (d, "info.product", "Apple Laptop Panel");
-
-	hal_device_property_set_string (d, "laptop_panel.access_method", "pmu");
-	/*
-	 * We can set laptop_panel.num_levels as it will not change, 
-	 * all powerbooks have 15 steps for brightness, where state 0
-	 * is backlight disable.
-	 */
-	hal_device_property_set_int (d, "laptop_panel.num_levels", 14);
-	hal_device_add_capability (d, "laptop_panel");
-	return TRUE;
-}
-
-static gboolean
-pmu_lid_compute_udi (HalDevice *d, PMUDevHandler *handler)
-{
-	gchar udi[256];
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pmu_lid");
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-static gboolean
-pmu_laptop_panel_compute_udi (HalDevice *d, PMUDevHandler *handler)
-{
-	gchar udi[256];
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pmu_lcd");
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-static gboolean
-pmu_poll (gpointer data)
-{
-	GSList *i;
-	GSList *devices;
-
-	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
-								    "battery.type",
-								    "primary");
-	for (i = devices; i != NULL; i = g_slist_next (i)) {
-		HalDevice *d;
-		
-		d = HAL_DEVICE (i->data);
-		if (hal_device_has_property (d, "linux.pmu_type")) {
-			hal_util_grep_discard_existing_data ();
-			device_property_atomic_update_begin ();
-			battery_refresh (d, NULL);
-			device_property_atomic_update_end ();		
-		}
-	}
-
-	devices = hal_device_store_match_multiple_key_value_string (hald_get_gdl (),
-								    "info.category",
-								    "ac_adapter");
-	for (i = devices; i != NULL; i = g_slist_next (i)) {
-		HalDevice *d;
-		
-		d = HAL_DEVICE (i->data);
-		if (hal_device_has_property (d, "linux.pmu_type")) {
-			hal_util_grep_discard_existing_data ();
-			device_property_atomic_update_begin ();
-			ac_adapter_refresh (d, NULL);
-			device_property_atomic_update_end ();		
-		}
-	}
-
-	return TRUE;
-}
-
-/** Synthesizes a *specific* PMU object.
- *
- *  @param	fullpath	The PMU path, e.g. "/dev/pmu/info"
- *  @param	pmu_type	The type of device, e.g. PMU_TYPE_BATTERY
- */
-static void
-pmu_synthesize_item (const gchar *fullpath, int pmu_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_PMU;
-	g_strlcpy (hotplug_event->pmu.pmu_path, fullpath, sizeof (hotplug_event->pmu.pmu_path));
-	hotplug_event->acpi.acpi_type = pmu_type;
-	hotplug_event_enqueue (hotplug_event);
-}
-
-/** Scan the data structures exported by the kernel and add hotplug
- *  events for adding PMU objects.
- *
- *  @param                      TRUE if, and only if, PMU capabilities
- *                              were detected
- */
-gboolean
-pmu_synthesize_hotplug_events (void)
-{
-	gboolean ret;
-	HalDevice *computer;
-	gchar path[HAL_PATH_MAX];
-	GError *error;
-	GDir *dir;
-	gboolean has_battery_bays;
-
-	ret = FALSE;
-
-	has_battery_bays = FALSE;
-
-	if (!g_file_test ("/proc/pmu/info", G_FILE_TEST_EXISTS))
-		goto out;
-
-	ret = TRUE;
-
-	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?"));
-		goto out;
-	}
-
-	/* Set appropriate properties on the computer object */
-	hal_device_property_set_string (computer, "power_management.type", "pmu");
-
-	/* AC Adapter */
-	snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
-	pmu_synthesize_item (path, PMU_TYPE_AC_ADAPTER);
-
-	error = NULL;
-	snprintf (path, sizeof (path), "%s/pmu", get_hal_proc_path ());
-	dir = g_dir_open (path, 0, &error);
-	if (dir != NULL) {
-		const gchar *f;
-		while ((f = g_dir_read_name (dir)) != NULL) {
-			gchar buf[HAL_PATH_MAX];
-			int battery_num;
-
-			snprintf (buf, sizeof (buf), "%s/pmu/%s", get_hal_proc_path (), f);
-			if (sscanf (f, "battery_%d", &battery_num) == 1) {
-				has_battery_bays = TRUE;
-				pmu_synthesize_item (buf, PMU_TYPE_BATTERY);
-			}
-			
-		}
-	} else {
-		HAL_ERROR (("Couldn't open %s: %s", path, error->message));
-		g_error_free (error);
-	}
-
-	/* close directory */
-	g_dir_close (dir);
-
-	/* We need to make another assumption - that there is a lid button,
-	 * if, and only if, the machine has got battery bays
-	 */
-	if (has_battery_bays) {
-		/* Add lid button */
-		snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
-		pmu_synthesize_item (path, PMU_TYPE_LID_BUTTON);
-
-		/* Add Laptop Panel */
-		snprintf (path, sizeof (path), "%s/pmu/info", get_hal_proc_path ());
-		pmu_synthesize_item (path, PMU_TYPE_LAPTOP_PANEL);
-
-		/* If the machine has got battery bays then this is a laptop. */
-		hal_device_property_set_string (computer, "system.formfactor", "laptop");
-	}
-
-	/* setup timer for things that we need to poll */
-	g_timeout_add (PMU_POLL_INTERVAL,
-		       pmu_poll,
-		       NULL);
-
-out:
-	return ret;
-}
-
-static HalDevice *
-pmu_generic_add (const gchar *pmu_path, HalDevice *parent, PMUDevHandler *handler)
-{
-	HalDevice *d;
-	d = hal_device_new ();
-	hal_device_property_set_string (d, "linux.pmu_path", pmu_path);
-	hal_device_property_set_int (d, "linux.pmu_type", handler->pmu_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
-pmu_generic_compute_udi (HalDevice *d, PMUDevHandler *handler)
-{
-	gchar udi[256];
-	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
-			      "/org/freedesktop/Hal/devices/pmu_%s_%d",
-			      hal_util_get_last_element (hal_device_property_get_string (d, "linux.pmu_path")),
-			      hal_device_property_get_int (d, "linux.pmu_type"));
-	hal_device_set_udi (d, udi);
-	hal_device_property_set_string (d, "info.udi", udi);
-	return TRUE;
-}
-
-static gboolean
-pmu_generic_remove (HalDevice *d, PMUDevHandler *handler)
-{
-	if (!hal_device_store_remove (hald_get_gdl (), d)) {
-		HAL_WARNING (("Error removing device"));
-	}
-
-	return TRUE;
-}
-
-static PMUDevHandler pmudev_handler_battery = { 
-	.pmu_type    = PMU_TYPE_BATTERY,
-	.add         = pmu_generic_add,
-	.compute_udi = pmu_generic_compute_udi,
-	.refresh     = battery_refresh,
-	.remove      = pmu_generic_remove
-};
-
-static PMUDevHandler pmudev_handler_ac_adapter = { 
-	.pmu_type    = PMU_TYPE_AC_ADAPTER,
-	.add         = pmu_generic_add,
-	.compute_udi = pmu_generic_compute_udi,
-	.refresh     = ac_adapter_refresh,
-	.remove      = pmu_generic_remove
-};
-
-static PMUDevHandler pmudev_handler_lid_button = { 
-	.pmu_type    = PMU_TYPE_LID_BUTTON,
-	.add         = pmu_generic_add,
-	.compute_udi = pmu_lid_compute_udi,
-	.refresh     = lid_button_refresh,
-	.remove      = pmu_generic_remove
-};
-
-static PMUDevHandler pmudev_handler_laptop_panel = { 
-	.pmu_type    = PMU_TYPE_LAPTOP_PANEL,
-	.add         = pmu_generic_add,
-	.compute_udi = pmu_laptop_panel_compute_udi,
-	.refresh     = laptop_panel_refresh,
-	.remove      = pmu_generic_remove
-};
-
-static PMUDevHandler *pmu_handlers[] = {
-	&pmudev_handler_battery,
-	&pmudev_handler_ac_adapter,
-	&pmudev_handler_lid_button,
-	&pmudev_handler_laptop_panel,
-	NULL
-};
-
-void
-hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token)
-{
-	guint i;
-
-	HAL_INFO (("pmu_add: pmu_path=%s pmu_type=%d, parent=0x%08x", pmu_path, pmu_type, parent));
-
-	for (i = 0; pmu_handlers [i] != NULL; i++) {
-		PMUDevHandler *handler;
-
-		handler = pmu_handlers[i];
-		if (handler->pmu_type == pmu_type) {
-			HalDevice *d;
-
-			d = handler->add (pmu_path, parent, handler);
-			if (d == NULL) {
-				/* didn't find anything - thus, ignore this hotplug event */
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_PMU);
-
-			/* 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);
-
-			/* TODO: Run callouts */
-			
-			/* Compute UDI */
-			if (!handler->compute_udi (d, handler)) {
-				hal_device_store_remove (hald_get_tdl (), d);
-				hotplug_event_end (end_token);
-				goto out;
-			}
-
-			/* 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);
-			goto out;
-		}
-	}
-	
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out:
-	;
-}
-
-void
-hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token)
-{
-	guint i;
-	HalDevice *d;
-
-	HAL_INFO (("pmu_rem: pmu_path=%s pmu_type=%d", pmu_path, pmu_type));
-
-	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.pmu_path", pmu_path);
-	if (d == NULL) {
-		HAL_WARNING (("Couldn't remove device with pmu path %s - not found", pmu_path));
-		goto out;
-	}
-
-	for (i = 0; pmu_handlers [i] != NULL; i++) {
-		PMUDevHandler *handler;
-
-		handler = pmu_handlers[i];
-		if (handler->pmu_type == pmu_type) {
-			if (handler->remove (d, handler)) {
-				hotplug_event_end (end_token);
-				goto out2;
-			}
-		}
-	}
-out:
-	/* didn't find anything - thus, ignore this hotplug event */
-	hotplug_event_end (end_token);
-out2:
-	;
-}
-
-gboolean
-pmu_rescan_device (HalDevice *d)
-{
-	guint i;
-	gboolean ret;
-	int pmu_type;
-
-	ret = FALSE;
-
-	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
-
-	for (i = 0; pmu_handlers [i] != NULL; i++) {
-		PMUDevHandler *handler;
-
-		handler = pmu_handlers[i];
-		if (handler->pmu_type == pmu_type) {
-			ret = handler->refresh (d, handler);
-			goto out;
-		}
-	}
-
-	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));
-
-out:
-	return ret;
-}
-
-HotplugEvent *
-pmu_generate_add_hotplug_event (HalDevice *d)
-{
-	int pmu_type;
-	const char *pmu_path;
-	HotplugEvent *hotplug_event;
-
-	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
-	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_ADD;
-	hotplug_event->type = HOTPLUG_EVENT_PMU;
-	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
-	hotplug_event->pmu.pmu_type = pmu_type;
-	return hotplug_event;
-}
-
-HotplugEvent *
-pmu_generate_remove_hotplug_event (HalDevice *d)
-{
-	int pmu_type;
-	const char *pmu_path;
-	HotplugEvent *hotplug_event;
-
-	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
-	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");
-
-	hotplug_event = g_new0 (HotplugEvent, 1);
-	hotplug_event->action = HOTPLUG_ACTION_REMOVE;
-	hotplug_event->type = HOTPLUG_EVENT_PMU;
-	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
-	hotplug_event->pmu.pmu_type = pmu_type;
-	return hotplug_event;
-}
diff --git a/hald/linux2/pmu.h b/hald/linux2/pmu.h
deleted file mode 100644
index c8304b3..0000000
--- a/hald/linux2/pmu.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.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.
- *
- * 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
- *
- **************************************************************************/
-
-#ifndef PMU_H
-#define PMU_H
-
-#include "../hald.h"
-#include "hotplug.h"
-
-gboolean pmu_synthesize_hotplug_events (void);
-
-void hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token);
-
-void hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token);
-
-gboolean pmu_rescan_device (HalDevice *d);
-
-HotplugEvent *pmu_generate_add_hotplug_event (HalDevice *d);
-
-HotplugEvent *pmu_generate_remove_hotplug_event (HalDevice *d);
-
-#endif /* PMU_H */
diff --git a/hald/linux2/probing/.gitignore b/hald/linux2/probing/.gitignore
deleted file mode 100644
index 226a9db..0000000
--- a/hald/linux2/probing/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-*.lo
-*.la
-hald-probe-hiddev
-hald-probe-input
-hald-probe-pc-floppy
-hald-probe-printer
-hald-probe-smbios
-hald-probe-storage
-hald-probe-volume
-hald-probe-serial
-*.o
-*~
diff --git a/hald/linux2/probing/Makefile.am b/hald/linux2/probing/Makefile.am
deleted file mode 100644
index a9f0342..0000000
--- a/hald/linux2/probing/Makefile.am
+++ /dev/null
@@ -1,39 +0,0 @@
-
-INCLUDES = \
-	-DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \
-	-DPACKAGE_DATA_DIR=\""$(datadir)"\" \
-	-DPACKAGE_BIN_DIR=\""$(bindir)"\" \
-	-DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\" \
-	-DPACKAGE_LOCALSTATEDIR=\""$(localstatedir)"\" \
-	-I$(top_srcdir) \
-	@GLIB_CFLAGS@ @DBUS_CFLAGS@
-
-if HALD_COMPILE_LINUX2
-libexec_PROGRAMS = hald-probe-input hald-probe-hiddev hald-probe-storage hald-probe-volume hald-probe-printer \
-	           hald-probe-pc-floppy hald-probe-smbios hald-probe-serial
-endif
-
-hald_probe_smbios_SOURCES = probe-smbios.c ../../logger.c
-hald_probe_smbios_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_probe_printer_SOURCES = probe-printer.c ../../logger.c
-hald_probe_printer_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@
-#TODO : get rid of glib in hald_probe_printer
-
-hald_probe_input_SOURCES = probe-input.c ../../logger.c
-hald_probe_input_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_probe_hiddev_SOURCES = probe-hiddev.c ../../logger.c
-hald_probe_hiddev_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_probe_serial_SOURCES = probe-serial.c ../../logger.c
-hald_probe_serial_LDADD = $(top_builddir)/libhal/libhal.la
-
-hald_probe_storage_SOURCES = probe-storage.c linux_dvd_rw_utils.c linux_dvd_rw_utils.h ../../logger.c
-hald_probe_storage_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ @VOLUME_ID_LIBS@
-
-hald_probe_pc_floppy_SOURCES = probe-pc-floppy.c ../../logger.c
-
-hald_probe_volume_SOURCES = probe-volume.c linux_dvd_rw_utils.c ../../logger.c 
-hald_probe_volume_LDADD = $(top_builddir)/libhal/libhal.la @GLIB_LIBS@ @VOLUME_ID_LIBS@
-
diff --git a/hald/linux2/probing/linux_dvd_rw_utils.c b/hald/linux2/probing/linux_dvd_rw_utils.c
deleted file mode 100644
index a75a091..0000000
--- a/hald/linux2/probing/linux_dvd_rw_utils.c
+++ /dev/null
@@ -1,818 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
- *
- * This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
- *
- * Use-it-on-your-own-risk, GPL bless...
- *
- * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
-*/
-
-#include <glib.h>
-
-#define CREAM_ON_ERRNO(s)	do {				\
-    switch ((s)[2]&0x0F)					\
-    {	case 2:	if ((s)[12]==4) errno=EAGAIN;	break;		\
-	case 5:	errno=EINVAL;					\
-		if ((s)[13]==0)					\
-		{   if ((s)[12]==0x21)		errno=ENOSPC;	\
-		    else if ((s)[12]==0x20)	errno=ENODEV;	\
-		}						\
-		break;						\
-    }								\
-} while(0)
-#define ERRCODE(s)	((((s)[2]&0x0F)<<16)|((s)[12]<<8)|((s)[13]))
-#define	SK(errcode)	(((errcode)>>16)&0xF)
-#define	ASC(errcode)	(((errcode)>>8)&0xFF)
-#define ASCQ(errcode)	((errcode)&0xFF)
-
-#ifndef _LARGEFILE_SOURCE
-#define _LARGEFILE_SOURCE
-#endif
-#ifndef _LARGEFILE64_SOURCE
-#define _LARGEFILE64_SOURCE
-#endif
-#ifndef _FILE_OFFSET_BITS
-#define _FILE_OFFSET_BITS 64
-#endif
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <linux/cdrom.h>
-#include <errno.h>
-#include <string.h>
-#include <mntent.h>
-#include <sys/wait.h>
-#include <sys/utsname.h>
-#include <scsi/scsi.h>
-#include <scsi/sg.h>
-#include <poll.h>
-#include <sys/time.h>
-
-#include "linux_dvd_rw_utils.h"
-
-typedef enum {
-	NONE = CGC_DATA_NONE,	// 3
-	READ = CGC_DATA_READ,	// 2
-	WRITE = CGC_DATA_WRITE	// 1
-} Direction;
-
-typedef struct ScsiCommand ScsiCommand;
-
-struct ScsiCommand {
-	int fd;
-	int autoclose;
-	char *filename;
-	struct cdrom_generic_command cgc;
-	union {
-		struct request_sense s;
-		unsigned char u[18];
-	} _sense;
-	struct sg_io_hdr sg_io;
-};
-
-#define DIRECTION(i) (Dir_xlate[i]);
-
-/* 1,CGC_DATA_WRITE
- * 2,CGC_DATA_READ
- * 3,CGC_DATA_NONE
- */
-const int Dir_xlate[4] = {
-	0,			// implementation-dependent...
-	SG_DXFER_TO_DEV,	// 1,CGC_DATA_WRITE
-	SG_DXFER_FROM_DEV,	// 2,CGC_DATA_READ
-	SG_DXFER_NONE		// 3,CGC_DATA_NONE
-};
-
-static ScsiCommand *
-scsi_command_new (void)
-{
-	ScsiCommand *cmd;
-
-	cmd = (ScsiCommand *) malloc (sizeof (ScsiCommand));
-	memset (cmd, 0, sizeof (ScsiCommand));
-	cmd->fd = -1;
-	cmd->filename = NULL;
-	cmd->autoclose = 1;
-
-	return cmd;
-}
-
-static ScsiCommand *
-scsi_command_new_from_fd (int f)
-{
-	ScsiCommand *cmd;
-
-	cmd = scsi_command_new ();
-	cmd->fd = f;
-	cmd->autoclose = 0;
-
-	return cmd;
-}
-
-static void
-scsi_command_free (ScsiCommand * cmd)
-{
-	if (cmd->fd >= 0 && cmd->autoclose) {
-		close (cmd->fd);
-		cmd->fd = -1;
-	}
-	if (cmd->filename) {
-		free (cmd->filename);
-		cmd->filename = NULL;
-	}
-
-	free (cmd);
-}
-
-static int
-scsi_command_transport (ScsiCommand * cmd, Direction dir, void *buf,
-			size_t sz)
-{
-	int ret = 0;
-
-	cmd->sg_io.dxferp = buf;
-	cmd->sg_io.dxfer_len = sz;
-	cmd->sg_io.dxfer_direction = DIRECTION (dir);
-
-	if (ioctl (cmd->fd, SG_IO, &cmd->sg_io))
-		return -1;
-
-	if ((cmd->sg_io.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
-		errno = EIO;
-		ret = -1;
-		if (cmd->sg_io.masked_status & CHECK_CONDITION) {
-			CREAM_ON_ERRNO (cmd->sg_io.sbp);
-			ret = ERRCODE (cmd->sg_io.sbp);
-			if (ret == 0)
-				ret = -1;
-		}
-	}
-
-	return ret;
-}
-
-static void
-scsi_command_init (ScsiCommand * cmd, size_t i, int arg)
-{
-	if (i == 0) {
-		memset (&cmd->cgc, 0, sizeof (cmd->cgc));
-		memset (&cmd->_sense, 0, sizeof (cmd->_sense));
-		cmd->cgc.quiet = 1;
-		cmd->cgc.sense = &cmd->_sense.s;
-		memset (&cmd->sg_io, 0, sizeof (cmd->sg_io));
-		cmd->sg_io.interface_id = 'S';
-		cmd->sg_io.mx_sb_len = sizeof (cmd->_sense);
-		cmd->sg_io.cmdp = cmd->cgc.cmd;
-		cmd->sg_io.sbp = cmd->_sense.u;
-		cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO;
-	}
-	cmd->sg_io.cmd_len = i + 1;
-	cmd->cgc.cmd[i] = arg;
-}
-
-int
-get_dvd_r_rw_profile (int fd)
-{
-	ScsiCommand *cmd;
-	int retval = 0;
-	unsigned char page[20];
-	unsigned char *list;
-	int i, len;
-
-	cmd = scsi_command_new_from_fd (fd);
-
-	scsi_command_init (cmd, 0, 0x46);
-	scsi_command_init (cmd, 1, 2);
-	scsi_command_init (cmd, 8, 8);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, page, 8)) {
-		/* GET CONFIGURATION failed */
-		scsi_command_free (cmd);
-		return -1;
-	}
-
-	/* See if it's 2 gen drive by checking if DVD+R profile is an option */
-	len = 4 + (page[0] << 24 | page[1] << 16 | page[2] << 8 | page[3]);
-	if (len > 264) {
-		scsi_command_free (cmd);
-		/* insane profile list length */
-		return -1;
-	}
-
-	list = (unsigned char *) malloc (len);
-
-	scsi_command_init (cmd, 0, 0x46);
-	scsi_command_init (cmd, 1, 2);
-	scsi_command_init (cmd, 7, len >> 8);
-	scsi_command_init (cmd, 8, len);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, list, len)) {
-		/* GET CONFIGURATION failed */
-		scsi_command_free (cmd);
-		free (list);
-		return -1;
-	}
-
-	for (i = 12; i < list[11]; i += 4) {
-		int profile = (list[i] << 8 | list[i + 1]);
-		/* 0x13: DVD-RW Restricted Overwrite
-		 * 0x14: DVD-RW Sequential
-		 * 0x1B: DVD+R 
-		 * 0x1A: DVD+RW  
-		 * 0x2A: DVD+RW DL
-		 * 0x2B: DVD+R DL 
-		 */
-
-		switch (profile) {
-			case 0x13:
-			case 0x14:
-				retval |= DRIVE_CDROM_CAPS_DVDRW;
-				break;
-			case 0x1B:
-				retval |= DRIVE_CDROM_CAPS_DVDPLUSR;
-				break;
-			case 0x1A:
-				retval |= DRIVE_CDROM_CAPS_DVDPLUSRW;
-				break;
-			case 0x2A:
-				retval |= DRIVE_CDROM_CAPS_DVDPLUSRWDL;
-				break;
-			case 0x2B:
-				retval |= DRIVE_CDROM_CAPS_DVDPLUSRDL;
-				break;
-			default:
-				break;
-		}
-	}
-
-	scsi_command_free (cmd);
-	free (list);
-	
-	return retval;
-	
-}
-
-static unsigned char *
-pull_page2a_from_fd (int fd)
-{
-	ScsiCommand *cmd;
-	unsigned char header[12], *page2A;
-	unsigned int len, bdlen;
-
-	cmd = scsi_command_new_from_fd (fd);
-
-	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
-	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
-	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
-	scsi_command_init (cmd, 8, sizeof (header));	/* header only to start with */
-	scsi_command_init (cmd, 9, 0);
-
-	if (scsi_command_transport (cmd, READ, header, sizeof (header))) {
-		/* MODE SENSE failed */
-		scsi_command_free (cmd);
-		return NULL;
-	}
-
-	len = (header[0] << 8 | header[1]) + 2;
-	bdlen = header[6] << 8 | header[7];
-
-	/* should never happen as we set "DBD" above */
-	if (bdlen) {
-		if (len < (8 + bdlen + 30)) {
-			/* LUN impossible to bear with */
-			scsi_command_free (cmd);
-			return NULL;
-		}
-	} else if (len < (8 + 2 + (unsigned int) header[9])) {
-		/* SANYO does this. */
-		len = 8 + 2 + header[9];
-	}
-
-	page2A = (unsigned char *) malloc (len);
-	if (page2A == NULL) {
-		/* ENOMEM */
-		scsi_command_free (cmd);
-		return NULL;
-	}
-
-	scsi_command_init (cmd, 0, 0x5A);	/* MODE SENSE */
-	scsi_command_init (cmd, 1, 0x08);	/* Disable Block Descriptors */
-	scsi_command_init (cmd, 2, 0x2A);	/* Capabilities and Mechanical Status */
-	scsi_command_init (cmd, 7, len >> 8);
-	scsi_command_init (cmd, 8, len);	/* Real length */
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, page2A, len)) {
-		/* MODE SENSE failed */
-		scsi_command_free (cmd);
-		free (page2A);
-		return NULL;
-	}
-
-	scsi_command_free (cmd);
-
-	len -= 2;
-	/* paranoia */
-	if (len < ((unsigned int) page2A[0] << 8 | page2A[1])) {
-		page2A[0] = len >> 8;
-		page2A[1] = len;
-	}
-
-	return page2A;
-}
-
-static int
-int_compare (const void *a, const void *b)
-{
-	/* descending order */
-	return *((int *) b) - *((int *) a);
-}
-
-/* gets the list of supported write speeds.  in the event
- * that anything goes wrong, returns NULL.
- */
-static char *
-get_write_speeds (const unsigned char *p, int length, int max_speed)
-{
-	char *result, *str;
-	int nr_records;
-	int *tmpspeeds;
-	int i, j;
-
-	result = NULL;
-
-	/* paranoia */
-	if (length < 32)
-		return NULL;
-
-	nr_records = p[30] << 8 | p[31];
-
-	/* paranoia */
-	if (length < 32 + 4 * nr_records)
-		return NULL;
-
-	tmpspeeds = malloc (nr_records * sizeof (int));
-
-	for (i = 0; i < nr_records; i++)
-	{
-		tmpspeeds[i] = p[4*i + 34] << 8 | p[4*i + 35];
-
-		/* i'm not sure how likely this is to show up, but it's
-		 * definitely wrong.  if we see it, abort.
-		 */
-		if (tmpspeeds[i] == 0)
-			goto free_tmpspeeds;
-	}
-
-	/* sort */
-	qsort (tmpspeeds, nr_records, sizeof (int), int_compare);
-
-	/* uniq */
-	for (i = j = 0; i < nr_records; i++)
-	{
-		tmpspeeds[j] = tmpspeeds[i];
-
-		/* make sure we don't look past the end of the array */
-		if (i >= (nr_records - 1) || tmpspeeds[i+1] != tmpspeeds[i])
-			j++;
-	}
-
-	/* j is now the number of unique entries in the array */
-	if (j == 0)
-		/* no entries?  this isn't right. */
-		goto free_tmpspeeds;
-
-	/* sanity check: the first item in the descending order
-	 * list ought to be the highest speed as detected through
-	 * other means
-	 */
-	if (tmpspeeds[0] != max_speed)
-		/* sanity check failed. */
-		goto free_tmpspeeds;
-
-	/* our values are 16-bit.  8 bytes per value
-	 * is more than enough including space for
-	 * ',' and '\0'.  we know j is not zero.
-	 */
-	result = str = malloc (8 * j);
-
-	for (i = 0; i < j; i++)
-	{
-		if (i > 0)
-			*(str++) = ',';
-
-		str += sprintf (str, "%d", tmpspeeds[i]);
-	}
-
-free_tmpspeeds:
-	free (tmpspeeds);
-
-	return result;
-}
-
-int
-get_read_write_speed (int fd, int *read_speed, int *write_speed, char **write_speeds)
-{
-	unsigned char *page2A;
-	int len, hlen;
-	unsigned char *p;
-
-	*read_speed = 0;
-	*write_speed = 0;
-	*write_speeds = NULL;
-
-	page2A = pull_page2a_from_fd (fd);
-	if (page2A == NULL) {
-		printf ("Failed to get Page 2A\n");
-		/* Failed to get Page 2A */
-		return -1;
-	}
-
-	len = (page2A[0] << 8 | page2A[1]) + 2;
-	hlen = 8 + (page2A[6] << 8 | page2A[7]);
-	p = page2A + hlen;
-
-	/* Values guessed from the cd_mode_page_2A struct
-	 * in cdrecord's libscg/scg/scsireg.h */
-	if (len < (hlen + 30) || p[1] < (30 - 2)) {
-		/* no MMC-3 "Current Write Speed" present,
-		 * try to use the MMC-2 one */
-		if (len < (hlen + 20) || p[1] < (20 - 2))
-			*write_speed = 0;
-		else
-			*write_speed = p[18] << 8 | p[19];
-	} else {
-		*write_speed = p[28] << 8 | p[29];
-	}
-
-	if (len >= hlen+9)
-	    *read_speed = p[8] << 8 | p[9];
-	else
-	    *read_speed = 0;
-
-	*write_speeds = get_write_speeds (p, len, *write_speed);
-
-	free (page2A);
-
-	return 0;
-}
-
-
-static int
-get_disc_capacity_cd (int fd,
-		      guint64 *size)
-{
-	ScsiCommand *cmd;
-	int retval;
-	guint64 block_size;
-	guint64 num_blocks;
-	unsigned char header [8];
-
-	retval = -1;
-
-	cmd = scsi_command_new_from_fd (fd);
-	scsi_command_init (cmd, 0, 0x25);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, header, 8)) {
-		/* READ CDROM CAPACITY failed */
-		goto done;
-	}
-
-	num_blocks = (header [0] << 24) | (header [1] << 16) | (header [2] << 8) | header [3];
-	num_blocks++;
-	block_size = header [4] << 24 | header [5] << 16 | header [6] << 8 | header [7];
-
-	if (size) {
-		*size = num_blocks * block_size;
-	}
-	retval = 0;
-
- done:
-	scsi_command_free (cmd);
-
-	return retval;
-}
-
-static int
-get_disc_capacity_cdr (int fd,
-		       guint64 *size)
-{
-	ScsiCommand *cmd;
-	int retval;
-	guint64 secs;
-	unsigned char toc [8];
-	unsigned char *atip;
-	int len;
-
-	retval = -1;
-
-	cmd = scsi_command_new_from_fd (fd);
-	/* READ_TOC */
-	scsi_command_init (cmd, 0, 0x43);
-	/* FMT_ATIP */
-	scsi_command_init (cmd, 2, 4 & 0x0F);
-	scsi_command_init (cmd, 6, 0);
-	scsi_command_init (cmd, 8, 4);
-	scsi_command_init (cmd, 9, 0);
-
-	if (scsi_command_transport (cmd, READ, toc, 4)) {
-		/* READ TOC failed */
-		goto done;
-	}
-
-	len = 2 + (toc [0] << 8 | toc [1]);
-
-	atip = (unsigned char *) malloc (len);
-
-	scsi_command_init (cmd, 0, 0x43);
-	scsi_command_init (cmd, 2, 4 & 0x0F);
-	scsi_command_init (cmd, 6, 0);
-	scsi_command_init (cmd, 7, len >> 8);
-	scsi_command_init (cmd, 8, len);
-	scsi_command_init (cmd, 9, 0);
-
-	if (scsi_command_transport (cmd, READ, atip, len)) {
-		/* READ TOC failed */
-		free (atip);
-		goto done;
-	}
-
-	secs = atip [12] * 60 + atip [13] + (atip [14] / 75 + 1);
-
-	if (size) {
-		*size = (1 + secs * 7 / 48) * 1024 * 1024;
-	}
-	retval = 0;
-
-	free (atip);
- done:
-	scsi_command_free (cmd);
-
-	return retval;
-}
-
-static int
-get_disc_capacity_dvdr_from_type (int fd,
-				  int type,
-				  guint64 *size)
-{
-	ScsiCommand *cmd;
-	unsigned char formats [260];
-	unsigned char buf [32];
-	guint64 blocks;
-	guint64 nwa;
-	int i;
-	int len;
-	int obligatory;
-	int retval;
-	int next_track;
-
-	retval = -1;
-	blocks = 0;
-	next_track = 1;
-
-	cmd = scsi_command_new_from_fd (fd);
-
- retry:
-	if (type == 0x1A || type == 0x14 || type == 0x13 || type == 0x12) {
-
-		/* READ FORMAT CAPACITIES */
-		scsi_command_init (cmd, 0, 0x23);
-		scsi_command_init (cmd, 8, 12);
-		scsi_command_init (cmd, 9, 0);
-		if (scsi_command_transport (cmd, READ, formats, 12)) {
-			/* READ FORMAT CAPACITIES failed */
-			goto done;
-		}
-
-		len = formats [3];
-		if (len & 7 || len < 16) {
-			/* Length isn't sane */
-			goto done;
-		}
-
-		scsi_command_init (cmd, 0, 0x23);
-		scsi_command_init (cmd, 7, (4 + len) >> 8);
-		scsi_command_init (cmd, 8, (4 + len) & 0xFF);
-		scsi_command_init (cmd, 9, 0);
-		if (scsi_command_transport (cmd, READ, formats, 4 + len)) {
-			/* READ FORMAT CAPACITIES failed */
-			goto done;
-		}
-
-		if (len != formats [3]) {
-			/* Parameter length inconsistency */
-			goto done;
-		}
-	}
-
-	obligatory = 0x00;
-
-	switch (type) {
-    	case 0x1A:		/* DVD+RW */
-		obligatory = 0x26;
-	case 0x13:		/* DVD-RW Restricted Overwrite */
-	case 0x14:		/* DVD-RW Sequential */
-		for (i = 8, len = formats [3]; i < len; i += 8) {
-			if ((formats [4 + i + 4] >> 2) == obligatory) {
-				break;
-			}
-		}
-
-		if (i == len) {
-			/* Can't find obligatory format descriptor */
-			goto done;
-		}
-
-		blocks  = formats [4 + i + 0] << 24;
-		blocks |= formats [4 + i + 1] << 16;
-		blocks |= formats [4 + i + 2] << 8;
-		blocks |= formats [4 + i + 3];
-		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
-		if (nwa > 2048) {
-			blocks *= nwa / 2048;
-		} else if (nwa < 2048) {
-			blocks /= 2048 / nwa;
-		}
-
-		retval = 0;
-		break;
-
-	case 0x12:		/* DVD-RAM */
-
-		blocks  = formats [4 + 0] << 24;
-		blocks |= formats [4 + 1] << 16;
-		blocks |= formats [4 + 2] << 8;
-		blocks |= formats [4 + 3];
-		nwa = formats [4 + 5] << 16 | formats [4 + 6] << 8 | formats [4 + 7];
-		if (nwa > 2048) {
-			blocks *= nwa / 2048;
-		} else if (nwa < 2048) {
-			blocks /= 2048 / nwa;
-		}
-
-		retval = 0;
-		break;
-
-	case 0x11:		/* DVD-R */
-	case 0x1B:		/* DVD+R */
-	case 0x2B:		/* DVD+R Double Layer */
-
-		/* READ TRACK INFORMATION */
-		scsi_command_init (cmd, 0, 0x52);
-		scsi_command_init (cmd, 1, 1);
-		scsi_command_init (cmd, 4, next_track >> 8);
-		scsi_command_init (cmd, 5, next_track & 0xFF);
-		scsi_command_init (cmd, 8, sizeof (buf));
-		scsi_command_init (cmd, 9, 0);
-		if (scsi_command_transport (cmd, READ, buf, sizeof (buf))) {
-			/* READ TRACK INFORMATION failed */
-			if (next_track > 0) {
-				goto done;
-			} else {
-				next_track = 1;
-				goto retry;
-			}
-		}
-
-		blocks = buf [24] << 24;
-		blocks |= buf [25] << 16;
-		blocks |= buf [26] << 8;
-		blocks |= buf [27];
-
-		retval = 0;
-		break;
-	default:
-		blocks = 0;
-		break;
-	}
-
- done:
-	scsi_command_free (cmd);
-
-	if (size) {
-		*size = blocks * 2048;
-	}
-
-	return retval;
-}
-
-int
-get_disc_capacity_for_type (int fd,
-			    int type,
-			    guint64 *size)
-{
-	int retval;
-
-	retval = -1;
-
-	switch (type) {
-	case 0x8:
-		retval = get_disc_capacity_cd (fd, size);
-		break;
-	case 0x9:
-	case 0xa:
-		retval = get_disc_capacity_cdr (fd, size);
-		break;
-	case 0x10:
-		retval = get_disc_capacity_cd (fd, size);
-		break;
-	case 0x11:
-	case 0x13:
-	case 0x14:
-	case 0x1B:
-	case 0x2B:
-	case 0x1A:
-	case 0x12:
-		retval = get_disc_capacity_dvdr_from_type (fd, type, size);
-		break;
-	default:
-		retval = -1;
-	}
-
-	return retval;
-}
-
-int
-get_disc_type (int fd)
-{
-	ScsiCommand *cmd;
-	int retval = -1;
-	unsigned char header[8];
-
-	cmd = scsi_command_new_from_fd (fd);
-
-	scsi_command_init (cmd, 0, 0x46);
-	scsi_command_init (cmd, 1, 1);
-	scsi_command_init (cmd, 8, 8);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, header, 8)) {
-		/* GET CONFIGURATION failed */
-		scsi_command_free (cmd);
-		return -1;
-	}
-	
-	retval = (header[6]<<8)|(header[7]);
-
-
-	scsi_command_free (cmd);
-	return retval;
-}
-
-
-int
-disc_is_appendable (int fd)
-{
-	ScsiCommand *cmd;
-	int retval = -1;
-	unsigned char header[32];
-
-	cmd = scsi_command_new_from_fd (fd);
-
-	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
-	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
-	scsi_command_init (cmd, 8, 32);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, header, 32)) {
-		/* READ_DISC_INFORMATION failed */
-		scsi_command_free (cmd);
-		return 0;
-	}
-	
-	retval = ((header[2]&0x03) == 0x01);
-
-	scsi_command_free (cmd);
-	return retval;
-}
-
-int
-disc_is_rewritable (int fd)
-{
-	ScsiCommand *cmd;
-	int retval = -1;
-	unsigned char header[32];
-
-	cmd = scsi_command_new_from_fd (fd);
-
-	/* see section 5.19 of MMC-3 from http://www.t10.org/drafts.htm#mmc3 */
-	scsi_command_init (cmd, 0, 0x51); /* READ_DISC_INFORMATION */
-	scsi_command_init (cmd, 8, 32);
-	scsi_command_init (cmd, 9, 0);
-	if (scsi_command_transport (cmd, READ, header, 32)) {
-		/* READ_DISC_INFORMATION failed */
-		scsi_command_free (cmd);
-		return 0;
-	}
-	
-	retval = ((header[2]&0x10) != 0);
-
-	scsi_command_free (cmd);
-	return retval;
-}
diff --git a/hald/linux2/probing/linux_dvd_rw_utils.h b/hald/linux2/probing/linux_dvd_rw_utils.h
deleted file mode 100644
index 5b6105a..0000000
--- a/hald/linux2/probing/linux_dvd_rw_utils.h
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-// This is part of dvd+rw-tools by Andy Polyakov <appro at fy.chalmers.se>
-//
-// Use-it-on-your-own-risk, GPL bless...
-//
-// For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/
-//
-
-#ifndef LINUX_DVD_RW_UTILS_H
-#define LINUX_DVD_RW_UTILS_H
-
-#include <glib.h>
-
-#define DRIVE_CDROM_CAPS_DVDRW        1
-#define DRIVE_CDROM_CAPS_DVDPLUSR     2
-#define DRIVE_CDROM_CAPS_DVDPLUSRW    4
-#define DRIVE_CDROM_CAPS_DVDPLUSRWDL  8
-#define DRIVE_CDROM_CAPS_DVDPLUSRDL  16
-
-int get_dvd_r_rw_profile (int fd);
-int get_read_write_speed (int fd, int *read_speed, int *write_speed, char **write_speeds);
-int get_disc_capacity_for_type (int fd, int type, guint64 *capacity);
-int get_disc_type (int fd);
-int disc_is_appendable (int fd);
-int disc_is_rewritable (int fd);
-
-#endif				/* LINUX_DVD_RW_UTILS_H */
diff --git a/hald/linux2/probing/probe-hiddev.c b/hald/linux2/probing/probe-hiddev.c
deleted file mode 100644
index fbc1861..0000000
--- a/hald/linux2/probing/probe-hiddev.c
+++ /dev/null
@@ -1,171 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-input.c : Probe input devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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
-
-/* asm/types.h required for __s32 in linux/hiddev.h */
-#include <asm/types.h>
-#include <fcntl.h>
-#include <linux/hiddev.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char name[256] = "Unknown HID device";
-	unsigned int i;
-	struct hiddev_devinfo device_info;
-
-	fd = -1;
-
-	/* assume failure */
-	ret = 1;
-
-	udi = getenv ("UDI");
-	if (udi == NULL)
-		goto out;
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	device_file = getenv ("HAL_PROP_HIDDEV_DEVICE");
-	if (device_file == NULL)
-		goto out;
-
-	fd = open (device_file, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	if (ioctl (fd, HIDIOCGNAME(sizeof (name)), name) >= 0) {
-		if (!libhal_device_set_property_string (ctx, udi, "hiddev.product", name, &error))
-			goto out;
-		if (!libhal_device_set_property_string (ctx, udi, "info.product", name, &error))
-			goto out;
-	}
-
-	if (ioctl (fd, HIDIOCGDEVINFO, &device_info) < 0)
-		goto out;
-
-	for (i = 0; i < device_info.num_applications; i++) {
-		int appl;
-		const char *appl_name;
-		char buf[256];
-
-		if ((appl = ioctl(fd, HIDIOCAPPLICATION, i)) < 0)
-			goto out;
-
-		/* The magic values come from various usage table specs */
-		switch (appl >> 16)
-		{
-		case 0x01 :
-			appl_name = "Generic Desktop Page";
-			break;
-		case 0x0c :
-			appl_name = "Consumer Product Page";
-			break;
-		case 0x80 :
-			appl_name = "USB Monitor Page";
-			break;
-		case 0x81 :
-			appl_name = "USB Enumerated Values Page";
-			break;
-		case 0x82 :
-			appl_name = "VESA Virtual Controls Page";
-			break;
-		case 0x83 :
-			appl_name = "Reserved Monitor Page";
-			break;
-		case 0x84 :
-			appl_name = "Power Device Page";
-			break;
-		case 0x85 :
-			appl_name = "Battery System Page";
-			break;
-		case 0x86 :
-		case 0x87 :
-			appl_name = "Reserved Power Device Page";
-			break;
-		default :
-			snprintf (buf, sizeof (buf), "Unknown page 0x%02x", appl);
-			appl_name = buf;
-		}
-
-		if (!libhal_device_property_strlist_append (ctx, udi, "hiddev.application_pages", appl_name, &error))
-			goto out;
-	}
-
-#if 0
-	DBusConnection *conn;
-
-	if (fork () == 0) {
-		sleep (10);
-
-		dbus_error_init (&error);
-		if ((conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error)) == NULL)
-			goto out;
-		
-		if ((ctx = libhal_ctx_new ()) == NULL)
-			goto out;
-		if (!libhal_ctx_set_dbus_connection (ctx, conn))
-			goto out;
-		if (!libhal_ctx_init (ctx, &error))
-			goto out;
-
-		main2 (ctx, "/org/freedesktop/Hal/devices/usb_device_51d_2_QB0435136106  _if0_hiddev", fd);
-	}
-	else
-		sleep (2);
-#endif
-
-	/* success */
-	ret = 0;
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-input.c b/hald/linux2/probing/probe-input.c
deleted file mode 100644
index 6a18990..0000000
--- a/hald/linux2/probing/probe-input.c
+++ /dev/null
@@ -1,230 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-input.c : Probe input devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <linux/input.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-
-/* we must use this kernel-compatible implementation */
-#define BITS_PER_LONG (sizeof(long) * 8)
-#define NBITS(x) ((((x)-1)/BITS_PER_LONG)+1)
-#define OFF(x)  ((x)%BITS_PER_LONG)
-#define BIT(x)  (1UL<<OFF(x))
-#define LONG(x) ((x)/BITS_PER_LONG)
-#define test_bit(bit, array)    ((array[LONG(bit)] >> OFF(bit)) & 1)
-
-static void 
-check_abs (int fd, LibHalContext *ctx, const char *udi)
-{
-	long bitmask[NBITS(ABS_MAX)];
-	long bitmask_touch[NBITS(KEY_MAX)];
-	DBusError error;
-
-	if (ioctl (fd, EVIOCGBIT(EV_ABS, sizeof (bitmask)), bitmask) < 0) {
-		HAL_DEBUG (("ioctl EVIOCGBIT for EV_ABS failed"));
-		goto out;
-	}
-
-	if (ioctl (fd, EVIOCGBIT(EV_KEY, sizeof (bitmask_touch)), bitmask_touch) < 0) {
-		HAL_DEBUG (("ioctl EVIOCGBIT for EV_KEY failed"));
-		goto out;
-	}
-	
-	if (!test_bit(ABS_X, bitmask) || !test_bit(ABS_Y, bitmask)) {
-		HAL_DEBUG (("missing x or y absolute axes"));
-		goto out;
-	}
-
-	dbus_error_init (&error);
-	if (test_bit(BTN_TOUCH, bitmask_touch) != 0) {
-		libhal_device_add_capability (ctx, udi, "input.tablet", &error);
-		goto out;
-	}
-	libhal_device_add_capability (ctx, udi, "input.joystick", &error);
-
-out:
-	;
-}
-
-static void 
-check_key (int fd, LibHalContext *ctx, const char *udi)
-{
-	unsigned int i;
-	long bitmask[NBITS(KEY_MAX)];
-	int is_keyboard;
-	DBusError error;
-
-	if (ioctl (fd, EVIOCGBIT(EV_KEY, sizeof (bitmask)), bitmask) < 0) {
-		HAL_DEBUG (("ioctl EVIOCGBIT for EV_KEY failed"));
-		goto out;
-	}
-
-	is_keyboard = FALSE;
-
-	/* All keys that are not buttons are less than BTN_MISC */
-	for (i = KEY_RESERVED + 1; i < BTN_MISC; i++) {
-		if (test_bit (i, bitmask)) {
-			is_keyboard = TRUE;
-			break;
-		}
-	}
-
-	if (is_keyboard) {
-		dbus_error_init (&error);
-		libhal_device_add_capability (ctx, udi, "input.keyboard", &error);
-	}
-
-out:
-	;
-}
-
-static void 
-check_rel (int fd, LibHalContext *ctx, const char *udi)
-{
-	long bitmask[NBITS(REL_MAX)];
-	DBusError error;
-
-	if (ioctl (fd, EVIOCGBIT(EV_REL, sizeof (bitmask)), bitmask) < 0) {
-		HAL_DEBUG (("ioctl EVIOCGBIT for EV_REL failed"));
-		goto out;
-	}
-
-	if (!test_bit (REL_X, bitmask) || !test_bit (REL_Y, bitmask)) {
-		HAL_DEBUG (("missing x or y relative axes"));
-		goto out;
-	}
-
-	dbus_error_init (&error);
-	libhal_device_add_capability (ctx, udi, "input.mouse", &error);
-
-out:
-	;
-}
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	char *physical_device;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char name[128];
-	struct input_id id;
-
-	setup_logger ();
-
-	fd = -1;
-
-	/* assume failure */
-	ret = 1;
-
-	udi = getenv ("UDI");
-	if (udi == NULL)
-		goto out;
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	device_file = getenv ("HAL_PROP_INPUT_DEVICE");
-	if (device_file == NULL)
-		goto out;
-
-	HAL_DEBUG (("Doing probe-input for %s (udi=%s)", device_file, udi));
-
-	fd = open (device_file, O_RDONLY);
-	if (fd < 0) {
-		HAL_ERROR (("Cannot open %s: %s", device_file, strerror (errno)));
-		goto out;
-	}
-
-	/* if we don't have a physical device then only accept input buses
-	 * that we now aren't hotpluggable
-	 */
-	if (ioctl (fd, EVIOCGID, &id) < 0) {
-		HAL_ERROR (("Error: EVIOCGID failed: %s\n", strerror(errno)));
-		goto out;
-	}
-	physical_device = getenv ("HAL_PROP_INPUT_PHYSICAL_DEVICE");
-
-	HAL_DEBUG (("probe-input: id.bustype=%i", id.bustype));
-	if (physical_device == NULL) {
-		switch (id.bustype) {
-		case BUS_I8042: /* x86 legacy port */
-		case BUS_HOST: /* not hotpluggable */
-		case BUS_PARPORT: /* XXX: really needed? */
-		case BUS_ADB: /* ADB on Apple computers */
-			break;
-
-		default:
-			goto out;
-		}
-	}
-
-	/* only consider devices with the event interface */
-	if (ioctl (fd, EVIOCGNAME(sizeof (name)), name) < 0) {
-		HAL_ERROR (("Error: EVIOCGNAME failed: %s\n", strerror(errno)));
-		goto out;
-	}
-	if (!libhal_device_set_property_string (ctx, udi, "info.product", name, &error))
-		goto out;
-	if (!libhal_device_set_property_string (ctx, udi, "input.product", name, &error))
-		goto out;
-
-	check_abs (fd, ctx, udi);
-	check_rel (fd, ctx, udi);
-	check_key (fd, ctx, udi);
-
-	/* success */
-	ret = 0;
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-pc-floppy.c b/hald/linux2/probing/probe-pc-floppy.c
deleted file mode 100644
index 7a66987..0000000
--- a/hald/linux2/probing/probe-pc-floppy.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-storage.c : Probe storage devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <fcntl.h>
-#include <linux/fd.h>
-#include <linux/kdev_t.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	char name[256];
-	struct floppy_drive_struct ds;
-
-	fd = -1;
-
-	/* assume failure */
-	ret = 1;
-
-	if ((udi = getenv ("UDI")) == NULL)
-		goto out;
-	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
-		goto out;
-
-	setup_logger ();
-	
-	HAL_DEBUG (("Checking if %s is actually present", device_file));
-	
-	/* Check that there actually is a drive at the other end */
-	fd = open (device_file, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		HAL_ERROR (("Could not open %s", device_file));
-		goto out;
-	}
-	
-	/* @todo Could use the name here */
-	ioctl (fd, FDRESET, NULL);
-	if (ioctl (fd, FDGETDRVTYP, name) != 0) {
-		HAL_ERROR (("FDGETDRVTYP failed for %s", device_file));
-		goto out;
-	}
-	HAL_DEBUG (("floppy drive name is '%s'", name));
-
-	if (ioctl (fd, FDPOLLDRVSTAT, &ds)) {
-		HAL_ERROR (("FDPOLLDRVSTAT failed for %s", device_file));
-		goto out;
-	}
-	
-	if (ds.track < 0) {
-		HAL_ERROR (("floppy drive %s seems not to exist", device_file));
-		goto out;
-	}
-
-	/* works */
-	ret = 0;
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-printer.c b/hald/linux2/probing/probe-printer.c
deleted file mode 100644
index bec6e9b..0000000
--- a/hald/linux2/probing/probe-printer.c
+++ /dev/null
@@ -1,176 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- *
- * 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 <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <glib.h>
-
-#include "libhal/libhal.h"
-#include "../../logger.h"
-
-/* Stolen from kernel 2.6.4, drivers/usb/class/usblp.c */
-#define IOCNR_GET_DEVICE_ID 1
-#define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char device_id[1024];
-	char **props;
-	char **iter;
-	char *mfg;
-	char *model;
-	char *serial;
-	char *desc;
-	char *cmd;
-
-	fd = -1;
-
-	/* assume failure */
-	ret = 1;
-
-	setup_logger ();
-	
-	udi = getenv ("UDI");
-	if (udi == NULL) {
-		HAL_ERROR (("UDI not set"));	
-		goto out;
-	}
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
-		HAL_ERROR (("ctx init failed"));
-		goto out;
-	}
-
-	device_file = getenv ("HAL_PROP_PRINTER_DEVICE");
-	if (device_file == NULL) {
-		HAL_ERROR (("device_file == NULL"));
-		goto out;
-	}
-
-	fd = open (device_file, O_RDONLY);
-	if (fd < 0) {
-		HAL_ERROR (("Cannot open %s", device_file));
-		goto out;
-	}
-
-	if (ioctl (fd, LPIOC_GET_DEVICE_ID (sizeof (device_id)), device_id) < 0) {
-		HAL_ERROR (("Cannot do LPIOC_GET_DEVICE_ID on %s", device_file));
-		goto out;
-	} else
-
-	mfg = NULL;
-	model = NULL;
-	serial = NULL;
-	desc = NULL;
-	cmd = NULL;
-
-	HAL_DEBUG (("device_id = %s", device_id + 2));
-
-	props = g_strsplit (device_id+2, ";", 0);
-	for (iter = props; *iter != NULL; iter++) {
-		if (strncmp (*iter, "MANUFACTURER:", 13) == 0)
-			mfg = *iter + 13;
-		else if (strncmp (*iter, "MFG:", 4) == 0)
-			mfg = *iter + 4;
-		else if (strncmp (*iter, "MODEL:", 6) == 0)
-			model = *iter + 6;
-		else if (strncmp (*iter, "MDL:", 4) == 0)
-			model = *iter + 4;
-		else if (strncmp (*iter, "SN:", 3) == 0)
-			serial = *iter + 3;
-		else if (strncmp (*iter, "SERN:", 5) == 0)
-			serial = *iter + 5;
-		else if (strncmp (*iter, "SERIALNUMBER:", 13) == 0)
-			serial = *iter + 13;
-		else if (strncmp (*iter, "DES:", 4) == 0)
-			desc = *iter + 4;
-		else if (strncmp (*iter, "DESCRIPTION:", 12) == 0)
-			desc = *iter + 12;
-		else if (strncmp (*iter, "COMMAND SET:", 12) == 0)
-			cmd = *iter + 12;
-		else if (strncmp (*iter, "COMMANDSET:", 11) == 0)
-			cmd = *iter + 11;
-		else if (strncmp (*iter, "CMD:", 4) == 0)
-			cmd = *iter + 4;
-	}
-
-	dbus_error_init (&error);
-
-	if (mfg != NULL) {
-		libhal_device_set_property_string (ctx, udi, "info.vendor", mfg, &error);
-		libhal_device_set_property_string (ctx, udi, "printer.vendor", mfg, &error);
-	}		
-
-	if (model != NULL) {
-		libhal_device_set_property_string (ctx, udi, "info.product", model, &error);
-		libhal_device_set_property_string (ctx, udi, "printer.product", model, &error);
-	}
-
-	if (serial != NULL)
-		libhal_device_set_property_string (ctx, udi, "printer.serial", serial, &error);
-
-	if (desc != NULL) {
-		libhal_device_set_property_string (ctx, udi, "printer.description", desc, &error);
-	}
-
-	if (cmd != NULL) {
-		char **cmdset = g_strsplit (cmd, ",", 0);
-		for (iter = cmdset; *iter != NULL; iter++)
-			libhal_device_property_strlist_append (ctx, udi, "printer.commandset", *iter, &error);
-		g_strfreev (cmdset);
-	}
-
-	g_strfreev (props);
-
-	ret = 0;
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-serial.c b/hald/linux2/probing/probe-serial.c
deleted file mode 100644
index b70f82b..0000000
--- a/hald/linux2/probing/probe-serial.c
+++ /dev/null
@@ -1,97 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-serial.c : Probe serial ports
- *
- * Copyright (C) 2005 Pierre Ossman <drzeus at drzeus.cx>
- *
- * 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 <fcntl.h>
-#include <linux/serial.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-
-#include "../../logger.h"
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	struct serial_struct ss;
-
-	fd = -1;
-
-	/* assume failure */
-	ret = 1;
-	
-	setup_logger ();
-
-	if ((udi = getenv ("UDI")) == NULL) {
-		HAL_ERROR (("UDI not set"));
-		goto out;
-	}
-
-	if ((device_file = getenv ("HAL_PROP_SERIAL_DEVICE")) == NULL) {
-		HAL_ERROR (("HAL_PROP_SERIAL_DEVICE not set"));
-		goto out;
-	}
-
-	HAL_DEBUG (("Checking if %s is actually present", device_file));
-	
-	/* Check that there actually is a drive at the other end */
-	fd = open (device_file, O_RDONLY | O_NONBLOCK);
-	if (fd < 0) {
-		HAL_ERROR (("Could not open %s", device_file));
-		goto out;
-	}
-	
-	if (ioctl (fd, TIOCGSERIAL, &ss)) {
-		HAL_ERROR (("TIOCGSERIAL failed for %s", device_file));
-		goto out;
-	}
-	
-	if (ss.type == 0) {
-		HAL_ERROR (("serial port %s seems not to exist", device_file));
-		goto out;
-	}
-
-	/* works */
-	ret = 0;
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-smbios.c b/hald/linux2/probing/probe-smbios.c
deleted file mode 100644
index 2beb809..0000000
--- a/hald/linux2/probing/probe-smbios.c
+++ /dev/null
@@ -1,243 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-smbios.c : Probe system BIOS according to the SMBIOS/DMI standard
- *
- * Copyright (C) 2005 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005 Richard Hughes, <richard at hughsie.com>
- *
- * 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 <ctype.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "libhal/libhal.h"
-#include "../../logger.h"
-
-#define DMIPARSER_STATE_IGNORE		0
-#define DMIPARSER_STATE_BIOS		1
-#define DMIPARSER_STATE_SYSTEM		2
-#define DMIPARSER_STATE_CHASSIS		3
-
-#define strbegin(buf, str) (strncmp (buf, str, strlen (str)) == 0)
-
-/* global */
-char *udi = NULL;
-LibHalContext *ctx = NULL;
-
-/** Finds the start of a null terminated string and sets HAL
- *  property if valid.
- *
- *  @param	buf		The non tabbed prefixed, null terminated string
- *  @param	str		The strings to compare with e.g. "Vendor:"
- *  @param	prop		The HAL property to set
- *  @return			TRUE is found, FALSE otherwise.
- */
-static int
-setstr (char *buf, char *str, char *prop)
-{
-	DBusError error;
-	char *value;
-
-	if (strbegin (buf, str)) {
-		dbus_error_init (&error);
-		value = buf + strlen (str) + 1;
-		libhal_device_set_property_string (ctx, udi, prop, value, &error);
-		HAL_DEBUG (("Setting %s='%s'", prop, value));
-		return TRUE;
-	}
-	return FALSE;
-}
-
-/** Main entry point
- *
- *  @param	argc		Number of arguments given to program
- *  @param	argv		Arguments given to program
- *  @return			Return code
- */
-int 
-main (int argc, char *argv[])
-{
-	int ret;
-	DBusError error;
-	char buf[512];
-	char *nbuf;
-	int dmipipe[2];
-	int nullfd;
-	int tmp_ret;
-	FILE *f;
-	int dmiparser_state = DMIPARSER_STATE_IGNORE;
-
-	/* on some system chassis pops up several times,
-	 * so only take the first entry for each
-	 */
-	int dmiparser_done_bios = FALSE;
-	int dmiparser_done_system = FALSE;
-	int dmiparser_done_chassis = FALSE;
-
-	/* assume failure */
-	ret = 1;
-
-	setup_logger ();
-	
-	udi = getenv ("UDI");
-	if (udi == NULL) {
-		HAL_ERROR (("UDI not set"));
-		goto out;
-	}
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL) {
-		HAL_ERROR (("ctx init failed"));
-		goto out;
-	}
-
-	tmp_ret = pipe (dmipipe);	
-	f = fdopen (dmipipe[0], "r");
-	nullfd = open ("/dev/null", O_RDONLY);
-	
-	/* fork the child process */
-	switch (fork ()) {
-	case 0:
-		/* child */
-		
-		dup2 (nullfd, STDIN_FILENO);
-		dup2 (dmipipe[1], STDOUT_FILENO);
-		close (dmipipe[0]);
-		close (dmipipe[1]);
-		
-		/* execute the child */
-		execl ("/usr/sbin/dmidecode", "/usr/sbin/dmidecode", NULL);
-		
-		/* throw an error if we ever reach this point */
-		HAL_ERROR (("Failed to execute dmidecode!"));
-		exit (1);
-		break;
-	case -1:
-		HAL_ERROR (("Cannot fork!"));
-		break;
-	}
-	
-	/* parent continues from here */
-	
-	/* close unused descriptor */
-	close (dmipipe[1]);
-	
-	/* read the output of the child */
-	while(fgets (buf, sizeof(buf), f) != NULL)
-	{
-		unsigned int i;
-		unsigned int len;
-		unsigned int tabs = 0;
-
-		/* trim whitespace */
-		len = strlen (buf);
-
-		/* check that will fit in buffer */
-		if (len >= sizeof (buf))
-			continue;
-
-		/* not big enough for data, and protects us from underflow */
-		if (len < 3) {
-			dmiparser_state = DMIPARSER_STATE_IGNORE;
-			continue;
-		}
-
-		/* find out number of leading tabs */
-		if (buf[0] == '\t' && buf[1] == '\t')
-			tabs = 2; /* this is list data */
-		else if (buf[0] == '\t')
-			tabs = 1; /* this is data, 0 is section type */
-
-		if (tabs == 2)
-			/* we do not proccess data at depth 2 */
-			continue;
-			
-		/* set the section type */
-		if (tabs == 0) {
-			if (!dmiparser_done_bios && strbegin (buf, "BIOS Information"))
-				dmiparser_state = DMIPARSER_STATE_BIOS;
-			else if (!dmiparser_done_system && strbegin (buf, "System Information"))
-				dmiparser_state = DMIPARSER_STATE_SYSTEM;
-			else if (!dmiparser_done_chassis && strbegin (buf, "Chassis Information"))
-				dmiparser_state = DMIPARSER_STATE_CHASSIS;
-			else
-				/*
-				 * We do not match the other sections,
-				 * or sections we have processed before
-				 */
-				dmiparser_state = DMIPARSER_STATE_IGNORE;
-			continue; /* next line */
-		}
-
-		/* we are not in a section we know, no point continueing */
-		if (dmiparser_state == DMIPARSER_STATE_IGNORE)
-			continue;
-
-		/* removes the leading tab */
-		nbuf = &buf[1];
-
-		/* removes the trailing spaces */
-		for (i = len - 2; isspace (nbuf[i]) && i >= 0; --i)
-			nbuf[i] = '\0';
-
-		if (dmiparser_state == DMIPARSER_STATE_BIOS) {
-			setstr (nbuf, "Vendor:", "smbios.bios.vendor");
-			setstr (nbuf, "Version:", "smbios.bios.version");
-			setstr (nbuf, "Release Date:", "smbios.bios.release_date");
-			dmiparser_done_bios = TRUE;
-		} else if (dmiparser_state == DMIPARSER_STATE_SYSTEM) {
-			setstr (nbuf, "Manufacturer:", "smbios.system.manufacturer");
-			setstr (nbuf, "Product Name:", "smbios.system.product");
-			setstr (nbuf, "Version:", "smbios.system.version");
-			setstr (nbuf, "Serial Number:", "smbios.system.serial");
-			setstr (nbuf, "UUID:", "smbios.system.uuid");
-			dmiparser_done_system = TRUE;
-		} else if (dmiparser_state == DMIPARSER_STATE_CHASSIS) {
-			setstr (nbuf, "Manufacturer:", "smbios.chassis.manufacturer");
-			setstr (nbuf, "Type:", "smbios.chassis.type");
-			dmiparser_done_chassis = TRUE;
-		}
-	}
-
-	/* as read to EOF, close */
-	fclose (f);
-
-	/* return success */
-	ret = 0;
-
-out:
-	/* free ctx */
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-storage.c b/hald/linux2/probing/probe-storage.c
deleted file mode 100644
index ed5f010..0000000
--- a/hald/linux2/probing/probe-storage.c
+++ /dev/null
@@ -1,427 +0,0 @@
-/***************************************************************************
- * CVSID: $Id$
- *
- * probe-storage.c : Probe storage devices
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- * Copyright (C) 2005 Danny Kukawka, <danny.kukawka at 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 <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/kdev_t.h>
-#include <linux/cdrom.h>
-#include <linux/fs.h>
-#include <mntent.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <libvolume_id.h>
-
-#include "libhal/libhal.h"
-#include "linux_dvd_rw_utils.h"
-
-#include "../../logger.h"
-
-static void vid_log(int priority, const char *file, int line, const char *format, ...)
-{
-	char log_str[1024];
-	va_list args;
-
-	va_start(args, format);
-	vsnprintf(log_str, sizeof(log_str), format, args);
-	logger_forward_debug("%s:%i %s", file, line, log_str);
-	va_end(args);
-}
-
-
-/** Check if a filesystem on a special device file is mounted
- *
- *  @param  device_file         Special device file, e.g. /dev/cdrom
- *  @return                     TRUE iff there is a filesystem system mounted
- *                              on the special device file
- */
-static dbus_bool_t
-is_mounted (const char *device_file)
-{
-	FILE *f;
-	dbus_bool_t rc;
-	struct mntent mnt;
-	struct mntent *mnte;
-	char buf[512];
-
-	rc = FALSE;
-
-	if ((f = setmntent ("/etc/mtab", "r")) == NULL)
-		goto out;
-
-	while ((mnte = getmntent_r (f, &mnt, buf, sizeof(buf))) != NULL) {
-		if (strcmp (device_file, mnt.mnt_fsname) == 0) {
-			rc = TRUE;
-			goto out1;
-		}
-	}
-
-out1:
-	endmntent (f);
-out:
-	return rc;
-}
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char *bus;
-	char *drive_type;
-	char *sysfs_path;
-	dbus_bool_t only_check_for_fs;
-
-	fd = -1;
-
-	/* hook in our debug into libvolume_id */
-	volume_id_log_fn = vid_log;
-
-	/* assume failure */
-	ret = 1;
-
-	if ((udi = getenv ("UDI")) == NULL)
-		goto out;
-	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
-		goto out;
-	if ((bus = getenv ("HAL_PROP_STORAGE_BUS")) == NULL)
-		goto out;
-	if ((drive_type = getenv ("HAL_PROP_STORAGE_DRIVE_TYPE")) == NULL)
-		goto out;
-	if ((sysfs_path = getenv ("HAL_PROP_LINUX_SYSFS_PATH")) == NULL)
-		goto out;
-
-	setup_logger ();
-
-	if (argc == 2 && strcmp (argv[1], "--only-check-for-media") == 0)
-		only_check_for_fs = TRUE;
-	else
-		only_check_for_fs = FALSE;
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	HAL_DEBUG (("Doing probe-storage for %s (bus %s) (drive_type %s) (udi=%s) (--only-check-for-fs==%d)", 
-	     device_file, bus, drive_type, udi, only_check_for_fs));
-
-	if (!only_check_for_fs) {
-		/* Get properties for CD-ROM drive */
-		if (strcmp (drive_type, "cdrom") == 0) {
-			int capabilities;
-			int read_speed, write_speed;
-			char *write_speeds;
-			
-			HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file));
-			fd = open (device_file, O_RDONLY | O_NONBLOCK);
-			if (fd < 0) {
-				HAL_ERROR (("Cannot open %s: %s", device_file, strerror (errno)));
-				goto out;
-			}
-			HAL_DEBUG (("Returned from open(2)"));
-
-			if (ioctl (fd, CDROM_SET_OPTIONS, CDO_USE_FFLAGS) < 0) {
-				HAL_ERROR (("Error: CDROM_SET_OPTIONS failed: %s\n", strerror(errno)));
-				close (fd);
-				goto out;
-			}
-			
-			capabilities = ioctl (fd, CDROM_GET_CAPABILITY, 0);
-			if (capabilities < 0) {
-				close (fd);
-				goto out;
-			}
-			
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusr", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrwdl", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrdl", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bd", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bdr", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.bdre", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvd", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvdr", FALSE, &error);
-			libhal_device_set_property_bool (ctx, udi, "storage.cdrom.hddvdrw", FALSE, &error);
-			
-			if (capabilities & CDC_CD_R) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdr", TRUE, &error);
-			}
-			
-			if (capabilities & CDC_CD_RW) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.cdrw", TRUE, &error);
-			}
-			if (capabilities & CDC_DVD) {
-				int profile;
-				
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvd", TRUE, &error);
-
-				profile = get_dvd_r_rw_profile (fd);
-				HAL_DEBUG (("get_dvd_r_rw_profile returned: %d", profile));
-
-				if (profile & DRIVE_CDROM_CAPS_DVDRW)
-					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdrw", TRUE, &error);
-				if (profile & DRIVE_CDROM_CAPS_DVDPLUSR)
-					libhal_device_set_property_bool(ctx, udi, "storage.cdrom.dvdplusr", TRUE, &error);
-				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRW)
-					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrw", TRUE, &error);
-				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRWDL)
-					libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrwdl", TRUE, &error);
-				if (profile & DRIVE_CDROM_CAPS_DVDPLUSRDL)
-                                        libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdplusrdl", TRUE, &error);
-			}
-			if (capabilities & CDC_DVD_R) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdr", TRUE, &error);
-			}
-			if (capabilities & CDC_DVD_RAM) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.dvdram", TRUE, &error);
-			}
-			
-			/* while we're at it, check if we support media changed */
-			if (capabilities & CDC_MEDIA_CHANGED) {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", TRUE, &error);
-			} else {
-				libhal_device_set_property_bool (ctx, udi, "storage.cdrom.support_media_changed", FALSE, &error);
-			}
-			
-			if (get_read_write_speed(fd, &read_speed, &write_speed, &write_speeds) >= 0) {
-				libhal_device_set_property_int (ctx, udi, "storage.cdrom.read_speed", read_speed, &error);
-				if (write_speed > 0) {
-					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", write_speed, &error);
-					if (write_speeds != NULL)
-					{
-						gchar **wspeeds;
-						int i;
-						wspeeds = g_strsplit_set (write_speeds, ",", -1);
-						for (i = 0 ; wspeeds[i] != NULL; i++) {
-					                if (strlen (wspeeds[i]) > 0)
-								libhal_device_property_strlist_append (ctx, udi, "storage.cdrom.write_speeds", wspeeds[i], &error);
-						}
-						free (write_speeds);
-					}
-				}	
-				else
-					libhal_device_set_property_int (ctx, udi, "storage.cdrom.write_speed", 0, &error);
-			}
-
-			close (fd);
-		}
-		
-	} /* !only_check_for_fs */
-
-	ret = 0;
-
-	/* Also return 2 if we're a cdrom and we got a disc */
-	if (strcmp (drive_type, "cdrom") == 0) {
-		char *support_media_changed_str;
-		int support_media_changed;
-		int got_media;
-		int drive;
-
-		HAL_DEBUG (("Checking for optical disc on %s", device_file));
-
-		support_media_changed_str = getenv ("HAL_PROP_STORAGE_CDROM_SUPPORT_MEDIA_CHANGED");
-		if (support_media_changed_str != NULL && strcmp (support_media_changed_str, "true") == 0)
-			support_media_changed = TRUE;
-		else
-			support_media_changed = FALSE;
-
-		HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK | O_EXCL)", device_file));
-		fd = open (device_file, O_RDONLY | O_NONBLOCK | O_EXCL);
-
-		if (fd < 0 && errno == EBUSY) {
-			/* this means the disc is mounted or some other app,
-			 * like a cd burner, has already opened O_EXCL */
-				
-			/* HOWEVER, when starting hald, a disc may be
-			 * mounted; so check /etc/mtab to see if it
-			 * actually is mounted. If it is we retry to open
-			 * without O_EXCL
-			 */
-			if (!is_mounted (device_file))
-				goto out;
-
-			HAL_DEBUG (("Doing open (\"%s\", O_RDONLY | O_NONBLOCK)", device_file));
-			fd = open (device_file, O_RDONLY | O_NONBLOCK);
-		}
-
-		if (fd < 0) {
-			HAL_DEBUG (("open failed for %s: %s", device_file, strerror (errno)));
-			goto out;
-		}
-
-		got_media = FALSE;
-
-		/* Check if a disc is in the drive
-		 *
-		 * @todo Use MMC-2 API if applicable
-		 */
-		drive = ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT);
-		switch (drive) {
-			/* explicit fallthrough */
-		case CDS_NO_INFO:
-		case CDS_NO_DISC:
-		case CDS_TRAY_OPEN:
-		case CDS_DRIVE_NOT_READY:
-			break;
-			
-		case CDS_DISC_OK:
-			/* some CD-ROMs report CDS_DISK_OK even with an open
-			 * tray; if media check has the same value two times in
-			 * a row then this seems to be the case and we must not
-			 * report that there is a media in it. */
-			if (support_media_changed &&
-			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT) && 
-			    ioctl (fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT)) {
-			} else {
-				got_media = TRUE;
-			}
-			break;
-			
-		case -1:
-			HAL_ERROR (("Error: CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)));
-			break;
-			
-		default:
-			break;
-		}
-
-		if (got_media) {
-			uint64_t size;
-			ret = 2;
-			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
-			if (ioctl (fd, BLKGETSIZE64, &size) == 0) {
-				HAL_DEBUG (("media size = %llu", size));
-				libhal_device_set_property_uint64 (ctx, udi, "storage.removable.media_size", size, &error);
-			}
-		} else {
-			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
-		}
-
-		close (fd);
-	} else {
-		struct volume_id *vid;
-		GDir *dir;
-		const gchar *partition;
-		const gchar *main_device;
-		size_t main_device_len;
-		uint64_t size;
-
-		HAL_DEBUG (("Checking for file system on %s", device_file));
-
-		/* See if we got a file system on the main block device - which 
-		 * means doing a data (non O_NONBLOCK) open - this might fail, 
-		 * especially if we don't have any media...
-		 */
-		HAL_DEBUG (("Doing open (\"%s\", O_RDONLY)", device_file));
-		fd = open (device_file, O_RDONLY);
-		if (fd < 0) {
-			HAL_DEBUG (("Cannot open %s: %s", device_file, strerror (errno)));
-			/* no media */
-			libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", FALSE, &error);
-			goto out;
-		}
-		HAL_DEBUG (("Returned from open(2)"));
-
-		/* if we get to here, we have media */
-		libhal_device_set_property_bool (ctx, udi, "storage.removable.media_available", TRUE, &error);
-
-		if (ioctl (fd, BLKGETSIZE64, &size) != 0)
-			size = 0;
-		
-		libhal_device_set_property_uint64 (ctx, udi, "storage.removable.media_size", size, &error);
-
-		/* if the kernel has created partitions, we don't look for a filesystem */
-		main_device = strrchr (sysfs_path, '/');
-		if (main_device == NULL)
-			goto out;
-		main_device = &main_device[1];
-		main_device_len = strlen (main_device);
-		HAL_DEBUG (("look for existing partitions for %s", main_device));
-		if ((dir = g_dir_open (sysfs_path, 0, NULL)) == NULL) {
-			HAL_DEBUG (("failed to open sysfs dir"));
-			goto out;
-		}
-		while ((partition = g_dir_read_name (dir)) != NULL) {
-			if (strncmp (main_device, partition, main_device_len) == 0 &&
-			    isdigit (partition[main_device_len])) {
-				HAL_DEBUG (("partition %s found, skip probing for filesystem", partition));
-				g_dir_close (dir);
-				goto out;
-			}
-		}
-		g_dir_close (dir);
-
-		/* probe for file system */
-		vid = volume_id_open_fd (fd);
-		if (vid != NULL) {
-			if (volume_id_probe_all (vid, 0, size) == 0) {
-				/* signal to hald that we've found something and a fakevolume
-				 * should be added - see hald/linux2/blockdev.c:add_blockdev_probing_helper_done()
-				 * and hald/linux2/blockdev.c:block_rescan_storage_done().
-				 */
-				if (vid->usage_id == VOLUME_ID_FILESYSTEM ||
-				    vid->usage_id == VOLUME_ID_RAID ||
-				    vid->usage_id == VOLUME_ID_OTHER ||
-				    vid->usage_id == VOLUME_ID_CRYPTO)
-					ret = 2;
-			} else {
-				;
-			}
-			volume_id_close(vid);
-		}
-		close (fd);
-	}
-	
-out:
-
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-}
diff --git a/hald/linux2/probing/probe-volume.c b/hald/linux2/probing/probe-volume.c
deleted file mode 100644
index 8a57e52..0000000
--- a/hald/linux2/probing/probe-volume.c
+++ /dev/null
@@ -1,812 +0,0 @@
-/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-
- ***************************************************************************
- * CVSID: $Id$
- *
- * probe-volume.c : Probe for volume type (filesystems etc.)
- *
- * Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
- *
- * 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 <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/cdrom.h>
-#include <linux/fs.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-
-#include <glib.h>
-#include <libvolume_id.h>
-
-#include "libhal/libhal.h"
-#include "linux_dvd_rw_utils.h"
-#include "../../logger.h"
-
-static void vid_log(int priority, const char *file, int line, const char *format, ...)
-{
-	char log_str[1024];
-	va_list args;
-
-	va_start(args, format);
-	vsnprintf(log_str, sizeof(log_str), format, args);
-	logger_forward_debug("%s:%i %s", file, line, log_str);
-	va_end(args);
-}
-
-static gchar *
-strdup_valid_utf8 (const char *str)
-{
-	char *endchar;
-	char *newstr;
-	unsigned int fixes;
-
-	if (str == NULL)
-		return NULL;
-
-	newstr = g_strdup (str);
-
-	fixes = 0;
-	while (!g_utf8_validate (newstr, -1, (const char **) &endchar)) {
-		*endchar = '_';
-		++fixes;
-	}
-
-	/* If we had to fix more than 20% of the characters, give up */
-	if (fixes > 0 && g_utf8_strlen (newstr, -1) / fixes < 5) {
-	    g_free (newstr);
-	    newstr = g_strdup("");
-	}
-
-	return newstr;
-}
-
-/* probe_msdos_part_table: return array of partiton type numbers */
-#define BSIZE				0x200
-#define MSDOS_MAGIC			"\x55\xaa"
-#define MSDOS_PARTTABLE_OFFSET		0x1be
-#define MSDOS_SIG_OFF			0x1fe
-#define DOS_EXTENDED_PARTITION		0x05
-#define LINUX_EXTENDED_PARTITION	0x85
-#define WIN98_EXTENDED_PARTITION	0x0f
-#define is_extended(type) \
-	(type == DOS_EXTENDED_PARTITION ||	\
-	 type == WIN98_EXTENDED_PARTITION ||	\
-	 type == LINUX_EXTENDED_PARTITION)
-
-struct msdos_part_entry {
-	uint8_t part_type;
-	uint64_t start;
-	uint64_t size;
-};
-
-static struct msdos_part_entry *
-probe_msdos_part_table(int fd)
-{
-	static struct msdos_part_entry partition_id_index[256];
-	unsigned int partition_count;
-	const uint8_t buf[BSIZE];
-	int i;
-	uint64_t poff;
-	uint64_t plen;
-	uint64_t extended = 0;
-	uint64_t next;
-	int limit;
-	int empty = 1;
-	struct msdos_partition_entry {
-		uint8_t		boot_ind;
-		uint8_t		head;
-		uint8_t		sector;
-		uint8_t		cyl;
-		uint8_t		sys_ind;
-		uint8_t		end_head;
-		uint8_t		end_sector;
-		uint8_t		end_cyl;
-		uint32_t	start_sect;
-		uint32_t	nr_sects;
-	} __attribute__((packed)) *part;
-
-	if (lseek(fd, 0, SEEK_SET) < 0) {
-		HAL_DEBUG (("lseek failed (%s)", strerror(errno)));
-		return NULL;
-	}
-	if (read(fd, &buf, BSIZE) < BSIZE) {
-		HAL_DEBUG (("read failed (%s)", strerror(errno)));
-		return NULL;
-	}
-	if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
-		return NULL;
-
-	part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
-	/* check flags on all entries for a valid partition table */
-	for (i = 0; i < 4; i++) {
-		if (part[i].boot_ind != 0 &&
-		    part[i].boot_ind != 0x80)
-			return NULL;
-
-		if (GINT32_FROM_LE(part[i].nr_sects) != 0)
-			empty = 0;
-	}
-	if (empty == 1)
-		return NULL;
-
-	memset(partition_id_index, 0x00, sizeof(partition_id_index));
-
-	for (i = 0; i < 4; i++) {
-		poff = (uint64_t) GINT32_FROM_LE(part[i].start_sect) * BSIZE;
-		plen = (uint64_t) GINT32_FROM_LE(part[i].nr_sects) * BSIZE;
-
-		if (plen == 0)
-			continue;
-
-		partition_id_index[i].part_type = part[i].sys_ind;
-		partition_id_index[i].start = poff;
-		partition_id_index[i].size = plen;
-		HAL_DEBUG (("part %d -> type=%d off=%lld size=%lld", i, part[i].sys_ind, poff, plen));
-
-		if (is_extended(part[i].sys_ind)) {
-			HAL_DEBUG (("found extended partition at 0x%llx", (unsigned long long) poff));
-			if (extended == 0)
-				extended = poff;
-		} else {
-			HAL_DEBUG (("found 0x%x primary data partition at 0x%llx, len 0x%llx",
-			    part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen));
-		}
-	}
-
-	/* follow extended partition chain and add data partitions */
-	partition_count = 4;
-	limit = 255;
-	next = extended;
-	while (next != 0) {
-		uint64_t oldnext;
-
-		if (limit-- == 0) {
-			HAL_DEBUG(("extended chain limit reached"));
-			break;
-		}
-
-		HAL_DEBUG (("read 0x%llx (%llu)", next, next));
-		if (lseek(fd, next, SEEK_SET) < 0) {
-			HAL_DEBUG(("lseek failed (%s)", strerror(errno)));
-			return NULL;
-		}
-		if (read(fd, &buf, BSIZE) < BSIZE) {
-			HAL_DEBUG(("read failed (%s)", strerror(errno)));
-			return NULL;
-		}
-		if (memcmp(&buf[MSDOS_SIG_OFF], MSDOS_MAGIC, 2) != 0)
-			break;
-
-		oldnext = next;
-		next = 0;
-
-		part = (struct msdos_partition_entry*) &buf[MSDOS_PARTTABLE_OFFSET];
-		for (i = 0; i < 4; i++) {
-			poff = (uint64_t) GINT32_FROM_LE(part[i].start_sect) * BSIZE;
-			plen = (uint64_t) GINT32_FROM_LE(part[i].nr_sects) * BSIZE;
-
-			if (plen == 0)
-				continue;
-
-			if (is_extended(part[i].sys_ind)) {
-				HAL_DEBUG(("found extended partition (chain) at 0x%llx", (unsigned long long) poff));
-				if (next == 0)
-					next = extended + poff;
-			} else {
-				HAL_DEBUG(("found 0x%x logical data partition at 0x%llx, len 0x%llx",
-					part[i].sys_ind, (unsigned long long) poff, (unsigned long long) plen));
-
-				partition_id_index[partition_count].part_type = part[i].sys_ind;
-				partition_id_index[partition_count].start = oldnext + poff;
-				partition_id_index[partition_count].size = plen;
-
-				partition_count++;
-			}
-		}
-	}
-
-	return partition_id_index;
-}
-
-static void
-set_volume_id_values (LibHalContext *ctx, const char *udi, LibHalChangeSet *changes, struct volume_id *vid)
-{
-	char buf[256];
-	const char *usage;
-	char *volume_label;
-	DBusError error;
-
-	dbus_error_init (&error);
-
-	switch (vid->usage_id) {
-	case VOLUME_ID_FILESYSTEM:
-		usage = "filesystem";
-		break;
-	case VOLUME_ID_OTHER:
-		usage = "other";
-		break;
-	case VOLUME_ID_RAID:
-		usage = "raid";
-		break;
-	case VOLUME_ID_CRYPTO:
-		usage = "crypto";
-		break;
-	case VOLUME_ID_UNUSED:
-		libhal_changeset_set_property_string (changes, "info.product", "Volume (unused)");
-		usage = "unused";
-		return;
-	default:
-		usage = "";
-	}
-
-	libhal_changeset_set_property_string (changes, "volume.fsusage", usage);
-	HAL_DEBUG (("volume.fsusage = '%s'", usage));
-
-	libhal_changeset_set_property_string (changes, "volume.fstype", vid->type);
-	HAL_DEBUG(("volume.fstype = '%s'", vid->type));
-	if (vid->type_version[0] != '\0') {
-		libhal_changeset_set_property_string (changes, "volume.fsversion", vid->type_version);
-		HAL_DEBUG(("volume.fsversion = '%s'", vid->type_version));
-	}
-	libhal_changeset_set_property_string (changes, "volume.uuid", vid->uuid);
-	HAL_DEBUG(("volume.uuid = '%s'", vid->uuid));
-
-	/* we need to be sure for a utf8 valid label, because dbus accept only utf8 valid strings */
-	volume_label = strdup_valid_utf8 (vid->label);
-	if( volume_label != NULL ) {
-		libhal_changeset_set_property_string (changes, "volume.label", volume_label);
-		HAL_DEBUG(("volume.label = '%s'", volume_label));
-		
-		if (strlen(volume_label) > 0) {	
-			libhal_changeset_set_property_string (changes, "info.product", volume_label);
-		}
-		else {
-			snprintf (buf, sizeof (buf), "Volume (%s)", vid->type);
-			libhal_changeset_set_property_string (changes, "info.product", buf);
-		}
-		g_free(volume_label);
-	} else {
-		snprintf (buf, sizeof (buf), "Volume (%s)", vid->type);
-		libhal_changeset_set_property_string (changes, "info.product", buf);
-	}
-}
-
-static void
-advanced_disc_detect (LibHalContext *ctx, const char *udi, LibHalChangeSet *changes,
-                      int fd, const char *device_file)
-{
-	/* the discs block size */
-	unsigned short bs; 
-	/* the path table size */
-	unsigned short ts;
-	/* the path table location (in blocks) */
-	unsigned int tl;
-	/* length of the directory name in current path table entry */
-	unsigned char len_di = 0;
-	/* the number of the parent directory's path table entry */
-	unsigned int parent = 0; 
-	/* filename for the current path table entry */
-	char dirname[256];
-	/* our position into the path table */
-	int pos = 0; 
-	/* the path table record we're on */
-	int curr_record = 1; 
-	/* loop counter */
-	int i; 
-	DBusError error;
-	
-	dbus_error_init (&error);
-	
-	/* set defaults */
-	libhal_changeset_set_property_bool (changes, "volume.disc.is_videodvd", FALSE);
-	libhal_changeset_set_property_bool (changes, "volume.disc.is_vcd", FALSE);
-	libhal_changeset_set_property_bool (changes, "volume.disc.is_svcd", FALSE);
-	
-	/* read the block size */
-	lseek (fd, 0x8080, SEEK_CUR);
-	if (read (fd, &bs, 2) != 2)
-	{
-		HAL_DEBUG(("Advanced probing on %s failed while reading block size", device_file));
-		goto out;
-	}
-
-	/* read in size of path table */
-	lseek (fd, 2, SEEK_CUR);
-	if (read (fd, &ts, 2) != 2)
-	{
-		HAL_DEBUG(("Advanced probing on %s failed while reading path table size", device_file));
-		goto out;
-	}
-
-	/* read in which block path table is in */
-	lseek (fd, 6, SEEK_CUR);
-	if (read (fd, &tl, 4) != 4)
-	{
-		HAL_DEBUG(("Advanced probing on %s failed while reading path table block", device_file));
-		goto out;
-	}
-
-	/* seek to the path table */
-	lseek (fd, GUINT16_FROM_LE (bs) * GUINT32_FROM_LE (tl), SEEK_SET);
-
-	/* loop through the path table entriesi */
-	while (pos < GUINT16_FROM_LE (ts))
-	{
-		/* get the length of the filename of the current entry */
-		if (read (fd, &len_di, 1) != 1)
-		{
-			HAL_DEBUG(("Advanced probing on %s failed, cannot read more entries", device_file));
-			break;
-		}
-
-		/* get the record number of this entry's parent
-		   i'm pretty sure that the 1st entry is always the top directory */
-		lseek (fd, 5, SEEK_CUR);
-		if (read (fd, &parent, 2) != 2)
-		{
-			HAL_DEBUG(("Advanced probing on %s failed, couldn't read parent entry", device_file));
-			break;
-		}
-		
-		/* read the name */
-		if (read (fd, dirname, len_di) != len_di)
-		{
-			HAL_DEBUG(("Advanced probing on %s failed, couldn't read the entry name", device_file));
-			break;
-		}
-		dirname[len_di] = 0;
-
-		/* strcasecmp is not POSIX or ANSI C unfortunately */
-		i=0;
-		while (dirname[i]!=0)
-		{
-			dirname[i] = (char)toupper (dirname[i]);
-			i++;
-		}
-
-		/* if we found a folder that has the root as a parent, and the directory name matches 
-		   one of the special directories then set the properties accordingly */
-		if (GUINT16_FROM_LE (parent) == 1)
-		{
-			if (!strcmp (dirname, "VIDEO_TS"))
-			{
-				libhal_changeset_set_property_bool (changes, "volume.disc.is_videodvd", TRUE);
-				HAL_DEBUG(("Disc in %s is a Video DVD", device_file));
-				break;
-			}
-			else if (!strcmp (dirname, "VCD"))
-			{
-				libhal_changeset_set_property_bool (changes, "volume.disc.is_vcd", TRUE);
-				HAL_DEBUG(("Disc in %s is a Video CD", device_file));
-				break;
-			}
-			else if (!strcmp (dirname, "SVCD"))
-			{
-				libhal_changeset_set_property_bool (changes, "volume.disc.is_svcd", TRUE);
-				HAL_DEBUG(("Disc in %s is a Super Video CD", device_file));
-				break;
-			}
-		}
-
-		/* all path table entries are padded to be even, 
-		   so if this is an odd-length table, seek a byte to fix it */
-		if (len_di%2 == 1)
-		{
-			lseek (fd, 1, SEEK_CUR);
-			pos++;
-		}
-
-		/* update our position */
-		pos += 8 + len_di;
-		curr_record++;
-	}
-
-out:
-	/* go back to the start of the file */
-	lseek (fd, 0, SEEK_SET);
-}
-
-int 
-main (int argc, char *argv[])
-{
-	int fd;
-	int ret;
-	char *udi;
-	char *device_file;
-	LibHalContext *ctx = NULL;
-	DBusError error;
-	char *parent_udi;
-	char *sysfs_path;
-	struct volume_id *vid;
-	char *stordev_dev_file;
-	char *partition_number_str;
-	char *is_disc_str;
-	dbus_bool_t is_disc;
-	unsigned int partition_number;
-	unsigned int block_size;
-	dbus_uint64_t vol_size;
-	dbus_bool_t should_probe_for_fs;
-	dbus_uint64_t vol_probe_offset = 0;
-	LibHalChangeSet *changeset;
-	fd = -1;
-
-	/* hook in our debug into libvolume_id */
-	volume_id_log_fn = vid_log;
-
-	/* assume failure */
-	ret = 1;
-
-	if ((udi = getenv ("UDI")) == NULL)
-		goto out;
-	if ((device_file = getenv ("HAL_PROP_BLOCK_DEVICE")) == NULL)
-		goto out;
-	if ((parent_udi = getenv ("HAL_PROP_INFO_PARENT")) == NULL)
-		goto out;
-	if ((sysfs_path = getenv ("HAL_PROP_LINUX_SYSFS_PATH")) == NULL)
-		goto out;
-	partition_number_str = getenv ("HAL_PROP_VOLUME_PARTITION_NUMBER");
-	if (partition_number_str != NULL)
-		partition_number = (unsigned int) atoi (partition_number_str);
-	else
-		partition_number = (unsigned int) -1;
-
-	is_disc_str = getenv ("HAL_PROP_VOLUME_IS_DISC");
-	if (is_disc_str != NULL && strcmp (is_disc_str, "true") == 0)
-		is_disc = TRUE;
-	else
-		is_disc = FALSE;
-
-	setup_logger ();
-
-	dbus_error_init (&error);
-	if ((ctx = libhal_ctx_init_direct (&error)) == NULL)
-		goto out;
-
-	changeset = libhal_device_new_changeset (udi);
-	if (changeset == NULL) {
-		HAL_DEBUG(("Cannot initialize changeset"));
-		goto out;
-	}
-
-	HAL_DEBUG(("Doing probe-volume for %s\n", device_file));
-
-	fd = open (device_file, O_RDONLY);
-	if (fd < 0)
-		goto out;
-
-	/* block size and total size */
-	if (ioctl (fd, BLKSSZGET, &block_size) == 0) {
-		HAL_DEBUG(("volume.block_size = %d", block_size));
-		libhal_changeset_set_property_int (changeset, "volume.block_size", block_size);
-	}
-	if (ioctl (fd, BLKGETSIZE64, &vol_size) == 0) {
-		HAL_DEBUG(("volume.size = %llu", vol_size));
-		libhal_changeset_set_property_uint64 (changeset, "volume.size", vol_size);
-	} else
-		vol_size = 0;
-
-	should_probe_for_fs = TRUE;
-
-	if (is_disc) {
-		int type;
-		guint64 capacity;
-		struct cdrom_tochdr; /* toc_hdr; */
-
-		/* defaults */
-		libhal_changeset_set_property_string (changeset, "volume.disc.type", "unknown");
-		libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", FALSE);
-		libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", FALSE);
-		libhal_changeset_set_property_bool (changeset, "volume.disc.is_blank", FALSE);
-		libhal_changeset_set_property_bool (changeset, "volume.disc.is_appendable", FALSE);
-		libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", FALSE);
-
-		/* Suggested by Alex Larsson to get rid of log spewage
-		 * on Alan's cd changer (RH bug 130649) */
-		if (ioctl (fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) {
-			goto out;
-		}
-
-		/* check for audio/data/blank */
-		type = ioctl (fd, CDROM_DISC_STATUS, CDSL_CURRENT);
-		switch (type) {
-		case CDS_AUDIO:		/* audio CD */
-			libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", TRUE);
-			HAL_DEBUG(("Disc in %s has audio", device_file));
-			should_probe_for_fs = FALSE;
-			break;
-		case CDS_MIXED:		/* mixed mode CD */
-			libhal_changeset_set_property_bool (changeset, "volume.disc.has_audio", TRUE);
-			libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", TRUE);
-			HAL_DEBUG(("Disc in %s has audio+data", device_file));
-			break;
-		case CDS_DATA_1:	/* data CD */
-		case CDS_DATA_2:
-		case CDS_XA_2_1:
-		case CDS_XA_2_2:
-			libhal_changeset_set_property_bool (changeset, "volume.disc.has_data", TRUE);
-			HAL_DEBUG(("Disc in %s has data", device_file));
-			advanced_disc_detect (ctx, udi, changeset, fd, device_file);
-			break;
-		case CDS_NO_INFO:	/* blank or invalid CD */
-			libhal_changeset_set_property_bool (changeset, "volume.disc.is_blank", TRUE);
-			/* set the volume size to 0 if disc is blank and not as 4 from BLKGETSIZE64 */
-			libhal_changeset_set_property_int (changeset, "volume.block_size", 0);
-			HAL_DEBUG(("Disc in %s is blank", device_file));
-			should_probe_for_fs = FALSE;
-			break;
-			
-		default:		/* should never see this */
-			libhal_changeset_set_property_string (changeset, "volume.disc_type", "unknown");
-			HAL_DEBUG(("Disc in %s returned unknown CDROM_DISC_STATUS", device_file));
-			should_probe_for_fs = FALSE;
-			break;
-		}
-		
-		/* see table 87 - Profile List in MMC-5 for details on disc type
-		 * http://www.t10.org/drafts.htm#mmc5
-		 */
-		type = get_disc_type (fd);
-		HAL_DEBUG(("get_disc_type returned 0x%02x", type));
-		if (type != -1) {
-			switch (type) {
-			case 0x08: /* CD-ROM */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_rom");
-				break;
-			case 0x09: /* CD-R */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_r");
-				break;
-			case 0x0a: /* CD-RW */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "cd_rw");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x10: /* DVD-ROM */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rom");
-				break;
-			case 0x11: /* DVD-R Sequential */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_r");
-				break;
-			case 0x12: /* DVD-RAM */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_ram");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x13: /* DVD-RW Restricted Overwrite */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rw");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x14: /* DVD-RW Sequential */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_rw");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x1A: /* DVD+RW */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_rw");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x1B: /* DVD+R */
-				libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_r");
-				break;
-			case 0x2B: /* DVD+R Double Layer */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "dvd_plus_r_dl");
-				break;
-			case 0x40: /* BD-ROM  */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_rom");
-				break;
-			case 0x41: /* BD-R Sequential */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_r");
-				break;
-			case 0x42: /* BD-R Random */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_r");
-				break;
-			case 0x43: /* BD-RE */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "bd_re");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			case 0x50: /* HD DVD-ROM */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_rom");
-				break;
-			case 0x51: /* HD DVD-R */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_r");
-				break;
-			case 0x52: /* HD DVD-Rewritable */
-                          	libhal_changeset_set_property_string (changeset, "volume.disc.type", "hddvd_rw");
-				libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-				break;
-			default: 
-				break;
-			}
-		}
-
-		if (get_disc_capacity_for_type (fd, type, &capacity) == 0) {
-			HAL_DEBUG(("volume.disc.capacity = %llu", capacity));
-			libhal_changeset_set_property_uint64 (changeset, "volume.disc.capacity", capacity);
-		}
-
-		/* On some hardware the get_disc_type call fails, so we use this as a backup */
-		if (disc_is_rewritable (fd)) {
-			libhal_changeset_set_property_bool (changeset, "volume.disc.is_rewritable", TRUE);
-		}
-		
-		if (disc_is_appendable (fd)) {
-			libhal_changeset_set_property_bool (changeset, "volume.disc.is_appendable", TRUE);
-		}
-
-#if 0
-		/* This seems to cause problems on some drives with broken firmware,
-		 * comment it out until we really need multisession support */
-
-		/* check for multisession disks */
-		if (ioctl (fd, CDROMREADTOCHDR, &toc_hdr) == 0) {
-			struct cdrom_tocentry toc_entr;
-			unsigned int vol_session_count = 0;
-
-			vol_session_count = toc_hdr.cdth_trk1;
-			HAL_DEBUG(("volume_session_count = %u", vol_session_count));
-
-			/* read session header */
-			memset (&toc_entr, 0x00, sizeof (toc_entr));
-			toc_entr.cdte_track = vol_session_count;
-			toc_entr.cdte_format = CDROM_LBA;
-			if (ioctl (fd, CDROMREADTOCENTRY, &toc_entr) == 0)
-				if ((toc_entr.cdte_ctrl & CDROM_DATA_TRACK) == 4) {
-					HAL_DEBUG(("last session starts at block = %u", toc_entr.cdte_addr.lba));
-					vol_probe_offset = toc_entr.cdte_addr.lba * block_size;
-				}
-		}
-#endif
-
-		/* try again, to get last session that way */
-		if (vol_probe_offset == 0) {
-			struct cdrom_multisession ms_info;
-
-			memset(&ms_info, 0x00, sizeof(ms_info));
-			ms_info.addr_format = CDROM_LBA;
-			if (ioctl(fd, CDROMMULTISESSION, &ms_info) == 0)
-				if (!ms_info.xa_flag)
-					vol_probe_offset = ms_info.addr.lba * block_size;
-		}
-	}
-
-	if (should_probe_for_fs) {
-
-		/* Optical discs have problems reporting the exact
-		 * size so we should never look for data there since
-		 * it causes problems with the broken ide-cd driver
-		 */
-		if (is_disc)
-			vol_size = 0;
-
-		/* probe for file system */
-		vid = volume_id_open_fd (fd);
-		if (vid != NULL) {
-			if (volume_id_probe_all (vid, vol_probe_offset , vol_size) == 0) {
-				set_volume_id_values(ctx, udi, changeset, vid);
-			} else {
-				libhal_changeset_set_property_string (changeset, "info.product", "Volume");
-			}
-
-			/* VOLUME_ID_UNUSED means vol_id didn't detect anything that it knows about - look if 
-			 * it's an extended msdos partition table 
-			 */
-			if (vid->usage_id == VOLUME_ID_UNUSED) {
-				unsigned char buf[2];
-
-				HAL_DEBUG (("looking whether partition is an extended msdos partition table", vid->usage_id));
-
-				/* TODO: Is it good enough to just look for this magic? Kay? */
-				lseek (fd, MSDOS_SIG_OFF, SEEK_SET);
-				if (read (fd, &buf, 2) != 2) {
-					HAL_DEBUG (("read failed (%s)", strerror (errno)));
-				} else {
-					if (memcmp (buf, MSDOS_MAGIC, 2) == 0) {
-						HAL_DEBUG (("partition is an extended msdos partition table"));
-
-						libhal_changeset_set_property_string (changeset, "volume.fsusage", "partitiontable");
-						libhal_changeset_set_property_string (changeset, "volume.fstype", "msdos_extended_partitiontable");
-						libhal_changeset_set_property_string (changeset, "volume.fsversion", "");
-						
-					}
-				}
-				
-			}
-
-			volume_id_close(vid);
-		}
-
-		/* get partition type number, if we find a msdos partition table */
-		if (partition_number_str != NULL && partition_number <= 256 && partition_number > 0) {
-			struct msdos_part_entry *idx;
-			int fd;
-
-			if ((stordev_dev_file = libhal_device_get_property_string (
-					ctx, parent_udi, "block.device", &error)) == NULL) {
-				goto out;
-			}
-			fd = open(stordev_dev_file, O_RDONLY);
-			if (fd >= 0) {
-				idx = probe_msdos_part_table(fd);
-				if (idx != NULL) {
-					uint64_t start;
-					uint64_t size;
-					unsigned char type;
-
-					type = idx[partition_number - 1].part_type;
-					start = idx[partition_number - 1].start;
-					size = idx[partition_number - 1].size;
-					if (type > 0) {
-						libhal_changeset_set_property_int (
-							changeset, "volume.partition.msdos_part_table_type", type);
-						libhal_changeset_set_property_uint64 (
-							changeset, "volume.partition.msdos_part_table_start", start);
-						libhal_changeset_set_property_uint64 (
-							changeset, "volume.partition.msdos_part_table_size", size);
-
-						/* NOTE: We trust the type from the partition table
-						 * if it explicitly got correct entries for RAID and
-						 * LVM partitions.
-						 *
-						 * But in general it's not a good idea to trust the
-						 * partition table type as many geek^Wexpert users use 
-						 * FAT filesystems on type 0x83 which is Linux.
-						 *
-						 * Linux RAID autodetect is 0xfd and Linux LVM is 0x8e
-						 */
-						if (type == 0xfd || type == 0x8e ) {
-							libhal_changeset_set_property_string (
-								changeset, "volume.fsusage", "raid");
-						}
-					}
-				}
-				close (fd);
-			}
-			libhal_free_string (stordev_dev_file);
-		}
-	}
-
-	/* good so far */
-	ret = 0;
-
-	/* for testing...
-	  char *values[4] = {"foo", "bar", "baz", NULL};
-	  libhal_changeset_set_property_strlist (changeset, "foo.bar", values);
-	*/
-
-	libhal_device_commit_changeset (ctx, changeset, &error);
-	libhal_device_free_changeset (changeset);
-
-out:
-	if (fd >= 0)
-		close (fd);
-
-	if (ctx != NULL) {
-		dbus_error_init (&error);
-		libhal_ctx_shutdown (ctx, &error);
-		libhal_ctx_free (ctx);
-	}
-
-	return ret;
-
-}
diff --git a/hald/run-hald.sh b/hald/run-hald.sh
index f36ed5a..69dd17e 100755
--- a/hald/run-hald.sh
+++ b/hald/run-hald.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-export HALD_RUNNER_PATH=`pwd`/linux2:`pwd`/linux2/probing:`pwd`/linux2/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
+export HALD_RUNNER_PATH=`pwd`/linux:`pwd`/linux/probing:`pwd`/linux/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
 export PATH=`pwd`/../hald-runner:$PATH
 export HAL_FDI_SOURCE_PREPROBE=../fdi/preprobe
 export HAL_FDI_SOURCE_INFORMATION=../fdi/information
diff --git a/hald/valgrind-hald.sh b/hald/valgrind-hald.sh
index 6a29bc5..8f47d20 100755
--- a/hald/valgrind-hald.sh
+++ b/hald/valgrind-hald.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-export HALD_RUNNER_PATH=`pwd`/linux2:`pwd`/linux2/probing:`pwd`/linux2/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
+export HALD_RUNNER_PATH=`pwd`/linux:`pwd`/linux/probing:`pwd`/linux/addons:`pwd`/.:`pwd`/../tools:`pwd`/../tools/linux
 export PATH=`pwd`/../hald-runner:$PATH
 export HAL_FDI_SOURCE_PREPROBE=../fdi/preprobe
 export HAL_FDI_SOURCE_INFORMATION=../fdi/information
diff --git a/tools/Makefile.am b/tools/Makefile.am
index b64c2c0..7d84238 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -3,7 +3,7 @@
 
 SUBDIRS = device-manager
 
-if HALD_COMPILE_LINUX2
+if HALD_COMPILE_LINUX
 SUBDIRS += linux
 endif
 if HALD_COMPILE_FREEBSD



More information about the hal-commit mailing list