[FIX] empty string in sprintf
[platform/core/system/swap-manager.git] / daemon / input_events.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Jaewon Lim           <jaewon81.lim@samsung.com>
9  * Woojin Jung          <woojin2.jung@samsung.com>
10  * Juyoung Kim          <j0.kim@samsung.com>
11  * Cherepanov Vitaliy   <v.cherepanov@samsung.com>
12  * Nikita Kalyazin      <n.kalyazin@samsung.com>
13  *
14  * Licensed under the Apache License, Version 2.0 (the "License");
15  * you may not use this file except in compliance with the License.
16  * You may obtain a copy of the License at
17  *
18  * http://www.apache.org/licenses/LICENSE-2.0
19  *
20  * Unless required by applicable law or agreed to in writing, software
21  * distributed under the License is distributed on an "AS IS" BASIS,
22  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23  * See the License for the specific language governing permissions and
24  * limitations under the License.
25  *
26  * Contributors:
27  * - S-Core Co., Ltd
28  * - Samsung RnD Institute Russia
29  *
30  */
31
32
33 #include <dirent.h>
34 #include <Ecore.h>
35
36 #include "debug.h"
37 #include "da_data.h"
38 #include "input_events.h"
39
40 #define MAX_DEVICE              10
41 #define ARRAY_END               (-11)
42 #define BUF_SIZE                1024
43 #define MAX_FILENAME 128
44
45 #define INPUT_ID_TOUCH          0
46 #define INPUT_ID_KEY            1
47 #define STR_TOUCH               "TOUCH"
48 #define STR_KEY                 "KEY"
49 #define INPUT_ID_STR_KEY        "ID_INPUT_KEY=1"
50 #define INPUT_ID_STR_TOUCH      "ID_INPUT_TOUCHSCREEN=1"
51 #define INPUT_ID_STR_KEYBOARD   "ID_INPUT_KEYBOARD=1"
52 #define INPUT_ID_STR_TABLET     "ID_INPUT_TABLET=1"
53
54 typedef struct _input_dev
55 {
56         int fd;
57         char fileName[MAX_FILENAME];
58 } input_dev;
59
60 static input_dev g_key_dev[MAX_DEVICE];
61 static input_dev g_touch_dev[MAX_DEVICE];
62
63 static Ecore_Fd_Handler *key_handlers[MAX_DEVICE];
64 static Ecore_Fd_Handler *touch_handlers[MAX_DEVICE];
65
66 enum status_t { s_stopped, s_running };
67 static enum status_t status = s_stopped;
68
69 static const char *input_key_devices[] = {
70         /* target: Emulator, kernel: 3.4, all buttons */
71         "Maru Virtio Hwkey",
72         /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */
73         "gpio-keys",
74         /* target: M0, kernel: 3.0, buttons: menu, back */
75         "melfas-touchkey",
76         /* target: M0, kernel: 3.10, buttons: menu, back */
77         "MELFAS MCS Touchkey",
78         /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */
79         "gpio-keys.5",
80         NULL
81 };
82
83 static const char *input_touch_devices[] = {
84         /* target: Emulator, kernel: 3.0 */
85         "Maru Virtio Touchscreen",
86         /* target: M0, kernel: 3.0 */
87         "sec_touchscreen",
88         /* target: M0, kernel: 3.10 */
89         "MELPAS MMS114 Touchscreen",
90         NULL
91 };
92
93 static int check_input(char *inputname, int input_id)
94 {
95         int ret = -1;
96         FILE *cmd_fp = NULL;
97         char buffer[BUF_SIZE];
98         char command[MAX_FILENAME];
99         char **name_arr;
100         size_t bytes_count;
101
102         sprintf(command, "/sys/class/input/%s/device/name", inputname);
103         // run command
104         cmd_fp = fopen(command, "r");
105         if (cmd_fp == NULL)
106                 goto exit;
107
108         buffer[0] = '\0';
109         bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp);
110         if (bytes_count <= 1) {
111                 LOGE("Failed to read input_id\n");
112                 goto exit;
113         } else {
114                 buffer[bytes_count - 1] = '\0';
115         }
116
117         if (input_id == INPUT_ID_KEY)
118                 name_arr = input_key_devices;
119         else if (input_id == INPUT_ID_TOUCH)
120                 name_arr = input_touch_devices;
121         else
122                 goto exit;
123
124         while (*name_arr != NULL) {
125                 if (strcmp(buffer, *name_arr) == 0) {
126                         ret = 0;
127                         goto exit;
128                 }
129                 name_arr++;
130         }
131
132 exit:
133         if (cmd_fp != NULL)
134                 pclose(cmd_fp);
135         return ret;
136 }
137
138 // get filename and fd of given input type devices
139 static void _get_fds(input_dev *dev, int input_id)
140 {
141         DIR *dp;
142         struct dirent *d;
143         int count = 0;
144
145         dp = opendir("/sys/class/input");
146
147         if (dp == NULL)
148                 goto exit;
149
150         while ((d = readdir(dp)) != NULL) {
151                 if (!strncmp(d->d_name, "event", 5)) {
152                         // start with "event"
153                         // event file
154                         if (!check_input(d->d_name, input_id)) {
155                                 sprintf(dev[count].fileName,
156                                         "/dev/input/%s", d->d_name);
157                                 dev[count].fd = open(dev[count].fileName,
158                                                      O_RDWR | O_NONBLOCK);
159                                 count++;
160                         }
161                 }
162         }
163
164         closedir(dp);
165
166 exit:
167         dev[count].fd = ARRAY_END;      // end of input_dev array
168 }
169
170 #define MAX_EVENTS_NUM 10
171 static int deviceEventHandler(input_dev *dev, int input_type)
172 {
173         int ret = 0;
174         ssize_t size = 0;
175         int count = 0;
176         struct input_event in_ev[MAX_EVENTS_NUM];
177         struct msg_data_t *log;
178
179         if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) {
180                 do {
181                         size = read(dev->fd, &in_ev[count], sizeof(*in_ev));
182                         if (size > 0)
183                                 count++;
184                 } while (count < MAX_EVENTS_NUM && size > 0);
185
186                 if (count) {
187                         LOGI("read %d %s events\n",
188                              count,
189                              input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
190                         log = gen_message_event(in_ev, count, input_type);
191                         printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
192                         write_to_buf(log);
193                         free_msg_data(log);
194                 }
195         } else {
196                 LOGW("unknown input_type\n");
197                 ret = 1;        // it is not error
198         }
199         return ret;
200 }
201
202 static Eina_Bool touch_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
203 {
204         input_dev *touch_dev = (input_dev *)data;
205
206         if (deviceEventHandler(touch_dev, INPUT_ID_TOUCH) < 0) {
207                 LOGE("Internal DA framework error, "
208                      "Please re-run the profiling (touch dev)\n");
209                 /* TODO: ??? */
210         }
211
212         return ECORE_CALLBACK_RENEW;
213 }
214
215 static Eina_Bool key_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
216 {
217         input_dev *key_dev = (input_dev *)data;
218
219         if (deviceEventHandler(key_dev, INPUT_ID_KEY) < 0) {
220                 LOGE("Internal DA framework error, "
221                      "Please re-run the profiling (key dev)\n");
222                 /* TODO: ??? */
223         }
224
225         return ECORE_CALLBACK_RENEW;
226 }
227
228 void add_input_events(void)
229 {
230         int i;
231
232         if (status == s_running)
233                 return;
234
235         for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
236                 if (g_key_dev[i].fd > 0) {
237                         key_handlers[i] =
238                                 ecore_main_fd_handler_add(g_key_dev[i].fd,
239                                                           ECORE_FD_READ,
240                                                           key_event_cb,
241                                                           &g_key_dev[i],
242                                                           NULL, NULL);
243                         if (!key_handlers[i])
244                                 LOGE("keyboard device file handler add error\n");
245                 }
246         }
247
248         for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
249                 if (g_touch_dev[i].fd > 0) {
250                         touch_handlers[i] =
251                                 ecore_main_fd_handler_add(g_touch_dev[i].fd,
252                                                           ECORE_FD_READ,
253                                                           touch_event_cb,
254                                                           &g_touch_dev[i],
255                                                           NULL, NULL);
256                         if (!touch_handlers[i])
257                                 LOGE("touch device file handler add error\n");
258                 }
259         }
260
261         status = s_running;
262 }
263
264 void del_input_events(void)
265 {
266         int i;
267
268         if (status == s_stopped)
269                 return;
270
271         for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
272                 if (g_key_dev[i].fd > 0)
273                         ecore_main_fd_handler_del(key_handlers[i]);
274
275         for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
276                 if (g_touch_dev[i].fd > 0)
277                         ecore_main_fd_handler_del(touch_handlers[i]);
278
279         status = s_stopped;
280 }
281
282 static void _device_write(input_dev dev[], struct input_event *in_ev)
283 {
284         int i;
285         for (i = 0; dev[i].fd != ARRAY_END; i++) {
286                 if (dev[i].fd >= 0) {
287                         write(dev[i].fd, in_ev, sizeof(struct input_event));
288                         LOGI("write(%d, %d, %d)\n",
289                              dev[i].fd, (int)in_ev, sizeof(struct input_event));
290                 }
291         }
292 }
293
294 void write_input_event(int id, struct input_event *ev)
295 {
296         switch (id) {
297         case INPUT_ID_TOUCH:
298                 _device_write(g_touch_dev, ev);
299                 break;
300         case INPUT_ID_KEY:
301                 _device_write(g_key_dev, ev);
302                 break;
303         default:
304                 LOGE("unknown input id (%d)\n", id);
305         }
306 }
307
308 int init_input_events(void)
309 {
310         _get_fds(g_key_dev, INPUT_ID_KEY);
311         if (g_key_dev[0].fd == ARRAY_END) {
312                 LOGE("No key devices found.\n");
313                 return -1;
314         }
315         _get_fds(g_touch_dev, INPUT_ID_TOUCH);
316         if (g_touch_dev[0].fd == ARRAY_END) {
317                 LOGE("No touch devices found.\n");
318                 return -1;
319         }
320
321         return 0;
322 }