xref: /illumos-gate/usr/src/cmd/hal/hald/solaris/devinfo.c (revision 506aa7c6)
118c2aff7Sartem /***************************************************************************
218c2aff7Sartem  *
318c2aff7Sartem  * devinfo.c : main file for libdevinfo-based device enumeration
418c2aff7Sartem  *
5*506aa7c6SGarrett D'Amore  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
63f7d54a6SGarrett D'Amore  * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
718c2aff7Sartem  *
818c2aff7Sartem  * Licensed under the Academic Free License version 2.1
918c2aff7Sartem  *
1018c2aff7Sartem  **************************************************************************/
1118c2aff7Sartem 
1200687e57Sartem #ifdef HAVE_CONFIG_H
1300687e57Sartem #  include <config.h>
1400687e57Sartem #endif
1500687e57Sartem 
1618c2aff7Sartem #include <stdio.h>
1718c2aff7Sartem #include <string.h>
1818c2aff7Sartem #include <libdevinfo.h>
1918c2aff7Sartem 
2018c2aff7Sartem #include "../osspec.h"
2118c2aff7Sartem #include "../logger.h"
2218c2aff7Sartem #include "../hald.h"
2318c2aff7Sartem #include "../hald_dbus.h"
2418c2aff7Sartem #include "../device_info.h"
2518c2aff7Sartem #include "../util.h"
2618c2aff7Sartem #include "../hald_runner.h"
2718c2aff7Sartem #include "osspec_solaris.h"
2818c2aff7Sartem #include "hotplug.h"
2918c2aff7Sartem #include "devinfo.h"
3018c2aff7Sartem #include "devinfo_pci.h"
3118c2aff7Sartem #include "devinfo_storage.h"
3218c2aff7Sartem #include "devinfo_ieee1394.h"
3318c2aff7Sartem #include "devinfo_usb.h"
3418c2aff7Sartem #include "devinfo_misc.h"
357b840e52Sphitran #include "devinfo_acpi.h"
36a9da3307Snp #include "devinfo_cpu.h"
3718c2aff7Sartem 
3818c2aff7Sartem void devinfo_add_subtree(HalDevice *parent, di_node_t node, gboolean is_root);
3918c2aff7Sartem HalDevice *devinfo_add_node(HalDevice *parent, di_node_t node);
4018c2aff7Sartem 
4118c2aff7Sartem void
4218c2aff7Sartem devinfo_add(HalDevice *parent, gchar *path)
4318c2aff7Sartem {
4418c2aff7Sartem 	di_node_t	root;
4518c2aff7Sartem 
4618c2aff7Sartem 	if (strcmp (path, "/") == 0) {
4718c2aff7Sartem 		if ((root = di_init(path, DINFOCACHE)) == DI_NODE_NIL) {
4818c2aff7Sartem 			HAL_INFO (("di_init() failed %d", errno));
4918c2aff7Sartem 			return;
5018c2aff7Sartem 		}
5118c2aff7Sartem 	} else {
5218c2aff7Sartem 		if ((root = di_init(path, DINFOCPYALL)) == DI_NODE_NIL) {
5318c2aff7Sartem 			HAL_INFO (("di_init() failed %d", errno));
5418c2aff7Sartem 			return;
5518c2aff7Sartem 		}
5618c2aff7Sartem 	}
5718c2aff7Sartem 
5818c2aff7Sartem 	devinfo_add_subtree(parent, root, TRUE);
5918c2aff7Sartem 
6018c2aff7Sartem 	di_fini (root);
6118c2aff7Sartem }
6218c2aff7Sartem 
6318c2aff7Sartem void
6418c2aff7Sartem devinfo_add_subtree(HalDevice *parent, di_node_t node, gboolean is_root)
6518c2aff7Sartem {
6618c2aff7Sartem 	HalDevice *d;
6718c2aff7Sartem 	di_node_t root_node, child_node;
6818c2aff7Sartem 
6918c2aff7Sartem 	HAL_INFO (("add_subtree: %s", di_node_name (node)));
7018c2aff7Sartem 
7118c2aff7Sartem 	root_node = node;
7218c2aff7Sartem 	do {
7318c2aff7Sartem 		d = devinfo_add_node (parent, node);
7418c2aff7Sartem 
7518c2aff7Sartem 		if ((d != NULL) &&
7618c2aff7Sartem 		    (child_node = di_child_node (node)) != DI_NODE_NIL) {
7718c2aff7Sartem 			devinfo_add_subtree (d, child_node, FALSE);
7818c2aff7Sartem 		}
7918c2aff7Sartem 
8018c2aff7Sartem 		node = di_sibling_node (node);
8118c2aff7Sartem 	} while ((node != DI_NODE_NIL) &&
8218c2aff7Sartem 		(!is_root || di_parent_node (node) == root_node));
8318c2aff7Sartem }
8418c2aff7Sartem 
8518c2aff7Sartem void
8618c2aff7Sartem devinfo_set_default_properties (HalDevice *d, HalDevice *parent, di_node_t node, char *devfs_path)
8718c2aff7Sartem {
8818c2aff7Sartem 	char	*driver_name, *s;
8918c2aff7Sartem 	const char *s1;
9018c2aff7Sartem 	char	udi[HAL_PATH_MAX];
9118c2aff7Sartem 
9218c2aff7Sartem 	if (parent != NULL) {
9300687e57Sartem 		hal_device_property_set_string (d, "info.parent", hal_device_get_udi (parent));
9418c2aff7Sartem 	} else {
9518c2aff7Sartem 		hal_device_property_set_string (d, "info.parent", "/org/freedesktop/Hal/devices/local");
9618c2aff7Sartem 	}
9718c2aff7Sartem 
9818c2aff7Sartem 	hal_util_compute_udi (hald_get_gdl (), udi, sizeof (udi),
9918c2aff7Sartem 				"/org/freedesktop/Hal/devices%s_%d",
10018c2aff7Sartem 				devfs_path,
10118c2aff7Sartem 				di_instance (node));
10218c2aff7Sartem 	hal_device_set_udi (d, udi);
10318c2aff7Sartem 	hal_device_property_set_string (d, "info.udi", udi);
10418c2aff7Sartem 
10518c2aff7Sartem 	if (di_prop_lookup_strings (DDI_DEV_T_ANY, node, "model", &s) > 0) {
10618c2aff7Sartem 		hal_device_property_set_string (d, "info.product", s);
10718c2aff7Sartem 	} else {
10818c2aff7Sartem 		hal_device_property_set_string (d, "info.product", di_node_name (node));
10918c2aff7Sartem 	}
11018c2aff7Sartem 
11118c2aff7Sartem 	hal_device_property_set_string (d, "solaris.devfs_path", devfs_path);
11218c2aff7Sartem 
11318c2aff7Sartem 	if ((driver_name = di_driver_name (node)) != NULL) {
11418c2aff7Sartem 		hal_device_property_set_string (d, "info.solaris.driver",
11518c2aff7Sartem 						driver_name);
11618c2aff7Sartem 	}
11718c2aff7Sartem 
11818c2aff7Sartem 
11918c2aff7Sartem 	/* inherit parent's claim attributes */
12018c2aff7Sartem 	if (hal_device_property_get_bool (parent, "info.claimed")) {
12118c2aff7Sartem 		s1 = hal_device_property_get_string (parent, "info.claimed.service");
12218c2aff7Sartem 		if (s1 != NULL) {
12318c2aff7Sartem 			hal_device_property_set_bool (d, "info.claimed", TRUE);
12418c2aff7Sartem 			hal_device_property_set_string (d, "info.claimed.service", s1);
12518c2aff7Sartem 		}
12618c2aff7Sartem 	}
12718c2aff7Sartem }
12818c2aff7Sartem 
12918c2aff7Sartem /* device handlers, ordered specific to generic */
13018c2aff7Sartem static DevinfoDevHandler *devinfo_handlers[] = {
13118c2aff7Sartem 	&devinfo_computer_handler,
13218c2aff7Sartem 	&devinfo_cpu_handler,
13318c2aff7Sartem 	&devinfo_ide_handler,
13418c2aff7Sartem 	&devinfo_scsi_handler,
1353f7d54a6SGarrett D'Amore 	&devinfo_blkdev_handler,
13618c2aff7Sartem 	&devinfo_floppy_handler,
13718c2aff7Sartem 	&devinfo_usb_handler,
13818c2aff7Sartem 	&devinfo_ieee1394_handler,
13918c2aff7Sartem 	&devinfo_lofi_handler,
1407b840e52Sphitran 	&devinfo_acpi_handler,
141d2ec54f7Sphitran 	&devinfo_power_button_handler,
142d2ec54f7Sphitran 	&devinfo_keyboard_handler,
143b453864fSLin Guo - Sun Microsystems 	&devinfo_mouse_handler,
14417c1f1d2SLin Guo - Sun Microsystems 	&devinfo_pci_handler,
14518c2aff7Sartem 	&devinfo_default_handler,
14618c2aff7Sartem 	NULL
14718c2aff7Sartem };
14818c2aff7Sartem 
14918c2aff7Sartem HalDevice *
15018c2aff7Sartem devinfo_add_node(HalDevice *parent, di_node_t node)
15118c2aff7Sartem {
15218c2aff7Sartem 	HalDevice *d = NULL;
15318c2aff7Sartem 	char	*devfs_path;
15418c2aff7Sartem 	char	*device_type = NULL;
15518c2aff7Sartem 	DevinfoDevHandler *handler;
15618c2aff7Sartem 	int	i;
15718c2aff7Sartem 
15818c2aff7Sartem 	devfs_path = di_devfs_path (node);
15918c2aff7Sartem 
16018c2aff7Sartem         (void) di_prop_lookup_strings (DDI_DEV_T_ANY, node, "device_type",
16118c2aff7Sartem 	    &device_type);
16218c2aff7Sartem 
16318c2aff7Sartem 	for (i = 0; (d == NULL) && (devinfo_handlers[i] != NULL); i++) {
16418c2aff7Sartem 		handler = devinfo_handlers[i];
16518c2aff7Sartem 		d = handler->add (parent, node, devfs_path, device_type);
16618c2aff7Sartem 	}
16718c2aff7Sartem 
16818c2aff7Sartem 	di_devfs_path_free(devfs_path);
16918c2aff7Sartem 
17000687e57Sartem 	HAL_INFO (("add_node: %s", d ? hal_device_get_udi (d) : "none"));
17118c2aff7Sartem 	return (d);
17218c2aff7Sartem }
17318c2aff7Sartem 
17418c2aff7Sartem void
17518c2aff7Sartem devinfo_hotplug_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler, int action, int front)
17618c2aff7Sartem {
17718c2aff7Sartem 	HotplugEvent *hotplug_event;
17818c2aff7Sartem 
17918c2aff7Sartem 	hotplug_event = g_new0 (HotplugEvent, 1);
18018c2aff7Sartem 	hotplug_event->action = action;
18118c2aff7Sartem 	hotplug_event->type = HOTPLUG_EVENT_DEVFS;
18218c2aff7Sartem 	hotplug_event->d = d;
18318c2aff7Sartem 	strlcpy (hotplug_event->un.devfs.devfs_path, devfs_path,
18418c2aff7Sartem 		sizeof (hotplug_event->un.devfs.devfs_path));
18518c2aff7Sartem 	hotplug_event->un.devfs.handler = handler;
18618c2aff7Sartem 
18718c2aff7Sartem 	hotplug_event_enqueue (hotplug_event, front);
18818c2aff7Sartem }
18918c2aff7Sartem 
19018c2aff7Sartem void
19118c2aff7Sartem devinfo_add_enqueue(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler)
19218c2aff7Sartem {
19318c2aff7Sartem 	devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 0);
19418c2aff7Sartem }
19518c2aff7Sartem 
19618c2aff7Sartem void
19718c2aff7Sartem devinfo_add_enqueue_at_front(HalDevice *d, gchar *devfs_path, DevinfoDevHandler *handler)
19818c2aff7Sartem {
19918c2aff7Sartem 	devinfo_hotplug_enqueue (d, devfs_path, handler, HOTPLUG_ACTION_ADD, 1);
20018c2aff7Sartem }
20118c2aff7Sartem 
20218c2aff7Sartem void
20318c2aff7Sartem devinfo_remove_enqueue(gchar *devfs_path, DevinfoDevHandler *handler)
20418c2aff7Sartem {
20518c2aff7Sartem 	devinfo_hotplug_enqueue (NULL, devfs_path, handler, HOTPLUG_ACTION_REMOVE, 0);
20618c2aff7Sartem }
20718c2aff7Sartem 
20818c2aff7Sartem void
20918c2aff7Sartem devinfo_callouts_add_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
21018c2aff7Sartem {
21118c2aff7Sartem         void *end_token = (void *) userdata1;
21218c2aff7Sartem 
21318c2aff7Sartem         /* Move from temporary to global device store */
21418c2aff7Sartem         hal_device_store_remove (hald_get_tdl (), d);
21518c2aff7Sartem         hal_device_store_add (hald_get_gdl (), d);
21618c2aff7Sartem 
21718c2aff7Sartem         hotplug_event_end (end_token);
21818c2aff7Sartem }
21918c2aff7Sartem 
22018c2aff7Sartem void
22118c2aff7Sartem devinfo_callouts_probing_done (HalDevice *d, guint32 exit_type, gint return_code, char **error, gpointer userdata1, gpointer userdata2)
22218c2aff7Sartem {
22318c2aff7Sartem         void *end_token = (void *) userdata1;
22418c2aff7Sartem 
22518c2aff7Sartem         /* Discard device if probing reports failure */
22618c2aff7Sartem         if (exit_type != HALD_RUN_SUCCESS || (return_code != 0)) {
22700687e57Sartem 		HAL_INFO (("Probing for %s failed %d", hal_device_get_udi (d), return_code));
22818c2aff7Sartem                 hal_device_store_remove (hald_get_tdl (), d);
22918c2aff7Sartem                 g_object_unref (d);
23018c2aff7Sartem                 hotplug_event_end (end_token);
23118c2aff7Sartem 		return;
23218c2aff7Sartem         }
23318c2aff7Sartem 
23418c2aff7Sartem         /* Merge properties from .fdi files */
23518c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_INFORMATION);
23618c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_POLICY);
23718c2aff7Sartem 
23818c2aff7Sartem 	hal_util_callout_device_add (d, devinfo_callouts_add_done, end_token, NULL);
23918c2aff7Sartem }
24018c2aff7Sartem 
24118c2aff7Sartem void
24218c2aff7Sartem devinfo_callouts_preprobing_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
24318c2aff7Sartem {
24418c2aff7Sartem         void *end_token = (void *) userdata1;
24518c2aff7Sartem 	DevinfoDevHandler *handler = (DevinfoDevHandler *) userdata2;
24618c2aff7Sartem 	void (*probing_done) (HalDevice *, guint32, gint, char **, gpointer, gpointer);
24718c2aff7Sartem 	const gchar *prober;
24818c2aff7Sartem 	int prober_timeout;
24918c2aff7Sartem 
25018c2aff7Sartem         if (hal_device_property_get_bool (d, "info.ignore")) {
25118c2aff7Sartem 		HAL_INFO (("Preprobing merged info.ignore==TRUE"));
25218c2aff7Sartem 
25318c2aff7Sartem                 /* Leave device with info.ignore==TRUE so we won't pick up children */
25418c2aff7Sartem 		hal_device_property_remove (d, "info.category");
25518c2aff7Sartem 		hal_device_property_remove (d, "info.capabilities");
25618c2aff7Sartem 
25718c2aff7Sartem 		hal_device_store_remove (hald_get_tdl (), d);
25818c2aff7Sartem 		hal_device_store_add (hald_get_gdl (), d);
25918c2aff7Sartem 
26018c2aff7Sartem 		hotplug_event_end (end_token);
26118c2aff7Sartem 		return;
26218c2aff7Sartem         }
26318c2aff7Sartem 
26418c2aff7Sartem         if (handler != NULL && handler->get_prober != NULL) {
26518c2aff7Sartem                 prober = handler->get_prober (d, &prober_timeout);
26618c2aff7Sartem         } else {
26718c2aff7Sartem                 prober = NULL;
26818c2aff7Sartem 	}
26918c2aff7Sartem 
27018c2aff7Sartem 	if (handler->probing_done != NULL) {
27118c2aff7Sartem 		probing_done = handler->probing_done;
27218c2aff7Sartem 	} else {
27318c2aff7Sartem 		probing_done = devinfo_callouts_probing_done;
27418c2aff7Sartem 	}
27518c2aff7Sartem 
27618c2aff7Sartem         if (prober != NULL) {
27718c2aff7Sartem                 /* probe the device */
27800687e57Sartem 		HAL_INFO(("Probing udi=%s", hal_device_get_udi (d)));
27918c2aff7Sartem                 hald_runner_run (d,
28018c2aff7Sartem 				prober, NULL,
28118c2aff7Sartem 				prober_timeout,
28218c2aff7Sartem 				probing_done,
28318c2aff7Sartem 				(gpointer) end_token, (gpointer) handler);
28418c2aff7Sartem 	} else {
28518c2aff7Sartem 		probing_done (d, 0, 0, NULL, userdata1, userdata2);
28618c2aff7Sartem 	}
28718c2aff7Sartem }
28818c2aff7Sartem 
28918c2aff7Sartem /* This is the beginning of hotplug even handling */
29018c2aff7Sartem void
29118c2aff7Sartem hotplug_event_begin_add_devinfo (HalDevice *d, HalDevice *parent, DevinfoDevHandler *handler, void *end_token)
29218c2aff7Sartem {
2938b80e8cbSLin Guo - Sun Microsystems 	HotplugEvent *hotplug_event = (HotplugEvent *)end_token;
2948b80e8cbSLin Guo - Sun Microsystems 
29500687e57Sartem 	HAL_INFO(("Preprobing udi=%s", hal_device_get_udi (d)));
29618c2aff7Sartem 
2978b80e8cbSLin Guo - Sun Microsystems 	if (parent == NULL && (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0)) {
2988b80e8cbSLin Guo - Sun Microsystems 		HAL_ERROR (("Parent is NULL, devfs_path=%s", hotplug_event->un.devfs.devfs_path));
2998b80e8cbSLin Guo - Sun Microsystems 
3008b80e8cbSLin Guo - Sun Microsystems 		goto skip;
3018b80e8cbSLin Guo - Sun Microsystems 	}
3028b80e8cbSLin Guo - Sun Microsystems 
3038b80e8cbSLin Guo - Sun Microsystems 
30418c2aff7Sartem 	if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
30518c2aff7Sartem 		HAL_INFO (("Ignoring device since parent has info.ignore==TRUE"));
30618c2aff7Sartem 
3078b80e8cbSLin Guo - Sun Microsystems 		goto skip;
30818c2aff7Sartem 	}
30918c2aff7Sartem 
310112cd14aSqz 	if (hal_device_store_find (hald_get_tdl (), hal_device_get_udi (d)) == NULL) {
311112cd14aSqz 
312112cd14aSqz 		/* add to TDL so preprobing callouts and prober can access it */
313112cd14aSqz 		hal_device_store_add (hald_get_tdl (), d);
314112cd14aSqz 	}
31518c2aff7Sartem 
31618c2aff7Sartem         /* Process preprobe fdi files */
31718c2aff7Sartem         di_search_and_merge (d, DEVICE_INFO_TYPE_PREPROBE);
31818c2aff7Sartem 
31918c2aff7Sartem         /* Run preprobe callouts */
32018c2aff7Sartem         hal_util_callout_device_preprobe (d, devinfo_callouts_preprobing_done, end_token, handler);
3218b80e8cbSLin Guo - Sun Microsystems 
3228b80e8cbSLin Guo - Sun Microsystems 	return;
3238b80e8cbSLin Guo - Sun Microsystems 
3248b80e8cbSLin Guo - Sun Microsystems skip:
3258b80e8cbSLin Guo - Sun Microsystems 	if (hal_device_store_find (hald_get_tdl (), hal_device_get_udi (d)))
3268b80e8cbSLin Guo - Sun Microsystems 		hal_device_store_remove (hald_get_tdl (), d);
3278b80e8cbSLin Guo - Sun Microsystems 
3288b80e8cbSLin Guo - Sun Microsystems 	g_object_unref (d);
3298b80e8cbSLin Guo - Sun Microsystems 	hotplug_event_end (end_token);
3308b80e8cbSLin Guo - Sun Microsystems 
3318b80e8cbSLin Guo - Sun Microsystems 	return;
33218c2aff7Sartem }
33318c2aff7Sartem 
33418c2aff7Sartem void
33518c2aff7Sartem devinfo_remove (gchar *devfs_path)
33618c2aff7Sartem {
33718c2aff7Sartem 	devinfo_remove_enqueue ((gchar *)devfs_path, NULL);
33818c2aff7Sartem }
33918c2aff7Sartem 
34018c2aff7Sartem /* generate hotplug event for each device in this branch */
34118c2aff7Sartem void
34218c2aff7Sartem devinfo_remove_branch (gchar *devfs_path, HalDevice *d)
34318c2aff7Sartem {
34418c2aff7Sartem 	GSList *i;
34518c2aff7Sartem 	GSList *children;
34618c2aff7Sartem 	HalDevice *child;
34718c2aff7Sartem 	char *child_devfs_path;
34818c2aff7Sartem 
34918c2aff7Sartem 	if (d == NULL) {
35018c2aff7Sartem 		d = hal_device_store_match_key_value_string (hald_get_gdl (),
35118c2aff7Sartem 			"solaris.devfs_path", devfs_path);
35218c2aff7Sartem 		if (d == NULL)
35318c2aff7Sartem 			return;
35418c2aff7Sartem 	}
35518c2aff7Sartem 
35600687e57Sartem 	HAL_INFO (("remove_branch: %s %s\n", devfs_path, hal_device_get_udi (d)));
35718c2aff7Sartem 
35818c2aff7Sartem 	/* first remove children */
35918c2aff7Sartem 	children = hal_device_store_match_multiple_key_value_string (hald_get_gdl(),
36000687e57Sartem 		"info.parent", hal_device_get_udi (d));
36118c2aff7Sartem         for (i = children; i != NULL; i = g_slist_next (i)) {
36218c2aff7Sartem                 child = HAL_DEVICE (i->data);
36300687e57Sartem 		HAL_INFO (("remove_branch: child %s\n", hal_device_get_udi (child)));
36418c2aff7Sartem 		devinfo_remove_branch ((gchar *)hal_device_property_get_string (child, "solaris.devfs_path"), child);
36518c2aff7Sartem 	}
36618c2aff7Sartem 	g_slist_free (children);
36718c2aff7Sartem 	HAL_INFO (("remove_branch: done with children"));
36818c2aff7Sartem 
36918c2aff7Sartem 	/* then remove self */
37018c2aff7Sartem 	HAL_INFO (("remove_branch: queueing %s", devfs_path));
37118c2aff7Sartem 	devinfo_remove_enqueue (devfs_path, NULL);
37218c2aff7Sartem }
37318c2aff7Sartem 
37418c2aff7Sartem void
37518c2aff7Sartem devinfo_callouts_remove_done (HalDevice *d, gpointer userdata1, gpointer userdata2)
37618c2aff7Sartem {
37718c2aff7Sartem         void *end_token = (void *) userdata1;
37818c2aff7Sartem 
37900687e57Sartem         HAL_INFO (("Remove callouts completed udi=%s", hal_device_get_udi (d)));
38018c2aff7Sartem 
38118c2aff7Sartem         if (!hal_device_store_remove (hald_get_gdl (), d)) {
38218c2aff7Sartem                 HAL_WARNING (("Error removing device"));
38318c2aff7Sartem         }
38418c2aff7Sartem         g_object_unref (d);
38518c2aff7Sartem 
38618c2aff7Sartem         hotplug_event_end (end_token);
38718c2aff7Sartem }
38818c2aff7Sartem 
38918c2aff7Sartem void
39018c2aff7Sartem hotplug_event_begin_remove_devinfo (HalDevice *d, gchar *devfs_path, void *end_token)
39118c2aff7Sartem {
39218c2aff7Sartem 	if (hal_device_has_capability (d, "volume")) {
39318c2aff7Sartem 		devinfo_volume_hotplug_begin_remove (d, devfs_path, end_token);
39418c2aff7Sartem 	} else {
39518c2aff7Sartem 		hal_util_callout_device_remove (d, devinfo_callouts_remove_done, end_token, NULL);
39618c2aff7Sartem 	}
39718c2aff7Sartem }
39818c2aff7Sartem 
39918c2aff7Sartem gboolean
40018c2aff7Sartem devinfo_device_rescan (HalDevice *d)
40118c2aff7Sartem {
40218c2aff7Sartem 	if (hal_device_has_capability (d, "block")) {
40318c2aff7Sartem 		return (devinfo_storage_device_rescan (d));
404076d97abSPhi Tran 	} else if (hal_device_has_capability (d, "button")) {
405076d97abSPhi Tran 		return (devinfo_lid_rescan (d));
4067b840e52Sphitran         } else {
40718c2aff7Sartem 		return (FALSE);
40818c2aff7Sartem 	}
40918c2aff7Sartem }
41042a7bdedSjacobs 
41142a7bdedSjacobs static int
41242a7bdedSjacobs walk_devlinks(di_devlink_t devlink, void *arg)
41342a7bdedSjacobs {
41442a7bdedSjacobs         char    **path= (char **)arg;
41542a7bdedSjacobs 
41642a7bdedSjacobs         *path = strdup(di_devlink_path(devlink));
41742a7bdedSjacobs 
41842a7bdedSjacobs         return (DI_WALK_TERMINATE);
41942a7bdedSjacobs }
42042a7bdedSjacobs 
42142a7bdedSjacobs char *
42242a7bdedSjacobs get_devlink(di_devlink_handle_t devlink_hdl, char *re, char *path)
42342a7bdedSjacobs {
42442a7bdedSjacobs         char    *devlink_path = NULL;
42542a7bdedSjacobs 
42642a7bdedSjacobs         (void) di_devlink_walk(devlink_hdl, re, path,
42742a7bdedSjacobs             DI_PRIMARY_LINK, &devlink_path, walk_devlinks);
42842a7bdedSjacobs 
42942a7bdedSjacobs         return (devlink_path);
43042a7bdedSjacobs }
431