blob: 617e6f95c0d924de9531a19bd2876ff59f81965f [file] [log] [blame]
Lianghu Sue1655222017-05-24 14:52:06 +08001#include <errno.h>
2#include <fcntl.h>
3#include <stdint.h>
4#include <linux/input.h>
5#include <pthread.h>
6#include <stdarg.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/stat.h>
11#include <sys/time.h>
12#include <sys/types.h>
13#include <time.h>
14#include <unistd.h>
15#include <ctype.h>
16#include "events.h"
17#include "events_process.h"
18
19#define WAIT_KEY_TIMEOUT_SEC 120
20#define nullptr NULL
Lianghu Su53dd4072017-05-26 19:04:48 +080021#define KEY_EVENT_TIME_INTERVAL 20
Lianghu Sue1655222017-05-24 14:52:06 +080022
Renjun Xu044c8ec2017-08-17 19:01:14 +080023EventsProcess:: KeyMapItem_t g_default_keymap[] = {
24 { "power", KEY_POWER },
25 { "down", KEY_DOWN },
26 { "up", KEY_UP },
27};
Lianghu Sue1655222017-05-24 14:52:06 +080028
29EventsProcess::EventsProcess()
30 : key_queue_len(0),
31 key_last_down(-1),
Lianghu Sue1655222017-05-24 14:52:06 +080032 last_key(-1),
Renjun Xu044c8ec2017-08-17 19:01:14 +080033 key_down_count(0),
34 report_longpress_flag(false),
Lianghu Sue1655222017-05-24 14:52:06 +080035 num_keys(0),
36 keys_map(NULL) {
37 pthread_mutex_init(&key_queue_mutex, nullptr);
38 pthread_cond_init(&key_queue_cond, nullptr);
39 memset(key_pressed, 0, sizeof(key_pressed));
Lianghu Su53dd4072017-05-26 19:04:48 +080040 memset(&last_queue_time, 0, sizeof(last_queue_time));
Lianghu Sue1655222017-05-24 14:52:06 +080041 load_key_map();
42}
43
Lianghu Sue1655222017-05-24 14:52:06 +080044
45int EventsProcess::InputCallback(int fd, uint32_t epevents, void* data) {
46 return reinterpret_cast<EventsProcess*>(data)->OnInputEvent(fd, epevents);
47}
48
Lianghu Sue1655222017-05-24 14:52:06 +080049static void* InputThreadLoop(void*) {
50 while (true) {
51 if (!ev_wait(-1)) {
52 ev_dispatch();
53 }
54 }
55 return nullptr;
56}
57
58void EventsProcess::Init() {
59 ev_init(InputCallback, this);
60
61 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
62}
63
64int EventsProcess::OnInputEvent(int fd, uint32_t epevents) {
65 struct input_event ev;
66
67 if (ev_get_input(fd, epevents, &ev) == -1) {
68 return -1;
69 }
70
71 if (ev.type == EV_SYN) {
72 return 0;
73 }
74
75 if (ev.type == EV_KEY && ev.code <= KEY_MAX) {
Renjun Xu044c8ec2017-08-17 19:01:14 +080076
Lianghu Sue1655222017-05-24 14:52:06 +080077 int code = getMapKey(ev.code);
78 if (code > 0) {
79 ProcessKey(code, ev.value);
80 } else {
81 ProcessKey(ev.code, ev.value);
82 }
83 }
84
85 return 0;
86}
87
jiacai.liu7c96e572019-11-28 14:09:36 +080088/* use CLOCK_MONOTONIC clock, gettimeofday will overlap if ntp changes */
89uint64_t EventsProcess::getSystemTimeUs() {
90 struct timespec ts;
91
92 clock_gettime(CLOCK_MONOTONIC, &ts);
93 return (ts.tv_sec)*1000000LL + ts.tv_nsec/1000LL;
94}
95
Lianghu Sue1655222017-05-24 14:52:06 +080096void EventsProcess::ProcessKey(int key_code, int value) {
97 bool register_key = false;
ziheng.li413496c2021-11-19 10:56:55 +080098 bool flag = false;
Lianghu Sue1655222017-05-24 14:52:06 +080099 pthread_mutex_lock(&key_queue_mutex);
100 key_pressed[key_code] = value;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800101 if (value == 1) {/*1:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800102 KeyEvent *ke = new KeyEvent;
103 ke->down_ts_us = getSystemTimeUs();
104 ke->keyCode = key_code;
105 ke->keyState = value; /*key down*/
106 ke->longPress = false;
ziheng.li413496c2021-11-19 10:56:55 +0800107 ke->curlongPress = false;
jiacai.liu7c96e572019-11-28 14:09:36 +0800108 mKeyEventVec.push_back(ke);
109
Lianghu Sue1655222017-05-24 14:52:06 +0800110 ++key_down_count;
111 key_last_down = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800112 key_timer_t* info = new key_timer_t;
113 info->ep = this;
114 info->key_code = key_code;
115 info->count = key_down_count;
jiacai.liu7c96e572019-11-28 14:09:36 +0800116 info->ke = ke;
Lianghu Sue1655222017-05-24 14:52:06 +0800117 pthread_t thread;
118 pthread_create(&thread, nullptr, &EventsProcess::time_key_helper, info);
119 pthread_detach(thread);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800120 } else if(value == 2){/*2:key repeat*/
121 } else {/*0:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800122 for (std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
123 iter != mKeyEventVec.end(); ++iter) {
124 if ((*iter)->keyCode == key_code && (*iter)->keyState == 1) {
125 (*iter)->up_ts_us = getSystemTimeUs();
126 (*iter)->keyState = value; /*key up*/
ziheng.li413496c2021-11-19 10:56:55 +0800127 if ((*iter)->longPress || (*iter)->curlongPress) {
128 (*iter)->curlongPress = false;
129 flag = true;
130 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800131 break;
132 }
133 }
134
Lianghu Sue1655222017-05-24 14:52:06 +0800135 if (key_last_down == key_code) {
Lianghu Sue1655222017-05-24 14:52:06 +0800136 register_key = true;
137 }
138 key_last_down = -1;
139 }
140 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800141 last_key = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800142 if (register_key) {
ziheng.li413496c2021-11-19 10:56:55 +0800143 EnqueueKey(key_code, flag);
Lianghu Sue1655222017-05-24 14:52:06 +0800144 }
145}
146
147void* EventsProcess::time_key_helper(void* cookie) {
148 key_timer_t* info = (key_timer_t*) cookie;
jiacai.liu7c96e572019-11-28 14:09:36 +0800149 info->ep->time_key(info);
Lianghu Sue1655222017-05-24 14:52:06 +0800150 delete info;
151 return nullptr;
152}
153
jiacai.liu7c96e572019-11-28 14:09:36 +0800154void EventsProcess::time_key(key_timer_t *info) {
155 int key_code = info->key_code;
156 int count = info->count;
ziheng.li413496c2021-11-19 10:56:55 +0800157 int keymode = getKeyMode(key_code);
Lianghu Sue1655222017-05-24 14:52:06 +0800158 usleep(750000); // 750 ms == "long"
Lianghu Sue1655222017-05-24 14:52:06 +0800159 pthread_mutex_lock(&key_queue_mutex);
160 if (key_last_down == key_code && key_down_count == count) {
ziheng.li413496c2021-11-19 10:56:55 +0800161 if (info->ke) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800162 info->ke->longPress = true;
ziheng.li413496c2021-11-19 10:56:55 +0800163 if (keymode != 0)
164 info->ke->curlongPress = true;
165 }
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800166 else {
167 printf("##recive key but no events##\n");
168 pthread_mutex_unlock(&key_queue_mutex);
169 return;
170 }
Lianghu Sue1655222017-05-24 14:52:06 +0800171 }
ziheng.li413496c2021-11-19 10:56:55 +0800172 if (info->ke->longPress && info->ke->curlongPress) {
173 pthread_mutex_unlock(&key_queue_mutex);
174 while (key_last_down == key_code && key_down_count == count) {
175 EnqueueKey(key_code, false);
176 }
177 } else {
178 pthread_mutex_unlock(&key_queue_mutex);
179 }
Lianghu Sue1655222017-05-24 14:52:06 +0800180}
181
Lianghu Sue1655222017-05-24 14:52:06 +0800182
Renjun Xu044c8ec2017-08-17 19:01:14 +0800183const char* EventsProcess::getKeyType(int key) {
184 int i;
185 for (i = 0; i < num_keys; i++) {
186 KeyMapItem_t* v = &keys_map[i];
187 if (v->value == key)
188 return v->type;
Lianghu Sue1655222017-05-24 14:52:06 +0800189 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800190
191 return NULL;
Lianghu Sue1655222017-05-24 14:52:06 +0800192}
193
ziheng.li413496c2021-11-19 10:56:55 +0800194int EventsProcess::getKeyMode(int key) {
195 int i;
196 for (i = 0; i < num_keys; i++) {
197 KeyMapItem_t* v = &keys_map[i];
198 if (v->value == key)
199 return v->mode;
200 }
201
202 return 0;
203}
204
Lianghu Sue1655222017-05-24 14:52:06 +0800205void EventsProcess::load_key_map() {
206 FILE* fstab = fopen("/etc/gpio_key.kl", "r");
207 if (fstab != NULL) {
208 printf("loaded /etc/gpio_key.kl\n");
209 int alloc = 2;
210 keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t));
Lianghu Sue1655222017-05-24 14:52:06 +0800211 num_keys = 0;
212
213 char buffer[1024];
214 int i;
215 int value = -1;
216 while (fgets(buffer, sizeof(buffer)-1, fstab)) {
217 for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
218
219 if (buffer[i] == '\0' || buffer[i] == '#') continue;
220
221 char* original = strdup(buffer);
Lianghu Sue1655222017-05-24 14:52:06 +0800222 char* type = strtok(original+i, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800223 char* key = strtok(NULL, " \t\n");
ziheng.li413496c2021-11-19 10:56:55 +0800224 char* mode = strtok(NULL, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800225 value = atoi (key);
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800226 if (type && (value > 0)) {
Lianghu Sue1655222017-05-24 14:52:06 +0800227 while (num_keys >= alloc) {
228 alloc *= 2;
229 keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t));
230 }
231 keys_map[num_keys].type = strdup(type);
232 keys_map[num_keys].value = value;
ziheng.li413496c2021-11-19 10:56:55 +0800233 if (!mode)
234 keys_map[num_keys].mode = 0;
235 else
236 keys_map[num_keys].mode = atoi (mode);
Lianghu Sue1655222017-05-24 14:52:06 +0800237
238 ++num_keys;
239 } else {
240 printf("error: skipping malformed keyboard.lk line: %s\n", original);
241 }
242 free(original);
243 }
244
245 fclose(fstab);
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800246 printf("keyboard key map table:\n");
Lianghu Sue1655222017-05-24 14:52:06 +0800247 } else {
248 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800249 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800250 keys_map = g_default_keymap;
Jiacai.Liu71a747b2022-07-25 15:01:56 +0800251 }
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800252 printf("keyboard key map table:\n");
253 int i;
254 for (i = 0; i < num_keys; ++i) {
255 KeyMapItem_t* v = &keys_map[i];
256 printf(" %d type:%s value:%d mode:%d\n", i, v->type, v->value, v->mode);
257 }
Jiacai.Liu71a747b2022-07-25 15:01:56 +0800258 if (keys_map != g_default_keymap)
259 free(keys_map);
Lianghu Sue1655222017-05-24 14:52:06 +0800260}
261
262int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800263 int i;
264 for (i = 0; i < num_keys; i++) {
265 KeyMapItem_t* v = &keys_map[i];
266 if (v->value == key)
267 return v->value;
268 }
Lianghu Sue1655222017-05-24 14:52:06 +0800269
Renjun Xu044c8ec2017-08-17 19:01:14 +0800270 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800271}
272
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800273long checkEventTime(struct timeval *before, struct timeval *later) {
274 time_t before_sec = before->tv_sec;
275 suseconds_t before_usec = before->tv_usec;
276 time_t later_sec = later->tv_sec;
277 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800278
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800279 long sec_diff = (later_sec - before_sec) * 1000;
280 if (sec_diff < 0)
281 return true;
282
283 long ret = sec_diff + (later_usec - before_usec) / 1000;
284 if (ret >= KEY_EVENT_TIME_INTERVAL)
285 return true;
286
287 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800288}
289
ziheng.li413496c2021-11-19 10:56:55 +0800290void EventsProcess::EnqueueKey(int key_code, bool flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800291 struct timeval now;
292 gettimeofday(&now, nullptr);
293
Lianghu Sue1655222017-05-24 14:52:06 +0800294 pthread_mutex_lock(&key_queue_mutex);
295 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
296 if (key_queue_len < queue_max) {
ziheng.li413496c2021-11-19 10:56:55 +0800297 if (last_key != key_code || checkEventTime(&last_queue_time, &now) || flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800298 key_queue[key_queue_len++] = key_code;
299 last_queue_time = now;
300 }
Lianghu Sue1655222017-05-24 14:52:06 +0800301 pthread_cond_signal(&key_queue_cond);
302 }
303 pthread_mutex_unlock(&key_queue_mutex);
304}
305
shu.wanga67d5ea2022-01-14 13:43:06 +0800306#ifdef FILTER_POWERKEY
307bool filter_power_key(const char* key_type)
308{
309#define FILTER_KEY_TIME 150 //ms
310 static long last_time_ms = -1;
311
312 if (!strcmp(key_type, "power")) {
313 struct timeval now_time;
314 gettimeofday(&now_time, nullptr);
315 long now_time_ms = now_time.tv_sec*1000 + now_time.tv_usec/1000;
316 if (last_time_ms == -1 || (now_time_ms - last_time_ms) >= FILTER_KEY_TIME) {
317 last_time_ms = now_time_ms;
318 return true;
319 } else {
320 return false;
321 }
322 } else {
323 return true;
324 }
325#undef FILTER_KEY_TIME
326}
327#endif
328
Renjun Xu044c8ec2017-08-17 19:01:14 +0800329void EventsProcess::WaitKey() {
ziheng.li413496c2021-11-19 10:56:55 +0800330 bool cur_longpress = false;
331 bool execute = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800332 pthread_mutex_lock(&key_queue_mutex);
333
Lianghu Sue1655222017-05-24 14:52:06 +0800334 do {
335 struct timeval now;
336 struct timespec timeout;
337 gettimeofday(&now, nullptr);
338 timeout.tv_sec = now.tv_sec;
339 timeout.tv_nsec = now.tv_usec * 1000;
340 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
341
342 int rc = 0;
343 while (key_queue_len == 0 && rc != ETIMEDOUT) {
344 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
345 }
346 } while (key_queue_len == 0);
347
348 int key = -1;
jiacai.liu7c96e572019-11-28 14:09:36 +0800349 KeyEvent *keyEvent = nullptr;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800350 char* event_str;
351 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800352 if (key_queue_len > 0) {
353 key = key_queue[0];
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800354 memmove(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
Lianghu Sue1655222017-05-24 14:52:06 +0800355 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800356
357 std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
358 //should remove zombie key down long long time?
359 for (; iter != mKeyEventVec.end();) {
ziheng.li413496c2021-11-19 10:56:55 +0800360 if ((*iter)->keyCode == key && ((*iter)->keyState == 0 || (*iter)->curlongPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800361 keyEvent = *iter;
ziheng.li413496c2021-11-19 10:56:55 +0800362 if (keyEvent->curlongPress)
363 cur_longpress = true;
364 else
365 iter = mKeyEventVec.erase(iter);
jiacai.liu7c96e572019-11-28 14:09:36 +0800366 break;
367 } else {
368 ++iter;
369 }
370 }
371
Lianghu Sue1655222017-05-24 14:52:06 +0800372 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800373 const char* keyType=getKeyType(key);
ziheng.li413496c2021-11-19 10:56:55 +0800374 int keymode=getKeyMode(key);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800375 int res;
376 memset(buf,'\0',sizeof(buf));
377 if (keyType != NULL) {
ziheng.li413496c2021-11-19 10:56:55 +0800378 if (keyEvent && cur_longpress && keyEvent->longPress && keymode != 0) {
379 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","curlongpress",keyType);
380 execute = true;
381 } else if (keyEvent && !cur_longpress && keyEvent->longPress && keymode != 1) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800382 uint64_t duration = 0;
383 if (keyEvent->up_ts_us < keyEvent->down_ts_us) {
384 duration = UINT64_MAX - keyEvent->down_ts_us + keyEvent->up_ts_us;
385 duration /= 1000LL;
386 } else {
387 duration = (keyEvent->up_ts_us - keyEvent->down_ts_us)/1000LL;
388 }
Lianghu Sue1655222017-05-24 14:52:06 +0800389
jiacai.liu7c96e572019-11-28 14:09:36 +0800390 sprintf(buf,"%s %s%s %llu","/etc/adckey/adckey_function.sh","longpress",keyType, duration);
ziheng.li413496c2021-11-19 10:56:55 +0800391 execute = true;
392 } else if (!(keyEvent && keyEvent->longPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800393 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
shu.wanga67d5ea2022-01-14 13:43:06 +0800394#ifdef FILTER_POWERKEY
395 execute = filter_power_key(keyType);
396#else
ziheng.li413496c2021-11-19 10:56:55 +0800397 execute = true;
shu.wanga67d5ea2022-01-14 13:43:06 +0800398#endif
jiacai.liu7c96e572019-11-28 14:09:36 +0800399 }
ziheng.li413496c2021-11-19 10:56:55 +0800400 if (execute) {
401 //printf("input_eventd: run %s\n", buf);
402 res=system(buf);
403 if (res != 0) printf("run %s exception!!!\n",buf);
404 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800405 }
Lianghu Sue1655222017-05-24 14:52:06 +0800406
jiacai.liu7c96e572019-11-28 14:09:36 +0800407 //release
ziheng.li413496c2021-11-19 10:56:55 +0800408 if (!cur_longpress)
409 delete keyEvent;
jiacai.liu7c96e572019-11-28 14:09:36 +0800410}