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