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_power_button_add(HalDevice *parent, di_node_t node, 41 char *devfs_path, char *device_type); 42 static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 43 gint return_code, char **error, gpointer userdata1, gpointer userdata2); 44 45 DevinfoDevHandler devinfo_acpi_handler = { 46 devinfo_acpi_add, 47 NULL, 48 NULL, 49 NULL, 50 NULL, 51 devinfo_acpi_get_prober 52 }; 53 54 DevinfoDevHandler devinfo_power_button_handler = { 55 devinfo_power_button_add, 56 NULL, 57 NULL, 58 NULL, 59 NULL, 60 NULL 61 }; 62 63 static HalDevice * 64 devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path, 65 char *device_type) 66 { 67 HalDevice *d, *computer; 68 char *driver_name; 69 di_devlink_handle_t devlink_hdl; 70 int major; 71 di_minor_t minor; 72 dev_t dev; 73 char *minor_path = NULL; 74 char *devpath; 75 76 driver_name = di_driver_name(node); 77 if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) { 78 return (NULL); 79 } 80 81 d = hal_device_new(); 82 83 if ((computer = hal_device_store_find(hald_get_gdl(), 84 "/org/freedesktop/Hal/devices/computer")) || 85 (computer = hal_device_store_find(hald_get_tdl(), 86 "/org/freedesktop/Hal/devices/computer"))) { 87 hal_device_property_set_string(computer, 88 "system.formfactor", "laptop"); 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 major = di_driver_major(node); 96 if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 97 return (d); 98 } 99 minor = DI_MINOR_NIL; 100 while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 101 dev = di_minor_devt(minor); 102 if ((major != major(dev)) || 103 (di_minor_type(minor) != DDM_MINOR) || 104 (di_minor_spectype(minor) != S_IFCHR) || 105 ((minor_path = di_devfs_minor_path(minor)) == NULL)) { 106 continue; 107 } 108 109 if (hal_device_store_match_key_value_string(hald_get_gdl(), 110 "solaris.devfs_path", minor_path) == NULL) { 111 devinfo_acpi_add_minor(d, node, minor_path, dev); 112 } 113 114 di_devfs_path_free(minor_path); 115 } 116 di_devlink_fini(&devlink_hdl); 117 118 return (d); 119 } 120 121 void 122 devinfo_acpi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, 123 dev_t dev) 124 { 125 HalDevice *d; 126 127 d = hal_device_new(); 128 devinfo_set_default_properties(d, parent, node, minor_path); 129 devinfo_add_enqueue(d, minor_path, &devinfo_acpi_handler); 130 } 131 132 static HalDevice * 133 devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path, 134 char *device_type) 135 { 136 HalDevice *d; 137 char *driver_name; 138 139 driver_name = di_driver_name(node); 140 if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) { 141 return (NULL); 142 } 143 144 d = hal_device_new(); 145 146 devinfo_set_default_properties(d, parent, node, devfs_path); 147 hal_device_add_capability(d, "button"); 148 hal_device_property_set_bool(d, "button.has_state", FALSE); 149 hal_device_property_set_string(d, "info.category", "input"); 150 hal_device_property_set_string(d, "button.type", "power"); 151 hal_device_property_set_string(d, "info.product", "Power Button"); 152 153 devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler); 154 155 return (d); 156 } 157 158 void 159 devinfo_power_button_rescan(void) 160 { 161 HalDevice *d = NULL; 162 HalDeviceStore *store = hald_get_gdl(); 163 164 d = hal_device_store_match_key_value_string (store, "button.type", 165 "power"); 166 if (d != NULL) { 167 device_send_signal_condition(d, "ButtonPressed", "power"); 168 } 169 } 170 171 void 172 devinfo_brightness_hotkeys_rescan(char *subclass) 173 { 174 HalDevice *d = NULL; 175 176 if ((d = hal_device_store_find(hald_get_gdl(), 177 "/org/freedesktop/Hal/devices/computer")) || 178 (d = hal_device_store_find(hald_get_tdl(), 179 "/org/freedesktop/Hal/devices/computer"))) { 180 if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) { 181 device_send_signal_condition(d, "ButtonPressed", 182 "brightness-up"); 183 } else { 184 device_send_signal_condition(d, "ButtonPressed", 185 "brightness-down"); 186 } 187 } 188 } 189 190 void 191 devinfo_battery_device_rescan(char *parent_devfs_path, gchar *udi) 192 { 193 HalDevice *d = NULL; 194 195 d = hal_device_store_find(hald_get_gdl(), udi); 196 if (d == NULL) { 197 HAL_INFO(("device not found %s", udi)); 198 return; 199 } 200 201 hald_runner_run(d, "hald-probe-acpi", NULL, 202 DEVINFO_PROBE_BATTERY_TIMEOUT, devinfo_battery_rescan_probing_done, 203 NULL, NULL); 204 } 205 206 void 207 devinfo_lid_device_rescan(char *subclass, gchar *udi) 208 { 209 HalDevice *d = NULL; 210 211 d = hal_device_store_find(hald_get_gdl(), udi); 212 if (d == NULL) { 213 HAL_INFO(("device not found %s", udi)); 214 return; 215 } 216 217 hal_device_property_set_bool(d, "button.state.value", 218 (strcmp(subclass, ESC_PWRCTL_REMOVE) == 0)); 219 device_send_signal_condition(d, "ButtonPressed", "lid"); 220 } 221 222 static void 223 devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 224 gint return_code, char **error, gpointer userdata1, gpointer userdata2) 225 { 226 /* hald_runner_run() requires this function since cannot pass NULL */ 227 } 228 229 const gchar * 230 devinfo_acpi_get_prober(HalDevice *d, int *timeout) 231 { 232 *timeout = DEVINFO_PROBE_BATTERY_TIMEOUT; /* 30 second timeout */ 233 return ("hald-probe-acpi"); 234 } 235