1*2912Sartem /***************************************************************************
2*2912Sartem  *
3*2912Sartem  * hotplug.c : HAL-internal hotplug events
4*2912Sartem  *
5*2912Sartem  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
6*2912Sartem  * Use is subject to license terms.
7*2912Sartem  *
8*2912Sartem  * Licensed under the Academic Free License version 2.1
9*2912Sartem  *
10*2912Sartem  **************************************************************************/
11*2912Sartem 
12*2912Sartem #pragma	ident	"%Z%%M%	%I%	%E% SMI"
13*2912Sartem 
14*2912Sartem #ifdef HAVE_CONFIG_H
15*2912Sartem #  include <config.h>
16*2912Sartem #endif
17*2912Sartem 
18*2912Sartem #include <stdio.h>
19*2912Sartem #include <string.h>
20*2912Sartem #include <errno.h>
21*2912Sartem #include <sys/types.h>
22*2912Sartem #include <sys/stat.h>
23*2912Sartem #include <sys/un.h>
24*2912Sartem #include <sys/utsname.h>
25*2912Sartem #include <unistd.h>
26*2912Sartem 
27*2912Sartem #include <glib.h>
28*2912Sartem #include <dbus/dbus.h>
29*2912Sartem #include <dbus/dbus-glib.h>
30*2912Sartem 
31*2912Sartem #include "../osspec.h"
32*2912Sartem #include "../logger.h"
33*2912Sartem #include "../hald.h"
34*2912Sartem #include "../device_info.h"
35*2912Sartem 
36*2912Sartem #include "osspec_solaris.h"
37*2912Sartem #include "hotplug.h"
38*2912Sartem #include "devinfo.h"
39*2912Sartem 
40*2912Sartem /** Queue of ordered hotplug events */
41*2912Sartem GQueue *hotplug_event_queue;
42*2912Sartem 
43*2912Sartem /** List of HotplugEvent objects we are currently processing */
44*2912Sartem GSList *hotplug_events_in_progress = NULL;
45*2912Sartem 
46*2912Sartem static void hotplug_event_begin (HotplugEvent *hotplug_event);
47*2912Sartem 
48*2912Sartem void
49*2912Sartem hotplug_event_end (void *end_token)
50*2912Sartem {
51*2912Sartem 	HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
52*2912Sartem 
53*2912Sartem 	hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
54*2912Sartem 	g_free (hotplug_event);
55*2912Sartem 	hotplug_event_process_queue ();
56*2912Sartem }
57*2912Sartem 
58*2912Sartem static void
59*2912Sartem hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d)
60*2912Sartem {
61*2912Sartem 	HalDevice *parent;
62*2912Sartem 	const gchar *parent_udi;
63*2912Sartem 	void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *);
64*2912Sartem 
65*2912Sartem 	if (d != NULL) {
66*2912Sartem 		/* XXX */
67*2912Sartem 		HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path));
68*2912Sartem 		hotplug_event_end ((void *) hotplug_event);
69*2912Sartem 		return;
70*2912Sartem 	}
71*2912Sartem 
72*2912Sartem 	/* find parent */
73*2912Sartem 	parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent");
74*2912Sartem 	if (parent_udi == NULL || strlen(parent_udi) == 0) {
75*2912Sartem 		parent = NULL;
76*2912Sartem 	} else {
77*2912Sartem 		parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi);
78*2912Sartem 	}
79*2912Sartem 	/* only root node is allowed to be orphan */
80*2912Sartem 	if (parent == NULL) {
81*2912Sartem 		if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) {
82*2912Sartem 			HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>"));
83*2912Sartem 			hotplug_event_end ((void *) hotplug_event);
84*2912Sartem 			return;
85*2912Sartem 		}
86*2912Sartem 	}
87*2912Sartem 
88*2912Sartem 	/* children of ignored parent should be ignored */
89*2912Sartem 	if (hal_device_property_get_bool (parent, "info.ignore")) {
90*2912Sartem 		HAL_INFO (("parent ignored %s", parent_udi));
91*2912Sartem 			hotplug_event_end ((void *) hotplug_event);
92*2912Sartem 			return;
93*2912Sartem 	}
94*2912Sartem 
95*2912Sartem 	/* custom or generic add function */
96*2912Sartem 	begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add;
97*2912Sartem 	if (begin_add_func == NULL) {
98*2912Sartem 		begin_add_func = hotplug_event_begin_add_devinfo;
99*2912Sartem 	}
100*2912Sartem 	begin_add_func (hotplug_event->d,
101*2912Sartem 			 parent,
102*2912Sartem 			 hotplug_event->un.devfs.handler,
103*2912Sartem 			 (void *) hotplug_event);
104*2912Sartem }
105*2912Sartem 
106*2912Sartem static void
107*2912Sartem hotplug_event_begin_devfs_remove (HotplugEvent *hotplug_event, HalDevice *d)
108*2912Sartem {
109*2912Sartem 	if (d == NULL) {
110*2912Sartem 		HAL_ERROR (("devpath %s not present in store, ignore event", hotplug_event->un.devfs.devfs_path));
111*2912Sartem 		hotplug_event_end ((void *) hotplug_event);
112*2912Sartem 		return;
113*2912Sartem 	}
114*2912Sartem 	HAL_INFO (("hotplug_event_begin_devfs_remove %s", d->udi));
115*2912Sartem 
116*2912Sartem 	hotplug_event_begin_remove_devinfo(d,
117*2912Sartem 			 hotplug_event->un.devfs.devfs_path,
118*2912Sartem 			 (void *) hotplug_event);
119*2912Sartem }
120*2912Sartem 
121*2912Sartem static void
122*2912Sartem hotplug_event_begin_devfs (HotplugEvent *hotplug_event)
123*2912Sartem {
124*2912Sartem 	HalDevice *d;
125*2912Sartem 
126*2912Sartem 	HAL_INFO (("hotplug_event_begin_devfs: %s", hotplug_event->un.devfs.devfs_path));
127*2912Sartem 	d = hal_device_store_match_key_value_string (hald_get_gdl (),
128*2912Sartem 						"solaris.devfs_path",
129*2912Sartem 						hotplug_event->un.devfs.devfs_path);
130*2912Sartem 
131*2912Sartem 	if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
132*2912Sartem 		hotplug_event_begin_devfs_add (hotplug_event, d);
133*2912Sartem 	} else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
134*2912Sartem 		hotplug_event_begin_devfs_remove (hotplug_event, d);
135*2912Sartem 	} else {
136*2912Sartem 		hotplug_event_end ((void *) hotplug_event);
137*2912Sartem 	}
138*2912Sartem }
139*2912Sartem 
140*2912Sartem static void
141*2912Sartem hotplug_event_begin (HotplugEvent *hotplug_event)
142*2912Sartem {
143*2912Sartem 	switch (hotplug_event->type) {
144*2912Sartem 
145*2912Sartem 	case HOTPLUG_EVENT_DEVFS:
146*2912Sartem 		hotplug_event_begin_devfs (hotplug_event);
147*2912Sartem 		break;
148*2912Sartem 
149*2912Sartem 	default:
150*2912Sartem 		HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
151*2912Sartem 		hotplug_event_end ((void *) hotplug_event);
152*2912Sartem 		break;
153*2912Sartem 	}
154*2912Sartem }
155*2912Sartem 
156*2912Sartem void
157*2912Sartem hotplug_event_enqueue (HotplugEvent *hotplug_event, int front)
158*2912Sartem {
159*2912Sartem 	if (hotplug_event_queue == NULL)
160*2912Sartem 		hotplug_event_queue = g_queue_new ();
161*2912Sartem 
162*2912Sartem 	if (front) {
163*2912Sartem 		g_queue_push_head (hotplug_event_queue, hotplug_event);
164*2912Sartem 	} else {
165*2912Sartem 		g_queue_push_tail (hotplug_event_queue, hotplug_event);
166*2912Sartem 	}
167*2912Sartem }
168*2912Sartem 
169*2912Sartem void
170*2912Sartem hotplug_event_process_queue (void)
171*2912Sartem {
172*2912Sartem 	HotplugEvent *hotplug_event;
173*2912Sartem 
174*2912Sartem 	if (hotplug_events_in_progress == NULL &&
175*2912Sartem 	    (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
176*2912Sartem 		hotplug_queue_now_empty ();
177*2912Sartem 		goto out;
178*2912Sartem 	}
179*2912Sartem 
180*2912Sartem 	/* do not process events if some other event is in progress */
181*2912Sartem 	if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
182*2912Sartem 		goto out;
183*2912Sartem 
184*2912Sartem 	hotplug_event = g_queue_pop_head (hotplug_event_queue);
185*2912Sartem 	if (hotplug_event == NULL)
186*2912Sartem 		goto out;
187*2912Sartem 
188*2912Sartem 	hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
189*2912Sartem 	hotplug_event_begin (hotplug_event);
190*2912Sartem 
191*2912Sartem out:
192*2912Sartem 	;
193*2912Sartem }
194