blob: 725252f1cc3d0442a7fff75581cd343473476ffb [file] [log] [blame]
hanliang.xiongcd3ad4c2024-12-23 11:07:00 +08001// SPDX-License-Identifier: Apache2.0
2/*
3 * Copyright (C) 2024 Amlogic Inc.
4 */
Lianghu Sue1655222017-05-24 14:52:06 +08005#include <errno.h>
6#include <fcntl.h>
7#include <stdint.h>
8#include <linux/input.h>
9#include <pthread.h>
10#include <stdarg.h>
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <sys/stat.h>
15#include <sys/time.h>
16#include <sys/types.h>
17#include <time.h>
18#include <unistd.h>
19#include <ctype.h>
20#include "events.h"
21#include "events_process.h"
22
23#define WAIT_KEY_TIMEOUT_SEC 120
24#define nullptr NULL
Lianghu Su53dd4072017-05-26 19:04:48 +080025#define KEY_EVENT_TIME_INTERVAL 20
Lianghu Sue1655222017-05-24 14:52:06 +080026
Renjun Xu044c8ec2017-08-17 19:01:14 +080027EventsProcess:: KeyMapItem_t g_default_keymap[] = {
28 { "power", KEY_POWER },
29 { "down", KEY_DOWN },
30 { "up", KEY_UP },
31};
Lianghu Sue1655222017-05-24 14:52:06 +080032
33EventsProcess::EventsProcess()
34 : key_queue_len(0),
35 key_last_down(-1),
Lianghu Sue1655222017-05-24 14:52:06 +080036 last_key(-1),
Renjun Xu044c8ec2017-08-17 19:01:14 +080037 key_down_count(0),
38 report_longpress_flag(false),
Lianghu Sue1655222017-05-24 14:52:06 +080039 num_keys(0),
40 keys_map(NULL) {
41 pthread_mutex_init(&key_queue_mutex, nullptr);
42 pthread_cond_init(&key_queue_cond, nullptr);
43 memset(key_pressed, 0, sizeof(key_pressed));
Lianghu Su53dd4072017-05-26 19:04:48 +080044 memset(&last_queue_time, 0, sizeof(last_queue_time));
Lianghu Sue1655222017-05-24 14:52:06 +080045 load_key_map();
46}
47
kirk.wang2ec32a22022-11-16 13:40:31 +080048EventsProcess::~EventsProcess() {
49
50 if ( (keys_map != g_default_keymap) && (NULL != keys_map) ) {
51 free(keys_map);
52 }
53 pthread_mutex_destroy(&key_queue_mutex);
54 pthread_cond_destroy(&key_queue_cond);
55}
Lianghu Sue1655222017-05-24 14:52:06 +080056
57int EventsProcess::InputCallback(int fd, uint32_t epevents, void* data) {
58 return reinterpret_cast<EventsProcess*>(data)->OnInputEvent(fd, epevents);
59}
60
Lianghu Sue1655222017-05-24 14:52:06 +080061static void* InputThreadLoop(void*) {
62 while (true) {
63 if (!ev_wait(-1)) {
64 ev_dispatch();
65 }
66 }
67 return nullptr;
68}
69
70void EventsProcess::Init() {
71 ev_init(InputCallback, this);
72
73 pthread_create(&input_thread_, nullptr, InputThreadLoop, nullptr);
74}
75
76int EventsProcess::OnInputEvent(int fd, uint32_t epevents) {
77 struct input_event ev;
78
79 if (ev_get_input(fd, epevents, &ev) == -1) {
80 return -1;
81 }
82
83 if (ev.type == EV_SYN) {
84 return 0;
85 }
86
87 if (ev.type == EV_KEY && ev.code <= KEY_MAX) {
Renjun Xu044c8ec2017-08-17 19:01:14 +080088
Lianghu Sue1655222017-05-24 14:52:06 +080089 int code = getMapKey(ev.code);
90 if (code > 0) {
91 ProcessKey(code, ev.value);
92 } else {
93 ProcessKey(ev.code, ev.value);
94 }
95 }
96
97 return 0;
98}
99
jiacai.liu7c96e572019-11-28 14:09:36 +0800100/* use CLOCK_MONOTONIC clock, gettimeofday will overlap if ntp changes */
101uint64_t EventsProcess::getSystemTimeUs() {
102 struct timespec ts;
103
104 clock_gettime(CLOCK_MONOTONIC, &ts);
105 return (ts.tv_sec)*1000000LL + ts.tv_nsec/1000LL;
106}
107
Lianghu Sue1655222017-05-24 14:52:06 +0800108void EventsProcess::ProcessKey(int key_code, int value) {
109 bool register_key = false;
ziheng.li413496c2021-11-19 10:56:55 +0800110 bool flag = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800111 pthread_mutex_lock(&key_queue_mutex);
112 key_pressed[key_code] = value;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800113 if (value == 1) {/*1:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800114 KeyEvent *ke = new KeyEvent;
115 ke->down_ts_us = getSystemTimeUs();
116 ke->keyCode = key_code;
117 ke->keyState = value; /*key down*/
118 ke->longPress = false;
ziheng.li413496c2021-11-19 10:56:55 +0800119 ke->curlongPress = false;
jiacai.liu7c96e572019-11-28 14:09:36 +0800120 mKeyEventVec.push_back(ke);
121
Lianghu Sue1655222017-05-24 14:52:06 +0800122 ++key_down_count;
123 key_last_down = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800124 key_timer_t* info = new key_timer_t;
125 info->ep = this;
126 info->key_code = key_code;
127 info->count = key_down_count;
jiacai.liu7c96e572019-11-28 14:09:36 +0800128 info->ke = ke;
Lianghu Sue1655222017-05-24 14:52:06 +0800129 pthread_t thread;
130 pthread_create(&thread, nullptr, &EventsProcess::time_key_helper, info);
131 pthread_detach(thread);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800132 } else if(value == 2){/*2:key repeat*/
133 } else {/*0:key down*/
jiacai.liu7c96e572019-11-28 14:09:36 +0800134 for (std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
135 iter != mKeyEventVec.end(); ++iter) {
136 if ((*iter)->keyCode == key_code && (*iter)->keyState == 1) {
137 (*iter)->up_ts_us = getSystemTimeUs();
138 (*iter)->keyState = value; /*key up*/
ziheng.li413496c2021-11-19 10:56:55 +0800139 if ((*iter)->longPress || (*iter)->curlongPress) {
140 (*iter)->curlongPress = false;
141 flag = true;
142 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800143 break;
144 }
145 }
146
Lianghu Sue1655222017-05-24 14:52:06 +0800147 if (key_last_down == key_code) {
Lianghu Sue1655222017-05-24 14:52:06 +0800148 register_key = true;
149 }
150 key_last_down = -1;
151 }
152 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800153 last_key = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800154 if (register_key) {
ziheng.li413496c2021-11-19 10:56:55 +0800155 EnqueueKey(key_code, flag);
Lianghu Sue1655222017-05-24 14:52:06 +0800156 }
157}
158
159void* EventsProcess::time_key_helper(void* cookie) {
160 key_timer_t* info = (key_timer_t*) cookie;
jiacai.liu7c96e572019-11-28 14:09:36 +0800161 info->ep->time_key(info);
Lianghu Sue1655222017-05-24 14:52:06 +0800162 delete info;
163 return nullptr;
164}
165
jiacai.liu7c96e572019-11-28 14:09:36 +0800166void EventsProcess::time_key(key_timer_t *info) {
167 int key_code = info->key_code;
168 int count = info->count;
ziheng.li413496c2021-11-19 10:56:55 +0800169 int keymode = getKeyMode(key_code);
Lianghu Sue1655222017-05-24 14:52:06 +0800170 usleep(750000); // 750 ms == "long"
Lianghu Sue1655222017-05-24 14:52:06 +0800171 pthread_mutex_lock(&key_queue_mutex);
172 if (key_last_down == key_code && key_down_count == count) {
ziheng.li413496c2021-11-19 10:56:55 +0800173 if (info->ke) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800174 info->ke->longPress = true;
ziheng.li413496c2021-11-19 10:56:55 +0800175 if (keymode != 0)
176 info->ke->curlongPress = true;
177 }
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800178 else {
179 printf("##recive key but no events##\n");
180 pthread_mutex_unlock(&key_queue_mutex);
181 return;
182 }
Lianghu Sue1655222017-05-24 14:52:06 +0800183 }
ziheng.li413496c2021-11-19 10:56:55 +0800184 if (info->ke->longPress && info->ke->curlongPress) {
185 pthread_mutex_unlock(&key_queue_mutex);
186 while (key_last_down == key_code && key_down_count == count) {
187 EnqueueKey(key_code, false);
188 }
189 } else {
190 pthread_mutex_unlock(&key_queue_mutex);
191 }
Lianghu Sue1655222017-05-24 14:52:06 +0800192}
193
Lianghu Sue1655222017-05-24 14:52:06 +0800194
Renjun Xu044c8ec2017-08-17 19:01:14 +0800195const char* EventsProcess::getKeyType(int key) {
196 int i;
197 for (i = 0; i < num_keys; i++) {
198 KeyMapItem_t* v = &keys_map[i];
199 if (v->value == key)
200 return v->type;
Lianghu Sue1655222017-05-24 14:52:06 +0800201 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800202
203 return NULL;
Lianghu Sue1655222017-05-24 14:52:06 +0800204}
205
ziheng.li413496c2021-11-19 10:56:55 +0800206int EventsProcess::getKeyMode(int key) {
207 int i;
208 for (i = 0; i < num_keys; i++) {
209 KeyMapItem_t* v = &keys_map[i];
210 if (v->value == key)
211 return v->mode;
212 }
213
214 return 0;
215}
216
Lianghu Sue1655222017-05-24 14:52:06 +0800217void EventsProcess::load_key_map() {
218 FILE* fstab = fopen("/etc/gpio_key.kl", "r");
219 if (fstab != NULL) {
220 printf("loaded /etc/gpio_key.kl\n");
221 int alloc = 2;
222 keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t));
Lianghu Sue1655222017-05-24 14:52:06 +0800223 num_keys = 0;
224
225 char buffer[1024];
226 int i;
227 int value = -1;
228 while (fgets(buffer, sizeof(buffer)-1, fstab)) {
229 for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
230
231 if (buffer[i] == '\0' || buffer[i] == '#') continue;
232
233 char* original = strdup(buffer);
Lianghu Sue1655222017-05-24 14:52:06 +0800234 char* type = strtok(original+i, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800235 char* key = strtok(NULL, " \t\n");
ziheng.li413496c2021-11-19 10:56:55 +0800236 char* mode = strtok(NULL, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800237 value = atoi (key);
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800238 if (type && (value > 0)) {
Lianghu Sue1655222017-05-24 14:52:06 +0800239 while (num_keys >= alloc) {
240 alloc *= 2;
241 keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t));
242 }
243 keys_map[num_keys].type = strdup(type);
244 keys_map[num_keys].value = value;
ziheng.li413496c2021-11-19 10:56:55 +0800245 if (!mode)
246 keys_map[num_keys].mode = 0;
247 else
248 keys_map[num_keys].mode = atoi (mode);
Lianghu Sue1655222017-05-24 14:52:06 +0800249
250 ++num_keys;
251 } else {
252 printf("error: skipping malformed keyboard.lk line: %s\n", original);
253 }
254 free(original);
255 }
256
257 fclose(fstab);
kirk.wang2ec32a22022-11-16 13:40:31 +0800258
Lianghu Sue1655222017-05-24 14:52:06 +0800259 } else {
260 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800261 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800262 keys_map = g_default_keymap;
Jiacai.Liu71a747b2022-07-25 15:01:56 +0800263 }
kirk.wang2ec32a22022-11-16 13:40:31 +0800264 printf("keyboard key map table:\n");
265 int i;
266 for (i = 0; i < num_keys; ++i) {
267 KeyMapItem_t* v = &keys_map[i];
268 printf(" %d type:%s value:%d mode:%d\n", i, v->type, v->value, v->mode);
269 }
Lianghu Sue1655222017-05-24 14:52:06 +0800270}
271
272int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800273 int i;
274 for (i = 0; i < num_keys; i++) {
275 KeyMapItem_t* v = &keys_map[i];
276 if (v->value == key)
277 return v->value;
278 }
Lianghu Sue1655222017-05-24 14:52:06 +0800279
Renjun Xu044c8ec2017-08-17 19:01:14 +0800280 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800281}
282
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800283long checkEventTime(struct timeval *before, struct timeval *later) {
284 time_t before_sec = before->tv_sec;
285 suseconds_t before_usec = before->tv_usec;
286 time_t later_sec = later->tv_sec;
287 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800288
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800289 long sec_diff = (later_sec - before_sec) * 1000;
290 if (sec_diff < 0)
291 return true;
292
293 long ret = sec_diff + (later_usec - before_usec) / 1000;
294 if (ret >= KEY_EVENT_TIME_INTERVAL)
295 return true;
296
297 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800298}
299
ziheng.li413496c2021-11-19 10:56:55 +0800300void EventsProcess::EnqueueKey(int key_code, bool flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800301 struct timeval now;
302 gettimeofday(&now, nullptr);
303
Lianghu Sue1655222017-05-24 14:52:06 +0800304 pthread_mutex_lock(&key_queue_mutex);
305 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
306 if (key_queue_len < queue_max) {
ziheng.li413496c2021-11-19 10:56:55 +0800307 if (last_key != key_code || checkEventTime(&last_queue_time, &now) || flag) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800308 key_queue[key_queue_len++] = key_code;
309 last_queue_time = now;
310 }
Lianghu Sue1655222017-05-24 14:52:06 +0800311 pthread_cond_signal(&key_queue_cond);
312 }
313 pthread_mutex_unlock(&key_queue_mutex);
314}
315
shu.wanga67d5ea2022-01-14 13:43:06 +0800316#ifdef FILTER_POWERKEY
317bool filter_power_key(const char* key_type)
318{
319#define FILTER_KEY_TIME 150 //ms
320 static long last_time_ms = -1;
321
322 if (!strcmp(key_type, "power")) {
323 struct timeval now_time;
324 gettimeofday(&now_time, nullptr);
325 long now_time_ms = now_time.tv_sec*1000 + now_time.tv_usec/1000;
326 if (last_time_ms == -1 || (now_time_ms - last_time_ms) >= FILTER_KEY_TIME) {
327 last_time_ms = now_time_ms;
328 return true;
329 } else {
330 return false;
331 }
332 } else {
333 return true;
334 }
335#undef FILTER_KEY_TIME
336}
337#endif
338
Renjun Xu044c8ec2017-08-17 19:01:14 +0800339void EventsProcess::WaitKey() {
ziheng.li413496c2021-11-19 10:56:55 +0800340 bool cur_longpress = false;
341 bool execute = false;
Lianghu Sue1655222017-05-24 14:52:06 +0800342 pthread_mutex_lock(&key_queue_mutex);
343
Lianghu Sue1655222017-05-24 14:52:06 +0800344 do {
345 struct timeval now;
346 struct timespec timeout;
347 gettimeofday(&now, nullptr);
348 timeout.tv_sec = now.tv_sec;
349 timeout.tv_nsec = now.tv_usec * 1000;
350 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
351
352 int rc = 0;
353 while (key_queue_len == 0 && rc != ETIMEDOUT) {
354 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
355 }
356 } while (key_queue_len == 0);
357
358 int key = -1;
jiacai.liu7c96e572019-11-28 14:09:36 +0800359 KeyEvent *keyEvent = nullptr;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800360 char* event_str;
361 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800362 if (key_queue_len > 0) {
363 key = key_queue[0];
Jiacai.Liu18f542a2022-07-25 15:01:56 +0800364 memmove(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
Lianghu Sue1655222017-05-24 14:52:06 +0800365 }
jiacai.liu7c96e572019-11-28 14:09:36 +0800366
367 std::vector<KeyEvent *>::iterator iter = mKeyEventVec.begin();
368 //should remove zombie key down long long time?
369 for (; iter != mKeyEventVec.end();) {
ziheng.li413496c2021-11-19 10:56:55 +0800370 if ((*iter)->keyCode == key && ((*iter)->keyState == 0 || (*iter)->curlongPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800371 keyEvent = *iter;
ziheng.li413496c2021-11-19 10:56:55 +0800372 if (keyEvent->curlongPress)
373 cur_longpress = true;
374 else
375 iter = mKeyEventVec.erase(iter);
jiacai.liu7c96e572019-11-28 14:09:36 +0800376 break;
377 } else {
378 ++iter;
379 }
380 }
381
Lianghu Sue1655222017-05-24 14:52:06 +0800382 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800383 const char* keyType=getKeyType(key);
ziheng.li413496c2021-11-19 10:56:55 +0800384 int keymode=getKeyMode(key);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800385 int res;
386 memset(buf,'\0',sizeof(buf));
387 if (keyType != NULL) {
ziheng.li413496c2021-11-19 10:56:55 +0800388 if (keyEvent && cur_longpress && keyEvent->longPress && keymode != 0) {
389 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","curlongpress",keyType);
390 execute = true;
391 } else if (keyEvent && !cur_longpress && keyEvent->longPress && keymode != 1) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800392 uint64_t duration = 0;
393 if (keyEvent->up_ts_us < keyEvent->down_ts_us) {
394 duration = UINT64_MAX - keyEvent->down_ts_us + keyEvent->up_ts_us;
395 duration /= 1000LL;
396 } else {
397 duration = (keyEvent->up_ts_us - keyEvent->down_ts_us)/1000LL;
398 }
Lianghu Sue1655222017-05-24 14:52:06 +0800399
jiacai.liu7c96e572019-11-28 14:09:36 +0800400 sprintf(buf,"%s %s%s %llu","/etc/adckey/adckey_function.sh","longpress",keyType, duration);
ziheng.li413496c2021-11-19 10:56:55 +0800401 execute = true;
402 } else if (!(keyEvent && keyEvent->longPress)) {
jiacai.liu7c96e572019-11-28 14:09:36 +0800403 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
shu.wanga67d5ea2022-01-14 13:43:06 +0800404#ifdef FILTER_POWERKEY
405 execute = filter_power_key(keyType);
406#else
ziheng.li413496c2021-11-19 10:56:55 +0800407 execute = true;
shu.wanga67d5ea2022-01-14 13:43:06 +0800408#endif
jiacai.liu7c96e572019-11-28 14:09:36 +0800409 }
ziheng.li413496c2021-11-19 10:56:55 +0800410 if (execute) {
411 //printf("input_eventd: run %s\n", buf);
412 res=system(buf);
413 if (res != 0) printf("run %s exception!!!\n",buf);
414 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800415 }
Lianghu Sue1655222017-05-24 14:52:06 +0800416
jiacai.liu7c96e572019-11-28 14:09:36 +0800417 //release
ziheng.li413496c2021-11-19 10:56:55 +0800418 if (!cur_longpress)
419 delete keyEvent;
jiacai.liu7c96e572019-11-28 14:09:36 +0800420}