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 struct timeval tv; /* Recording Activate / Deactivate time */
91 static int activate_thread(void);
93 HAPI int event_init(void)
96 ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
98 ErrPrint("Mutex: %s\n", strerror(ret));
99 return LB_STATUS_ERROR_FAULT;
101 return LB_STATUS_SUCCESS;
104 HAPI int event_fini(void)
107 ret = pthread_mutex_destroy(&s_info.event_list_lock);
109 ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
111 return LB_STATUS_SUCCESS;
114 static inline int processing_input_event(struct input_event *event)
116 struct event_data *item;
118 switch (event->type) {
120 switch (event->code) {
126 if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
127 /* Waiting full event packet */
131 item = malloc(sizeof(*item));
133 char event_ch = EVENT_CH;
135 if (gettimeofday(&s_info.event_data.tv, NULL) < 0) {
136 ErrPrint("gettimeofday: %s\n", strerror(errno));
139 memcpy(item, &s_info.event_data, sizeof(*item));
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);
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;
153 ErrPrint("Heap: %s\n", strerror(errno));
156 if (s_info.event_data.device < 0) {
157 s_info.event_data.x = -1;
158 s_info.event_data.y = -1;
159 s_info.event_data.slot = -1;
164 DbgPrint("EV_SYN, SYN_DROPPED\n");
168 DbgPrint("EV_SYN, 0x%x\n", event->code);
177 switch (event->code) {
179 s_info.event_data.distance = event->value;
184 case ABS_MT_POSITION_X:
185 s_info.event_data.x = event->value;
187 case ABS_MT_POSITION_Y:
188 s_info.event_data.y = event->value;
191 s_info.event_data.slot = event->value;
193 case ABS_MT_TRACKING_ID:
194 s_info.event_data.device = event->value;
196 case ABS_MT_TOUCH_MAJOR:
197 s_info.event_data.touch.major = event->value;
199 case ABS_MT_TOUCH_MINOR:
200 s_info.event_data.touch.minor = event->value;
202 case ABS_MT_WIDTH_MAJOR:
203 s_info.event_data.width.major = event->value;
205 case ABS_MT_WIDTH_MINOR:
206 s_info.event_data.width.minor = event->value;
209 DbgPrint("EV_ABS, 0x%x\n", event->code);
230 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
234 return LB_STATUS_SUCCESS;
237 static void *event_thread_main(void *data)
241 struct input_event input_event;
242 char *ptr = (char *)&input_event;
247 DbgPrint("Initiated\n");
251 FD_SET(s_info.handle, &set);
252 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
254 fd = s_info.handle > s_info.tcb_pipe[PIPE_READ] ? s_info.handle : s_info.tcb_pipe[PIPE_READ];
255 ret = select(fd + 1, &set, NULL, NULL, NULL);
258 if (errno == EINTR) {
259 DbgPrint("Select receives INTR\n");
262 ErrPrint("Error: %s\n", strerror(errno));
264 } else if (ret == 0) {
265 ErrPrint("Timeout expired\n");
266 ret = LB_STATUS_ERROR_TIMEOUT;
270 if (FD_ISSET(s_info.handle, &set)) {
271 readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
273 ErrPrint("Unable to read device: %s / fd: %d / offset: %d / size: %d - %d\n", strerror(errno), s_info.handle, offset, sizeof(input_event), readsize);
274 ret = LB_STATUS_ERROR_FAULT;
279 if (offset == sizeof(input_event)) {
281 if (processing_input_event(&input_event) < 0) {
282 ret = LB_STATUS_ERROR_FAULT;
288 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
291 if (read(s_info.tcb_pipe[PIPE_READ], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
292 ErrPrint("Unable to read TCB_PIPE: %s\n", strerror(errno));
295 ret = LB_STATUS_ERROR_CANCEL;
303 static inline void clear_all_listener_list(void)
305 struct event_listener *listener;
306 enum event_state next_state;
310 s_info.event_handler = NULL;
311 CLOSE_PIPE(s_info.evt_pipe);
313 while (s_info.event_listener_list) {
314 EINA_LIST_FOREACH_SAFE(s_info.event_listener_list, l, n, listener) {
315 switch (listener->state) {
316 case EVENT_STATE_ACTIVATE:
317 next_state = EVENT_STATE_ACTIVATED;
319 case EVENT_STATE_ACTIVATED:
320 next_state = EVENT_STATE_DEACTIVATE;
322 case EVENT_STATE_DEACTIVATE:
323 next_state = EVENT_STATE_DEACTIVATED;
325 case EVENT_STATE_DEACTIVATED:
327 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
332 if (listener->event_cb(listener->state, &s_info.event_data, listener->cbdata) < 0) {
333 if (eina_list_data_find(s_info.event_listener_list, listener)) {
334 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
340 listener->state = next_state;
345 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
348 struct event_data *item;
350 struct event_listener *listener;
353 enum event_state next_state;
354 enum event_state cur_state;
355 struct event_data modified_item;
357 fd = ecore_main_fd_handler_fd_get(handler);
359 ErrPrint("Invalid fd\n");
360 return ECORE_CALLBACK_CANCEL;
363 if (read(fd, &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
364 ErrPrint("Unable to read event ch: %s\n", strerror(errno));
365 return ECORE_CALLBACK_CANCEL;
368 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
369 item = eina_list_nth(s_info.event_list, 0);
371 s_info.event_list = eina_list_remove(s_info.event_list, item);
373 CRITICAL_SECTION_END(&s_info.event_list_lock);
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 */
384 next_state = EVENT_STATE_ACTIVATED;
385 cur_state = listener->state;
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;
395 cur_state = listener->state;
396 next_state = EVENT_STATE_DEACTIVATED;
398 case EVENT_STATE_ACTIVATED:
399 cur_state = listener->state;
400 next_state = listener->state;
402 case EVENT_STATE_DEACTIVATED:
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);
414 memcpy(&modified_item, item, sizeof(modified_item));
415 modified_item.x -= listener->x;
416 modified_item.y -= listener->y;
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);
426 listener->state = next_state;
432 if (s_info.handle < 0 && !s_info.event_list) {
433 /* This callback must has to clear all listeners in this case */
434 clear_all_listener_list();
436 EINA_LIST_FREE(s_info.reactivate_list, listener) {
437 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
440 if (s_info.event_listener_list) {
441 if (activate_thread() < 0) {
442 EINA_LIST_FREE(s_info.event_listener_list, listener) {
443 (void)listener->event_cb(EVENT_STATE_ERROR, NULL, listener->cbdata);
448 return ECORE_CALLBACK_CANCEL;
451 return ECORE_CALLBACK_RENEW;
454 static int activate_thread(void)
458 s_info.handle = open(INPUT_PATH, O_RDONLY);
459 if (s_info.handle < 0) {
460 ErrPrint("Unable to access the device: %s\n", strerror(errno));
461 return LB_STATUS_ERROR_IO;
464 if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
465 ErrPrint("Error: %s\n", strerror(errno));
468 if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
469 ErrPrint("Error: %s\n", strerror(errno));
472 status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
474 ErrPrint("Unable to prepare evt pipe: %s\n", strerror(errno));
475 if (close(s_info.handle) < 0) {
476 ErrPrint("Failed to close handle: %s\n", strerror(errno));
479 return LB_STATUS_ERROR_FAULT;
482 status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
484 ErrPrint("Unable to prepare tcb pipe: %s\n", strerror(errno));
485 if (close(s_info.handle) < 0) {
486 ErrPrint("Failed to close handle: %s\n", strerror(errno));
489 CLOSE_PIPE(s_info.evt_pipe);
490 return LB_STATUS_ERROR_FAULT;
493 s_info.event_handler = ecore_main_fd_handler_add(s_info.evt_pipe[PIPE_READ], ECORE_FD_READ, event_read_cb, NULL, NULL, NULL);
494 if (!s_info.event_handler) {
495 if (close(s_info.handle) < 0) {
496 ErrPrint("Failed to close handle: %s\n", strerror(errno));
500 CLOSE_PIPE(s_info.tcb_pipe);
501 CLOSE_PIPE(s_info.evt_pipe);
502 return LB_STATUS_ERROR_FAULT;
505 status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
507 ErrPrint("Failed to initiate the thread: %s\n", strerror(status));
508 ecore_main_fd_handler_del(s_info.event_handler);
509 s_info.event_handler = NULL;
511 if (close(s_info.handle) < 0) {
512 ErrPrint("close: %s\n", strerror(errno));
516 CLOSE_PIPE(s_info.tcb_pipe);
517 CLOSE_PIPE(s_info.evt_pipe);
518 return LB_STATUS_ERROR_FAULT;
521 DbgPrint("Event handler activated\n");
522 return LB_STATUS_SUCCESS;
526 * x, y is the starting point.
528 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
530 struct event_listener *listener;
531 int ret = LB_STATUS_SUCCESS;
533 listener = malloc(sizeof(*listener));
535 ErrPrint("Heap: %s\n", strerror(errno));
536 return LB_STATUS_ERROR_MEMORY;
539 if (gettimeofday(&listener->tv, NULL) < 0) {
540 ErrPrint("gettimeofday: %s\n", strerror(errno));
542 return LB_STATUS_ERROR_FAULT;
545 listener->event_cb = event_cb;
546 listener->cbdata = data;
547 listener->state = EVENT_STATE_ACTIVATE;
551 if (s_info.handle < 0) {
554 * We don't need to lock to access event_list here.
555 * If the _sinfo.handle is greater than 0, the event_list will not be touched.
556 * But if the s_info.handle is less than 0, it means, there is not thread,
557 * so we can access the event_list without lock.
559 if (s_info.event_list) {
560 DbgPrint("Event thread is deactivating now. activating will be delayed\n");
561 s_info.reactivate_list = eina_list_append(s_info.reactivate_list, listener);
563 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
565 if ((ret = activate_thread()) < 0) {
566 s_info.event_listener_list = eina_list_remove(s_info.event_listener_list, listener);
571 s_info.event_listener_list = eina_list_append(s_info.event_listener_list, listener);
577 HAPI int event_deactivate(int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
581 char event_ch = EVENT_CH;
582 struct event_listener *listener = NULL;
586 EINA_LIST_FOREACH(s_info.event_listener_list, l, listener) {
587 if (listener->event_cb == event_cb && listener->cbdata == data) {
588 listener->state = EVENT_STATE_DEACTIVATE;
591 keep_thread += (listener->state == EVENT_STATE_ACTIVATE || listener->state == EVENT_STATE_ACTIVATED);
595 ErrPrint("Listener is not registered\n");
596 return LB_STATUS_ERROR_NOT_EXIST;
599 if (s_info.handle < 0) {
600 ErrPrint("Event handler is not actiavated\n");
602 return LB_STATUS_SUCCESS;
606 return LB_STATUS_SUCCESS;
609 /* Terminating thread */
610 if (write(s_info.tcb_pipe[PIPE_WRITE], &event_ch, sizeof(event_ch)) != sizeof(event_ch)) {
611 ErrPrint("Unable to write tcb_pipe: %s\n", strerror(errno));
614 status = pthread_join(s_info.tid, &ret);
616 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
618 DbgPrint("Thread returns: %d\n", (int)ret);
621 if (close(s_info.handle) < 0) {
622 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
626 DbgPrint("Event handler deactivated\n");
628 CLOSE_PIPE(s_info.tcb_pipe);
630 if (!eina_list_count(s_info.event_list)) {
631 ecore_main_fd_handler_del(s_info.event_handler);
632 clear_all_listener_list();
635 s_info.event_data.x = -1;
636 s_info.event_data.y = -1;
637 s_info.event_data.slot = -1;
638 return LB_STATUS_SUCCESS;
641 HAPI int event_is_activated(void)
643 return s_info.handle >= 0;