blob: 906d010fafe1e34db2ceb6ffcd0a27b3afef41d8 [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 }
Lianghu Sue1655222017-05-24 14:52:06 +0800166 }
ziheng.li413496c2021-11-19 10:56:55 +0800167 if (info->ke->longPress && info->ke->curlongPress) {
168 pthread_mutex_unlock(&key_queue_mutex);
169 while (key_last_down == key_code && key_down_count == count) {
170 EnqueueKey(key_code, false);
171 }
172 } else {
173 pthread_mutex_unlock(&key_queue_mutex);
174 }
Lianghu Sue1655222017-05-24 14:52:06 +0800175}
176
Lianghu Sue1655222017-05-24 14:52:06 +0800177
Renjun Xu044c8ec2017-08-17 19:01:14 +0800178const char* EventsProcess::getKeyType(int key) {
179 int i;
180 for (i = 0; i < num_keys; i++) {
181 KeyMapItem_t* v = &keys_map[i];
182 if (v->value == key)
183 return v->type;
Lianghu Sue1655222017-05-24 14:52:06 +0800184 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800185
186 return NULL;
Lianghu Sue1655222017-05-24 14:52:06 +0800187}
188
ziheng.li413496c2021-11-19 10:56:55 +0800189int EventsProcess::getKeyMode(int key) {
190 int i;
191 for (i = 0; i < num_keys; i++) {
192 KeyMapItem_t* v = &keys_map[i];
193 if (v->value == key)
194 return v->mode;
195 }
196
197 return 0;
198}
199
Lianghu Sue1655222017-05-24 14:52:06 +0800200void EventsProcess::load_key_map() {
201 FILE* fstab = fopen("/etc/gpio_key.kl", "r");
202 if (fstab != NULL) {
203 printf("loaded /etc/gpio_key.kl\n");
204 int alloc = 2;
205 keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t));
Lianghu Sue1655222017-05-24 14:52:06 +0800206 num_keys = 0;
207
208 char buffer[1024];
209 int i;
210 int value = -1;
211 while (fgets(buffer, sizeof(buffer)-1, fstab)) {
212 for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
213
214 if (buffer[i] == '\0' || buffer[i] == '#') continue;
215
216 char* original = strdup(buffer);
Lianghu Sue1655222017-05-24 14:52:06 +0800217 char* type = strtok(original+i, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800218 char* key = strtok(NULL, " \t\n");
ziheng.li413496c2021-11-19 10:56:55 +0800219 char* mode = strtok(NULL, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800220 value = atoi (key);
221 if (type && key && (value > 0)) {
Lianghu Sue1655222017-05-24 14:52:06 +0800222 while (num_keys >= alloc) {
223 alloc *= 2;
224 keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t));
225 }
226 keys_map[num_keys].type = strdup(type);
227 keys_map[num_keys].value = value;
ziheng.li413496c2021-11-19 10:56:55 +0800228 if (!mode)
229 keys_map[num_keys].mode = 0;
230 else
231 keys_map[num_keys].mode = atoi (mode);
Lianghu Sue1655222017-05-24 14:52:06 +0800232
233 ++num_keys;
234 } else {
235 printf("error: skipping malformed keyboard.lk line: %s\n", original);
236 }
237 free(original);
238 }
239
240 fclose(fstab);
241 } else {
242 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800243 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800244 keys_map = g_default_keymap;
245 }
246
247 printf("keyboard key map table:\n");
248 int i;
249 for (i = 0; i < num_keys; ++i) {
250 KeyMapItem_t* v = &keys_map[i];
ziheng.li413496c2021-11-19 10:56:55 +0800251 printf(" %d type:%s value:%d mode:%d\n", i, v->type, v->value, v->mode);
Lianghu Sue1655222017-05-24 14:52:06 +0800252 }
Lianghu Sue1655222017-05-24 14:52:06 +0800253}
254
255int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800256 int i;
257 for (i = 0; i < num_keys; i++) {
258 KeyMapItem_t* v = &keys_map[i];
259 if (v->value == key)
260 return v->value;
261 }
Lianghu Sue1655222017-05-24 14:52:06 +0800262
Renjun Xu044c8ec2017-08-17 19:01:14 +0800263 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800264}
265
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800266long checkEventTime(struct timeval *before, struct timeval *later) {
267 time_t before_sec = before->tv_sec;
268 suseconds_t before_usec = before->tv_usec;
269 time_t later_sec = later->tv_sec;
270 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800271
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800272 long sec_diff = (later_sec - before_sec) * 1000;
273 if (sec_diff < 0)
274 return true;
275
276 long ret = sec_diff + (later_usec - before_usec) / 1000;
277 if (ret >= KEY_EVENT_TIME_INTERVAL)
278 return true;
279
280 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800281}
282
ziheng.li413496c2021-11-19 10:56:55 +0800283void EventsProcess::EnqueueKey(int key_code, bool flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800284 struct timeval now;
285 gettimeofday(&now, nullptr);
286
Lianghu Sue1655222017-05-24 14:52:06 +0800287 pthread_mutex_lock(&key_queue_mutex);
288 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
289 if (key_queue_len < queue_max) {
ziheng.li413496c2021-11-19 10:56:55 +0800290 if (last_key != key_code || checkEventTime(&last_queue_time, &now) || flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800291 key_queue[key_queue_len++] = key_code;
292 last_queue_time = now;
293 }
Lianghu Sue1655222017-05-24 14:52:06 +0800294 pthread_cond_signal(&key_queue_cond);
295 }
296 pthread_mutex_unlock(&key_queue_mutex);
297}
298
shu.wanga67d5ea2022-01-14 13:43:06 +0800299#ifdef FILTER_POWERKEY
300bool filter_power_key(const char* key_type)
301{
302#define FILTER_KEY_TIME 150 //ms
303 static long last_time_ms = -1;
304
305 if (!strcmp(key_type, "power")) {
306 struct timeval now_time;
307 gettimeofday(&now_time, nullptr);
308 long now_time_ms = now_time.tv_sec*1000 + now_time.tv_usec/1000;
309 if (last_time_ms == -1 || (now_time_ms - last_time_ms) >= FILTER_KEY_TIME) {
310 last_time_ms = now_time_ms;
311 return true;
312 } else {
313 return false;
314 }
315 } else {
316 return true;
317 }
318#undef FILTER_KEY_TIME
319}
320#endif
321
Renjun Xu044c8ec2017-08-17 19:01:14 +0800322void EventsProcess::WaitKey() {
ziheng.li413496c2021-11-19 10:56:55 +0800323 bool cur_longpress = false;
324 bool execute = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800325 pthread_mutex_lock(&key_queue_mutex);
326
Lianghu Sue1655222017-05-24 14:52:06 +0800327 do {
328 struct timeval now;
329 struct timespec timeout;
330 gettimeofday(&now, nullptr);
331 timeout.tv_sec = now.tv_sec;
332 timeout.tv_nsec = now.tv_usec * 1000;
333 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
334
335 int rc = 0;
336 while (key_queue_len == 0 && rc != ETIMEDOUT) {
337 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
338 }
339 } while (key_queue_len == 0);
340
341 int key = -1;
jiacai.liu7c96e572019-11-28 14:09:36 +0800342 KeyEvent *keyEvent = nullptr;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800343 char* event_str;
344 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800345 if (key_queue_len > 0) {
346 key = key_queue[0];
347 memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
348 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800349
350 std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
351 //should remove zombie key down long long time?
352 for (; iter != mKeyEventVec.end();) {
ziheng.li413496c2021-11-19 10:56:55 +0800353 if ((*iter)->keyCode == key && ((*iter)->keyState == 0 || (*iter)->curlongPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800354 keyEvent = *iter;
ziheng.li413496c2021-11-19 10:56:55 +0800355 if (keyEvent->curlongPress)
356 cur_longpress = true;
357 else
358 iter = mKeyEventVec.erase(iter);
jiacai.liu7c96e572019-11-28 14:09:36 +0800359 break;
360 } else {
361 ++iter;
362 }
363 }
364
Lianghu Sue1655222017-05-24 14:52:06 +0800365 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800366 const char* keyType=getKeyType(key);
ziheng.li413496c2021-11-19 10:56:55 +0800367 int keymode=getKeyMode(key);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800368 int res;
369 memset(buf,'\0',sizeof(buf));
370 if (keyType != NULL) {
ziheng.li413496c2021-11-19 10:56:55 +0800371 if (keyEvent && cur_longpress && keyEvent->longPress && keymode != 0) {
372 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","curlongpress",keyType);
373 execute = true;
374 } else if (keyEvent && !cur_longpress && keyEvent->longPress && keymode != 1) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800375 uint64_t duration = 0;
376 if (keyEvent->up_ts_us < keyEvent->down_ts_us) {
377 duration = UINT64_MAX - keyEvent->down_ts_us + keyEvent->up_ts_us;
378 duration /= 1000LL;
379 } else {
380 duration = (keyEvent->up_ts_us - keyEvent->down_ts_us)/1000LL;
381 }
Lianghu Sue1655222017-05-24 14:52:06 +0800382
jiacai.liu7c96e572019-11-28 14:09:36 +0800383 sprintf(buf,"%s %s%s %llu","/etc/adckey/adckey_function.sh","longpress",keyType, duration);
ziheng.li413496c2021-11-19 10:56:55 +0800384 execute = true;
385 } else if (!(keyEvent && keyEvent->longPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800386 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
shu.wanga67d5ea2022-01-14 13:43:06 +0800387#ifdef FILTER_POWERKEY
388 execute = filter_power_key(keyType);
389#else
ziheng.li413496c2021-11-19 10:56:55 +0800390 execute = true;
shu.wanga67d5ea2022-01-14 13:43:06 +0800391#endif
jiacai.liu7c96e572019-11-28 14:09:36 +0800392 }
ziheng.li413496c2021-11-19 10:56:55 +0800393 if (execute) {
394 //printf("input_eventd: run %s\n", buf);
395 res=system(buf);
396 if (res != 0) printf("run %s exception!!!\n",buf);
397 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800398 }
Lianghu Sue1655222017-05-24 14:52:06 +0800399
jiacai.liu7c96e572019-11-28 14:09:36 +0800400 //release
ziheng.li413496c2021-11-19 10:56:55 +0800401 if (!cur_longpress)
402 delete keyEvent;
jiacai.liu7c96e572019-11-28 14:09:36 +0800403}