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 37static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *); 38static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node, 39 char *devfs_path, char *device_type); 40static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 41 gint return_code, char **error, gpointer userdata1, gpointer userdata2); 42 43DevinfoDevHandler devinfo_acpi_handler = { 44 devinfo_acpi_add, 45 NULL, 46 NULL, 47 NULL, 48 NULL, 49 devinfo_acpi_get_prober 50}; 51 52DevinfoDevHandler devinfo_power_button_handler = { 53 devinfo_power_button_add, 54 NULL, 55 NULL, 56 NULL, 57 NULL, 58 NULL 59}; 60 61static HalDevice * 62devinfo_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 119void 120devinfo_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 130static HalDevice * 131devinfo_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 156void 157devinfo_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 169void 170devinfo_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 188void 189devinfo_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 204void 205devinfo_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 220gboolean 221devinfo_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 235static void 236devinfo_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 242const gchar * 243devinfo_acpi_get_prober(HalDevice *d, int *timeout) 244{ 245 *timeout = DEVINFO_PROBE_ACPI_TIMEOUT; /* 30 second timeout */ 246 return ("hald-probe-acpi"); 247} 248