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