Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * A daemon to simulate power button of Android
- *
- * Copyright (C) 2011-2012 The Android-x86 Open Source Project
- *
- * by Chih-Wei Huang <[email protected]>
- *
- * Licensed under GPLv2 or later
- *
- **/
- #define LOG_TAG "powerbtn"
- #include <sys/stat.h>
- #include <poll.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <dirent.h>
- #include <cutils/log.h>
- #include <linux/input.h>
- #include <linux/uinput.h>
- #include <cutils/properties.h>
- const int MAX_POWERBTNS = 3;
- int openfds(struct pollfd pfds[]) //парсит /dev/input и выбирает девайс по его имени
- {
- int cnt = 0;
- const char *dirname = "/dev/input";
- DIR *dir;
- if ((dir = opendir(dirname))) {
- int fd;
- struct dirent *de;
- while ((de = readdir(dir))) {
- if (de->d_name[0] != 'e') // eventX
- continue;
- char name[PATH_MAX];
- snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
- fd = open(name, O_RDWR | O_NONBLOCK);
- if (fd < 0) {
- LOGE("could not open %s, %s", name, strerror(errno));
- continue;
- }
- name[sizeof(name) - 1] = '\0';
- if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
- LOGE("could not get device name for %s, %s\n", name, strerror(errno));
- name[0] = '\0';
- }
- // TODO: parse /etc/excluded-input-devices.xml
- if (!strcmp(name, "NVEC power button")) {
- LOGI("open %s(%s) ok", de->d_name, name);
- pfds[cnt].events = POLLIN;
- pfds[cnt++].fd = fd;
- if (cnt < MAX_POWERBTNS)
- continue;
- else
- break;
- }
- close(fd);
- }
- closedir(dir);
- }
- return cnt;
- }
- void send_power(int ufd, int down) // пишет в девайс нажатия клавиш и SYN_REPORT - SYN_REPORT типа системное имя..больше в тексте не фигурирует
- {
- struct input_event iev;
- iev.type = EV_KEY;
- iev.code = KEY_POWER;
- iev.value = down; // если функцию вызвали как send_power(ufd,1) то в iev.value попадает 1
- write(ufd, &iev, sizeof(iev)); // тут идет запись в наш инпут девайс всей перемной iev (до этого мы объявили ее как перемную типа input_event с 3 параметрами тип код и value(соответствует нажатию) )
- iev.type = EV_SYN;
- iev.code = SYN_REPORT;
- iev.value = 0;
- write(ufd, &iev, sizeof(iev));
- }
- void simulate_powerkey(int ufd, int longpress)
- {
- send_power(ufd, 1);
- if (longpress)
- sleep(2);
- send_power(ufd, 0);
- }
- int main() // главная функция с нее начинается работа этого кода
- {
- struct pollfd pfds[MAX_POWERBTNS];
- int cnt = openfds(pfds); // вызывается функция открытия нашего инпут девайса
- int timeout = -1; // таймаут выстанавливается в -1 чтобы не было путаницы в будущем
- char prop[PROPERTY_VALUE_MAX];
- int ufd = open("/dev/uinput", O_WRONLY | O_NDELAY); // какой то код для работы с андроидом.. по сути нам не важен =)
- if (ufd >= 0) {
- struct uinput_user_dev ud;
- memset(&ud, 0, sizeof(ud));
- strcpy(ud.name, "Android Power Button");
- write(ufd, &ud, sizeof(ud));
- ioctl(ufd, UI_SET_EVBIT, EV_KEY);
- ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
- ioctl(ufd, UI_DEV_CREATE, 0);
- } else {
- LOGE("could not open uinput device: %s", strerror(errno));
- return -1;
- }
- property_get("poweroff.doubleclick", prop, NULL); // получение от андроида события даблклика
- for (;;) {
- int i;
- int pollres = poll(pfds, cnt, timeout) ; // в таймаут пишет функция poll ..видимо она знает время между событиями
- LOGV("pollres=%d %d\n", pollres, timeout);
- if (pollres < 0) {
- LOGE("poll error: %s", strerror(errno));
- break;
- }
- if (pollres == 0) { // timeout, send one power key
- simulate_powerkey(ufd, 0);
- timeout = -1;
- continue;
- }
- for (i = 0; i < cnt; ++i) {
- if (pfds[i].revents & POLLIN) { // проверка что эта клавиша нажимается не в первые как я понял
- struct input_event iev;
- size_t res = read(pfds[i].fd, &iev, sizeof(iev));
- if (res < sizeof(iev)) {
- LOGW("insufficient input data(%d)? fd=%d", res, pfds[i].fd);
- continue;
- }
- LOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
- if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) { // проверка что нажатая клавиша именно KEY_POWER и что она была отпущена
- if (prop[0] != '1' || timeout > 0) {
- simulate_powerkey(ufd, 1); // симулируем нажатие с 1 в качестве longpress - т.е в функции simulate_powerkey будет сделан слиип на 2 секунды между событиями нажатия и отпускания
- timeout = -1; // сбрасываем таймаут
- } else {
- timeout = 1000; // one second
- }
- }
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment