blob: 9d6c7df935829b8b5d436a5c418b8fdddc81047d [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");
247 int j;
248 for (j = 0; j < num_keys; ++j) {
249 KeyMapItem_t* v = &keys_map[j];
250 printf(" %d type:%s value:%d mode:%d\n", j, v->type, v->value, v->mode);
251 }
252 free(keys_map);
Lianghu Sue1655222017-05-24 14:52:06 +0800253 } else {
254 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800255 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800256 keys_map = g_default_keymap;
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800257 printf("keyboard key map table:\n");
258 int i;
259 for (i = 0; i < num_keys; ++i) {
260 KeyMapItem_t* v = &keys_map[i];
261 printf(" %d type:%s value:%d mode:%d\n", i, v->type, v->value, v->mode);
262 }
Lianghu Sue1655222017-05-24 14:52:06 +0800263 }
264
Lianghu Sue1655222017-05-24 14:52:06 +0800265}
266
267int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800268 int i;
269 for (i = 0; i < num_keys; i++) {
270 KeyMapItem_t* v = &keys_map[i];
271 if (v->value == key)
272 return v->value;
273 }
Lianghu Sue1655222017-05-24 14:52:06 +0800274
Renjun Xu044c8ec2017-08-17 19:01:14 +0800275 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800276}
277
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800278long checkEventTime(struct timeval *before, struct timeval *later) {
279 time_t before_sec = before->tv_sec;
280 suseconds_t before_usec = before->tv_usec;
281 time_t later_sec = later->tv_sec;
282 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800283
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800284 long sec_diff = (later_sec - before_sec) * 1000;
285 if (sec_diff < 0)
286 return true;
287
288 long ret = sec_diff + (later_usec - before_usec) / 1000;
289 if (ret >= KEY_EVENT_TIME_INTERVAL)
290 return true;
291
292 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800293}
294
ziheng.li413496c2021-11-19 10:56:55 +0800295void EventsProcess::EnqueueKey(int key_code, bool flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800296 struct timeval now;
297 gettimeofday(&now, nullptr);
298
Lianghu Sue1655222017-05-24 14:52:06 +0800299 pthread_mutex_lock(&key_queue_mutex);
300 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
301 if (key_queue_len < queue_max) {
ziheng.li413496c2021-11-19 10:56:55 +0800302 if (last_key != key_code || checkEventTime(&last_queue_time, &now) || flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800303 key_queue[key_queue_len++] = key_code;
304 last_queue_time = now;
305 }
Lianghu Sue1655222017-05-24 14:52:06 +0800306 pthread_cond_signal(&key_queue_cond);
307 }
308 pthread_mutex_unlock(&key_queue_mutex);
309}
310
shu.wanga67d5ea2022-01-14 13:43:06 +0800311#ifdef FILTER_POWERKEY
312bool filter_power_key(const char* key_type)
313{
314#define FILTER_KEY_TIME 150 //ms
315 static long last_time_ms = -1;
316
317 if (!strcmp(key_type, "power")) {
318 struct timeval now_time;
319 gettimeofday(&now_time, nullptr);
320 long now_time_ms = now_time.tv_sec*1000 + now_time.tv_usec/1000;
321 if (last_time_ms == -1 || (now_time_ms - last_time_ms) >= FILTER_KEY_TIME) {
322 last_time_ms = now_time_ms;
323 return true;
324 } else {
325 return false;
326 }
327 } else {
328 return true;
329 }
330#undef FILTER_KEY_TIME
331}
332#endif
333
Renjun Xu044c8ec2017-08-17 19:01:14 +0800334void EventsProcess::WaitKey() {
ziheng.li413496c2021-11-19 10:56:55 +0800335 bool cur_longpress = false;
336 bool execute = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800337 pthread_mutex_lock(&key_queue_mutex);
338
Lianghu Sue1655222017-05-24 14:52:06 +0800339 do {
340 struct timeval now;
341 struct timespec timeout;
342 gettimeofday(&now, nullptr);
343 timeout.tv_sec = now.tv_sec;
344 timeout.tv_nsec = now.tv_usec * 1000;
345 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
346
347 int rc = 0;
348 while (key_queue_len == 0 && rc != ETIMEDOUT) {
349 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
350 }
351 } while (key_queue_len == 0);
352
353 int key = -1;
jiacai.liu7c96e572019-11-28 14:09:36 +0800354 KeyEvent *keyEvent = nullptr;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800355 char* event_str;
356 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800357 if (key_queue_len > 0) {
358 key = key_queue[0];
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800359 memmove(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
Lianghu Sue1655222017-05-24 14:52:06 +0800360 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800361
362 std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
363 //should remove zombie key down long long time?
364 for (; iter != mKeyEventVec.end();) {
ziheng.li413496c2021-11-19 10:56:55 +0800365 if ((*iter)->keyCode == key && ((*iter)->keyState == 0 || (*iter)->curlongPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800366 keyEvent = *iter;
ziheng.li413496c2021-11-19 10:56:55 +0800367 if (keyEvent->curlongPress)
368 cur_longpress = true;
369 else
370 iter = mKeyEventVec.erase(iter);
jiacai.liu7c96e572019-11-28 14:09:36 +0800371 break;
372 } else {
373 ++iter;
374 }
375 }
376
Lianghu Sue1655222017-05-24 14:52:06 +0800377 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800378 const char* keyType=getKeyType(key);
ziheng.li413496c2021-11-19 10:56:55 +0800379 int keymode=getKeyMode(key);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800380 int res;
381 memset(buf,'\0',sizeof(buf));
382 if (keyType != NULL) {
ziheng.li413496c2021-11-19 10:56:55 +0800383 if (keyEvent && cur_longpress && keyEvent->longPress && keymode != 0) {
384 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","curlongpress",keyType);
385 execute = true;
386 } else if (keyEvent && !cur_longpress && keyEvent->longPress && keymode != 1) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800387 uint64_t duration = 0;
388 if (keyEvent->up_ts_us < keyEvent->down_ts_us) {
389 duration = UINT64_MAX - keyEvent->down_ts_us + keyEvent->up_ts_us;
390 duration /= 1000LL;
391 } else {
392 duration = (keyEvent->up_ts_us - keyEvent->down_ts_us)/1000LL;
393 }
Lianghu Sue1655222017-05-24 14:52:06 +0800394
jiacai.liu7c96e572019-11-28 14:09:36 +0800395 sprintf(buf,"%s %s%s %llu","/etc/adckey/adckey_function.sh","longpress",keyType, duration);
ziheng.li413496c2021-11-19 10:56:55 +0800396 execute = true;
397 } else if (!(keyEvent && keyEvent->longPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800398 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
shu.wanga67d5ea2022-01-14 13:43:06 +0800399#ifdef FILTER_POWERKEY
400 execute = filter_power_key(keyType);
401#else
ziheng.li413496c2021-11-19 10:56:55 +0800402 execute = true;
shu.wanga67d5ea2022-01-14 13:43:06 +0800403#endif
jiacai.liu7c96e572019-11-28 14:09:36 +0800404 }
ziheng.li413496c2021-11-19 10:56:55 +0800405 if (execute) {
406 //printf("input_eventd: run %s\n", buf);
407 res=system(buf);
408 if (res != 0) printf("run %s exception!!!\n",buf);
409 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800410 }
Lianghu Sue1655222017-05-24 14:52:06 +0800411
jiacai.liu7c96e572019-11-28 14:09:36 +0800412 //release
ziheng.li413496c2021-11-19 10:56:55 +0800413 if (!cur_longpress)
414 delete keyEvent;
jiacai.liu7c96e572019-11-28 14:09:36 +0800415}