hal/hald/linux2 Makefile.am, NONE, 1.1 blockdev.c, NONE,
1.1 blockdev.h, NONE, 1.1 classdev.c, NONE, 1.1 classdev.h,
NONE, 1.1 coldplug.c, NONE, 1.1 coldplug.h, NONE,
1.1 hotplug.c, NONE, 1.1 hotplug.h, NONE, 1.1 hotplug_helper.h,
NONE, 1.1 ids.c, NONE, 1.1 ids.h, NONE, 1.1 osspec.c, NONE,
1.1 physdev.c, NONE, 1.1 physdev.h, NONE, 1.1 util.c, NONE,
1.1 util.h, NONE, 1.1
David Zeuthen
david at freedesktop.org
Tue Jan 18 11:48:15 PST 2005
- Previous message: hal/hald/linux Makefile.am, 1.1, NONE block_class_device.c, 1.88,
NONE bus_device.c, 1.20, NONE bus_device.h, 1.9,
NONE class_device.c, 1.30, NONE class_device.h, 1.12,
NONE common.c, 1.16, NONE common.h, 1.11, NONE hald_helper.h,
1.6, NONE ide_bus_device.c, 1.8, NONE ide_host_bus_device.c,
1.9, NONE ieee1394_class_device.c, 1.4,
NONE ieee1394_host_class_device.c, 1.5,
NONE ieee1394_node_class_device.c, 1.6,
NONE input_class_device.c, 1.11, NONE linux_dvd_rw_utils.c,
1.8, NONE linux_dvd_rw_utils.h, 1.6, NONE macio_bus_device.c,
1.4, NONE multimedia_class_device.c, 1.2,
NONE net_class_device.c, 1.22, NONE osspec.c, 1.54,
NONE pci_bus_device.c, 1.9, NONE pcmcia_cs.h, 1.1,
NONE pcmcia_socket_class_device.c, 1.4, NONE pcmcia_utils.c,
1.2, NONE pcmcia_utils.h, 1.1, NONE platform_bus_device.c, 1.7,
NONE printer_class_device.c, 1.10, NONE scsi_bus_device.c, 1.1,
NONE scsi_generic_class_device.c, 1.4,
NONE scsi_host_class_device.c, 1.10,
NONE serial_class_device.c, 1.1, NONE usb_bus_device.c, 1.15,
NONE usb_serial_bus_device.c, 1.1, NONE usbif_bus_device.c,
1.9, NONE
- Next message: hal/hald callout.c, 1.15, 1.16 device_info.c, 1.17, 1.18 hald_dbus.c,
1.17, 1.18
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
Update of /cvs/hal/hal/hald/linux2
In directory gabe:/tmp/cvs-serv19239/hald/linux2
Added Files:
Makefile.am blockdev.c blockdev.h classdev.c classdev.h
coldplug.c coldplug.h hotplug.c hotplug.h hotplug_helper.h
ids.c ids.h osspec.c physdev.c physdev.h util.c util.h
Log Message:
2005-01-18 David Zeuthen <david at fubar.dk>
* tools/linux/Makefile.am: Remove hal.dev build rules
* tools/linux/hal_dev.c: Remove
* configure.in: Set linux2 as the default backend
* hald/linux: Remove all files here as they will get reimplemented
in hald/linux2
* hald/linux2: Add a bunch of new files
* hald/linux2/probing: Add some new files
2005-01-18 David Zeuthen <davidz at redhat.com>
Merge some more changes from the stable branch (except those
in hald/linux and doc/spec)
2005-01-12 David Zeuthen <davidz at redhat.com>
* hald/callout.c (callout_timeout_handler): Be tough and kill
the misbehaving child the hard way - suggestion from Joe Shaw.
2005-01-12 David Zeuthen <davidz at redhat.com>
* hald/linux/osspec.c (HOTPLUG_TIMEOUT): Increase to 25 seconds
to better cope with callouts timeout of 10 seconds
* hald/callout.c (iochn_data): Cope with callouts terminating
and free timeout handler
(callout_timeout_handler): New function; kill callouts if they
time out
(process_next_callout): Setup timeout for callouts - set to
ten seconds
2005-01-11 David Zeuthen <davidz at redhat.com>
* hald/callout.c: Simplify a lot more by demanding that callouts
are run sequentially - which they are anyway since everything is
serialized. Make a mental note to review and stress test this in
the morning.
2005-01-11 David Zeuthen <davidz at redhat.com>
* hald/callout.c: Fix some craziness adding an idle handler for
detecting when callouts complete - fixes bug on my new AMD64
system with device add/remove prior to completion of callouts -
one visible effect was that fstab-sync was crashing since it
couldn't retrieve the block.device device as the device was
removed prior to the completion of the callout
2005-01-07 David Zeuthen <davidz at redhat.com>
* fdi/20freedesktop/ide-drives.fdi: Also check IDE floppies for whether
they are Zip drives
2005-01-07 Joe Shaw <joeshaw at novell.com>
* configure.in: Check for popt when building fstab-sync and error
out if it's not found.
* tools/Makefile.am: Build fstab-sync conditionally based on
whether --enable-fstab-sync is passed in.
2005-01-06 David Zeuthen <davidz at redhat.com>
* libhal/libhal.c (hal_device_query_capability): Patch from Tim
Müller <t.i.m at zen.co.uk>. The attached patch fixes a small memory
leak in libhal's hal_device_query_capability().
2005-01-03 David Zeuthen <davidz at redhat.com>
* configure.in: Added it to ALL_LINGUAS
* po/it.po: Italien translation from Pier Luigi Fiorini
<pierluigi.fiorini at mockup.org>
2004-12-15 David Zeuthen <davidz at redhat.com>
* fdi/20freedesktop/usb-zip-drives.fdi: Only match on actual
harddisks to avoid wrong detection of e.g. "Iomega ZipCD 650 USB CDRW"
drives (Red Hat bug #143834)
* fdi/20freedesktop/ide-drives.fdi: ditto
--- NEW FILE: Makefile.am ---
SUBDIRS = probing .
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.. \
@PACKAGE_CFLAGS@
noinst_LTLIBRARIES = libhald_linux2.la
libhald_linux2_la_SOURCES = \
osspec.c \
hotplug.h hotplug.c \
coldplug.h coldplug.c \
physdev.h physdev.c \
classdev.h classdev.c \
blockdev.h blockdev.c \
util.h util.c \
ids.h ids.c
--- NEW FILE: blockdev.c ---
/***************************************************************************
* CVSID: $Id: blockdev.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* blockdev.c : Handling of block devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
#include "coldplug.h"
#include "hotplug_helper.h"
#include "hotplug.h"
#include "blockdev.h"
void
hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const char *device_file, gboolean is_partition,
HalDevice *parent, void *end_token)
{
#if 0
HalDevice *d;
HAL_INFO (("block_add: sysfs_path=%s dev=%s is_part=%d parent=0x%08x",
sysfs_path, device_file, is_partition, parent));
d = hal_device_new ();
hal_device_property_set_string (d, "linux.sysfs_path_device", sysfs_path);
hal_device_property_set_string (d, "info.udi", sysfs_path);
hal_device_property_set_string (d, "info.bus", "block");
hal_device_set_udi (d, sysfs_path);
if (parent != NULL) {
hal_device_property_set_string (d, "info.parent", parent->udi);
}
hal_device_store_add (hald_get_gdl (), d);
#endif
hotplug_event_end (end_token);
}
void
hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, gboolean is_partition, void *end_token)
{
#if 0
HalDevice *d;
HAL_INFO (("block_rem: sysfs_path=%s is_part=%d", sysfs_path, is_partition));
d = hal_device_store_match_key_value_string (hald_get_gdl (),
"linux.sysfs_path_device",
sysfs_path);
if (d == NULL) {
HAL_WARNING (("Couldn't remove device with sysfs path %s - not found", sysfs_path));
goto out;
}
if (!hal_device_store_remove (hald_get_gdl (), d)) {
HAL_WARNING (("Error removing device with sysfs path %s", sysfs_path));
}
out:
#endif
hotplug_event_end (end_token);
}
--- NEW FILE: blockdev.h ---
/***************************************************************************
* CVSID: $Id: blockdev.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* blockdev.h : Handling of block devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef BLOCKDEV_H
#define BLOCKDEV_H
#include <glib.h>
void hotplug_event_begin_add_blockdev (const gchar *sysfs_path, const char *device_file, gboolean is_partition, HalDevice *parent, void *end_token);
void hotplug_event_begin_remove_blockdev (const gchar *sysfs_path, gboolean is_partition, void *end_token);
#endif /* BLOCKDEV_H */
--- NEW FILE: classdev.c ---
/***************************************************************************
* CVSID: $Id: classdev.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* classdev.c : Handling of functional kernel devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
#include "coldplug.h"
#include "hotplug_helper.h"
#include "hotplug.h"
#include "classdev.h"
static void
input_helper_done(HalDevice *d, gboolean timed_out, gint return_code, gpointer data1, gpointer data2)
{
gchar udi[256];
void *end_token = (void *) data1;
HAL_INFO (("entering; timed_out=%d, return_code=%d", timed_out, return_code));
/* Discard device if probing reports failure */
if (return_code != 0) {
hal_device_store_remove (hald_get_tdl (), d);
goto out;
}
/* Merge properties from .fdi files */
di_search_and_merge (d);
/* TODO: Run callouts */
/* Compute UDI */
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);
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
hal_device_store_add (hald_get_gdl (), d);
/* TODO: adjust capabilities on physdev */
out:
hotplug_event_end (end_token);
}
static gboolean
input_add (const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, void *end_token)
{
HalDevice *d;
d = hal_device_new ();
hal_device_property_set_string (d, "linux.sysfs_path_device", 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, "info.bus", "unknown");
hal_device_property_set_string (d, "input.device", device_file);
/* Add to temporary device store */
hal_device_store_add (hald_get_tdl (), d);
/* probe the actual device node */
if (!helper_invoke ("hald-probe-input", d, (gpointer) end_token, NULL, input_helper_done, HAL_HELPER_TIMEOUT)) {
hal_device_store_remove (hald_get_tdl (), d);
goto out;
}
return TRUE;
out:
hotplug_event_end (end_token);
return TRUE;
}
void
hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file,
HalDevice *physdev, void *end_token)
{
HAL_INFO (("class_add: subsys=%s sysfs_path=%s dev=%s physdev=0x%08x", subsystem, sysfs_path, device_file, physdev));
if (strcmp (subsystem, "input") == 0)
input_add (sysfs_path, device_file, physdev, end_token);
else
hotplug_event_end (end_token);
}
void
hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token)
{
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_device", sysfs_path);
if (d == NULL) {
HAL_WARNING (("Error removing device"));
} else {
const gchar *physdev_udi;
HalDevice *physdev;
physdev_udi = hal_device_property_get_string (d, "info.physical_device");
if (!hal_device_store_remove (hald_get_gdl (), d)) {
HAL_WARNING (("Error removing device"));
}
if (physdev_udi != NULL) {
physdev = hal_device_store_find (hald_get_gdl (), physdev_udi);
/* TODO: adjust capabilities on physdev */
}
}
hotplug_event_end (end_token);
}
--- NEW FILE: classdev.h ---
/***************************************************************************
* CVSID: $Id: classdev.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* classdev.h : Handling of functional kernel devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef CLASSDEV_H
#define CLASSDEV_H
#include <glib.h>
void hotplug_event_begin_add_classdev (const gchar *subsystem, const gchar *sysfs_path, const gchar *device_file, HalDevice *physdev, void *end_token);
void hotplug_event_begin_remove_classdev (const gchar *subsystem, const gchar *sysfs_path, void *end_token);
#endif /* CLASSDEV_H */
--- NEW FILE: coldplug.c ---
/***************************************************************************
* CVSID: $Id: coldplug.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* coldplug.c : Synthesize hotplug events when starting up
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
#include "coldplug.h"
#include "hotplug.h"
static void
coldplug_compute_visit_device (const gchar *path, GHashTable *sysfs_to_bus_map);
/*#define HAL_COLDPLUG_VERBOSE*/
/** 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 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];
const gchar *f;
const gchar *f1;
const gchar *f2;
/** 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;
/* 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", hal_sysfs_path);
if ((dir = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/bus: %s", 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", hal_sysfs_path, f);
if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/bus/%s: %s", 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",
hal_sysfs_path, f, f1);
if ((dir2 = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %s/bus/%s/%s: %s",
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",
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!",
hal_sysfs_path,
f, f1, f2, err->message));
g_error_free (err);
goto error;
}
g_snprintf (path, HAL_PATH_MAX, "%s/bus/%s/%s", 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);
/* 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", hal_sysfs_path);
if ((dir = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/devices: %s", 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", hal_sysfs_path, f);
if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/devices/%s: %s", 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", hal_sysfs_path, f, f1);
coldplug_compute_visit_device (path, sysfs_to_bus_map);
}
g_dir_close (dir1);
}
g_dir_close (dir);
g_hash_table_destroy (sysfs_to_bus_map);
/* add class devices */
g_snprintf (path, HAL_PATH_MAX, "%s/class", hal_sysfs_path);
if ((dir = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/class: %s", 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", hal_sysfs_path, f);
if ((dir1 = g_dir_open (path, 0, &err)) == NULL) {
HAL_ERROR (("Unable to open %/class/%s: %s", hal_sysfs_path, f, err->message));
g_error_free (err);
goto error;
}
while ((f1 = g_dir_read_name (dir1)) != NULL) {
HotplugEvent *hotplug_event;
gchar *target;
gchar *normalized_target;
g_snprintf (path, HAL_PATH_MAX, "%s/class/%s/%s", hal_sysfs_path, f, f1);
#ifdef HAL_COLDPLUG_VERBOSE
printf ("class: %s (%s)\n", path, f);
#endif
g_snprintf (path1, HAL_PATH_MAX, "%s/class/%s/%s/device", hal_sysfs_path, f, f1);
if (((target = g_file_read_link (path1, NULL)) != NULL)) {
normalized_target = hal_util_get_normalized_path (path1, target);
g_free (target);
} else {
normalized_target = NULL;
}
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = TRUE;
g_strlcpy (hotplug_event->subsystem, f, sizeof (hotplug_event->subsystem));
g_strlcpy (hotplug_event->sysfs_path, path, sizeof (hotplug_event->sysfs_path));
hal_util_get_device_file (path, hotplug_event->device_file, sizeof (hotplug_event->device_file));
if (normalized_target != NULL)
g_strlcpy (hotplug_event->wait_for_sysfs_path, normalized_target, sizeof (hotplug_event->wait_for_sysfs_path));
else
hotplug_event->wait_for_sysfs_path[0] = '\0';
hotplug_event->net_ifindex = -1;
hotplug_event_enqueue (hotplug_event);
g_free (normalized_target);
}
g_dir_close (dir1);
}
g_dir_close (dir);
/* add block devices */
g_snprintf (path, HAL_PATH_MAX, "%s/block", 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) {
GDir *dir1;
gsize flen;
HotplugEvent *hotplug_event;
gchar *target;
gchar *normalized_target;
g_snprintf (path, HAL_PATH_MAX, "%s/block/%s", hal_sysfs_path, f);
#ifdef HAL_COLDPLUG_VERBOSE
printf ("block: %s (block)\n", path);
#endif
g_snprintf (path1, HAL_PATH_MAX, "%s/block/%s/device", hal_sysfs_path, f);
if (((target = g_file_read_link (path1, NULL)) != NULL)) {
normalized_target = hal_util_get_normalized_path (path1, target);
g_free (target);
} else {
normalized_target = NULL;
}
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = TRUE;
g_strlcpy (hotplug_event->subsystem, "block", sizeof (hotplug_event->subsystem));
g_strlcpy (hotplug_event->sysfs_path, path, sizeof (hotplug_event->sysfs_path));
hal_util_get_device_file (path, hotplug_event->device_file, sizeof (hotplug_event->device_file));
if (normalized_target != NULL)
g_strlcpy (hotplug_event->wait_for_sysfs_path, normalized_target, sizeof (hotplug_event->wait_for_sysfs_path));
else
hotplug_event->wait_for_sysfs_path[0] = '\0';
hotplug_event->net_ifindex = -1;
hotplug_event_enqueue (hotplug_event);
g_free (normalized_target);
flen = strlen (f);
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, flen) == 0) {
g_snprintf (path1, HAL_PATH_MAX, "%s/%s", path, f1);
#ifdef HAL_COLDPLUG_VERBOSE
printf ("block: %s (block)\n", path1);
#endif
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = TRUE;
g_strlcpy (hotplug_event->subsystem, "block", sizeof (hotplug_event->subsystem));
g_strlcpy (hotplug_event->sysfs_path, path1, sizeof (hotplug_event->sysfs_path));
g_strlcpy (hotplug_event->wait_for_sysfs_path, path, sizeof (hotplug_event->wait_for_sysfs_path));
hal_util_get_device_file (path1, hotplug_event->device_file, sizeof (hotplug_event->device_file));
hotplug_event->net_ifindex = -1;
hotplug_event_enqueue (hotplug_event);
}
}
g_dir_close (dir1);
}
g_dir_close (dir);
return TRUE;
error:
HAL_ERROR (("Error building the orderered list of sysfs paths"));
return FALSE;
}
static void
coldplug_compute_visit_device (const gchar *path, GHashTable *sysfs_to_bus_map)
{
gchar *bus;
GError *err;
GDir *dir;
const gchar *f;
bus = g_hash_table_lookup (sysfs_to_bus_map, path);
if (bus != NULL) {
HotplugEvent *hotplug_event;
gchar *parent_sysfs_path;
#ifdef HAL_COLDPLUG_VERBOSE
printf ("bus: %s (%s)\n", path, bus);
#endif
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = TRUE;
g_strlcpy (hotplug_event->subsystem, bus, sizeof (hotplug_event->subsystem));
g_strlcpy (hotplug_event->sysfs_path, path, sizeof (hotplug_event->sysfs_path));
hotplug_event->net_ifindex = -1;
parent_sysfs_path = hal_util_get_parent_sysfs_path (path);
g_strlcpy (hotplug_event->wait_for_sysfs_path, parent_sysfs_path, sizeof (hotplug_event->wait_for_sysfs_path));
g_free (parent_sysfs_path);
hotplug_event->device_file[0] = '\0';
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);
}
}
}
g_dir_close (dir);
error:
return;
}
--- NEW FILE: coldplug.h ---
/***************************************************************************
* CVSID: $Id: coldplug.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* coldplug.h : Synthesize hotplug events when starting up
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef COLDPLUG_H
#define COLDPLUG_H
#include <glib.h>
gboolean coldplug_synthesize_events (void);
#endif /* COLDPLUG_H */
--- NEW FILE: hotplug.c ---
/***************************************************************************
* CVSID: $Id: hotplug.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* hotplug.c : Handling of hotplug events
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "hotplug.h"
#include "physdev.h"
#include "classdev.h"
#include "blockdev.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 ();
}
static void
hotplug_event_begin (HotplugEvent *hotplug_event)
{
static char sys_devices_path[HAL_PATH_MAX];
static char sys_class_path[HAL_PATH_MAX];
static char sys_block_path[HAL_PATH_MAX];
static gsize sys_devices_path_len = 0;
static gsize sys_class_path_len = 0;
static gsize sys_block_path_len = 0;
if (sys_block_path_len == 0) {
sys_devices_path_len = g_snprintf (sys_devices_path, HAL_PATH_MAX, "%s/devices", hal_sysfs_path);
sys_class_path_len = g_snprintf (sys_class_path, HAL_PATH_MAX, "%s/class", hal_sysfs_path);
sys_block_path_len = g_snprintf (sys_block_path, HAL_PATH_MAX, "%s/block", hal_sysfs_path);
}
if (strncmp (hotplug_event->sysfs_path, sys_devices_path, sys_devices_path_len) == 0) {
if (hotplug_event->is_add) {
HalDevice *parent;
parent = hal_util_find_closest_ancestor (hotplug_event->sysfs_path);
hotplug_event_begin_add_physdev (hotplug_event->subsystem,
hotplug_event->sysfs_path,
parent,
(void *) hotplug_event);
} else {
hotplug_event_begin_remove_physdev (hotplug_event->subsystem,
hotplug_event->sysfs_path,
(void *) hotplug_event);
}
} else if (strncmp (hotplug_event->sysfs_path, sys_class_path, sys_class_path_len) == 0) {
if (hotplug_event->is_add) {
gchar *target;
HalDevice *physdev;
char physdevpath[256];
/* TODO: fixup net devices by looking at ifindex */
g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs_path);
if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
gchar *normalized_target;
normalized_target = hal_util_get_normalized_path (hotplug_event->sysfs_path, target);
g_free (target);
physdev = hal_device_store_match_key_value_string (hald_get_gdl (),
"linux.sysfs_path_device",
normalized_target);
g_free (normalized_target);
} else {
physdev = NULL;
}
hotplug_event_begin_add_classdev (hotplug_event->subsystem,
hotplug_event->sysfs_path,
hotplug_event->device_file,
physdev,
(void *) hotplug_event);
} else {
hotplug_event_begin_remove_classdev (hotplug_event->subsystem,
hotplug_event->sysfs_path,
(void *) hotplug_event);
}
} else if (strncmp (hotplug_event->sysfs_path, sys_block_path, sys_block_path_len) == 0) {
gchar *parent_path;
gboolean is_partition;
parent_path = hal_util_get_parent_sysfs_path (hotplug_event->sysfs_path);
is_partition = (strcmp (parent_path, sys_block_path) != 0);
if (hotplug_event->is_add) {
HalDevice *parent;
if (is_partition) {
parent = hal_device_store_match_key_value_string (hald_get_gdl (),
"linux.sysfs_path_device",
parent_path);
} else {
gchar *target;
char physdevpath[256];
g_snprintf (physdevpath, HAL_PATH_MAX, "%s/device", hotplug_event->sysfs_path);
if (((target = g_file_read_link (physdevpath, NULL)) != NULL)) {
gchar *normalized_target;
normalized_target = hal_util_get_normalized_path (hotplug_event->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);
} else {
parent = NULL;
}
}
hotplug_event_begin_add_blockdev (hotplug_event->sysfs_path,
hotplug_event->device_file,
is_partition,
parent,
(void *) hotplug_event);
} else {
hotplug_event_begin_remove_blockdev (hotplug_event->sysfs_path,
is_partition,
(void *) hotplug_event);
}
} else {
/* just ignore this hotplug event */
hotplug_event_end ((void *) hotplug_event);
}
}
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_process_queue (void)
{
HotplugEvent *hotplug_event;
if (hotplug_event_queue == NULL)
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:
;
}
--- NEW FILE: hotplug.h ---
/***************************************************************************
* CVSID: $Id: hotplug.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* hotplug.h : Handling of hotplug events
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef HOTPLUG_H
#define HOTPLUG_H
#include <glib.h>
#include "util.h"
/** Data structure representing a hotplug event; also used for
* coldplugging.
*/
typedef struct
{
gboolean is_add; /**< Whether the event is add or remove */
char subsystem[HAL_PATH_MAX]; /**< Subsystem e.g. usb, pci (only for hotplug msg) */
char sysfs_path[HAL_PATH_MAX]; /**< Path into sysfs e.g. /sys/block/sda */
char wait_for_sysfs_path[HAL_PATH_MAX]; /**< Wait for completion of events that a) comes before this one; AND
* b) has a sysfs path that is contained in or equals this */
char device_file [HAL_PATH_MAX]; /**< Path to special device (may be NULL) */
int net_ifindex; /**< For network class devices only; the value of the ifindex file */
} HotplugEvent;
void hotplug_event_enqueue (HotplugEvent *event);
void hotplug_event_process_queue (void);
void hotplug_event_end (void *end_token);
#endif /* HOTPLUG_H */
--- NEW FILE: hotplug_helper.h ---
/***************************************************************************
* CVSID: $Id: hotplug_helper.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* HAL daemon hotplug.d and dev.d helper details
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 */
--- NEW FILE: ids.c ---
/***************************************************************************
* CVSID: $Id: ids.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* classdev.c : Handling of functional kernel devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../logger.h"
#include "ids.h"
/** Pointer to where the pci.ids file is loaded */
static char *pci_ids = NULL;
/** Length of data store at at pci_ids */
static unsigned int pci_ids_len;
/** Iterator position into pci_ids */
static unsigned int pci_ids_iter_pos;
/** Initialize the pci.ids line iterator to the beginning of the file */
static void
pci_ids_line_iter_init ()
{
pci_ids_iter_pos = 0;
}
/** Maximum length of lines in pci.ids */
#define PCI_IDS_MAX_LINE_LEN 512
/** Get the next line from pci.ids
*
* @param line_len Pointer to where number of bytes in line will
* be stored
* @return Pointer to the line; only valid until the
* next invocation of this function
*/
static char *
pci_ids_line_iter_get_line (unsigned int *line_len)
{
unsigned int i;
static char line[PCI_IDS_MAX_LINE_LEN];
for (i = 0;
pci_ids_iter_pos < pci_ids_len &&
i < PCI_IDS_MAX_LINE_LEN - 1 &&
pci_ids[pci_ids_iter_pos] != '\n'; i++, pci_ids_iter_pos++) {
line[i] = pci_ids[pci_ids_iter_pos];
}
line[i] = '\0';
if (line_len != NULL)
*line_len = i;
pci_ids_iter_pos++;
return line;
}
/** See if there are more lines to process in pci.ids
*
* @return #TRUE iff there are more lines to process
*/
static dbus_bool_t
pci_ids_line_iter_has_more ()
{
return pci_ids_iter_pos < pci_ids_len;
}
/** Find the names for a PCI device.
*
* The pointers returned are only valid until the next invocation of this
* function.
*
* @param vendor_id PCI vendor id or 0 if unknown
* @param product_id PCI product id or 0 if unknown
* @param subsys_vendor_id PCI subsystem vendor id or 0 if unknown
* @param subsys_product_id PCI subsystem product id or 0 if unknown
* @param vendor_name Set to pointer of result or #NULL
* @param product_name Set to pointer of result or #NULL
* @param subsys_vendor_name Set to pointer of result or #NULL
* @param subsys_product_name Set to pointer of result or #NULL
*/
void
ids_find_pci (int vendor_id, int product_id,
int subsys_vendor_id, int subsys_product_id,
char **vendor_name, char **product_name,
char **subsys_vendor_name, char **subsys_product_name)
{
char *line;
unsigned int i;
unsigned int line_len;
unsigned int num_tabs;
char rep_vi[8];
char rep_pi[8];
char rep_svi[8];
char rep_spi[8];
dbus_bool_t vendor_matched = FALSE;
dbus_bool_t product_matched = FALSE;
static char store_vn[PCI_IDS_MAX_LINE_LEN];
static char store_pn[PCI_IDS_MAX_LINE_LEN];
static char store_svn[PCI_IDS_MAX_LINE_LEN];
static char store_spn[PCI_IDS_MAX_LINE_LEN];
snprintf (rep_vi, 8, "%04x", vendor_id);
snprintf (rep_pi, 8, "%04x", product_id);
snprintf (rep_svi, 8, "%04x", subsys_vendor_id);
snprintf (rep_spi, 8, "%04x", subsys_product_id);
*vendor_name = NULL;
*product_name = NULL;
*subsys_vendor_name = NULL;
*subsys_product_name = NULL;
for (pci_ids_line_iter_init (); pci_ids_line_iter_has_more ();) {
line = pci_ids_line_iter_get_line (&line_len);
/* skip lines with no content */
if (line_len < 4)
continue;
/* skip comments */
if (line[0] == '#')
continue;
/* count number of tabs */
num_tabs = 0;
for (i = 0; i < line_len; i++) {
if (line[i] != '\t')
break;
num_tabs++;
}
switch (num_tabs) {
case 0:
/* vendor names */
vendor_matched = FALSE;
/* first check subsys_vendor_id, if haven't done
* already */
if (*subsys_vendor_name == NULL
&& subsys_vendor_id != 0) {
if ((*((dbus_uint32_t *) line)) ==
(*((dbus_uint32_t *) rep_svi))) {
/* found it */
for (i = 4; i < line_len; i++) {
if (!isspace (line[i]))
break;
}
strncpy (store_svn, line + i,
PCI_IDS_MAX_LINE_LEN);
*subsys_vendor_name = store_svn;
}
}
/* check vendor_id */
if (vendor_id != 0) {
if (memcmp (line, rep_vi, 4) == 0) {
/* found it */
vendor_matched = TRUE;
for (i = 4; i < line_len; i++) {
if (!isspace (line[i]))
break;
}
strncpy (store_vn, line + i,
PCI_IDS_MAX_LINE_LEN);
*vendor_name = store_vn;
}
}
break;
case 1:
product_matched = FALSE;
/* product names */
if (!vendor_matched)
continue;
/* check product_id */
if (product_id != 0) {
if (memcmp (line + 1, rep_pi, 4) == 0) {
/* found it */
product_matched = TRUE;
for (i = 5; i < line_len; i++) {
if (!isspace (line[i]))
break;
}
strncpy (store_pn, line + i,
PCI_IDS_MAX_LINE_LEN);
*product_name = store_pn;
}
}
break;
case 2:
/* subsystem_vendor subsystem_product */
if (!vendor_matched || !product_matched)
continue;
/* check product_id */
if (subsys_vendor_id != 0
&& subsys_product_id != 0) {
if (memcmp (line + 2, rep_svi, 4) == 0
&& memcmp (line + 7, rep_spi,
4) == 0) {
/* found it */
for (i = 11; i < line_len; i++) {
if (!isspace (line[i]))
break;
}
strncpy (store_spn, line + i,
PCI_IDS_MAX_LINE_LEN);
*subsys_product_name = store_spn;
}
}
break;
default:
break;
}
}
}
/** 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"));
free (pci_ids);
pci_ids = NULL;
fclose(fp);
return FALSE;
}
fclose(fp);
return TRUE;
}
/** 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;
}
/*==========================================================================*/
/** 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;
}
}
}
/** 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");
free (usb_ids);
usb_ids = NULL;
fclose(fp);
return FALSE;
}
fclose(fp);
return TRUE;
}
/** 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;
}
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");
}
--- NEW FILE: ids.h ---
/***************************************************************************
* CVSID: $Id: ids.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* ids.h : Lookup names from hardware identifiers
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef IDS_H
#define IDS_H
#include <glib.h>
void ids_init (void);
void
ids_find_pci (int vendor_id, int product_id,
int subsys_vendor_id, int subsys_product_id,
char **vendor_name, char **product_name,
char **subsys_vendor_name, char **subsys_product_name);
void
ids_find_usb (int vendor_id, int product_id,
char **vendor_name, char **product_name);
#endif /* IDS_H */
--- NEW FILE: osspec.c ---
/***************************************************************************
* CVSID: $Id: osspec.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* osspec.c : New and improved HAL backend for Linux 2.6
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
#include "hotplug.h"
#include "coldplug.h"
#include "hotplug_helper.h"
#include "ids.h"
char hal_sysfs_path [HAL_PATH_MAX];
char hal_proc_path [HAL_PATH_MAX];
static gboolean
hald_helper_data (GIOChannel *source,
GIOCondition condition,
gpointer user_data)
{
struct hald_helper_msg msg;
int fd;
int retval;
struct msghdr smsg;
struct cmsghdr *cmsg;
struct iovec iov;
struct ucred *cred;
char cred_msg[CMSG_SPACE(sizeof(struct ucred))];
fd = g_io_channel_unix_get_fd (source);
iov.iov_base = &msg;
iov.iov_len = sizeof (struct hald_helper_msg);
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 (msg.magic != HALD_HELPER_MAGIC) {
HAL_INFO (("Magic is wrong, message ignored", cred->uid));
goto out;
}
HAL_INFO (("SEQNUM=%lld, TIMESTAMP=%d, ACTION=%s, SUBSYS=%s, SYSFSPATH=%s, DEVNAME=%s, IFINDEX=%d",
msg.seqnum, msg.time_stamp, msg.action, msg.subsystem,
msg.sysfs_path, msg.device_name, msg.net_ifindex));
if (strcmp (msg.action, "add") == 0) {
HotplugEvent *hotplug_event;
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = TRUE;
g_strlcpy (hotplug_event->subsystem, msg.subsystem, sizeof (hotplug_event->subsystem));
g_snprintf (hotplug_event->sysfs_path, sizeof (hotplug_event->sysfs_path), "%s%s",
hal_sysfs_path, msg.sysfs_path);
g_strlcpy (hotplug_event->device_file, msg.device_name, sizeof (hotplug_event->device_file));
/* TODO: set wait_for_sysfs_path */
hotplug_event->net_ifindex = msg.net_ifindex;
/* queue up and process */
hotplug_event_enqueue (hotplug_event);
hotplug_event_process_queue ();
} else if (strcmp (msg.action, "remove") == 0) {
HotplugEvent *hotplug_event;
hotplug_event = g_new0 (HotplugEvent, 1);
hotplug_event->is_add = FALSE;
g_strlcpy (hotplug_event->subsystem, msg.subsystem, sizeof (hotplug_event->subsystem));
g_snprintf (hotplug_event->sysfs_path, sizeof (hotplug_event->sysfs_path), "%s%s",
hal_sysfs_path, msg.sysfs_path);
g_strlcpy (hotplug_event->device_file, msg.device_name, sizeof (hotplug_event->device_file));
/* TODO: set wait_for_sysfs_path */
hotplug_event->net_ifindex = msg.net_ifindex;
/* queue up and process */
hotplug_event_enqueue (hotplug_event);
hotplug_event_process_queue ();
}
out:
return TRUE;
}
void
osspec_init (void)
{
int socketfd;
struct sockaddr_un saddr;
socklen_t addrlen;
GIOChannel *channel;
const int on = 1;
/* setup socket for listening from datagrams from the hal.hotplug helper */
memset(&saddr, 0x00, sizeof(saddr));
saddr.sun_family = AF_LOCAL;
/* use abstract namespace for socket path */
strcpy(&saddr.sun_path[1], HALD_HELPER_SOCKET_PATH);
addrlen = offsetof(struct sockaddr_un, sun_path) + strlen(saddr.sun_path+1) + 1;
socketfd = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (socketfd == -1) {
DIE (("Couldn't open socket"));
}
if (bind(socketfd, (struct sockaddr *) &saddr, addrlen) < 0) {
fprintf (stderr, "Error binding to %s: %s\n", HALD_HELPER_SOCKET_PATH, strerror(errno));
exit (1);
}
/* enable receiving of the sender credentials */
setsockopt(socketfd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
channel = g_io_channel_unix_new (socketfd);
g_io_add_watch (channel, G_IO_IN, hald_helper_data, NULL);
g_io_channel_unref (channel);
/* Get mount points for /proc and /sys */
if (!hal_util_get_fs_mnt_path ("sysfs", hal_sysfs_path, sizeof (hal_sysfs_path))) {
HAL_ERROR (("Could not get sysfs mount point"));
goto error;
}
HAL_INFO (("sysfs mount point is '%s'", hal_sysfs_path));
if (!hal_util_get_fs_mnt_path ("proc", hal_proc_path, sizeof (hal_proc_path))) {
HAL_ERROR (("Could not get proc mount point"));
goto error;
}
HAL_INFO (("proc mount point is '%s'", hal_proc_path));
/* Load various hardware id databases */
ids_init ();
error:
;
}
void
osspec_shutdown (void)
{
}
void
osspec_probe (void)
{
HalDevice *root;
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");
hal_device_store_add (hald_get_tdl (), root);
di_search_and_merge (root);
hal_device_store_remove (hald_get_tdl (), root);
hal_device_store_add (hald_get_gdl (), root);
/* will enqueue hotplug events for entire system */
coldplug_synthesize_events ();
/* start processing events */
hotplug_event_process_queue ();
/*osspec_probe_done ();*/
}
DBusHandlerResult
osspec_filter_function (DBusConnection *connection, DBusMessage *message, void *user_data)
{
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
--- NEW FILE: physdev.c ---
/***************************************************************************
* CVSID: $Id: physdev.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* physdev.c : Handling of physical kernel devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/utsname.h>
#include <unistd.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
#include "coldplug.h"
#include "hotplug_helper.h"
#include "hotplug.h"
#include "physdev.h"
#include "ids.h"
static gboolean
pci_add (const gchar *sysfs_path, HalDevice *parent, void *end_token)
{
HalDevice *d;
gint device_class;
gchar udi[256];
d = hal_device_new ();
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_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);
}
}
/* Add to temporary device store */
hal_device_store_add (hald_get_tdl (), d);
/* Merge properties from .fdi files */
di_search_and_merge (d);
/* TODO: Run callouts */
/* Compute UDI */
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);
/* 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);
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 gboolean
usb_add (const gchar *sysfs_path, HalDevice *parent, void *end_token)
{
HalDevice *d;
const gchar *bus_id;
gchar udi[256];
d = hal_device_new ();
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_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 */
/* Add to temporary device store */
hal_device_store_add (hald_get_tdl (), d);
/* Merge properties from .fdi files */
di_search_and_merge (d);
/* TODO: Run callouts */
/* Compute UDI */
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);
/* Move from temporary to global device store */
hal_device_store_remove (hald_get_tdl (), d);
hal_device_store_add (hald_get_gdl (), d);
} else {
hal_device_property_set_string (d, "info.bus", "usb");
/* take all usb_device.* properties from parent and make them usb.* on this object */
hal_device_merge_with_rewrite (d, parent, "usb.", "usb_device.");
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"));
/* Add to temporary device store */
hal_device_store_add (hald_get_tdl (), d);
/* Merge properties from .fdi files */
di_search_and_merge (d);
/* TODO: Run callouts */
/* Compute UDI */
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);
/* 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);
return TRUE;
}
static gboolean
physdev_remove (HalDevice *d, void *end_token)
{
if (!hal_device_store_remove (hald_get_gdl (), d)) {
HAL_WARNING (("Error removing device"));
}
hotplug_event_end (end_token);
return TRUE;
}
typedef struct
{
const gchar *subsystem;
gboolean (*add) (const gchar *sysfs_path, HalDevice *parent, void *end_token);
gboolean (*remove) (HalDevice *d, void *end_token);
} PhysDevHandler;
static PhysDevHandler physdev_handler_pci = {
"pci",
pci_add,
physdev_remove
};
static PhysDevHandler physdev_handler_usb = {
"usb",
usb_add,
physdev_remove
};
static PhysDevHandler *phys_handlers[] = {
&physdev_handler_pci,
&physdev_handler_usb,
NULL
};
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));
for (i = 0; phys_handlers [i] != NULL; i++) {
PhysDevHandler *handler;
handler = phys_handlers[i];
if (strcmp (handler->subsystem, subsystem) == 0) {
if (handler->add (sysfs_path, parent, end_token)) {
/* let the handler end the event */
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_device",
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) {
if (handler->remove (d, end_token)) {
/* let the handler end the event */
goto out2;
}
}
}
out:
/* didn't find anything - thus, ignore this hotplug event */
hotplug_event_end (end_token);
out2:
;
}
--- NEW FILE: physdev.h ---
/***************************************************************************
* CVSID: $Id: physdev.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* physdev.h : Handling of physical kernel devices
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef PHYSDEV_H
#define PHYSDEV_H
#include <glib.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);
#endif /* PHYSDEV_H */
--- NEW FILE: util.c ---
/***************************************************************************
* CVSID: $Id: util.c,v 1.1 2005/01/18 19:48:13 david Exp $
*
* util.c - Various utilities
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <mntent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <signal.h>
#include <sys/wait.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include "../osspec.h"
#include "../logger.h"
#include "../hald.h"
#include "../callout.h"
#include "../device_info.h"
#include "../hald_conf.h"
#include "util.h"
gboolean
hal_util_remove_trailing_slash (gchar *path)
{
gchar *c = NULL;
if (path == NULL) {
return FALSE;
}
c = strrchr (path, '/');
if (c == NULL) {
HAL_WARNING (("Invalid path %s", path));
return 1;
}
if (*(c+1) == '\0')
*c = '\0';
return TRUE;
}
gboolean
hal_util_get_fs_mnt_path (const gchar *fs_type, gchar *mnt_path, gsize len)
{
FILE *mnt;
struct mntent *mntent;
gboolean rc;
gsize dirlen;
rc = FALSE;
dirlen = 0;
if (fs_type == NULL || mnt_path == NULL || len == 0) {
HAL_ERROR (("Arguments not sane"));
return -1;
}
if ((mnt = setmntent ("/proc/mounts", "r")) == NULL) {
HAL_ERROR (("Error getting mount information"));
return -1;
}
while (rc == FALSE && dirlen == 0 && (mntent = getmntent(mnt)) != NULL) {
if (strcmp (mntent->mnt_type, fs_type) == 0) {
dirlen = strlen (mntent->mnt_dir);
if (dirlen <= (len - 1)) {
g_strlcpy (mnt_path, mntent->mnt_dir, len);
rc = TRUE;
} else {
HAL_ERROR (("Error - mount path too long"));
rc = FALSE;
}
}
}
endmntent (mnt);
if (dirlen == 0 && rc == TRUE) {
HAL_ERROR (("Filesystem %s not found", fs_type));
rc = FALSE;
}
if ((!hal_util_remove_trailing_slash (mnt_path)))
rc = FALSE;
return rc;
}
/** Given a path, /foo/bar/bat/foobar, return the last element, e.g.
* foobar.
*
* @param path Path
* @return Pointer into given string
*/
const gchar *
hal_util_get_last_element (const gchar *s)
{
int len;
const gchar *p;
len = strlen (s);
for (p = s + len - 1; p > s; --p) {
if ((*p) == '/')
return p + 1;
}
return s;
}
/** Given a sysfs-path for a device, this functions finds the sysfs
* path representing the parent of the given device by truncation.
*
* @param path Sysfs-path of device to find parent for
* @return Path for parent or NULL if there is no parent;
* must be freed by caller
*/
gchar *
hal_util_get_parent_sysfs_path (const gchar *path)
{
guint i;
guint len;
gchar *parent_path;
/* Find parent device by truncating our own path */
parent_path = g_strndup (path, HAL_PATH_MAX);
len = strlen (parent_path);
for (i = len - 1; parent_path[i] != '/'; --i) {
parent_path[i] = '\0';
}
parent_path[i] = '\0';
return parent_path;
}
/* 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[] = {
"/sbin/udevinfo",
"/usr/bin/udevinfo",
"/usr/sbin/udevinfo",
"/usr/local/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;
}
/** Get the name of the special device file given the sysfs path.
*
* @param sysfs_path Path to class device in sysfs
* @param dev_file Where the special device file name should be stored
* @param dev_file_length Size of dev_file character array
* @return TRUE only if the device file could be found
*/
gboolean
hal_util_get_device_file (const gchar *sysfs_path, gchar *dev_file, gsize dev_file_length)
{
int i;
gsize sysfs_path_len;
gsize sysfs_mount_path_len;
gchar sysfs_path_trunc[HAL_PATH_MAX];
gchar sysfs_path_dev_trunc[HAL_PATH_MAX + 4];
char *udev_argv[7] = { NULL,
"-r", "-q", "name", "-p",
sysfs_path_trunc, NULL };
char *udev_stdout;
char *udev_stderr;
int udev_exitcode;
struct stat statbuf;
/* check for dev file in sysfs path */
sysfs_path_len = strlen (sysfs_path);
strncpy (sysfs_path_dev_trunc, sysfs_path, HAL_PATH_MAX);
strncat (sysfs_path_dev_trunc + sysfs_path_len, "/dev", 4);
if (g_stat (sysfs_path_dev_trunc, &statbuf) != 0)
return FALSE;
/* get path to udevinfo */
udev_argv[0] = (char *) hal_util_get_udevinfo_path ();
if (udev_argv[0] == NULL)
return FALSE;
/* compute truncated sysfs path as udevinfo doesn't want the sysfs_mount_path (e.g. /sys) prefix */
sysfs_mount_path_len = strlen (hal_sysfs_path);
if (strlen (sysfs_path) > sysfs_mount_path_len) {
strncpy (sysfs_path_trunc, sysfs_path + sysfs_mount_path_len, HAL_PATH_MAX - sysfs_mount_path_len);
}
/* Now invoke udevinfo */
if (udev_argv[0] == NULL || g_spawn_sync ("/",
udev_argv,
NULL,
0,
NULL,
NULL,
&udev_stdout,
&udev_stderr,
&udev_exitcode,
NULL) != TRUE) {
HAL_ERROR (("Couldn't invoke %s", udev_argv[0]));
return FALSE;
}
if (udev_exitcode != 0) {
HAL_ERROR (("%s returned %d for %s", udev_argv[0], udev_exitcode, sysfs_path_trunc));
return FALSE;
}
/* sanitize string returned by udev */
for (i = 0; udev_stdout[i] != 0; i++) {
if (udev_stdout[i] == '\r' || udev_stdout[i] == '\n') {
udev_stdout[i] = 0;
break;
}
}
/*HAL_INFO (("got device file %s for %s", udev_stdout, sysfs_path));*/
strncpy (dev_file, udev_stdout, dev_file_length);
return TRUE;
}
/** 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;
}
gchar *
hal_util_get_normalized_path (const gchar *path1, const gchar *path2)
{
int i;
int len1;
int len2;
const gchar *p1;
const gchar *p2;
gchar buf[HAL_PATH_MAX];
len1 = strlen (path1);
len2 = strlen (path1);
p1 = path1 + len1;
i = 0;
p2 = path2;
while (p2 < path2 + len2 && strncmp (p2, "../", 3) == 0) {
p2 += 3;
while (p1 >= path1 && *(--p1)!='/')
;
}
strncpy (buf, path1, (p1-path1));
buf[p1-path1] = '\0';
return g_strdup_printf ("%s/%s", buf, p2);
}
gboolean
hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base)
{
FILE *f;
char buf[64];
gchar path[HAL_PATH_MAX];
gboolean ret;
f = NULL;
ret = FALSE;
g_snprintf (path, sizeof (path), "%s/%s", directory, file);
f = fopen (path, "rb");
if (f == NULL) {
HAL_ERROR (("Cannot open '%s'", path));
goto out;
}
if (fgets (buf, sizeof (buf), f) == NULL) {
HAL_ERROR (("Cannot read from '%s'", path));
goto out;
}
/* TODO: handle error condition */
*result = strtol (buf, NULL, base);
ret = TRUE;
out:
if (f != NULL)
fclose (f);
return ret;
}
gboolean
hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base)
{
gint value;
gboolean ret;
ret = FALSE;
if (hal_util_get_int_from_file (directory, file, &value, base))
ret = hal_device_property_set_int (d, key, value);
return ret;
}
gboolean
hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result)
{
FILE *f;
char buf[64];
gchar path[HAL_PATH_MAX];
gboolean ret;
gint digit;
gint left, right;
gboolean passed_white_space;
gint num_prec;
gsize len;
gchar c;
guint i;
f = NULL;
ret = FALSE;
g_snprintf (path, sizeof (path), "%s/%s", directory, file);
f = fopen (path, "rb");
if (f == NULL) {
HAL_ERROR (("Cannot open '%s'", path));
goto out;
}
if (fgets (buf, sizeof (buf), f) == NULL) {
HAL_ERROR (("Cannot read from '%s'", path));
goto out;
}
left = 0;
len = strlen (buf);
passed_white_space = FALSE;
for (i = 0; i < len && buf[i] != '.'; i++) {
if (g_ascii_isspace (buf[i])) {
if (passed_white_space)
break;
else
continue;
}
passed_white_space = TRUE;
left *= 16;
c = buf[i];
digit = (int) (c - '0');
left += digit;
}
i++;
right = 0;
num_prec = 0;
for (; i < len; i++) {
if (g_ascii_isspace (buf[i]))
break;
if (num_prec == 2) /* Only care about two digits
* of precision */
break;
right *= 16;
c = buf[i];
digit = (int) (c - '0');
right += digit;
num_prec++;
}
for (; num_prec < 2; num_prec++)
right *= 16;
*result = left * 256 + (right & 255);
ret = TRUE;
out:
if (f != NULL)
fclose (f);
return ret;
}
gboolean
hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
{
gint value;
gboolean ret;
ret = FALSE;
if (hal_util_get_bcd2_from_file (directory, file, &value))
ret = hal_device_property_set_int (d, key, value);
return ret;
}
gboolean
hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file)
{
FILE *f;
gchar buf[256];
gchar path[HAL_PATH_MAX];
gboolean ret;
gsize len;
f = NULL;
ret = FALSE;
g_snprintf (path, sizeof (path), "%s/%s", directory, file);
f = fopen (path, "rb");
if (f == NULL) {
HAL_ERROR (("Cannot open '%s'", path));
goto out;
}
if (fgets (buf, sizeof (buf), f) == NULL) {
HAL_ERROR (("Cannot read from '%s'", path));
goto out;
}
len = strlen (buf);
if (len>0)
buf[len-1] = '\0';
ret = hal_device_property_set_string (d, key, buf);
out:
if (f != NULL)
fclose (f);
return ret;
}
void
hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...)
{
guint i;
va_list args;
gchar buf[256];
va_start (args, format);
g_vsnprintf (buf, sizeof (buf), format, args);
va_end (args);
g_strlcpy (dst, buf, dstsize);
if (hal_device_store_find (store, dst) == NULL)
goto out;
for (i = 0; ; i++) {
g_snprintf (dst, dstsize, "%s-%d", buf, i);
if (hal_device_store_find (store, dst) == NULL)
goto out;
}
out:
;
}
typedef struct
{
GPid pid;
guint timeout_watch_id;
guint child_watch_id;
HelperTerminatedCB cb;
gpointer data1;
gpointer data2;
HalDevice *d;
} HelperData;
static gboolean
helper_child_timeout (gpointer data)
{
HelperData *ed = (HelperData *) data;
HAL_INFO (("child timeout for pid %d", ed->pid));
/* kill kenny! kill it!! */
kill (ed->pid, SIGTERM);
/* TODO: yikes; what about removing the zombie? */
g_source_remove (ed->child_watch_id);
g_spawn_close_pid (ed->pid);
ed->cb (ed->d, TRUE, -1, ed->data1, ed->data2);
g_free (ed);
return FALSE;
}
static void
helper_child_exited (GPid pid, gint status, gpointer data)
{
HelperData *ed = (HelperData *) data;
HAL_INFO (("child exited for pid %d", ed->pid));
g_source_remove (ed->timeout_watch_id);
g_spawn_close_pid (ed->pid);
ed->cb (ed->d, FALSE, WEXITSTATUS (status), ed->data1, ed->data2);
g_free (ed);
}
static gboolean
helper_add_property_to_env (HalDevice *device, HalProperty *property, gpointer user_data)
{
char *prop_upper, *value;
char *c;
gchar ***ienvp = (gchar ***) user_data;
gchar **envp;
envp = *ienvp;
*ienvp = *ienvp + 1;
prop_upper = g_ascii_strup (hal_property_get_key (property), -1);
/* periods aren't valid in the environment, so replace them with
* underscores. */
for (c = prop_upper; *c; c++) {
if (*c == '.')
*c = '_';
}
value = hal_property_to_string (property);
*envp = g_strdup_printf ("HAL_PROP_%s=%s", prop_upper, value);
g_free (value);
g_free (prop_upper);
return TRUE;
}
gboolean
helper_invoke (const gchar *path, HalDevice *d, gpointer data1, gpointer data2, HelperTerminatedCB cb, guint timeout)
{
gboolean ret;
HelperData *ed;
gchar *argv[] = {(gchar *) path, NULL};
gchar **envp;
gchar **ienvp;
GError *err;
guint num_env_vars;
guint i;
guint num_properties;
ed = g_new0 (HelperData, 1);
ed->data1 = data1;
ed->data2 = data2;
ed->d = d;
ed->cb = cb;
num_properties = hal_device_num_properties (d);
num_env_vars = num_properties + 2;
if (hald_is_verbose)
num_env_vars++;
if (hald_is_initialising)
num_env_vars++;
if (hald_is_shutting_down)
num_env_vars++;
envp = g_new (char *, num_env_vars);
ienvp = envp;
hal_device_property_foreach (d, helper_add_property_to_env, &ienvp);
i = num_properties;
envp[i++] = g_strdup_printf ("UDI=%s", hal_device_get_udi (d));
if (hald_is_verbose)
envp[i++] = g_strdup ("HALD_VERBOSE=1");
if (hald_is_initialising)
envp[i++] = g_strdup ("HALD_STARTUP=1");
if (hald_is_shutting_down)
envp[i++] = g_strdup ("HALD_SHUTDOWN=1");
envp[i++] = NULL;
err = NULL;
if (!g_spawn_async (NULL,
argv,
envp,
G_SPAWN_DO_NOT_REAP_CHILD|G_SPAWN_SEARCH_PATH,
NULL,
NULL,
&ed->pid,
&err)) {
HAL_ERROR (("Couldn't spawn '%s' err=%s!", path, err->message));
g_error_free (err);
ret = FALSE;
g_free (ed);
} else {
ed->child_watch_id = g_child_watch_add (ed->pid, helper_child_exited, (gpointer) ed);
ed->timeout_watch_id = g_timeout_add (timeout, helper_child_timeout, (gpointer) ed);
ret = TRUE;
}
g_strfreev (envp);
return ret;
}
--- NEW FILE: util.h ---
/***************************************************************************
* CVSID: $Id: util.h,v 1.1 2005/01/18 19:48:13 david Exp $
*
* util.h - Various utilities
*
* Copyright (C) 2004 David Zeuthen, <david at fubar.dk>
*
* Licensed under the Academic Free License version 2.0
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
**************************************************************************/
#ifndef UTIL_H
#define UTIL_H
#include "../device.h"
gboolean hal_util_remove_trailing_slash (gchar *path);
gboolean hal_util_get_fs_mnt_path (const gchar *fs_type, gchar *mnt_path, gsize len);
const gchar *hal_util_get_last_element (const gchar *s);
gchar *hal_util_get_parent_sysfs_path (const gchar *path);
gboolean hal_util_get_device_file (const gchar *sysfs_path, gchar *dev_file, gsize dev_file_length);
HalDevice *hal_util_find_closest_ancestor (const gchar *sysfs_path);
gchar *hal_util_get_normalized_path (const gchar *path1, const gchar *path2);
gboolean hal_util_get_int_from_file (const gchar *directory, const gchar *file, gint *result, gint base);
gboolean hal_util_set_int_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file, gint base);
gboolean hal_util_set_string_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file);
gboolean hal_util_get_bcd2_from_file (const gchar *directory, const gchar *file, gint *result);
gboolean hal_util_set_bcd2_from_file (HalDevice *d, const gchar *key, const gchar *directory, const gchar *file);
void hal_util_compute_udi (HalDeviceStore *store, gchar *dst, gsize dstsize, const gchar *format, ...);
typedef void (*HelperTerminatedCB)(HalDevice *d, gboolean timed_out, gint return_code, gpointer data1, gpointer data2);
gboolean helper_invoke (const gchar *path, HalDevice *d, gpointer data1, gpointer data2, HelperTerminatedCB cb, guint timeout);
#define HAL_HELPER_TIMEOUT 10000
#define HAL_PATH_MAX 256
extern char hal_sysfs_path [HAL_PATH_MAX];
extern char hal_proc_path [HAL_PATH_MAX];
#endif /* UTIL_H */
- Previous message: hal/hald/linux Makefile.am, 1.1, NONE block_class_device.c, 1.88,
NONE bus_device.c, 1.20, NONE bus_device.h, 1.9,
NONE class_device.c, 1.30, NONE class_device.h, 1.12,
NONE common.c, 1.16, NONE common.h, 1.11, NONE hald_helper.h,
1.6, NONE ide_bus_device.c, 1.8, NONE ide_host_bus_device.c,
1.9, NONE ieee1394_class_device.c, 1.4,
NONE ieee1394_host_class_device.c, 1.5,
NONE ieee1394_node_class_device.c, 1.6,
NONE input_class_device.c, 1.11, NONE linux_dvd_rw_utils.c,
1.8, NONE linux_dvd_rw_utils.h, 1.6, NONE macio_bus_device.c,
1.4, NONE multimedia_class_device.c, 1.2,
NONE net_class_device.c, 1.22, NONE osspec.c, 1.54,
NONE pci_bus_device.c, 1.9, NONE pcmcia_cs.h, 1.1,
NONE pcmcia_socket_class_device.c, 1.4, NONE pcmcia_utils.c,
1.2, NONE pcmcia_utils.h, 1.1, NONE platform_bus_device.c, 1.7,
NONE printer_class_device.c, 1.10, NONE scsi_bus_device.c, 1.1,
NONE scsi_generic_class_device.c, 1.4,
NONE scsi_host_class_device.c, 1.10,
NONE serial_class_device.c, 1.1, NONE usb_bus_device.c, 1.15,
NONE usb_serial_bus_device.c, 1.1, NONE usbif_bus_device.c,
1.9, NONE
- Next message: hal/hald callout.c, 1.15, 1.16 device_info.c, 1.17, 1.18 hald_dbus.c,
1.17, 1.18
- Messages sorted by:
[ date ]
[ thread ]
[ subject ]
[ author ]
More information about the hal-commit
mailing list