2 * Copyright 2013 Samsung Electronics Co., Ltd
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
8 * http://floralicense.org/license/
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.
25 #include <sys/types.h>
27 #include <linux/input.h>
32 #include <livebox-errno.h>
41 #if !defined(ABS_MT_TOOL_X)
42 #define ABS_MT_TOOL_X 0x3c /* Center X tool position */
45 #if !defined(ABS_MT_TOOL_Y)
46 #define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */
53 Eina_List *event_list;
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;
60 struct event_data event_data;
62 Eina_List *event_listener_list;
63 Eina_List *reactivate_list;
67 .event_handler = NULL,
76 .event_listener_list = NULL,
77 .reactivate_list = NULL,
80 struct event_listener {
81 int (*event_cb)(enum event_state state, struct event_data *event, void *data);
84 enum event_state state;
86 #if defined(_USE_ECORE_TIME_GET)
89 struct timeval tv; /* Recording Activate / Deactivate time */
95 static int activate_thread(void);
97 HAPI int event_init(void)
100 ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
102 ErrPrint("Mutex: %s\n", strerror(ret));
103 return LB_STATUS_ERROR_FAULT;
105 return LB_STATUS_SUCCESS;
108 HAPI int event_fini(void)
111 ret = pthread_mutex_destroy(&s_info.event_list_lock);
113 ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
115 return LB_STATUS_SUCCESS;
118 static inline int processing_input_event(struct input_event *event)
120 struct event_data *item;
122 switch (event->type) {
124 switch (event->code) {
130 if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
131 /* Waiting full event packet */
135 item = malloc(sizeof(*item));
137 char event_ch = EVENT_CH;
139 #if defined(_USE_ECORE_TIME_GET)
140 s_info.event_data.tv = ecore_time_get();
142 if (gettimeofday(&s_info.event_data.tv, NULL) < 0) {
143 ErrPrint("gettimeofday: %s\n", strerror(errno));
147 memcpy(item, &s_info.event_data, sizeof(*item));
149 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
150 s_info.event_list = eina_list_append(s_info.event_list, item);
151 CRITICAL_SECTION_END(&s_info.event_list_lock);
153 if (write(s_info.evt_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
154 ErrPrint("Unable to send an event: %s\n", strerror(errno));
155 return LB_STATUS_ERROR_IO;
161 ErrPrint("Heap: %s\n", strerror(errno));
164 if (s_info.event_data.device < 0) {
165 s_info.event_data.x = -1;
166 s_info.event_data.y = -1;
167 s_info.event_data.slot = -1;
172 DbgPrint("EV_SYN, SYN_DROPPED\n");
176 DbgPrint("EV_SYN, 0x%x\n", event->code);
185 switch (event->code) {
187 s_info.event_data.distance = event->value;
192 case ABS_MT_POSITION_X:
193 s_info.event_data.x = event->value;
195 case ABS_MT_POSITION_Y:
196 s_info.event_data.y = event->value;
199 s_info.event_data.slot = event->value;
201 case ABS_MT_TRACKING_ID:
202 s_info.event_data.device = event->value;
204 case ABS_MT_TOUCH_MAJOR:
205 s_info.event_data.touch.major = event->value;
207 case ABS_MT_TOUCH_MINOR:
208 s_info.event_data.touch.minor = event->value;
210 case ABS_MT_WIDTH_MAJOR:
211 s_info.event_data.width.major = event->value;
213 case ABS_MT_WIDTH_MINOR:
214 s_info.event_data.width.minor = event->value;
217 DbgPrint("EV_ABS, 0x%x\n", event->code);
238 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
242 return LB_STATUS_SUCCESS;
245 static void *event_thread_main(void *data)
249 struct input_event input_event;
250 char *ptr = (char *)&input_event;
255 DbgPrint("Initiated\n");
259 FD_SET(s_info.handle, &set);
260 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
262 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
263 ret = select(fd + 1, &set, NULL, NULL, NULL);
266 if (errno == EINTR) {
267 DbgPrint("Select receives INTR\n");
270 ErrPrint("Error: %s\n", strerror(errno));
272 } else if (ret == 0) {
273 ErrPrint("Timeout expired\n");
274 ret = LB_STATUS_ERROR_TIMEOUT;
278 if (FD_ISSET(s_info.handle, &set)) {
279 readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
281 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
282 ret = LB_STATUS_ERROR_FAULT;
287 if (offset == sizeof(input_event)) {
289 if (processing_input_event(&input_event) < 0) {
290 ret = LB_STATUS_ERROR_FAULT;
296 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
299 if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
300 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
303 ret = LB_STATUS_ERROR_CANCEL;
311 static inline void clear_all_listener_list(void)
313 struct event_listener *listener;
314 enum event_state next_state;
318 s_info.event_handler = NULL;
319 CLOSE_PIPE(s_info.evt_pipe);
321 while (s_info.event_listener_list) {
322 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
323 switch (listener->state) {
324 case EVENT_STATE_ACTIVATE:
325 next_state = EVENT_STATE_ACTIVATED;
327 case EVENT_STATE_ACTIVATED:
328 next_state = EVENT_STATE_DEACTIVATE;
330 case EVENT_STATE_DEACTIVATE:
331 next_state = EVENT_STATE_DEACTIVATED;
333 case EVENT_STATE_DEACTIVATED:
335 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
340 if (listener->event_cb(listener->state, &s_info.event_data, listener->cbdata) < 0) {
341 if (eina_list_data_find(s_info.event_listener_list, listener)) {
342 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
348 listener->state = next_state;
353 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
356 struct event_data *item;
358 struct event_listener *listener;
361 enum event_state next_state;
362 enum event_state cur_state;
363 struct event_data modified_item;
365 fd = ecore_main_fd_handler_fd_get(handler);
367 ErrPrint("Invalid fd\n");
368 return ECORE_CALLBACK_CANCEL;
371 if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
372 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
373 return ECORE_CALLBACK_CANCEL;
376 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
377 item = eina_list_nth(s_info.event_list, 0);
379 s_info.event_list = eina_list_remove(s_info.event_list, item);
381 CRITICAL_SECTION_END(&s_info.event_list_lock);
384 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
385 switch (listener->state) {
386 case EVENT_STATE_ACTIVATE:
387 #if defined(_USE_ECORE_TIME_GET)
388 if (listener->tv > item->tv) {
392 if (timercmp(&listener->tv, &item->tv, >)) {
393 /* Ignore previous events before activating this listener */
398 next_state = EVENT_STATE_ACTIVATED;
399 cur_state = listener->state;
401 case EVENT_STATE_DEACTIVATE:
402 #if defined(_USE_ECORE_TIME_GET)
403 if (listener->tv > item->tv) {
404 /* Consuming all events occurred while activating this listener */
405 cur_state = EVENT_STATE_ACTIVATED;
406 next_state = EVENT_STATE_ACTIVATED;
410 if (timercmp(&listener->tv, &item->tv, >)) {
411 /* Consuming all events occurred while activating this listener */
412 cur_state = EVENT_STATE_ACTIVATED;
413 next_state = EVENT_STATE_ACTIVATED;
418 cur_state = listener->state;
419 next_state = EVENT_STATE_DEACTIVATED;
421 case EVENT_STATE_ACTIVATED:
422 cur_state = listener->state;
423 next_state = listener->state;
425 case EVENT_STATE_DEACTIVATED:
427 /* Remove this from the list */
428 /* Check the item again. the listener can be deleted from the callback */
429 if (eina_list_data_find(s_info.event_listener_list, listener)) {
430 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
437 memcpy(&modified_item, item, sizeof(modified_item));
438 modified_item.x -= listener->x;
439 modified_item.y -= listener->y;
441 if (listener->event_cb(cur_state, &modified_item, listener->cbdata) < 0) {
442 if (eina_list_data_find(s_info.event_listener_list, listener)) {
443 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
449 listener->state = next_state;
455 if (s_info.handle < 0 && !s_info.event_list) {
456 /* This callback must has to clear all listeners in this case */
457 clear_all_listener_list();
459 EINA_LIST_FREE(s_info.reactivate_list, listener) {
460 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
463 if (s_info.event_listener_list) {
464 if (activate_thread() < 0) {
465 EINA_LIST_FREE(s_info.event_listener_list, listener) {
466 (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
471 return ECORE_CALLBACK_CANCEL;
474 return ECORE_CALLBACK_RENEW;
477 static int activate_thread(void)
481 s_info.handle = open(INPUT_PATH, O_RDONLY);
482 if (s_info.handle < 0) {
483 ErrPrint("Unable to access the device: %s\n", strerror(errno));
484 return LB_STATUS_ERROR_IO;
487 if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
488 ErrPrint("Error: %s\n", strerror(errno));
491 if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
492 ErrPrint("Error: %s\n", strerror(errno));
495 status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
497 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
498 if (close(s_info.handle) < 0) {
499 ErrPrint("Failed to close handle: %s\n", strerror(errno));
502 return LB_STATUS_ERROR_FAULT;
505 status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
507 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
508 if (close(s_info.handle) < 0) {
509 ErrPrint("Failed to close handle: %s\n", strerror(errno));
512 CLOSE_PIPE(s_info.evt_pipe);
513 return LB_STATUS_ERROR_FAULT;
516 s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
517 if (!s_info.event_handler) {
518 if (close(s_info.handle) < 0) {
519 ErrPrint("Failed to close handle: %s\n", strerror(errno));
523 CLOSE_PIPE(s_info.tcb_pipe);
524 CLOSE_PIPE(s_info.evt_pipe);
525 return LB_STATUS_ERROR_FAULT;
528 status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
530 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
531 ecore_main_fd_handler_del(s_info.event_handler);
532 s_info.event_handler = NULL;
534 if (close(s_info.handle) < 0) {
535 ErrPrint("close: %s\n", strerror(errno));
539 CLOSE_PIPE(s_info.tcb_pipe);
540 CLOSE_PIPE(s_info.evt_pipe);
541 return LB_STATUS_ERROR_FAULT;
544 DbgPrint("Event handler activated\n");
545 return LB_STATUS_SUCCESS;
549 * x, y is the starting point.
551 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
553 struct event_listener *listener;
554 int ret = LB_STATUS_SUCCESS;
556 listener = malloc(sizeof(*listener));
558 ErrPrint("Heap: %s\n", strerror(errno));
559 return LB_STATUS_ERROR_MEMORY;
562 #if defined(_USE_ECORE_TIME_GET)
563 listener->tv = ecore_time_get();
565 if (gettimeofday(&listener->tv, NULL) < 0) {
566 ErrPrint("gettimeofday: %s\n", strerror(errno));
568 return LB_STATUS_ERROR_FAULT;
572 listener->event_cb = event_cb;
573 listener->cbdata = data;
574 listener->state = EVENT_STATE_ACTIVATE;
578 if (s_info.handle < 0) {
581 * We don't need to lock to access event_list here.
582 * If the _sinfo.handle is greater than 0, the event_list will not be touched.
583 * But if the s_info.handle is less than 0, it means, there is not thread,
584 * so we can access the event_list without lock.
586 if (s_info.event_list) {
587 DbgPrint("Event thread is deactivating now. activating will be delayed\n");
588 s_info.reactivate_list = eina_list_append(s_info.reactivate_list, listener);
590 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
592 if ((ret = activate_thread()) < 0) {
593 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
598 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
604 HAPI int event_deactivate(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
608 char event_ch = EVENT_CH;
609 struct event_listener *listener = NULL;
613 EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
614 if (listener->event_cb == event_cb && listener->cbdata == data) {
615 listener->state = EVENT_STATE_DEACTIVATE;
618 keep_thread += (listener->state == EVENT_STATE_ACTIVATE || listener->state == EVENT_STATE_ACTIVATED);
622 ErrPrint("Listener is not registered\n");
623 return LB_STATUS_ERROR_NOT_EXIST;
626 if (s_info.handle < 0) {
627 ErrPrint("Event handler is not actiavated\n");
629 return LB_STATUS_SUCCESS;
633 return LB_STATUS_SUCCESS;
636 /* Terminating thread */
637 if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
638 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
641 status = pthread_join(s_info.tid, &ret);
643 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
645 DbgPrint("Thread returns: %p\n", ret);
648 if (close(s_info.handle) < 0) {
649 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
653 DbgPrint("Event handler deactivated\n");
655 CLOSE_PIPE(s_info.tcb_pipe);
657 if (!eina_list_count(s_info.event_list)) {
658 ecore_main_fd_handler_del(s_info.event_handler);
659 clear_all_listener_list();
662 s_info.event_data.x = -1;
663 s_info.event_data.y = -1;
664 s_info.event_data.slot = -1;
665 return LB_STATUS_SUCCESS;
668 HAPI int event_is_activated(void)
670 return s_info.handle >= 0;