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>
45 Eina_List *event_list;
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;
52 int (*event_cb)(enum event_state state, struct event_data *event, void *data);
55 enum event_state event_state;
56 struct event_data event_data;
63 .event_handler = NULL,
68 .event_state = EVENT_STATE_DEACTIVATE,
77 HAPI int event_init(void)
80 ret = pthread_mutex_init(&s_info.event_list_lock, NULL);
82 ErrPrint("Mutex: %s\n", strerror(ret));
83 return LB_STATUS_ERROR_FAULT;
85 return LB_STATUS_SUCCESS;
88 HAPI int event_fini(void)
91 ret = pthread_mutex_destroy(&s_info.event_list_lock);
93 ErrPrint("Mutex destroy failed: %s\n", strerror(ret));
95 return LB_STATUS_SUCCESS;
98 static inline int processing_input_event(struct input_event *event)
100 struct event_data *item;
102 switch (event->type) {
104 switch (event->code) {
106 if (s_info.event_data.x < 0 || s_info.event_data.y < 0) {
107 /* Waiting full event packet */
111 item = malloc(sizeof(*item));
115 memcpy(item, &s_info.event_data, sizeof(*item));
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);
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;
137 DbgPrint("EV_SYN, SYN_DROPPED\n");
141 DbgPrint("EV_SYN, 0x%x\n", event->code);
150 switch (event->code) {
153 case ABS_MT_POSITION_X:
154 s_info.event_data.x = event->value - s_info.x;
156 case ABS_MT_POSITION_Y:
157 s_info.event_data.y = event->value - s_info.y;
161 case ABS_MT_TRACKING_ID:
162 s_info.event_data.device = event->value;
164 case ABS_MT_TOUCH_MAJOR:
166 case ABS_MT_TOUCH_MINOR:
168 case ABS_MT_WIDTH_MAJOR:
170 case ABS_MT_WIDTH_MINOR:
173 DbgPrint("EV_ABS, 0x%x\n", event->code);
194 DbgPrint("0x%X, 0x%X\n", event->type, event->code);
198 return LB_STATUS_SUCCESS;
201 static void *event_thread_main(void *data)
205 struct input_event input_event;
206 char *ptr = (char *)&input_event;
211 DbgPrint("Initiated\n");
215 FD_SET(s_info.handle, &set);
216 FD_SET(s_info.tcb_pipe[PIPE_READ], &set);
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);
222 if (errno == EINTR) {
223 DbgPrint("Select receives INTR\n");
226 ErrPrint("Error: %s\n", strerror(errno));
228 } else if (ret == 0) {
229 ErrPrint("Timeout expired\n");
230 ret = LB_STATUS_ERROR_TIMEOUT;
234 if (FD_ISSET(s_info.handle, &set)) {
235 readsize = read(s_info.handle, ptr + offset, sizeof(input_event) - offset);
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;
243 if (offset == sizeof(input_event)) {
245 if (processing_input_event(&input_event) < 0) {
246 ret = LB_STATUS_ERROR_FAULT;
252 if (FD_ISSET(s_info.tcb_pipe[PIPE_READ], &set)) {
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));
259 ret = LB_STATUS_ERROR_CANCEL;
267 static Eina_Bool event_read_cb(void *data, Ecore_Fd_Handler *handler)
270 struct event_data *item;
273 fd = ecore_main_fd_handler_fd_get(handler);
275 ErrPrint("Invalid fd\n");
276 return ECORE_CALLBACK_CANCEL;
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;
284 CRITICAL_SECTION_BEGIN(&s_info.event_list_lock);
285 item = eina_list_nth(s_info.event_list, 0);
287 s_info.event_list = eina_list_remove(s_info.event_list, item);
289 ErrPrint("Unable to get event\n");
291 CRITICAL_SECTION_END(&s_info.event_list_lock);
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;
298 case EVENT_STATE_ACTIVATE:
299 s_info.event_state = EVENT_STATE_ACTIVATED;
301 case EVENT_STATE_ACTIVATED:
305 s_info.event_cb(s_info.event_state, item, s_info.cbdata);
309 return ECORE_CALLBACK_RENEW;
313 * x, y is the starting point.
315 HAPI int event_activate(int x, int y, int (*event_cb)(enum event_state state, struct event_data *event, void *data), void *data)
319 if (s_info.handle >= 0) {
320 DbgPrint("Already activated\n");
321 return LB_STATUS_SUCCESS;
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;
330 if (fcntl(s_info.handle, F_SETFD, FD_CLOEXEC) < 0) {
331 ErrPrint("Error: %s\n", strerror(errno));
334 if (fcntl(s_info.handle, F_SETFL, O_NONBLOCK) < 0) {
335 ErrPrint("Error: %s\n", strerror(errno));
338 status = pipe2(s_info.evt_pipe, O_NONBLOCK | O_CLOEXEC);
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));
345 return LB_STATUS_ERROR_FAULT;
348 status = pipe2(s_info.tcb_pipe, O_NONBLOCK | O_CLOEXEC);
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));
355 CLOSE_PIPE(s_info.evt_pipe);
356 return LB_STATUS_ERROR_FAULT;
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));
366 CLOSE_PIPE(s_info.tcb_pipe);
367 CLOSE_PIPE(s_info.evt_pipe);
368 return LB_STATUS_ERROR_FAULT;
371 status = pthread_create(&s_info.tid, NULL, event_thread_main, NULL);
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;
377 if (close(s_info.handle) < 0) {
378 ErrPrint("close: %s\n", strerror(errno));
382 CLOSE_PIPE(s_info.tcb_pipe);
383 CLOSE_PIPE(s_info.evt_pipe);
384 return LB_STATUS_ERROR_FAULT;
387 s_info.event_cb = event_cb;
388 s_info.cbdata = data;
392 DbgPrint("Event handler activated\n");
393 return LB_STATUS_SUCCESS;
396 HAPI int event_deactivate(void)
399 struct event_data *event;
401 char event_ch = EVENT_CH;
403 if (s_info.handle < 0) {
404 ErrPrint("Event handler is not actiavated\n");
405 return LB_STATUS_SUCCESS;
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));
412 status = pthread_join(s_info.tid, &ret);
414 ErrPrint("Failed to join a thread: %s\n", strerror(errno));
416 DbgPrint("Thread returns: %d\n", (int)ret);
419 ecore_main_fd_handler_del(s_info.event_handler);
420 s_info.event_handler = NULL;
422 if (close(s_info.handle) < 0) {
423 ErrPrint("Unable to release the fd: %s\n", strerror(errno));
427 DbgPrint("Event handler deactivated\n");
429 CLOSE_PIPE(s_info.tcb_pipe);
430 CLOSE_PIPE(s_info.evt_pipe);
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;
439 s_info.event_cb(s_info.event_state, event, s_info.cbdata);
444 if (s_info.event_state != EVENT_STATE_DEACTIVATE) {
445 s_info.event_state = EVENT_STATE_DEACTIVATE;
447 if (s_info.event_cb) {
448 s_info.event_cb(s_info.event_state, &s_info.event_data, s_info.cbdata);
452 s_info.event_data.x = -1;
453 s_info.event_data.y = -1;
454 return LB_STATUS_SUCCESS;
457 HAPI int event_is_activated(void)
459 return s_info.handle >= 0;