blob: 76740d08a269482294548b7d742e2e50cbc1dc4d [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
Lianghu Sue1655222017-05-24 14:52:06 +080088void EventsProcess::ProcessKey(int key_code, int value) {
89 bool register_key = false;
90 bool long_press = false;
91
92 pthread_mutex_lock(&key_queue_mutex);
93 key_pressed[key_code] = value;
Renjun Xu044c8ec2017-08-17 19:01:14 +080094 if (value == 1) {/*1:key down*/
Lianghu Sue1655222017-05-24 14:52:06 +080095 ++key_down_count;
96 key_last_down = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +080097 key_timer_t* info = new key_timer_t;
98 info->ep = this;
99 info->key_code = key_code;
100 info->count = key_down_count;
101 pthread_t thread;
102 pthread_create(&thread, nullptr, &EventsProcess::time_key_helper, info);
103 pthread_detach(thread);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800104 } else if(value == 2){/*2:key repeat*/
105 } else {/*0:key down*/
Lianghu Sue1655222017-05-24 14:52:06 +0800106 if (key_last_down == key_code) {
Lianghu Sue1655222017-05-24 14:52:06 +0800107 register_key = true;
108 }
109 key_last_down = -1;
110 }
111 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800112 last_key = key_code;
Lianghu Sue1655222017-05-24 14:52:06 +0800113 if (register_key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800114 EnqueueKey(key_code);
Lianghu Sue1655222017-05-24 14:52:06 +0800115 }
116}
117
118void* EventsProcess::time_key_helper(void* cookie) {
119 key_timer_t* info = (key_timer_t*) cookie;
120 info->ep->time_key(info->key_code, info->count);
121 delete info;
122 return nullptr;
123}
124
125void EventsProcess::time_key(int key_code, int count) {
126 usleep(750000); // 750 ms == "long"
127 bool long_press = false;
128 pthread_mutex_lock(&key_queue_mutex);
129 if (key_last_down == key_code && key_down_count == count) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800130 long_press = true;
Lianghu Sue1655222017-05-24 14:52:06 +0800131 }
132 pthread_mutex_unlock(&key_queue_mutex);
133 if (long_press)
Renjun Xu044c8ec2017-08-17 19:01:14 +0800134 KeyLongPress(key_code);
Lianghu Sue1655222017-05-24 14:52:06 +0800135}
136
Lianghu Sue1655222017-05-24 14:52:06 +0800137
Renjun Xu044c8ec2017-08-17 19:01:14 +0800138const char* EventsProcess::getKeyType(int key) {
139 int i;
140 for (i = 0; i < num_keys; i++) {
141 KeyMapItem_t* v = &keys_map[i];
142 if (v->value == key)
143 return v->type;
Lianghu Sue1655222017-05-24 14:52:06 +0800144 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800145
146 return NULL;
Lianghu Sue1655222017-05-24 14:52:06 +0800147}
148
149void EventsProcess::load_key_map() {
150 FILE* fstab = fopen("/etc/gpio_key.kl", "r");
151 if (fstab != NULL) {
152 printf("loaded /etc/gpio_key.kl\n");
153 int alloc = 2;
154 keys_map = (KeyMapItem_t*)malloc(alloc * sizeof(KeyMapItem_t));
Lianghu Sue1655222017-05-24 14:52:06 +0800155 num_keys = 0;
156
157 char buffer[1024];
158 int i;
159 int value = -1;
160 while (fgets(buffer, sizeof(buffer)-1, fstab)) {
161 for (i = 0; buffer[i] && isspace(buffer[i]); ++i);
162
163 if (buffer[i] == '\0' || buffer[i] == '#') continue;
164
165 char* original = strdup(buffer);
Lianghu Sue1655222017-05-24 14:52:06 +0800166 char* type = strtok(original+i, " \t\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800167 char* key = strtok(NULL, " \t\n");
168 value = atoi (key);
169 if (type && key && (value > 0)) {
Lianghu Sue1655222017-05-24 14:52:06 +0800170 while (num_keys >= alloc) {
171 alloc *= 2;
172 keys_map = (KeyMapItem_t*)realloc(keys_map, alloc*sizeof(KeyMapItem_t));
173 }
174 keys_map[num_keys].type = strdup(type);
175 keys_map[num_keys].value = value;
Lianghu Sue1655222017-05-24 14:52:06 +0800176
177 ++num_keys;
178 } else {
179 printf("error: skipping malformed keyboard.lk line: %s\n", original);
180 }
181 free(original);
182 }
183
184 fclose(fstab);
185 } else {
186 printf("error: failed to open /etc/gpio_key.kl, use default map\n");
Renjun Xu044c8ec2017-08-17 19:01:14 +0800187 num_keys = DEFAULT_KEY_NUM;
Lianghu Sue1655222017-05-24 14:52:06 +0800188 keys_map = g_default_keymap;
189 }
190
191 printf("keyboard key map table:\n");
192 int i;
193 for (i = 0; i < num_keys; ++i) {
194 KeyMapItem_t* v = &keys_map[i];
Renjun Xu044c8ec2017-08-17 19:01:14 +0800195 printf(" %d type:%s value:%d\n", i, v->type, v->value);
Lianghu Sue1655222017-05-24 14:52:06 +0800196 }
Lianghu Sue1655222017-05-24 14:52:06 +0800197}
198
199int EventsProcess::getMapKey(int key) {
Renjun Xu044c8ec2017-08-17 19:01:14 +0800200 int i;
201 for (i = 0; i < num_keys; i++) {
202 KeyMapItem_t* v = &keys_map[i];
203 if (v->value == key)
204 return v->value;
205 }
Lianghu Sue1655222017-05-24 14:52:06 +0800206
Renjun Xu044c8ec2017-08-17 19:01:14 +0800207 return -1;
Lianghu Sue1655222017-05-24 14:52:06 +0800208}
209
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800210long checkEventTime(struct timeval *before, struct timeval *later) {
211 time_t before_sec = before->tv_sec;
212 suseconds_t before_usec = before->tv_usec;
213 time_t later_sec = later->tv_sec;
214 suseconds_t later_usec = later->tv_usec;
Lianghu Su53dd4072017-05-26 19:04:48 +0800215
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800216 long sec_diff = (later_sec - before_sec) * 1000;
217 if (sec_diff < 0)
218 return true;
219
220 long ret = sec_diff + (later_usec - before_usec) / 1000;
221 if (ret >= KEY_EVENT_TIME_INTERVAL)
222 return true;
223
224 return false;
Lianghu Su53dd4072017-05-26 19:04:48 +0800225}
226
Lianghu Sue1655222017-05-24 14:52:06 +0800227void EventsProcess::EnqueueKey(int key_code) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800228 struct timeval now;
229 gettimeofday(&now, nullptr);
230
Lianghu Sue1655222017-05-24 14:52:06 +0800231 pthread_mutex_lock(&key_queue_mutex);
232 const int queue_max = sizeof(key_queue) / sizeof(key_queue[0]);
233 if (key_queue_len < queue_max) {
Lianghu Su4a0a8db2017-06-27 21:10:22 +0800234 if (last_key != key_code || checkEventTime(&last_queue_time, &now)) {
Lianghu Su53dd4072017-05-26 19:04:48 +0800235 key_queue[key_queue_len++] = key_code;
236 last_queue_time = now;
237 }
Lianghu Sue1655222017-05-24 14:52:06 +0800238 pthread_cond_signal(&key_queue_cond);
239 }
240 pthread_mutex_unlock(&key_queue_mutex);
241}
242
Renjun Xu044c8ec2017-08-17 19:01:14 +0800243void EventsProcess::WaitKey() {
Lianghu Sue1655222017-05-24 14:52:06 +0800244 pthread_mutex_lock(&key_queue_mutex);
245
Lianghu Sue1655222017-05-24 14:52:06 +0800246 do {
247 struct timeval now;
248 struct timespec timeout;
249 gettimeofday(&now, nullptr);
250 timeout.tv_sec = now.tv_sec;
251 timeout.tv_nsec = now.tv_usec * 1000;
252 timeout.tv_sec += WAIT_KEY_TIMEOUT_SEC;
253
254 int rc = 0;
255 while (key_queue_len == 0 && rc != ETIMEDOUT) {
256 rc = pthread_cond_timedwait(&key_queue_cond, &key_queue_mutex, &timeout);
257 }
258 } while (key_queue_len == 0);
259
260 int key = -1;
Renjun Xu044c8ec2017-08-17 19:01:14 +0800261 char* event_str;
262 char buf[100];
Lianghu Sue1655222017-05-24 14:52:06 +0800263 if (key_queue_len > 0) {
264 key = key_queue[0];
265 memcpy(&key_queue[0], &key_queue[1], sizeof(int) * --key_queue_len);
266 }
267 pthread_mutex_unlock(&key_queue_mutex);
Renjun Xu044c8ec2017-08-17 19:01:14 +0800268 const char* keyType=getKeyType(key);
269 int res;
270 memset(buf,'\0',sizeof(buf));
271 if (keyType != NULL) {
272 if (report_longpress_flag == true) {
273 //w_num=write(fifofd,"key1longpress\n",14);
274 }else{
275 sprintf(buf,"%s %s","/etc/adckey/adckey_function.sh",keyType);
276 res=system(buf);
277 if (res != 0) printf("run %s exception!!!\n",buf);
Lianghu Sue1655222017-05-24 14:52:06 +0800278 }
Renjun Xu044c8ec2017-08-17 19:01:14 +0800279 report_longpress_flag=false;
Lianghu Sue1655222017-05-24 14:52:06 +0800280 }
Lianghu Sue1655222017-05-24 14:52:06 +0800281}
282
Renjun Xu044c8ec2017-08-17 19:01:14 +0800283void EventsProcess::KeyLongPress(int key) {
284 char buf[100];
285 int res;
286 const char* keyType=getKeyType(key);
287 memset(buf,'\0',sizeof(buf));
288 if (keyType != NULL) {
289 sprintf(buf,"%s %s%s","/etc/adckey/adckey_function.sh","longpress",keyType);
290 res=system(buf);
291 if (res != 0) printf("run %s exception!!!\n",buf);
292 report_longpress_flag=true;
293 }
Lianghu Sue1655222017-05-24 14:52:06 +0800294}
295