From 019898159cd064f33bce4082d26295f9e3e6a2ef Mon Sep 17 00:00:00 2001 From: Danny Kukawka Date: Mon, 21 Aug 2006 20:59:21 +0200 Subject: 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. --- configure.in | 12 +- hald/Makefile.am | 2 +- hald/debug-hald.sh | 2 +- hald/linux/.gitignore | 8 + hald/linux/Makefile.am | 37 + hald/linux/acpi.c | 1361 ++++++++++++++++++ hald/linux/acpi.h | 41 + hald/linux/addons/.gitignore | 16 + hald/linux/addons/Makefile.am | 54 + hald/linux/addons/addon-acpi-buttons-toshiba.c | 184 +++ hald/linux/addons/addon-acpi.c | 211 +++ hald/linux/addons/addon-hid-ups.c | 351 +++++ hald/linux/addons/addon-keyboard.c | 233 ++++ hald/linux/addons/addon-macbookpro-backlight.c | 521 +++++++ hald/linux/addons/addon-pmu.c | 137 ++ hald/linux/addons/addon-storage.c | 486 +++++++ hald/linux/addons/addon-usb-csr.c | 329 +++++ hald/linux/apm.c | 542 +++++++ hald/linux/apm.h | 41 + hald/linux/blockdev.c | 1419 +++++++++++++++++++ hald/linux/blockdev.h | 43 + hald/linux/classdev.c | 1495 ++++++++++++++++++++ hald/linux/classdev.h | 52 + hald/linux/coldplug.c | 682 +++++++++ hald/linux/coldplug.h | 34 + hald/linux/hotplug.c | 618 ++++++++ hald/linux/hotplug.h | 113 ++ hald/linux/hotplug_helper.h | 45 + hald/linux/ids.c | 973 +++++++++++++ hald/linux/ids.h | 47 + hald/linux/osspec.c | 632 +++++++++ hald/linux/osspec_linux.h | 43 + hald/linux/physdev.c | 1707 +++++++++++++++++++++++ hald/linux/physdev.h | 42 + hald/linux/pmu.c | 622 +++++++++ hald/linux/pmu.h | 40 + hald/linux/probing/.gitignore | 16 + hald/linux/probing/Makefile.am | 39 + hald/linux/probing/linux_dvd_rw_utils.c | 818 +++++++++++ hald/linux/probing/linux_dvd_rw_utils.h | 27 + hald/linux/probing/probe-hiddev.c | 171 +++ hald/linux/probing/probe-input.c | 230 +++ hald/linux/probing/probe-pc-floppy.c | 101 ++ hald/linux/probing/probe-printer.c | 176 +++ hald/linux/probing/probe-serial.c | 97 ++ hald/linux/probing/probe-smbios.c | 243 ++++ hald/linux/probing/probe-storage.c | 427 ++++++ hald/linux/probing/probe-volume.c | 812 +++++++++++ hald/linux2/.gitignore | 8 - hald/linux2/Makefile.am | 37 - hald/linux2/acpi.c | 1361 ------------------ hald/linux2/acpi.h | 41 - hald/linux2/addons/.gitignore | 16 - hald/linux2/addons/Makefile.am | 54 - hald/linux2/addons/addon-acpi-buttons-toshiba.c | 184 --- hald/linux2/addons/addon-acpi.c | 211 --- hald/linux2/addons/addon-hid-ups.c | 351 ----- hald/linux2/addons/addon-keyboard.c | 233 ---- hald/linux2/addons/addon-macbookpro-backlight.c | 521 ------- hald/linux2/addons/addon-pmu.c | 137 -- hald/linux2/addons/addon-storage.c | 486 ------- hald/linux2/addons/addon-usb-csr.c | 329 ----- hald/linux2/apm.c | 542 ------- hald/linux2/apm.h | 41 - hald/linux2/blockdev.c | 1419 ------------------- hald/linux2/blockdev.h | 43 - hald/linux2/classdev.c | 1495 -------------------- hald/linux2/classdev.h | 52 - hald/linux2/coldplug.c | 682 --------- hald/linux2/coldplug.h | 34 - hald/linux2/hotplug.c | 618 -------- hald/linux2/hotplug.h | 113 -- hald/linux2/hotplug_helper.h | 45 - hald/linux2/ids.c | 973 ------------- hald/linux2/ids.h | 47 - hald/linux2/osspec.c | 632 --------- hald/linux2/osspec_linux.h | 43 - hald/linux2/physdev.c | 1707 ----------------------- hald/linux2/physdev.h | 42 - hald/linux2/pmu.c | 622 --------- hald/linux2/pmu.h | 40 - hald/linux2/probing/.gitignore | 16 - hald/linux2/probing/Makefile.am | 39 - hald/linux2/probing/linux_dvd_rw_utils.c | 818 ----------- hald/linux2/probing/linux_dvd_rw_utils.h | 27 - hald/linux2/probing/probe-hiddev.c | 171 --- hald/linux2/probing/probe-input.c | 230 --- hald/linux2/probing/probe-pc-floppy.c | 101 -- hald/linux2/probing/probe-printer.c | 176 --- hald/linux2/probing/probe-serial.c | 97 -- hald/linux2/probing/probe-smbios.c | 243 ---- hald/linux2/probing/probe-storage.c | 427 ------ hald/linux2/probing/probe-volume.c | 812 ----------- hald/run-hald.sh | 2 +- hald/valgrind-hald.sh | 2 +- tools/Makefile.am | 2 +- 96 files changed, 16327 insertions(+), 16327 deletions(-) create mode 100644 hald/linux/.gitignore create mode 100644 hald/linux/Makefile.am create mode 100644 hald/linux/acpi.c create mode 100644 hald/linux/acpi.h create mode 100644 hald/linux/addons/.gitignore create mode 100644 hald/linux/addons/Makefile.am create mode 100644 hald/linux/addons/addon-acpi-buttons-toshiba.c create mode 100644 hald/linux/addons/addon-acpi.c create mode 100644 hald/linux/addons/addon-hid-ups.c create mode 100644 hald/linux/addons/addon-keyboard.c create mode 100644 hald/linux/addons/addon-macbookpro-backlight.c create mode 100644 hald/linux/addons/addon-pmu.c create mode 100644 hald/linux/addons/addon-storage.c create mode 100644 hald/linux/addons/addon-usb-csr.c create mode 100644 hald/linux/apm.c create mode 100644 hald/linux/apm.h create mode 100644 hald/linux/blockdev.c create mode 100644 hald/linux/blockdev.h create mode 100644 hald/linux/classdev.c create mode 100644 hald/linux/classdev.h create mode 100644 hald/linux/coldplug.c create mode 100644 hald/linux/coldplug.h create mode 100644 hald/linux/hotplug.c create mode 100644 hald/linux/hotplug.h create mode 100644 hald/linux/hotplug_helper.h create mode 100644 hald/linux/ids.c create mode 100644 hald/linux/ids.h create mode 100644 hald/linux/osspec.c create mode 100644 hald/linux/osspec_linux.h create mode 100644 hald/linux/physdev.c create mode 100644 hald/linux/physdev.h create mode 100644 hald/linux/pmu.c create mode 100644 hald/linux/pmu.h create mode 100644 hald/linux/probing/.gitignore create mode 100644 hald/linux/probing/Makefile.am create mode 100644 hald/linux/probing/linux_dvd_rw_utils.c create mode 100644 hald/linux/probing/linux_dvd_rw_utils.h create mode 100644 hald/linux/probing/probe-hiddev.c create mode 100644 hald/linux/probing/probe-input.c create mode 100644 hald/linux/probing/probe-pc-floppy.c create mode 100644 hald/linux/probing/probe-printer.c create mode 100644 hald/linux/probing/probe-serial.c create mode 100644 hald/linux/probing/probe-smbios.c create mode 100644 hald/linux/probing/probe-storage.c create mode 100644 hald/linux/probing/probe-volume.c delete mode 100644 hald/linux2/.gitignore delete mode 100644 hald/linux2/Makefile.am delete mode 100644 hald/linux2/acpi.c delete mode 100644 hald/linux2/acpi.h delete mode 100644 hald/linux2/addons/.gitignore delete mode 100644 hald/linux2/addons/Makefile.am delete mode 100644 hald/linux2/addons/addon-acpi-buttons-toshiba.c delete mode 100644 hald/linux2/addons/addon-acpi.c delete mode 100644 hald/linux2/addons/addon-hid-ups.c delete mode 100644 hald/linux2/addons/addon-keyboard.c delete mode 100644 hald/linux2/addons/addon-macbookpro-backlight.c delete mode 100644 hald/linux2/addons/addon-pmu.c delete mode 100644 hald/linux2/addons/addon-storage.c delete mode 100644 hald/linux2/addons/addon-usb-csr.c delete mode 100644 hald/linux2/apm.c delete mode 100644 hald/linux2/apm.h delete mode 100644 hald/linux2/blockdev.c delete mode 100644 hald/linux2/blockdev.h delete mode 100644 hald/linux2/classdev.c delete mode 100644 hald/linux2/classdev.h delete mode 100644 hald/linux2/coldplug.c delete mode 100644 hald/linux2/coldplug.h delete mode 100644 hald/linux2/hotplug.c delete mode 100644 hald/linux2/hotplug.h delete mode 100644 hald/linux2/hotplug_helper.h delete mode 100644 hald/linux2/ids.c delete mode 100644 hald/linux2/ids.h delete mode 100644 hald/linux2/osspec.c delete mode 100644 hald/linux2/osspec_linux.h delete mode 100644 hald/linux2/physdev.c delete mode 100644 hald/linux2/physdev.h delete mode 100644 hald/linux2/pmu.c delete mode 100644 hald/linux2/pmu.h delete mode 100644 hald/linux2/probing/.gitignore delete mode 100644 hald/linux2/probing/Makefile.am delete mode 100644 hald/linux2/probing/linux_dvd_rw_utils.c delete mode 100644 hald/linux2/probing/linux_dvd_rw_utils.h delete mode 100644 hald/linux2/probing/probe-hiddev.c delete mode 100644 hald/linux2/probing/probe-input.c delete mode 100644 hald/linux2/probing/probe-pc-floppy.c delete mode 100644 hald/linux2/probing/probe-printer.c delete mode 100644 hald/linux2/probing/probe-serial.c delete mode 100644 hald/linux2/probing/probe-smbios.c delete mode 100644 hald/linux2/probing/probe-storage.c delete mode 100644 hald/linux2/probing/probe-volume.c diff --git a/configure.in b/configure.in index 1d229241..be68d8fb 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= backend to use (linux2/solaris/dummy)], +AC_ARG_WITH(backend, [ --with-backend= 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 b3323900..e02e3212 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 beae4668..49f460b5 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 00000000..4bec0e4b --- /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 00000000..a3bf2bc3 --- /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 00000000..4274d77e --- /dev/null +++ b/hald/linux/acpi.c @@ -0,0 +1,1361 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 Richard Hughes + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * Copyright (C) 2005 Danny Kukawka, + * + * 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 +#endif + +#include + +#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 00000000..f7ed07a1 --- /dev/null +++ b/hald/linux/acpi.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 Richard Hughes + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * + * 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 00000000..6c2e5097 --- /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 00000000..65819f4f --- /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 00000000..7252759e --- /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 + * @date 2005-10-15 + * + * @note Low level routines from IAL, Copyright (C) 2004, 2005 + * Timo Hoenig + */ +/* + * 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 +#endif + +#include +#include +#include +#include +#include + +#include + +#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 00000000..4b193212 --- /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, + * Copyright (C) 2005 Ryan Lortie + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..1361ed6d --- /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, + * + * Based on hid-ups.c: Copyright (c) 2001 Vojtech Pavlik + * , Copyright (c) 2001 Paul + * Stewart , Tweaked by Kern + * Sibbald 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 +#endif + +/* asm/types.h required for __s32 in linux/hiddev.h */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..a054ac97 --- /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, + * Copyright (C) 2005 Ryan Lortie + * Copyright (C) 2006 Matthew Garrett + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include + +#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 00000000..f25a555a --- /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 + * Copyright (C) 2006 Nicolas Boichat + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + **************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 in the fdi files */ + if (!libhal_device_claim_interface (halctx, + "/org/freedesktop/Hal/devices/macbook_pro_lcd_panel", + "org.freedesktop.Hal.Device.LaptopPanel", + " \n" + " \n" + " \n" + " \n" + " \n" + " \n" + " \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", + " \n" + " \n" + " \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", + " \n" + " \n" + " \n" + " \n" + " \n" + " \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 00000000..68b59fe9 --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..1660abcd --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..cd1747dc --- /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 + * Copyright (C) 2005 Richard Hughes + * + * 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 +#include +#include +#include + +#include +#include +#include + +#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 00000000..e8554382 --- /dev/null +++ b/hald/linux/apm.c @@ -0,0 +1,542 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 Richard Hughes + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * + * 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 +#endif + +#include + +#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 00000000..80d0de6a --- /dev/null +++ b/hald/linux/apm.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 Richard Hughes + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * + * 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 00000000..e40dd932 --- /dev/null +++ b/hald/linux/blockdev.c @@ -0,0 +1,1419 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * blockdev.c : Handling of block devices + * + * Copyright (C) 2005 David Zeuthen, + * Copyright (C) 2005,2006 Kay Sievers, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 00000000..9095d8c5 --- /dev/null +++ b/hald/linux/blockdev.h @@ -0,0 +1,43 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * blockdev.h : Handling of block devices + * + * Copyright (C) 2004 David Zeuthen, + * + * 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 + +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 00000000..3e3a6679 --- /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, + * Copyright (C) 2005 Richard Hughes, + * Copyright (C) 2005 Danny Kukawka, + * + * 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 +#endif + +#include +#include +#include +#include /* for ARPHRD_... */ +#include +#include +#include +#include + +#include +#include + +#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 00000000..c88dc9b3 --- /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, + * + * 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 +#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 00000000..e47a90f5 --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include + +#include +#include + +#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 00000000..7da868a7 --- /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, + * + * 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 + +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 00000000..4eac8b9e --- /dev/null +++ b/hald/linux/hotplug.c @@ -0,0 +1,618 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * hotplug.c : Handling of hotplug events + * + * Copyright (C) 2004 David Zeuthen, + * + * 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 +#endif + +#include +#include +#include +#include + +#include +#include + +#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 00000000..d93d6205 --- /dev/null +++ b/hald/linux/hotplug.h @@ -0,0 +1,113 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * hotplug.h : Handling of hotplug events + * + * Copyright (C) 2004 David Zeuthen, + * + * 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 + +#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 00000000..27670374 --- /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, + * + * 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 00000000..7cb41f30 --- /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, + * + * 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 +#endif + +#include +#include +#include +#include + +#include +#include + +#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 00000000..c1893202 --- /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, + * + * 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 + +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 00000000..9571d250 --- /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, + * Copyright (C) 2005,2006 Kay Sievers, + * Copyright (C) 2005 Danny Kukawka, + * + * 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 +#endif + +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 00000000..88d516c1 --- /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, + * + * 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 +#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 00000000..c2ae795b --- /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, + * + * 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 +#endif + +#include +#include +#include + +#include +#include + +#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 00000000..6c16cc2f --- /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, + * + * 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 +#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 00000000..892fff14 --- /dev/null +++ b/hald/linux/pmu.c @@ -0,0 +1,622 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 Sjoerd Simons + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * + * 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 +#endif + +#include +#include +#include +#include +#include + +#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 00000000..c8304b3e --- /dev/null +++ b/hald/linux/pmu.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 David Zeuthen, Red Hat Inc., + * + * 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 00000000..226a9dbf --- /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 00000000..a66d858b --- /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 00000000..a75a0912 --- /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 + * + * Use-it-on-your-own-risk, GPL bless... + * + * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/ +*/ + +#include + +#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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..5b6105a5 --- /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 +// +// 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 + +#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 00000000..fbc1861a --- /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, + * + * 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 +#endif + +/* asm/types.h required for __s32 in linux/hiddev.h */ +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..6a18990d --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#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(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 00000000..7a66987e --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..bec6e9bb --- /dev/null +++ b/hald/linux/probing/probe-printer.c @@ -0,0 +1,176 @@ +/*************************************************************************** + * CVSID: $Id$ + * + * Copyright (C) 2005 David Zeuthen, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#include + +#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 00000000..b70f82ba --- /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 + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..2beb8096 --- /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, + * Copyright (C) 2005 Richard Hughes, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include + +#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 00000000..7b84a642 --- /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, + * Copyright (C) 2005 Danny Kukawka, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 00000000..8a57e525 --- /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, + * + * 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 +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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 4bec0e4b..00000000 --- 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 d7b90a31..00000000 --- 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 4274d77e..00000000 --- a/hald/linux2/acpi.c +++ /dev/null @@ -1,1361 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 Richard Hughes - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * Copyright (C) 2005 Danny Kukawka, - * - * 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 -#endif - -#include - -#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 f7ed07a1..00000000 --- a/hald/linux2/acpi.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 Richard Hughes - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * - * 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 6c2e5097..00000000 --- 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 19c229d7..00000000 --- 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 7252759e..00000000 --- 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 - * @date 2005-10-15 - * - * @note Low level routines from IAL, Copyright (C) 2004, 2005 - * Timo Hoenig - */ -/* - * 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 -#endif - -#include -#include -#include -#include -#include - -#include - -#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 4b193212..00000000 --- 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, - * Copyright (C) 2005 Ryan Lortie - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#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 1361ed6d..00000000 --- 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, - * - * Based on hid-ups.c: Copyright (c) 2001 Vojtech Pavlik - * , Copyright (c) 2001 Paul - * Stewart , Tweaked by Kern - * Sibbald 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 -#endif - -/* asm/types.h required for __s32 in linux/hiddev.h */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 a054ac97..00000000 --- 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, - * Copyright (C) 2005 Ryan Lortie - * Copyright (C) 2006 Matthew Garrett - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include - -#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 f25a555a..00000000 --- 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 - * Copyright (C) 2006 Nicolas Boichat - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - **************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#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 in the fdi files */ - if (!libhal_device_claim_interface (halctx, - "/org/freedesktop/Hal/devices/macbook_pro_lcd_panel", - "org.freedesktop.Hal.Device.LaptopPanel", - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \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", - " \n" - " \n" - " \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", - " \n" - " \n" - " \n" - " \n" - " \n" - " \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 68b59fe9..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 1660abcd..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 cd1747dc..00000000 --- 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 - * Copyright (C) 2005 Richard Hughes - * - * 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 -#include -#include -#include - -#include -#include -#include - -#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 e8554382..00000000 --- a/hald/linux2/apm.c +++ /dev/null @@ -1,542 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 Richard Hughes - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * - * 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 -#endif - -#include - -#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 80d0de6a..00000000 --- a/hald/linux2/apm.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 Richard Hughes - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * - * 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 e40dd932..00000000 --- a/hald/linux2/blockdev.c +++ /dev/null @@ -1,1419 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * blockdev.c : Handling of block devices - * - * Copyright (C) 2005 David Zeuthen, - * Copyright (C) 2005,2006 Kay Sievers, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 9095d8c5..00000000 --- a/hald/linux2/blockdev.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * blockdev.h : Handling of block devices - * - * Copyright (C) 2004 David Zeuthen, - * - * 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 - -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 3e3a6679..00000000 --- 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, - * Copyright (C) 2005 Richard Hughes, - * Copyright (C) 2005 Danny Kukawka, - * - * 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 -#endif - -#include -#include -#include -#include /* for ARPHRD_... */ -#include -#include -#include -#include - -#include -#include - -#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 c88dc9b3..00000000 --- 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, - * - * 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 -#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 e47a90f5..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include - -#include -#include - -#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 7da868a7..00000000 --- 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, - * - * 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 - -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 4eac8b9e..00000000 --- a/hald/linux2/hotplug.c +++ /dev/null @@ -1,618 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * hotplug.c : Handling of hotplug events - * - * Copyright (C) 2004 David Zeuthen, - * - * 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 -#endif - -#include -#include -#include -#include - -#include -#include - -#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 d93d6205..00000000 --- a/hald/linux2/hotplug.h +++ /dev/null @@ -1,113 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * hotplug.h : Handling of hotplug events - * - * Copyright (C) 2004 David Zeuthen, - * - * 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 - -#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 27670374..00000000 --- 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, - * - * 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 7cb41f30..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include - -#include -#include - -#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 c1893202..00000000 --- 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, - * - * 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 - -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 9571d250..00000000 --- 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, - * Copyright (C) 2005,2006 Kay Sievers, - * Copyright (C) 2005 Danny Kukawka, - * - * 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 -#endif - -#define _GNU_SOURCE 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 88d516c1..00000000 --- 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, - * - * 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 -#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 c2ae795b..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include - -#include -#include - -#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 6c16cc2f..00000000 --- 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, - * - * 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 -#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 892fff14..00000000 --- a/hald/linux2/pmu.c +++ /dev/null @@ -1,622 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 Sjoerd Simons - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * - * 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 -#endif - -#include -#include -#include -#include -#include - -#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 c8304b3e..00000000 --- a/hald/linux2/pmu.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 David Zeuthen, Red Hat Inc., - * - * 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 226a9dbf..00000000 --- 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 a9f0342e..00000000 --- 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 a75a0912..00000000 --- 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 - * - * Use-it-on-your-own-risk, GPL bless... - * - * For further details see http://fy.chalmers.se/~appro/linux/DVD+RW/ -*/ - -#include - -#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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 5b6105a5..00000000 --- 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 -// -// 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 - -#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 fbc1861a..00000000 --- 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, - * - * 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 -#endif - -/* asm/types.h required for __s32 in linux/hiddev.h */ -#include -#include -#include -#include -#include -#include -#include -#include - -#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 6a18990d..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#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(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 7a66987e..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#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 bec6e9bb..00000000 --- a/hald/linux2/probing/probe-printer.c +++ /dev/null @@ -1,176 +0,0 @@ -/*************************************************************************** - * CVSID: $Id$ - * - * Copyright (C) 2005 David Zeuthen, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - -#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 b70f82ba..00000000 --- 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 - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include - -#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 2beb8096..00000000 --- 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, - * Copyright (C) 2005 Richard Hughes, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include - -#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 ed5f010f..00000000 --- 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, - * Copyright (C) 2005 Danny Kukawka, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 8a57e525..00000000 --- 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, - * - * 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 -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#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 f36ed5a6..69dd17eb 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 6a29bc5a..8f47d206 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 b64c2c04..7d842382 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 -- cgit v1.2.3