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