Skip to content

Commit 8e8ed07

Browse files
yliu80acrnsi
authored andcommitted
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>
1 parent b24a8a0 commit 8e8ed07

File tree

1 file changed

+41
-0
lines changed
  • devicemodel/arch/x86

1 file changed

+41
-0
lines changed

devicemodel/arch/x86/pm.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@
3434
#include <signal.h>
3535
#include <stdbool.h>
3636
#include <pthread.h>
37+
#include <unistd.h>
38+
#include <fcntl.h>
39+
#include <linux/input.h>
3740

3841
#include "vmmapi.h"
3942
#include "acpi.h"
@@ -42,10 +45,13 @@
4245
#include "irq.h"
4346
#include "lpc.h"
4447

48+
#define POWER_BUTTON_EVENT 116
4549
static pthread_mutex_t pm_lock = PTHREAD_MUTEX_INITIALIZER;
4650
static struct mevent *power_button;
4751
static sig_t old_power_handler;
4852

53+
static struct mevent *input_evt0;
54+
static int pwrbtn_fd = -1;
4955
/*
5056
* Reset Control register at I/O port 0xcf9. Bit 2 forces a system
5157
* 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)
224230
pthread_mutex_unlock(&pm_lock);
225231
}
226232

233+
static void
234+
input_event0_handler(int fd, enum ev_type type, void *arg)
235+
{
236+
struct input_event ev;
237+
int rc;
238+
239+
rc = read(fd, &ev, sizeof(ev));
240+
if (rc < 0 || rc != sizeof(ev))
241+
return;
242+
243+
if (ev.code == POWER_BUTTON_EVENT && ev.value == 1)
244+
power_button_handler(fd, type, arg);
245+
}
246+
227247
/*
228248
* Power Management 1 Control Register
229249
*
@@ -295,10 +315,26 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
295315
case ACPI_ENABLE:
296316
pm1_control |= PM1_SCI_EN;
297317
if (power_button == NULL) {
318+
319+
/*
320+
* TODO: For the SIGTERM, IOC mediator also needs to
321+
* support it, and SIGTERM handler needs to be written
322+
* as one common interface for both APCI power button
323+
* and IOC mediator in future.
324+
*/
298325
power_button = mevent_add(SIGTERM, EVF_SIGNAL,
299326
power_button_handler, ctx, NULL, NULL);
300327
old_power_handler = signal(SIGTERM, SIG_IGN);
301328
}
329+
if (input_evt0 == NULL) {
330+
pwrbtn_fd = open("/dev/input/event0", O_RDONLY);
331+
if (pwrbtn_fd < 0)
332+
fprintf(stderr, "open input event0 error=%d\n",
333+
errno);
334+
else
335+
input_evt0 = mevent_add(pwrbtn_fd, EVF_READ,
336+
input_event0_handler, ctx, NULL, NULL);
337+
}
302338
break;
303339
case ACPI_DISABLE:
304340
pm1_control &= ~PM1_SCI_EN;
@@ -307,6 +343,11 @@ smi_cmd_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes,
307343
power_button = NULL;
308344
signal(SIGTERM, old_power_handler);
309345
}
346+
if (input_evt0 != NULL) {
347+
mevent_delete_close(input_evt0);
348+
input_evt0 = NULL;
349+
pwrbtn_fd = -1;
350+
}
310351
break;
311352
}
312353
pthread_mutex_unlock(&pm_lock);

0 commit comments

Comments
 (0)