4 * Copyright (c) 2022 Samsung Electronics Co., Ltd.
6 * Licensed under the Apache License, Version 2.0 (the License);
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
22 #include <linux/input.h>
24 #include <libsyscommon/libgdbus.h>
25 #include <libsyscommon/list.h>
27 #include "shared/common.h"
28 #include "shared/device-notifier.h"
29 #include "shared/log.h"
30 #include "shared/event.h"
32 #include "input-config.h"
33 #include "input/input.h"
34 #include "input/input-plugin-interface.h"
36 static int input_event_handler_id;
38 static gboolean level_event_detected(gpointer data)
40 struct input_event_unit *ieu = (struct input_event_unit *) data;
44 _D("Detected level event=%s(%d), action=%d", ieu->name, ieu->id, ieu->notifier);
46 if (check_input_event_condition(ieu) == 0) {
47 _D("Skip triggering event=%s(%d), condition=%s isn't meet", ieu->name, ieu->id, ieu->cv.keyname);
48 return G_SOURCE_REMOVE;
52 event_broadcast_id(ieu->id);
54 if (ieu->wakelock_duration > 0)
55 event_acquire_wakelock(ieu->id, ieu->wakelock_duration);
58 syscommon_notifier_emit_notify(ieu->notifier, ieu->user_data);
60 return G_SOURCE_REMOVE;
63 static void edge_event_detected(struct input_event_unit *ieu)
65 _D("Detected edge event=%s(%d), action=%d", ieu->name, ieu->id, ieu->notifier);
67 if (check_input_event_condition(ieu) == 0) {
68 _D("Skip triggering event=%s(%d), condition=%s isn't meet", ieu->name, ieu->id, ieu->cv.keyname);
73 event_broadcast_id(ieu->id);
75 if (ieu->wakelock_duration > 0)
76 event_acquire_wakelock(ieu->id, ieu->wakelock_duration);
79 syscommon_notifier_emit_notify(ieu->notifier, ieu->user_data);
82 static void start_event_timer(struct input_config *ic)
85 struct input_event_unit *ieu;
88 clock_gettime(CLOCK_MONOTONIC, &ts);
89 ic->start = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
91 /* set timer for level-trigger event */
92 SYS_G_LIST_FOREACH(ic->event_list, elem, ieu) {
93 if (ieu->type == TRIGGER_TYPE_LEVEL) {
95 g_source_remove(ieu->timer);
96 ieu->timer = g_timeout_add(ieu->interval[0], level_event_detected, (gpointer) ieu);
101 static void stop_event_timer(struct input_config *ic)
104 struct input_event_unit *ieu;
106 unsigned long current;
112 clock_gettime(CLOCK_MONOTONIC, &ts);
113 current = ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
114 lapse = current - ic->start;
117 SYS_G_LIST_FOREACH(ic->event_list, elem, ieu) {
118 /* remove all level-trigger timer */
120 g_source_remove(ieu->timer);
124 /* detected edge-trigger event */
125 if (lapse >= ieu->interval[0] && lapse < ieu->interval[1] && ieu->type == TRIGGER_TYPE_EDGE)
126 edge_event_detected(ieu);
130 static void input_handler_process_key(struct timeval time, unsigned short type, unsigned short keycode, unsigned int keyvalue)
132 struct input_config *ic;
137 _D("Key input: code=%d, value=%d", keycode, keyvalue);
139 /* acquire tmplock on pressing key */
140 if (keyvalue == KEY_PRESSED)
141 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_KEY_PRESS, (void *)(intptr_t) keycode);
143 /* process all registered event to the keycode */
144 ic = find_input_config(keycode);
145 if (ic && keyvalue == KEY_PRESSED)
146 start_event_timer(ic);
147 else if (ic && keyvalue == KEY_RELEASED)
148 stop_event_timer(ic);
150 /* release tmplock on releasing key */
151 if (keyvalue == KEY_RELEASED)
152 syscommon_notifier_emit_notify(DEVICE_NOTIFIER_KEY_RELEASE, (void *)(intptr_t) keycode);
155 static int input_handler_init(void *data)
158 input_register_event_callback(input_handler_process_key, NULL, NULL, &input_event_handler_id);
163 static void input_handler_exit(void *data)
165 input_unregister_event_callback(input_event_handler_id);
168 const struct input_plugin_interface INPUT_PLUGIN_INTERFACE_SYMBOL = {
169 .init = input_handler_init,
170 .exit = input_handler_exit,