OSDN Git Service

add powerbtnd to simulate long press of power button.
[android-x86/hardware-libhardware_legacy.git] / power / powerbtnd.c
1 /**
2  * A daemon to simulate power button of Android
3  *
4  * Copyright (C) 2011 The Android-x86 Open Source Project
5  *
6  * by Chih-Wei Huang <cwhuang@linux.org.tw>
7  *
8  * Licensed under GPLv2 or later
9  *
10  **/
11
12 #define LOG_TAG "powerbtn"
13
14 #include <sys/stat.h>
15 #include <poll.h>
16 #include <fcntl.h>
17 #include <errno.h>
18 #include <dirent.h>
19 #include <cutils/log.h>
20 #include <linux/input.h>
21 #include <linux/uinput.h>
22
23 const int MAX_POWERBTNS = 3;
24
25 int openfds(struct pollfd pfds[])
26 {
27         int cnt = 0;
28         const char *dirname = "/dev/input";
29         DIR *dir;
30         if ((dir = opendir(dirname))) {
31                 int fd;
32                 struct dirent *de;
33                 while ((de = readdir(dir))) {
34                         if (de->d_name[0] != 'e') // eventX
35                                 continue;
36                         char name[PATH_MAX];
37                         snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
38                         fd = open(name, O_RDWR);
39                         if (fd < 0) {
40                                 LOGE("could not open %s, %s", name, strerror(errno));
41                                 continue;
42                         }
43                         name[sizeof(name) - 1] = '\0';
44                         if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
45                                 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
46                                 name[0] = '\0';
47                         }
48
49                         // TODO: parse /etc/excluded-input-devices.xml
50                         if (!strcmp(name, "Power Button")) {
51                                 LOGI("open %s(%s) ok", de->d_name, name);
52                                 pfds[cnt].events = POLLIN;
53                                 pfds[cnt++].fd = fd;
54                                 if (cnt < MAX_POWERBTNS)
55                                         continue;
56                                 else
57                                         break;
58                         }
59                         close(fd);
60                 }
61                 closedir(dir);
62         }
63
64         return cnt;
65 }
66
67 int main()
68 {
69         struct pollfd pfds[MAX_POWERBTNS];
70         int cnt = openfds(pfds);
71         int pollres;
72
73         int ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);
74         if (ufd >= 0) {
75                 struct uinput_user_dev ud;
76                 memset(&ud, 0, sizeof(ud));
77                 strcpy(ud.name, "Android Power Button");
78                 write(ufd, &ud, sizeof(ud));
79                 ioctl(ufd, UI_SET_EVBIT, EV_KEY);
80                 ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
81                 ioctl(ufd, UI_DEV_CREATE, 0);
82         } else {
83                 LOGE("could not open uinput device: %s", strerror(errno));
84                 return -1;
85         }
86
87         while ((pollres = poll(pfds, cnt, -1))) {
88                 int i;
89                 if (pollres < 0) {
90                         LOGE("poll error: %s", strerror(errno));
91                         break;
92                 }
93                 for (i = 0; i < cnt; ++i) {
94                         if (pfds[i].revents & POLLIN) {
95                                 struct input_event iev;
96                                 size_t res = read(pfds[i].fd, &iev, sizeof(iev));
97                                 if (res < sizeof(iev)) {
98                                         LOGW("insufficient input data(%d)? fd=%d", res, pfds[i].fd);
99                                         continue;
100                                 }
101                                 LOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
102                                 if (iev.type == EV_KEY) {
103                                         switch (iev.code)
104                                         {
105                                                 case KEY_POWER:
106                                                         if (!iev.value)
107                                                                 sleep(2);
108                                                         break;
109                                         }
110                                 }
111
112                                 write(ufd, &iev, sizeof(iev));
113                         }
114                 }
115         }
116
117         return 0;
118 }