dm: use power button acpi device to find its input event
check the power button acpi driver firstly, then find input event corresponding to the power button. Tracked-On: #2695 Signed-off-by: Yuan Liu <yuan1.liu@intel.com> Acked-by: Yu Wang <yu1.wang@intel.com>
This commit is contained in:
parent
55f52978db
commit
f6a989b7be
|
@ -37,6 +37,9 @@
|
|||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/input.h>
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "vmmapi.h"
|
||||
#include "acpi.h"
|
||||
|
@ -46,8 +49,9 @@
|
|||
#include "lpc.h"
|
||||
#include "monitor.h"
|
||||
|
||||
#define POWER_BUTTON_EVENT 116
|
||||
#define POWER_BUTTON_NAME "power_button"
|
||||
#define POWER_BUTTON_ACPI_DRV "/sys/bus/acpi/drivers/button/LNXPWRBN:00/"
|
||||
#define POWER_BUTTON_INPUT_DIR POWER_BUTTON_ACPI_DRV"input"
|
||||
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
static struct mevent *power_button;
|
||||
static sig_t old_power_handler;
|
||||
|
@ -242,6 +246,7 @@ INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler);
|
|||
static void
|
||||
power_button_press_emulation(struct vmctx *ctx)
|
||||
{
|
||||
printf("%s", "press power button\n");
|
||||
pthread_mutex_lock(&pm_lock);
|
||||
if (!(pm1_status & PM1_PWRBTN_STS)) {
|
||||
pm1_status |= PM1_PWRBTN_STS;
|
||||
|
@ -267,7 +272,11 @@ input_event0_handler(int fd, enum ev_type type, void *arg)
|
|||
if (rc < 0 || rc != sizeof(ev))
|
||||
return;
|
||||
|
||||
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
|
||||
/*
|
||||
* The input key defines in input-event-codes.h
|
||||
* KEY_POWER 116 SC System Power Down
|
||||
*/
|
||||
if (ev.code == KEY_POWER && ev.value == 1)
|
||||
power_button_press_emulation(arg);
|
||||
}
|
||||
|
||||
|
@ -336,6 +345,109 @@ static struct monitor_vm_ops vm_ops = {
|
|||
.suspend = vm_suspend_handler,
|
||||
};
|
||||
|
||||
static int
|
||||
input_dir_filter(const struct dirent *dir)
|
||||
{
|
||||
return !strncmp(dir->d_name, "input", 5);
|
||||
}
|
||||
|
||||
static int
|
||||
event_dir_filter(const struct dirent *dir)
|
||||
{
|
||||
return !strncmp(dir->d_name, "event", 5);
|
||||
}
|
||||
|
||||
static int
|
||||
open_power_button_input_device()
|
||||
{
|
||||
struct dirent **input_dirs = NULL;
|
||||
struct dirent **event_dirs = NULL;
|
||||
int ninput = 0;
|
||||
int nevent = 0;
|
||||
char path[256] = {0};
|
||||
char name[256] = {0};
|
||||
int rc, fd;
|
||||
|
||||
if (access(POWER_BUTTON_ACPI_DRV, F_OK) != 0) {
|
||||
fprintf(stderr, "failed to detect power button driver\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan path to get inputN
|
||||
* path is /sys/bus/acpi/drivers/button/LNXPWRBN:00/input
|
||||
*/
|
||||
ninput = scandir(POWER_BUTTON_INPUT_DIR, &input_dirs, input_dir_filter,
|
||||
alphasort);
|
||||
if (ninput < 0) {
|
||||
fprintf(stderr, "failed to scan power button %s\n",
|
||||
POWER_BUTTON_INPUT_DIR);
|
||||
goto err;
|
||||
} else if (ninput == 1) {
|
||||
rc = snprintf(path, sizeof(path), "%s/%s",
|
||||
POWER_BUTTON_INPUT_DIR, input_dirs[0]->d_name);
|
||||
if (rc < 0 || rc >= sizeof(path)) {
|
||||
fprintf(stderr, "failed to set power button path %d\n",
|
||||
rc);
|
||||
goto err_input;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan path to get eventN
|
||||
* path is /sys/bus/acpi/drivers/button/LNXPWRBN:00/input/inputN
|
||||
*/
|
||||
nevent = scandir(path, &event_dirs, event_dir_filter,
|
||||
alphasort);
|
||||
if (nevent < 0) {
|
||||
fprintf(stderr, "failed to get power button event %s\n",
|
||||
path);
|
||||
goto err_input;
|
||||
} else if (nevent == 1) {
|
||||
|
||||
/* Get the power button input event name */
|
||||
rc = snprintf(name, sizeof(name), "/dev/input/%s",
|
||||
event_dirs[0]->d_name);
|
||||
if (rc < 0 || rc >= sizeof(name)) {
|
||||
fprintf(stderr, "power button error %d\n", rc);
|
||||
goto err_input;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "power button event number error %d\n",
|
||||
nevent);
|
||||
goto err_event;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "power button input number error %d\n", nevent);
|
||||
goto err_input;
|
||||
}
|
||||
|
||||
/* Open the input device */
|
||||
fd = open(name, O_RDONLY);
|
||||
if (fd > 0)
|
||||
printf("Watching power button on %s\n", name);
|
||||
|
||||
while (nevent--)
|
||||
free(event_dirs[nevent]);
|
||||
free(event_dirs);
|
||||
while (ninput--)
|
||||
free(input_dirs[ninput]);
|
||||
free(input_dirs);
|
||||
return fd;
|
||||
|
||||
err_event:
|
||||
while (nevent--)
|
||||
free(event_dirs[nevent]);
|
||||
free(event_dirs);
|
||||
|
||||
err_input:
|
||||
while (ninput--)
|
||||
free(input_dirs[ninput]);
|
||||
free(input_dirs);
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI SMI Command Register
|
||||
*
|
||||
|
@ -371,11 +483,8 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
|
|||
old_power_handler = signal(SIGTERM, SIG_IGN);
|
||||
}
|
||||
if (input_evt0 == NULL) {
|
||||
/*
|
||||
* FIXME: check /sys/bus/acpi/devices/LNXPWRBN\:00/input to
|
||||
* get input event node instead hardcode in here.
|
||||
*/
|
||||
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
|
||||
|
||||
pwrbtn_fd = open_power_button_input_device();
|
||||
if (pwrbtn_fd < 0)
|
||||
fprintf(stderr, "open input event0 error=%d\n",
|
||||
errno);
|
||||
|
|
Loading…
Reference in New Issue