hal/hald/linux2 Makefile.am, 1.4, 1.5 acpi.c, 1.3, 1.4 classdev.c, 1.6, 1.7 hotplug.c, 1.6, 1.7 hotplug.h, 1.3, 1.4 osspec.c, 1.6, 1.7 pmu.c, NONE, 1.1 pmu.h, NONE, 1.1 util.c, 1.5, 1.6 util.h, 1.4, 1.5

David Zeuthen david at freedesktop.org
Wed Feb 2 20:13:53 PST 2005


Update of /cvs/hal/hal/hald/linux2
In directory gabe:/tmp/cvs-serv30229/hald/linux2

Modified Files:
	Makefile.am acpi.c classdev.c hotplug.c hotplug.h osspec.c 
	util.c util.h 
Added Files:
	pmu.c pmu.h 
Log Message:
2005-02-02  David Zeuthen  <davidz at redhat.com>

	* hald/linux2/pmu.[ch]: New files

	* hald/linux2/util.h: Add prototypes for
	hal_util_grep_string_elem_from_file and
	hal_util_grep_int_elem_from_file.

	* hald/linux2/util.c (hal_util_grep_file): Allow file to be NULL
	or empty and handle it correctly
	(hal_util_grep_string_elem_from_file): New function
	(hal_util_grep_int_elem_from_file): New function
	(hal_util_set_string_elem_from_file): Simplify by using
	hal_util_grep_string_elem_from_file
	(hal_util_set_int_elem_from_file): Simplify by using
	hal_util_grep_string_elem_from_file

	* hald/linux2/osspec.c (osspec_probe): Refine algorithm for selecting
	power management system since PMU based systems may simultaneously
	support APM as well.

	* hald/linux2/hotplug.h: Add PMU hotplug event

	* hald/linux2/hotplug.c (hotplug_event_begin_pmu): New function
	(hotplug_event_begin): Handle PMU
	(hotplug_rescan_device): Handle PMU
	(hotplug_reprobe_generate_remove_events): Handle PMU
	(hotplug_reprobe_generate_add_events): Handle PMU

	* hald/linux2/classdev.c (hotplug_event_begin_add_classdev): Only
	set linux.device_file if there really is a device file

	* hald/linux2/acpi.c (battery_refresh): Use maximum instead of
	maximum_specified

	* hald/linux2/Makefile.am: Add pmu.[ch]



Index: Makefile.am
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/Makefile.am,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- Makefile.am	3 Feb 2005 00:21:50 -0000	1.4
+++ Makefile.am	3 Feb 2005 04:13:46 -0000	1.5
@@ -22,6 +22,7 @@
 	util.h			util.c				\
 	acpi.h			acpi.c				\
 	apm.h			apm.c				\
+	pmu.h			pmu.c				\
 	ids.h			ids.c				\
 	pcmcia_utils.h		pcmcia_utils.c
 

Index: acpi.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/acpi.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- acpi.c	3 Feb 2005 00:21:51 -0000	1.3
+++ acpi.c	3 Feb 2005 04:13:46 -0000	1.4
@@ -77,7 +77,7 @@
 		hal_device_property_remove (d, "battery.vendor");
 		hal_device_property_remove (d, "battery.charge_level.unit");
 		hal_device_property_remove (d, "battery.charge_level.current");
-		hal_device_property_remove (d, "battery.charge_level.maximum_specified");
+		hal_device_property_remove (d, "battery.charge_level.maximum");
 		device_property_atomic_update_end ();		
 	} else {
 		device_property_atomic_update_begin ();
@@ -94,12 +94,12 @@
 		hal_util_set_string_elem_from_file (d, "battery.technology", path, "info", "battery type", 0);
 		hal_util_set_string_elem_from_file (d, "battery.vendor", path, "info", "OEM info", 0);
 		hal_util_set_string_elem_from_file (d, "battery.charge_level.unit", path, "info", "design capacity", 1);
-
+		
 		hal_util_set_int_elem_from_file (d, "battery.charge_level.current", path, 
-						 "state", "remaining capacity", 0);
+						 "state", "remaining capacity", 0, 10);
 
-		hal_util_set_int_elem_from_file (d, "battery.charge_level.maximum_specified", path, 
-						 "info", "design capacity", 0);
+		hal_util_set_int_elem_from_file (d, "battery.charge_level.maximum", path, 
+						 "info", "design capacity", 0, 10);
 		device_property_atomic_update_end ();
 	}
 

Index: classdev.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/classdev.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- classdev.c	2 Feb 2005 20:44:25 -0000	1.6
+++ classdev.c	3 Feb 2005 04:13:46 -0000	1.7
@@ -513,7 +513,9 @@
 
 			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_SYSFS_CLASS);
 			hal_device_property_set_string (d, "linux.subsystem", subsystem);
-			hal_device_property_set_string (d, "linux.device_file", device_file);
+			
+			if (device_file != NULL && strlen (device_file) > 0)
+				hal_device_property_set_string (d, "linux.device_file", device_file);
 
 			/* Add to temporary device store */
 			hal_device_store_add (hald_get_tdl (), d);
@@ -610,12 +612,10 @@
 {
 	const char *subsystem;
 	const char *sysfs_path;
-	const char *device_file;
 	HotplugEvent *hotplug_event;
 
 	subsystem = hal_device_property_get_string (d, "linux.subsystem");
 	sysfs_path = hal_device_property_get_string (d, "linux.sysfs_path");
-	device_file = hal_device_property_get_string (d, "linux.device_file");
 
 	hotplug_event = g_new0 (HotplugEvent, 1);
 	hotplug_event->is_add = FALSE;

Index: hotplug.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- hotplug.c	3 Feb 2005 00:21:51 -0000	1.6
+++ hotplug.c	3 Feb 2005 04:13:46 -0000	1.7
@@ -56,6 +56,7 @@
 #include "blockdev.h"
 #include "acpi.h"
 #include "apm.h"
+#include "pmu.h"
 
 /** Queue of ordered hotplug events */
 GQueue *hotplug_event_queue;
@@ -287,6 +288,21 @@
 }
 
 static void
+hotplug_event_begin_pmu (HotplugEvent *hotplug_event)
+{
+	if (hotplug_event->is_add) {
+		hotplug_event_begin_add_pmu (hotplug_event->pmu.pmu_path, 
+					     hotplug_event->pmu.pmu_type,
+					     NULL,
+					     (void *) hotplug_event);
+	} else {
+		hotplug_event_begin_remove_pmu (hotplug_event->pmu.pmu_path, 
+						hotplug_event->pmu.pmu_type,
+						(void *) hotplug_event);
+	}
+}
+
+static void
 hotplug_event_begin (HotplugEvent *hotplug_event)
 {
 	switch (hotplug_event->type) {
@@ -307,6 +323,10 @@
 		hotplug_event_begin_apm (hotplug_event);
 		break;
 
+	case HOTPLUG_EVENT_PMU:
+		hotplug_event_begin_pmu (hotplug_event);
+		break;
+
 	default:
 		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
 		hotplug_event_end ((void *) hotplug_event);
@@ -374,7 +394,11 @@
 		break;
 
 	case HOTPLUG_EVENT_APM:
-		ret = acpi_rescan_device (d);
+		ret = apm_rescan_device (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		ret = pmu_rescan_device (d);
 		break;
 
 	default:
@@ -422,7 +446,11 @@
 		break;
 
 	case HOTPLUG_EVENT_APM:
-		e = acpi_generate_remove_hotplug_event (d);
+		e = apm_generate_remove_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		e = pmu_generate_remove_hotplug_event (d);
 		break;
 
 	default:
@@ -463,7 +491,11 @@
 		break;
 
 	case HOTPLUG_EVENT_APM:
-		e = acpi_generate_add_hotplug_event (d);
+		e = apm_generate_add_hotplug_event (d);
+		break;
+
+	case HOTPLUG_EVENT_PMU:
+		e = pmu_generate_add_hotplug_event (d);
 		break;
 
 	default:

Index: hotplug.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/hotplug.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- hotplug.h	3 Feb 2005 00:21:51 -0000	1.3
+++ hotplug.h	3 Feb 2005 04:13:46 -0000	1.4
@@ -37,7 +37,8 @@
 	HOTPLUG_EVENT_SYSFS_CLASS = 2,
 	HOTPLUG_EVENT_SYSFS_BLOCK = 3,
 	HOTPLUG_EVENT_ACPI        = 4,
-	HOTPLUG_EVENT_APM         = 5
+	HOTPLUG_EVENT_APM         = 5,
+	HOTPLUG_EVENT_PMU         = 6
 } HotplugEventType;
 
 /** Data structure representing a hotplug event; also used for
@@ -69,9 +70,14 @@
 		} acpi;
 
 		struct {
-			int  apm_type;                          /**< Type of ACPI object; see apm.c */
+			int  apm_type;                          /**< Type of APM object; see apm.c */
 			char apm_path[HAL_PATH_MAX];            /**< Path into procfs, e.g. /proc/apm */
 		} apm;
+
+		struct {
+			int  pmu_type;                          /**< Type of PMU object; see pmu.c */
+			char pmu_path[HAL_PATH_MAX];            /**< Path into procfs, e.g. /proc/pmu/battery_0 */
+		} pmu;
 	};
 
 } HotplugEvent;

Index: osspec.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/osspec.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- osspec.c	3 Feb 2005 00:21:51 -0000	1.6
+++ osspec.c	3 Feb 2005 04:13:46 -0000	1.7
@@ -81,6 +81,7 @@
 
 #include "acpi.h"
 #include "apm.h"
+#include "pmu.h"
 
 char hal_sysfs_path [HAL_PATH_MAX];
 char hal_proc_path [HAL_PATH_MAX];
@@ -471,10 +472,15 @@
 	/* will enqueue hotplug events for entire system */
 	HAL_INFO (("Synthesizing sysfs events..."));
 	coldplug_synthesize_events ();
-	HAL_INFO (("Synthesizing ACPI events..."));
-	if (!acpi_synthesize_hotplug_events ()) {
-		HAL_INFO (("No ACPI capabilities found; checking for APM"));
-		apm_synthesize_hotplug_events ();
+	HAL_INFO (("Synthesizing powermgmt events..."));
+	if (acpi_synthesize_hotplug_events ()) {
+		HAL_INFO (("ACPI capabilities found"));
+	} else if (pmu_synthesize_hotplug_events ()) {
+		HAL_INFO (("PMU capabilities found"));		
+	} else if (apm_synthesize_hotplug_events ()) {
+		HAL_INFO (("APM capabilities found"));		
+	} else {
+		HAL_INFO (("No powermgmt capabilities"));		
 	}
 	HAL_INFO (("Done synthesizing events"));
 

--- NEW FILE: pmu.c ---
/***************************************************************************
 * CVSID: $Id: pmu.c,v 1.1 2005/02/03 04:13:46 david Exp $
 *
 * Copyright (C) 2005 Sjoerd Simons <sjoerd at luon.net>
 * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <string.h>

#include "../callout.h"
#include "../device_info.h"
#include "../logger.h"
#include "../hald_dbus.h"
#include "util.h"

#include "pmu.h"
#include "hotplug.h"

enum {
	PMU_TYPE_BATTERY,
	PMU_TYPE_AC_ADAPTER
};


typedef struct PMUDevHandler_s
{
	int pmu_type;
	HalDevice *(*add) (const gchar *pmu_path, HalDevice *parent, struct PMUDevHandler_s *handler);
	gboolean (*compute_udi) (HalDevice *d, struct PMUDevHandler_s *handler);
	gboolean (*remove) (HalDevice *d, struct PMUDevHandler_s *handler);
	gboolean (*refresh) (HalDevice *d, struct PMUDevHandler_s *handler);
} PMUDevHandler;


/* defines from the kernel PMU driver (include/linux/pmu.h) */
#define PMU_BATT_PRESENT  0x00000001
#define PMU_BATT_CHARGING 0x00000002
#define PMU_BATT_TYPE_MASK  0x000000f0
#define PMU_BATT_TYPE_SMART 0x00000010	  /* Smart battery */
#define PMU_BATT_TYPE_HOOPER  0x00000020  /* 3400/3500 */
#define PMU_BATT_TYPE_COMET 0x00000030	  /* 2400 */

static gboolean
battery_refresh (HalDevice *d, PMUDevHandler *handler)
{
	const char *path;
	int flags;

	path = hal_device_property_get_string (d, "linux.pmu_path");
	if (path == NULL)
		return FALSE;

	hal_device_property_set_string (d, "info.product", "Battery Bay");
	hal_device_property_set_string (d, "battery.type", "primary");
	hal_device_property_set_string (d, "info.category", "battery");
	hal_device_add_capability (d, "battery");

	flags = hal_util_grep_int_elem_from_file (path, "", "flags", 0, 16);

	hal_device_property_set_bool (d, "battery.present", flags & PMU_BATT_PRESENT);

	if (flags & PMU_BATT_PRESENT) {
		device_property_atomic_update_begin ();
		hal_device_property_set_bool (d, "battery.is_rechargeable", TRUE);

		/* we don't know the unit here :-/ */
		/*hal_device_property_set_string (d, "battery.charge_level.unit", "percent");*/

		hal_device_property_set_bool (d, "battery.rechargeable.is_charging", flags & PMU_BATT_CHARGING);
		/* we're discharging if, and only if, we are not plugged into the wall */
		{
			char buf[HAL_PATH_MAX];
			snprintf (buf, sizeof (buf), "%s/pmu/info", hal_proc_path);
			hal_util_set_bool_elem_from_file (d, "battery.rechargeable.is_discharging", buf, "", 
							  "AC Power", 0, "0");
		}

		hal_util_set_int_elem_from_file (d, "battery.charge_level.current", path, "", "charge", 0, 10);
		hal_util_set_int_elem_from_file (d, "battery.charge_level.maximum", path, "", "max_charge", 0, 10);

		device_property_atomic_update_end ();
	} else {
		device_property_atomic_update_begin ();
		hal_device_property_remove (d, "battery.is_rechargeable");
		hal_device_property_remove (d, "battery.rechargeable.is_charging");
		hal_device_property_remove (d, "battery.rechargeable.is_discharging");
		/*hal_device_property_remove (d, "battery.charge_level.unit");*/
		hal_device_property_remove (d, "battery.charge_level.current");
		hal_device_property_remove (d, "battery.charge_level.maximum");
		device_property_atomic_update_end ();		
	}

	return TRUE;
}

static gboolean
ac_adapter_refresh (HalDevice *d, PMUDevHandler *handler)
{
	const char *path;

	path = hal_device_property_get_string (d, "linux.pmu_path");
	if (path == NULL)
		return FALSE;

	hal_device_property_set_string (d, "info.product", "AC Adapter");
	hal_device_property_set_string (d, "info.category", "system.ac_adapter");
	hal_device_add_capability (d, "system.ac_adapter");

	hal_util_set_bool_elem_from_file (d, "system.ac_adapter.present", path, "", "AC Power", 0, "1");	

	return TRUE;
}

/** Scan the data structures exported by the kernel and add hotplug
 *  events for adding PMU objects.
 *
 *  @param                      TRUE if, and only if, PMU capabilities
 *                              were detected
 */
gboolean
pmu_synthesize_hotplug_events (void)
{
	gboolean ret;
	HalDevice *computer;
	gchar path[HAL_PATH_MAX];
	HotplugEvent *hotplug_event;
	GError *error;
	GDir *dir;

	ret = FALSE;

	if (!g_file_test ("/proc/pmu/info", G_FILE_TEST_EXISTS))
		goto out;

	ret = TRUE;

	if ((computer = hal_device_store_find (hald_get_gdl (), "/org/freedesktop/Hal/devices/computer")) == NULL) {
		HAL_ERROR (("No computer object?"));
		goto out;
	}

	/* Set appropriate properties on the computer object */
	hal_device_property_set_bool (computer, "power_management.is_enabled", TRUE);
	hal_device_property_set_string (computer, "power_management.type", "pmu");

	/* AC Adapter */
	snprintf (path, sizeof (path), "%s/pmu/info", hal_proc_path);
	hotplug_event = g_new0 (HotplugEvent, 1);
	hotplug_event->is_add = TRUE;
	hotplug_event->type = HOTPLUG_EVENT_PMU;
	g_strlcpy (hotplug_event->pmu.pmu_path, path, sizeof (hotplug_event->pmu.pmu_path));
	hotplug_event->pmu.pmu_type = PMU_TYPE_AC_ADAPTER;
	hotplug_event_enqueue (hotplug_event);

	error = NULL;
	snprintf (path, sizeof (path), "%s/pmu", hal_proc_path);
	dir = g_dir_open (path, 0, &error);
	if (dir != NULL) {
		const gchar *f;
			
		while ((f = g_dir_read_name (dir)) != NULL) {
			HotplugEvent *hotplug_event;
			gchar buf[HAL_PATH_MAX];
			int battery_num;

			snprintf (buf, sizeof (buf), "%s/pmu/%s", hal_proc_path, f);
			if (sscanf (f, "battery_%d", &battery_num) == 1) {
				HAL_INFO (("Processing %s", buf));
				
				hotplug_event = g_new0 (HotplugEvent, 1);
				hotplug_event->is_add = TRUE;
				hotplug_event->type = HOTPLUG_EVENT_PMU;
				g_strlcpy (hotplug_event->pmu.pmu_path, buf, sizeof (hotplug_event->pmu.pmu_path));
				hotplug_event->pmu.pmu_type = PMU_TYPE_BATTERY;
				
				hotplug_event_enqueue (hotplug_event);
			}
			
		}
	} else {
		HAL_ERROR (("Couldn't open %s: %s", path, error->message));
		g_error_free (error);
	}

	/* close directory */
	g_dir_close (dir);

out:
	return ret;
}

static HalDevice *
pmu_generic_add (const gchar *pmu_path, HalDevice *parent, PMUDevHandler *handler)
{
	HalDevice *d;
	d = hal_device_new ();
	hal_device_property_set_string (d, "linux.pmu_path", pmu_path);
	hal_device_property_set_int (d, "linux.pmu_type", handler->pmu_type);
	if (parent != NULL)
		hal_device_property_set_string (d, "info.parent", parent->udi);
	else
		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/computer");
	if (handler->refresh == NULL || !handler->refresh (d, handler)) {
		g_object_unref (d);
		d = NULL;
	}
	return d;
}

static gboolean
pmu_generic_compute_udi (HalDevice *d, PMUDevHandler *handler)
{
	gchar udi[256];
	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
			      "/org/freedesktop/Hal/devices/pmu_%s_%d",
			      hal_util_get_last_element (hal_device_property_get_string (d, "linux.pmu_path")),
			      hal_device_property_get_int (d, "linux.pmu_type"));
	hal_device_set_udi (d, udi);
	hal_device_property_set_string (d, "info.udi", udi);
	return TRUE;
}

static gboolean
pmu_generic_remove (HalDevice *d, PMUDevHandler *handler)
{
	if (!hal_device_store_remove (hald_get_gdl (), d)) {
		HAL_WARNING (("Error removing device"));
	}

	return TRUE;
}

static PMUDevHandler pmudev_handler_battery = { 
	.pmu_type    = PMU_TYPE_BATTERY,
	.add         = pmu_generic_add,
	.compute_udi = pmu_generic_compute_udi,
	.refresh     = battery_refresh,
	.remove      = pmu_generic_remove
};

static PMUDevHandler pmudev_handler_ac_adapter = { 
	.pmu_type    = PMU_TYPE_AC_ADAPTER,
	.add         = pmu_generic_add,
	.compute_udi = pmu_generic_compute_udi,
	.refresh     = ac_adapter_refresh,
	.remove      = pmu_generic_remove
};

static PMUDevHandler *pmu_handlers[] = {
	&pmudev_handler_battery,
	&pmudev_handler_ac_adapter,
	NULL
};

void
hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token)
{
	guint i;

	HAL_INFO (("pmu_add: pmu_path=%s pmu_type=%d, parent=0x%08x", pmu_path, pmu_type, parent));

	for (i = 0; pmu_handlers [i] != NULL; i++) {
		PMUDevHandler *handler;

		handler = pmu_handlers[i];
		if (handler->pmu_type == pmu_type) {
			HalDevice *d;

			d = handler->add (pmu_path, parent, handler);
			if (d == NULL) {
				/* didn't find anything - thus, ignore this hotplug event */
				hotplug_event_end (end_token);
				goto out;
			}

			hal_device_property_set_int (d, "linux.hotplug_type", HOTPLUG_EVENT_PMU);

			/* Add to temporary device store */
			hal_device_store_add (hald_get_tdl (), d);

			/* Merge properties from .fdi files */
			di_search_and_merge (d);

			/* TODO: Run callouts */
			
			/* Compute UDI */
			if (!handler->compute_udi (d, handler)) {
				hal_device_store_remove (hald_get_tdl (), d);
				hotplug_event_end (end_token);
				goto out;
			}

			/* Move from temporary to global device store */
			hal_device_store_remove (hald_get_tdl (), d);
			hal_device_store_add (hald_get_gdl (), d);
			
			hotplug_event_end (end_token);
			goto out;
		}
	}
	
	/* didn't find anything - thus, ignore this hotplug event */
	hotplug_event_end (end_token);
out:
	;
}

void
hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token)
{
	guint i;
	HalDevice *d;

	HAL_INFO (("pmu_rem: pmu_path=%s pmu_type=%d", pmu_path, pmu_type));

	d = hal_device_store_match_key_value_string (hald_get_gdl (), "linux.pmu_path", pmu_path);
	if (d == NULL) {
		HAL_WARNING (("Couldn't remove device with pmu path %s - not found", pmu_path));
		goto out;
	}

	for (i = 0; pmu_handlers [i] != NULL; i++) {
		PMUDevHandler *handler;

		handler = pmu_handlers[i];
		if (handler->pmu_type == pmu_type) {
			if (handler->remove (d, handler)) {
				hotplug_event_end (end_token);
				goto out2;
			}
		}
	}
out:
	/* didn't find anything - thus, ignore this hotplug event */
	hotplug_event_end (end_token);
out2:
	;
}

gboolean
pmu_rescan_device (HalDevice *d)
{
	guint i;
	gboolean ret;
	int pmu_type;

	ret = FALSE;

	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");

	for (i = 0; pmu_handlers [i] != NULL; i++) {
		PMUDevHandler *handler;

		handler = pmu_handlers[i];
		if (handler->pmu_type == pmu_type) {
			ret = handler->refresh (d, handler);
			goto out;
		}
	}

	HAL_WARNING (("Didn't find a rescan handler for udi %s", d->udi));

out:
	return ret;
}

HotplugEvent *
pmu_generate_add_hotplug_event (HalDevice *d)
{
	int pmu_type;
	const char *pmu_path;
	HotplugEvent *hotplug_event;

	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");

	hotplug_event = g_new0 (HotplugEvent, 1);
	hotplug_event->is_add = TRUE;
	hotplug_event->type = HOTPLUG_EVENT_PMU;
	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
	hotplug_event->pmu.pmu_type = pmu_type;
	return hotplug_event;
}

HotplugEvent *
pmu_generate_remove_hotplug_event (HalDevice *d)
{
	int pmu_type;
	const char *pmu_path;
	HotplugEvent *hotplug_event;

	pmu_path = hal_device_property_get_string (d, "linux.pmu_path");
	pmu_type = hal_device_property_get_int (d, "linux.pmu_type");

	hotplug_event = g_new0 (HotplugEvent, 1);
	hotplug_event->is_add = FALSE;
	hotplug_event->type = HOTPLUG_EVENT_PMU;
	g_strlcpy (hotplug_event->pmu.pmu_path, pmu_path, sizeof (hotplug_event->pmu.pmu_path));
	hotplug_event->pmu.pmu_type = pmu_type;
	return hotplug_event;
}

--- NEW FILE: pmu.h ---
/***************************************************************************
 * CVSID: $Id: pmu.h,v 1.1 2005/02/03 04:13:46 david Exp $
 *
 * Copyright (C) 2005 David Zeuthen, Red Hat Inc., <davidz at redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 **************************************************************************/

#ifndef PMU_H
#define PMU_H

#include "../hald.h"
#include "hotplug.h"

gboolean pmu_synthesize_hotplug_events (void);

void hotplug_event_begin_add_pmu (const gchar *pmu_path, int pmu_type, HalDevice *parent, void *end_token);

void hotplug_event_begin_remove_pmu (const gchar *pmu_path, int pmu_type, void *end_token);

gboolean pmu_rescan_device (HalDevice *d);

HotplugEvent *pmu_generate_add_hotplug_event (HalDevice *d);

HotplugEvent *pmu_generate_remove_hotplug_event (HalDevice *d);

#endif /* PMU_H */

Index: util.c
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/util.c,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -d -r1.5 -r1.6
--- util.c	3 Feb 2005 00:21:51 -0000	1.5
+++ util.c	3 Feb 2005 04:13:46 -0000	1.6
@@ -758,7 +758,10 @@
 
 	result = NULL;
 
-	snprintf (filename, sizeof (filename), "%s/%s", directory, file);
+	if (file != NULL && strlen (file) > 0)
+		snprintf (filename, sizeof (filename), "%s/%s", directory, file);
+	else
+		strncpy (filename, directory, sizeof (filename));
 	f = fopen (filename, "r");
 	if (f == NULL)
 		goto out;
@@ -792,6 +795,64 @@
 	return result;
 }
 
+gchar *
+hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file, 
+				     const gchar *linestart, guint elem)
+{
+	gchar *line;
+	gchar *res;
+	gchar buf[256];
+	gchar **tokens;
+	guint i, j;
+
+	res = NULL;
+	tokens = NULL;
+
+	if (((line = hal_util_grep_file (directory, file, linestart)) == NULL) || (strlen (line) == 0))
+		goto out;
+
+	tokens = g_strsplit_set (line, " \t:", 0);
+	for (i = 0, j = 0; tokens[i] != NULL; i++) {
+		if (strlen (tokens[i]) == 0)
+			continue;
+		if (j == elem) {
+			strncpy (buf, tokens[i], sizeof (buf));
+			res = buf;
+			goto out;
+		}
+		j++;
+	}
+	
+out:
+	if (tokens != NULL)
+		g_strfreev (tokens);
+
+	return res;
+}
+
+gint
+hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file, 
+				  const gchar *linestart, guint elem, guint base)
+{
+	gchar *endptr;
+	gchar *strvalue;
+	int value;
+
+	value = G_MAXINT;
+
+	if ((strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem)) == NULL)
+		goto out;
+
+	value = strtol (strvalue, &endptr, base);
+	if (endptr == strvalue) {
+		value = G_MAXINT;
+		goto out;
+	}
+
+out:
+	return value;
+}
+
 /** Get a string value from a formatted text file and assign it to
  *  a property on a device object.
  *
@@ -819,33 +880,16 @@
 				    const gchar *directory, const gchar *file, 
 				    const gchar *linestart, guint elem)
 {
-	gchar *line;
 	gboolean res;
-	gchar **tokens;
-	guint i, j;
+	gchar *value;
 
 	res = FALSE;
-	tokens = NULL;
 
-	if (((line = hal_util_grep_file (directory, file, linestart)) == NULL) || (strlen (line) == 0))
+	if ((value = hal_util_grep_string_elem_from_file (directory, file, linestart, elem)) == NULL)
 		goto out;
 
-	tokens = g_strsplit_set (line, " \t:", 0);
-	for (i = 0, j = 0; tokens[i] != NULL; i++) {
-		if (strlen (tokens[i]) == 0)
-			continue;
-		if (j == elem) {
-			hal_device_property_set_string (d, key, tokens[i]);
-			res = TRUE;
-			goto out;
-		}
-		j++;
-	}
-	
+	res = hal_device_property_set_string (d, key, value);
 out:
-	if (tokens != NULL)
-		g_strfreev (tokens);
-
 	return res;
 }
 
@@ -874,42 +918,27 @@
 gboolean
 hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key, 
 				 const gchar *directory, const gchar *file, 
-				 const gchar *linestart, guint elem)
+				 const gchar *linestart, guint elem, guint base)
 {
-	gchar *line;
+	gchar *endptr;
 	gboolean res;
-	gchar **tokens;
+	gchar *strvalue;
 	int value;
-	char *endptr;
-	guint i, j;
 
 	res = FALSE;
-	tokens = NULL;
 
-	if (((line = hal_util_grep_file (directory, file, linestart)) == NULL) || (strlen (line) == 0))
+	if ((strvalue = hal_util_grep_string_elem_from_file (directory, file, linestart, elem)) == NULL)
 		goto out;
 
-	tokens = g_strsplit_set (line, " \t:", 0);
-
-	for (i = 0, j = 0; tokens[i] != NULL; i++) {
-		if (strlen (tokens[i]) == 0)
-			continue;
-		if (j == elem) {
-			value = strtol (tokens[i], &endptr, 0);
-			if (endptr == tokens[i])
-				goto out;
-			hal_device_property_set_int (d, key, value);
-			res = TRUE;
-			goto out;
-		}
-		j++;
-	}	
-
+	value = strtol (strvalue, &endptr, base);
+	if (endptr == strvalue)
+		goto out;
+	
+	res = hal_device_property_set_int (d, key, value);
+	
 out:
-	if (tokens != NULL)
-		g_strfreev (tokens);
-
 	return res;
+
 }
 
 /** Get a value from a formatted text file, test it against a given

Index: util.h
===================================================================
RCS file: /cvs/hal/hal/hald/linux2/util.h,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- util.h	1 Feb 2005 05:50:40 -0000	1.4
+++ util.h	3 Feb 2005 04:13:46 -0000	1.5
@@ -64,13 +64,19 @@
 
 gchar *hal_util_grep_file (const gchar *directory, const gchar *file, const gchar *linestart);
 
+gint hal_util_grep_int_elem_from_file (const gchar *directory, const gchar *file, 
+				       const gchar *linestart, guint elem, guint base);
+
+gchar *hal_util_grep_string_elem_from_file (const gchar *directory, const gchar *file, 
+					    const gchar *linestart, guint elem);
+
 gboolean hal_util_set_string_elem_from_file (HalDevice *d, const gchar *key, 
 					     const gchar *directory, const gchar *file, 
 					     const gchar *linestart, guint elem);
 
 gboolean hal_util_set_int_elem_from_file (HalDevice *d, const gchar *key, 
 					  const gchar *directory, const gchar *file, 
-					  const gchar *linestart, guint elem);
+					  const gchar *linestart, guint elem, guint base);
 
 gboolean hal_util_set_bool_elem_from_file (HalDevice *d, const gchar *key, 
 					   const gchar *directory, const gchar *file, 




More information about the hal-commit mailing list