mirror of
https://github.com/projectacrn/acrn-hypervisor.git
synced 2025-08-22 10:00:47 +00:00
Rename SOS_VM_NUM to SERVICE_VM_NUM. rename SOS_SOCKET_PORT to SERVICE_VM_SOCKET_PORT. rename PROCESS_RUN_IN_SOS to PROCESS_RUN_IN_SERVICE_VM. rename PCI_DEV_TYPE_SOSEMUL to PCI_DEV_TYPE_SERVICE_VM_EMUL. rename SHUTDOWN_REQ_FROM_SOS to SHUTDOWN_REQ_FROM_SERVICE_VM. rename PROCESS_RUN_IN_SOS to PROCESS_RUN_IN_SERVICE_VM. rename SHUTDOWN_REQ_FROM_UOS to SHUTDOWN_REQ_FROM_USER_VM. rename UOS_SOCKET_PORT to USER_VM_SOCKET_PORT. rename SOS_CONSOLE to SERVICE_VM_OS_CONSOLE. rename SOS_LCS_SOCK to SERVICE_VM_LCS_SOCK. rename SOS_VM_BOOTARGS to SERVICE_VM_OS_BOOTARGS. rename SOS_ROOTFS to SERVICE_VM_ROOTFS. rename SOS_IDLE to SERVICE_VM_IDLE. rename SEVERITY_SOS to SEVERITY_SERVICE_VM. rename SOS_VM_UUID to SERVICE_VM_UUID. rename SOS_REQ to SERVICE_VM_REQ. rename RTCT_NATIVE_FILE_PATH_IN_SOS to RTCT_NATIVE_FILE_PATH_IN_SERVICE_VM. rename CBC_REQ_T_UOS_ACTIVE to CBC_REQ_T_USER_VM_ACTIVE. rename CBC_REQ_T_UOS_INACTIVE to CBC_REQ_T_USER_VM_INACTIV. rename uos_active to user_vm_active. Tracked-On: #6744 Signed-off-by: Liu Long <long.liu@linux.intel.com> Reviewed-by: Geoffroy Van Cutsem <geoffroy.vancutsem@intel.com>
235 lines
4.8 KiB
C
235 lines
4.8 KiB
C
/*
|
|
* Copyright (C) 2019 Intel Corporation. All rights reserved.
|
|
*
|
|
* 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;
|
|
}
|
|
}
|