2 * Copyright 2012 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.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.tizenopensource.org/license
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.
21 * @brief Power Manager poll implementation (input devices & a domain socket file)
23 * This file includes the input device poll implementation.
24 * Default input devices are /dev/event0 and /dev/event1
25 * User can use "PM_INPUT" for setting another input device poll in an environment file (/etc/profile).
26 * (ex: PM_INPUT=/dev/event0:/dev/event1:/dev/event5 )
32 #include <sys/types.h>
38 #include <sys/socket.h>
45 #define DEV_PATH_DLM ":"
48 int (*g_pm_callback) (int, PMMsg *);
50 #ifdef ENABLE_KEY_FILTER
51 extern int check_key_filter(int length, char buf[]);
52 # define CHECK_KEY_FILTER(a, b) do {\
53 if (check_key_filter(a, b) != 0)\
58 # define CHECK_KEY_FILTER(a, b)
61 #define DEFAULT_DEV_PATH "/dev/event1:/dev/event0"
64 static GSourceFuncs *funcs;
67 static gboolean pm_check(GSource *src)
72 fd_list = src->poll_fds;
74 tmp = (GPollFD *) fd_list->data;
75 if ((tmp->revents & (POLLIN | POLLPRI)))
77 fd_list = fd_list->next;
83 static gboolean pm_dispatch(GSource *src, GSourceFunc callback, gpointer data)
89 static gboolean pm_prepare(GSource *src, gint *timeout)
94 gboolean pm_handler(gpointer data)
97 struct sockaddr_un clientaddr;
99 GPollFD *gpollfd = (GPollFD *) data;
101 int clilen = sizeof(clientaddr);
103 if (g_pm_callback == NULL) {
106 if (gpollfd->fd == sockfd) {
108 recvfrom(gpollfd->fd, &recv_data, sizeof(recv_data), 0,
109 (struct sockaddr *)&clientaddr,
110 (socklen_t *)&clilen);
111 (*g_pm_callback) (PM_CONTROL_EVENT, &recv_data);
113 ret = read(gpollfd->fd, buf, sizeof(buf));
114 CHECK_KEY_FILTER(ret, buf);
115 (*g_pm_callback) (INPUT_POLL_EVENT, NULL);
121 static int init_sock(char *sock_path)
123 struct sockaddr_un serveraddr;
126 LOGINFO("initialize pm_socket for pm_control library");
128 if (sock_path == NULL || strcmp(sock_path, SOCK_PATH)) {
129 LOGERR("invalid sock_path= %s");
133 fd = socket(AF_UNIX, SOCK_DGRAM, 0);
135 LOGERR("socket error");
141 bzero(&serveraddr, sizeof(serveraddr));
142 serveraddr.sun_family = AF_UNIX;
143 strncpy(serveraddr.sun_path, sock_path, sizeof(serveraddr.sun_path) - 1);
145 if (bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0) {
146 LOGERR("bind error");
150 if (chmod(sock_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) /* 0777 */
151 LOGERR("failed to change the socket permission");
153 if (!strcmp(sock_path, SOCK_PATH))
156 LOGDBG("init sock() sueccess!");
160 int init_pm_poll(int (*pm_callback) (int, PMMsg *))
164 char *dev_paths, *path_tok, *pm_input_env, *save_ptr;
169 g_pm_callback = pm_callback;
172 ("initialize pm poll - input devices and domain socket(libpmapi)");
174 pm_input_env = getenv("PM_INPUT");
175 if ((pm_input_env != NULL) && (strlen(pm_input_env) < 1024)) {
176 LOGDBG("Getting input device path from environment: %s",
178 /* Add 2 bytes for following strncat() */
179 dev_paths_size = strlen(pm_input_env) + strlen(SOCK_PATH) + strlen(DEV_PATH_DLM) + 1;
180 dev_paths = (char *)malloc(dev_paths_size);
181 snprintf(dev_paths, dev_paths_size, "%s", pm_input_env);
183 /* Add 2 bytes for following strncat() */
184 dev_paths_size = strlen(DEFAULT_DEV_PATH) + strlen(SOCK_PATH) + strlen(DEV_PATH_DLM) + 1;
185 dev_paths = (char *)malloc(dev_paths_size);
186 snprintf(dev_paths, dev_paths_size, "%s", DEFAULT_DEV_PATH);
189 /* add the UNIX domain socket file path */
190 strncat(dev_paths, DEV_PATH_DLM, strlen(DEV_PATH_DLM));
191 strncat(dev_paths, SOCK_PATH, strlen(SOCK_PATH));
192 dev_paths[dev_paths_size - 1] = '\0';
194 path_tok = strtok_r(dev_paths, DEV_PATH_DLM, &save_ptr);
195 if (path_tok == NULL) {
196 LOGERR("Device Path Tokeninzing Failed");
201 funcs = (GSourceFuncs *) g_malloc(sizeof(GSourceFuncs));
202 funcs->prepare = pm_prepare;
203 funcs->check = pm_check;
204 funcs->dispatch = pm_dispatch;
205 funcs->finalize = NULL;
208 src = g_source_new(funcs, sizeof(GSource));
210 gpollfd = (GPollFD *) g_malloc(sizeof(GPollFD));
211 gpollfd->events = POLLIN;
213 if (strcmp(path_tok, SOCK_PATH) == 0) {
214 gpollfd->fd = init_sock(SOCK_PATH);
215 LOGDBG("pm_poll domain socket file: %s, fd: %d",
216 path_tok, gpollfd->fd);
218 gpollfd->fd = open(path_tok, O_RDONLY);
219 LOGDBG("pm_poll input device file: %s, fd: %d",
220 path_tok, gpollfd->fd);
223 if (gpollfd->fd == -1) {
224 LOGERR("Cannot open the file: %s", path_tok);
228 g_source_add_poll(src, gpollfd);
229 g_source_set_callback(src, (GSourceFunc) pm_handler,
230 (gpointer) gpollfd, NULL);
232 g_source_set_priority(src, G_PRIORITY_LOW);
233 ret = g_source_attach(src, NULL);
235 LOGERR("Failed g_source_attach() in init_pm_poll()");
241 } while ((path_tok = strtok_r(NULL, DEV_PATH_DLM, &save_ptr)));
252 LOGINFO("pm_poll is finished");
256 int init_pm_poll_input(int (*pm_callback)(int , PMMsg * ), const char *path)
259 indev *adddev = NULL;
261 g_pm_callback = pm_callback;
267 LOGINFO("initialize pm poll for bt %s",path);
268 adddev=(indev *)malloc(sizeof(indev));
269 adddev->dev_fd = (GPollFD *)g_malloc(sizeof(GPollFD));
270 (adddev->dev_fd)->events = POLLIN;
271 (adddev->dev_fd)->fd = open(path, O_RDONLY);
272 if((adddev->dev_fd)->fd == -1) {
273 LOGERR("Cannot open the file for BT: %s",path);
274 g_free(adddev->dev_fd);
278 adddev->dev_path = (char *)malloc(strlen(path) + 1);
279 strncpy(adddev->dev_path, path, strlen(path) + 1);
280 adddev->dev_src = g_source_new(funcs, sizeof(GSource));
281 LOGINFO("pm_poll for BT input device file(path: %s, gsource: %d, gpollfd: %d", adddev->dev_path, adddev->dev_src, adddev->dev_fd);
282 indev_list=g_list_append(indev_list, adddev);
284 g_source_add_poll(adddev->dev_src, adddev->dev_fd);
286 g_source_set_callback(adddev->dev_src, (GSourceFunc) pm_handler, (gpointer)adddev->dev_fd, NULL);
289 g_source_set_priority(adddev->dev_src, G_PRIORITY_LOW );
291 ret = g_source_attach(adddev->dev_src, NULL);
294 LOGERR("Failed g_source_attach() in init_pm_poll()");
297 g_source_unref(adddev->dev_src);