Fix i586 build error
[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                         }
160                         break;
161                 /*
162                 case SYN_DROPPED:
163                         DbgPrint("EV_SYN, SYN_DROPPED\n");
164                         break;
165                 */
166                 default:
167                         DbgPrint("EV_SYN, 0x%x\n", event->code);
168                         break;
169                 }
170                 break;
171         case EV_KEY:
172                 break;
173         case EV_REL:
174                 break;
175         case EV_ABS:
176                 switch (event->code) {
177                 case ABS_DISTANCE:
178                         s_info.event_data.distance = event->value;
179                         break;
180                 case ABS_MT_TOOL_X:
181                 case ABS_MT_TOOL_Y:
182                         break;
183                 case ABS_MT_POSITION_X:
184                         s_info.event_data.x = event->value;
185                         break;
186                 case ABS_MT_POSITION_Y:
187                         s_info.event_data.y = event->value;
188                         break;
189                 case ABS_MT_SLOT:
190                         s_info.event_data.slot = event->value;
191                         break;
192                 case ABS_MT_TRACKING_ID:
193                         s_info.event_data.device = event->value;
194                         break;
195                 case ABS_MT_TOUCH_MAJOR:
196                         s_info.event_data.touch.major = event->value;
197                         break;
198                 case ABS_MT_TOUCH_MINOR:
199                         s_info.event_data.touch.minor = event->value;
200                         break;
201                 case ABS_MT_WIDTH_MAJOR:
202                         s_info.event_data.width.major = event->value;
203                         break;
204                 case ABS_MT_WIDTH_MINOR:
205                         s_info.event_data.width.minor = event->value;
206                         break;
207                 default:
208                         DbgPrint("EV_ABS, 0x%x\n", event->code);
209                         break;
210                 }
211                 break;
212         case EV_MSC:
213                 break;
214         case EV_SW:
215                 break;
216         case EV_LED:
217                 break;
218         case EV_SND:
219                 break;
220         case EV_REP:
221                 break;
222         case EV_FF:
223                 break;
224         case EV_PWR:
225                 break;
226         case EV_FF_STATUS:
227                 break;
228         default:
229                 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
230                 break;
231         }
232
233         return LB_STATUS_SUCCESS;
234 }
235
236 static void *event_thread_main(void *data)
237 {
238         fd_set set;
239         int ret = 0;
240         struct input_event input_event;
241         char *ptr = (char *)&input_event;
242         int offset = 0;
243         int readsize = 0;
244         int fd;
245
246         DbgPrint("Initiated\n");
247
248         while (1) {
249                 FD_ZERO(&set);
250                 FD_SET(s_info.handle, &set);
251                 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
252
253                 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
254                 ret = select(fd + 1, &set, NULL, NULL, NULL);
255                 if (ret < 0) {
256                         ret = -errno;
257                         if (errno == EINTR) {
258                                 DbgPrint("Select receives INTR\n");
259                                 continue;
260                         }
261                         ErrPrint("Error: %s\n", strerror(errno));
262                         break;
263                 } else if (ret == 0) {
264                         ErrPrint("Timeout expired\n");
265                         ret = LB_STATUS_ERROR_TIMEOUT;
266                         break;
267                 }
268
269                 if (FD_ISSET(s_info.handle, &set)) {
270                         readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
271                         if (readsize < 0) {
272                                 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
273                                 ret = LB_STATUS_ERROR_FAULT;
274                                 break;
275                         }
276
277                         offset += readsize;
278                         if (offset == sizeof(input_event)) {
279                                 offset = 0;
280                                 if (processing_input_event(&input_event) < 0) {
281                                         ret = LB_STATUS_ERROR_FAULT;
282                                         break;
283                                 }
284                         }
285                 }
286
287                 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
288                         char event_ch;
289
290                         if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
291                                 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
292                         }
293
294                         ret = LB_STATUS_ERROR_CANCEL;
295                         break;
296                 }
297         }
298
299         return (void *)ret;
300 }
301
302 static inline void clear_all_listener_list(void)
303 {
304         struct event_listener *listener;
305         enum event_state next_state;
306         Eina_List *l;
307         Eina_List *n;
308
309         s_info.event_handler = NULL;
310         CLOSE_PIPE(s_info.evt_pipe);
311
312         while (s_info.event_listener_list) {
313                 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
314                         switch (listener->state) {
315                         case EVENT_STATE_ACTIVATE:
316                                 next_state = EVENT_STATE_ACTIVATED;
317                                 break;
318                         case EVENT_STATE_ACTIVATED:
319                                 next_state = EVENT_STATE_DEACTIVATE;
320                                 break;
321                         case EVENT_STATE_DEACTIVATE:
322                                 next_state = EVENT_STATE_DEACTIVATED;
323                                 break;
324                         case EVENT_STATE_DEACTIVATED:
325                         default:
326                                 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
327                                 free(listener);
328                                 continue;
329                         }
330
331                         if (listener->event_cb(listener->state, &s_info.event_data, listener->cbdata) < 0) {
332                                 if (eina_list_data_find(s_info.event_listener_list, listener)) {
333                                         s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
334                                         free(listener);
335                                         continue;
336                                 }
337                         }
338
339                         listener->state = next_state;
340                 }
341         }
342 }
343
344 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
345 {
346         int fd;
347         struct event_data *item;
348         char event_ch;
349         struct event_listener *listener;
350         Eina_List *l;
351         Eina_List *n;
352         enum event_state next_state;
353         enum event_state cur_state;
354         struct event_data modified_item;
355
356         fd = ecore_main_fd_handler_fd_get(handler);
357         if (fd < 0) {
358                 ErrPrint("Invalid fd\n");
359                 return ECORE_CALLBACK_CANCEL;
360         }
361
362         if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
363                 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
364                 return ECORE_CALLBACK_CANCEL;
365         }
366
367         CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
368         item = eina_list_nth(s_info.event_list, 0);
369         if (item) {
370                 s_info.event_list = eina_list_remove(s_info.event_list, item);
371         } else {
372                 ErrPrint("Unable to get event\n");
373         }
374         CRITICAL_SECTION_END(&s_info.event_list_lock);
375
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                                 free(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                                 free(listener);
422                                 continue;
423                         }
424                 }
425
426                 listener->state = next_state;
427         }
428
429         free(item);
430
431         if (s_info.handle < 0 && !s_info.event_list) {
432                 /* This callback must has to clear all listeners in this case */
433                 clear_all_listener_list();
434
435                 EINA_LIST_FREE(s_info.reactivate_list, listener) {
436                         s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
437                 }
438
439                 if (s_info.event_listener_list) {
440                         if (activate_thread() < 0) {
441                                 EINA_LIST_FREE(s_info.event_listener_list, listener) {
442                                         (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
443                                 }
444                         }
445                 }
446
447                 return ECORE_CALLBACK_CANCEL;
448         }
449
450         return ECORE_CALLBACK_RENEW;
451 }
452
453 static int activate_thread(void)
454 {
455         int status;
456
457         s_info.handle = open(INPUT_PATH, O_RDONLY);
458         if (s_info.handle < 0) {
459                 ErrPrint("Unable to access the device: %s\n", strerror(errno));
460                 return LB_STATUS_ERROR_IO;
461         }
462
463         if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
464                 ErrPrint("Error: %s\n", strerror(errno));
465         }
466
467         if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
468                 ErrPrint("Error: %s\n", strerror(errno));
469         }
470
471         status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
472         if (status < 0) {
473                 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
474                 if (close(s_info.handle) < 0) {
475                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
476                 }
477                 s_info.handle = -1;
478                 return LB_STATUS_ERROR_FAULT;
479         }
480
481         status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
482         if (status < 0) {
483                 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
484                 if (close(s_info.handle) < 0) {
485                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
486                 }
487                 s_info.handle = -1;
488                 CLOSE_PIPE(s_info.evt_pipe);
489                 return LB_STATUS_ERROR_FAULT;
490         }
491
492         s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
493         if (!s_info.event_handler) {
494                 if (close(s_info.handle) < 0) {
495                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
496                 }
497                 s_info.handle = -1;
498
499                 CLOSE_PIPE(s_info.tcb_pipe);
500                 CLOSE_PIPE(s_info.evt_pipe);
501                 return LB_STATUS_ERROR_FAULT;
502         }
503
504         status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
505         if (status != 0) {
506                 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
507                 ecore_main_fd_handler_del(s_info.event_handler);
508                 s_info.event_handler = NULL;
509
510                 if (close(s_info.handle) < 0) {
511                         ErrPrint("close: %s\n", strerror(errno));
512                 }
513                 s_info.handle = -1;
514
515                 CLOSE_PIPE(s_info.tcb_pipe);
516                 CLOSE_PIPE(s_info.evt_pipe);
517                 return LB_STATUS_ERROR_FAULT;
518         }
519
520         DbgPrint("Event handler activated\n");
521         return LB_STATUS_SUCCESS;
522 }
523
524 /*!
525  * x, y is the starting point.
526  */
527 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
528 {
529         struct event_listener *listener;
530         int ret = LB_STATUS_SUCCESS;
531
532         listener = malloc(sizeof(*listener));
533         if (!listener) {
534                 ErrPrint("Heap: %s\n", strerror(errno));
535                 return LB_STATUS_ERROR_MEMORY;
536         }
537
538         if (gettimeofday(&listener->tv, NULL) < 0) {
539                 ErrPrint("gettimeofday: %s\n", strerror(errno));
540                 free(listener);
541                 return LB_STATUS_ERROR_FAULT;
542         }
543
544         listener->event_cb = event_cb;
545         listener->cbdata = data;
546         listener->state = EVENT_STATE_ACTIVATE;
547         listener->x = x;
548         listener->y = y;
549
550         if (s_info.handle < 0) {
551                 /*!
552                  * \note
553                  * We don't need to lock to access event_list here.
554                  * If the _sinfo.handle is greater than 0, the event_list will not be touched.
555                  * But if the s_info.handle is less than 0, it means, there is not thread,
556                  * so we can access the event_list without lock.
557                  */
558                 if (s_info.event_list) {
559                         DbgPrint("Event thread is deactivating now. activating will be delayed\n");
560                         s_info.reactivate_list = eina_list_append(s_info.reactivate_list, listener);
561                 } else {
562                         s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
563
564                         if ((ret = activate_thread()) < 0) {
565                                 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
566                                 free(listener);
567                         }
568                 }
569         } else {
570                 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
571         }
572
573         return ret;
574 }
575
576 HAPI int event_deactivate(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
577 {
578         int status;
579         void *ret;
580         char event_ch = EVENT_CH;
581         struct event_listener *listener = NULL;
582         Eina_List *l;
583         int keep_thread = 0;
584
585         EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
586                 if (listener->event_cb == event_cb && listener->cbdata == data) {
587                         listener->state = EVENT_STATE_DEACTIVATE;
588                 }
589
590                 keep_thread += (listener->state == EVENT_STATE_ACTIVATE || listener->state == EVENT_STATE_ACTIVATED);
591         }
592
593         if (!listener) {
594                 ErrPrint("Listener is not registered\n");
595                 return LB_STATUS_ERROR_NOT_EXIST;
596         }
597
598         if (s_info.handle < 0) {
599                 ErrPrint("Event handler is not actiavated\n");
600                 free(listener);
601                 return LB_STATUS_SUCCESS;
602         }
603
604         if (keep_thread) {
605                 return LB_STATUS_SUCCESS;
606         }
607
608         /* Terminating thread */
609         if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
610                 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
611         }
612
613         status = pthread_join(s_info.tid, &ret);
614         if (status != 0) {
615                 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
616         } else {
617                 DbgPrint("Thread returns: %d\n", (int)ret);
618         }
619
620         if (close(s_info.handle) < 0) {
621                 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
622         }
623
624         s_info.handle = -1;
625         DbgPrint("Event handler deactivated\n");
626
627         CLOSE_PIPE(s_info.tcb_pipe);
628
629         if (!eina_list_count(s_info.event_list)) {
630                 ecore_main_fd_handler_del(s_info.event_handler);
631                 clear_all_listener_list();
632         }
633
634         s_info.event_data.x = -1;
635         s_info.event_data.y = -1;
636         return LB_STATUS_SUCCESS;
637 }
638
639 HAPI int event_is_activated(void)
640 {
641         return s_info.handle >= 0;
642 }
643
644 /* End of a file */