summaryrefslogtreecommitdiff
path: root/sysnoti.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysnoti.c')
-rw-r--r--sysnoti.c362
1 files changed, 362 insertions, 0 deletions
diff --git a/sysnoti.c b/sysnoti.c
new file mode 100644
index 0000000..106bd55
--- /dev/null
+++ b/sysnoti.c
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <vconf.h>
+#include <vconf-keys.h>
+
+#include "sysman.h"
+#include "sysman-priv.h"
+
+#define PREDEF_PWROFF_POPUP "pwroff-popup"
+#define PREDEF_ENTERSLEEP "entersleep"
+#define PREDEF_LEAVESLEEP "leavesleep"
+#define PREDEF_REBOOT "reboot"
+#define PREDEF_BACKGRD "backgrd"
+#define PREDEF_FOREGRD "foregrd"
+#define PREDEF_ACTIVE "active"
+#define PREDEF_INACTIVE "inactive"
+#define PREDEF_SET_DATETIME "set_datetime"
+#define PREDEF_SET_TIMEZONE "set_timezone"
+#define PREDEF_MOUNT_MMC "mountmmc"
+#define PREDEF_UNMOUNT_MMC "unmountmmc"
+#define PREDEF_FORMAT_MMC "formatmmc"
+
+#define PREDEF_SET_MAX_FREQUENCY "set_max_frequency"
+#define PREDEF_SET_MIN_FREQUENCY "set_min_frequency"
+#define PREDEF_RELEASE_MAX_FREQUENCY "release_max_frequency"
+#define PREDEF_RELEASE_MIN_FREQUENCY "release_min_frequency"
+
+enum sysnoti_cmd {
+ ADD_SYSMAN_ACTION,
+ CALL_SYSMAN_ACTION
+};
+
+#define SYSNOTI_SOCKET_PATH "/tmp/sn"
+
+static inline int send_int(int fd, int val)
+{
+ return write(fd, &val, sizeof(int));
+}
+
+static inline int send_str(int fd, char *str)
+{
+ int len;
+ int ret;
+ if (str == NULL) {
+ len = 0;
+ ret = write(fd, &len, sizeof(int));
+ } else {
+ len = strlen(str);
+ if (len > SYSMAN_MAXSTR)
+ len = SYSMAN_MAXSTR;
+ write(fd, &len, sizeof(int));
+ ret = write(fd, str, len);
+ }
+ return ret;
+}
+
+static int sysnoti_send(struct sysnoti *msg)
+{
+ ERR("--- %s: start", __FUNCTION__);
+ int client_len;
+ int client_sockfd;
+ int result;
+ struct sockaddr_un clientaddr;
+ int i;
+
+ client_sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (client_sockfd == -1) {
+ ERR("%s: socket create failed\n", __FUNCTION__);
+ return -1;
+ }
+ bzero(&clientaddr, sizeof(clientaddr));
+ clientaddr.sun_family = AF_UNIX;
+ strncpy(clientaddr.sun_path, SYSNOTI_SOCKET_PATH, sizeof(clientaddr.sun_path) - 1);
+ client_len = sizeof(clientaddr);
+
+ if (connect(client_sockfd, (struct sockaddr *)&clientaddr, client_len) <
+ 0) {
+ ERR("%s: connect failed\n", __FUNCTION__);
+ close(client_sockfd);
+ return -1;
+ }
+
+ send_int(client_sockfd, msg->pid);
+ send_int(client_sockfd, msg->cmd);
+ send_str(client_sockfd, msg->type);
+ send_str(client_sockfd, msg->path);
+ send_int(client_sockfd, msg->argc);
+ for (i = 0; i < msg->argc; i++)
+ send_str(client_sockfd, msg->argv[i]);
+
+ ERR("--- %s: read", __FUNCTION__);
+ read(client_sockfd, &result, sizeof(int));
+
+ close(client_sockfd);
+ ERR("--- %s: end", __FUNCTION__);
+ return result;
+}
+
+API int sysman_call_predef_action(const char *type, int num, ...)
+{
+ ERR("--- %s: start", __FUNCTION__);
+ struct sysnoti *msg;
+ int ret;
+ va_list argptr;
+
+ int i;
+ char *args = NULL;
+
+ if (type == NULL || num > SYSMAN_MAXARG) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ msg = malloc(sizeof(struct sysnoti));
+
+ if (msg == NULL) {
+ /* Do something for not enought memory error */
+ return -1;
+ }
+
+ msg->pid = getpid();
+ msg->cmd = CALL_SYSMAN_ACTION;
+ msg->type = (char *)type;
+ msg->path = NULL;
+
+ msg->argc = num;
+ va_start(argptr, num);
+ for (i = 0; i < num; i++) {
+ args = va_arg(argptr, char *);
+ msg->argv[i] = args;
+ }
+ va_end(argptr);
+
+ ERR("--- %s: send msg", __FUNCTION__);
+ ret = sysnoti_send(msg);
+ free(msg);
+
+ ERR("--- %s: end", __FUNCTION__);
+ return ret;
+}
+
+API int sysman_inform_foregrd(void)
+{
+ char buf[255];
+ snprintf(buf, sizeof(buf), "%d", getpid());
+ return sysman_call_predef_action(PREDEF_FOREGRD, 1, buf);
+}
+
+API int sysman_inform_backgrd(void)
+{
+ char buf[255];
+ snprintf(buf, sizeof(buf), "%d", getpid());
+ return sysman_call_predef_action(PREDEF_BACKGRD, 1, buf);
+}
+
+API int sysman_inform_active(pid_t pid)
+{
+ char buf[255];
+ snprintf(buf, sizeof(buf), "%d", pid);
+ return sysman_call_predef_action(PREDEF_ACTIVE, 1, buf);
+}
+
+API int sysman_inform_inactive(pid_t pid)
+{
+ char buf[255];
+ snprintf(buf, sizeof(buf), "%d", pid);
+ return sysman_call_predef_action(PREDEF_INACTIVE, 1, buf);
+}
+
+API int sysman_request_poweroff(void)
+{
+ return sysman_call_predef_action(PREDEF_PWROFF_POPUP, 0);
+}
+
+API int sysman_request_entersleep(void)
+{
+ return sysman_call_predef_action(PREDEF_ENTERSLEEP, 0);
+}
+
+API int sysman_request_leavesleep(void)
+{
+ return sysman_call_predef_action(PREDEF_LEAVESLEEP, 0);
+}
+
+API int sysman_request_reboot(void)
+{
+ return sysman_call_predef_action(PREDEF_REBOOT, 0);
+}
+
+API int sysman_set_datetime(time_t timet)
+{
+ if (timet < 0L)
+ return -1;
+ char buf[255] = { 0 };
+ snprintf(buf, sizeof(buf), "%ld", timet);
+ return sysman_call_predef_action(PREDEF_SET_DATETIME, 1, buf);
+}
+
+API int sysman_set_timezone(char *tzpath_str)
+{
+ if (tzpath_str == NULL)
+ return -1;
+ char buf[255];
+ snprintf(buf, sizeof(buf), "%s", tzpath_str);
+ return sysman_call_predef_action(PREDEF_SET_TIMEZONE, 1, buf);
+}
+
+static int sysnoti_mount_mmc_cb(keynode_t *key_nodes, void *data)
+{
+ struct mmc_contents *mmc_data;
+ mmc_data = (struct mmc_contents *)data;
+ DBG("mountmmc_cb called");
+ if (vconf_keynode_get_int(key_nodes) ==
+ VCONFKEY_SYSMAN_MMC_MOUNT_COMPLETED) {
+ DBG("mount ok");
+ (mmc_data->mmc_cb)(0, mmc_data->user_data);
+ } else if (vconf_keynode_get_int(key_nodes) ==
+ VCONFKEY_SYSMAN_MMC_MOUNT_ALREADY) {
+ DBG("mount already");
+ (mmc_data->mmc_cb)(-2, mmc_data->user_data);
+ } else {
+ DBG("mount fail");
+ (mmc_data->mmc_cb)(-1, mmc_data->user_data);
+ }
+ vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_MOUNT,
+ (void *)sysnoti_mount_mmc_cb);
+ return 0;
+}
+
+API int sysman_request_mount_mmc(struct mmc_contents *mmc_data)
+{
+ if (mmc_data != NULL && mmc_data->mmc_cb != NULL)
+ vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_MOUNT,
+ (void *)sysnoti_mount_mmc_cb, (void *)mmc_data);
+ return sysman_call_predef_action(PREDEF_MOUNT_MMC, 0);
+}
+
+static int sysnoti_unmount_mmc_cb(keynode_t *key_nodes, void *data)
+{
+ struct mmc_contents *mmc_data;
+ mmc_data = (struct mmc_contents *)data;
+ DBG("unmountmmc_cb called");
+ if (vconf_keynode_get_int(key_nodes) ==
+ VCONFKEY_SYSMAN_MMC_UNMOUNT_COMPLETED) {
+ DBG("unmount ok");
+ (mmc_data->mmc_cb)(0, mmc_data->user_data);
+ } else {
+ DBG("unmount fail");
+ (mmc_data->mmc_cb)(-1, mmc_data->user_data);
+ }
+ vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_UNMOUNT,
+ (void *)sysnoti_unmount_mmc_cb);
+ return 0;
+}
+
+API int sysman_request_unmount_mmc(struct mmc_contents *mmc_data, int option)
+{
+ char buf[255];
+ if (option != 1 && option != 2) {
+ DBG("option is wrong. default option 1 will be used");
+ option = 1;
+ }
+ snprintf(buf, sizeof(buf), "%d", option);
+
+ if (mmc_data != NULL && mmc_data->mmc_cb != NULL)
+ vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_UNMOUNT,
+ (void *)sysnoti_unmount_mmc_cb,
+ (void *)mmc_data);
+ return sysman_call_predef_action(PREDEF_UNMOUNT_MMC, 1, buf);
+}
+
+static int sysnoti_format_mmc_cb(keynode_t *key_nodes, void *data)
+{
+ struct mmc_contents *mmc_data;
+ mmc_data = (struct mmc_contents *)data;
+ DBG("format_cb called");
+ if (vconf_keynode_get_int(key_nodes) ==
+ VCONFKEY_SYSMAN_MMC_FORMAT_COMPLETED) {
+ DBG("format ok");
+ (mmc_data->mmc_cb)(0, mmc_data->user_data);
+
+ } else {
+ DBG("format fail");
+ (mmc_data->mmc_cb)(-1, mmc_data->user_data);
+ }
+ vconf_ignore_key_changed(VCONFKEY_SYSMAN_MMC_FORMAT,
+ (void *)sysnoti_format_mmc_cb);
+ return 0;
+}
+
+API int sysman_request_format_mmc(struct mmc_contents *mmc_data)
+{
+ if (mmc_data != NULL && mmc_data->mmc_cb != NULL)
+ vconf_notify_key_changed(VCONFKEY_SYSMAN_MMC_FORMAT,
+ (void *)sysnoti_format_mmc_cb,
+ (void *)mmc_data);
+ return sysman_call_predef_action(PREDEF_FORMAT_MMC, 0);
+}
+
+API int sysman_request_set_cpu_max_frequency(int val)
+{
+ char buf_pid[8];
+ char buf_freq[256];
+
+ // to do - need to check new frequncy is valid
+ snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
+ snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000);
+
+ return sysman_call_predef_action(PREDEF_SET_MAX_FREQUENCY, 2, buf_pid, buf_freq);
+}
+
+API int sysman_request_set_cpu_min_frequency(int val)
+{
+ char buf_pid[8];
+ char buf_freq[256];
+
+ // to do - need to check new frequncy is valid
+ snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
+ snprintf(buf_freq, sizeof(buf_freq), "%d", val * 1000);
+
+ return sysman_call_predef_action(PREDEF_SET_MIN_FREQUENCY, 2, buf_pid, buf_freq);
+}
+
+API int sysman_release_cpu_max_frequency()
+{
+ char buf_pid[8];
+
+ snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
+
+ return sysman_call_predef_action(PREDEF_RELEASE_MAX_FREQUENCY, 1, buf_pid);
+}
+
+API int sysman_release_cpu_min_frequency()
+{
+ char buf_pid[8];
+
+ snprintf(buf_pid, sizeof(buf_pid), "%d", getpid());
+
+ return sysman_call_predef_action(PREDEF_RELEASE_MIN_FREQUENCY, 1, buf_pid);
+}