12912Sartem /***************************************************************************
22912Sartem *
32912Sartem * hotplug.c : HAL-internal hotplug events
42912Sartem *
5*8100SLin.Guo@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
62912Sartem * Use is subject to license terms.
72912Sartem *
82912Sartem * Licensed under the Academic Free License version 2.1
92912Sartem *
102912Sartem **************************************************************************/
112912Sartem
122912Sartem
132912Sartem #ifdef HAVE_CONFIG_H
142912Sartem # include <config.h>
152912Sartem #endif
162912Sartem
172912Sartem #include <stdio.h>
182912Sartem #include <string.h>
192912Sartem #include <errno.h>
202912Sartem #include <sys/types.h>
212912Sartem #include <sys/stat.h>
222912Sartem #include <sys/un.h>
232912Sartem #include <sys/utsname.h>
242912Sartem #include <unistd.h>
252912Sartem
262912Sartem #include <glib.h>
272912Sartem #include <dbus/dbus.h>
282912Sartem #include <dbus/dbus-glib.h>
292912Sartem
302912Sartem #include "../osspec.h"
312912Sartem #include "../logger.h"
322912Sartem #include "../hald.h"
332912Sartem #include "../device_info.h"
342912Sartem
352912Sartem #include "osspec_solaris.h"
362912Sartem #include "hotplug.h"
372912Sartem #include "devinfo.h"
382912Sartem
392912Sartem /** Queue of ordered hotplug events */
402912Sartem GQueue *hotplug_event_queue;
412912Sartem
422912Sartem /** List of HotplugEvent objects we are currently processing */
432912Sartem GSList *hotplug_events_in_progress = NULL;
442912Sartem
452912Sartem static void hotplug_event_begin (HotplugEvent *hotplug_event);
462912Sartem
472912Sartem void
hotplug_event_end(void * end_token)482912Sartem hotplug_event_end (void *end_token)
492912Sartem {
502912Sartem HotplugEvent *hotplug_event = (HotplugEvent *) end_token;
512912Sartem
522912Sartem hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event);
532912Sartem g_free (hotplug_event);
542912Sartem hotplug_event_process_queue ();
552912Sartem }
562912Sartem
572912Sartem static void
hotplug_event_begin_devfs_add(HotplugEvent * hotplug_event,HalDevice * d)582912Sartem hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d)
592912Sartem {
602912Sartem HalDevice *parent;
612912Sartem const gchar *parent_udi;
622912Sartem void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *);
632912Sartem
642912Sartem if (d != NULL) {
652912Sartem /* XXX */
662912Sartem HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path));
67*8100SLin.Guo@Sun.COM
68*8100SLin.Guo@Sun.COM goto out;
692912Sartem }
702912Sartem
712912Sartem /* find parent */
722912Sartem parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent");
732912Sartem if (parent_udi == NULL || strlen(parent_udi) == 0) {
742912Sartem parent = NULL;
752912Sartem } else {
762912Sartem parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi);
772912Sartem }
782912Sartem /* only root node is allowed to be orphan */
792912Sartem if (parent == NULL) {
802912Sartem if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) {
812912Sartem HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>"));
82*8100SLin.Guo@Sun.COM
83*8100SLin.Guo@Sun.COM goto out;
842912Sartem }
852912Sartem }
862912Sartem
872912Sartem /* children of ignored parent should be ignored */
883121Sartem if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) {
892912Sartem HAL_INFO (("parent ignored %s", parent_udi));
90*8100SLin.Guo@Sun.COM
91*8100SLin.Guo@Sun.COM goto out;
922912Sartem }
932912Sartem
942912Sartem /* custom or generic add function */
952912Sartem begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add;
962912Sartem if (begin_add_func == NULL) {
972912Sartem begin_add_func = hotplug_event_begin_add_devinfo;
982912Sartem }
992912Sartem begin_add_func (hotplug_event->d,
1002912Sartem parent,
1012912Sartem hotplug_event->un.devfs.handler,
1022912Sartem (void *) hotplug_event);
103*8100SLin.Guo@Sun.COM return;
104*8100SLin.Guo@Sun.COM
105*8100SLin.Guo@Sun.COM out:
106*8100SLin.Guo@Sun.COM g_object_unref (hotplug_event->d);
107*8100SLin.Guo@Sun.COM hotplug_event_end ((void *) hotplug_event);
108*8100SLin.Guo@Sun.COM
109*8100SLin.Guo@Sun.COM return;
1102912Sartem }
1112912Sartem
1122912Sartem static void
hotplug_event_begin_devfs_remove(HotplugEvent * hotplug_event,HalDevice * d)1132912Sartem hotplug_event_begin_devfs_remove (HotplugEvent *hotplug_event, HalDevice *d)
1142912Sartem {
1152912Sartem if (d == NULL) {
1162912Sartem HAL_ERROR (("devpath %s not present in store, ignore event", hotplug_event->un.devfs.devfs_path));
1172912Sartem hotplug_event_end ((void *) hotplug_event);
1182912Sartem return;
1192912Sartem }
1203121Sartem HAL_INFO (("hotplug_event_begin_devfs_remove %s", hal_device_get_udi (d)));
1212912Sartem
1222912Sartem hotplug_event_begin_remove_devinfo(d,
1232912Sartem hotplug_event->un.devfs.devfs_path,
1242912Sartem (void *) hotplug_event);
1252912Sartem }
1262912Sartem
1272912Sartem static void
hotplug_event_begin_devfs(HotplugEvent * hotplug_event)1282912Sartem hotplug_event_begin_devfs (HotplugEvent *hotplug_event)
1292912Sartem {
1302912Sartem HalDevice *d;
1312912Sartem
1322912Sartem HAL_INFO (("hotplug_event_begin_devfs: %s", hotplug_event->un.devfs.devfs_path));
1332912Sartem d = hal_device_store_match_key_value_string (hald_get_gdl (),
1342912Sartem "solaris.devfs_path",
1352912Sartem hotplug_event->un.devfs.devfs_path);
1362912Sartem
1372912Sartem if (hotplug_event->action == HOTPLUG_ACTION_ADD) {
1382912Sartem hotplug_event_begin_devfs_add (hotplug_event, d);
1392912Sartem } else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) {
1402912Sartem hotplug_event_begin_devfs_remove (hotplug_event, d);
1412912Sartem } else {
142*8100SLin.Guo@Sun.COM HAL_ERROR (("unsupported action %d", hotplug_event->action));
143*8100SLin.Guo@Sun.COM g_object_unref (hotplug_event->d);
1442912Sartem hotplug_event_end ((void *) hotplug_event);
1452912Sartem }
1462912Sartem }
1472912Sartem
1482912Sartem static void
hotplug_event_begin(HotplugEvent * hotplug_event)1492912Sartem hotplug_event_begin (HotplugEvent *hotplug_event)
1502912Sartem {
1512912Sartem switch (hotplug_event->type) {
1522912Sartem
1532912Sartem case HOTPLUG_EVENT_DEVFS:
1542912Sartem hotplug_event_begin_devfs (hotplug_event);
1552912Sartem break;
1562912Sartem
1572912Sartem default:
1582912Sartem HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type));
159*8100SLin.Guo@Sun.COM g_object_unref (hotplug_event->d);
1602912Sartem hotplug_event_end ((void *) hotplug_event);
1612912Sartem break;
1622912Sartem }
1632912Sartem }
1642912Sartem
1652912Sartem void
hotplug_event_enqueue(HotplugEvent * hotplug_event,int front)1662912Sartem hotplug_event_enqueue (HotplugEvent *hotplug_event, int front)
1672912Sartem {
1682912Sartem if (hotplug_event_queue == NULL)
1692912Sartem hotplug_event_queue = g_queue_new ();
1702912Sartem
1712912Sartem if (front) {
1722912Sartem g_queue_push_head (hotplug_event_queue, hotplug_event);
1732912Sartem } else {
1742912Sartem g_queue_push_tail (hotplug_event_queue, hotplug_event);
1752912Sartem }
1762912Sartem }
1772912Sartem
1782912Sartem void
hotplug_event_process_queue(void)1792912Sartem hotplug_event_process_queue (void)
1802912Sartem {
1812912Sartem HotplugEvent *hotplug_event;
1822912Sartem
1832912Sartem if (hotplug_events_in_progress == NULL &&
1842912Sartem (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) {
1852912Sartem hotplug_queue_now_empty ();
1862912Sartem goto out;
1872912Sartem }
1882912Sartem
1892912Sartem /* do not process events if some other event is in progress */
1902912Sartem if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0)
1912912Sartem goto out;
1922912Sartem
1932912Sartem hotplug_event = g_queue_pop_head (hotplug_event_queue);
1942912Sartem if (hotplug_event == NULL)
1952912Sartem goto out;
1962912Sartem
1972912Sartem hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event);
1982912Sartem hotplug_event_begin (hotplug_event);
1992912Sartem
2002912Sartem out:
2012912Sartem ;
2022912Sartem }
203