#include <sys/socket.h> // for accept
#include <sys/stat.h> // for mkdir
#include <sys/eventfd.h> // for eventfd
-#include <sys/epoll.h> // for epoll apis
#include <sys/timerfd.h> // for timerfd
#include <unistd.h> // for access, sleep
#include <stdbool.h>
#include <attr/xattr.h> // for fsetxattr
#include <sys/smack.h>
-#include <linux/input.h>
-#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
+#include <Ecore.h>
+
#include "daemon.h"
#include "sys_stat.h"
#include "utils.h"
#include "da_protocol.h"
#include "da_inst.h"
#include "da_data.h"
+#include "input_events.h"
#include "debug.h"
#define DA_WORK_DIR "/home/developer/sdk_tools/da/"
#define DA_READELF_PATH "/home/developer/sdk_tools/da/readelf"
#define SCREENSHOT_DIR "/tmp/da"
-#define EPOLL_SIZE 10
#define MAX_APP_LAUNCH_TIME 60
#define MAX_CONNECT_TIMEOUT_TIME 5*60
-#define MAX_DEVICE 10
-#define MAX_FILENAME 128
-#define BUF_SIZE 1024
-#define ARRAY_END (-11)
-
-input_dev g_key_dev[MAX_DEVICE];
-input_dev g_touch_dev[MAX_DEVICE];
-
-const char *input_key_devices[] = {
- /* target: Emulator, kernel: 3.4, all buttons */
- "Maru Virtio Hwkey",
- /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */
- "gpio-keys",
- /* target: M0, kernel: 3.0, buttons: menu, back */
- "melfas-touchkey",
- /* target: M0, kernel: 3.10, buttons: menu, back */
- "MELFAS MCS Touchkey",
- /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */
- "gpio-keys.5",
- NULL //array tail
-};
-
-const char *input_touch_devices[] = {
- /* target: Emulator, kernel: 3.0 */
- "Maru Virtio Touchscreen",
- /* target: M0, kernel: 3.0 */
- "sec_touchscreen",
- /* target: M0, kernel: 3.10 */
- "MELPAS MMS114 Touchscreen",
- NULL //array tail
-};
-
-
-static int check_input(char *inputname, int input_id)
-{
- int ret = -1;
- FILE *cmd_fp = NULL;
- char buffer[BUF_SIZE];
- char command[MAX_FILENAME];
- char **name_arr;
- size_t bytes_count;
-
- sprintf(command, "/sys/class/input/%s/device/name", inputname);
- // run command
- cmd_fp = fopen(command, "r");
- if (cmd_fp == NULL)
- goto exit;
-
- buffer[0] = '\0';
- bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp);
- if (bytes_count <= 1) {
- LOGE("Failed to read input_id\n");
- goto exit;
- } else {
- buffer[bytes_count - 1] = '\0';
- }
-
- if (input_id == INPUT_ID_KEY)
- name_arr = input_key_devices;
- else if (input_id == INPUT_ID_TOUCH)
- name_arr = input_touch_devices;
- else
- goto exit;
-
- while (*name_arr != NULL) {
- if (strcmp(buffer, *name_arr) == 0) {
- ret = 0;
- goto exit;
- }
- name_arr++;
- }
-
-exit:
- if (cmd_fp != NULL)
- pclose(cmd_fp);
- return ret;
-}
-
-// get filename and fd of given input type devices
-static void _get_fds(input_dev *dev, int input_id)
-{
- DIR *dp;
- struct dirent *d;
- int count = 0;
-
- dp = opendir("/sys/class/input");
-
- if (dp == NULL)
- goto exit;
-
- while ((d = readdir(dp)) != NULL) {
- if (!strncmp(d->d_name, "event", 5)) {
- // start with "event"
- // event file
- if (!check_input(d->d_name, input_id)) {
- sprintf(dev[count].fileName,
- "/dev/input/%s", d->d_name);
- dev[count].fd = open(dev[count].fileName,
- O_RDWR | O_NONBLOCK);
- count++;
- }
- }
- }
-
- closedir(dp);
-
-exit:
- dev[count].fd = ARRAY_END; // end of input_dev array
-}
-
-//static
-void _device_write(input_dev *dev, struct input_event *in_ev)
-{
- int i;
- for (i = 0; dev[i].fd != ARRAY_END; i++) {
- if (dev[i].fd >= 0) {
- write(dev[i].fd, in_ev, sizeof(struct input_event));
- LOGI("write(%d, %d, %d)\n",
- dev[i].fd, (int)in_ev, sizeof(struct input_event));
- }
- }
-}
-
uint64_t get_total_alloc_size()
{
int i;
// start and terminate control functions
// =============================================================================
+static Ecore_Fd_Handler *launch_timer_handler;
+
+//stop application launch timer
+static int stop_app_launch_timer()
+{
+ close(manager.app_launch_timerfd);
+ manager.app_launch_timerfd = -1;
+
+ return 0;
+}
+
+static Eina_Bool launch_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ LOGE("Failed to launch application\n");
+ if (stop_app_launch_timer() < 0)
+ LOGE("cannot stop app launch timer\n");
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
//start application launch timer function
static int start_app_launch_timer(int apps_count)
{
int res = 0;
- struct epoll_event ev;
assert(apps_count >= 0 && "negative apps count");
ctime.it_interval.tv_nsec = 0;
if (timerfd_settime(manager.app_launch_timerfd, 0, &ctime, NULL) < 0) {
LOGE("fail to set app launch timer\n");
- close(manager.app_launch_timerfd);
- manager.app_launch_timerfd = -1;
+ stop_app_launch_timer();
res = -1;
} else {
- // add event fd to epoll list
- ev.events = EPOLLIN;
- ev.data.fd = manager.app_launch_timerfd;
- if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
- manager.app_launch_timerfd, &ev) < 0) {
- // fail to add event fd
- LOGE("fail to add app launch timer fd to epoll list\n");
- close(manager.app_launch_timerfd);
- manager.app_launch_timerfd = -1;
+ launch_timer_handler =
+ ecore_main_fd_handler_add(manager.app_launch_timerfd,
+ ECORE_FD_READ,
+ launch_timer_cb,
+ NULL,
+ NULL, NULL);
+ if (!launch_timer_handler) {
+ LOGE("fail to add app launch timer fd to \n");
+ stop_app_launch_timer();
res = -2;
} else {
LOGI("application launch time started\n");
return res;
}
-//stop application launch timer
-static int stop_app_launch_timer()
-{
- if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL,
- manager.app_launch_timerfd, NULL))
- LOGW("fail to EPOLL DEL of app launch timerfd\n");
- close(manager.app_launch_timerfd);
- manager.app_launch_timerfd = -1;
- return 0;
-}
-
static inline void inc_apps_to_run()
{
manager.apps_to_run++;
return res;
}
+// just send stop message to all target process
+static void terminate_all_target()
+{
+ int i;
+ ssize_t sendlen;
+ msg_target_t sendlog;
+
+ sendlog.type = MSG_STOP;
+ sendlog.length = 0;
+
+ for (i = 0; i < MAX_TARGET_COUNT; i++) {
+ if (manager.target[i].socket != -1) {
+ sendlen = send(manager.target[i].socket, &sendlog,
+ sizeof(sendlog.type) +
+ sizeof(sendlog.length), MSG_NOSIGNAL);
+ if (sendlen != -1) {
+ LOGI("TERMINATE send exit msg (socket %d) "
+ "by terminate_all_target()\n",
+ manager.target[i].socket);
+ }
+ }
+ }
+}
+
+// terminate all target and wait for threads
+void terminate_all()
+{
+ int i;
+ terminate_all_target();
+
+ // wait for all other thread exit
+ for (i = 0; i < MAX_TARGET_COUNT; i++) {
+ if (manager.target[i].recv_thread != -1) {
+ LOGI("join recv thread [%d] is started\n", i);
+ pthread_join(manager.target[i].recv_thread, NULL);
+ LOGI("join recv thread %d. done\n", i);
+ }
+ }
+}
+
+// terminate all profiling by critical error
+// TODO: don't send data to host
+static void terminate_error(char *errstr, int send_to_host)
+{
+ LOGE("termination all with err '%s'\n", errstr);
+ struct msg_data_t *msg = NULL;
+ if (send_to_host != 0) {
+ msg = gen_message_error(errstr);
+ if (msg) {
+ write_to_buf(msg);
+ free_msg_data(msg);
+ } else {
+ LOGI("cannot generate error message\n");
+ }
+ }
+ terminate_all();
+}
+
+static Ecore_Fd_Handler *connect_timer_handler;
+
+static Eina_Bool connect_timer_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ terminate_error("no incoming connections", 1);
+ close(manager.connect_timeout_timerfd);
+ manager.connect_timeout_timerfd = -1;
+ LOGE("No connection in %d sec. shutdown.\n",
+ MAX_CONNECT_TIMEOUT_TIME);
+ ecore_main_loop_quit();
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
int launch_timer_start()
{
- static struct epoll_event ev;
int res = 0;
manager.connect_timeout_timerfd =
close(manager.connect_timeout_timerfd);
manager.connect_timeout_timerfd = -1;
} else {
- // add event fd to epoll list
- ev.events = EPOLLIN;
- ev.data.fd = manager.connect_timeout_timerfd;
- if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
- manager.connect_timeout_timerfd, &ev) < 0)
- {
- // fail to add event fd
- LOGE("fail to add app connection timeout timer fd to epoll list\n");
+ connect_timer_handler =
+ ecore_main_fd_handler_add(manager.connect_timeout_timerfd,
+ ECORE_FD_READ,
+ connect_timer_cb,
+ NULL,
+ NULL, NULL);
+ if (!connect_timer_handler) {
+ LOGE("fail to add app connection timeout timer fd\n");
close(manager.connect_timeout_timerfd);
manager.connect_timeout_timerfd = -1;
} else {
return res;
}
-static void epoll_add_input_events();
-static void epoll_del_input_events();
-
int prepare_profiling()
{
struct app_list_t *app = NULL;
}
if (IS_OPT_SET(FL_RECORDING))
- epoll_add_input_events();
+ add_input_events();
while (app_info != NULL) {
if (exec_app(app_info)) {
recording_stop:
if (IS_OPT_SET(FL_RECORDING))
- epoll_del_input_events();
+ del_input_events();
samplingStop();
exit:
void stop_profiling(void)
{
if (IS_OPT_SET(FL_RECORDING))
- epoll_del_input_events();
+ del_input_events();
samplingStop();
}
uint64_t to_disable = (new_features ^ old_features) & old_features;
if (IS_OPT_SET_IN(FL_RECORDING, to_disable)) {
- epoll_del_input_events();
+ del_input_events();
prof_session.conf.use_features0 &= ~FL_RECORDING;
}
if (IS_OPT_SET_IN(FL_RECORDING, to_enable)) {
- epoll_add_input_events();
+ add_input_events();
prof_session.conf.use_features0 |= FL_RECORDING;
}
return 0;
}
-// just send stop message to all target process
-static void terminate_all_target()
-{
- int i;
- ssize_t sendlen;
- msg_target_t sendlog;
-
- sendlog.type = MSG_STOP;
- sendlog.length = 0;
-
- for (i = 0; i < MAX_TARGET_COUNT; i++) {
- if (manager.target[i].socket != -1) {
- sendlen = send(manager.target[i].socket, &sendlog,
- sizeof(sendlog.type) +
- sizeof(sendlog.length), MSG_NOSIGNAL);
- if (sendlen != -1) {
- LOGI("TERMINATE send exit msg (socket %d) "
- "by terminate_all_target()\n",
- manager.target[i].socket);
- }
- }
- }
-}
-
-// terminate all target and wait for threads
-void terminate_all()
-{
- int i;
- terminate_all_target();
-
- // wait for all other thread exit
- for (i = 0; i < MAX_TARGET_COUNT; i++) {
- if (manager.target[i].recv_thread != -1) {
- LOGI("join recv thread [%d] is started\n", i);
- pthread_join(manager.target[i].recv_thread, NULL);
- LOGI("join recv thread %d. done\n", i);
- }
- }
-}
-
-// terminate all profiling by critical error
-// TODO: don't send data to host
-static void terminate_error(char *errstr, int send_to_host)
-{
- LOGE("termination all with err '%s'\n", errstr);
- struct msg_data_t *msg = NULL;
- if (send_to_host != 0) {
- msg = gen_message_error(errstr);
- if (msg) {
- write_to_buf(msg);
- free_msg_data(msg);
- } else {
- LOGI("cannot generate error message\n");
- }
- }
- terminate_all();
-}
-
-#define MAX_EVENTS_NUM 10
-static int deviceEventHandler(input_dev *dev, int input_type)
-{
- int ret = 0;
- ssize_t size = 0;
- int count = 0;
- struct input_event in_ev[MAX_EVENTS_NUM];
- struct msg_data_t *log;
-
- if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) {
- do {
- size = read(dev->fd, &in_ev[count], sizeof(*in_ev));
- if (size > 0)
- count++;
- } while (count < MAX_EVENTS_NUM && size > 0);
-
- if (count) {
- LOGI("read %d %s events\n",
- count,
- input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
- log = gen_message_event(in_ev, count, input_type);
- printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
- write_to_buf(log);
- free_msg_data(log);
- }
- } else {
- LOGW("unknown input_type\n");
- ret = 1; // it is not error
- }
- return ret;
-}
+static Ecore_Fd_Handler *target_handlers[MAX_TARGET_COUNT];
static int target_event_pid_handler(int index, uint64_t msg)
{
return 0;
}
-static int target_event_stop_handler(int epollfd, int index, uint64_t msg)
+static int target_event_stop_handler(int index, uint64_t msg)
{
LOGI("target close, socket(%d), pid(%d) : (remaining %d target)\n",
manager.target[index].socket, manager.target[index].pid,
if (index == 0) // main application
stop_replay();
- if (0 > epoll_ctl(epollfd, EPOLL_CTL_DEL,
- manager.target[index].event_fd, NULL))
- LOGW("fail to EPOLL DEL of event fd(%d)\n", index);
+ ecore_main_fd_handler_del(target_handlers[index]);
setEmptyTargetSlot(index);
// all target client are closed
// return plus value if non critical error occur
// return minus value if critical error occur
// return -11 if all target process closed
-static int target_event_handler(int epollfd, int index, uint64_t msg)
+static int target_event_handler(int index, uint64_t msg)
{
int err = 0;
if (msg & EVENT_PID)
return err;
if (msg & EVENT_STOP || msg & EVENT_ERROR)
- err = target_event_stop_handler(epollfd, index, msg);
+ err = target_event_stop_handler(index, msg);
return err;
}
+static Eina_Bool target_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ uint64_t u;
+ ssize_t recvLen;
+ int index = (int)data;
+
+ recvLen = read(manager.target[index].event_fd, &u, sizeof(uint64_t));
+ if (recvLen != sizeof(uint64_t)) {
+ // maybe closed, but ignoring is more safe then
+ // removing fd from event loop
+ } else {
+ if (-11 == target_event_handler(index, u)) {
+ LOGI("all target process is closed\n");
+ }
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
/**
* return 0 if normal case
* return plus value if non critical error occur
* return minus value if critical error occur
*/
-static int targetServerHandler(int efd)
+static int targetServerHandler(void)
{
msg_target_t log;
- struct epoll_event ev;
int index = getEmptyTargetSlot();
if (index == MAX_TARGET_COUNT) {
LOGE("fail to send data to target index(%d)\n", index);
// make event fd
- manager.target[index].event_fd = eventfd(0, EFD_NONBLOCK);
+ manager.target[index].event_fd = eventfd(EFD_CLOEXEC, EFD_NONBLOCK);
if (manager.target[index].event_fd == -1) {
// fail to make event fd
LOGE("fail to make event fd for socket (%d)\n",
goto TARGET_CONNECT_FAIL;
}
- // add event fd to epoll list
- ev.events = EPOLLIN;
- ev.data.fd = manager.target[index].event_fd;
- if (epoll_ctl(efd, EPOLL_CTL_ADD, manager.target[index].event_fd, &ev) < 0) {
- // fail to add event fd
- LOGE("fail to add event fd to epoll list for socket (%d)\n",
+ target_handlers[index] =
+ ecore_main_fd_handler_add(manager.target[index].event_fd,
+ ECORE_FD_READ,
+ target_event_cb,
+ (void *)index,
+ NULL, NULL);
+ if (!target_handlers[index]) {
+ LOGE("fail to add event fd for socket (%d)\n",
manager.target[index].socket);
goto TARGET_CONNECT_FAIL;
}
// fail to make recv thread
LOGE("fail to make recv thread for socket (%d)\n",
manager.target[index].socket);
- if (0 > epoll_ctl(efd, EPOLL_CTL_DEL,
- manager.target[index].event_fd, NULL))
- LOGW("fail to EPOLL DEL of event fd(%d)\n", index);
+ ecore_main_fd_handler_del(target_handlers[index]);
goto TARGET_CONNECT_FAIL;
}
}
}
-// return 0 if normal case
-// return plus value if non critical error occur
-// return minus value if critical error occur
-static int hostServerHandler(int efd)
-{
- static int hostserverorder = 0;
- int csocket;
- struct epoll_event ev;
-
- if (hostserverorder > 1) // control and data socket connected already
- return 1; // ignore
-
- csocket = accept(manager.host_server_socket, NULL, NULL);
-
- if (csocket >= 0) {
- // accept succeed
- ev.events = EPOLLIN;
- ev.data.fd = csocket;
- if (epoll_ctl(efd, EPOLL_CTL_ADD, csocket, &ev) < 0) {
- // consider as accept fail
- LOGE("Failed to add socket fd to epoll list\n");
- close(csocket);
- return -1;
- }
-
- if (hostserverorder == 0) {
- manager.host.control_socket = csocket;
- unlink_portfile();
- LOGI("host control socket connected = %d\n", csocket);
- } else {
- manager.host.data_socket = csocket;
- LOGI("host data socket connected = %d\n", csocket);
- }
-
- hostserverorder++;
- return 0;
- } else {
- // accept error
- LOGE("Failed to accept from host server socket\n");
- return -1;
- }
-}
+static Ecore_Fd_Handler *host_ctrl_handler;
+static Ecore_Fd_Handler *host_data_handler;
// return plus value if non critical error occur
// return minus value if critical error occur
// return -11 if socket closed
-
static int controlSocketHandler(int efd)
{
ssize_t recv_len;
if (manager.connect_timeout_timerfd >= 0) {
LOGI("release connect timeout timer\n");
- if (0 > epoll_ctl(efd, EPOLL_CTL_DEL,
- manager.connect_timeout_timerfd, NULL))
- LOGW("fail to EPOLL DEL of timeout timer fd\n");
close(manager.connect_timeout_timerfd);
manager.connect_timeout_timerfd = -1;
}
return res;
}
-static void epoll_add_input_events()
+static Eina_Bool host_ctrl_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
- struct epoll_event ev;
- int i;
+ int result = controlSocketHandler(manager.efd);
+ if (result == -11) {
+ // socket close
+ //if the host disconnected.
+ //In all other cases daemon must report an error and continue the loop
+ //close connect_timeoutt and host socket and quit
+ LOGI("Connection closed. Termination. (%d)\n",
+ manager.host.control_socket);
+ ecore_main_loop_quit();
+ } else if (result < 0) {
+ LOGE("Control socket handler.\n");
+ }
- // add device fds to epoll event pool
- ev.events = EPOLLIN;
- for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
- if (g_key_dev[i].fd >= 0) {
- ev.data.fd = g_key_dev[i].fd;
- if (epoll_ctl(manager.efd,
- EPOLL_CTL_ADD, g_key_dev[i].fd, &ev) < 0
- && errno != EEXIST)
- LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno));
- }
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool host_data_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ ssize_t recvLen;
+ char recvBuf[32];
+
+ recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
+ if (recvLen == 0) {
+ // close data socket
+ ecore_main_fd_handler_del(host_data_handler);
+ close(manager.host.data_socket);
+ manager.host.data_socket = -1;
+ // TODO: finish transfer thread
}
- ev.events = EPOLLIN;
- for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
- if (g_touch_dev[i].fd >= 0) {
- ev.data.fd = g_touch_dev[i].fd;
- if (epoll_ctl(manager.efd,
- EPOLL_CTL_ADD,
- g_touch_dev[i].fd, &ev) < 0
- && errno != EEXIST)
- LOGE("touch device file epoll_ctl error: %s\n", strerror(errno));
+ LOGI("host message from data socket %d\n", recvLen);
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+// return 0 if normal case
+// return plus value if non critical error occur
+// return minus value if critical error occur
+static int hostServerHandler(void)
+{
+ static int hostserverorder = 0;
+ int csocket;
+
+ if (hostserverorder > 1) // control and data socket connected already
+ return 1; // ignore
+
+ csocket = accept(manager.host_server_socket, NULL, NULL);
+
+ if (csocket >= 0) {
+ // accept succeed
+
+ if (hostserverorder == 0) {
+ manager.host.control_socket = csocket;
+ unlink_portfile();
+ LOGI("host control socket connected = %d\n", csocket);
+ host_ctrl_handler =
+ ecore_main_fd_handler_add(manager.host.control_socket,
+ ECORE_FD_READ,
+ host_ctrl_cb,
+ NULL,
+ NULL, NULL);
+ if (!host_ctrl_handler) {
+ LOGE("Failed to add host control socket fd\n");
+ close(csocket);
+ return -1;
+ }
+ } else {
+ manager.host.data_socket = csocket;
+ LOGI("host data socket connected = %d\n", csocket);
+
+ host_data_handler =
+ ecore_main_fd_handler_add(manager.host.data_socket,
+ ECORE_FD_READ,
+ host_data_cb,
+ NULL,
+ NULL, NULL);
+ if (!host_data_handler) {
+ LOGE("Failed to add host data socket fd\n");
+ close(csocket);
+ return -1;
+ }
}
+
+ hostserverorder++;
+ return 0;
+ } else {
+ // accept error
+ LOGE("Failed to accept from host server socket\n");
+ return -1;
}
}
-static void epoll_del_input_events()
+static Ecore_Fd_Handler *host_connect_handler;
+static Ecore_Fd_Handler *target_connect_handler;
+
+static Eina_Bool host_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
- int i;
+ // connect request from host
+ int result = hostServerHandler();
+ if (result < 0) {
+ LOGE("Internal DA framework error (hostServerHandler)\n");
+ }
- // remove device fds from epoll event pool
- for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
- if (g_key_dev[i].fd >= 0)
- if (epoll_ctl(manager.efd,
- EPOLL_CTL_DEL, g_key_dev[i].fd, NULL) < 0)
- LOGE("keyboard device file epoll_ctl error: %s\n", strerror(errno));
-
- for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
- if (g_touch_dev[i].fd >= 0)
- if (epoll_ctl(manager.efd,
- EPOLL_CTL_DEL,
- g_touch_dev[i].fd, NULL) < 0)
- LOGE("touch device file epoll_ctl error: %s\n", strerror(errno));
+ return ECORE_CALLBACK_RENEW;
}
-static bool initialize_epoll_events(void)
+static Eina_Bool target_connect_cb(void *data, Ecore_Fd_Handler *fd_handler)
{
- struct epoll_event ev;
-
- if ((manager.efd = epoll_create1(0)) < 0) {
- LOGE("epoll creation error\n");
- return false;
+ if (targetServerHandler() < 0) {
+ // critical error
+ terminate_error("Internal DA framework error, "
+ "Please re-run the profiling "
+ "(targetServerHandler)\n", 1);
}
- // add server sockets to epoll event pool
- ev.events = EPOLLIN;
- ev.data.fd = manager.host_server_socket;
- if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
- manager.host_server_socket, &ev) < 0) {
- LOGE("Host server socket epoll_ctl error\n");
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static bool initialize_events(void)
+{
+ host_connect_handler =
+ ecore_main_fd_handler_add(manager.host_server_socket,
+ ECORE_FD_READ,
+ host_connect_cb,
+ NULL,
+ NULL, NULL);
+ if (!host_connect_handler) {
+ LOGE("Host server socket add error\n");
return false;
}
- ev.events = EPOLLIN;
- ev.data.fd = manager.target_server_socket;
- if (epoll_ctl(manager.efd, EPOLL_CTL_ADD,
- manager.target_server_socket, &ev) < 0) {
- LOGE("Target server socket epoll_ctl error\n");
+
+ target_connect_handler =
+ ecore_main_fd_handler_add(manager.target_server_socket,
+ ECORE_FD_READ,
+ target_connect_cb,
+ NULL,
+ NULL, NULL);
+ if (!target_connect_handler) {
+ LOGE("Target server socket add error\n");
return false;
}
+
return true;
}
int daemonLoop()
{
int return_value = 0;
- struct epoll_event *events = malloc(EPOLL_SIZE * sizeof(*events));
- _get_fds(g_key_dev, INPUT_ID_KEY);
- if (g_key_dev[0].fd == ARRAY_END) {
- LOGE("No key devices found.\n");
- return_value = -1;
- goto END_EVENT;
- }
- _get_fds(g_touch_dev, INPUT_ID_TOUCH);
- if (g_touch_dev[0].fd == ARRAY_END) {
- LOGE("No touch devices found.\n");
- return_value = -1;
- goto END_EVENT;
- }
+ ecore_init();
- if (!events) {
- LOGE("Out of memory when allocate epoll event pool\n");
+ if (init_input_events() == -1) {
return_value = -1;
goto END_EVENT;
}
- if (!initialize_epoll_events()) {
+
+ if (!initialize_events()) {
return_value = -1;
goto END_EFD;
}
init_prof_session(&prof_session);
- // handler loop
- while (1) {
- int i, k;
- ssize_t recvLen;
- // number of occured events
- int numevent = epoll_wait(manager.efd, events, EPOLL_SIZE, -1);
- if (numevent <= 0) {
- LOGE("Failed to epoll_wait : num of event(%d), errno(%d)\n", numevent, errno);
- continue;
- }
-
- for (i = 0; i < numevent; i++) {
- // check for request from event fd
- for (k = 0; k < MAX_TARGET_COUNT; k++) {
- if (manager.target[k].socket != -1 &&
- events[i].data.fd == manager.target[k].event_fd) {
- uint64_t u;
- recvLen = read(manager.target[k].event_fd, &u, sizeof(uint64_t));
- if (recvLen != sizeof(uint64_t)) {
- // maybe closed, but ignoring is more safe then
- // removing fd from epoll list
- } else {
- if (-11 == target_event_handler(manager.efd, k, u))
- LOGI("all target process is closed\n");
- }
- break;
- }
- }
-
- if (k != MAX_TARGET_COUNT)
- continue;
-
- // check for request from device fd
- for (k = 0; g_touch_dev[k].fd != ARRAY_END; k++) {
- if (g_touch_dev[k].fd >= 0 &&
- events[i].data.fd == g_touch_dev[k].fd) {
- if (deviceEventHandler(&g_touch_dev[k],
- INPUT_ID_TOUCH) < 0) {
- LOGE("Internal DA framework error, "
- "Please re-run the profiling (touch dev)\n");
- continue;
- }
- break;
- }
- }
-
- if (g_touch_dev[k].fd != ARRAY_END)
- continue;
-
- for (k = 0; g_key_dev[k].fd != ARRAY_END; k++) {
- if (g_key_dev[k].fd >= 0 &&
- events[i].data.fd == g_key_dev[k].fd) {
- if (deviceEventHandler(&g_key_dev[k], INPUT_ID_KEY) < 0) {
- LOGE("Internal DA framework error, "
- "Please re-run the profiling (key dev)\n");
- continue;
- }
- break;
- }
- }
-
- if (g_key_dev[k].fd != ARRAY_END)
- continue;
-
- // connect request from target
- if (events[i].data.fd == manager.target_server_socket) {
- if (targetServerHandler(manager.efd) < 0) {
- // critical error
- terminate_error("Internal DA framework error, "
- "Please re-run the profiling "
- "(targetServerHandler)\n", 1);
- continue;
- }
- } else if (events[i].data.fd == manager.host_server_socket) {
- // connect request from host
- int result = hostServerHandler(manager.efd);
- if (result < 0) {
- LOGE("Internal DA framework error (hostServerHandler)\n");
- continue;
- }
- } else if (events[i].data.fd == manager.host.control_socket) {
- // control message from host
- int result = controlSocketHandler(manager.efd);
- if (result == -11) {
- // socket close
- //if the host disconnected.
- //In all other cases daemon must report an error and continue the loop
- //close connect_timeoutt and host socket and quit
- LOGI("Connection closed. Termination. (%d)\n",
- manager.host.control_socket);
- return_value = 0;
- goto END_EFD;
- } else if (result < 0) {
- LOGE("Control socket handler.\n");
- }
- } else if (events[i].data.fd == manager.host.data_socket) {
- char recvBuf[32];
- recvLen = recv(manager.host.data_socket, recvBuf, 32, MSG_DONTWAIT);
- if (recvLen == 0) {
- // close data socket
- if (0 > epoll_ctl(manager.efd,
- EPOLL_CTL_DEL,
- manager.host.data_socket,
- NULL))
- LOGW("fail to EPOLL DEL of host data socket\n");
- close(manager.host.data_socket);
- manager.host.data_socket = -1;
- // TODO: finish transfer thread
- }
-
- LOGI("host message from data socket %d\n",
- recvLen);
- } else if (events[i].data.fd == manager.app_launch_timerfd) {
- // check for application launch timerfd
- // send to host timeout error message for launching application
- LOGE("Failed to launch application\n");
- if (stop_app_launch_timer() < 0)
- LOGE("cannot stop app launch timer\n");
- continue;
- } else if (events[i].data.fd == manager.connect_timeout_timerfd) {
- // check for connection timeout timerfd
- // send to host timeout error message for launching application
- terminate_error("no incoming connections", 1);
- if (0 > epoll_ctl(manager.efd, EPOLL_CTL_DEL,
- manager.connect_timeout_timerfd,
- NULL))
- LOGW("fail to EPOLL DEL of timeout timer fd\n");
- close(manager.connect_timeout_timerfd);
- manager.connect_timeout_timerfd = -1;
- LOGE("No connection in %d sec. shutdown.\n",
- MAX_CONNECT_TIMEOUT_TIME);
- goto END_EFD;
- } else {
- // unknown socket
- // never happened
- LOGW("Unknown socket fd (%d)\n",
- events[i].data.fd);
- }
- }
- }
+ ecore_main_loop_begin();
+ ecore_shutdown();
END_EFD:
LOGI("close efd\n");
close(manager.efd);
END_EVENT:
- free(events);
return return_value;
}
--- /dev/null
+/*
+ * DA manager
+ *
+ * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ *
+ * Jaewon Lim <jaewon81.lim@samsung.com>
+ * Woojin Jung <woojin2.jung@samsung.com>
+ * Juyoung Kim <j0.kim@samsung.com>
+ * Cherepanov Vitaliy <v.cherepanov@samsung.com>
+ * Nikita Kalyazin <n.kalyazin@samsung.com>
+ *
+ * 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.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ * - Samsung RnD Institute Russia
+ *
+ */
+
+
+#include <dirent.h>
+#include <Ecore.h>
+
+#include "debug.h"
+#include "da_data.h"
+#include "input_events.h"
+
+#define MAX_DEVICE 10
+#define ARRAY_END (-11)
+#define BUF_SIZE 1024
+#define MAX_FILENAME 128
+
+#define INPUT_ID_TOUCH 0
+#define INPUT_ID_KEY 1
+#define STR_TOUCH "TOUCH"
+#define STR_KEY "KEY"
+#define INPUT_ID_STR_KEY "ID_INPUT_KEY=1"
+#define INPUT_ID_STR_TOUCH "ID_INPUT_TOUCHSCREEN=1"
+#define INPUT_ID_STR_KEYBOARD "ID_INPUT_KEYBOARD=1"
+#define INPUT_ID_STR_TABLET "ID_INPUT_TABLET=1"
+
+typedef struct _input_dev
+{
+ int fd;
+ char fileName[MAX_FILENAME];
+} input_dev;
+
+static input_dev g_key_dev[MAX_DEVICE];
+static input_dev g_touch_dev[MAX_DEVICE];
+
+static Ecore_Fd_Handler *key_handlers[MAX_DEVICE];
+static Ecore_Fd_Handler *touch_handlers[MAX_DEVICE];
+
+enum status_t { s_stopped, s_running };
+static enum status_t status = s_stopped;
+
+static const char *input_key_devices[] = {
+ /* target: Emulator, kernel: 3.4, all buttons */
+ "Maru Virtio Hwkey",
+ /* target: M0, kernel: 3.0, buttons: volume +/-, home, power */
+ "gpio-keys",
+ /* target: M0, kernel: 3.0, buttons: menu, back */
+ "melfas-touchkey",
+ /* target: M0, kernel: 3.10, buttons: menu, back */
+ "MELFAS MCS Touchkey",
+ /* target: M0, kernel: 3.10, buttons: volume +/-, home, power */
+ "gpio-keys.5",
+ NULL
+};
+
+static const char *input_touch_devices[] = {
+ /* target: Emulator, kernel: 3.0 */
+ "Maru Virtio Touchscreen",
+ /* target: M0, kernel: 3.0 */
+ "sec_touchscreen",
+ /* target: M0, kernel: 3.10 */
+ "MELPAS MMS114 Touchscreen",
+ NULL
+};
+
+static int check_input(char *inputname, int input_id)
+{
+ int ret = -1;
+ FILE *cmd_fp = NULL;
+ char buffer[BUF_SIZE];
+ char command[MAX_FILENAME];
+ char **name_arr;
+ size_t bytes_count;
+
+ sprintf(command, "/sys/class/input/%s/device/name", inputname);
+ // run command
+ cmd_fp = fopen(command, "r");
+ if (cmd_fp == NULL)
+ goto exit;
+
+ buffer[0] = '\0';
+ bytes_count = fread(buffer, 1, BUF_SIZE, cmd_fp);
+ if (bytes_count <= 1) {
+ LOGE("Failed to read input_id\n");
+ goto exit;
+ } else {
+ buffer[bytes_count - 1] = '\0';
+ }
+
+ if (input_id == INPUT_ID_KEY)
+ name_arr = input_key_devices;
+ else if (input_id == INPUT_ID_TOUCH)
+ name_arr = input_touch_devices;
+ else
+ goto exit;
+
+ while (*name_arr != NULL) {
+ if (strcmp(buffer, *name_arr) == 0) {
+ ret = 0;
+ goto exit;
+ }
+ name_arr++;
+ }
+
+exit:
+ if (cmd_fp != NULL)
+ pclose(cmd_fp);
+ return ret;
+}
+
+// get filename and fd of given input type devices
+static void _get_fds(input_dev *dev, int input_id)
+{
+ DIR *dp;
+ struct dirent *d;
+ int count = 0;
+
+ dp = opendir("/sys/class/input");
+
+ if (dp == NULL)
+ goto exit;
+
+ while ((d = readdir(dp)) != NULL) {
+ if (!strncmp(d->d_name, "event", 5)) {
+ // start with "event"
+ // event file
+ if (!check_input(d->d_name, input_id)) {
+ sprintf(dev[count].fileName,
+ "/dev/input/%s", d->d_name);
+ dev[count].fd = open(dev[count].fileName,
+ O_RDWR | O_NONBLOCK);
+ count++;
+ }
+ }
+ }
+
+ closedir(dp);
+
+exit:
+ dev[count].fd = ARRAY_END; // end of input_dev array
+}
+
+#define MAX_EVENTS_NUM 10
+static int deviceEventHandler(input_dev *dev, int input_type)
+{
+ int ret = 0;
+ ssize_t size = 0;
+ int count = 0;
+ struct input_event in_ev[MAX_EVENTS_NUM];
+ struct msg_data_t *log;
+
+ if (input_type == INPUT_ID_TOUCH || input_type == INPUT_ID_KEY) {
+ do {
+ size = read(dev->fd, &in_ev[count], sizeof(*in_ev));
+ if (size > 0)
+ count++;
+ } while (count < MAX_EVENTS_NUM && size > 0);
+
+ if (count) {
+ LOGI("read %d %s events\n",
+ count,
+ input_type == INPUT_ID_KEY ? STR_KEY : STR_TOUCH);
+ log = gen_message_event(in_ev, count, input_type);
+ printBuf((char *)log, MSG_DATA_HDR_LEN + log->len);
+ write_to_buf(log);
+ free_msg_data(log);
+ }
+ } else {
+ LOGW("unknown input_type\n");
+ ret = 1; // it is not error
+ }
+ return ret;
+}
+
+static Eina_Bool touch_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ input_dev *touch_dev = (input_dev *)data;
+
+ if (deviceEventHandler(touch_dev, INPUT_ID_TOUCH) < 0) {
+ LOGE("Internal DA framework error, "
+ "Please re-run the profiling (touch dev)\n");
+ /* TODO: ??? */
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Eina_Bool key_event_cb(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ input_dev *key_dev = (input_dev *)data;
+
+ if (deviceEventHandler(key_dev, INPUT_ID_KEY) < 0) {
+ LOGE("Internal DA framework error, "
+ "Please re-run the profiling (key dev)\n");
+ /* TODO: ??? */
+ }
+
+ return ECORE_CALLBACK_RENEW;
+}
+
+void add_input_events(void)
+{
+ int i;
+
+ if (status == s_running)
+ return;
+
+ for (i = 0; g_key_dev[i].fd != ARRAY_END; i++) {
+ if (g_key_dev[i].fd > 0) {
+ key_handlers[i] =
+ ecore_main_fd_handler_add(g_key_dev[i].fd,
+ ECORE_FD_READ,
+ key_event_cb,
+ &g_key_dev[i],
+ NULL, NULL);
+ if (!key_handlers[i])
+ LOGE("keyboard device file handler add error\n");
+ }
+ }
+
+ for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++) {
+ if (g_touch_dev[i].fd > 0) {
+ touch_handlers[i] =
+ ecore_main_fd_handler_add(g_touch_dev[i].fd,
+ ECORE_FD_READ,
+ touch_event_cb,
+ &g_touch_dev[i],
+ NULL, NULL);
+ if (!touch_handlers[i])
+ LOGE("touch device file handler add error\n");
+ }
+ }
+
+ status = s_running;
+}
+
+void del_input_events(void)
+{
+ int i;
+
+ if (status == s_stopped)
+ return;
+
+ for (i = 0; g_key_dev[i].fd != ARRAY_END; i++)
+ if (g_key_dev[i].fd > 0)
+ ecore_main_fd_handler_del(key_handlers[i]);
+
+ for (i = 0; g_touch_dev[i].fd != ARRAY_END; i++)
+ if (g_touch_dev[i].fd > 0)
+ ecore_main_fd_handler_del(touch_handlers[i]);
+
+ status = s_stopped;
+}
+
+static void _device_write(input_dev dev[], struct input_event *in_ev)
+{
+ int i;
+ for (i = 0; dev[i].fd != ARRAY_END; i++) {
+ if (dev[i].fd >= 0) {
+ write(dev[i].fd, in_ev, sizeof(struct input_event));
+ LOGI("write(%d, %d, %d)\n",
+ dev[i].fd, (int)in_ev, sizeof(struct input_event));
+ }
+ }
+}
+
+void write_input_event(int id, struct input_event *ev)
+{
+ switch (id) {
+ case INPUT_ID_TOUCH:
+ _device_write(g_touch_dev, ev);
+ break;
+ case INPUT_ID_KEY:
+ _device_write(g_key_dev, ev);
+ break;
+ default:
+ LOGE("unknown input id (%d)\n", id);
+ }
+}
+
+int init_input_events(void)
+{
+ _get_fds(g_key_dev, INPUT_ID_KEY);
+ if (g_key_dev[0].fd == ARRAY_END) {
+ LOGE("No key devices found.\n");
+ return -1;
+ }
+ _get_fds(g_touch_dev, INPUT_ID_TOUCH);
+ if (g_touch_dev[0].fd == ARRAY_END) {
+ LOGE("No touch devices found.\n");
+ return -1;
+ }
+
+ return 0;
+}