2 * @copyright Copyright (c) 2017-2020 TOYOTA MOTOR CORPORATION.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include <sys/prctl.h>
25 #include <sys/types.h>
29 #include <native_service/ns_message_center_if.h>
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"
37 #define HAL_INPUT_UDEVMONITOR_THREADNAME "input_hal_udevm"
38 #define max_value(x, y) ((x) > (y) ? (x) : (y))
40 #define INPUT_VIRTUAL_INPUTDEVICE_NAME "/devices/virtual" /* Virtual device name created by SwitchManager */
42 // Enough name length to contain node name
43 #define INPUT_NODE_NAME_LENGTH 256
45 #define TRACKING_ID_NONE -1
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 */
54 static void InputUdevMonitorTouchInitFinEventSend(int result) {
55 struct TouchInitFinishInput msg;
57 if (g_input_touch_init_notify) {
61 if (NULL == g_sender_handle) {
62 g_sender_handle = McOpenSender(g_app_name);
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;
72 static void InputUdevMonitorInputEventHandle(int fd, int device_type, int notify_id) {
74 struct EventsPackageInput events = {0};
76 read_size = read(fd, events.event, sizeof(events.event));
78 events.count = read_size / sizeof(struct input_event);
79 events.device_type = device_type;
81 if (NULL == g_sender_handle) {
82 g_sender_handle = McOpenSender(g_app_name);
86 g_sender_handle, HAL_INPUT_SOURCE_NAME,
87 notify_id, sizeof(events), &events);
91 static void InputUdevMonitorTouchEventHandle(int fd, int notify_id) {
93 struct input_event event[HAL_INPUT_EVENT_COUNT] = {0};
96 read_size = read(fd, event, sizeof(event));
99 if (NULL == g_sender_handle) {
100 g_sender_handle = McOpenSender(g_app_name);
103 int event_num = read_size / sizeof(struct input_event);
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;
111 touch_status = HAL_INPUT_TOUCH_PRESS;
114 g_sender_handle, HAL_INPUT_SOURCE_NAME,
115 notify_id, sizeof(touch_status), &touch_status);
122 static int InputUdevMonitorDeviceAssort(struct udev_device *dev) {
123 const char *property;
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;
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;
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;
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;
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;
161 return HAL_INPUT_DEVICE_INVALID;
164 static void InputUdevMonitorDeviceListOutput(void) {
165 struct InputUtilList *p;
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);
171 INPUT_LOG_TRACE("FD: %d Device=%s Assort=%d\n",
172 entry->fd, entry->device_node, entry->device_assort);
175 INPUT_LOG_TRACE("OutputList << end ======================\n");
178 static void InputUdevMonitorDeviceListDelete(const char *node) {
179 struct InputUtilList *p;
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) {
185 InputUtilListDelete(p);
190 InputUdevMonitorDeviceListOutput();
193 static int InputUdevMonitorDeviceListAdd(int fd, int device_assort, const char *node) {
194 int ret = HAL_INPUT_RET_NORMAL;
195 struct InputInputDeviceList *p;
197 p = (struct InputInputDeviceList *) malloc(sizeof(struct InputInputDeviceList));
200 p->device_assort = device_assort;
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);
207 ret = HAL_INPUT_RET_ERROR;
210 ret = HAL_INPUT_RET_ERROR;
213 InputUdevMonitorDeviceListOutput();
218 static int InputUdevMonitorInputEventGrab(const char *node, struct udev_device *dev) {
221 InputUdevMonitorDeviceListDelete(node);
223 fd = open(node, O_RDONLY);
226 INPUT_ERROR_LOG("ERR: open %s errno=%d \n", node, errno);
230 rtn = ioctl(fd, EVIOCGRAB, 1);
232 INPUT_ERROR_LOG("ERR: ioctl grab %s \n", node);
235 INPUT_LOG_TRACE("%s Grab \n", node);
238 rtn = InputUdevMonitorDeviceListAdd(fd, InputUdevMonitorDeviceAssort(dev), node);
243 return HAL_INPUT_RET_NORMAL;
248 INPUT_LOG_TRACE("%s Grab impossible \n", node);
249 return HAL_INPUT_RET_ERROR;
252 static void InputUdevMonitorFDSet(int *nfds, fd_set *fds) {
253 struct InputUtilList *p;
255 input_list_for_each(p, &g_input_udevmonitor_info.dev_list.list) {
256 struct InputInputDeviceList *entry = input_list_entry(p, struct InputInputDeviceList, list);
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);
272 static void InputUdevMonitorFDHandle(fd_set *fds) {
273 struct InputUtilList *p;
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)) {
279 switch (entry->device_assort) {
280 case HAL_INPUT_DEVICE_TOUCH_ESCKEY:
281 notify_id = HAL_INPUT_NOTIFY_ESC_KEY;
283 case HAL_INPUT_DEVICE_TOUCH:
284 notify_id = HAL_INPUT_NOTIFY_TOUCH;
286 case HAL_INPUT_DEVICE_KEYBOARD:
287 notify_id = HAL_INPUT_NOTIFY_KEY_BOARD;
289 case HAL_INPUT_DEVICE_TABLET_FINGER:
290 notify_id = HAL_INPUT_NOTIFY_TABLET_FINGER;
295 if (notify_id == HAL_INPUT_NOTIFY_TOUCH) {
296 InputUdevMonitorTouchEventHandle(entry->fd, notify_id);
298 InputUdevMonitorInputEventHandle(entry->fd, entry->device_assort, notify_id);
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;
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);
315 // start receiving hotplug events
316 udev_monitor_enable_receiving(g_input_udevmonitor_info.monitor);
318 INPUT_INIT_LIST_HEAD(&g_input_udevmonitor_info.dev_list.list)
320 return HAL_INPUT_RET_NORMAL;
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);
329 if (g_sender_handle != NULL) {
330 McClose(g_sender_handle);
331 g_sender_handle = NULL;
334 g_input_touch_init_notify = false;
337 static int InputUdevMonitorDevicesGet(void) {
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;
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));
352 // Enumerate device list
353 udev_list_entry_foreach(dev_list_entry, devices) {
354 const char *path, *node;
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;
361 // usb_device_get_devnode() returns the path to the device node itself in /dev.
362 node = udev_device_get_devnode(dev);
364 udev_device_unref(dev);
368 // Filter device name is eventX
369 if (strncmp("event", udev_device_get_sysname(dev), sizeof("event") -1) != 0) {
370 udev_device_unref(dev);
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);
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);
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);
397 if (0 == strcmp(touch_device_name, sysattr_name)) {
398 INPUT_LOG_TRACE("Found %s : %s \n", touch_device_name, path);
401 GetPanelSpecResolutionInput(&spec_reso_h, &spec_reso_v);
402 ret = ConfigTouch(udev_device_get_syspath(input_dev),
403 spec_reso_h, spec_reso_v);
405 if (HAL_INPUT_RET_NORMAL == ret) {
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);
413 INPUT_ERROR_LOG("GetConfigStatusTouch fail\n");
414 InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_ERROR);
417 INPUT_ERROR_LOG("ConfigTouch fail\n");
418 InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_ERROR);
421 input_touch_device_found = true;
424 INPUT_LOG_TRACE("Found Device : %s \n", node);
426 /* Modified not to notify input events to other processes */
427 InputUdevMonitorInputEventGrab(node, input_dev);
429 udev_device_unref(dev);
432 if (!input_touch_device_found) {
433 INPUT_ERROR_LOG("ERR: Dummy Device Create");
434 InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_NORMAL);
437 // Free the enumerator object
438 udev_enumerate_unref(enumerate);
440 return HAL_INPUT_RET_NORMAL;
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;
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);
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);
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);
469 if (strcmp(action, "remove") == 0) {
470 InputUdevMonitorDeviceListDelete(node);
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);
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);
487 if (0 == strcmp(touch_device_name, sysattr_name)) {
488 if (strcmp(action, "remove") == 0) {
490 INPUT_LOG_TRACE("Found %s \n", touch_device_name);
491 InputUdevMonitorTouchInitFinEventSend(HAL_INPUT_RET_NORMAL);
495 INPUT_LOG_TRACE("%s : %s \n", node, action);
496 if (strcmp(action, "remove") == 0) {
498 /* Modified not to notify input events to other processes */
499 InputUdevMonitorInputEventGrab(node, input_dev);
501 udev_device_unref(dev);
505 static void InputUdevMonitorWatch(void) {
507 int fd = udev_monitor_get_fd(g_input_udevmonitor_info.monitor);
510 while (!g_break_from_watch) {
513 int nfds = max_value(0, fd);
515 InputUdevMonitorFDSet(&nfds, &fds);
517 struct timeval timeout;
519 timeout.tv_usec = 100 * 1000;
520 int ret = select(nfds + 1, &fds, NULL, NULL, &timeout);
522 InputUdevMonitorDeviceStatusChange(fd, &fds);
524 InputUdevMonitorFDHandle(&fds);
528 INPUT_ERROR_LOG("ERR: udev_monitor_get_fd");
532 static void *InputUdevMonitorMain(void * arg) {
534 prctl(PR_SET_NAME, HAL_INPUT_UDEVMONITOR_THREADNAME);
536 rtn = InputUdevMonitorInit();
537 if (rtn != HAL_INPUT_RET_NORMAL) {
541 /* Get input device */
542 InputUdevMonitorDevicesGet();
544 /* Input device monitoring (basically never get out from here) */
545 InputUdevMonitorWatch();
547 InputUdevMonitorDeinit();
552 INPUT_LOG_TRACE("pthread_detach\n");
556 int32_t InputUdevMonitorThreadCreate(void) {
559 ret = pthread_create(&g_udev_monitor_thread, NULL, InputUdevMonitorMain, NULL);
561 INPUT_ERROR_LOG("ERR: pthread_create =%d\n", errno);
562 return HAL_INPUT_RET_ERROR;
565 return HAL_INPUT_RET_NORMAL;