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.
21 #include <linux/input.h>
22 #include <libsyscommon/ini-parser.h>
24 #include "shared/bitmap.h"
25 #include "shared/device-notifier.h"
26 #include "shared/log.h"
27 #include "power-event-lock.h"
29 #define BATTERY_CONF_FILE "/etc/deviced/battery.conf"
31 /* eventlock is another wakelock than mainlock.
33 * The eventlock works independently of mainlock, which is controlled by
34 * power state. The main purpose of eventlock is to prevent the subroutine
35 * of an event from going to sleep regardless of the power state. */
36 #define EVENT_LOCK "eventlock"
40 /* On receiving key event, expands EL_KEY to EL_KEY_* according to keycode */
42 EL_KEY_POWER = EL_KEY,
46 /* add eventlock type here */
50 static struct dd_bitmap *eventlock;
51 static int notifier_id[EL_MAX][2];
53 static void event_wake_lock(enum eventlock_type type)
57 if (type <= EL_MIN || type >= EL_MAX)
60 set_bit(eventlock, type);
61 setcount = count_set_bit(eventlock);
63 _D("Set eventlock of type=%d, current number of eventlock=%d", type, setcount);
66 sys_set_str("/sys/power/wake_lock", EVENT_LOCK);
67 _D("Acquired eventlock");
71 static void event_wake_unlock(enum eventlock_type type)
75 if (type <= EL_MIN || type >= EL_MAX)
78 clear_bit(eventlock, type);
79 setcount = count_set_bit(eventlock);
81 _D("Unset eventlock of type=%d, current number of eventlock=%d", type, setcount);
84 sys_set_str("/sys/power/wake_unlock", EVENT_LOCK);
85 _D("Released eventlock");
89 static enum eventlock_type expand_key_eventlock_type(int keycode)
91 if (keycode == KEY_POWER)
93 if (keycode == KEY_BLUETOOTH)
94 return EL_KEY_BLUETOOTH;
95 /* add mapping for keycode to eventlock_type here */
100 static int power_event_lock_callback(void *data, void *udata)
102 enum eventlock_type type = (enum eventlock_type)(intptr_t) udata;
104 if (type == EL_KEY) {
105 /* On receiving key event, expand EL_KEY to EL_KEY_* according to the keycode */
106 int keycode = (int)(intptr_t) data;
107 type = expand_key_eventlock_type(keycode);
110 event_wake_lock(type);
115 static int power_event_unlock_callback(void *data, void *udata)
117 enum eventlock_type type = (enum eventlock_type)(intptr_t) udata;
119 if (type == EL_KEY) {
120 /* On receiving key event, expand EL_KEY to EL_KEY_* according to the keycode */
121 int keycode = (int)(intptr_t) data;
122 type = expand_key_eventlock_type(keycode);
125 event_wake_unlock(type);
130 static void register_power_event_lock_controller(enum eventlock_type type,
131 enum device_notifier_type lock_notify,
132 enum device_notifier_type unlock_notify)
134 /* Acquiring lock must be followed by all the other notifiers, therefore
135 * give a large enough number as priority to make it be at the head of notifier list.
136 * On the other hand, releasing lock must follow all the other notifiers, therefore
137 * give a small enough number as priority to make it be at the tail of notifier list. */
138 notifier_id[type][0] = register_notifier_udata_priority(lock_notify,
139 power_event_lock_callback, (void *)(intptr_t) type, NULL, 1000);
140 notifier_id[type][1] = register_notifier_udata_priority(unlock_notify,
141 power_event_unlock_callback, (void *)(intptr_t) type, NULL, -1000);
144 static int check_charger_wakelock(struct parse_result *result, void *user_data)
146 if (MATCH(result->section, "ChargerWakelock")
147 && MATCH(result->name, "ChargerWakeLockEnabled")
148 && MATCH(result->value, "yes"))
149 *(int *) user_data = 1;
154 void power_event_lock_init(void)
156 int charger_wakelock = 0;
158 eventlock = init_bitmap(EL_MAX);
160 _E("Failed to init event lock bitmap");
164 config_parse(BATTERY_CONF_FILE, check_charger_wakelock, &charger_wakelock);
166 register_power_event_lock_controller(EL_KEY,
167 DEVICE_NOTIFIER_KEY_PRESS,
168 DEVICE_NOTIFIER_KEY_RELEASE);
170 if (charger_wakelock) {
171 register_power_event_lock_controller(EL_CHARGER,
172 DEVICE_NOTIFIER_BATTERY_CHARGER_CONNECTED,
173 DEVICE_NOTIFIER_BATTERY_CHARGER_DISCONNECTED);