acrn-hypervisor/devicemodel/arch/x86/power_button.c
Geoffroy Van Cutsem 8b16be9185 Remove "All rights reserved" string headers
Many of the license and Intel copyright headers include the "All rights
reserved" string. It is not relevant in the context of the BSD-3-Clause
license that the code is released under. This patch removes those strings
throughout the code (hypervisor, devicemodel and misc).

Tracked-On: #7254
Signed-off-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
2022-04-06 13:21:02 +08:00

235 lines
4.8 KiB
C

/*
* Copyright (C) 2019 Intel Corporation.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <sys/cdefs.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdbool.h>
#include <pthread.h>
#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"
#include "mevent.h"
#include "monitor.h"
#include "log.h"
#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"
#define POWER_BUTTON_PNP0C0C_DRV "/sys/bus/acpi/drivers/button/PNP0C0C:00/"
#define POWER_BUTTON_PNP0C0C_DIR POWER_BUTTON_PNP0C0C_DRV"input"
static struct mevent *input_evt0;
static int pwrbtn_fd = -1;
static bool monitor_run;
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;
/*
* The input key defines in input-event-codes.h
* KEY_POWER 116 SC System Power Down
*/
if (ev.code == KEY_POWER && ev.value == 1)
inject_power_button_event(arg);
}
static int
vm_stop_handler(void *arg)
{
if (!arg)
return -EINVAL;
inject_power_button_event(arg);
return 0;
}
static int
vm_suspend_handler(void *arg)
{
/*
* Invoke vm_stop_handler directly in here since suspend of User VM is
* set by User VM power button setting.
*/
return vm_stop_handler(arg);
}
static struct monitor_vm_ops vm_ops = {
.stop = vm_stop_handler,
.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(const char *drv, const char *dir)
{
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(drv, F_OK) != 0)
return -1;
/*
* Scan path to get inputN
* path is /sys/bus/acpi/drivers/button/LNXPWRBN:00/input
*/
ninput = scandir(dir, &input_dirs, input_dir_filter,
alphasort);
if (ninput < 0) {
pr_err("failed to scan power button %s\n",
dir);
goto err;
} else if (ninput == 1) {
rc = snprintf(path, sizeof(path), "%s/%s",
dir, input_dirs[0]->d_name);
if (rc < 0 || rc >= sizeof(path)) {
pr_err("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) {
pr_err("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)) {
pr_err("power button error %d\n", rc);
goto err_input;
}
} else {
pr_err("power button event number error %d\n",
nevent);
goto err_event;
}
} else {
pr_err("power button input number error %d\n", nevent);
goto err_input;
}
/* Open the input device */
fd = open(name, O_RDONLY);
if (fd > 0)
pr_info("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;
}
static int
open_native_power_button()
{
int fd;
/*
* Open fixed power button firstly, if it can't be opened
* try to open control method power button.
*/
fd = open_power_button_input_device(POWER_BUTTON_ACPI_DRV,
POWER_BUTTON_INPUT_DIR);
if (fd < 0)
return open_power_button_input_device(
POWER_BUTTON_PNP0C0C_DRV,
POWER_BUTTON_PNP0C0C_DIR);
else
return fd;
}
void
power_button_init(struct vmctx *ctx)
{
if (input_evt0 == NULL) {
pwrbtn_fd = open_native_power_button();
if (pwrbtn_fd < 0)
pr_err("open power button error=%d\n",
errno);
else
input_evt0 = mevent_add(pwrbtn_fd, EVF_READ,
input_event0_handler, ctx, NULL, NULL);
}
/*
* Suspend or shutdown User VM by acrnctl suspend and
* stop command.
*/
if (monitor_run == false) {
if (monitor_register_vm_ops(&vm_ops, ctx,
POWER_BUTTON_NAME) < 0)
pr_err("failed to register vm ops for power button\n");
else
monitor_run = true;
}
}
void
power_button_deinit(struct vmctx *ctx)
{
if (input_evt0 != NULL) {
mevent_delete_close(input_evt0);
input_evt0 = NULL;
pwrbtn_fd = -1;
}
}