17b840e52Sphitran /*************************************************************************** 27b840e52Sphitran * 37b840e52Sphitran * devinfo_acpi : acpi devices 47b840e52Sphitran * 5d2ec54f7Sphitran * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 67b840e52Sphitran * Use is subject to license terms. 77b840e52Sphitran * 87b840e52Sphitran * Licensed under the Academic Free License version 2.1 97b840e52Sphitran * 107b840e52Sphitran **************************************************************************/ 117b840e52Sphitran 127b840e52Sphitran #ifdef HAVE_CONFIG_H 137b840e52Sphitran #include <config.h> 147b840e52Sphitran #endif 157b840e52Sphitran 167b840e52Sphitran #include <stdio.h> 177b840e52Sphitran #include <string.h> 187b840e52Sphitran #include <sys/utsname.h> 197b840e52Sphitran #include <libdevinfo.h> 207b840e52Sphitran #include <sys/mkdev.h> 217b840e52Sphitran #include <sys/stat.h> 227b840e52Sphitran #include <unistd.h> 23d2ec54f7Sphitran #include <sys/sysevent/dev.h> 24d2ec54f7Sphitran #include <sys/sysevent/pwrctl.h> 257b840e52Sphitran 267b840e52Sphitran #include "../osspec.h" 277b840e52Sphitran #include "../logger.h" 287b840e52Sphitran #include "../hald.h" 297b840e52Sphitran #include "../hald_dbus.h" 307b840e52Sphitran #include "../device_info.h" 317b840e52Sphitran #include "../util.h" 327b840e52Sphitran #include "../hald_runner.h" 337b840e52Sphitran #include "devinfo_acpi.h" 347b840e52Sphitran 35*076d97abSPhi Tran #define DEVINFO_PROBE_ACPI_TIMEOUT 30000 367b840e52Sphitran 377b840e52Sphitran static HalDevice *devinfo_acpi_add(HalDevice *, di_node_t, char *, char *); 38d2ec54f7Sphitran static HalDevice *devinfo_power_button_add(HalDevice *parent, di_node_t node, 39d2ec54f7Sphitran char *devfs_path, char *device_type); 40d2ec54f7Sphitran static void devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 41d2ec54f7Sphitran gint return_code, char **error, gpointer userdata1, gpointer userdata2); 427b840e52Sphitran 437b840e52Sphitran DevinfoDevHandler devinfo_acpi_handler = { 447b840e52Sphitran devinfo_acpi_add, 457b840e52Sphitran NULL, 467b840e52Sphitran NULL, 477b840e52Sphitran NULL, 487b840e52Sphitran NULL, 4959066d3cSphitran devinfo_acpi_get_prober 507b840e52Sphitran }; 517b840e52Sphitran 52d2ec54f7Sphitran DevinfoDevHandler devinfo_power_button_handler = { 53d2ec54f7Sphitran devinfo_power_button_add, 54d2ec54f7Sphitran NULL, 55d2ec54f7Sphitran NULL, 56d2ec54f7Sphitran NULL, 57d2ec54f7Sphitran NULL, 58d2ec54f7Sphitran NULL 59d2ec54f7Sphitran }; 60d2ec54f7Sphitran 617b840e52Sphitran static HalDevice * 627b840e52Sphitran devinfo_acpi_add(HalDevice *parent, di_node_t node, char *devfs_path, 637b840e52Sphitran char *device_type) 647b840e52Sphitran { 657b840e52Sphitran HalDevice *d, *computer; 667b840e52Sphitran char *driver_name; 677b840e52Sphitran di_devlink_handle_t devlink_hdl; 687b840e52Sphitran int major; 697b840e52Sphitran di_minor_t minor; 707b840e52Sphitran dev_t dev; 717b840e52Sphitran char *minor_path = NULL; 727b840e52Sphitran char *devpath; 737b840e52Sphitran 747b840e52Sphitran driver_name = di_driver_name(node); 75d2ec54f7Sphitran if ((driver_name == NULL) || (strcmp(driver_name, "acpi_drv") != 0)) { 767b840e52Sphitran return (NULL); 777b840e52Sphitran } 787b840e52Sphitran 797b840e52Sphitran d = hal_device_new(); 807b840e52Sphitran 817b840e52Sphitran if ((computer = hal_device_store_find(hald_get_gdl(), 827b840e52Sphitran "/org/freedesktop/Hal/devices/computer")) || 837b840e52Sphitran (computer = hal_device_store_find(hald_get_tdl(), 847b840e52Sphitran "/org/freedesktop/Hal/devices/computer"))) { 857b840e52Sphitran hal_device_property_set_string(computer, 867b840e52Sphitran "system.formfactor", "laptop"); 8759066d3cSphitran hal_device_property_set_string(computer, 8859066d3cSphitran "power_management.type", "acpi"); 897b840e52Sphitran } 907b840e52Sphitran devinfo_set_default_properties(d, parent, node, devfs_path); 9159066d3cSphitran devinfo_add_enqueue(d, devfs_path, &devinfo_acpi_handler); 927b840e52Sphitran 937b840e52Sphitran major = di_driver_major(node); 947b840e52Sphitran if ((devlink_hdl = di_devlink_init(NULL, 0)) == NULL) { 957b840e52Sphitran return (d); 967b840e52Sphitran } 977b840e52Sphitran minor = DI_MINOR_NIL; 987b840e52Sphitran while ((minor = di_minor_next(node, minor)) != DI_MINOR_NIL) { 997b840e52Sphitran dev = di_minor_devt(minor); 1007b840e52Sphitran if ((major != major(dev)) || 1017b840e52Sphitran (di_minor_type(minor) != DDM_MINOR) || 1027b840e52Sphitran (di_minor_spectype(minor) != S_IFCHR) || 1037b840e52Sphitran ((minor_path = di_devfs_minor_path(minor)) == NULL)) { 1047b840e52Sphitran continue; 1057b840e52Sphitran } 1067b840e52Sphitran 1077b840e52Sphitran if (hal_device_store_match_key_value_string(hald_get_gdl(), 1087b840e52Sphitran "solaris.devfs_path", minor_path) == NULL) { 10959066d3cSphitran devinfo_acpi_add_minor(d, node, minor_path, dev); 1107b840e52Sphitran } 1117b840e52Sphitran 1127b840e52Sphitran di_devfs_path_free(minor_path); 1137b840e52Sphitran } 1147b840e52Sphitran di_devlink_fini(&devlink_hdl); 1157b840e52Sphitran 1167b840e52Sphitran return (d); 1177b840e52Sphitran } 1187b840e52Sphitran 1197b840e52Sphitran void 12059066d3cSphitran devinfo_acpi_add_minor(HalDevice *parent, di_node_t node, char *minor_path, 1217b840e52Sphitran dev_t dev) 1227b840e52Sphitran { 1237b840e52Sphitran HalDevice *d; 1247b840e52Sphitran 1257b840e52Sphitran d = hal_device_new(); 1267b840e52Sphitran devinfo_set_default_properties(d, parent, node, minor_path); 12759066d3cSphitran devinfo_add_enqueue(d, minor_path, &devinfo_acpi_handler); 1287b840e52Sphitran } 1297b840e52Sphitran 130d2ec54f7Sphitran static HalDevice * 131d2ec54f7Sphitran devinfo_power_button_add(HalDevice *parent, di_node_t node, char *devfs_path, 132d2ec54f7Sphitran char *device_type) 133d2ec54f7Sphitran { 134d2ec54f7Sphitran HalDevice *d; 135d2ec54f7Sphitran char *driver_name; 136d2ec54f7Sphitran 137d2ec54f7Sphitran driver_name = di_driver_name(node); 138d2ec54f7Sphitran if ((driver_name == NULL) || (strcmp(driver_name, "power") != 0)) { 139d2ec54f7Sphitran return (NULL); 140d2ec54f7Sphitran } 141d2ec54f7Sphitran 142d2ec54f7Sphitran d = hal_device_new(); 143d2ec54f7Sphitran 144d2ec54f7Sphitran devinfo_set_default_properties(d, parent, node, devfs_path); 145d2ec54f7Sphitran hal_device_add_capability(d, "button"); 146d2ec54f7Sphitran hal_device_property_set_bool(d, "button.has_state", FALSE); 147d2ec54f7Sphitran hal_device_property_set_string(d, "info.category", "input"); 148d2ec54f7Sphitran hal_device_property_set_string(d, "button.type", "power"); 149d2ec54f7Sphitran hal_device_property_set_string(d, "info.product", "Power Button"); 150d2ec54f7Sphitran 151d2ec54f7Sphitran devinfo_add_enqueue(d, devfs_path, &devinfo_power_button_handler); 152d2ec54f7Sphitran 153d2ec54f7Sphitran return (d); 154d2ec54f7Sphitran } 155d2ec54f7Sphitran 156d2ec54f7Sphitran void 157*076d97abSPhi Tran devinfo_power_button_event(void) 158d2ec54f7Sphitran { 159d2ec54f7Sphitran HalDevice *d = NULL; 160d2ec54f7Sphitran HalDeviceStore *store = hald_get_gdl(); 161d2ec54f7Sphitran 162d2ec54f7Sphitran d = hal_device_store_match_key_value_string (store, "button.type", 163d2ec54f7Sphitran "power"); 164d2ec54f7Sphitran if (d != NULL) { 165d2ec54f7Sphitran device_send_signal_condition(d, "ButtonPressed", "power"); 166d2ec54f7Sphitran } 167d2ec54f7Sphitran } 168d2ec54f7Sphitran 169d2ec54f7Sphitran void 170*076d97abSPhi Tran devinfo_brightness_hotkeys_event(char *subclass) 171d2ec54f7Sphitran { 172d2ec54f7Sphitran HalDevice *d = NULL; 173d2ec54f7Sphitran 174d2ec54f7Sphitran if ((d = hal_device_store_find(hald_get_gdl(), 175d2ec54f7Sphitran "/org/freedesktop/Hal/devices/computer")) || 176d2ec54f7Sphitran (d = hal_device_store_find(hald_get_tdl(), 177d2ec54f7Sphitran "/org/freedesktop/Hal/devices/computer"))) { 178d2ec54f7Sphitran if (strcmp(subclass, ESC_PWRCTL_BRIGHTNESS_UP) == 0) { 179d2ec54f7Sphitran device_send_signal_condition(d, "ButtonPressed", 180d2ec54f7Sphitran "brightness-up"); 181d2ec54f7Sphitran } else { 182d2ec54f7Sphitran device_send_signal_condition(d, "ButtonPressed", 183d2ec54f7Sphitran "brightness-down"); 184d2ec54f7Sphitran } 185d2ec54f7Sphitran } 186d2ec54f7Sphitran } 187d2ec54f7Sphitran 1887b840e52Sphitran void 189*076d97abSPhi Tran devinfo_battery_rescan(char *parent_devfs_path, gchar *udi) 1907b840e52Sphitran { 1917b840e52Sphitran HalDevice *d = NULL; 1927b840e52Sphitran 1937b840e52Sphitran d = hal_device_store_find(hald_get_gdl(), udi); 1947b840e52Sphitran if (d == NULL) { 1957b840e52Sphitran HAL_INFO(("device not found %s", udi)); 1967b840e52Sphitran return; 1977b840e52Sphitran } 1987b840e52Sphitran 199d2ec54f7Sphitran hald_runner_run(d, "hald-probe-acpi", NULL, 200*076d97abSPhi Tran DEVINFO_PROBE_ACPI_TIMEOUT, devinfo_battery_rescan_probing_done, 2017b840e52Sphitran NULL, NULL); 2027b840e52Sphitran } 2037b840e52Sphitran 204d2ec54f7Sphitran void 205*076d97abSPhi Tran devinfo_lid_event(char *subclass, gchar *udi) 206d2ec54f7Sphitran { 207d2ec54f7Sphitran HalDevice *d = NULL; 208d2ec54f7Sphitran 209d2ec54f7Sphitran d = hal_device_store_find(hald_get_gdl(), udi); 210d2ec54f7Sphitran if (d == NULL) { 211d2ec54f7Sphitran HAL_INFO(("device not found %s", udi)); 212d2ec54f7Sphitran return; 213d2ec54f7Sphitran } 214d2ec54f7Sphitran 215d2ec54f7Sphitran hal_device_property_set_bool(d, "button.state.value", 216d2ec54f7Sphitran (strcmp(subclass, ESC_PWRCTL_REMOVE) == 0)); 217d2ec54f7Sphitran device_send_signal_condition(d, "ButtonPressed", "lid"); 218d2ec54f7Sphitran } 219d2ec54f7Sphitran 220*076d97abSPhi Tran gboolean 221*076d97abSPhi Tran devinfo_lid_rescan(HalDevice *d) 222*076d97abSPhi Tran { 223*076d97abSPhi Tran if (hal_device_property_get_bool(d, "button.workaround")) { 224*076d97abSPhi Tran /* Set lid state to open for workaround */ 225*076d97abSPhi Tran hal_device_property_set_bool(d, "button.state.value", FALSE); 226*076d97abSPhi Tran } else { 227*076d97abSPhi Tran hald_runner_run(d, "hald-probe-acpi", NULL, 228*076d97abSPhi Tran DEVINFO_PROBE_ACPI_TIMEOUT, 229*076d97abSPhi Tran devinfo_battery_rescan_probing_done, NULL, NULL); 230*076d97abSPhi Tran } 231*076d97abSPhi Tran 232*076d97abSPhi Tran return (TRUE); 233*076d97abSPhi Tran } 234*076d97abSPhi Tran 2357b840e52Sphitran static void 2367b840e52Sphitran devinfo_battery_rescan_probing_done(HalDevice *d, guint32 exit_type, 2377b840e52Sphitran gint return_code, char **error, gpointer userdata1, gpointer userdata2) 2387b840e52Sphitran { 2397b840e52Sphitran /* hald_runner_run() requires this function since cannot pass NULL */ 2407b840e52Sphitran } 2417b840e52Sphitran 2427b840e52Sphitran const gchar * 24359066d3cSphitran devinfo_acpi_get_prober(HalDevice *d, int *timeout) 2447b840e52Sphitran { 245*076d97abSPhi Tran *timeout = DEVINFO_PROBE_ACPI_TIMEOUT; /* 30 second timeout */ 246d2ec54f7Sphitran return ("hald-probe-acpi"); 2477b840e52Sphitran } 248