0604c1157975c7dfeac5fd7c73f9867b4a948f8e
[apps/livebox/data-provider-master.git] / src / event.c
1 /*
2  * Copyright 2013  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.1 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://floralicense.org/license/
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <errno.h>
20 #include <pthread.h>
21 #include <unistd.h>
22 #include <fcntl.h>
23 #include <string.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26
27 #include <linux/input.h>
28
29 #include <Eina.h>
30 #include <Ecore.h>
31 #include <dlog.h>
32 #include <livebox-errno.h>
33
34 #include "util.h"
35 #include "debug.h"
36 #include "conf.h"
37 #include "event.h"
38
39 #define EVENT_CH        'e'
40
41 #if !defined(ABS_MT_TOOL_X)
42 #define ABS_MT_TOOL_X           0x3c    /* Center X tool position */
43 #endif
44
45 #if !defined(ABS_MT_TOOL_Y)
46 #define ABS_MT_TOOL_Y           0x3d    /* Center Y tool position */
47 #endif
48
49 int errno;
50
51 static struct info {
52         pthread_t tid;
53         Eina_List *event_list;
54         int handle;
55         pthread_mutex_t event_list_lock;
56         int evt_pipe[PIPE_MAX];
57         int tcb_pipe[PIPE_MAX];
58         Ecore_Fd_Handler *event_handler;
59
60         struct event_data event_data;
61
62         Eina_List *event_listener_list;
63         Eina_List *reactivate_list;
64 } s_info = {
65         .event_list = NULL,
66         .handle = -1,
67         .event_handler = NULL,
68
69         .event_data = {
70                 .x = -1,
71                 .y = -1,
72                 .device = -1,
73                 .slot = -1,
74                 .keycode = 0,
75         },
76
77         .event_listener_list = NULL,
78         .reactivate_list = NULL,
79 };
80
81 struct event_listener {
82         int (*event_cb)(enum event_state state, struct event_data *event, void *data);
83         void *cbdata;
84
85         enum event_state state;
86
87 #if defined(_USE_ECORE_TIME_GET)
88         double tv;
89 #else
90         struct timeval tv; /* Recording Activate / Deactivate time */
91 #endif
92         int x; /* RelX */
93         int y; /* RelY */
94 };
95
96 static int activate_thread(void);
97
98 HAPI int event_init(void)
99 {
100         int ret;
101         ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
102         if (ret != 0) {
103                 ErrPrint("Mutex: %s\n", strerror(ret));
104                 return LB_STATUS_ERROR_FAULT;
105         }
106         return LB_STATUS_SUCCESS;
107 }
108
109 HAPI int event_fini(void)
110 {
111         int ret;
112         ret = pthread_mutex_destroy(&s_info.event_list_lock);
113         if (ret != 0) {
114                 ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
115         }
116         return LB_STATUS_SUCCESS;
117 }
118
119 static inline int processing_input_event(struct input_event *event)
120 {
121         struct event_data *item;
122
123         switch (event->type) {
124         case EV_SYN:
125                 switch (event->code) {
126                         break;
127                 case SYN_CONFIG:
128                         break;
129                 case SYN_MT_REPORT:
130                 case SYN_REPORT:
131                         if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
132                                 /* Waiting full event packet */
133                                 break;
134                         }
135
136                         item = malloc(sizeof(*item));
137                         if (item) {
138                                 char event_ch = EVENT_CH;
139
140 #if defined(_USE_ECORE_TIME_GET)
141                                 s_info.event_data.tv = ecore_time_get();
142 #else
143                                 if (gettimeofday(&s_info.event_data.tv, NULL) < 0) {
144                                         ErrPrint("gettimeofday: %s\n", strerror(errno));
145                                 }
146 #endif
147
148                                 memcpy(item, &s_info.event_data, sizeof(*item));
149
150                                 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
151                                 s_info.event_list = eina_list_append(s_info.event_list, item);
152                                 CRITICAL_SECTION_END(&s_info.event_list_lock);
153
154                                 if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
155                                         ErrPrint("Unable to send an event: %s\n", strerror(errno));
156                                         return LB_STATUS_ERROR_IO;
157                                 }
158
159                                 /* Take a breathe */
160                                 pthread_yield();
161                         } else {
162                                 ErrPrint("Heap: %s\n", strerror(errno));
163                         }
164
165                         if (s_info.event_data.device < 0) {
166                                 s_info.event_data.x = -1;
167                                 s_info.event_data.y = -1;
168                                 s_info.event_data.slot = -1;
169                         }
170                         break;
171                 /*
172                 case SYN_DROPPED:
173                         DbgPrint("EV_SYN, SYN_DROPPED\n");
174                         break;
175                 */
176                 default:
177                         DbgPrint("EV_SYN, 0x%x\n", event->code);
178                         break;
179                 }
180                 break;
181         case EV_KEY:
182                 DbgPrint("EV_KEY: 0x%X\n", event->value);
183                 s_info.event_data.keycode = event->value;
184                 break;
185         case EV_REL:
186                 break;
187         case EV_ABS:
188                 switch (event->code) {
189                 case ABS_DISTANCE:
190                         s_info.event_data.distance = event->value;
191                         break;
192                 case ABS_MT_TOOL_X:
193                 case ABS_MT_TOOL_Y:
194                         break;
195                 case ABS_MT_POSITION_X:
196                         s_info.event_data.x = event->value;
197                         break;
198                 case ABS_MT_POSITION_Y:
199                         s_info.event_data.y = event->value;
200                         break;
201                 case ABS_MT_SLOT:
202                         s_info.event_data.slot = event->value;
203                         break;
204                 case ABS_MT_TRACKING_ID:
205                         s_info.event_data.device = event->value;
206                         break;
207                 case ABS_MT_TOUCH_MAJOR:
208                         s_info.event_data.touch.major = event->value;
209                         break;
210                 case ABS_MT_TOUCH_MINOR:
211                         s_info.event_data.touch.minor = event->value;
212                         break;
213                 case ABS_MT_WIDTH_MAJOR:
214                         s_info.event_data.width.major = event->value;
215                         break;
216                 case ABS_MT_WIDTH_MINOR:
217                         s_info.event_data.width.minor = event->value;
218                         break;
219                 default:
220                         DbgPrint("EV_ABS, 0x%x\n", event->code);
221                         break;
222                 }
223                 break;
224         case EV_MSC:
225                 break;
226         case EV_SW:
227                 break;
228         case EV_LED:
229                 break;
230         case EV_SND:
231                 break;
232         case EV_REP:
233                 break;
234         case EV_FF:
235                 break;
236         case EV_PWR:
237                 break;
238         case EV_FF_STATUS:
239                 break;
240         default:
241                 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
242                 break;
243         }
244
245         return LB_STATUS_SUCCESS;
246 }
247
248 static void *event_thread_main(void *data)
249 {
250         fd_set set;
251         long ret = 0;
252         struct input_event input_event;
253         char *ptr = (char *)&input_event;
254         int offset = 0;
255         int readsize = 0;
256         int fd;
257
258         DbgPrint("Initiated\n");
259
260         while (1) {
261                 FD_ZERO(&set);
262                 FD_SET(s_info.handle, &set);
263                 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
264
265                 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
266                 ret = select(fd + 1, &set, NULL, NULL, NULL);
267                 if (ret < 0) {
268                         ret = -errno;
269                         if (errno == EINTR) {
270                                 DbgPrint("Select receives INTR\n");
271                                 continue;
272                         }
273                         ErrPrint("Error: %s\n", strerror(errno));
274                         break;
275                 } else if (ret == 0) {
276                         ErrPrint("Timeout expired\n");
277                         ret = LB_STATUS_ERROR_TIMEOUT;
278                         break;
279                 }
280
281                 if (FD_ISSET(s_info.handle, &set)) {
282                         readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
283                         if (readsize < 0) {
284                                 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
285                                 ret = LB_STATUS_ERROR_FAULT;
286                                 break;
287                         }
288
289                         offset += readsize;
290                         if (offset == sizeof(input_event)) {
291                                 offset = 0;
292                                 if (processing_input_event(&input_event) < 0) {
293                                         ret = LB_STATUS_ERROR_FAULT;
294                                         break;
295                                 }
296                         }
297                 }
298
299                 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
300                         char event_ch;
301
302                         if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
303                                 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
304                         }
305
306                         ret = LB_STATUS_ERROR_CANCEL;
307                         break;
308                 }
309         }
310
311         return (void *)ret;
312 }
313
314 static inline void clear_all_listener_list(void)
315 {
316         struct event_listener *listener;
317         enum event_state next_state;
318         Eina_List *l;
319         Eina_List *n;
320
321         s_info.event_handler = NULL;
322         CLOSE_PIPE(s_info.evt_pipe);
323
324         while (s_info.event_listener_list) {
325                 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
326                         switch (listener->state) {
327                         case EVENT_STATE_ACTIVATE:
328                                 next_state = EVENT_STATE_ACTIVATED;
329                                 break;
330                         case EVENT_STATE_ACTIVATED:
331                                 next_state = EVENT_STATE_DEACTIVATE;
332                                 break;
333                         case EVENT_STATE_DEACTIVATE:
334                                 next_state = EVENT_STATE_DEACTIVATED;
335                                 break;
336                         case EVENT_STATE_DEACTIVATED:
337                         default:
338                                 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
339                                 DbgFree(listener);
340                                 continue;
341                         }
342
343                         if (listener->event_cb(listener->state, &s_info.event_data, listener->cbdata) < 0) {
344                                 if (eina_list_data_find(s_info.event_listener_list, listener)) {
345                                         s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
346                                         DbgFree(listener);
347                                         continue;
348                                 }
349                         }
350
351                         listener->state = next_state;
352                 }
353         }
354 }
355
356 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
357 {
358         int fd;
359         struct event_data *item;
360         char event_ch;
361         struct event_listener *listener;
362         Eina_List *l;
363         Eina_List *n;
364         enum event_state next_state;
365         enum event_state cur_state;
366         struct event_data modified_item;
367
368         fd = ecore_main_fd_handler_fd_get(handler);
369         if (fd < 0) {
370                 ErrPrint("Invalid fd\n");
371                 return ECORE_CALLBACK_CANCEL;
372         }
373
374         if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
375                 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
376                 return ECORE_CALLBACK_CANCEL;
377         }
378
379         CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
380         item = eina_list_nth(s_info.event_list, 0);
381         if (item) {
382                 s_info.event_list = eina_list_remove(s_info.event_list, item);
383         }
384         CRITICAL_SECTION_END(&s_info.event_list_lock);
385
386         if (item) {
387                 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
388                         switch (listener->state) {
389                         case EVENT_STATE_ACTIVATE:
390 #if defined(_USE_ECORE_TIME_GET)
391                                 if (listener->tv > item->tv) {
392                                         continue;
393                                 }
394 #else
395                                 if (timercmp(&listener->tv, &item->tv, >)) {
396                                         /* Ignore previous events before activating this listener */
397                                         continue;
398                                 }
399 #endif
400
401                                 next_state = EVENT_STATE_ACTIVATED;
402                                 cur_state = listener->state;
403                                 break;
404                         case EVENT_STATE_DEACTIVATE:
405 #if defined(_USE_ECORE_TIME_GET)
406                                 if (listener->tv > item->tv) {
407                                         /* Consuming all events occurred while activating this listener */
408                                         cur_state = EVENT_STATE_ACTIVATED;
409                                         next_state = EVENT_STATE_ACTIVATED;
410                                         break;
411                                 }
412 #else
413                                 if (timercmp(&listener->tv, &item->tv, >)) {
414                                         /* Consuming all events occurred while activating this listener */
415                                         cur_state = EVENT_STATE_ACTIVATED;
416                                         next_state = EVENT_STATE_ACTIVATED;
417                                         break;
418                                 }
419 #endif
420
421                                 cur_state = listener->state;
422                                 next_state = EVENT_STATE_DEACTIVATED;
423                                 break;
424                         case EVENT_STATE_ACTIVATED:
425                                 cur_state = listener->state;
426                                 next_state = listener->state;
427                                 break;
428                         case EVENT_STATE_DEACTIVATED:
429                         default:
430                                 /* Remove this from the list */
431                                         /* Check the item again. the listener can be deleted from the callback */
432                                 if (eina_list_data_find(s_info.event_listener_list, listener)) {
433                                         s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
434                                         DbgFree(listener);
435                                 }
436
437                                 continue;
438                         }
439
440                         memcpy(&modified_item, item, sizeof(modified_item));
441                         modified_item.x -= listener->x;
442                         modified_item.y -= listener->y;
443
444                         if (listener->event_cb(cur_state, &modified_item, listener->cbdata) < 0) {
445                                 if (eina_list_data_find(s_info.event_listener_list, listener)) {
446                                         s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
447                                         DbgFree(listener);
448                                         continue;
449                                 }
450                         }
451
452                         listener->state = next_state;
453                 }
454
455                 DbgFree(item);
456         }
457
458         if (s_info.handle < 0 && !s_info.event_list) {
459                 /* This callback must has to clear all listeners in this case */
460                 clear_all_listener_list();
461
462                 EINA_LIST_FREE(s_info.reactivate_list, listener) {
463                         s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
464                 }
465
466                 if (s_info.event_listener_list) {
467                         if (activate_thread() < 0) {
468                                 EINA_LIST_FREE(s_info.event_listener_list, listener) {
469                                         (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
470                                 }
471                         }
472                 }
473
474                 return ECORE_CALLBACK_CANCEL;
475         }
476
477         return ECORE_CALLBACK_RENEW;
478 }
479
480 static int activate_thread(void)
481 {
482         int status;
483
484         s_info.handle = open(INPUT_PATH, O_RDONLY);
485         if (s_info.handle < 0) {
486                 ErrPrint("Unable to access the device: %s\n", strerror(errno));
487                 return LB_STATUS_ERROR_IO;
488         }
489
490         if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
491                 ErrPrint("Error: %s\n", strerror(errno));
492         }
493
494         if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
495                 ErrPrint("Error: %s\n", strerror(errno));
496         }
497
498         status = pipe2(s_info.evt_pipe, O_CLOEXEC);
499         if (status < 0) {
500                 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
501                 if (close(s_info.handle) < 0) {
502                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
503                 }
504                 s_info.handle = -1;
505                 return LB_STATUS_ERROR_FAULT;
506         }
507
508         status = pipe2(s_info.tcb_pipe, O_CLOEXEC);
509         if (status < 0) {
510                 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
511                 if (close(s_info.handle) < 0) {
512                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
513                 }
514                 s_info.handle = -1;
515                 CLOSE_PIPE(s_info.evt_pipe);
516                 return LB_STATUS_ERROR_FAULT;
517         }
518
519         s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
520         if (!s_info.event_handler) {
521                 if (close(s_info.handle) < 0) {
522                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
523                 }
524                 s_info.handle = -1;
525
526                 CLOSE_PIPE(s_info.tcb_pipe);
527                 CLOSE_PIPE(s_info.evt_pipe);
528                 return LB_STATUS_ERROR_FAULT;
529         }
530
531         status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
532         if (status != 0) {
533                 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
534                 ecore_main_fd_handler_del(s_info.event_handler);
535                 s_info.event_handler = NULL;
536
537                 if (close(s_info.handle) < 0) {
538                         ErrPrint("close: %s\n", strerror(errno));
539                 }
540                 s_info.handle = -1;
541
542                 CLOSE_PIPE(s_info.tcb_pipe);
543                 CLOSE_PIPE(s_info.evt_pipe);
544                 return LB_STATUS_ERROR_FAULT;
545         }
546
547         DbgPrint("Event handler activated\n");
548         return LB_STATUS_SUCCESS;
549 }
550
551 /*!
552  * x, y is the starting point.
553  */
554 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
555 {
556         struct event_listener *listener;
557         int ret = LB_STATUS_SUCCESS;
558
559         listener = malloc(sizeof(*listener));
560         if (!listener) {
561                 ErrPrint("Heap: %s\n", strerror(errno));
562                 return LB_STATUS_ERROR_MEMORY;
563         }
564
565 #if defined(_USE_ECORE_TIME_GET)
566         listener->tv = ecore_time_get();
567 #else
568         if (gettimeofday(&listener->tv, NULL) < 0) {
569                 ErrPrint("gettimeofday: %s\n", strerror(errno));
570                 DbgFree(listener);
571                 return LB_STATUS_ERROR_FAULT;
572         }
573 #endif
574
575         listener->event_cb = event_cb;
576         listener->cbdata = data;
577         listener->state = EVENT_STATE_ACTIVATE;
578         listener->x = x;
579         listener->y = y;
580
581         if (s_info.handle < 0) {
582                 /*!
583                  * \note
584                  * We don't need to lock to access event_list here.
585                  * If the _sinfo.handle is greater than 0, the event_list will not be touched.
586                  * But if the s_info.handle is less than 0, it means, there is not thread,
587                  * so we can access the event_list without lock.
588                  */
589                 if (s_info.event_list) {
590                         DbgPrint("Event thread is deactivating now. activating will be delayed\n");
591                         s_info.reactivate_list = eina_list_append(s_info.reactivate_list, listener);
592                 } else {
593                         s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
594
595                         if ((ret = activate_thread()) < 0) {
596                                 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
597                                 DbgFree(listener);
598                         }
599                 }
600         } else {
601                 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
602         }
603
604         return ret;
605 }
606
607 HAPI int event_deactivate(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
608 {
609         int status;
610         void *ret;
611         char event_ch = EVENT_CH;
612         struct event_listener *listener = NULL;
613         Eina_List *l;
614         int keep_thread = 0;
615
616         EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
617                 if (listener->event_cb == event_cb && listener->cbdata == data) {
618                         listener->state = EVENT_STATE_DEACTIVATE;
619                 }
620
621                 keep_thread += (listener->state == EVENT_STATE_ACTIVATE || listener->state == EVENT_STATE_ACTIVATED);
622         }
623
624         if (!listener) {
625                 ErrPrint("Listener is not registered\n");
626                 return LB_STATUS_ERROR_NOT_EXIST;
627         }
628
629         if (s_info.handle < 0) {
630                 ErrPrint("Event handler is not actiavated\n");
631                 DbgFree(listener);
632                 return LB_STATUS_SUCCESS;
633         }
634
635         if (keep_thread) {
636                 return LB_STATUS_SUCCESS;
637         }
638
639         /* Terminating thread */
640         if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
641                 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
642         }
643
644         status = pthread_join(s_info.tid, &ret);
645         if (status != 0) {
646                 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
647         } else {
648                 DbgPrint("Thread returns: %p\n", ret);
649         }
650
651         if (close(s_info.handle) < 0) {
652                 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
653         }
654
655         s_info.handle = -1;
656         DbgPrint("Event handler deactivated\n");
657
658         CLOSE_PIPE(s_info.tcb_pipe);
659
660         if (!eina_list_count(s_info.event_list)) {
661                 ecore_main_fd_handler_del(s_info.event_handler);
662                 clear_all_listener_list();
663         }
664
665         s_info.event_data.x = -1;
666         s_info.event_data.y = -1;
667         s_info.event_data.slot = -1;
668         return LB_STATUS_SUCCESS;
669 }
670
671 HAPI int event_is_activated(void)
672 {
673         return s_info.handle >= 0;
674 }
675
676 /* End of a file */