]> xenbits.xen.org Git - xenclient/xen.git/commitdiff
[xenpmd] Add sci for power management
authorJean Guyader <jean.guyader@eu.citrix.com>
Thu, 18 Dec 2008 18:14:55 +0000 (18:14 +0000)
committerJean Guyader <jean.guyader@eu.citrix.com>
Thu, 18 Dec 2008 18:14:55 +0000 (18:14 +0000)
tools/xenpmd/Makefile
tools/xenpmd/acpi-events.c [new file with mode: 0644]
tools/xenpmd/xenpmd.c

index 6fc31a46b41ce9e10d7d57fb3bb3098326677b61..c9fc6377a2ba01c4a904f81e0a261a9a2498ef3b 100644 (file)
@@ -10,6 +10,8 @@ BIN      = xenpmd
 .PHONY: all
 all: $(BIN)
 
+$(BIN): xenpmd.o acpi-events.o
+
 .PHONY: install
 install: all
        $(INSTALL_DIR) $(DESTDIR)$(SBINDIR)
@@ -17,4 +19,4 @@ install: all
 
 .PHONY: clean
 clean:
-       $(RM) -f $(BIN)
+       $(RM) -f $(BIN) *.o
diff --git a/tools/xenpmd/acpi-events.c b/tools/xenpmd/acpi-events.c
new file mode 100644 (file)
index 0000000..54b546b
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * acpi-events.c
+ *
+ * Register for and monitor acpi events and communicate relevant
+ * events to ioemu by triggering xenstore events. 
+ *
+ * Copyright (c) 2008  Kamala Narasimhan
+ * Copyright (c) 2008  Citrix Systems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <xs.h>
+
+#define AC_ADAPTER_STATE_FILE_PATH "/proc/acpi/ac_adapter/AC/state"
+#define LID_STATE_FILE_PATH "/proc/acpi/button/lid/LID/state"
+#define ACPID_SOCKET_PATH "/var/run/acpid.socket"
+
+#define XS_AC_ADAPTER_STATE_PATH "/pm/ac_adapter"
+#define XS_LID_STATE_PATH "/pm/lid_state"
+
+#define XS_AC_ADAPTER_EVENT_PATH "/pm/events/acadapterstatechanged"
+#define XS_LID_EVENT_PATH "/pm/events/lidstatechanged"
+#define XS_PBTN_EVENT_PATH "/pm/events/powerbuttonpressed"
+
+static int socket_fd;
+static pthread_t acpi_thread;  
+extern struct xs_handle *xs;
+
+void write_state_info_in_xenstore(char *file_path, char *xenstore_path, 
+             char *search_str, char *default_value, char *alternate_value)
+{
+    FILE *file;
+    char file_data[1024];
+
+    xs_write(xs, XBT_NULL, xenstore_path, default_value, strlen(default_value));
+    file = fopen(file_path, "r");
+    if ( file == NULL )
+        return;
+
+    memset(file_data, 0, 1024);
+    fgets(file_data, 1024, file);
+    if ( strstr(file_data, search_str) )
+        xs_write(xs, XBT_NULL, xenstore_path, alternate_value,
+                 strlen(alternate_value));
+    fclose(file);
+}
+
+void initialize_system_state_info(void)
+{
+    write_state_info_in_xenstore(AC_ADAPTER_STATE_FILE_PATH, 
+                                XS_AC_ADAPTER_STATE_PATH, "off-line", "1", "0");
+    write_state_info_in_xenstore(LID_STATE_FILE_PATH, XS_LID_STATE_PATH, 
+                                "closed", "1", "0");
+}
+
+void handle_ac_adapter_state_change(void)
+{
+    write_state_info_in_xenstore(AC_ADAPTER_STATE_FILE_PATH, 
+                     XS_AC_ADAPTER_STATE_PATH, "off-line", "1", "0");
+    xs_write(xs, XBT_NULL, XS_AC_ADAPTER_EVENT_PATH, "1", 1);
+}
+
+void handle_lid_state_change(void)
+{
+    write_state_info_in_xenstore(LID_STATE_FILE_PATH, XS_LID_STATE_PATH, 
+                                "closed", "1", "0");
+    xs_write(xs, XBT_NULL, XS_LID_EVENT_PATH, "1", 1);
+}
+
+void handle_pbtn_pressed_event(void)
+{
+    xs_write(xs, XBT_NULL, XS_PBTN_EVENT_PATH, "1", 1);
+}
+
+void process_acpi_message(char *acpi_buffer)
+{
+    if ( strstr(acpi_buffer, "ac_adapter") )
+    {
+        handle_ac_adapter_state_change();
+        return;
+    }
+
+    if ( strstr(acpi_buffer, "LID") )
+    {
+        handle_lid_state_change();
+        return;
+    }
+
+    if ( strstr(acpi_buffer, "PBTN") )
+        handle_pbtn_pressed_event();
+}
+
+static void *acpi_events_thread(void *arg)
+{
+    int ret;
+    struct sockaddr_un addr;
+    char acpi_buffer[1024];
+
+    socket_fd = socket(PF_UNIX, SOCK_STREAM, 0);
+    if ( socket_fd == -1)
+        return (void *)socket_fd;
+
+    addr.sun_family = AF_UNIX;
+    strncpy(addr.sun_path, ACPID_SOCKET_PATH, strlen(ACPID_SOCKET_PATH)); 
+    addr.sun_path[strlen(ACPID_SOCKET_PATH)] = '\0';
+    ret = connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)); 
+    if ( ret == -1 )
+        return (void *)ret; 
+
+    while( 1 )
+    {
+        memset(acpi_buffer, 0, sizeof(acpi_buffer));
+        ret = recv(socket_fd, acpi_buffer, sizeof(acpi_buffer), 0);
+        if ( ret == 0 )
+            continue;
+
+        process_acpi_message(acpi_buffer);
+    }
+
+    return (void *)1;
+}
+
+void monitor_acpi_events(void)
+{
+    pthread_create(&acpi_thread, NULL, &acpi_events_thread, NULL);
+}
+
+void acpi_events_cleanup(void)
+{
+    if ( socket_fd != -1 )
+        close(socket_fd);
+
+    pthread_cancel(acpi_thread);
+}
+
index d6dd3569165b664f5f983aab260811721cffaa12..2d29c0cc5b20ffc04479714dad91b3fb020a9343 100644 (file)
@@ -84,7 +84,10 @@ struct battery_status {
     unsigned long           present_voltage;
 };
 
-static struct xs_handle *xs;
+struct xs_handle *xs;
+extern void initialize_system_state_info(void);
+extern void monitor_acpi_events(void);
+extern void acpi_events_cleanup(void);
 
 #ifdef RUN_IN_SIMULATE_MODE
     #define BATTERY_DIR_PATH "/tmp/battery"
@@ -321,14 +324,14 @@ int get_next_battery_info_or_status(DIR *battery_dir,
 void print_battery_info(struct battery_info *info)
 {
     printf("present:                %d\n", info->present);
-    printf("design capacity:        %d\n", info->design_capacity);
-    printf("last full capacity:     %d\n", info->last_full_capacity);
+    printf("design capacity:        %d\n", (int) info->design_capacity);
+    printf("last full capacity:     %d\n", (int) info->last_full_capacity);
     printf("battery technology:     %d\n", info->battery_technology);
-    printf("design voltage:         %d\n", info->design_voltage);
-    printf("design capacity warning:%d\n", info->design_capacity_warning);
-    printf("design capacity low:    %d\n", info->design_capacity_low);
-    printf("capacity granularity 1: %d\n", info->capacity_granularity_1);
-    printf("capacity granularity 2: %d\n", info->capacity_granularity_2);
+    printf("design voltage:         %d\n", (int) info->design_voltage);
+    printf("design capacity warning:%d\n", (int) info->design_capacity_warning);
+    printf("design capacity low:    %d\n", (int) info->design_capacity_low);
+    printf("capacity granularity 1: %d\n", (int) info->capacity_granularity_1);
+    printf("capacity granularity 2: %d\n", (int) info->capacity_granularity_2);
     printf("model number:           %s\n", info->model_number);
     printf("serial number:          %s\n", info->serial_number);
     printf("battery type:           %s\n", info->battery_type);
@@ -410,10 +413,11 @@ int write_one_time_battery_info(void)
 void print_battery_status(struct battery_status *status)
 {
     printf("present:                     %d\n", status->present);
-    printf("Battery state                %d\n", status->state);
-    printf("Battery present rate         %d\n", status->present_rate);
-    printf("Battery remining capacity    %d\n", status->remaining_capacity);
-    printf("Battery present voltage      %d\n", status->present_voltage);
+    printf("Battery state                %d\n", (int) status->state);
+    printf("Battery present rate         %d\n", (int) status->present_rate);
+    printf("Battery remining capacity    %d\n", 
+            (int) status->remaining_capacity);
+    printf("Battery present voltage      %d\n", (int) status->present_voltage);
 }
 #endif /*RUN_STANDALONE*/
 
@@ -473,6 +477,7 @@ int wait_for_and_update_battery_status_request(void)
     return ret;
 }
 
+#ifndef RUN_STANDALONE
 /* Borrowed daemonize from xenstored - Initially written by Stevens. */
 static void daemonize(void)
 {
@@ -497,6 +502,7 @@ static void daemonize(void)
 
     umask(0);
 }
+#endif /* RUN_STANDALONE */
 
 int main(int argc, char *argv[])
 {
@@ -507,6 +513,8 @@ int main(int argc, char *argv[])
     if ( xs == NULL ) 
         return -1;
 
+    initialize_system_state_info();
+    monitor_acpi_events();
     if ( write_one_time_battery_info() == 0 ) 
     {
         xs_daemon_close(xs);
@@ -514,6 +522,7 @@ int main(int argc, char *argv[])
     }
 
     wait_for_and_update_battery_status_request();
+    acpi_events_cleanup();
     xs_daemon_close(xs);
     return 0;
 }