dm: implement power button for power managerment

Listen to power button state via /dev/input/event0. When the power
button is pressed, then set PWRBTN_STS bit. If PWRBTN_EN is set, the
sci interrupt is triggered.

For suspend or shutdown of UOS by power button, needs UOS to configure
the default behavior of the power button.

Tracked-On: #2560
Signed-off-by: Yuan Liu <yuan1.liu@intel.com>
Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
Yuan Liu 2019-02-12 20:02:53 +08:00 committed by ACRN System Integration
parent b24a8a0f59
commit 8e8ed07dd7
1 changed files with 41 additions and 0 deletions

View File

@ -34,6 +34,9 @@
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>
#include "vmmapi.h"
#include "acpi.h"
@ -42,10 +45,13 @@
#include "irq.h"
#include "lpc.h"
#define POWER_BUTTON_EVENT 116
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
static struct mevent *power_button;
static sig_t old_power_handler;
static struct mevent *input_evt0;
static int pwrbtn_fd = -1;
/*
* Reset Control register at I/O port 0xcf9. Bit 2 forces a system
* reset when it transitions from 0 to 1. Bit 1 selects the type of
@ -224,6 +230,20 @@ power_button_handler(int signal, enum ev_type type, void *arg)
pthread_mutex_unlock(&pm_lock);
}
static void
input_event0_handler(int fd, enum ev_type type, void *arg)
{
struct input_event ev;
int rc;
rc = read(fd, &ev, sizeof(ev));
if (rc < 0 || rc != sizeof(ev))
return;
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
power_button_handler(fd, type, arg);
}
/*
* Power Management 1 Control Register
*
@ -295,10 +315,26 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
case ACPI_ENABLE:
pm1_control |= PM1_SCI_EN;
if (power_button == NULL) {
/*
* TODO: For the SIGTERM, IOC mediator also needs to
* support it, and SIGTERM handler needs to be written
* as one common interface for both APCI power button
* and IOC mediator in future.
*/
power_button = mevent_add(SIGTERM, EVF_SIGNAL,
power_button_handler, ctx, NULL, NULL);
old_power_handler = signal(SIGTERM, SIG_IGN);
}
if (input_evt0 == NULL) {
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
if (pwrbtn_fd < 0)
fprintf(stderr, "open input event0 error=%d\n",
errno);
else
input_evt0 = mevent_add(pwrbtn_fd, EVF_READ,
input_event0_handler, ctx, NULL, NULL);
}
break;
case ACPI_DISABLE:
pm1_control &= ~PM1_SCI_EN;
@ -307,6 +343,11 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
power_button = NULL;
signal(SIGTERM, old_power_handler);
}
if (input_evt0 != NULL) {
mevent_delete_close(input_evt0);
input_evt0 = NULL;
pwrbtn_fd = -1;
}
break;
}
pthread_mutex_unlock(&pm_lock);