input_hal branch
[staging/toyota.git] / src / input_udev_monitor.cpp
1 /*
2  * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION.
3  *
4  * Licensed under the Apache License, Version 2.0 (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://www.apache.org/licenses/LICENSE-2.0
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 #include <errno.h>
18 #include <fcntl.h>
19 #include <pthread.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/prctl.h>
24 #include <sys/stat.h>
25 #include <sys/types.h>
26 #include <unistd.h>
27
28 #include <libudev.h>
29 #include <native_service/ns_message_center_if.h>
30
31 #include "input_hal.h"
32 #include "input_hal_debug.h"
33 #include "input_hal_internal.h"
34 #include "input_drm.h"
35 #include "input_udev_monitor.h"
36
37 #define HAL_INPUT_UDEVMONITOR_THREADNAME "input_hal_udevm"
38 #define max_value(x, y) ((x) > (y) ? (x) : (y))
39
40 #define INPUT_VIRTUAL_INPUTDEVICE_NAME "/devices/virtual" /* Virtual device name created by SwitchManager */
41
42 // Enough name length to contain node name
43 #define INPUT_NODE_NAME_LENGTH 256
44
45 #define TRACKING_ID_NONE    -1
46
47 static struct InputUdevMonitorInfo g_input_udevmonitor_info;
48 static HANDLE g_sender_handle;
49 static bool g_input_touch_init_notify = false;
50 extern char* g_app_name;  /* app name */
51 bool g_break_from_watch = false;  /* watch thread loop break flag */
52 pthread_t g_udev_monitor_thread = -1;  /* udev monitor thread */
53
54 static void InputUdevMonitorTouchInitFinEventSend(int result) {
55   struct TouchInitFinishInput msg;
56
57   if (g_input_touch_init_notify) {
58     return;
59   }
60
61   if (NULL == g_sender_handle) {
62     g_sender_handle = McOpenSender(g_app_name);
63   }
64   msg.result = result;
65
66   InputUtilMCSend(
67       g_sender_handle, HAL_INPUT_SOURCE_NAME,
68       HAL_INPUT_NOTIFY_TOUCH_INIT_FINISH, sizeof(msg), &msg);
69   g_input_touch_init_notify = true;
70 }
71
72 static void InputUdevMonitorInputEventHandle(int fd, int device_type, int notify_id) {
73   ssize_t   read_size;
74   struct EventsPackageInput events = {0};
75
76   read_size = read(fd, events.event, sizeof(events.event));
77   if (read_size > 0) {
78     events.count = read_size / sizeof(struct input_event);
79     events.device_type = device_type;
80
81     if (NULL == g_sender_handle) {
82       g_sender_handle = McOpenSender(g_app_name);
83     }
84
85     InputUtilMCSend(
86         g_sender_handle, HAL_INPUT_SOURCE_NAME,
87         notify_id, sizeof(events), &events);
88   }
89 }
90
91 static void InputUdevMonitorTouchEventHandle(int fd, int notify_id) {
92   ssize_t   read_size;
93   struct input_event event[HAL_INPUT_EVENT_COUNT] = {0};
94   int touch_status;
95
96   read_size = read(fd, event, sizeof(event));
97
98   if (read_size > 0) {
99     if (NULL == g_sender_handle) {
100       g_sender_handle = McOpenSender(g_app_name);
101     }
102
103     int event_num = read_size / sizeof(struct input_event);
104
105     for (int index = 0; index < event_num; ++index) {
106       if (EV_ABS == event[index].type) {
107         if (event[index].code == ABS_MT_TRACKING_ID) {
108           if (TRACKING_ID_NONE == event[index].value) {
109             touch_status = HAL_INPUT_TOUCH_RELEASE;
110           } else {
111             touch_status = HAL_INPUT_TOUCH_PRESS;
112           }
113           InputUtilMCSend(
114               g_sender_handle, HAL_INPUT_SOURCE_NAME,
115               notify_id, sizeof(touch_status), &touch_status);
116         }
117       }
118     }
119   }
120 }
121
122 static int InputUdevMonitorDeviceAssort(struct udev_device *dev) {
123   const char *property;
124
125   char touch_key_device_name[INPUT_NODE_NAME_LENGTH] = { 0 };
126   GetKeyNameTouch(touch_key_device_name, sizeof(touch_key_device_name));
127   const char *sysattr_name = udev_device_get_sysattr_value(dev, "name");
128   if ((sysattr_name) &&
129       (0 == strcmp(touch_key_device_name, sysattr_name))) {
130     INPUT_LOG_TRACE("DeviceAssort : ESC_SW\n");
131     return HAL_INPUT_DEVICE_TOUCH_ESCKEY;
132   }
133
134   char touch_device_name[INPUT_NODE_NAME_LENGTH] = { 0 };
135   GetPanelNameTouch(touch_device_name, sizeof(touch_device_name));
136   sysattr_name = udev_device_get_sysattr_value(dev, "name");
137   if ((sysattr_name) &&
138       (0 == strcmp(touch_device_name, sysattr_name))) {
139     INPUT_LOG_TRACE("DeviceAssort : Touch\n");
140     return HAL_INPUT_DEVICE_TOUCH;
141   }
142
143   property = udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
144   if ((property) && (strcmp("1", property) == 0)) {
145     INPUT_LOG_TRACE("DeviceAssort : KeyBoard\n");
146     return HAL_INPUT_DEVICE_KEYBOARD;
147   }
148
149   property = udev_device_get_property_value(dev, "ID_INPUT_TABLET");
150   if ((property) && (strcmp("1", property) == 0)) {
151     INPUT_LOG_TRACE("DeviceAssort : Tablet\n");
152     return HAL_INPUT_DEVICE_INVALID;
153   }
154
155   property = udev_device_get_property_value(dev, "ID_INPUT_TOUCHPAD");
156   if ((property) && (strcmp("1", property) == 0)) {
157     INPUT_LOG_TRACE("DeviceAssort : Touch pad\n");
158     return HAL_INPUT_DEVICE_TABLET_FINGER;
159   }
160
161   return HAL_INPUT_DEVICE_INVALID;
162 }
163
164 static void InputUdevMonitorDeviceListOutput(void) {
165   struct InputUtilList *p;
166
167   INPUT_LOG_TRACE("OutputList >> start ======================\n");
168   input_list_for_each(p, &g_input_udevmonitor_info.dev_list.list) {
169     struct InputInputDeviceList *entry = input_list_entry(p, struct InputInputDeviceList, list);
170     if (NULL != entry) {
171       INPUT_LOG_TRACE("FD: %d Device=%s Assort=%d\n",
172                      entry->fd, entry->device_node, entry->device_assort);
173     }
174   }
175   INPUT_LOG_TRACE("OutputList << end ======================\n");
176 }
177
178 static void InputUdevMonitorDeviceListDelete(const char *node) {
179   struct InputUtilList *p;
180
181   input_list_for_each(p, &g_input_udevmonitor_info.dev_list.list) {
182     struct InputInputDeviceList *entry = input_list_entry(p, struct InputInputDeviceList, list);
183     if (strcmp(node, entry->device_node) == 0) {
184       close(entry->fd);
185       InputUtilListDelete(p);
186       free(entry);
187       break;
188     }
189   }
190   InputUdevMonitorDeviceListOutput();
191 }
192
193 static int InputUdevMonitorDeviceListAdd(int fd, int device_assort, const char *node) {
194   int   ret = HAL_INPUT_RET_NORMAL;
195   struct InputInputDeviceList *p;
196
197   p = (struct InputInputDeviceList *) malloc(sizeof(struct InputInputDeviceList));
198   if (p) {
199     p->fd = fd;
200     p->device_assort = device_assort;
201
202     if (strlen(node) < INPUT_DEVICE_NODE_LENGTH_MAX) {
203       strncpy(p->device_node, node, sizeof(p->device_node) - 1);
204       InputUdevMonitorDeviceListDelete(node);
205       InputUtilListAdd(&p->list, &g_input_udevmonitor_info.dev_list.list);
206     } else {
207       ret = HAL_INPUT_RET_ERROR;
208     }
209   } else {
210     ret = HAL_INPUT_RET_ERROR;
211   }
212
213   InputUdevMonitorDeviceListOutput();
214
215   return ret;
216 }
217
218 static int InputUdevMonitorInputEventGrab(const char *node, struct udev_device *dev) {
219   int fd, rtn;
220
221   InputUdevMonitorDeviceListDelete(node);
222
223   fd = open(node, O_RDONLY);
224
225   if (fd < 0) {
226     INPUT_ERROR_LOG("ERR: open %s errno=%d \n", node, errno);
227     goto err_rtn;
228   }
229
230   rtn = ioctl(fd, EVIOCGRAB, 1);
231   if (rtn) {
232     INPUT_ERROR_LOG("ERR: ioctl grab %s \n", node);
233     goto err_rtn_close;
234   }
235   INPUT_LOG_TRACE("%s Grab \n", node);
236
237   /* Backup FD */
238   rtn = InputUdevMonitorDeviceListAdd(fd, InputUdevMonitorDeviceAssort(dev), node);
239   if (rtn) {
240     goto err_rtn_close;
241   }
242
243   return HAL_INPUT_RET_NORMAL;
244
245 err_rtn_close:
246   close(fd);
247 err_rtn:
248   INPUT_LOG_TRACE("%s Grab impossible \n", node);
249   return HAL_INPUT_RET_ERROR;
250 }
251
252 static void InputUdevMonitorFDSet(int *nfds, fd_set *fds) {
253   struct InputUtilList *p;
254
255   input_list_for_each(p, &g_input_udevmonitor_info.dev_list.list) {
256     struct InputInputDeviceList *entry = input_list_entry(p, struct InputInputDeviceList, list);
257
258     switch (entry->device_assort) {
259       case HAL_INPUT_DEVICE_TOUCH_ESCKEY:
260       case HAL_INPUT_DEVICE_TOUCH:
261       case HAL_INPUT_DEVICE_KEYBOARD:
262       case HAL_INPUT_DEVICE_TABLET_FINGER:
263       FD_SET(entry->fd, fds);
264       *nfds = max_value(*nfds, entry->fd);
265       break;
266       default:
267       break;
268     }
269   }
270 }
271
272 static void InputUdevMonitorFDHandle(fd_set *fds) {
273   struct InputUtilList *p;
274
275   input_list_for_each(p, &g_input_udevmonitor_info.dev_list.list) {
276     struct InputInputDeviceList *entry = input_list_entry(p, struct InputInputDeviceList, list);
277     if (FD_ISSET(entry->fd, fds)) {
278       int notify_id = 0;
279       switch (entry->device_assort) {
280       case HAL_INPUT_DEVICE_TOUCH_ESCKEY:
281         notify_id = HAL_INPUT_NOTIFY_ESC_KEY;
282         break;
283       case HAL_INPUT_DEVICE_TOUCH:
284         notify_id = HAL_INPUT_NOTIFY_TOUCH;
285         break;
286       case HAL_INPUT_DEVICE_KEYBOARD:
287         notify_id = HAL_INPUT_NOTIFY_KEY_BOARD;
288         break;
289       case HAL_INPUT_DEVICE_TABLET_FINGER:
290         notify_id = HAL_INPUT_NOTIFY_TABLET_FINGER;
291         break;
292       default:
293         return;
294       }
295       if (notify_id == HAL_INPUT_NOTIFY_TOUCH) {
296         InputUdevMonitorTouchEventHandle(entry->fd, notify_id);
297       } else {
298         InputUdevMonitorInputEventHandle(entry->fd, entry->device_assort, notify_id);
299       }
300     }
301   }
302 }
303
304 static int InputUdevMonitorInit(void) {
305   g_input_udevmonitor_info.udev = udev_new();
306   if (NULL == g_input_udevmonitor_info.udev) {
307     INPUT_ERROR_LOG("ERR: udev_new ret=%d \n", errno);
308     return HAL_INPUT_RET_ERROR;
309   }
310
311   // create the udev monitor
312   g_input_udevmonitor_info.monitor = udev_monitor_new_from_netlink(g_input_udevmonitor_info.udev, "udev");
313   udev_monitor_filter_add_match_subsystem_devtype(g_input_udevmonitor_info.monitor, "input", NULL);
314
315   // start receiving hotplug events
316   udev_monitor_enable_receiving(g_input_udevmonitor_info.monitor);
317
318   INPUT_INIT_LIST_HEAD(&g_input_udevmonitor_info.dev_list.list)
319
320   return HAL_INPUT_RET_NORMAL;
321 }
322
323 static void InputUdevMonitorDeinit(void) {
324     // destroy the udev monitor
325     udev_monitor_unref(g_input_udevmonitor_info.monitor);
326     // destroy the udev object
327     udev_unref(g_input_udevmonitor_info.udev);
328
329     if (g_sender_handle != NULL) {
330       McClose(g_sender_handle);
331       g_sender_handle = NULL;
332     }
333
334     g_input_touch_init_notify = false;
335 }
336
337 static int InputUdevMonitorDevicesGet(void) {
338   int   ret;
339   struct udev_enumerate *enumerate;
340   struct udev_list_entry *devices, *dev_list_entry;
341   char touch_device_name[INPUT_NODE_NAME_LENGTH] = { 0};
342   const char* sysattr_name;
343   bool input_touch_device_found = false;
344
345   // Create a list of the devices in the 'usb_device' subsystem.
346   enumerate = udev_enumerate_new(g_input_udevmonitor_info.udev);
347   udev_enumerate_add_match_subsystem(enumerate, "input");
348   udev_enumerate_scan_devices(enumerate);
349   devices = udev_enumerate_get_list_entry(enumerate);
350   GetPanelNameTouch(touch_device_name, sizeof(touch_device_name));
351
352   // Enumerate device list
353   udev_list_entry_foreach(dev_list_entry, devices) {
354     const char *path, *node;
355
356     // Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it
357     path = udev_list_entry_get_name(dev_list_entry);
358     struct udev_device* dev = udev_device_new_from_syspath(g_input_udevmonitor_info.udev, path);
359     if (NULL == dev) continue;
360
361     // usb_device_get_devnode() returns the path to the device node itself in /dev.
362     node = udev_device_get_devnode(dev);
363     if (!node) {
364       udev_device_unref(dev);
365       continue;
366     }
367
368     // Filter device name is eventX
369     if (strncmp("event", udev_device_get_sysname(dev), sizeof("event") -1) != 0) {
370       udev_device_unref(dev);
371       continue;
372     }
373
374     // virtual device
375     if (strncmp(INPUT_VIRTUAL_INPUTDEVICE_NAME, udev_device_get_devpath(dev),
376                 sizeof(INPUT_VIRTUAL_INPUTDEVICE_NAME) - 1) == 0) {
377       INPUT_LOG_TRACE("Found Virtual Device : %s \n", node);
378       udev_device_unref(dev);
379       continue;
380     }
381
382     // check parent is input
383     struct udev_device* input_dev = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL);
384     if (NULL == input_dev) {
385       udev_device_unref(dev);
386       continue;
387     }
388
389     sysattr_name = udev_device_get_sysattr_value(input_dev, "name");
390     if (NULL == sysattr_name) {
391       INPUT_ERROR_LOG("ERR: Unable to find sysattr \n");
392       udev_device_unref(dev);
393       continue;
394     }
395
396     // touchpanel device
397     if (0 == strcmp(touch_device_name, sysattr_name)) {
398       INPUT_LOG_TRACE("Found %s : %s \n", touch_device_name, path);
399       int spec_reso_h;
400       int spec_reso_v;
401       GetPanelSpecResolutionInput(&spec_reso_h, &spec_reso_v);
402       ret = ConfigTouch(udev_device_get_syspath(input_dev),
403                         spec_reso_h, spec_reso_v);
404
405       if (HAL_INPUT_RET_NORMAL == ret) {
406         int status;
407         ret = GetConfigStatusTouch(&status);
408         if (HAL_INPUT_RET_NORMAL == ret) {
409           if (HAL_INPUT_TOUCH_CONFIG_OFF == status) {
410             InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_NORMAL);
411           }
412         } else {
413           INPUT_ERROR_LOG("GetConfigStatusTouch fail\n");
414           InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_ERROR);
415         }
416       } else {
417         INPUT_ERROR_LOG("ConfigTouch fail\n");
418         InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_ERROR);
419       }
420
421       input_touch_device_found = true;
422     }
423
424     INPUT_LOG_TRACE("Found Device : %s \n", node);
425
426     /* Modified not to notify input events to other processes */
427     InputUdevMonitorInputEventGrab(node, input_dev);
428
429     udev_device_unref(dev);
430   }  // end foreach
431
432   if (!input_touch_device_found) {
433     INPUT_ERROR_LOG("ERR: Dummy Device Create");
434     InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_NORMAL);
435   }
436
437   // Free the enumerator object
438   udev_enumerate_unref(enumerate);
439
440   return HAL_INPUT_RET_NORMAL;
441 }
442
443 static void InputUdevMonitorDeviceStatusChange(int fd, fd_set *fds) {
444   if (FD_ISSET(fd, fds)) {
445     // receive the relevant device
446     struct udev_device* dev = udev_monitor_receive_device(g_input_udevmonitor_info.monitor);
447     if (NULL == dev) return;
448
449     //   input_udev_DevicesGet(udm);
450     const char* action = udev_device_get_action(dev);
451     const char* node = udev_device_get_devnode(dev);
452     if ((!action) || (!node)) {
453       udev_device_unref(dev);
454       return;
455     }
456
457     if (strncmp("event", udev_device_get_sysname(dev), sizeof("event") -1) != 0) {
458       INPUT_LOG_TRACE("not event device %s \n", udev_device_get_sysname(dev));
459       udev_device_unref(dev);
460       return;
461     }
462
463     if (strncmp(INPUT_VIRTUAL_INPUTDEVICE_NAME, udev_device_get_devpath(dev),
464                 sizeof(INPUT_VIRTUAL_INPUTDEVICE_NAME) - 1) == 0) {
465       udev_device_unref(dev);
466       return;
467     }
468
469     if (strcmp(action, "remove") == 0) {
470       InputUdevMonitorDeviceListDelete(node);
471     }
472
473     struct udev_device* input_dev = udev_device_get_parent_with_subsystem_devtype(dev, "input", NULL);
474     if (NULL == input_dev) {
475       udev_device_unref(dev);
476       return;
477     }
478     char touch_device_name[INPUT_NODE_NAME_LENGTH] = { 0};
479     GetPanelNameTouch(touch_device_name, sizeof(touch_device_name));
480     const char *sysattr_name = udev_device_get_sysattr_value(input_dev, "name");
481     if (NULL == sysattr_name) {
482       INPUT_ERROR_LOG("ERR: Unable to find sysattr \n");
483       udev_device_unref(dev);
484       return;
485     }
486
487     if (0 == strcmp(touch_device_name, sysattr_name)) {
488       if (strcmp(action, "remove") == 0) {
489       } else {
490         INPUT_LOG_TRACE("Found %s \n", touch_device_name);
491         InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_NORMAL);
492       }
493     }
494
495     INPUT_LOG_TRACE("%s : %s \n", node, action);
496     if (strcmp(action, "remove") == 0) {
497     } else {
498       /* Modified not to notify input events to other processes */
499       InputUdevMonitorInputEventGrab(node, input_dev);
500     }
501     udev_device_unref(dev);
502   }
503 }
504
505 static void InputUdevMonitorWatch(void) {
506   fd_set fds;
507   int fd = udev_monitor_get_fd(g_input_udevmonitor_info.monitor);
508
509   if (fd != -1) {
510     while (!g_break_from_watch) {
511       FD_ZERO(&fds);
512       FD_SET(fd, &fds);
513       int nfds = max_value(0, fd);
514
515       InputUdevMonitorFDSet(&nfds, &fds);
516
517       struct timeval timeout;
518       timeout.tv_sec = 0;
519       timeout.tv_usec = 100 * 1000;
520       int ret = select(nfds + 1, &fds, NULL, NULL, &timeout);
521       if (ret > 0) {
522         InputUdevMonitorDeviceStatusChange(fd, &fds);
523
524         InputUdevMonitorFDHandle(&fds);
525       }
526     }
527   } else {
528     INPUT_ERROR_LOG("ERR: udev_monitor_get_fd");
529   }
530 }
531
532 static void *InputUdevMonitorMain(void * arg) {
533   int   rtn;
534   prctl(PR_SET_NAME, HAL_INPUT_UDEVMONITOR_THREADNAME);
535
536   rtn = InputUdevMonitorInit();
537     if (rtn != HAL_INPUT_RET_NORMAL) {
538     goto err_rtn;
539   }
540
541   /* Get input device */
542   InputUdevMonitorDevicesGet();
543
544   /* Input device monitoring (basically never get out from here) */
545   InputUdevMonitorWatch();
546
547   InputUdevMonitorDeinit();
548
549   return NULL;
550
551 err_rtn:
552   INPUT_LOG_TRACE("pthread_detach\n");
553   return NULL;
554 }
555
556 int32_t InputUdevMonitorThreadCreate(void) {
557   int ret;
558
559   ret = pthread_create(&g_udev_monitor_thread, NULL, InputUdevMonitorMain, NULL);
560   if (ret != 0) {
561     INPUT_ERROR_LOG("ERR: pthread_create =%d\n", errno);
562     return HAL_INPUT_RET_ERROR;
563   }
564
565   return HAL_INPUT_RET_NORMAL;
566 }