blob: ee4edf098a9ad6bcdf982f4f3203bdf30af9a9eb [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
kirk.wang2ec32a22022-11-16 13:40:31 +080044EventsProcess::~EventsProcess() {
45
46 if ( (keys_map != g_default_keymap) && (NULL != keys_map) ) {
47 free(keys_map);
48 }
49 pthread_mutex_destroy(&key_queue_mutex);
50 pthread_cond_destroy(&key_queue_cond);
51}
Lianghu Sue1655222017-05-24 14:52:06 +080052
53int EventsProcess::InputCallback(int fd, uint32_t epevents, void* data) {
54 return reinterpret_cast<EventsProcess*>(data)->OnInputEvent(fd, epevents);
55}
56
Lianghu Sue1655222017-05-24 14:52:06 +080057static void* InputThreadLoop(void*) {
58 while (true) {
59 if (!ev_wait(-1)) {
60 ev_dispatch();
61 }
62 }
63 return nullptr;
64}
65
66void EventsProcess::Init() {
67 ev_init(InputCallback, this);
68
69 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
70}
71
72int EventsProcess::OnInputEvent(int fd, uint32_t epevents) {
73 struct input_event ev;
74
75 if (ev_get_input(fd, epevents, &ev) == -1) {
76 return -1;
77 }
78
79 if (ev.type == EV_SYN) {
80 return 0;
81 }
82
83 if (ev.type == EV_KEY && ev.code <= KEY_MAX) {
Renjun Xu044c8ec2017-08-17 19:01:14 +080084
Lianghu Sue1655222017-05-24 14:52:06 +080085 int code = getMapKey(ev.code);
86 if (code > 0) {
87 ProcessKey(code, ev.value);
88 } else {
89 ProcessKey(ev.code, ev.value);
90 }
91 }
92
93 return 0;
94}
95
jiacai.liu7c96e572019-11-28 14:09:36 +080096/* use CLOCK_MONOTONIC clock, gettimeofday will overlap if ntp changes */
97uint64_t EventsProcess::getSystemTimeUs() {
98 struct timespec ts;
99
100 clock_gettime(CLOCK_MONOTONIC, &ts);
101 return (ts.tv_sec)*1000000LL + ts.tv_nsec/1000LL;
102}
103
Lianghu Sue1655222017-05-24 14:52:06 +0800104void EventsProcess::ProcessKey(int key_code, int value) {
105 bool register_key = false;
ziheng.li413496c2021-11-19 10:56:55 +0800106 bool flag = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800107 pthread_mutex_lock(&key_queue_mutex);
108 key_pressed[key_code] = value;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800109 if (value == 1) {/*1:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800110 KeyEvent *ke = new KeyEvent;
111 ke->down_ts_us = getSystemTimeUs();
112 ke->keyCode = key_code;
113 ke->keyState = value; /*key down*/
114 ke->longPress = false;
ziheng.li413496c2021-11-19 10:56:55 +0800115 ke->curlongPress = false;
jiacai.liu7c96e572019-11-28 14:09:36 +0800116 mKeyEventVec.push_back(ke);
117
Lianghu Sue1655222017-05-24 14:52:06 +0800118 ++key_down_count;
119 key_last_down = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800120 key_timer_t* info = new key_timer_t;
121 info->ep = this;
122 info->key_code = key_code;
123 info->count = key_down_count;
jiacai.liu7c96e572019-11-28 14:09:36 +0800124 info->ke = ke;
Lianghu Sue1655222017-05-24 14:52:06 +0800125 pthread_t thread;
126 pthread_create(&thread, nullptr, &EventsProcess::time_key_helper, info);
127 pthread_detach(thread);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800128 } else if(value == 2){/*2:key repeat*/
129 } else {/*0:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800130 for (std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
131 iter != mKeyEventVec.end(); ++iter) {
132 if ((*iter)->keyCode == key_code && (*iter)->keyState == 1) {
133 (*iter)->up_ts_us = getSystemTimeUs();
134 (*iter)->keyState = value; /*key up*/
ziheng.li413496c2021-11-19 10:56:55 +0800135 if ((*iter)->longPress || (*iter)->curlongPress) {
136 (*iter)->curlongPress = false;
137 flag = true;
138 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800139 break;
140 }
141 }
142
Lianghu Sue1655222017-05-24 14:52:06 +0800143 if (key_last_down == key_code) {
Lianghu Sue1655222017-05-24 14:52:06 +0800144 register_key = true;
145 }
146 key_last_down = -1;
147 }
148 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800149 last_key = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800150 if (register_key) {
ziheng.li413496c2021-11-19 10:56:55 +0800151 EnqueueKey(key_code, flag);
Lianghu Sue1655222017-05-24 14:52:06 +0800152 }
153}
154
155void* EventsProcess::time_key_helper(void* cookie) {
156 key_timer_t* info = (key_timer_t*) cookie;
jiacai.liu7c96e572019-11-28 14:09:36 +0800157 info->ep->time_key(info);
Lianghu Sue1655222017-05-24 14:52:06 +0800158 delete info;
159 return nullptr;
160}
161
jiacai.liu7c96e572019-11-28 14:09:36 +0800162void EventsProcess::time_key(key_timer_t *info) {
163 int key_code = info->key_code;
164 int count = info->count;
ziheng.li413496c2021-11-19 10:56:55 +0800165 int keymode = getKeyMode(key_code);
Lianghu Sue1655222017-05-24 14:52:06 +0800166 usleep(750000); // 750 ms == "long"
Lianghu Sue1655222017-05-24 14:52:06 +0800167 pthread_mutex_lock(&key_queue_mutex);
168 if (key_last_down == key_code && key_down_count == count) {
ziheng.li413496c2021-11-19 10:56:55 +0800169 if (info->ke) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800170 info->ke->longPress = true;
ziheng.li413496c2021-11-19 10:56:55 +0800171 if (keymode != 0)
172 info->ke->curlongPress = true;
173 }
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800174 else {
175 printf("##recive key but no events##\n");
176 pthread_mutex_unlock(&key_queue_mutex);
177 return;
178 }
Lianghu Sue1655222017-05-24 14:52:06 +0800179 }
ziheng.li413496c2021-11-19 10:56:55 +0800180 if (info->ke->longPress && info->ke->curlongPress) {
181 pthread_mutex_unlock(&key_queue_mutex);
182 while (key_last_down == key_code && key_down_count == count) {
183 EnqueueKey(key_code, false);
184 }
185 } else {
186 pthread_mutex_unlock(&key_queue_mutex);
187 }
Lianghu Sue1655222017-05-24 14:52:06 +0800188}
189
Lianghu Sue1655222017-05-24 14:52:06 +0800190
Renjun Xu044c8ec2017-08-17 19:01:14 +0800191const char* EventsProcess::getKeyType(int key) {
192 int i;
193 for (i = 0; i < num_keys; i++) {
194 KeyMapItem_t* v = &keys_map[i];
195 if (v->value == key)
196 return v->type;
Lianghu Sue1655222017-05-24 14:52:06 +0800197 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800198
199 return NULL;
Lianghu Sue1655222017-05-24 14:52:06 +0800200}
201
ziheng.li413496c2021-11-19 10:56:55 +0800202int EventsProcess::getKeyMode(int key) {
203 int i;
204 for (i = 0; i < num_keys; i++) {
205 KeyMapItem_t* v = &keys_map[i];
206 if (v->value == key)
207 return v->mode;
208 }
209
210 return 0;
211}
212
Lianghu Sue1655222017-05-24 14:52:06 +0800213void EventsProcess::load_key_map() {
214 FILE* fstab = fopen("/etc/gpio_key.kl", "r");
215 if (fstab != NULL) {
216 printf("loaded /etc/gpio_key.kl\n");
217 int alloc = 2;
218 keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t));
Lianghu Sue1655222017-05-24 14:52:06 +0800219 num_keys = 0;
220
221 char buffer[1024];
222 int i;
223 int value = -1;
224 while (fgets(buffer, sizeof(buffer)-1, fstab)) {
225 for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
226
227 if (buffer[i] == '\0' || buffer[i] == '#') continue;
228
229 char* original = strdup(buffer);
Lianghu Sue1655222017-05-24 14:52:06 +0800230 char* type = strtok(original+i, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800231 char* key = strtok(NULL, " \t\n");
ziheng.li413496c2021-11-19 10:56:55 +0800232 char* mode = strtok(NULL, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800233 value = atoi (key);
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800234 if (type && (value > 0)) {
Lianghu Sue1655222017-05-24 14:52:06 +0800235 while (num_keys >= alloc) {
236 alloc *= 2;
237 keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t));
238 }
239 keys_map[num_keys].type = strdup(type);
240 keys_map[num_keys].value = value;
ziheng.li413496c2021-11-19 10:56:55 +0800241 if (!mode)
242 keys_map[num_keys].mode = 0;
243 else
244 keys_map[num_keys].mode = atoi (mode);
Lianghu Sue1655222017-05-24 14:52:06 +0800245
246 ++num_keys;
247 } else {
248 printf("error: skipping malformed keyboard.lk line: %s\n", original);
249 }
250 free(original);
251 }
252
253 fclose(fstab);
kirk.wang2ec32a22022-11-16 13:40:31 +0800254
Lianghu Sue1655222017-05-24 14:52:06 +0800255 } else {
256 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800257 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800258 keys_map = g_default_keymap;
Jiacai.Liu71a747b2022-07-25 15:01:56 +0800259 }
kirk.wang2ec32a22022-11-16 13:40:31 +0800260 printf("keyboard key map table:\n");
261 int i;
262 for (i = 0; i < num_keys; ++i) {
263 KeyMapItem_t* v = &keys_map[i];
264 printf(" %d type:%s value:%d mode:%d\n", i, v->type, v->value, v->mode);
265 }
Lianghu Sue1655222017-05-24 14:52:06 +0800266}
267
268int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800269 int i;
270 for (i = 0; i < num_keys; i++) {
271 KeyMapItem_t* v = &keys_map[i];
272 if (v->value == key)
273 return v->value;
274 }
Lianghu Sue1655222017-05-24 14:52:06 +0800275
Renjun Xu044c8ec2017-08-17 19:01:14 +0800276 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800277}
278
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800279long checkEventTime(struct timeval *before, struct timeval *later) {
280 time_t before_sec = before->tv_sec;
281 suseconds_t before_usec = before->tv_usec;
282 time_t later_sec = later->tv_sec;
283 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800284
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800285 long sec_diff = (later_sec - before_sec) * 1000;
286 if (sec_diff < 0)
287 return true;
288
289 long ret = sec_diff + (later_usec - before_usec) / 1000;
290 if (ret >= KEY_EVENT_TIME_INTERVAL)
291 return true;
292
293 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800294}
295
ziheng.li413496c2021-11-19 10:56:55 +0800296void EventsProcess::EnqueueKey(int key_code, bool flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800297 struct timeval now;
298 gettimeofday(&now, nullptr);
299
Lianghu Sue1655222017-05-24 14:52:06 +0800300 pthread_mutex_lock(&key_queue_mutex);
301 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
302 if (key_queue_len < queue_max) {
ziheng.li413496c2021-11-19 10:56:55 +0800303 if (last_key != key_code || checkEventTime(&last_queue_time, &now) || flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800304 key_queue[key_queue_len++] = key_code;
305 last_queue_time = now;
306 }
Lianghu Sue1655222017-05-24 14:52:06 +0800307 pthread_cond_signal(&key_queue_cond);
308 }
309 pthread_mutex_unlock(&key_queue_mutex);
310}
311
shu.wanga67d5ea2022-01-14 13:43:06 +0800312#ifdef FILTER_POWERKEY
313bool filter_power_key(const char* key_type)
314{
315#define FILTER_KEY_TIME 150 //ms
316 static long last_time_ms = -1;
317
318 if (!strcmp(key_type, "power")) {
319 struct timeval now_time;
320 gettimeofday(&now_time, nullptr);
321 long now_time_ms = now_time.tv_sec*1000 + now_time.tv_usec/1000;
322 if (last_time_ms == -1 || (now_time_ms - last_time_ms) >= FILTER_KEY_TIME) {
323 last_time_ms = now_time_ms;
324 return true;
325 } else {
326 return false;
327 }
328 } else {
329 return true;
330 }
331#undef FILTER_KEY_TIME
332}
333#endif
334
Renjun Xu044c8ec2017-08-17 19:01:14 +0800335void EventsProcess::WaitKey() {
ziheng.li413496c2021-11-19 10:56:55 +0800336 bool cur_longpress = false;
337 bool execute = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800338 pthread_mutex_lock(&key_queue_mutex);
339
Lianghu Sue1655222017-05-24 14:52:06 +0800340 do {
341 struct timeval now;
342 struct timespec timeout;
343 gettimeofday(&now, nullptr);
344 timeout.tv_sec = now.tv_sec;
345 timeout.tv_nsec = now.tv_usec * 1000;
346 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
347
348 int rc = 0;
349 while (key_queue_len == 0 && rc != ETIMEDOUT) {
350 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
351 }
352 } while (key_queue_len == 0);
353
354 int key = -1;
jiacai.liu7c96e572019-11-28 14:09:36 +0800355 KeyEvent *keyEvent = nullptr;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800356 char* event_str;
357 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800358 if (key_queue_len > 0) {
359 key = key_queue[0];
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800360 memmove(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
Lianghu Sue1655222017-05-24 14:52:06 +0800361 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800362
363 std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
364 //should remove zombie key down long long time?
365 for (; iter != mKeyEventVec.end();) {
ziheng.li413496c2021-11-19 10:56:55 +0800366 if ((*iter)->keyCode == key && ((*iter)->keyState == 0 || (*iter)->curlongPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800367 keyEvent = *iter;
ziheng.li413496c2021-11-19 10:56:55 +0800368 if (keyEvent->curlongPress)
369 cur_longpress = true;
370 else
371 iter = mKeyEventVec.erase(iter);
jiacai.liu7c96e572019-11-28 14:09:36 +0800372 break;
373 } else {
374 ++iter;
375 }
376 }
377
Lianghu Sue1655222017-05-24 14:52:06 +0800378 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800379 const char* keyType=getKeyType(key);
ziheng.li413496c2021-11-19 10:56:55 +0800380 int keymode=getKeyMode(key);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800381 int res;
382 memset(buf,'\0',sizeof(buf));
383 if (keyType != NULL) {
ziheng.li413496c2021-11-19 10:56:55 +0800384 if (keyEvent && cur_longpress && keyEvent->longPress && keymode != 0) {
385 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","curlongpress",keyType);
386 execute = true;
387 } else if (keyEvent && !cur_longpress && keyEvent->longPress && keymode != 1) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800388 uint64_t duration = 0;
389 if (keyEvent->up_ts_us < keyEvent->down_ts_us) {
390 duration = UINT64_MAX - keyEvent->down_ts_us + keyEvent->up_ts_us;
391 duration /= 1000LL;
392 } else {
393 duration = (keyEvent->up_ts_us - keyEvent->down_ts_us)/1000LL;
394 }
Lianghu Sue1655222017-05-24 14:52:06 +0800395
jiacai.liu7c96e572019-11-28 14:09:36 +0800396 sprintf(buf,"%s %s%s %llu","/etc/adckey/adckey_function.sh","longpress",keyType, duration);
ziheng.li413496c2021-11-19 10:56:55 +0800397 execute = true;
398 } else if (!(keyEvent && keyEvent->longPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800399 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
shu.wanga67d5ea2022-01-14 13:43:06 +0800400#ifdef FILTER_POWERKEY
401 execute = filter_power_key(keyType);
402#else
ziheng.li413496c2021-11-19 10:56:55 +0800403 execute = true;
shu.wanga67d5ea2022-01-14 13:43:06 +0800404#endif
jiacai.liu7c96e572019-11-28 14:09:36 +0800405 }
ziheng.li413496c2021-11-19 10:56:55 +0800406 if (execute) {
407 //printf("input_eventd: run %s\n", buf);
408 res=system(buf);
409 if (res != 0) printf("run %s exception!!!\n",buf);
410 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800411 }
Lianghu Sue1655222017-05-24 14:52:06 +0800412
jiacai.liu7c96e572019-11-28 14:09:36 +0800413 //release
ziheng.li413496c2021-11-19 10:56:55 +0800414 if (!cur_longpress)
415 delete keyEvent;
jiacai.liu7c96e572019-11-28 14:09:36 +0800416}