12912Sartem /*************************************************************************** 22912Sartem * 32912Sartem * hotplug.c : HAL-internal hotplug events 42912Sartem * 52912Sartem * Copyright 2006 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 122916Sartem #pragma ident "%Z%%M% %I% %E% SMI" 132912Sartem 142912Sartem #ifdef HAVE_CONFIG_H 152912Sartem # include <config.h> 162912Sartem #endif 172912Sartem 182912Sartem #include <stdio.h> 192912Sartem #include <string.h> 202912Sartem #include <errno.h> 212912Sartem #include <sys/types.h> 222912Sartem #include <sys/stat.h> 232912Sartem #include <sys/un.h> 242912Sartem #include <sys/utsname.h> 252912Sartem #include <unistd.h> 262912Sartem 272912Sartem #include <glib.h> 282912Sartem #include <dbus/dbus.h> 292912Sartem #include <dbus/dbus-glib.h> 302912Sartem 312912Sartem #include "../osspec.h" 322912Sartem #include "../logger.h" 332912Sartem #include "../hald.h" 342912Sartem #include "../device_info.h" 352912Sartem 362912Sartem #include "osspec_solaris.h" 372912Sartem #include "hotplug.h" 382912Sartem #include "devinfo.h" 392912Sartem 402912Sartem /** Queue of ordered hotplug events */ 412912Sartem GQueue *hotplug_event_queue; 422912Sartem 432912Sartem /** List of HotplugEvent objects we are currently processing */ 442912Sartem GSList *hotplug_events_in_progress = NULL; 452912Sartem 462912Sartem static void hotplug_event_begin (HotplugEvent *hotplug_event); 472912Sartem 482912Sartem void 492912Sartem hotplug_event_end (void *end_token) 502912Sartem { 512912Sartem HotplugEvent *hotplug_event = (HotplugEvent *) end_token; 522912Sartem 532912Sartem hotplug_events_in_progress = g_slist_remove (hotplug_events_in_progress, hotplug_event); 542912Sartem g_free (hotplug_event); 552912Sartem hotplug_event_process_queue (); 562912Sartem } 572912Sartem 582912Sartem static void 592912Sartem hotplug_event_begin_devfs_add (HotplugEvent *hotplug_event, HalDevice *d) 602912Sartem { 612912Sartem HalDevice *parent; 622912Sartem const gchar *parent_udi; 632912Sartem void (*begin_add_func) (HalDevice *, HalDevice *, DevinfoDevHandler *, void *); 642912Sartem 652912Sartem if (d != NULL) { 662912Sartem /* XXX */ 672912Sartem HAL_ERROR (("devpath %s already present in store, ignore event", hotplug_event->un.devfs.devfs_path)); 682912Sartem hotplug_event_end ((void *) hotplug_event); 692912Sartem return; 702912Sartem } 712912Sartem 722912Sartem /* find parent */ 732912Sartem parent_udi = hal_device_property_get_string (hotplug_event->d, "info.parent"); 742912Sartem if (parent_udi == NULL || strlen(parent_udi) == 0) { 752912Sartem parent = NULL; 762912Sartem } else { 772912Sartem parent = hal_device_store_match_key_value_string (hald_get_gdl (), "info.udi", parent_udi); 782912Sartem } 792912Sartem /* only root node is allowed to be orphan */ 802912Sartem if (parent == NULL) { 812912Sartem if (strcmp(hotplug_event->un.devfs.devfs_path, "/") != 0) { 822912Sartem HAL_ERROR (("Parent is NULL devfs_path=%s parent_udi=%s", hotplug_event->un.devfs.devfs_path, parent_udi ? parent_udi : "<null>")); 832912Sartem hotplug_event_end ((void *) hotplug_event); 842912Sartem return; 852912Sartem } 862912Sartem } 872912Sartem 882912Sartem /* children of ignored parent should be ignored */ 89*3121Sartem if (parent != NULL && hal_device_property_get_bool (parent, "info.ignore")) { 902912Sartem HAL_INFO (("parent ignored %s", parent_udi)); 91*3121Sartem hotplug_event_end ((void *) hotplug_event); 92*3121Sartem return; 932912Sartem } 942912Sartem 952912Sartem /* custom or generic add function */ 962912Sartem begin_add_func = hotplug_event->un.devfs.handler->hotplug_begin_add; 972912Sartem if (begin_add_func == NULL) { 982912Sartem begin_add_func = hotplug_event_begin_add_devinfo; 992912Sartem } 1002912Sartem begin_add_func (hotplug_event->d, 1012912Sartem parent, 1022912Sartem hotplug_event->un.devfs.handler, 1032912Sartem (void *) hotplug_event); 1042912Sartem } 1052912Sartem 1062912Sartem static void 1072912Sartem hotplug_event_begin_devfs_remove (HotplugEvent *hotplug_event, HalDevice *d) 1082912Sartem { 1092912Sartem if (d == NULL) { 1102912Sartem HAL_ERROR (("devpath %s not present in store, ignore event", hotplug_event->un.devfs.devfs_path)); 1112912Sartem hotplug_event_end ((void *) hotplug_event); 1122912Sartem return; 1132912Sartem } 114*3121Sartem HAL_INFO (("hotplug_event_begin_devfs_remove %s", hal_device_get_udi (d))); 1152912Sartem 1162912Sartem hotplug_event_begin_remove_devinfo(d, 1172912Sartem hotplug_event->un.devfs.devfs_path, 1182912Sartem (void *) hotplug_event); 1192912Sartem } 1202912Sartem 1212912Sartem static void 1222912Sartem hotplug_event_begin_devfs (HotplugEvent *hotplug_event) 1232912Sartem { 1242912Sartem HalDevice *d; 1252912Sartem 1262912Sartem HAL_INFO (("hotplug_event_begin_devfs: %s", hotplug_event->un.devfs.devfs_path)); 1272912Sartem d = hal_device_store_match_key_value_string (hald_get_gdl (), 1282912Sartem "solaris.devfs_path", 1292912Sartem hotplug_event->un.devfs.devfs_path); 1302912Sartem 1312912Sartem if (hotplug_event->action == HOTPLUG_ACTION_ADD) { 1322912Sartem hotplug_event_begin_devfs_add (hotplug_event, d); 1332912Sartem } else if (hotplug_event->action == HOTPLUG_ACTION_REMOVE) { 1342912Sartem hotplug_event_begin_devfs_remove (hotplug_event, d); 1352912Sartem } else { 1362912Sartem hotplug_event_end ((void *) hotplug_event); 1372912Sartem } 1382912Sartem } 1392912Sartem 1402912Sartem static void 1412912Sartem hotplug_event_begin (HotplugEvent *hotplug_event) 1422912Sartem { 1432912Sartem switch (hotplug_event->type) { 1442912Sartem 1452912Sartem case HOTPLUG_EVENT_DEVFS: 1462912Sartem hotplug_event_begin_devfs (hotplug_event); 1472912Sartem break; 1482912Sartem 1492912Sartem default: 1502912Sartem HAL_ERROR (("Unknown hotplug event type %d", hotplug_event->type)); 1512912Sartem hotplug_event_end ((void *) hotplug_event); 1522912Sartem break; 1532912Sartem } 1542912Sartem } 1552912Sartem 1562912Sartem void 1572912Sartem hotplug_event_enqueue (HotplugEvent *hotplug_event, int front) 1582912Sartem { 1592912Sartem if (hotplug_event_queue == NULL) 1602912Sartem hotplug_event_queue = g_queue_new (); 1612912Sartem 1622912Sartem if (front) { 1632912Sartem g_queue_push_head (hotplug_event_queue, hotplug_event); 1642912Sartem } else { 1652912Sartem g_queue_push_tail (hotplug_event_queue, hotplug_event); 1662912Sartem } 1672912Sartem } 1682912Sartem 1692912Sartem void 1702912Sartem hotplug_event_process_queue (void) 1712912Sartem { 1722912Sartem HotplugEvent *hotplug_event; 1732912Sartem 1742912Sartem if (hotplug_events_in_progress == NULL && 1752912Sartem (hotplug_event_queue == NULL || g_queue_is_empty (hotplug_event_queue))) { 1762912Sartem hotplug_queue_now_empty (); 1772912Sartem goto out; 1782912Sartem } 1792912Sartem 1802912Sartem /* do not process events if some other event is in progress */ 1812912Sartem if (hotplug_events_in_progress != NULL && g_slist_length (hotplug_events_in_progress) > 0) 1822912Sartem goto out; 1832912Sartem 1842912Sartem hotplug_event = g_queue_pop_head (hotplug_event_queue); 1852912Sartem if (hotplug_event == NULL) 1862912Sartem goto out; 1872912Sartem 1882912Sartem hotplug_events_in_progress = g_slist_append (hotplug_events_in_progress, hotplug_event); 1892912Sartem hotplug_event_begin (hotplug_event); 1902912Sartem 1912912Sartem out: 1922912Sartem ; 1932912Sartem } 194