Update Input event thread. and reduce the logs.
[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 int errno;
42
43 static struct info {
44         pthread_t tid;
45         Eina_List *event_list;
46         int handle;
47         pthread_mutex_t event_list_lock;
48         int evt_pipe[PIPE_MAX];
49         int tcb_pipe[PIPE_MAX];
50         Ecore_Fd_Handler *event_handler;
51
52         int (*event_cb)(enum event_state state, struct event_data *event, void *data);
53         void *cbdata;
54
55         enum event_state event_state;
56         struct event_data event_data;
57
58         int x;
59         int y;
60 } s_info = {
61         .event_list = NULL,
62         .handle = -1,
63         .event_handler = NULL,
64
65         .event_cb = NULL,
66         .cbdata = NULL,
67
68         .event_state = EVENT_STATE_DEACTIVATE,
69
70         .event_data = {
71                 .x = 0,
72                 .y = 0,
73                 .device = -1,
74         },
75 };
76
77 HAPI int event_init(void)
78 {
79         int ret;
80         ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
81         if (ret != 0) {
82                 ErrPrint("Mutex: %s\n", strerror(ret));
83                 return LB_STATUS_ERROR_FAULT;
84         }
85         return LB_STATUS_SUCCESS;
86 }
87
88 HAPI int event_fini(void)
89 {
90         int ret;
91         ret = pthread_mutex_destroy(&s_info.event_list_lock);
92         if (ret != 0)
93                 ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
94         return LB_STATUS_SUCCESS;
95 }
96
97 static inline int processing_input_event(struct input_event *event)
98 {
99         struct event_data *item;
100
101         switch (event->type) {
102         case EV_SYN:
103                 switch (event->code) {
104                 case SYN_REPORT:
105                         if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
106                                 /* Waiting full event packet */
107                                 break;
108                         }
109
110                         item = malloc(sizeof(*item));
111                         if (item) {
112                                 char event_ch;
113
114                                 memcpy(item, &s_info.event_data, sizeof(*item));
115
116                                 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
117                                 s_info.event_list = eina_list_append(s_info.event_list, item);
118                                 CRITICAL_SECTION_END(&s_info.event_list_lock);
119
120                                 event_ch = EVENT_CH;
121                                 if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
122                                         ErrPrint("Unable to send an event: %s\n", strerror(errno));
123                                         return LB_STATUS_ERROR_IO;
124                                 }
125                         }
126                         break;
127                 case SYN_CONFIG:
128                         break;
129                 case SYN_MT_REPORT:
130                         break;
131                 /*
132                 case SYN_DROPPED:
133                         DbgPrint("EV_SYN, SYN_DROPPED\n");
134                         break;
135                 */
136                 default:
137                         DbgPrint("EV_SYN, 0x%x\n", event->code);
138                         break;
139                 }
140                 break;
141         case EV_KEY:
142                 break;
143         case EV_REL:
144                 break;
145         case EV_ABS:
146                 switch (event->code) {
147                 case ABS_DISTANCE:
148                         break;
149                 case ABS_MT_POSITION_X:
150                         s_info.event_data.x = event->value - s_info.x;
151                         break;
152                 case ABS_MT_POSITION_Y:
153                         s_info.event_data.y = event->value - s_info.y;
154                         break;
155                 case ABS_MT_SLOT:
156                         break;
157                 case ABS_MT_TRACKING_ID:
158                         s_info.event_data.device = event->value;
159                         break;
160                 case ABS_MT_TOUCH_MAJOR:
161                         break;
162                 case ABS_MT_TOUCH_MINOR:
163                         break;
164                 case ABS_MT_WIDTH_MAJOR:
165                         break;
166                 case ABS_MT_WIDTH_MINOR:
167                         break;
168                 default:
169                         DbgPrint("EV_ABS, 0x%x\n", event->code);
170                         break;
171                 }
172                 break;
173         case EV_MSC:
174                 break;
175         case EV_SW:
176                 break;
177         case EV_LED:
178                 break;
179         case EV_SND:
180                 break;
181         case EV_REP:
182                 break;
183         case EV_FF:
184                 break;
185         case EV_PWR:
186                 break;
187         case EV_FF_STATUS:
188                 break;
189         default:
190                 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
191                 break;
192         }
193
194         return LB_STATUS_SUCCESS;
195 }
196
197 static void *event_thread_main(void *data)
198 {
199         fd_set set;
200         int ret = 0;
201         struct input_event input_event;
202         char *ptr = (char *)&input_event;
203         int offset = 0;
204         int readsize = 0;
205         int fd;
206
207         DbgPrint("Initiated\n");
208
209         while (1) {
210                 FD_ZERO(&set);
211                 FD_SET(s_info.handle, &set);
212                 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
213
214                 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
215                 ret = select(fd + 1, &set, NULL, NULL, NULL);
216                 if (ret < 0) {
217                         ret = -errno;
218                         if (errno == EINTR) {
219                                 DbgPrint("Select receives INTR\n");
220                                 continue;
221                         }
222                         ErrPrint("Error: %s\n", strerror(errno));
223                         break;
224                 } else if (ret == 0) {
225                         ErrPrint("Timeout expired\n");
226                         ret = LB_STATUS_ERROR_TIMEOUT;
227                         break;
228                 }
229
230                 if (FD_ISSET(s_info.handle, &set)) {
231                         readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
232                         if (readsize < 0) {
233                                 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
234                                 ret = LB_STATUS_ERROR_FAULT;
235                                 break;
236                         }
237
238                         offset += readsize;
239                         if (offset == sizeof(input_event)) {
240                                 offset = 0;
241                                 if (processing_input_event(&input_event) < 0) {
242                                         ret = LB_STATUS_ERROR_FAULT;
243                                         break;
244                                 }
245                         }
246                 }
247
248                 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
249                         char event_ch;
250
251                         if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch))
252                                 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
253
254                         ret = LB_STATUS_ERROR_CANCEL;
255                         break;
256                 }
257         }
258
259         return (void *)ret;
260 }
261
262 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
263 {
264         int fd;
265         struct event_data *item;
266         char event_ch;
267
268         fd = ecore_main_fd_handler_fd_get(handler);
269         if (fd < 0) {
270                 ErrPrint("Invalid fd\n");
271                 return ECORE_CALLBACK_CANCEL;
272         }
273
274         if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
275                 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
276                 return ECORE_CALLBACK_CANCEL;
277         }
278
279         CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
280         item = eina_list_nth(s_info.event_list, 0);
281         if (item)
282                 s_info.event_list = eina_list_remove(s_info.event_list, item);
283         else
284                 ErrPrint("Unable to get event\n");
285         CRITICAL_SECTION_END(&s_info.event_list_lock);
286
287         if (item && s_info.event_cb) {
288                 switch (s_info.event_state) {
289                 case EVENT_STATE_DEACTIVATE:
290                         s_info.event_state = EVENT_STATE_ACTIVATE;
291                         break;
292                 case EVENT_STATE_ACTIVATE:
293                         s_info.event_state = EVENT_STATE_ACTIVATED;
294                         break;
295                 case EVENT_STATE_ACTIVATED:
296                 default:
297                         break;
298                 }
299                 s_info.event_cb(s_info.event_state, item, s_info.cbdata);
300         }
301
302         free(item);
303         return ECORE_CALLBACK_RENEW;
304 }
305
306 /*!
307  * x, y is the starting point.
308  */
309 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
310 {
311         int status;
312
313         if (s_info.handle >= 0) {
314                 DbgPrint("Already activated\n");
315                 return LB_STATUS_SUCCESS;
316         }
317
318         s_info.handle = open(INPUT_PATH, O_RDONLY);
319         if (s_info.handle < 0) {
320                 ErrPrint("Unable to access the device: %s\n", strerror(errno));
321                 return LB_STATUS_ERROR_IO;
322         }
323
324         if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0)
325                 ErrPrint("Error: %s\n", strerror(errno));
326
327         if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0)
328                 ErrPrint("Error: %s\n", strerror(errno));
329
330         status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
331         if (status < 0) {
332                 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
333                 if (close(s_info.handle) < 0)
334                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
335                 s_info.handle = -1;
336                 return LB_STATUS_ERROR_FAULT;
337         }
338
339         status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
340         if (status < 0) {
341                 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
342                 if (close(s_info.handle) < 0)
343                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
344                 s_info.handle = -1;
345                 CLOSE_PIPE(s_info.evt_pipe);
346                 return LB_STATUS_ERROR_FAULT;
347         }
348
349         s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
350         if (!s_info.event_handler) {
351                 if (close(s_info.handle) < 0)
352                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
353                 s_info.handle = -1;
354
355                 CLOSE_PIPE(s_info.tcb_pipe);
356                 CLOSE_PIPE(s_info.evt_pipe);
357                 return LB_STATUS_ERROR_FAULT;
358         }
359
360         status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
361         if (status != 0) {
362                 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
363                 ecore_main_fd_handler_del(s_info.event_handler);
364                 s_info.event_handler = NULL;
365
366                 if (close(s_info.handle) < 0)
367                         ErrPrint("close: %s\n", strerror(errno));
368                 s_info.handle = -1;
369
370                 CLOSE_PIPE(s_info.tcb_pipe);
371                 CLOSE_PIPE(s_info.evt_pipe);
372                 return LB_STATUS_ERROR_FAULT;
373         }
374
375         s_info.event_cb = event_cb;
376         s_info.cbdata = data;
377         s_info.x = x;
378         s_info.y = y;
379
380         DbgPrint("Event handler activated\n");
381         return LB_STATUS_SUCCESS;
382 }
383
384 HAPI int event_deactivate(void)
385 {
386         int status;
387         struct event_data *event;
388         void *ret;
389         char event_ch = EVENT_CH;
390
391         if (s_info.handle < 0) {
392                 ErrPrint("Event handler is not actiavated\n");
393                 return LB_STATUS_SUCCESS;
394         }
395
396         if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch))
397                 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
398
399         status = pthread_join(s_info.tid, &ret);
400         if (status != 0)
401                 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
402         else
403                 DbgPrint("Thread returns: %d\n", (int)ret);
404
405         ecore_main_fd_handler_del(s_info.event_handler);
406         s_info.event_handler = NULL;
407
408         if (close(s_info.handle) < 0)
409                 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
410
411         s_info.handle = -1;
412         DbgPrint("Event handler deactivated\n");
413
414         CLOSE_PIPE(s_info.tcb_pipe);
415         CLOSE_PIPE(s_info.evt_pipe);
416
417         EINA_LIST_FREE(s_info.event_list, event) {
418                 if (s_info.event_cb) {
419                         if (s_info.event_state == EVENT_STATE_DEACTIVATE) {
420                                 s_info.event_state = EVENT_STATE_ACTIVATE;
421                         } else if (s_info.event_state == EVENT_STATE_ACTIVATE) {
422                                 s_info.event_state = EVENT_STATE_ACTIVATED;
423                         }
424                         s_info.event_cb(s_info.event_state, event, s_info.cbdata);
425                 }
426                 free(event);
427         }
428
429         if (s_info.event_state != EVENT_STATE_DEACTIVATE) {
430                 s_info.event_state = EVENT_STATE_DEACTIVATE;
431
432                 if (s_info.event_cb)
433                         s_info.event_cb(s_info.event_state, &s_info.event_data, s_info.cbdata);
434         }
435
436         s_info.event_data.x = -1;
437         s_info.event_data.y = -1;
438         return LB_STATUS_SUCCESS;
439 }
440
441 HAPI int event_is_activated(void)
442 {
443         return s_info.handle >= 0;
444 }
445
446 /* End of a file */