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 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 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 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 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 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 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 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