Skip to content

Commit f6a989b

Browse files
yliu80wenlingz
authored andcommitted
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>
1 parent 55f5297 commit f6a989b

File tree

1 file changed

+116
-7
lines changed
  • devicemodel/arch/x86

1 file changed

+116
-7
lines changed

devicemodel/arch/x86/pm.c

Lines changed: 116 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@
3737
#include <unistd.h>
3838
#include <fcntl.h>
3939
#include <linux/input.h>
40+
#include <dirent.h>
41+
#include <string.h>
42+
#include <stdlib.h>
4043

4144
#include "vmmapi.h"
4245
#include "acpi.h"
@@ -46,8 +49,9 @@
4649
#include "lpc.h"
4750
#include "monitor.h"
4851

49-
#define POWER_BUTTON_EVENT 116
5052
#define POWER_BUTTON_NAME "power_button"
53+
#define POWER_BUTTON_ACPI_DRV "/sys/bus/acpi/drivers/button/LNXPWRBN:00/"
54+
#define POWER_BUTTON_INPUT_DIR POWER_BUTTON_ACPI_DRV"input"
5155
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
5256
static struct mevent *power_button;
5357
static sig_t old_power_handler;
@@ -242,6 +246,7 @@ INOUT_PORT(pm1_enable, PM1A_EVT_ADDR + 2, IOPORT_F_INOUT, pm1_enable_handler);
242246
static void
243247
power_button_press_emulation(struct vmctx *ctx)
244248
{
249+
printf("%s", "press power button\n");
245250
pthread_mutex_lock(&pm_lock);
246251
if (!(pm1_status & PM1_PWRBTN_STS)) {
247252
pm1_status |= PM1_PWRBTN_STS;
@@ -267,7 +272,11 @@ input_event0_handler(int fd, enum ev_type type, void *arg)
267272
if (rc < 0 || rc != sizeof(ev))
268273
return;
269274

270-
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
275+
/*
276+
* The input key defines in input-event-codes.h
277+
* KEY_POWER 116 SC System Power Down
278+
*/
279+
if (ev.code == KEY_POWER && ev.value == 1)
271280
power_button_press_emulation(arg);
272281
}
273282

@@ -336,6 +345,109 @@ static struct monitor_vm_ops vm_ops = {
336345
.suspend = vm_suspend_handler,
337346
};
338347

348+
static int
349+
input_dir_filter(const struct dirent *dir)
350+
{
351+
return !strncmp(dir->d_name, "input", 5);
352+
}
353+
354+
static int
355+
event_dir_filter(const struct dirent *dir)
356+
{
357+
return !strncmp(dir->d_name, "event", 5);
358+
}
359+
360+
static int
361+
open_power_button_input_device()
362+
{
363+
struct dirent **input_dirs = NULL;
364+
struct dirent **event_dirs = NULL;
365+
int ninput = 0;
366+
int nevent = 0;
367+
char path[256] = {0};
368+
char name[256] = {0};
369+
int rc, fd;
370+
371+
if (access(POWER_BUTTON_ACPI_DRV, F_OK) != 0) {
372+
fprintf(stderr, "failed to detect power button driver\n");
373+
return -1;
374+
}
375+
376+
/*
377+
* Scan path to get inputN
378+
* path is /sys/bus/acpi/drivers/button/LNXPWRBN:00/input
379+
*/
380+
ninput = scandir(POWER_BUTTON_INPUT_DIR, &input_dirs, input_dir_filter,
381+
alphasort);
382+
if (ninput < 0) {
383+
fprintf(stderr, "failed to scan power button %s\n",
384+
POWER_BUTTON_INPUT_DIR);
385+
goto err;
386+
} else if (ninput == 1) {
387+
rc = snprintf(path, sizeof(path), "%s/%s",
388+
POWER_BUTTON_INPUT_DIR, input_dirs[0]->d_name);
389+
if (rc < 0 || rc >= sizeof(path)) {
390+
fprintf(stderr, "failed to set power button path %d\n",
391+
rc);
392+
goto err_input;
393+
}
394+
395+
/*
396+
* Scan path to get eventN
397+
* path is /sys/bus/acpi/drivers/button/LNXPWRBN:00/input/inputN
398+
*/
399+
nevent = scandir(path, &event_dirs, event_dir_filter,
400+
alphasort);
401+
if (nevent < 0) {
402+
fprintf(stderr, "failed to get power button event %s\n",
403+
path);
404+
goto err_input;
405+
} else if (nevent == 1) {
406+
407+
/* Get the power button input event name */
408+
rc = snprintf(name, sizeof(name), "/dev/input/%s",
409+
event_dirs[0]->d_name);
410+
if (rc < 0 || rc >= sizeof(name)) {
411+
fprintf(stderr, "power button error %d\n", rc);
412+
goto err_input;
413+
}
414+
} else {
415+
fprintf(stderr, "power button event number error %d\n",
416+
nevent);
417+
goto err_event;
418+
}
419+
} else {
420+
fprintf(stderr, "power button input number error %d\n", nevent);
421+
goto err_input;
422+
}
423+
424+
/* Open the input device */
425+
fd = open(name, O_RDONLY);
426+
if (fd > 0)
427+
printf("Watching power button on %s\n", name);
428+
429+
while (nevent--)
430+
free(event_dirs[nevent]);
431+
free(event_dirs);
432+
while (ninput--)
433+
free(input_dirs[ninput]);
434+
free(input_dirs);
435+
return fd;
436+
437+
err_event:
438+
while (nevent--)
439+
free(event_dirs[nevent]);
440+
free(event_dirs);
441+
442+
err_input:
443+
while (ninput--)
444+
free(input_dirs[ninput]);
445+
free(input_dirs);
446+
447+
err:
448+
return -1;
449+
}
450+
339451
/*
340452
* ACPI SMI Command Register
341453
*
@@ -371,11 +483,8 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
371483
old_power_handler = signal(SIGTERM, SIG_IGN);
372484
}
373485
if (input_evt0 == NULL) {
374-
/*
375-
* FIXME: check /sys/bus/acpi/devices/LNXPWRBN\:00/input to
376-
* get input event node instead hardcode in here.
377-
*/
378-
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
486+
487+
pwrbtn_fd = open_power_button_input_device();
379488
if (pwrbtn_fd < 0)
380489
fprintf(stderr, "open input event0 error=%d\n",
381490
errno);

0 commit comments

Comments
 (0)