1 /*************************************************************************** 2 * 3 * devinfo_acpi : acpi devices 4 * 5 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 6 * Use is subject to license terms. 7 * 8 * Licensed under the Academic Free License version 2.1 9 * 10 **************************************************************************/ 11 12 #ifdef HAVE_CONFIG_H 13 #include <config.h> 14 #endif 15 16 #include <stdio.h> 17 #include <string.h> 18 #include <sys/utsname.h> 19 #include <libdevinfo.h> 20 #include <sys/mkdev.h> 21 #include <sys/stat.h> 22 #include <unistd.h> 23 #include <sys/sysevent/dev.h> 24 #include <sys/sysevent/pwrctl.h> 25 26 #include "../osspec.h" 27 #include "../logger.h" 28 #include "../hald.h" 29 #include "../hald_dbus.h" 30 #include "../device_info.h" 31 #include "../util.h" 32 #include "../hald_runner.h" 33 #include "devinfo_acpi.h" 34 35 #define DEVINFO_PROBE_ACPI_TIMEOUT 30000 36 37 static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *); 38 static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node, 39 char *devfs_path, char *device_type); 40 static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 41 gint return_code, char **error, gpointer userdata1, gpointer userdata2); 42 43 DevinfoDevHandler devinfo_acpi_handler = { 44 devinfo_acpi_add, 45 NULL, 46 NULL, 47 NULL, 48 NULL, 49 devinfo_acpi_get_prober 50 }; 51 52 DevinfoDevHandler devinfo_power_button_handler = { 53 devinfo_power_button_add, 54 NULL, 55 NULL, 56 NULL, 57 NULL, 58 NULL 59 }; 60 61 static HalDevice * 62 devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path, 63 char *device_type) 64 { 65 HalDevice *d, *computer; 66 char *driver_name; 67 di_devlink_handle_t devlink_hdl; 68 int major; 69 di_minor_t minor; 70 dev_t dev; 71 char *minor_path = NULL; 72 char *devpath; 73 74 driver_name = di_driver_name(node); 75 if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) { 76 return (NULL); 77 } 78 79 d = hal_device_new(); 80 81 if ((computer = hal_device_store_find(hald_get_gdl(), 82 "/org/freedesktop/Hal/devices/computer")) || 83 (computer = hal_device_store_find(hald_get_tdl(), 84 "/org/freedesktop/Hal/devices/computer"))) { 85 hal_device_property_set_string(computer, 86 "system.formfactor", "laptop"); 87 hal_device_property_set_string(computer, 88 "power_management.type", "acpi"); 89 } 90 devinfo_set_default_properties(d, parent, node, devfs_path); 91 devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler); 92 93 major = di_driver_major(node); 94 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 95 return (d); 96 } 97 minor = DI_MINOR_NIL; 98 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 99 dev = di_minor_devt(minor); 100 if ((major != major(dev)) || 101 (di_minor_type(minor) != DDM_MINOR) || 102 (di_minor_spectype(minor) != S_IFCHR) || 103 ((minor_path = di_devfs_minor_path(minor)) == NULL)) { 104 continue; 105 } 106 107 if (hal_device_store_match_key_value_string(hald_get_gdl(), 108 "solaris.devfs_path", minor_path) == NULL) { 109 devinfo_acpi_add_minor(d, node, minor_path, dev); 110 } 111 112 di_devfs_path_free(minor_path); 113 } 114 di_devlink_fini(&devlink_hdl); 115 116 return (d); 117 } 118 119 void 120 devinfo_acpi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, 121 dev_t dev) 122 { 123 HalDevice *d; 124 125 d = hal_device_new(); 126 devinfo_set_default_properties(d, parent, node, minor_path); 127 devinfo_add_enqueue(d, minor_path, &devinfo_acpi_handler); 128 } 129 130 static HalDevice * 131 devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path, 132 char *device_type) 133 { 134 HalDevice *d; 135 char *driver_name; 136 137 driver_name = di_driver_name(node); 138 if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) { 139 return (NULL); 140 } 141 142 d = hal_device_new(); 143 144 devinfo_set_default_properties(d, parent, node, devfs_path); 145 hal_device_add_capability(d, "button"); 146 hal_device_property_set_bool(d, "button.has_state", FALSE); 147 hal_device_property_set_string(d, "info.category", "input"); 148 hal_device_property_set_string(d, "button.type", "power"); 149 hal_device_property_set_string(d, "info.product", "Power Button"); 150 151 devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler); 152 153 return (d); 154 } 155 156 void 157 devinfo_power_button_event(void) 158 { 159 HalDevice *d = NULL; 160 HalDeviceStore *store = hald_get_gdl(); 161 162 d = hal_device_store_match_key_value_string (store, "button.type", 163 "power"); 164 if (d != NULL) { 165 device_send_signal_condition(d, "ButtonPressed", "power"); 166 } 167 } 168 169 void 170 devinfo_brightness_hotkeys_event(char *subclass) 171 { 172 HalDevice *d = NULL; 173 174 if ((d = hal_device_store_find(hald_get_gdl(), 175 "/org/freedesktop/Hal/devices/computer")) || 176 (d = hal_device_store_find(hald_get_tdl(), 177 "/org/freedesktop/Hal/devices/computer"))) { 178 if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) { 179 device_send_signal_condition(d, "ButtonPressed", 180 "brightness-up"); 181 } else { 182 device_send_signal_condition(d, "ButtonPressed", 183 "brightness-down"); 184 } 185 } 186 } 187 188 void 189 devinfo_battery_rescan(char *parent_devfs_path, gchar *udi) 190 { 191 HalDevice *d = NULL; 192 193 d = hal_device_store_find(hald_get_gdl(), udi); 194 if (d == NULL) { 195 HAL_INFO(("device not found %s", udi)); 196 return; 197 } 198 199 hald_runner_run(d, "hald-probe-acpi", NULL, 200 DEVINFO_PROBE_ACPI_TIMEOUT, devinfo_battery_rescan_probing_done, 201 NULL, NULL); 202 } 203 204 void 205 devinfo_lid_event(char *subclass, gchar *udi) 206 { 207 HalDevice *d = NULL; 208 209 d = hal_device_store_find(hald_get_gdl(), udi); 210 if (d == NULL) { 211 HAL_INFO(("device not found %s", udi)); 212 return; 213 } 214 215 hal_device_property_set_bool(d, "button.state.value", 216 (strcmp(subclass, ESC_PWRCTL_REMOVE) == 0)); 217 device_send_signal_condition(d, "ButtonPressed", "lid"); 218 } 219 220 gboolean 221 devinfo_lid_rescan(HalDevice *d) 222 { 223 if (hal_device_property_get_bool(d, "button.workaround")) { 224 /* Set lid state to open for workaround */ 225 hal_device_property_set_bool(d, "button.state.value", FALSE); 226 } else { 227 hald_runner_run(d, "hald-probe-acpi", NULL, 228 DEVINFO_PROBE_ACPI_TIMEOUT, 229 devinfo_battery_rescan_probing_done, NULL, NULL); 230 } 231 232 return (TRUE); 233 } 234 235 static void 236 devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 237 gint return_code, char **error, gpointer userdata1, gpointer userdata2) 238 { 239 /* hald_runner_run() requires this function since cannot pass NULL */ 240 } 241 242 const gchar * 243 devinfo_acpi_get_prober(HalDevice *d, int *timeout) 244 { 245 *timeout = DEVINFO_PROBE_ACPI_TIMEOUT; /* 30 second timeout */ 246 return ("hald-probe-acpi"); 247 } 248