Guest User

powerbtnd

a guest
Aug 19th, 2012
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.15 KB | None | 0 0
  1. /**
  2.  * A daemon to simulate power button of Android
  3.  *
  4.  * Copyright (C) 2011-2012 The Android-x86 Open Source Project
  5.  *
  6.  * by Chih-Wei Huang <[email protected]>
  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. #include <cutils/properties.h>
  23.  
  24. const int MAX_POWERBTNS = 3;
  25.  
  26. int openfds(struct pollfd pfds[])  //парсит /dev/input и выбирает девайс по его имени
  27. {
  28.     int cnt = 0;
  29.     const char *dirname = "/dev/input";
  30.     DIR *dir;
  31.     if ((dir = opendir(dirname))) {
  32.         int fd;
  33.         struct dirent *de;
  34.         while ((de = readdir(dir))) {
  35.             if (de->d_name[0] != 'e') // eventX
  36.                 continue;
  37.             char name[PATH_MAX];
  38.             snprintf(name, PATH_MAX, "%s/%s", dirname, de->d_name);
  39.             fd = open(name, O_RDWR | O_NONBLOCK);
  40.             if (fd < 0) {
  41.                 LOGE("could not open %s, %s", name, strerror(errno));
  42.                 continue;
  43.             }
  44.             name[sizeof(name) - 1] = '\0';
  45.             if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
  46.                 LOGE("could not get device name for %s, %s\n", name, strerror(errno));
  47.                 name[0] = '\0';
  48.             }
  49.  
  50.             // TODO: parse /etc/excluded-input-devices.xml
  51.             if (!strcmp(name, "NVEC power button")) {
  52.                 LOGI("open %s(%s) ok", de->d_name, name);
  53.                 pfds[cnt].events = POLLIN;
  54.                 pfds[cnt++].fd = fd;
  55.                 if (cnt < MAX_POWERBTNS)
  56.                     continue;
  57.                 else
  58.                     break;
  59.             }
  60.             close(fd);
  61.         }
  62.         closedir(dir);
  63.     }
  64.  
  65.     return cnt;
  66. }
  67.  
  68. void send_power(int ufd, int down)  // пишет в девайс нажатия клавиш и SYN_REPORT - SYN_REPORT типа системное имя..больше в тексте не фигурирует
  69. {
  70.     struct input_event iev;
  71.     iev.type  = EV_KEY;
  72.     iev.code  = KEY_POWER;
  73.     iev.value = down;   // если функцию вызвали как send_power(ufd,1) то в iev.value попадает 1
  74.     write(ufd, &iev, sizeof(iev)); // тут идет запись в наш инпут девайс всей перемной iev (до этого мы объявили ее как перемную типа input_event с 3 параметрами тип код и value(соответствует нажатию) )
  75.     iev.type  = EV_SYN;
  76.     iev.code  = SYN_REPORT;
  77.     iev.value = 0;
  78.     write(ufd, &iev, sizeof(iev));
  79. }
  80.  
  81. void simulate_powerkey(int ufd, int longpress)
  82. {
  83.     send_power(ufd, 1);
  84.     if (longpress)
  85.         sleep(2);
  86.     send_power(ufd, 0);
  87. }
  88.  
  89. int main() // главная функция с нее начинается работа этого кода
  90. {
  91.     struct pollfd pfds[MAX_POWERBTNS];  
  92.     int cnt = openfds(pfds);  // вызывается функция открытия нашего инпут девайса
  93.     int timeout = -1;  // таймаут выстанавливается в -1 чтобы не было путаницы в будущем
  94.     char prop[PROPERTY_VALUE_MAX];
  95.  
  96.     int ufd = open("/dev/uinput", O_WRONLY | O_NDELAY);  // какой то код для работы с андроидом.. по сути нам не важен =)
  97.     if (ufd >= 0) {
  98.         struct uinput_user_dev ud;
  99.         memset(&ud, 0, sizeof(ud));
  100.         strcpy(ud.name, "Android Power Button");
  101.         write(ufd, &ud, sizeof(ud));
  102.         ioctl(ufd, UI_SET_EVBIT, EV_KEY);
  103.         ioctl(ufd, UI_SET_KEYBIT, KEY_POWER);
  104.         ioctl(ufd, UI_DEV_CREATE, 0);
  105.     } else {
  106.         LOGE("could not open uinput device: %s", strerror(errno));
  107.         return -1;
  108.     }
  109.  
  110.     property_get("poweroff.doubleclick", prop, NULL);  // получение от андроида события даблклика
  111.  
  112.     for (;;) {
  113.         int i;
  114.         int pollres = poll(pfds, cnt, timeout) ;  // в таймаут пишет функция poll ..видимо она знает время между событиями
  115.         LOGV("pollres=%d %d\n", pollres, timeout);
  116.         if (pollres < 0) {
  117.             LOGE("poll error: %s", strerror(errno));
  118.             break;
  119.         }
  120.         if (pollres == 0) { // timeout, send one power key
  121.             simulate_powerkey(ufd, 0);
  122.             timeout = -1;
  123.             continue;
  124.         }
  125.         for (i = 0; i < cnt; ++i) {
  126.             if (pfds[i].revents & POLLIN) {  // проверка что эта клавиша нажимается не в первые как я понял
  127.                 struct input_event iev;
  128.                 size_t res = read(pfds[i].fd, &iev, sizeof(iev));
  129.                 if (res < sizeof(iev)) {
  130.                     LOGW("insufficient input data(%d)? fd=%d", res, pfds[i].fd);
  131.                     continue;
  132.                 }
  133.                 LOGV("type=%d scancode=%d value=%d from fd=%d", iev.type, iev.code, iev.value, pfds[i].fd);
  134.                 if (iev.type == EV_KEY && iev.code == KEY_POWER && !iev.value) {  // проверка что нажатая клавиша именно KEY_POWER и что она была отпущена
  135.                     if (prop[0] != '1' || timeout > 0) {
  136.                         simulate_powerkey(ufd, 1);  // симулируем нажатие с 1 в качестве longpress - т.е в функции simulate_powerkey будет сделан слиип на 2 секунды между событиями нажатия и отпускания
  137.                         timeout = -1; // сбрасываем таймаут
  138.                     } else {
  139.                         timeout = 1000; // one second
  140.                     }
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146.     return 0;
  147. }
Advertisement
Add Comment
Please, Sign In to add comment