4 * Copyright (c) 2012 - 2013 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 * @brief Power Manager poll implementation (input devices & a domain socket file)
24 * This file includes the input device poll implementation.
25 * Default input devices are /dev/event0 and /dev/event1
26 * User can use "PM_INPUT" for setting another input device poll in an environment file (/etc/profile).
27 * (ex: PM_INPUT=/dev/event0:/dev/event1:/dev/event5 )
32 #include <sys/types.h>
38 #include <sys/socket.h>
41 #include <core/devices.h>
42 #include <core/device-handler.h>
47 #define SHIFT_UNLOCK 4
48 #define SHIFT_UNLOCK_PARAMETER 12
49 #define SHIFT_CHANGE_STATE 8
50 #define SHIFT_CHANGE_TIMEOUT 20
51 #define LOCK_FLAG_SHIFT 16
52 #define __HOLDKEY_BLOCK_BIT 0x1
53 #define __STANDBY_MODE_BIT 0x2
54 #define HOLDKEY_BLOCK_BIT (__HOLDKEY_BLOCK_BIT << LOCK_FLAG_SHIFT)
55 #define STANDBY_MODE_BIT (__STANDBY_MODE_BIT << LOCK_FLAG_SHIFT)
57 #define DEV_PATH_DLM ":"
60 int (*g_pm_callback) (int, PMMsg *);
62 #ifdef ENABLE_KEY_FILTER
63 extern int check_key_filter(int length, char buf[], int fd);
64 # define CHECK_KEY_FILTER(a, b, c) \
66 if (CHECK_OPS(keyfilter_ops, check) && \
67 keyfilter_ops->check(a, b, c) != 0) \
71 # define CHECK_KEY_FILTER(a, b, c)
74 #define DEFAULT_DEV_PATH "/dev/event1:/dev/event0"
76 static Eina_Bool pm_handler(void *data, Ecore_Fd_Handler *fd_handler)
79 struct sockaddr_un clientaddr;
83 static const struct device_ops *display_device_ops;
85 if (!display_device_ops) {
86 display_device_ops = find_device("display");
87 if (!display_device_ops)
91 if (device_get_status(display_device_ops) != DEVICE_OPS_STATUS_START) {
92 _E("display is not started!");
96 if (g_pm_callback == NULL) {
100 ret = read(fd, buf, sizeof(buf));
101 CHECK_KEY_FILTER(ret, buf, fd);
102 (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
107 int init_pm_poll(int (*pm_callback) (int, PMMsg *))
109 char *dev_paths, *path_tok, *pm_input_env, *save_ptr;
112 Ecore_Fd_Handler *fd_handler;
114 indev *new_dev = NULL;
116 g_pm_callback = pm_callback;
118 _I("initialize pm poll - input devices(deviced)");
120 pm_input_env = getenv("PM_INPUT");
121 if ((pm_input_env != NULL) && (strlen(pm_input_env) < 1024)) {
122 _I("Getting input device path from environment: %s",
124 /* Add 2 bytes for following strncat() */
125 dev_paths_size = strlen(pm_input_env) + 1;
126 dev_paths = (char *)malloc(dev_paths_size);
128 _E("Fail to malloc for dev path");
131 snprintf(dev_paths, dev_paths_size, "%s", pm_input_env);
133 /* Add 2 bytes for following strncat() */
134 dev_paths_size = strlen(DEFAULT_DEV_PATH) + 1;
135 dev_paths = (char *)malloc(dev_paths_size);
137 _E("Fail to malloc for dev path");
140 snprintf(dev_paths, dev_paths_size, "%s", DEFAULT_DEV_PATH);
143 /* add the UNIX domain socket file path */
144 strncat(dev_paths, DEV_PATH_DLM, strlen(DEV_PATH_DLM));
145 dev_paths[dev_paths_size - 1] = '\0';
147 path_tok = strtok_r(dev_paths, DEV_PATH_DLM, &save_ptr);
148 if (path_tok == NULL) {
149 _E("Device Path Tokeninzing Failed");
155 char *path, *new_path;
158 fd = open(path_tok, O_RDONLY);
160 _I("pm_poll input device file: %s, fd: %d", path_tok, fd);
163 _E("Cannot open the file: %s", path_tok);
167 fd_handler = ecore_main_fd_handler_add(fd,
168 ECORE_FD_READ|ECORE_FD_ERROR,
169 pm_handler, (void *)fd, NULL, NULL);
170 if (fd_handler == NULL) {
171 _E("Failed ecore_main_handler_add() in init_pm_poll()");
175 new_dev = (indev *)malloc(sizeof(indev));
178 _E("Fail to malloc for new_dev %s", path);
182 memset(new_dev, 0, sizeof(indev));
184 len = strlen(path) + 1;
185 new_path = (char*) malloc(len);
187 _E("Fail to malloc for dev_path %s", path);
191 strncpy(new_path, path, len);
192 new_dev->dev_path = new_path;
194 new_dev->dev_fd = fd_handler;
195 new_dev->pre_install = true;
196 indev_list = eina_list_append(indev_list, new_dev);
198 } while ((path_tok = strtok_r(NULL, DEV_PATH_DLM, &save_ptr)));
206 ecore_main_fd_handler_del(fd_handler);
215 int exit_pm_poll(void)
218 Eina_List *l_next = NULL;
221 EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data) {
222 ecore_main_fd_handler_del(data->dev_fd);
224 free(data->dev_path);
226 indev_list = eina_list_remove_list(indev_list, l);
229 _I("pm_poll is finished");
233 int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path)
235 indev *new_dev = NULL;
237 Ecore_Fd_Handler *fd_handler = NULL;
239 Eina_List *l_next = NULL;
241 char *dev_path = NULL;
243 if (!pm_callback || !path) {
244 _E("argument is NULL! (%x,%x)", pm_callback, path);
248 EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data)
249 if(!strcmp(path, data->dev_path)) {
250 _E("%s is already polled!", path);
254 _I("initialize pm poll for bt %s", path);
256 g_pm_callback = pm_callback;
258 fd = open(path, O_RDONLY);
260 _E("Cannot open the file for BT: %s", path);
264 dev_path = (char*)malloc(strlen(path) + 1);
266 _E("Fail to malloc for dev_path");
270 strncpy(dev_path, path, strlen(path) +1);
272 fd_handler = ecore_main_fd_handler_add(fd,
273 ECORE_FD_READ|ECORE_FD_ERROR,
274 pm_handler, (void *)fd, NULL, NULL);
276 _E("Fail to ecore fd handler add! %s", path);
282 new_dev = (indev *)malloc(sizeof(indev));
284 _E("Fail to malloc for new_dev %s", path);
285 ecore_main_fd_handler_del(fd_handler);
290 new_dev->dev_path = dev_path;
292 new_dev->dev_fd = fd_handler;
293 new_dev->pre_install = false;
295 _I("pm_poll for BT input device file(path: %s, fd: %d",
296 new_dev->dev_path, new_dev->fd);
297 indev_list = eina_list_append(indev_list, new_dev);
302 int check_pre_install(int fd)
306 Eina_List *l_next = NULL;
308 EINA_LIST_FOREACH_SAFE(indev_list, l, l_next, data)
310 return data->pre_install;
316 int check_dimstay(int next_state, int flag)
318 if (next_state != LCD_OFF)
321 if (!(flag & GOTO_STATE_NOW))
324 if (!(pm_status_flag & DIMSTAY_FLAG))
327 if (check_abnormal_popup() != HEALTH_BAD)
333 int pm_lock_internal(pid_t pid, int s_bits, int flag, int timeout)
346 if (flag & GOTO_STATE_NOW)
347 /* if the flag is true, go to the locking state directly */
348 s_bits = s_bits | (s_bits << SHIFT_CHANGE_STATE);
350 if (flag & HOLD_KEY_BLOCK)
351 s_bits = s_bits | HOLDKEY_BLOCK_BIT;
353 if (flag & STANDBY_MODE)
354 s_bits = s_bits | STANDBY_MODE_BIT;
357 recv_data.cond = s_bits;
358 recv_data.timeout = timeout;
360 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
365 int pm_unlock_internal(pid_t pid, int s_bits, int flag)
379 s_bits = (s_bits << SHIFT_UNLOCK);
380 s_bits = (s_bits | (flag << SHIFT_UNLOCK_PARAMETER));
383 recv_data.cond = s_bits;
385 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);
390 int pm_change_internal(pid_t pid, int s_bits)
406 recv_data.cond = s_bits << SHIFT_CHANGE_STATE;
408 (*g_pm_callback)(PM_CONTROL_EVENT, &recv_data);