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