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