pkgmgr plugin, coding convention, AUL exception
[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         }
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                                 /* Take a breathe */
128                                 pthread_yield();
129                         }
130                         break;
131                 case SYN_CONFIG:
132                         break;
133                 case SYN_MT_REPORT:
134                         break;
135                 /*
136                 case SYN_DROPPED:
137                         DbgPrint("EV_SYN, SYN_DROPPED\n");
138                         break;
139                 */
140                 default:
141                         DbgPrint("EV_SYN, 0x%x\n", event->code);
142                         break;
143                 }
144                 break;
145         case EV_KEY:
146                 break;
147         case EV_REL:
148                 break;
149         case EV_ABS:
150                 switch (event->code) {
151                 case ABS_DISTANCE:
152                         break;
153                 case ABS_MT_POSITION_X:
154                         s_info.event_data.x = event->value - s_info.x;
155                         break;
156                 case ABS_MT_POSITION_Y:
157                         s_info.event_data.y = event->value - s_info.y;
158                         break;
159                 case ABS_MT_SLOT:
160                         break;
161                 case ABS_MT_TRACKING_ID:
162                         s_info.event_data.device = event->value;
163                         break;
164                 case ABS_MT_TOUCH_MAJOR:
165                         break;
166                 case ABS_MT_TOUCH_MINOR:
167                         break;
168                 case ABS_MT_WIDTH_MAJOR:
169                         break;
170                 case ABS_MT_WIDTH_MINOR:
171                         break;
172                 default:
173                         DbgPrint("EV_ABS, 0x%x\n", event->code);
174                         break;
175                 }
176                 break;
177         case EV_MSC:
178                 break;
179         case EV_SW:
180                 break;
181         case EV_LED:
182                 break;
183         case EV_SND:
184                 break;
185         case EV_REP:
186                 break;
187         case EV_FF:
188                 break;
189         case EV_PWR:
190                 break;
191         case EV_FF_STATUS:
192                 break;
193         default:
194                 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
195                 break;
196         }
197
198         return LB_STATUS_SUCCESS;
199 }
200
201 static void *event_thread_main(void *data)
202 {
203         fd_set set;
204         int ret = 0;
205         struct input_event input_event;
206         char *ptr = (char *)&input_event;
207         int offset = 0;
208         int readsize = 0;
209         int fd;
210
211         DbgPrint("Initiated\n");
212
213         while (1) {
214                 FD_ZERO(&set);
215                 FD_SET(s_info.handle, &set);
216                 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
217
218                 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
219                 ret = select(fd + 1, &set, NULL, NULL, NULL);
220                 if (ret < 0) {
221                         ret = -errno;
222                         if (errno == EINTR) {
223                                 DbgPrint("Select receives INTR\n");
224                                 continue;
225                         }
226                         ErrPrint("Error: %s\n", strerror(errno));
227                         break;
228                 } else if (ret == 0) {
229                         ErrPrint("Timeout expired\n");
230                         ret = LB_STATUS_ERROR_TIMEOUT;
231                         break;
232                 }
233
234                 if (FD_ISSET(s_info.handle, &set)) {
235                         readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
236                         if (readsize < 0) {
237                                 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
238                                 ret = LB_STATUS_ERROR_FAULT;
239                                 break;
240                         }
241
242                         offset += readsize;
243                         if (offset == sizeof(input_event)) {
244                                 offset = 0;
245                                 if (processing_input_event(&input_event) < 0) {
246                                         ret = LB_STATUS_ERROR_FAULT;
247                                         break;
248                                 }
249                         }
250                 }
251
252                 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
253                         char event_ch;
254
255                         if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
256                                 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
257                         }
258
259                         ret = LB_STATUS_ERROR_CANCEL;
260                         break;
261                 }
262         }
263
264         return (void *)ret;
265 }
266
267 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
268 {
269         int fd;
270         struct event_data *item;
271         char event_ch;
272
273         fd = ecore_main_fd_handler_fd_get(handler);
274         if (fd < 0) {
275                 ErrPrint("Invalid fd\n");
276                 return ECORE_CALLBACK_CANCEL;
277         }
278
279         if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
280                 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
281                 return ECORE_CALLBACK_CANCEL;
282         }
283
284         CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
285         item = eina_list_nth(s_info.event_list, 0);
286         if (item) {
287                 s_info.event_list = eina_list_remove(s_info.event_list, item);
288         } else {
289                 ErrPrint("Unable to get event\n");
290         }
291         CRITICAL_SECTION_END(&s_info.event_list_lock);
292
293         if (item && s_info.event_cb) {
294                 switch (s_info.event_state) {
295                 case EVENT_STATE_DEACTIVATE:
296                         s_info.event_state = EVENT_STATE_ACTIVATE;
297                         break;
298                 case EVENT_STATE_ACTIVATE:
299                         s_info.event_state = EVENT_STATE_ACTIVATED;
300                         break;
301                 case EVENT_STATE_ACTIVATED:
302                 default:
303                         break;
304                 }
305                 s_info.event_cb(s_info.event_state, item, s_info.cbdata);
306         }
307
308         free(item);
309         return ECORE_CALLBACK_RENEW;
310 }
311
312 /*!
313  * x, y is the starting point.
314  */
315 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
316 {
317         int status;
318
319         if (s_info.handle >= 0) {
320                 DbgPrint("Already activated\n");
321                 return LB_STATUS_SUCCESS;
322         }
323
324         s_info.handle = open(INPUT_PATH, O_RDONLY);
325         if (s_info.handle < 0) {
326                 ErrPrint("Unable to access the device: %s\n", strerror(errno));
327                 return LB_STATUS_ERROR_IO;
328         }
329
330         if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
331                 ErrPrint("Error: %s\n", strerror(errno));
332         }
333
334         if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
335                 ErrPrint("Error: %s\n", strerror(errno));
336         }
337
338         status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
339         if (status < 0) {
340                 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
341                 if (close(s_info.handle) < 0) {
342                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
343                 }
344                 s_info.handle = -1;
345                 return LB_STATUS_ERROR_FAULT;
346         }
347
348         status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
349         if (status < 0) {
350                 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
351                 if (close(s_info.handle) < 0) {
352                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
353                 }
354                 s_info.handle = -1;
355                 CLOSE_PIPE(s_info.evt_pipe);
356                 return LB_STATUS_ERROR_FAULT;
357         }
358
359         s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
360         if (!s_info.event_handler) {
361                 if (close(s_info.handle) < 0) {
362                         ErrPrint("Failed to close handle: %s\n", strerror(errno));
363                 }
364                 s_info.handle = -1;
365
366                 CLOSE_PIPE(s_info.tcb_pipe);
367                 CLOSE_PIPE(s_info.evt_pipe);
368                 return LB_STATUS_ERROR_FAULT;
369         }
370
371         status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
372         if (status != 0) {
373                 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
374                 ecore_main_fd_handler_del(s_info.event_handler);
375                 s_info.event_handler = NULL;
376
377                 if (close(s_info.handle) < 0) {
378                         ErrPrint("close: %s\n", strerror(errno));
379                 }
380                 s_info.handle = -1;
381
382                 CLOSE_PIPE(s_info.tcb_pipe);
383                 CLOSE_PIPE(s_info.evt_pipe);
384                 return LB_STATUS_ERROR_FAULT;
385         }
386
387         s_info.event_cb = event_cb;
388         s_info.cbdata = data;
389         s_info.x = x;
390         s_info.y = y;
391
392         DbgPrint("Event handler activated\n");
393         return LB_STATUS_SUCCESS;
394 }
395
396 HAPI int event_deactivate(void)
397 {
398         int status;
399         struct event_data *event;
400         void *ret;
401         char event_ch = EVENT_CH;
402
403         if (s_info.handle < 0) {
404                 ErrPrint("Event handler is not actiavated\n");
405                 return LB_STATUS_SUCCESS;
406         }
407
408         if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
409                 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
410         }
411
412         status = pthread_join(s_info.tid, &ret);
413         if (status != 0) {
414                 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
415         } else {
416                 DbgPrint("Thread returns: %d\n", (int)ret);
417         }
418
419         ecore_main_fd_handler_del(s_info.event_handler);
420         s_info.event_handler = NULL;
421
422         if (close(s_info.handle) < 0) {
423                 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
424         }
425
426         s_info.handle = -1;
427         DbgPrint("Event handler deactivated\n");
428
429         CLOSE_PIPE(s_info.tcb_pipe);
430         CLOSE_PIPE(s_info.evt_pipe);
431
432         EINA_LIST_FREE(s_info.event_list, event) {
433                 if (s_info.event_cb) {
434                         if (s_info.event_state == EVENT_STATE_DEACTIVATE) {
435                                 s_info.event_state = EVENT_STATE_ACTIVATE;
436                         } else if (s_info.event_state == EVENT_STATE_ACTIVATE) {
437                                 s_info.event_state = EVENT_STATE_ACTIVATED;
438                         }
439                         s_info.event_cb(s_info.event_state, event, s_info.cbdata);
440                 }
441                 free(event);
442         }
443
444         if (s_info.event_state != EVENT_STATE_DEACTIVATE) {
445                 s_info.event_state = EVENT_STATE_DEACTIVATE;
446
447                 if (s_info.event_cb) {
448                         s_info.event_cb(s_info.event_state, &s_info.event_data, s_info.cbdata);
449                 }
450         }
451
452         s_info.event_data.x = -1;
453         s_info.event_data.y = -1;
454         return LB_STATUS_SUCCESS;
455 }
456
457 HAPI int event_is_activated(void)
458 {
459         return s_info.handle >= 0;
460 }
461
462 /* End of a file */