From: SeokYeon Hwang Date: Thu, 16 Oct 2014 01:56:08 +0000 (+0900) Subject: Merge branch 'tizen' into tizen_2.3 X-Git-Tag: Tizen_Studio_1.3_Release_p2.3.1~228^2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=666b3aca5d24b3c1b8605605677e3191e5a3f5be;p=sdk%2Femulator%2Fqemu.git Merge branch 'tizen' into tizen_2.3 Signed-off-by: SeokYeon Hwang Conflicts: hw/virtio/virtio-pci.c hw/virtio/virtio-pci.h package/build.macos-64 package/build.ubuntu-32 package/build.ubuntu-64 package/build.windows-32 package/changelog package/pkginfo.manifest tizen/src/Makefile.tizen tizen/src/Makefile.tizen.i386 tizen/src/debug_ch.c tizen/src/debug_ch.h tizen/src/display/maru_sdl.c tizen/src/display/maru_sdl_processing.c tizen/src/display/maru_shm.c tizen/src/display/maru_shm.h tizen/src/ecs/Makefile.tizen tizen/src/ecs/ecs.c tizen/src/ecs/ecs_eventcast.h tizen/src/ecs/ecs_msg.c tizen/src/ecs/ecs_tethering.c tizen/src/emul_state.c tizen/src/emul_state.h tizen/src/emulator.c tizen/src/eventcast/common.h tizen/src/eventcast/msg/eventcast.proto tizen/src/hw/maru_pm.c tizen/src/hw/pci/maru_brillcodec.c tizen/src/hw/virtio/maru_virtio_jack.h tizen/src/hw/virtio/maru_virtio_nfc.c tizen/src/hw/virtio/maru_virtio_sensor.h tizen/src/sdb.c tizen/src/sdb.h tizen/src/skin/client/skins/mobile-320x480-3btn/default.dbi tizen/src/skin/client/skins/mobile-480x800-3btn/default.dbi tizen/src/skin/client/skins/mobile-720x1280-3btn/default.dbi tizen/src/skin/client/skins/mobile-general-3btn/default.dbi tizen/src/skin/client/skins/wearable-general-1btn/default.dbi tizen/src/skin/client/src/org/tizen/emulator/skin/EmulatorSkin.java tizen/src/skin/maruskin_operation.c tizen/src/skin/maruskin_server.c tizen/src/tethering/Makefile.tizen tizen/src/tethering/app_tethering.h tizen/src/tethering/common.h tizen/src/tethering/genmsg/tethering.pb-c.c tizen/src/tethering/genmsg/tethering.pb-c.h tizen/src/tethering/touch.h tizen/src/util/osutil-linux.c tizen/src/util/osutil-win32.c tizen/src/util/osutil.h --- 666b3aca5d24b3c1b8605605677e3191e5a3f5be diff --cc package/build.windows-32 index 5725448ee6,5b6ab54afc..3e560fa730 --- a/package/build.windows-32 +++ b/package/build.windows-32 @@@ -32,7 -32,7 +32,7 @@@ prepare( echo "and then set installed Python/bin path into PATH system variable on your PC!" exit 1 fi -- ++ PURIFIED_ROOTDIR=`TEMP=\`echo "${ROOTDIR}" | cut -c-2 | sed "s/[:/]//g" | awk {'print tolower ($_)'}\`; echo \`echo "${ROOTDIR}" | sed "s/^../\/${TEMP}/"\`` PATH=$PATH:$PURIFIED_ROOTDIR/bin:$PURIFIED_ROOTDIR/apache-ant_1.9.2/bin:$PURIFIED_ROOTDIR/SDL_1.2.15/bin:$PURIFIED_ROOTDIR/pixman_0.30.0/bin:$PURIFIED_ROOTDIR/gtk-bundle_2.24.10/bin:$PURIFIED_ROOTDIR/libcurl-4_1.0.1/bin export PATH diff --cc tizen/src/ecs/Makefile.objs index 0000000000,658659cc62..5f58026bd8 mode 000000,100644..100644 --- a/tizen/src/ecs/Makefile.objs +++ b/tizen/src/ecs/Makefile.objs @@@ -1,0 -1,4 +1,6 @@@ + obj-y += genmsg/ecs.pb-c.o genmsg/ecs_ids.pb-c.o ../../distrib/protobuf/protobuf-c.o -obj-y += ecs_msg.o ecs.o ecs_sensor.o ++obj-y += ecs.o ecs_msg.o ecs_msg_injector.o ecs_msg_device.o + obj-y += ecs_mon.o ecs-json-streamer.o + obj-y += ecs_eventcast.o ++obj-y += ecs_sensor.o ++obj-y += ecs_nfc.o diff --cc tizen/src/ecs/ecs.h index 67c1f10f64,5d7da12459..08a3d1c659 --- a/tizen/src/ecs/ecs.h +++ b/tizen/src/ecs/ecs.h @@@ -40,7 -40,7 +40,6 @@@ #include "ecs-json-streamer.h" #include "genmsg/ecs.pb-c.h" #include "genmsg/ecs_ids.pb-c.h" - #include "../osutil.h" -#include "../util/osutil.h" #define ECS_VERSION "1.0" diff --cc tizen/src/ecs/ecs_eventcast.c index 0000000000,385a5f5222..25aec62130 mode 000000,100644..100644 --- a/tizen/src/ecs/ecs_eventcast.c +++ b/tizen/src/ecs/ecs_eventcast.c @@@ -1,0 -1,348 +1,348 @@@ + /* + * Emulator Control Server - Device Tethering Handler + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * KiTae Kim + * JiHye Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + #include "ui/console.h" + + #include "ecs.h" + #include "ecs_eventcast.h" + #include "eventcast/common.h" + #include "eventcast/sensor.h" + #include "eventcast/touch.h" + #include "hw/virtio/maru_virtio_touchscreen.h" + #include "hw/virtio/maru_virtio_hwkey.h" + + #include "util/new_debug_ch.h" + + DECLARE_DEBUG_CHANNEL(ecs_eventcast); + + #define MSG_BUF_SIZE 255 + #define MSG_LEN_SIZE 4 + + #define PRESSED 1 + #define RELEASED 2 + + static bool send_eventcast_ntf(const char *data); + static void send_eventcast_status_ntf(type_group group, type_action action); + + static int eventcast_port = 0; + + void send_eventcast_sensor_status_ecp(void) + { + LOG_INFO(">> send eventcast_event_status to ecp\n"); + send_eventcast_status_ntf(ECS_EVENTCAST_MSG_GROUP_ECP, + ECS_EVENTCAST_MSG_ACTION_SENSOR_STATUS); + } + + void send_eventcast_touch_status_ecp(void) + { + send_eventcast_status_ntf(ECS_EVENTCAST_MSG_GROUP_ECP, + ECS_EVENTCAST_MSG_ACTION_TOUCH_STATUS); + } + + void send_eventcast_connection_status_ecp(void) + { + LOG_INFO(">> send eventcast_connection_status to ecp\n"); + send_eventcast_status_ntf(ECS_EVENTCAST_MSG_GROUP_ECP, + ECS_EVENTCAST_MSG_ACTION_CONNECTION_STATUS); + } + + #if 0 + static void send_eventcast_port_ecp(void) + { + type_length length; + type_group group = ECS_EVENTCAST_MSG_GROUP_ECP; + type_action action = ECS_EVENTCAST_MSG_ACTION_CONNECT; + uint8_t *msg = NULL; + gchar data[12]; + + msg = g_malloc(MSG_BUF_SIZE); + if (!msg) { + return; + } + + LOG_TRACE(">> send port_num: %d\n", eventcast_port); + g_snprintf(data, sizeof(data) - 1, "%d", eventcast_port); + length = strlen(data); + + memcpy(msg, ECS_EVENTCAST_MSG_CATEGORY, 10); + memcpy(msg + 10, &length, sizeof(unsigned short)); + memcpy(msg + 12, &group, sizeof(unsigned char)); + memcpy(msg + 13, &action, sizeof(unsigned char)); + memcpy(msg + 14, data, length); + + LOG_TRACE(">> send eventcast_ntf to ecp. action=%d, group=%d, data=%s\n", + action, group, data); + + send_eventcast_ntf((const char *)msg); + + if (msg) { + g_free(msg); + } + } + #endif + + static void send_eventcast_connection_info(void) + { + type_length length; + type_group group = ECS_EVENTCAST_MSG_GROUP_ECP; + type_action action = ECS_EVENTCAST_MSG_ACTION_CONNECT; + uint8_t *msg = NULL; + gchar data[64]; + + msg = g_malloc(MSG_BUF_SIZE); + if (!msg) { + LOG_SEVERE("failed to allocate memory\n"); + return; + } + + LOG_INFO(">> send port_num: %d\n", eventcast_port); + { + const char *ip = get_eventcast_connected_ipaddr(); + int port = get_eventcast_connected_port(); + + if (!ip) { + LOG_SEVERE("invalid connected ip\n"); + return; + } + + if (!port) { + LOG_SEVERE("invalid connected port\n"); + return; + } + g_snprintf(data, sizeof(data) - 1, "%s:%d", ip, port); + length = strlen(data); + data[length] = '\0'; + } + + memcpy(msg, ECS_EVENTCAST_MSG_CATEGORY, 10); + memcpy(msg + 10, &length, sizeof(unsigned short)); + memcpy(msg + 12, &group, sizeof(unsigned char)); + memcpy(msg + 13, &action, sizeof(unsigned char)); + memcpy(msg + 14, data, length); + + LOG_INFO(">> send connection msg to ecp. " + "action=%d, group=%d, data=%s length=%d\n", + action, group, data, length); + + send_eventcast_ntf((const char *)msg); + + g_free(msg); + } + + static void send_eventcast_status_ntf(type_group group, type_action action) + { + type_length length = 1; + int status = 0; + uint8_t *msg = NULL; + gchar data[2]; + + switch (action) { + case ECS_EVENTCAST_MSG_ACTION_CONNECTION_STATUS: + status = get_eventcast_connection_status(); + if (status == CONNECTED) { + send_eventcast_connection_info(); + } + break; + case ECS_EVENTCAST_MSG_ACTION_SENSOR_STATUS: + status = get_eventcast_sensor_status(); + break; + case ECS_EVENTCAST_MSG_ACTION_TOUCH_STATUS: + status = get_eventcast_touch_status(); + break; + default: + break; + } + + msg = g_malloc(MSG_BUF_SIZE); + if (!msg) { + return; + } + + g_snprintf(data, sizeof(data), "%d", status); + + memcpy(msg, ECS_EVENTCAST_MSG_CATEGORY, 10); + memcpy(msg + 10, &length, sizeof(unsigned short)); + memcpy(msg + 12, &group, sizeof(unsigned char)); + memcpy(msg + 13, &action, sizeof(unsigned char)); + memcpy(msg + 14, data, 1); + + LOG_TRACE(">> send eventcast_ntf to ecp. action=%d, group=%d, data=%s\n", + action, group, data); + + send_eventcast_ntf((const char *)msg); + + if (msg) { + g_free(msg); + } + } + + static bool send_eventcast_ntf(const char *data) + { + type_length length = 0; + type_group group = 0; + type_action action = 0; + + const int catsize = 10; + char cat[catsize + 1]; + memset(cat, 0, catsize + 1); + + read_val_str(data, cat, catsize); + read_val_short(data + catsize, &length); + read_val_char(data + catsize + 2, &group); + read_val_char(data + catsize + 2 + 1, &action); + + const char* ijdata = (data + catsize + 2 + 1 + 1); + + LOG_TRACE(">> header cat = %s, length = %d, action=%d, group=%d\n", cat, length,action, group); + + ECS__Master master = ECS__MASTER__INIT; + ECS__EventCastNtf ntf = ECS__EVENT_CAST_NTF__INIT; + + ntf.category = (char*) g_malloc(catsize + 1); + strncpy(ntf.category, cat, 10); + + ntf.length = length; + ntf.group = group; + ntf.action = action; + + if (length > 0) { + ntf.has_data = 1; + + ntf.data.data = g_malloc(length); + ntf.data.len = length; + memcpy(ntf.data.data, ijdata, length); + + LOG_TRACE("data = %s, length = %hu\n", ijdata, length); + } + + master.type = ECS__MASTER__TYPE__EVENTCAST_NTF; + master.eventcast_ntf = &ntf; + - send_to_ecp(&master); ++ pb_to_all_clients(&master); + + if (ntf.data.data && ntf.data.len > 0) { + g_free(ntf.data.data); + } + + if (ntf.category) { + g_free(ntf.category); + } + + return true; + } + + void send_eventcast_sensor_data(const char *data, int len) + { + set_injector_data(data); + } + + void send_eventcast_touch_data(int x, int y, int index, int status) + { + virtio_touchscreen_event(x, y, index, status); + } + + void send_eventcast_hwkey_data(int keycode) + { + maru_hwkey_event(PRESSED, keycode); + maru_hwkey_event(RELEASED, keycode); + } + + // handle eventcast_req message + bool msgproc_eventcast_req(ECS_Client* ccli, ECS__EventCastReq* msg) + { + gchar cmd[10] = {0}; + gchar **server_addr = NULL; + + LOG_TRACE("enter %s\n", __func__); + + g_strlcpy(cmd, msg->category, sizeof(cmd)); + type_length length = (type_length) msg->length; + type_group group = (type_group) (msg->group & 0xff); + type_action action = (type_action) (msg->action & 0xff); + + LOG_TRACE("<< header = cmd = %s, length = %d, action=%d, group=%d\n", + cmd, length, action, group); + + switch(action) { + case ECS_EVENTCAST_MSG_ACTION_CONNECT: + LOG_INFO("MSG_ACTION_CONNECT\n"); + + if (msg->data.data && msg->data.len > 0) { + const gchar *data = (const gchar *)msg->data.data; + gchar *ip_address = NULL; + guint64 port = 0; + + server_addr = g_strsplit(data, ":", 0); + if (server_addr && server_addr[0]) { + int len = strlen(server_addr[0]); + + if (len) { + ip_address = g_malloc(len + 1); + g_strlcpy(ip_address, server_addr[0], len + 1); + } + LOG_INFO("IP address: %s, length: %d\n", ip_address, len); + } + + if (server_addr && server_addr[1]) { + port = g_ascii_strtoull(server_addr[1], NULL, 10); + LOG_INFO("port number: %d\n", port); + } else { + LOG_SEVERE("failed to parse port number\n"); + } + LOG_TRACE("len = %zd, data\" %s\"", strlen(data), data); + + connect_eventcast_app(ip_address, port); + eventcast_port = port; + + LOG_TRACE(">> port_num: %d, %d\n", port, eventcast_port); + g_free(ip_address); + g_strfreev(server_addr); + } else { + LOG_INFO("ip address and port value are null\n"); + } + break; + case ECS_EVENTCAST_MSG_ACTION_DISCONNECT: + LOG_INFO(">> MSG_ACTION_DISCONNECT\n"); + disconnect_eventcast_app(); + eventcast_port = 0; + break; + case ECS_EVENTCAST_MSG_ACTION_CONNECTION_STATUS: + case ECS_EVENTCAST_MSG_ACTION_SENSOR_STATUS: + case ECS_EVENTCAST_MSG_ACTION_TOUCH_STATUS: + LOG_TRACE(">> get_status_action\n"); + send_eventcast_status_ntf(group, action); + break; + default: + break; + } + + LOG_TRACE("leave %s\n", __func__); + + return true; + } diff --cc tizen/src/ecs/ecs_msg.c index 55aef098ce,b2773806bc..3ad09b30da --- a/tizen/src/ecs/ecs_msg.c +++ b/tizen/src/ecs/ecs_msg.c @@@ -42,26 -45,42 +45,21 @@@ #include "qapi/qmp/json-parser.h" #include "ui/qemu-spice.h" #include "qemu/queue.h" -#include "qemu/option.h" #include "sysemu/char.h" #include "qemu/main-loop.h" - - #ifdef CONFIG_LINUX - #include - #endif - #include "qemu-common.h" - #include "sdb.h" + #include "util/sdb.h" #include "ecs-json-streamer.h" #include "qmp-commands.h" - #include "hw/maru_virtio_vmodem.h" - #include "hw/maru_virtio_evdi.h" -#include "ecs.h" -#ifndef CONFIG_USE_SHM -#include "display/maru_finger.h" -#endif - -#include "hw/virtio/maru_virtio_evdi.h" -#include "hw/virtio/maru_virtio_sensor.h" -#include "hw/virtio/maru_virtio_jack.h" -#include "hw/virtio/maru_virtio_power.h" -#include "hw/virtio/maru_virtio_nfc.h" + #include "hw/virtio/maru_virtio_vmodem.h" -#include "skin/maruskin_operation.h" -#include "skin/maruskin_server.h" -#include "util/maru_device_hotplug.h" -#include "emul_state.h" ++#include "hw/virtio/maru_virtio_evdi.h" + +#include "ecs.h" #include "debug_ch.h" -MULTI_DEBUG_CHANNEL(qemu, ecs-msg); -// utility functions -static int guest_connection = 0; -extern QemuMutex mutex_guest_connection; -extern QemuMutex mutex_location_data; -static char location_data[MAX_INJECTOR_REQ_DATA]; -/*static function define*/ -static bool handle_sdcard(char* dataBuf, size_t dataLen); -static char* get_emulator_sdcard_path(void); -static char *get_old_tizen_sdk_data_path(void); +MULTI_DEBUG_CHANNEL(qemu, ecs); static void* build_master(ECS__Master* master, int* payloadsize) { @@@ -253,4 -763,459 +251,3 @@@ bool ntf_to_injector(const char* data, return true; } - -static bool injector_req_handle(const char* cat, type_action action) -{ - /*SD CARD msg process*/ - if (!strcmp(cat, MSG_TYPE_SDCARD)) { - return false; - - } else if (!strcmp(cat, "suspend")) { - ecs_suspend_lock_state(ecs_get_suspend_state()); - return true; - } else if (!strcmp(cat, MSG_TYPE_GUEST)) { - INFO("emuld connection is %d\n", action); - qemu_mutex_lock(&mutex_guest_connection); - guest_connection = action; - qemu_mutex_unlock(&mutex_guest_connection); - return false; - } - - return false; -} - -bool send_injector_ntf(const char* data, const int len) -{ - type_length length = 0; - type_group group = 0; - type_action action = 0; - - const int catsize = 10; - char cat[catsize + 1]; - memset(cat, 0, catsize + 1); - - read_val_str(data, cat, catsize); - read_val_short(data + catsize, &length); - read_val_char(data + catsize + 2, &group); - read_val_char(data + catsize + 2 + 1, &action); - - if (injector_req_handle(cat, action)) { - return true; - } - - const char* ijdata = (data + catsize + 2 + 1 + 1); - - TRACE("<< header cat = %s, length = %d, action=%d, group=%d", cat, length,action, group); - - ECS__Master master = ECS__MASTER__INIT; - ECS__InjectorNtf ntf = ECS__INJECTOR_NTF__INIT; - - ntf.category = (char*) g_malloc(catsize + 1); - strncpy(ntf.category, cat, 10); - - ntf.length = length; - ntf.group = group; - ntf.action = action; - - if (length > 0) - { - ntf.has_data = 1; - - ntf.data.data = g_malloc(length); - ntf.data.len = length; - memcpy(ntf.data.data, ijdata, length); - } - - master.type = ECS__MASTER__TYPE__INJECTOR_NTF; - master.injector_ntf = &ntf; - - send_to_ecp(&master); - - if (ntf.data.len > 0) - { - g_free(ntf.data.data); - } - - g_free(ntf.category); - - return true; -} - -bool send_device_ntf(const char* data, const int len) -{ - type_length length = 0; - type_group group = 0; - type_action action = 0; - - const int catsize = 10; - char cat[catsize + 1]; - memset(cat, 0, catsize + 1); - - read_val_str(data, cat, catsize); - read_val_short(data + catsize, &length); - read_val_char(data + catsize + 2, &group); - read_val_char(data + catsize + 2 + 1, &action); - - const char* ijdata = (data + catsize + 2 + 1 + 1); - - TRACE("<< header cat = %s, length = %d, action=%d, group=%d", cat, length,action, group); - - ECS__Master master = ECS__MASTER__INIT; - ECS__DeviceNtf ntf = ECS__DEVICE_NTF__INIT; - - ntf.category = (char*) g_malloc(catsize + 1); - strncpy(ntf.category, cat, 10); - - - ntf.length = length; - ntf.group = group; - ntf.action = action; - - if (length > 0) - { - ntf.has_data = 1; - - ntf.data.data = g_malloc(length); - ntf.data.len = length; - memcpy(ntf.data.data, ijdata, length); - - TRACE("data = %s, length = %hu", ijdata, length); - } - - master.type = ECS__MASTER__TYPE__DEVICE_NTF; - master.device_ntf = &ntf; - - send_to_ecp(&master); - - if (ntf.data.data && ntf.data.len > 0) - { - g_free(ntf.data.data); - } - - if (ntf.category) - g_free(ntf.category); - - return true; -} - -bool send_nfc_ntf(struct nfc_msg_info* msg) -{ - const int catsize = 10; - char cat[catsize + 1]; - ECS_Client *clii; - memset(cat, 0, catsize + 1); - - print_binary((char*)msg->buf, msg->use); - TRACE("id: %02x, type: %02x, use: %d", msg->client_id, msg->client_type, msg->use); - clii = find_client(msg->client_id, msg->client_type); - if (clii) { - if(clii->client_type == TYPE_SIMUL_NFC) { - strncpy(cat, MSG_TYPE_NFC, 3); - } else if (clii->client_type == TYPE_ECP) { - strncpy(cat, MSG_TYPE_SIMUL_NFC, 9); - }else { - ERR("cannot find type! : %d", clii->client_type); - } - TRACE("header category = %s", cat); - } - else { - ERR("cannot find client!\n"); - } - - ECS__Master master = ECS__MASTER__INIT; - ECS__NfcNtf ntf = ECS__NFC_NTF__INIT; - - ntf.category = (char*) g_malloc(catsize + 1); - strncpy(ntf.category, cat, 10); - - ntf.has_data = 1; - - ntf.data.data = g_malloc(NFC_MAX_BUF_SIZE); - ntf.data.len = NFC_MAX_BUF_SIZE; - memcpy(ntf.data.data, msg->buf, NFC_MAX_BUF_SIZE); - - printf("send to nfc injector: "); - master.type = ECS__MASTER__TYPE__NFC_NTF; - master.nfc_ntf = &ntf; - - send_single_msg(&master, clii); - - if (ntf.data.data && ntf.data.len > 0) - { - g_free(ntf.data.data); - } - - if (ntf.category) - g_free(ntf.category); - - return true; -} - -static bool handle_sdcard(char* dataBuf, size_t dataLen) -{ - int err_no = 0; - char ret = 0; - INFO("handle_sdcard() data: %s\n", dataBuf); - if (dataBuf != NULL) { - ret = dataBuf[0]; - - if (ret == '0' ) { - /* umount sdcard */ - //mloop_evcmd_usbdisk(NULL); - char sdcard_img_path[256]; - char* sdcard_path = NULL; - - sdcard_path = get_emulator_sdcard_path(); - if (sdcard_path) { - g_strlcpy(sdcard_img_path, sdcard_path, - sizeof(sdcard_img_path)); - - /* emulator_sdcard_img_path + sdcard img name */ - char* sdcard_img_name = dataBuf+2; - if (dataLen > 3 && sdcard_img_name != NULL) { - char* pLinechange = strchr(sdcard_img_name, '\n'); - if(pLinechange != NULL){ - sdcard_img_name = g_strndup(sdcard_img_name, pLinechange - sdcard_img_name); - } - - g_strlcat(sdcard_img_path, sdcard_img_name, sizeof(sdcard_img_path)); - INFO("sdcard path: [%s]\n", sdcard_img_path); - - /*if using strndup than free string*/ - if (pLinechange != NULL && sdcard_img_name!= NULL) { - free(sdcard_img_name); - } - } - g_free(sdcard_path); - - } - err_no = remove_sdcard_lock_os(sdcard_img_path); - INFO("umount err_no: %d\n", err_no); - if (errno == 0 && is_sdcard_attached()) { - do_hotplug(DETACH_SDCARD, NULL, 0); - } else { - ERR("failed to umount: %s\n", sdcard_img_path); - send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, err_no, NULL); - return err_no; - } - } - else if (ret == '1') { - /* mount sdcard */ - char sdcard_img_path[256]; - char* sdcard_path = NULL; - - sdcard_path = get_emulator_sdcard_path(); - if (sdcard_path) { - g_strlcpy(sdcard_img_path, sdcard_path, - sizeof(sdcard_img_path)); - - /* emulator_sdcard_img_path + sdcard img name */ - char* sdcard_img_name = dataBuf+2; - if (dataLen > 3 && sdcard_img_name != NULL) { - char* pLinechange = strchr(sdcard_img_name, '\n'); - if(pLinechange != NULL){ - sdcard_img_name = g_strndup(sdcard_img_name, pLinechange - sdcard_img_name); - } - - g_strlcat(sdcard_img_path, sdcard_img_name, sizeof(sdcard_img_path)); - TRACE("sdcard path: [%s]\n", sdcard_img_path); - - //mloop_evcmd_usbdisk(sdcard_img_path); - if ( !is_sdcard_attached() && make_sdcard_lock_os(sdcard_img_path)) { - do_hotplug(ATTACH_SDCARD, sdcard_img_path, strlen(sdcard_img_path) + 1); - send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 0, NULL); - } else { - send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 5, NULL); - return ERR_LCK; - } - /*if using strndup than free string*/ - if (pLinechange != NULL && sdcard_img_name!= NULL) { - free(sdcard_img_name); - } - - } - - g_free(sdcard_path); - } else { - ERR("failed to get sdcard path!!\n"); - } - } else if (ret == '2') { - TRACE("sdcard status 2 bypass\n" ); - } else { - ERR("!!! unknown command : %c\n", ret); - } - - } else { - ERR("!!! unknown data : %c\n", ret); - } - return ERR_SUCCESS; -} - -static char* get_emulator_sdcard_path(void) -{ - char *emulator_sdcard_path = NULL; - char *tizen_sdk_data = NULL; - -#ifndef CONFIG_WIN32 - char emulator_sdcard[] = "/emulator/sdcard/"; -#else - char emulator_sdcard[] = "\\emulator\\sdcard\\"; -#endif - - TRACE("emulator_sdcard: %s, %zu\n", emulator_sdcard, sizeof(emulator_sdcard)); - - tizen_sdk_data = get_tizen_sdk_data_path(); - if (!tizen_sdk_data) { - ERR("failed to get tizen-sdk-data path.\n"); - return NULL; - } - - emulator_sdcard_path = - g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_sdcard) + 1); - if (!emulator_sdcard_path) { - ERR("failed to allocate memory.\n"); - return NULL; - } - - g_snprintf(emulator_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_sdcard), - "%s%s", tizen_sdk_data, emulator_sdcard); - - g_free(tizen_sdk_data); - - TRACE("sdcard path: %s\n", emulator_sdcard_path); - return emulator_sdcard_path; -} - -/* - * get tizen-sdk-data path from sdk.info. - */ -char *get_tizen_sdk_data_path(void) -{ - char const *emul_bin_path = NULL; - char *sdk_info_file_path = NULL; - char *tizen_sdk_data_path = NULL; -#ifndef CONFIG_WIN32 - const char *sdk_info = "../../../sdk.info"; -#else - const char *sdk_info = "..\\..\\..\\sdk.info"; -#endif - const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH"; - - FILE *sdk_info_fp = NULL; - int sdk_info_path_len = 0; - - TRACE("%s\n", __func__); - - emul_bin_path = get_bin_path(); - if (!emul_bin_path) { - ERR("failed to get emulator path.\n"); - return NULL; - } - - sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1; - sdk_info_file_path = g_malloc(sdk_info_path_len); - if (!sdk_info_file_path) { - ERR("failed to allocate sdk-data buffer.\n"); - return NULL; - } - - g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s", - emul_bin_path, sdk_info); - INFO("sdk.info path: %s\n", sdk_info_file_path); - - sdk_info_fp = fopen(sdk_info_file_path, "r"); - g_free(sdk_info_file_path); - - if (sdk_info_fp) { - TRACE("Succeeded to open [sdk.info].\n"); - - char tmp[256] = { '\0', }; - char *tmpline = NULL; - while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) { - if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) { - tmpline += strlen(sdk_data_var) + 1; // 1 for '=' - break; - } - } - - if (tmpline) { - if (tmpline[strlen(tmpline) - 1] == '\n') { - tmpline[strlen(tmpline) - 1] = '\0'; - } - if (tmpline[strlen(tmpline) - 1] == '\r') { - tmpline[strlen(tmpline) - 1] = '\0'; - } - - tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1); - g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1); - - INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); - - fclose(sdk_info_fp); - return tizen_sdk_data_path; - } - - fclose(sdk_info_fp); - } - - // legacy mode - ERR("Failed to open [sdk.info].\n"); - - return get_old_tizen_sdk_data_path(); -} - -static char *get_old_tizen_sdk_data_path(void) -{ - char *tizen_sdk_data_path = NULL; - - INFO("try to search tizen-sdk-data path in another way.\n"); - -#ifndef CONFIG_WIN32 - char tizen_sdk_data[] = "/tizen-sdk-data"; - int tizen_sdk_data_len = 0; - char *home_dir; - - home_dir = (char *)g_getenv("HOME"); - if (!home_dir) { - home_dir = (char *)g_get_home_dir(); - } - - tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1; - tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); - if (!tizen_sdk_data_path) { - ERR("failed to allocate memory.\n"); - return NULL; - } - g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len); - g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); - -#else - char tizen_sdk_data[] = "\\tizen-sdk-data\\"; - gint tizen_sdk_data_len = 0; - HKEY hKey; - char strLocalAppDataPath[1024] = { 0 }; - DWORD dwBufLen = 1024; - - RegOpenKeyEx(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", - 0, KEY_QUERY_VALUE, &hKey); - - RegQueryValueEx(hKey, "Local AppData", NULL, - NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen); - RegCloseKey(hKey); - - tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1; - tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); - if (!tizen_sdk_data_path) { - ERR("failed to allocate memory.\n"); - return NULL; - } - - g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len); - g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); -#endif - - INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); - return tizen_sdk_data_path; -} -- diff --cc tizen/src/ecs/ecs_msg_device.c index 947cda6d0f,0000000000..55d6f6ac30 mode 100644,000000..100644 --- a/tizen/src/ecs/ecs_msg_device.c +++ b/tizen/src/ecs/ecs_msg_device.c @@@ -1,537 -1,0 +1,466 @@@ +/* Emulator Control Server + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung choi + * MunKyu Im + * Daiyoung Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" +#include "qemu/option.h" +#include "qemu/config-file.h" + +#include "qmp-commands.h" +#include "net/slirp.h" +#include "fsdev/qemu-fsdev.h" +#include "monitor/qdev.h" - #include "mloop_event.h" - #include "hw/maru_virtio_sensor.h" - #include "hw/maru_virtio_nfc.h" ++#include "hw/virtio/maru_virtio_sensor.h" ++#include "hw/virtio/maru_virtio_nfc.h" +#include "skin/maruskin_operation.h" +#include "skin/maruskin_server.h" - #ifndef CONFIG_USE_SHM - #include "maru_finger.h" - #endif + - #include "emulator.h" ++#include "util/maru_device_hotplug.h" +#include "emul_state.h" +#include "ecs.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, ecs); + +static void msgproc_device_ans(ECS_Client* ccli, const char* category, bool succeed, char* data) +{ + if (ccli == NULL) { + return; + } + int catlen = 0; + ECS__Master master = ECS__MASTER__INIT; + ECS__DeviceAns ans = ECS__DEVICE_ANS__INIT; + + TRACE("device ans - category : %s, succed : %d\n", category, succeed); + + catlen = strlen(category); + ans.category = (char*) g_malloc0(catlen + 1); + memcpy(ans.category, category, catlen); + + ans.errcode = !succeed; + + if (data != NULL) { + ans.length = strlen(data); + + if (ans.length > 0) { + ans.has_data = 1; + ans.data.data = g_malloc(ans.length); + ans.data.len = ans.length; + memcpy(ans.data.data, data, ans.length); + TRACE("data = %s, length = %hu\n", data, ans.length); + } + } + + master.type = ECS__MASTER__TYPE__DEVICE_ANS; + master.device_ans = &ans; + + pb_to_all_clients(&master); + + if (ans.category) + g_free(ans.category); +} + +extern char tizen_target_img_path[]; +void send_target_image_information(ECS_Client* ccli) { + ECS__Master master = ECS__MASTER__INIT; + ECS__DeviceAns ans = ECS__DEVICE_ANS__INIT; + int length = strlen(tizen_target_img_path); // ?? + + ans.category = (char*) g_malloc(10 + 1); + strncpy(ans.category, "info", 10); + + ans.errcode = 0; + ans.length = length; + ans.group = 1; + ans.action = 1; + + if (length > 0) + { + ans.has_data = 1; + + ans.data.data = g_malloc(length); + ans.data.len = length; + memcpy(ans.data.data, tizen_target_img_path, length); + + TRACE("data = %s, length = %hu\n", tizen_target_img_path, length); + } + + master.type = ECS__MASTER__TYPE__DEVICE_ANS; + master.device_ans = &ans; + + pb_to_single_client(&master, ccli); + + if (ans.data.len > 0) + { + g_free(ans.data.data); + } + + g_free(ans.category); +} + +static void msgproc_device_req_sensor(ECS_Client* ccli, ECS__DeviceReq* msg, char* cmd) +{ + char* data = NULL; + type_group group = (type_group) (msg->group & 0xff); + type_action action = (type_action) (msg->action & 0xff); + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + if (group == MSG_GROUP_STATUS) { + if (action == MSG_ACT_ACCEL) { + get_sensor_accel(); + } else if (action == MSG_ACT_GYRO) { + get_sensor_gyro(); + } else if (action == MSG_ACT_MAG) { + get_sensor_mag(); + } else if (action == MSG_ACT_LIGHT) { + get_sensor_light(); + } else if (action == MSG_ACT_PROXI) { + get_sensor_proxi(); + } + } else { + if (data != NULL) { + set_injector_data(data); + } else { + ERR("sensor set data is null\n"); + } + } + msgproc_device_ans(ccli, cmd, true, NULL); + + if (data) { + g_free(data); + } +} + +static void msgproc_device_req_network(ECS_Client* ccli, ECS__DeviceReq* msg) +{ + char* data = NULL; + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + if (data != NULL) { + TRACE(">>> Network msg: '%s'\n", data); + if(net_slirp_redir(data) < 0) { + ERR( "redirect [%s] fail\n", data); + } else { + TRACE("redirect [%s] success\n", data); + } + } else { + ERR("Network redirection data is null.\n"); + } + + if (data) { + g_free(data); + } +} + +static void msgproc_device_req_tgesture(ECS_Client* ccli, ECS__DeviceReq* msg) +{ + char* data = NULL; + type_group group = (type_group) (msg->group & 0xff); + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + /* release multi-touch */ +#ifndef CONFIG_USE_SHM + if (get_multi_touch_enable() != 0) { + clear_finger_slot(false); + } +#else + // TODO: +#endif + + if (data == NULL) { + ERR("touch gesture data is NULL\n"); + return; + } + + TRACE("%s\n", data); + + char token[] = "#"; + + if (group == 1) { /* HW key event */ + char *section = strtok(data, token); + int event_type = atoi(section); + + section = strtok(NULL, token); + int keycode = atoi(section); + + do_hw_key_event(event_type, keycode); + } else { /* touch event */ + char *section = strtok(data, token); + int event_type = atoi(section); + + section = strtok(NULL, token); + int xx = atoi(section); + + section = strtok(NULL, token); + int yy = atoi(section); + + section = strtok(NULL, token); + int zz = atoi(section); + + do_mouse_event(1/* LEFT */, event_type, 0, 0, xx, yy, zz); + } + + if (data) { + g_free(data); + } +} + +static void msgproc_device_req_input(ECS_Client* ccli, ECS__DeviceReq* msg, char* cmd) +{ + char* data = NULL; + type_group group = (type_group) (msg->group & 0xff); + type_action action = (type_action) (msg->action & 0xff); + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + // cli input + TRACE("receive input message [%s]\n", data); + + if (group == 0) { + TRACE("input keycode data : [%s]\n", data); + + char token[] = " "; + char *section = strtok(data, token); + int keycode = atoi(section); + if (action == 1) { + //action 1 press + do_hw_key_event(KEY_PRESSED, keycode); + + } else if (action == 2) { + //action 2 released + do_hw_key_event(KEY_RELEASED, keycode); + + } else { + ERR("unknown action : [%d]\n", (int)action); + } + } else if (group == 1) { + //spec out + TRACE("input category's group 1 is spec out\n"); + } else { + ERR("unknown group [%d]\n", (int)group); + } + msgproc_device_ans(ccli, cmd, true, NULL); + + if (data) { + g_free(data); + } +} + +static void msgproc_device_req_nfc(ECS_Client* ccli, ECS__DeviceReq* msg) +{ + char* data = NULL; + type_group group = (type_group) (msg->group & 0xff); + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + if (group == MSG_GROUP_STATUS) { + get_nfc_data(); + } else { + if (data != NULL) { + send_to_nfc(ccli->client_id, ccli->client_type, data, msg->data.len); + } else { + ERR("nfc data is null\n"); + } + } + + if (data) { + g_free(data); + } +} + - static bool is_hds_attached = false; - - #define FS_FILE_SYSTEM "virtfs" - #define FS_DRIVER "virtio-9p-pci" - #define FS_MOUNT_TAG "fileshare" - static bool do_virtfs_attach(const char * const file) - { - QemuOpts *fsdev; - int ret; - QDict *qdict = qdict_new(); - - fsdev = qemu_opts_create(qemu_find_opts("fsdev"), - FS_MOUNT_TAG, 0, NULL); - if (!fsdev) { - fprintf(stderr, "duplicate fsdev id: %s\n", FS_MOUNT_TAG); - return false; - } - - qemu_opt_set(fsdev, "fsdriver", "local"); - qemu_opt_set(fsdev, "path", file); - qemu_opt_set(fsdev, "security_model", "none"); - - ret = qemu_fsdev_add(fsdev); - if (ret != 0) { - ERR("qemu_fsdev_add failed. with ret: %d\n", ret); - return false; - } - - qdict = qdict_new(); - qdict_put(qdict, "driver", qstring_from_str(FS_DRIVER)); - qdict_put(qdict, "fsdev", qstring_from_str(FS_MOUNT_TAG)); - qdict_put(qdict, "mount_tag", qstring_from_str(FS_MOUNT_TAG)); - - qdict_put(qdict, "id", qstring_from_str(FS_MOUNT_TAG)); - - if (do_device_add(default_mon, qdict, NULL)) { - QDECREF(qdict); - return false; - } - - QDECREF(qdict); - - is_hds_attached = true; - - return true; - } - - bool do_virtfs_detach(void) - { - INFO("try to detach hds.\n"); - - QDict *qdict = qdict_new(); - qemu_fsdev_remove(FS_MOUNT_TAG); - - qdict_put(qdict, "id", qstring_from_str(FS_MOUNT_TAG)); - - if (qmp_marshal_input_device_del(cur_mon, qdict, NULL)) { - QDECREF(qdict); - return false; - } - - QDECREF(qdict); - - is_hds_attached = false; - - return true; - } - +static char hds_path[PATH_MAX]; + +static void msgproc_device_req_hds(ECS_Client* ccli, ECS__DeviceReq* msg, char * cmd) +{ + char* data = NULL; + type_group group = (type_group) (msg->group & 0xff); + type_action action = (type_action) (msg->action & 0xff); + + if (msg->has_data && msg->data.len > 0) + { + data = (char*) g_malloc0(msg->data.len + 1); + memcpy(data, msg->data.data, msg->data.len); + } + + INFO("hds group: %d, action : %d\n", group, action); + if (group == MSG_GROUP_STATUS) { + char hds_data_send[PATH_MAX + 3]; - if (is_hds_attached) { ++ if (is_hds_attached()) { + sprintf(hds_data_send, "1, %s", hds_path); + } else { + sprintf(hds_data_send, "0, "); + } + make_send_device_ntf(cmd, group, 99, hds_data_send); + } else if (group == 100 && action == 1) { - INFO("try attach with is_hds_attached : %d\n", is_hds_attached); - if (data != NULL && !is_hds_attached) { - if (!do_virtfs_attach(data)) { ++ INFO("try attach with is_hds_attached : %d\n", is_hds_attached()); ++ if (data != NULL && !is_hds_attached()) { ++ do_hotplug(ATTACH_HDS, data, strlen(data) + 1); ++ if (!is_hds_attached()) { + ERR("failed to attach"); + make_send_device_ntf(cmd, 100, 2, NULL); + } else { + memset(hds_path, 0, sizeof(hds_path)); + memcpy(hds_path, data, sizeof(hds_path) - 1); + INFO("send emuld to mount.\n"); + send_msg_to_guest(ccli, cmd, group, action, data, strlen(data)); + } + } else { + make_send_device_ntf(cmd, 100, 2, NULL); - } ++ } + } else if (group == 100 && action == 2) { - INFO("try detach with is_hds_attached : %d\n", is_hds_attached); - if (is_hds_attached) { ++ INFO("try detach with is_hds_attached : %d\n", is_hds_attached()); ++ if (is_hds_attached()) { + INFO("send emuld to umount.\n"); + send_msg_to_guest(ccli, cmd, group, action, NULL, 0); + } else { + INFO("hds is not attached. do not try detach it.\n"); + } + } else { + ERR("hds unknown command: group %d action %d\n", group, action); + } + + if (data) { + g_free(data); + } +} + +bool msgproc_device_req(ECS_Client* ccli, ECS__DeviceReq* msg) +{ + char cmd[10]; + memset(cmd, 0, 10); + strcpy(cmd, msg->category); + - TRACE(">> device_req: header = cmd = %s, length = %d, action=%d, group=%d\n", ++ TRACE(">> device_req: header = cmd = %s, length = %d, action=%d, group=%d\n", + cmd, msg->length, msg->action, msg->group); + + if (!strcmp(cmd, MSG_TYPE_SENSOR)) { + msgproc_device_req_sensor(ccli, msg, cmd); + } else if (!strcmp(cmd, "Network")) { + msgproc_device_req_network(ccli, msg); + } else if (!strcmp(cmd, "TGesture")) { + msgproc_device_req_tgesture(ccli, msg); + } else if (!strcmp(cmd, "info")) { + // check to emulator target image path + TRACE("receive info message %s\n", tizen_target_img_path); + send_target_image_information(ccli); + } else if (!strcmp(cmd, "hds")) { + msgproc_device_req_hds(ccli, msg, cmd); + } else if (!strcmp(cmd, "input")) { + msgproc_device_req_input(ccli, msg, cmd); + } else if (!strcmp(cmd, "vmname")) { + char* vmname = get_emul_vm_name(); + msgproc_device_ans(ccli, cmd, true, vmname); + } else if (!strcmp(cmd, "nfc")) { + msgproc_device_req_nfc(ccli, msg); + } else { + ERR("unknown cmd [%s]\n", cmd); + } + + return true; +} + +bool send_device_ntf(const char* data, const int len) +{ + type_length length = 0; + type_group group = 0; + type_action action = 0; + + const int catsize = 10; + char cat[catsize + 1]; + memset(cat, 0, catsize + 1); + + read_val_str(data, cat, catsize); + read_val_short(data + catsize, &length); + read_val_char(data + catsize + 2, &group); + read_val_char(data + catsize + 2 + 1, &action); + + const char* ijdata = (data + catsize + 2 + 1 + 1); + + TRACE("<< header cat = %s, length = %d, action=%d, group=%d\n", cat, length,action, group); + + ECS__Master master = ECS__MASTER__INIT; + ECS__DeviceNtf ntf = ECS__DEVICE_NTF__INIT; + + ntf.category = (char*) g_malloc(catsize + 1); + strncpy(ntf.category, cat, 10); + + + ntf.length = length; + ntf.group = group; + ntf.action = action; + + if (length > 0) + { + ntf.has_data = 1; + + ntf.data.data = g_malloc(length); + ntf.data.len = length; + memcpy(ntf.data.data, ijdata, length); + + TRACE("data = %s, length = %hu\n", ijdata, length); + } + + master.type = ECS__MASTER__TYPE__DEVICE_NTF; + master.device_ntf = &ntf; + + pb_to_all_clients(&master); + + if (ntf.data.data && ntf.data.len > 0) + { + g_free(ntf.data.data); + } + + if (ntf.category) + g_free(ntf.category); + + return true; +} + diff --cc tizen/src/ecs/ecs_msg_injector.c index 4373a8f520,0000000000..6f7f6e78b8 mode 100644,000000..100644 --- a/tizen/src/ecs/ecs_msg_injector.c +++ b/tizen/src/ecs/ecs_msg_injector.c @@@ -1,699 -1,0 +1,611 @@@ +/* Emulator Control Server + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung choi + * MunKyu Im + * Daiyoung Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" + - #include "mloop_event.h" ++#include "hw/virtio/maru_virtio_vmodem.h" ++#include "hw/virtio/maru_virtio_evdi.h" ++#include "hw/virtio/maru_virtio_jack.h" ++#include "hw/virtio/maru_virtio_power.h" + - #include "hw/maru_virtio_vmodem.h" - #include "hw/maru_virtio_evdi.h" - #include "hw/maru_virtio_jack.h" - #include "hw/maru_virtio_power.h" - - #include "emulator.h" ++#include "util/maru_device_hotplug.h" +#include "emul_state.h" +#include "ecs.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, ecs); + +extern QemuMutex mutex_guest_connection; +static int guest_connection = 0; + +extern QemuMutex mutex_location_data; +static char location_data[MAX_INJECTOR_REQ_DATA]; + - static bool is_sdcard_attached = false; - +static void msgproc_injector_ans(ECS_Client* ccli, const char* category, bool succeed) +{ + if (ccli == NULL) { + return; + } + int catlen = 0; + ECS__Master master = ECS__MASTER__INIT; + ECS__InjectorAns ans = ECS__INJECTOR_ANS__INIT; + + TRACE("injector ans - category : %s, succed : %d\n", category, succeed); + + catlen = strlen(category); + ans.category = (char*) g_malloc0(catlen + 1); + memcpy(ans.category, category, catlen); + + ans.errcode = !succeed; + master.type = ECS__MASTER__TYPE__INJECTOR_ANS; + master.injector_ans = &ans; + + pb_to_all_clients(&master); + + if (ans.category) + g_free(ans.category); +} + +static bool injector_send(ECS_Client* ccli, ECS__InjectorReq* msg, char* cmd) +{ + int sndlen = 15; // HEADER(CMD + LENGTH + GROUP + ACTION) + 1 + const char* msg_data; + char* sndbuf; + bool ret = false; + type_group group; + + group = (type_group) (msg->group & 0xff); + + if (msg->has_data && msg->data.data && msg->data.len > 0) + sndlen += msg->data.len; + + sndbuf = (char*) g_malloc0(sndlen); + if (!sndbuf) { + msgproc_injector_ans(ccli, cmd, false); + return false; + } + + memcpy(sndbuf, cmd, 10); + memcpy(sndbuf + 10, &msg->length, 2); + memcpy(sndbuf + 12, &msg->group, 1); + memcpy(sndbuf + 13, &msg->action, 1); + + if (msg->has_data && msg->data.data && msg->data.len > 0) { + msg_data = (const char*)msg->data.data; + memcpy(sndbuf + 14, msg_data, msg->data.len); + TRACE(">> print len = %zd, data\" %s\"\n", msg->data.len, msg_data); + } + + if(strcmp(cmd, "telephony") == 0) { + TRACE("telephony msg >>"); + ret = send_to_vmodem(route_ij, sndbuf, sndlen); + } else { + TRACE("evdi msg >> %s", cmd); + ret = send_to_evdi(route_ij, sndbuf, sndlen); + } + + g_free(sndbuf); + + if (group != MSG_GROUP_STATUS) { + msgproc_injector_ans(ccli, cmd, ret); + } + + if (!ret) { + return false; + } + + return true; +} + +static char* get_emulator_sdcard_path(void) +{ + char *emulator_sdcard_path = NULL; + char *tizen_sdk_data = NULL; + +#ifndef CONFIG_WIN32 + char emulator_sdcard[] = "/emulator/sdcard/"; +#else + char emulator_sdcard[] = "\\emulator\\sdcard\\"; +#endif + + TRACE("emulator_sdcard: %s, %zu\n", emulator_sdcard, sizeof(emulator_sdcard)); + + tizen_sdk_data = get_tizen_sdk_data_path(); + if (!tizen_sdk_data) { + ERR("failed to get tizen-sdk-data path.\n"); + return NULL; + } + + emulator_sdcard_path = + g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_sdcard) + 1); + if (!emulator_sdcard_path) { + ERR("failed to allocate memory.\n"); + return NULL; + } + + g_snprintf(emulator_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_sdcard), + "%s%s", tizen_sdk_data, emulator_sdcard); + + g_free(tizen_sdk_data); + + TRACE("sdcard path: %s\n", emulator_sdcard_path); + return emulator_sdcard_path; +} + +static char *get_old_tizen_sdk_data_path(void) +{ + char *tizen_sdk_data_path = NULL; + + INFO("try to search tizen-sdk-data path in another way.\n"); + +#ifndef CONFIG_WIN32 + char tizen_sdk_data[] = "/tizen-sdk-data"; + int tizen_sdk_data_len = 0; + char *home_dir; + + home_dir = (char *)g_getenv("HOME"); + if (!home_dir) { + home_dir = (char *)g_get_home_dir(); + } + + tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1; + tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); + if (!tizen_sdk_data_path) { + ERR("failed to allocate memory.\n"); + return NULL; + } + g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len); + g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); + +#else + char tizen_sdk_data[] = "\\tizen-sdk-data\\"; + gint tizen_sdk_data_len = 0; + HKEY hKey; + char strLocalAppDataPath[1024] = { 0 }; + DWORD dwBufLen = 1024; + + RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 0, KEY_QUERY_VALUE, &hKey); + + RegQueryValueEx(hKey, "Local AppData", NULL, + NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen); + RegCloseKey(hKey); + + tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1; + tizen_sdk_data_path = g_malloc(tizen_sdk_data_len); + if (!tizen_sdk_data_path) { + ERR("failed to allocate memory.\n"); + return NULL; + } + + g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len); + g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len); +#endif + + INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); + return tizen_sdk_data_path; +} + +/* + * get tizen-sdk-data path from sdk.info. + */ +char *get_tizen_sdk_data_path(void) +{ - char *emul_bin_path = NULL; ++ char const *emul_bin_path = NULL; + char *sdk_info_file_path = NULL; + char *tizen_sdk_data_path = NULL; +#ifndef CONFIG_WIN32 + const char *sdk_info = "../../../sdk.info"; +#else + const char *sdk_info = "..\\..\\..\\sdk.info"; +#endif + const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH"; + + FILE *sdk_info_fp = NULL; + int sdk_info_path_len = 0; + + TRACE("%s\n", __func__); + + emul_bin_path = get_bin_path(); + if (!emul_bin_path) { + ERR("failed to get emulator path.\n"); + return NULL; + } + + sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1; + sdk_info_file_path = g_malloc(sdk_info_path_len); + if (!sdk_info_file_path) { + ERR("failed to allocate sdk-data buffer.\n"); + return NULL; + } + + g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s", + emul_bin_path, sdk_info); + INFO("sdk.info path: %s\n", sdk_info_file_path); + + sdk_info_fp = fopen(sdk_info_file_path, "r"); + g_free(sdk_info_file_path); + + if (sdk_info_fp) { + TRACE("Succeeded to open [sdk.info].\n"); + + char tmp[256] = { '\0', }; + char *tmpline = NULL; + while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) { + if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) { + tmpline += strlen(sdk_data_var) + 1; // 1 for '=' + break; + } + } + + if (tmpline) { + if (tmpline[strlen(tmpline) - 1] == '\n') { + tmpline[strlen(tmpline) - 1] = '\0'; + } + if (tmpline[strlen(tmpline) - 1] == '\r') { + tmpline[strlen(tmpline) - 1] = '\0'; + } + + tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1); + g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1); + + INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path); + + fclose(sdk_info_fp); + return tizen_sdk_data_path; + } + + fclose(sdk_info_fp); + } + + // legacy mode + ERR("Failed to open [sdk.info].\n"); + + return get_old_tizen_sdk_data_path(); +} + - static void send_gen_injector_ntf(const char* cmd, int cmdlen, int grp, int act, char* on) ++static void handle_sdcard(char* dataBuf, size_t dataLen) +{ - int msglen = 0, datalen = 0; - type_length length = 0; - type_group group = grp; - type_action action = act; + - if (cmd == NULL || cmdlen > 10) - return; - - if (on == NULL) { - msglen = 14; - } else { - datalen = strlen(on); - length = (unsigned short)datalen; - - msglen = datalen + 15; - } - - char* status_msg = (char*) malloc(msglen); - if(!status_msg) - return; - - memset(status_msg, 0, msglen); - - memcpy(status_msg, cmd, cmdlen); - memcpy(status_msg + 10, &length, sizeof(unsigned short)); - memcpy(status_msg + 12, &group, sizeof(unsigned char)); - memcpy(status_msg + 13, &action, sizeof(unsigned char)); - - if (on != NULL) { - memcpy(status_msg + 14, on, datalen); - } - - send_injector_ntf(status_msg, msglen); - - if (status_msg) - free(status_msg); - } - - static bool handle_sdcard(char* dataBuf, size_t dataLen) - { - int err_no = 0; + char ret = 0; - INFO("handle_sdcard() data: %s\n", dataBuf); - if (dataBuf != NULL) { ++ ++ if (dataBuf != NULL){ + ret = dataBuf[0]; + + if (ret == '0' ) { + /* umount sdcard */ - //mloop_evcmd_usbdisk(NULL); - char sdcard_img_path[256]; - char* sdcard_path = NULL; - - sdcard_path = get_emulator_sdcard_path(); - if (sdcard_path) { - g_strlcpy(sdcard_img_path, sdcard_path, - sizeof(sdcard_img_path)); - - /* emulator_sdcard_img_path + sdcard img name */ - char* sdcard_img_name = dataBuf+2; - if (dataLen > 3 && sdcard_img_name != NULL) { - char* pLinechange = strchr(sdcard_img_name, '\n'); - if(pLinechange != NULL){ - sdcard_img_name = g_strndup(sdcard_img_name, pLinechange - sdcard_img_name); - } - - g_strlcat(sdcard_img_path, sdcard_img_name, sizeof(sdcard_img_path)); - INFO("sdcard path: [%s]\n", sdcard_img_path); - - /*if using strndup than free string*/ - if (pLinechange != NULL && sdcard_img_name!= NULL) { - free(sdcard_img_name); - } - } - g_free(sdcard_path); - - } - err_no = remove_sdcard_lock_os(sdcard_img_path); - INFO("umount err_no: %d\n", err_no); - if (errno == 0 && is_sdcard_attached) { - mloop_evcmd_sdcard(NULL); - is_sdcard_attached = false; - } else { - ERR("failed to umount: %s\n", sdcard_img_path); - send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, err_no, NULL); - return err_no; - } - } - else if (ret == '1') { ++ do_hotplug(DETACH_SDCARD, NULL, 0); ++ } else if (ret == '1') { + /* mount sdcard */ + char sdcard_img_path[256]; + char* sdcard_path = NULL; + + sdcard_path = get_emulator_sdcard_path(); + if (sdcard_path) { + g_strlcpy(sdcard_img_path, sdcard_path, + sizeof(sdcard_img_path)); + + /* emulator_sdcard_img_path + sdcard img name */ + char* sdcard_img_name = dataBuf+2; - if (dataLen > 3 && sdcard_img_name != NULL) { ++ if(dataLen > 3 && sdcard_img_name != NULL){ + char* pLinechange = strchr(sdcard_img_name, '\n'); + if(pLinechange != NULL){ + sdcard_img_name = g_strndup(sdcard_img_name, pLinechange - sdcard_img_name); + } + + g_strlcat(sdcard_img_path, sdcard_img_name, sizeof(sdcard_img_path)); + TRACE("sdcard path: [%s]\n", sdcard_img_path); + - //mloop_evcmd_usbdisk(sdcard_img_path); - if (!is_sdcard_attached && make_sdcard_lock_os(sdcard_img_path)) { - mloop_evcmd_sdcard(sdcard_img_path); - is_sdcard_attached = true; - } else { - send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 5, NULL); - return ERR_LCK; - } ++ do_hotplug(ATTACH_SDCARD, sdcard_img_path, strlen(sdcard_img_path) + 1); ++ + /*if using strndup than free string*/ - if (pLinechange != NULL && sdcard_img_name!= NULL) { ++ if(pLinechange != NULL && sdcard_img_name!= NULL){ + free(sdcard_img_name); + } + + } + + g_free(sdcard_path); + } else { + ERR("failed to get sdcard path!!\n"); + } - } else if (ret == '2') { - TRACE("sdcard status 2 bypass\n" ); - } else { ++ } else if(ret == '2'){ ++ TRACE("sdcard status 2 bypass" ); ++ }else { + ERR("!!! unknown command : %c\n", ret); + } + - } else { ++ }else{ + ERR("!!! unknown data : %c\n", ret); + } - return ERR_SUCCESS; +} + +static bool injector_req_sdcard(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd) +{ + if (msg->has_data) { + TRACE("msg(%zu) : %s\n", msg->data.len, msg->data.data); - if (handle_sdcard((char*) msg->data.data, msg->data.len) > 0) { - return false; - } ++ handle_sdcard((char*) msg->data.data, msg->data.len); + } else { + ERR("has no msg\n"); + } + - return injector_send(ccli, msg, cmd); ++ injector_send(ccli, msg, cmd); ++ ++ return true; +} + +static void send_status_injector_ntf(const char* cmd, int cmdlen, int act, char* on) +{ + int msglen = 0, datalen = 0; + type_length length = 0; + type_group group = MSG_GROUP_STATUS; + type_action action = act; + + if (cmd == NULL || cmdlen > 10) + return; + + if (on == NULL) { + msglen = 14; + } else { + datalen = strlen(on); + length = (unsigned short)datalen; + + msglen = datalen + 15; + } + + char* status_msg = (char*) malloc(msglen); + if(!status_msg) + return; + + memset(status_msg, 0, msglen); + + memcpy(status_msg, cmd, cmdlen); + memcpy(status_msg + 10, &length, sizeof(unsigned short)); + memcpy(status_msg + 12, &group, sizeof(unsigned char)); + memcpy(status_msg + 13, &action, sizeof(unsigned char)); + + if (on != NULL) { + memcpy(status_msg + 14, on, datalen); + } + + send_injector_ntf(status_msg, msglen); + + if (status_msg) + free(status_msg); +} + +static bool injector_req_sensor(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd) +{ + char data[MAX_INJECTOR_REQ_DATA]; + type_group group; + type_action action; + + memset(data, 0, MAX_INJECTOR_REQ_DATA); + group = (type_group) (msg->group & 0xff); + action = (type_action) (msg->action & 0xff); + + if (group == MSG_GROUP_STATUS) { + switch (action) { + case MSG_ACT_BATTERY_LEVEL: + sprintf(data, "%d", get_power_capacity()); + break; + case MSG_ACT_BATTERY_CHARGER: + sprintf(data, "%d", get_jack_charger()); + break; + case MSG_ACT_USB: + sprintf(data, "%d", get_jack_usb()); + break; + case MSG_ACT_EARJACK: + sprintf(data, "%d", get_jack_earjack()); + break; + case MSG_ACT_LOCATION: + qemu_mutex_lock(&mutex_location_data); + sprintf(data, "%s", location_data); + qemu_mutex_unlock(&mutex_location_data); + break; + default: + return injector_send(ccli, msg, cmd); + } + TRACE("status : %s\n", data); + send_status_injector_ntf(MSG_TYPE_SENSOR, 6, action, data); + return true; + } else if (msg->data.data && msg->data.len > 0) { + set_injector_data((char*) msg->data.data); + return injector_send(ccli, msg, cmd); + } + + return false; +} + +static bool injector_req_guest(void) +{ + int value = 0; + qemu_mutex_lock(&mutex_guest_connection); + value = guest_connection; + qemu_mutex_unlock(&mutex_guest_connection); + send_status_injector_ntf(MSG_TYPE_GUEST, 5, value, NULL); + return true; +} + +static bool injector_req_location(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd) +{ + if (msg->data.data != NULL && msg->data.len > 0) { + qemu_mutex_lock(&mutex_location_data); + snprintf(location_data, msg->data.len + 1, "%s", (char*)msg->data.data); + qemu_mutex_unlock(&mutex_location_data); + return injector_send(ccli, msg, cmd); + } + + return false; +} + +bool msgproc_injector_req(ECS_Client* ccli, ECS__InjectorReq* msg) +{ + char cmd[11]; + bool ret = false; + + strncpy(cmd, msg->category, sizeof(cmd) - 1); + + if (!strcmp(cmd, MSG_TYPE_SDCARD)) { + ret = injector_req_sdcard(ccli, msg, cmd); + } else if (!strcmp(cmd, MSG_TYPE_SENSOR)) { + ret = injector_req_sensor(ccli, msg, cmd); + } else if (!strcmp(cmd, MSG_TYPE_GUEST)) { + ret = injector_req_guest(); + } else if (!strcmp(cmd, MSG_TYPE_LOCATION)) { + ret = injector_req_location(ccli, msg, cmd); + } else { + ret = injector_send(ccli, msg, cmd); + } + + return ret; +} + +void ecs_suspend_lock_state(int state) +{ + int catlen; + + ECS__InjectorReq msg = ECS__INJECTOR_REQ__INIT; + const char* category = "suspend"; + + catlen = strlen(category); + msg.category = (char*) g_malloc0(catlen + 1); + memcpy(msg.category, category, catlen); + + msg.group = 5; + msg.action = state; + + msgproc_injector_req(NULL, &msg); +} + +#define MSG_GROUP_HDS 100 +static bool injector_req_handle(char* cat, type_action action) +{ + /*SD CARD msg process*/ + if (!strcmp(cat, MSG_TYPE_SDCARD)) { + return false; + } else if (!strcmp(cat, "suspend")) { + ecs_suspend_lock_state(ecs_get_suspend_state()); + return true; + } else if (!strcmp(cat, MSG_TYPE_GUEST)) { + INFO("emuld connection is %d\n", action); + qemu_mutex_lock(&mutex_guest_connection); + guest_connection = action; + qemu_mutex_unlock(&mutex_guest_connection); + return false; + } else if (!strcmp(cat, "hds")) { + INFO("hds status is %d\n", action); + switch (action) { + case 1: + make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL); + break; + case 2: + make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL); + break; + case 3: - if (!do_virtfs_detach()) { ++ do_hotplug(DETACH_HDS, NULL, 0); ++ if (!is_hds_attached()) { + make_send_device_ntf(cat, MSG_GROUP_HDS, 5, NULL); + } else { + make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL); + } + break; + case 4: + make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL); + break; + default: + ERR("unknown action: %s.\n", action); + break; + } + return true; + } else { + ERR("unknown command: %s.\n", cat); + } + + return false; +} + +bool send_injector_ntf(const char* data, const int len) +{ + type_length length = 0; + type_group group = 0; + type_action action = 0; + + const int catsize = 10; + char cat[catsize + 1]; + memset(cat, 0, catsize + 1); + + read_val_str(data, cat, catsize); + read_val_short(data + catsize, &length); + read_val_char(data + catsize + 2, &group); + read_val_char(data + catsize + 2 + 1, &action); + + if (injector_req_handle(cat, action)) { + return true; + } + + const char* ijdata = (data + catsize + 2 + 1 + 1); + + TRACE("<< header cat = %s, length = %d, action=%d, group=%d\n", cat, length,action, group); + + ECS__Master master = ECS__MASTER__INIT; + ECS__InjectorNtf ntf = ECS__INJECTOR_NTF__INIT; + + ntf.category = (char*) g_malloc(catsize + 1); + strncpy(ntf.category, cat, 10); + + ntf.length = length; + ntf.group = group; + ntf.action = action; + + if (length > 0) + { + ntf.has_data = 1; + + ntf.data.data = g_malloc(length); + ntf.data.len = length; + memcpy(ntf.data.data, ijdata, length); + } + + master.type = ECS__MASTER__TYPE__INJECTOR_NTF; + master.injector_ntf = &ntf; + + pb_to_all_clients(&master); + + if (ntf.data.len > 0) + { + g_free(ntf.data.data); + } + + g_free(ntf.category); + + return true; +} + diff --cc tizen/src/ecs/ecs_nfc.c index 7e5ee5ff8c,0000000000..dcc1e4c5d5 mode 100644,000000..100644 --- a/tizen/src/ecs/ecs_nfc.c +++ b/tizen/src/ecs/ecs_nfc.c @@@ -1,116 -1,0 +1,116 @@@ +/* Emulator Control Server + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung choi + * MunKyu Im + * Daiyoung Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include "qemu-common.h" + - #include "hw/maru_virtio_nfc.h" ++#include "hw/virtio/maru_virtio_nfc.h" + +#include "ecs.h" + +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, ecs); + +bool msgproc_nfc_req(ECS_Client* ccli, ECS__NfcReq* msg) +{ + int datalen = msg->data.len; + void* data = (void*)g_malloc(datalen); + if(!data) { + ERR("g_malloc failed!\n"); + return false; + } + + memset(data, 0, datalen); + memcpy(data, msg->data.data, msg->data.len); + + if (msg->has_data && msg->data.len > 0) + { + TRACE("recv from nfc injector: %s, %z\n", msg->has_data, msg->data.len); + print_binary(data, datalen); + } + + send_to_nfc(ccli->client_id, ccli->client_type, data, msg->data.len); + g_free(data); + return true; +} + +bool send_nfc_ntf(struct nfc_msg_info* msg) +{ + const int catsize = 10; + char cat[catsize + 1]; + ECS_Client *clii; + memset(cat, 0, catsize + 1); + + print_binary((char*)msg->buf, msg->use); + TRACE("id: %02x, type: %02x, use: %d\n", msg->client_id, msg->client_type, msg->use); + clii = find_client(msg->client_id, msg->client_type); + if (clii) { + if(clii->client_type == TYPE_SIMUL_NFC) { + strncpy(cat, MSG_TYPE_NFC, 3); + } else if (clii->client_type == TYPE_ECP) { + strncpy(cat, MSG_TYPE_SIMUL_NFC, 9); + }else { + ERR("cannot find type! : %d\n", clii->client_type); + } + TRACE("header category = %s\n", cat); + } + else { + ERR("cannot find client!\n"); + } + + ECS__Master master = ECS__MASTER__INIT; + ECS__NfcNtf ntf = ECS__NFC_NTF__INIT; + + ntf.category = (char*) g_malloc(catsize + 1); + strncpy(ntf.category, cat, 10); + + ntf.has_data = 1; + + ntf.data.data = g_malloc(NFC_MAX_BUF_SIZE); + ntf.data.len = NFC_MAX_BUF_SIZE; + memcpy(ntf.data.data, msg->buf, NFC_MAX_BUF_SIZE); + + TRACE("send to nfc injector: \n"); + master.type = ECS__MASTER__TYPE__NFC_NTF; + master.nfc_ntf = &ntf; + + pb_to_all_clients(&master); + + if (ntf.data.data && ntf.data.len > 0) + { + g_free(ntf.data.data); + } + + if (ntf.category) + g_free(ntf.category); + + return true; +} + + diff --cc tizen/src/emul_state.h index 740ff93bc8,2663d776a6..0266102048 --- a/tizen/src/emul_state.h +++ b/tizen/src/emul_state.h @@@ -33,12 -33,13 +33,16 @@@ #ifndef __EMUL_STATE_H__ #define __EMUL_STATE_H__ - #include "maru_common.h" - #include "maru_finger.h" + + #include "display/maru_finger.h" + + #define SUPPORT_LEGACY_ARGS + #define MAX_ADDR_LEN 256 + #define MAX_PORT_LEN 256 +#define MAX_ADDR_LEN 256 +#define MAX_PORT_LEN 256 + enum { RESET = 0, BOOT_COMPLETED = 1, diff --cc tizen/src/hw/pci/maru_brillcodec.c index 0000000000,cb6585dcee..b021733682 mode 000000,100644..100644 --- a/tizen/src/hw/pci/maru_brillcodec.c +++ b/tizen/src/hw/pci/maru_brillcodec.c @@@ -1,0 -1,1757 +1,1773 @@@ + /* + * Virtual Codec Device + * + * Copyright (c) 2013 - 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Kitae Kim + * SeokYeon Hwang + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + #include "maru_brillcodec.h" + + #include "libavresample/avresample.h" + #include "libavutil/mathematics.h" + #include "libavutil/opt.h" + #include "libavformat/avformat.h" + + #include "debug_ch.h" + + /* define debug channel */ + MULTI_DEBUG_CHANNEL(qemu, brillcodec); + + // device memory + #define CODEC_META_DATA_SIZE (256) + + // libav + #define GEN_MASK(x) ((1 << (x)) - 1) + #define ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) & ~GEN_MASK(x)) + #define ROUND_UP_2(x) ROUND_UP_X(x, 1) + #define ROUND_UP_4(x) ROUND_UP_X(x, 2) + #define ROUND_UP_8(x) ROUND_UP_X(x, 3) + #define DIV_ROUND_UP_X(v, x) (((v) + GEN_MASK(x)) >> (x)) + + #define DEFAULT_VIDEO_GOP_SIZE 15 + + enum codec_api_type { + CODEC_INIT = 0, + CODEC_DECODE_VIDEO, + CODEC_ENCODE_VIDEO, + CODEC_DECODE_AUDIO, + CODEC_ENCODE_AUDIO, + CODEC_PICTURE_COPY, + CODEC_DEINIT, + CODEC_FLUSH_BUFFERS, + }; + + enum codec_type { + CODEC_TYPE_UNKNOWN = -1, + CODEC_TYPE_DECODE, + CODEC_TYPE_ENCODE, + }; + + struct video_data { + int32_t width; + int32_t height; + int32_t fps_n; + int32_t fps_d; + int32_t par_n; + int32_t par_d; + int32_t pix_fmt; + int32_t bpp; + int32_t ticks_per_frame; + }; + + struct audio_data { + int32_t channels; + int32_t sample_rate; + int32_t block_align; + int32_t depth; + int32_t sample_fmt; + int32_t frame_size; + int32_t bits_per_smp_fmt; + int32_t reserved; + int64_t channel_layout; + }; + + DeviceMemEntry *entry[CODEC_CONTEXT_MAX]; + + // define a queue to manage ioparam, context data + typedef struct CodecDataStg { + CodecParam *param_buf; + DeviceMemEntry *data_buf; + + QTAILQ_ENTRY(CodecDataStg) node; + } CodecDataStg; + + // define two queue to store input and output buffers. + struct codec_wq codec_wq = QTAILQ_HEAD_INITIALIZER(codec_wq); + static QTAILQ_HEAD(codec_rq, CodecDataStg) codec_rq = + QTAILQ_HEAD_INITIALIZER(codec_rq); + + // codec functions + static bool codec_init(MaruBrillCodecState *, int, void *); + static bool codec_deinit(MaruBrillCodecState *, int, void *); + static bool codec_decode_video(MaruBrillCodecState *, int, void *); + static bool codec_encode_video(MaruBrillCodecState *, int, void *); + static bool codec_decode_audio(MaruBrillCodecState *, int, void *); + static bool codec_encode_audio(MaruBrillCodecState *, int, void *); + static bool codec_picture_copy(MaruBrillCodecState *, int, void *); + static bool codec_flush_buffers(MaruBrillCodecState *, int, void *); + + typedef bool (*CodecFuncEntry)(MaruBrillCodecState *, int, void *); + static CodecFuncEntry codec_func_handler[] = { + codec_init, + codec_decode_video, + codec_encode_video, + codec_decode_audio, + codec_encode_audio, + codec_picture_copy, + codec_deinit, + codec_flush_buffers, + }; + + static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx); + + static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, CodecParam *ioparam); + static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* opaque, + size_t data_size, int ctx_id, + DataHandler *handler); + + static void *maru_brill_codec_store_inbuf(uint8_t *mem_base, CodecParam *ioparam); + + // default handler + static void default_get_data(void *dst, void *src, size_t size, enum AVPixelFormat pix_fmt) { + memcpy(dst, src, size); + } + + static void default_release(void *opaque) { + g_free(opaque); + } + + static DataHandler default_data_handler = { + .get_data = default_get_data, + .release = default_release, + }; + + + // default video decode data handler + static void extract(void *dst, void *src, size_t size, enum AVPixelFormat pix_fmt) { + AVFrame *frame = (AVFrame *)src; + avpicture_layout((AVPicture *)src, pix_fmt, frame->width, frame->height, dst, size); + } + + static void release(void *buf) {} + + static DataHandler default_video_decode_data_handler = { + .get_data = extract, + .release = release, + }; + + static void maru_brill_codec_thread_exit(MaruBrillCodecState *s) + { + int index; + + TRACE("enter: %s\n", __func__); + + /* stop to run dedicated threads. */ + s->is_thread_running = false; + + for (index = 0; index < s->worker_thread_cnt; index++) { + qemu_thread_join(&s->threadpool.threads[index]); + } + + TRACE("destroy mutex and conditional.\n"); + qemu_mutex_destroy(&s->threadpool.mutex); + qemu_cond_destroy(&s->threadpool.cond); + + if (s->threadpool.threads) { + g_free(s->threadpool.threads); + s->threadpool.threads = NULL; + } + + TRACE("leave: %s\n", __func__); + } + + void maru_brill_codec_wakeup_threads(MaruBrillCodecState *s, int api_index) + { + CodecParam *ioparam = NULL; + + ioparam = g_malloc0(sizeof(CodecParam)); + if (!ioparam) { + ERR("failed to allocate ioparam\n"); + return; + } + + memcpy(ioparam, &s->ioparam, sizeof(CodecParam)); + + TRACE("wakeup thread. ctx_id: %u, api_id: %u, mem_offset: 0x%x\n", + ioparam->ctx_index, ioparam->api_index, ioparam->mem_offset); + + qemu_mutex_lock(&s->context_mutex); + + if (ioparam->api_index != CODEC_INIT) { + if (!CONTEXT(s, ioparam->ctx_index).opened_context) { + INFO("abandon api %d for context %d\n", + ioparam->api_index, ioparam->ctx_index); + qemu_mutex_unlock(&s->context_mutex); + return; + } + } + + qemu_mutex_unlock(&s->context_mutex); + + maru_brill_codec_push_readqueue(s, ioparam); + + qemu_mutex_lock(&s->context_mutex); + // W/A for threads starvation. + while (s->idle_thread_cnt == 0) { + qemu_mutex_unlock(&s->context_mutex); + TRACE("Worker threads are exhausted\n"); + usleep(2000); // wait 2ms. + qemu_mutex_lock(&s->context_mutex); + } + qemu_cond_signal(&s->threadpool.cond); + qemu_mutex_unlock(&s->context_mutex); + + TRACE("after sending conditional signal\n"); + } + + void *maru_brill_codec_threads(void *opaque) + { + MaruBrillCodecState *s = (MaruBrillCodecState *)opaque; + bool ret = false; + + TRACE("enter: %s\n", __func__); + + while (s->is_thread_running) { + int ctx_id = 0, api_id = 0; + CodecDataStg *elem = NULL; + DeviceMemEntry *indata_buf = NULL; + + qemu_mutex_lock(&s->context_mutex); + ++(s->idle_thread_cnt); // protected under mutex. + qemu_cond_wait(&s->threadpool.cond, &s->context_mutex); + --(s->idle_thread_cnt); // protected under mutex. + qemu_mutex_unlock(&s->context_mutex); + + qemu_mutex_lock(&s->ioparam_queue_mutex); + elem = QTAILQ_FIRST(&codec_rq); + if (elem) { + QTAILQ_REMOVE(&codec_rq, elem, node); + qemu_mutex_unlock(&s->ioparam_queue_mutex); + } else { + qemu_mutex_unlock(&s->ioparam_queue_mutex); + continue; + } + + if (!elem->param_buf) { + continue; + } + + api_id = elem->param_buf->api_index; + ctx_id = elem->param_buf->ctx_index; + + indata_buf = elem->data_buf; + + TRACE("api_id: %d ctx_id: %d\n", api_id, ctx_id); + + qemu_mutex_lock(&s->context_mutex); + CONTEXT(s, ctx_id).occupied_thread = true; + qemu_mutex_unlock(&s->context_mutex); + + ret = codec_func_handler[api_id](s, ctx_id, indata_buf); + if (!ret) { + ERR("fail api %d for context %d\n", api_id, ctx_id); + g_free(elem->param_buf); + continue; + } + + TRACE("release a buffer of CodecParam\n"); + g_free(elem->param_buf); + elem->param_buf = NULL; + + if (elem->data_buf) { + if (elem->data_buf->opaque) { + TRACE("release inbuf\n"); + g_free(elem->data_buf->opaque); + elem->data_buf->opaque = NULL; + } + + TRACE("release a buffer indata_buf\n"); + g_free(elem->data_buf); + elem->data_buf = NULL; + } + + TRACE("release an element of CodecDataStg\n"); + g_free(elem); + + qemu_mutex_lock(&s->context_mutex); + if (CONTEXT(s, ctx_id).requested_close) { + INFO("make worker thread to handle deinit\n"); + // codec_deinit(s, ctx_id, NULL); + maru_brill_codec_release_context(s, ctx_id); + CONTEXT(s, ctx_id).requested_close = false; + } + qemu_mutex_unlock(&s->context_mutex); + + TRACE("switch context to raise interrupt.\n"); + qemu_bh_schedule(s->codec_bh); + + qemu_mutex_lock(&s->context_mutex); + CONTEXT(s, ctx_id).occupied_thread = false; + qemu_mutex_unlock(&s->context_mutex); + } + + maru_brill_codec_thread_exit(s); + + TRACE("leave: %s\n", __func__); + return NULL; + } + + // queue + static void maru_brill_codec_push_readqueue(MaruBrillCodecState *s, + CodecParam *ioparam) + { + CodecDataStg *elem = NULL; + DeviceMemEntry *data_buf = NULL; + + elem = g_malloc0(sizeof(CodecDataStg)); + if (!elem) { + ERR("failed to allocate ioparam_queue. %d\n", sizeof(CodecDataStg)); + return; + } + + elem->param_buf = ioparam; + + switch(ioparam->api_index) { + case CODEC_INIT ... CODEC_ENCODE_AUDIO: + data_buf = maru_brill_codec_store_inbuf((uint8_t *)s->vaddr, ioparam); + break; + default: + TRACE("no buffer from guest\n"); + break; + } + + elem->data_buf = data_buf; + + qemu_mutex_lock(&s->ioparam_queue_mutex); + QTAILQ_INSERT_TAIL(&codec_rq, elem, node); + qemu_mutex_unlock(&s->ioparam_queue_mutex); + } + + static void *maru_brill_codec_store_inbuf(uint8_t *mem_base, + CodecParam *ioparam) + { + DeviceMemEntry *elem = NULL; + int readbuf_size, size = 0; + uint8_t *readbuf = NULL; + uint8_t *device_mem = mem_base + ioparam->mem_offset; + + elem = g_malloc0(sizeof(DeviceMemEntry)); + if (!elem) { + ERR("failed to allocate readqueue node. size: %d\n", + sizeof(DeviceMemEntry)); + return NULL; + } + + memcpy(&readbuf_size, device_mem, sizeof(readbuf_size)); + size = sizeof(readbuf_size); + + TRACE("readbuf size: %d\n", readbuf_size); + if (readbuf_size <= 0) { + TRACE("inbuf size is 0. api_id %d, ctx_id %d, mem_offset %x\n", + ioparam->api_index, ioparam->ctx_index, ioparam->mem_offset); + } else { + readbuf = g_malloc0(readbuf_size); + if (!readbuf) { + ERR("failed to allocate a read buffer. size: %d\n", readbuf_size); + } else { + TRACE("copy input buffer from guest. ctx_id: %d, mem_offset: %x\n", + ioparam->ctx_index, ioparam->mem_offset); + memcpy(readbuf, device_mem + size, readbuf_size); + } + } + // memset(device_mem, 0x00, sizeof(readbuf_size)); + + elem->opaque = readbuf; + elem->data_size = readbuf_size; + elem->ctx_id = ioparam->ctx_index; + + return elem; + } + + static void maru_brill_codec_push_writequeue(MaruBrillCodecState *s, void* opaque, + size_t data_size, int ctx_id, + DataHandler *handler) + { + DeviceMemEntry *elem = NULL; + elem = g_malloc0(sizeof(DeviceMemEntry)); + + elem->opaque = opaque; + elem->data_size = data_size; + elem->ctx_id = ctx_id; + + if (handler) { + elem->handler = handler; + } else { + elem->handler = &default_data_handler; + } + + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_INSERT_TAIL(&codec_wq, elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); + } + + void maru_brill_codec_pop_writequeue(MaruBrillCodecState *s, uint32_t ctx_idx) + { + DeviceMemEntry *elem = NULL; + uint32_t mem_offset = 0; + + TRACE("enter: %s\n", __func__); + + if (ctx_idx < 1 || ctx_idx > (CODEC_CONTEXT_MAX - 1)) { + ERR("invalid buffer index. %d\n", ctx_idx); + return; + } + + TRACE("pop_writeqeue. context index: %d\n", ctx_idx); + elem = entry[ctx_idx]; + if (elem) { + mem_offset = s->ioparam.mem_offset; + + // check corrupted mem_offset + if (mem_offset < CODEC_MEM_SIZE) { + elem->handler->get_data(s->vaddr + mem_offset, elem->opaque, elem->data_size, s->context[ctx_idx].avctx->pix_fmt); + elem->handler->release(elem->opaque); + } else { + TRACE("mem_offset is corrupted!!\n"); + } + + TRACE("pop_writequeue. release elem: %p\n", elem); + g_free(elem); + + entry[ctx_idx] = NULL; + } else { + TRACE("there is no buffer to copy data to guest\n"); + } + + TRACE("leave: %s\n", __func__); + } + + static void serialize_video_data(const struct video_data *video, + AVCodecContext *avctx) + { + if (video->width) { + avctx->width = video->width; + } + if (video->height) { + avctx->height = video->height; + } + if (video->fps_n) { + avctx->time_base.num = video->fps_n; + } + if (video->fps_d) { + avctx->time_base.den = video->fps_d; + } + if (video->pix_fmt > PIX_FMT_NONE) { + avctx->pix_fmt = video->pix_fmt; + } + if (video->par_n) { + avctx->sample_aspect_ratio.num = video->par_n; + } + if (video->par_d) { + avctx->sample_aspect_ratio.den = video->par_d; + } + if (video->bpp) { + avctx->bits_per_coded_sample = video->bpp; + } + if (video->ticks_per_frame) { + avctx->ticks_per_frame = video->ticks_per_frame; + } + + INFO("codec_init. video, resolution: %dx%d, framerate: %d/%d " + "pixel_fmt: %d sample_aspect_ratio: %d/%d bpp %d\n", + avctx->width, avctx->height, avctx->time_base.num, + avctx->time_base.den, avctx->pix_fmt, avctx->sample_aspect_ratio.num, + avctx->sample_aspect_ratio.den, avctx->bits_per_coded_sample); + } + + static void deserialize_video_data (const AVCodecContext *avctx, + struct video_data *video) + { + memset(video, 0x00, sizeof(struct video_data)); + + video->width = avctx->width; + video->height = avctx->height; + video->fps_n = avctx->time_base.num; + video->fps_d = avctx->time_base.den; + video->pix_fmt = avctx->pix_fmt; + video->par_n = avctx->sample_aspect_ratio.num; + video->par_d = avctx->sample_aspect_ratio.den; + video->bpp = avctx->bits_per_coded_sample; + video->ticks_per_frame = avctx->ticks_per_frame; + } + + static void serialize_audio_data (const struct audio_data *audio, + AVCodecContext *avctx) + { + if (audio->channels) { + avctx->channels = audio->channels; + } + if (audio->sample_rate) { + avctx->sample_rate = audio->sample_rate; + } + if (audio->block_align) { + avctx->block_align = audio->block_align; + } + + if (audio->sample_fmt > AV_SAMPLE_FMT_NONE) { + avctx->sample_fmt = audio->sample_fmt; + } + + INFO("codec_init. audio, channel %d sample_rate %d sample_fmt %d ch_layout %lld\n", + avctx->channels, avctx->sample_rate, avctx->sample_fmt, avctx->channel_layout); + } + + void maru_brill_codec_release_context(MaruBrillCodecState *s, int32_t ctx_id) + { + DeviceMemEntry *wq_elem = NULL, *wnext = NULL; + CodecDataStg *rq_elem = NULL, *rnext = NULL; + + TRACE("enter: %s\n", __func__); + + TRACE("release %d of context\n", ctx_id); + + qemu_mutex_lock(&s->threadpool.mutex); + if (CONTEXT(s, ctx_id).opened_context) { + // qemu_mutex_unlock(&s->threadpool.mutex); + codec_deinit(s, ctx_id, NULL); + // qemu_mutex_lock(&s->threadpool.mutex); + } + CONTEXT(s, ctx_id).occupied_context = false; + qemu_mutex_unlock(&s->threadpool.mutex); + + // TODO: check if foreach statment needs lock or not. + QTAILQ_FOREACH_SAFE(rq_elem, &codec_rq, node, rnext) { + if (rq_elem && rq_elem->data_buf && + (rq_elem->data_buf->ctx_id == ctx_id)) { + + TRACE("remove unused node from codec_rq. ctx_id: %d\n", ctx_id); + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_REMOVE(&codec_rq, rq_elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); + if (rq_elem && rq_elem->data_buf) { + TRACE("release rq_buffer: %p\n", rq_elem->data_buf); + g_free(rq_elem->data_buf); + } + + TRACE("release rq_elem: %p\n", rq_elem); + g_free(rq_elem); + } else { + TRACE("no elem of %d context in the codec_rq.\n", ctx_id); + } + } + + QTAILQ_FOREACH_SAFE(wq_elem, &codec_wq, node, wnext) { + if (wq_elem && wq_elem->ctx_id == ctx_id) { + TRACE("remove unused node from codec_wq. ctx_id: %d\n", ctx_id); + qemu_mutex_lock(&s->context_queue_mutex); + QTAILQ_REMOVE(&codec_wq, wq_elem, node); + qemu_mutex_unlock(&s->context_queue_mutex); + + if (wq_elem && wq_elem->opaque) { + TRACE("release wq_buffer: %p\n", wq_elem->opaque); + g_free(wq_elem->opaque); + wq_elem->opaque = NULL; + } + + TRACE("release wq_elem: %p\n", wq_elem); + g_free(wq_elem); + } else { + TRACE("no elem of %d context in the codec_wq.\n", ctx_id); + } + } + + TRACE("leave: %s\n", __func__); + } + + int maru_brill_codec_query_list (MaruBrillCodecState *s) + { + AVCodec *codec = NULL; + uint32_t size = 0, mem_size = 0; + uint32_t data_len = 0, length = 0; + int32_t codec_type, media_type; + int32_t codec_fmts[4], i; + + /* register avcodec */ + TRACE("register avcodec\n"); + av_register_all(); + + codec = av_codec_next(NULL); + if (!codec) { + ERR("failed to get codec info.\n"); + return -1; + } + + // a region to store the number of codecs. + length = 32 + 64 + 6 * sizeof(int32_t); + mem_size = size = sizeof(uint32_t); + + while (codec) { + codec_type = + codec->decode ? CODEC_TYPE_DECODE : CODEC_TYPE_ENCODE; + media_type = codec->type; + + memset(codec_fmts, -1, sizeof(codec_fmts)); + if (media_type == AVMEDIA_TYPE_VIDEO) { + if (codec->pix_fmts) { + for (i = 0; codec->pix_fmts[i] != -1 && i < 4; i++) { + codec_fmts[i] = codec->pix_fmts[i]; + } + } + } else if (media_type == AVMEDIA_TYPE_AUDIO) { + if (codec->sample_fmts) { + for (i = 0; codec->sample_fmts[i] != -1; i++) { + codec_fmts[i] = codec->sample_fmts[i]; + } + } + } else { + ERR("unknown media type: %d\n", media_type); + } + + memset(s->vaddr + mem_size, 0x00, length); + mem_size += length; + + data_len += length; + memcpy(s->vaddr, &data_len, sizeof(data_len)); + + memcpy(s->vaddr + size, &codec_type, sizeof(codec_type)); + size += sizeof(codec_type); + memcpy(s->vaddr + size, &media_type, sizeof(media_type)); + size += sizeof(media_type); + memcpy(s->vaddr + size, codec->name, strlen(codec->name)); + size += 32; + memcpy(s->vaddr + size, + codec->long_name, strlen(codec->long_name)); + size += 64; + memcpy(s->vaddr + size, codec_fmts, sizeof(codec_fmts)); + size += sizeof(codec_fmts); + + TRACE("register %s %s\n", codec->name, codec->decode ? "decoder" : "encoder"); + codec = av_codec_next(codec); + } + + return 0; + } + + int maru_brill_codec_get_context_index(MaruBrillCodecState *s) + { + int ctx_id; + + TRACE("enter: %s\n", __func__); + + // requires mutex_lock? its function is protected by critical section. + qemu_mutex_lock(&s->threadpool.mutex); + for (ctx_id = 1; ctx_id < CODEC_CONTEXT_MAX; ctx_id++) { + if (CONTEXT(s, ctx_id).occupied_context == false) { + TRACE("get %d of codec context successfully.\n", ctx_id); + CONTEXT(s, ctx_id).occupied_context = true; + break; + } + } + qemu_mutex_unlock(&s->threadpool.mutex); + + if (ctx_id == CODEC_CONTEXT_MAX) { + ERR("failed to get available codec context. "); + ERR("try to run codec again.\n"); + ctx_id = -1; + } + + TRACE("leave: %s\n", __func__); + + return ctx_id; + } + + + // allocate avcontext and avframe struct. + static AVCodecContext *maru_brill_codec_alloc_context(MaruBrillCodecState *s, int ctx_id) + { + TRACE("enter: %s\n", __func__); + + TRACE("allocate %d of context and frame.\n", ctx_id); + CONTEXT(s, ctx_id).avctx = avcodec_alloc_context3(NULL); + CONTEXT(s, ctx_id).frame = avcodec_alloc_frame(); + CONTEXT(s, ctx_id).opened_context = false; + + TRACE("leave: %s\n", __func__); + + return CONTEXT(s, ctx_id).avctx; + } + + static AVCodec *maru_brill_codec_find_avcodec(uint8_t *mem_buf) + { + AVCodec *codec = NULL; + int32_t encode, size = 0; + char codec_name[32] = {0, }; + + memcpy(&encode, mem_buf, sizeof(encode)); + size = sizeof(encode); + memcpy(codec_name, mem_buf + size, sizeof(codec_name)); + size += sizeof(codec_name); + + TRACE("type: %d, name: %s\n", encode, codec_name); + + if (encode) { + codec = avcodec_find_encoder_by_name (codec_name); + } else { + codec = avcodec_find_decoder_by_name (codec_name); + } + INFO("%s!! find %s %s\n", codec ? "success" : "failure", + codec_name, encode ? "encoder" : "decoder"); + + return codec; + } + + static void read_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf) + { + struct video_data video = { 0, }; + struct audio_data audio = { 0, }; + int bitrate = 0, size = 0; + + memcpy(&video, mem_buf + size, sizeof(video)); + size = sizeof(video); + serialize_video_data(&video, avctx); + + memcpy(&audio, mem_buf + size, sizeof(audio)); + size += sizeof(audio); + serialize_audio_data(&audio, avctx); + + memcpy(&bitrate, mem_buf + size, sizeof(bitrate)); + size += sizeof(bitrate); + if (bitrate) { + avctx->bit_rate = bitrate; + } + + memcpy(&avctx->codec_tag, mem_buf + size, sizeof(avctx->codec_tag)); + size += sizeof(avctx->codec_tag); + memcpy(&avctx->extradata_size, + mem_buf + size, sizeof(avctx->extradata_size)); + size += sizeof(avctx->extradata_size); + INFO("extradata size: %d.\n", avctx->extradata_size); + + if (avctx->extradata_size > 0) { + avctx->extradata = + av_mallocz(ROUND_UP_X(avctx->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE, 4)); + if (avctx->extradata) { + memcpy(avctx->extradata, mem_buf + size, avctx->extradata_size); + } + } else { + TRACE("no extra data.\n"); + avctx->extradata = + av_mallocz(ROUND_UP_X(FF_INPUT_BUFFER_PADDING_SIZE, 4)); + } + } + + // write the result of codec_init + static int write_codec_init_data(AVCodecContext *avctx, uint8_t *mem_buf) + { + int size = 0; + + if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) { + int osize = av_get_bytes_per_sample(avctx->sample_fmt); + + INFO("avcodec_open. sample_fmt %d, bytes_per_sample %d\n", avctx->sample_fmt, osize); + + if ((avctx->codec_id == AV_CODEC_ID_AAC) && avctx->codec->encode2) { + osize = av_get_bytes_per_sample(AV_SAMPLE_FMT_S16); + } + memcpy(mem_buf, &avctx->sample_fmt, sizeof(avctx->sample_fmt)); + size = sizeof(avctx->sample_fmt); + + // frame_size: samples per packet, initialized when calling 'init' + memcpy(mem_buf + size, &avctx->frame_size, sizeof(avctx->frame_size)); + size += sizeof(avctx->frame_size); + + memcpy(mem_buf + size, &osize, sizeof(osize)); + size += sizeof(osize); + } + + return size; + } + + static int convert_audio_sample_fmt(const AVCodec *codec, int codec_type, bool encode) + { + int audio_sample_fmt = AV_SAMPLE_FMT_NONE; + + if (!codec) { + return audio_sample_fmt; + } + + if (codec_type != AVMEDIA_TYPE_AUDIO) { + ERR("this codec_type is invalid %d\n", codec_type); + return audio_sample_fmt; + } + + if (!strcmp(codec->name, "aac")) { + // FLOAT format + if (encode) { + audio_sample_fmt = AV_SAMPLE_FMT_FLTP; + } else { + audio_sample_fmt = AV_SAMPLE_FMT_FLT; + } + } else if (!strcmp(codec->name, "mp3") || !strcmp(codec->name, "mp3adu")) { + // S16 format + if (encode) { + audio_sample_fmt = AV_SAMPLE_FMT_S16P; + } else { + audio_sample_fmt = AV_SAMPLE_FMT_S16; + } + } else if (!strcmp(codec->name, "wmav1") || !strcmp(codec->name, "wmav2")) { + if (encode) { + audio_sample_fmt = AV_SAMPLE_FMT_FLTP; + } else { + audio_sample_fmt = AV_SAMPLE_FMT_FLT; + } + } else { + INFO("cannot handle %s codec\n", codec->name); + } + + TRACE("convert audio sample_fmt %d\n", audio_sample_fmt); + return audio_sample_fmt; + } + + static int fill_audio_into_frame(AVCodecContext *avctx, AVFrame *frame, + uint8_t *samples, int samples_size, + int nb_samples, int audio_sample_fmt) + { + int result = 0; + + if (!avctx) { + ERR("fill_audio. AVCodecContext is NULL!!\n"); + return -1; + } + + if (!frame) { + ERR("fill_audio. AVFrame is NULL!!\n"); + return -1; + } + + frame->nb_samples = nb_samples; + frame->format = audio_sample_fmt; + frame->channel_layout = avctx->channel_layout; + + result = + avcodec_fill_audio_frame(frame, avctx->channels, audio_sample_fmt, (const uint8_t *)samples, samples_size, 0); + TRACE("fill audio in_frame. ret: %d in_frame->ch_layout %lld\n", result, frame->channel_layout); + + return result; + } + + static AVFrame *resample_audio(AVCodecContext *avctx, AVFrame *sample_frame, + int sample_buffer_size, int in_sample_fmt, + AVFrame *resample_frame, int *resample_buffer_size, + int resample_sample_fmt) + { + AVAudioResampleContext *avr = NULL; + uint8_t *resample_buffer = NULL; + int buffer_size = 0; + int resample_nb_samples = sample_frame->nb_samples; + + avr = avresample_alloc_context(); + if (!avr) { + ERR("failed to allocate avresample context\n"); + return NULL; + } + + TRACE("channel_layout %lld sample_rate %d in_sample_fmt %d resample_sample_fmt %d\n", + avctx->channel_layout, avctx->sample_rate, avctx->sample_fmt, resample_sample_fmt); + + av_opt_set_int(avr, "in_channel_layout", avctx->channel_layout, 0); + av_opt_set_int(avr, "in_sample_fmt", in_sample_fmt, 0); + av_opt_set_int(avr, "in_sample_rate", avctx->sample_rate, 0); + + av_opt_set_int(avr, "out_channel_layout", avctx->channel_layout, 0); + av_opt_set_int(avr, "out_sample_fmt", resample_sample_fmt, 0); + av_opt_set_int(avr, "out_sample_rate", avctx->sample_rate, 0); + + TRACE("open avresample context\n"); + if (avresample_open(avr) < 0) { + ERR("failed to open avresample context\n"); + avresample_free(&avr); + return NULL; + } + + resample_frame = avcodec_alloc_frame(); + TRACE("resample audio. nb_samples %d sample_fmt %d\n", resample_nb_samples, resample_sample_fmt); + + *resample_buffer_size = av_samples_get_buffer_size(NULL, avctx->channels, resample_nb_samples, resample_sample_fmt, 0); + if (*resample_buffer_size < 0) { + ERR("failed to get size of resample buffer %d\n", *resample_buffer_size); + avresample_close(avr); + avresample_free(&avr); + return NULL; + } + + resample_buffer = av_mallocz(*resample_buffer_size); + if (!resample_buffer) { + ERR("failed to allocate resample buffer\n"); + avresample_close(avr); + avresample_free(&avr); + return NULL; + } + + fill_audio_into_frame(avctx, resample_frame, resample_buffer, + *resample_buffer_size, resample_nb_samples, resample_sample_fmt); + + buffer_size = avresample_convert(avr, resample_frame->data, + *resample_buffer_size, resample_nb_samples, + sample_frame->data, sample_buffer_size, + sample_frame->nb_samples); + + TRACE("resample_audio buffer_size %d\n", buffer_size); + + avresample_close(avr); + avresample_free(&avr); + + return resample_frame; + } + + static int parse_and_decode_video(AVCodecContext *avctx, AVFrame *picture, + AVCodecParserContext *pctx, int ctx_id, + AVPacket *packet, int *got_picture, + int idx, int64_t in_offset) + { + uint8_t *parser_outbuf = NULL; + int parser_outbuf_size = 0; + uint8_t *parser_buf = packet->data; + int parser_buf_size = packet->size; + int ret = 0, len = -1; + int64_t pts = 0, dts = 0, pos = 0; + + pts = dts = idx; + pos = in_offset; + + do { + if (pctx) { + ret = av_parser_parse2(pctx, avctx, &parser_outbuf, + &parser_outbuf_size, parser_buf, parser_buf_size, + pts, dts, pos); + + if (ret) { + parser_buf_size -= ret; + parser_buf += ret; + } + + TRACE("after parsing ret: %d parser_outbuf_size %d parser_buf_size %d pts %lld\n", + ret, parser_outbuf_size, parser_buf_size, pctx->pts); + + /* if there is no output, we must break and wait for more data. + * also the timestamp in the context is not updated. + */ + if (parser_outbuf_size == 0) { + if (parser_buf_size > 0) { + TRACE("parsing data have been left\n"); + continue; + } else { + TRACE("finish parsing data\n"); + break; + } + } + + packet->data = parser_outbuf; + packet->size = parser_outbuf_size; + } else { + TRACE("not using parser %s\n", avctx->codec->name); + } + + len = avcodec_decode_video2(avctx, picture, got_picture, packet); + TRACE("decode_video. len %d, got_picture %d\n", len, *got_picture); + + if (!pctx) { + if (len == 0 && (*got_picture) == 0) { + ERR("decoding video didn't return any data! ctx_id %d len %d\n", ctx_id, len); + break; + } else if (len < 0) { + ERR("decoding video error! ctx_id %d len %d\n", ctx_id, len); + break; + } + parser_buf_size -= len; + parser_buf += len; + } else { + if (len == 0) { + ERR("decoding video didn't return any data! ctx_id %d len %d\n", ctx_id, len); + *got_picture = 0; + break; + } else if (len < 0) { + ERR("decoding video error! trying next ctx_id %d len %d\n", ctx_id, len); + break; + } + } + } while (parser_buf_size > 0); + + return len; + } + + // codec functions + static bool codec_init(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + AVCodec *codec = NULL; + int size = 0, ret = -1; + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + int tempbuf_size = 0; + + TRACE("enter: %s\n", __func__); + + elem = (DeviceMemEntry *)data_buf; + + // allocate AVCodecContext + avctx = maru_brill_codec_alloc_context(s, ctx_id); + if (!avctx) { + ERR("[%d] failed to allocate context.\n", __LINE__); + ret = -1; + } else { + codec = maru_brill_codec_find_avcodec(elem->opaque); + if (codec) { + size = sizeof(int32_t) + 32; // buffer size of codec_name + read_codec_init_data(avctx, elem->opaque + size); + + // in case of aac encoder, sample format is float + if (!strcmp(codec->name, "aac") && codec->encode2) { + TRACE("convert sample format into SAMPLE_FMT_FLTP\n"); + avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; + + avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; + + INFO("aac encoder!! channels %d channel_layout %lld\n", + avctx->channels, avctx->channel_layout); + avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + } + + TRACE("audio sample format %d\n", avctx->sample_fmt); + TRACE("strict_std_compliance %d\n", avctx->strict_std_compliance); + ++ // in case of aac encoder, sample format is float ++ if (!strcmp(codec->name, "aac") && codec->encode2) { ++ TRACE("convert sample format into SAMPLE_FMT_FLTP\n"); ++ avctx->sample_fmt = AV_SAMPLE_FMT_FLTP; ++ ++ avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; ++ ++ INFO("aac encoder!! channels %d channel_layout %lld\n", avctx->channels, avctx->channel_layout); ++ avctx->channel_layout = av_get_default_channel_layout(avctx->channels); ++ } ++ ++ TRACE("audio sample format %d\n", avctx->sample_fmt); ++ TRACE("strict_std_compliance %d\n", avctx->strict_std_compliance); ++ + ret = avcodec_open2(avctx, codec, NULL); + INFO("avcodec_open. ret 0x%x ctx_id %d\n", ret, ctx_id); + + INFO("channels %d sample_rate %d sample_fmt %d " + "channel_layout %lld frame_size %d\n", + avctx->channels, avctx->sample_rate, avctx->sample_fmt, + avctx->channel_layout, avctx->frame_size); + + tempbuf_size = (sizeof(avctx->sample_fmt) + sizeof(avctx->frame_size) + + sizeof(avctx->extradata_size) + avctx->extradata_size) + + sizeof(int); + + CONTEXT(s, ctx_id).opened_context = true; + CONTEXT(s, ctx_id).parser_ctx = + maru_brill_codec_parser_init(avctx); + } else { + ERR("failed to find codec. ctx_id: %d\n", ctx_id); + ret = -1; + } + } + + tempbuf_size += sizeof(ret); + + tempbuf = g_malloc(tempbuf_size); + if (!tempbuf) { + ERR("failed to allocate a buffer\n"); + tempbuf_size = 0; + } else { + memcpy(tempbuf, &ret, sizeof(ret)); + size = sizeof(ret); + if (ret < 0) { + ERR("failed to open codec contex.\n"); + } else { + size += write_codec_init_data(avctx, tempbuf + size); + TRACE("codec_init. copyback!! size %d\n", size); + { + memcpy(tempbuf + size, &avctx->extradata_size, sizeof(avctx->extradata_size)); + size += sizeof(avctx->extradata_size); + + INFO("codec_init. extradata_size: %d\n", avctx->extradata_size); + if (avctx->extradata) { + memcpy(tempbuf + size, avctx->extradata, avctx->extradata_size); + size += avctx->extradata_size; + } + } + } + } + + maru_brill_codec_push_writequeue(s, tempbuf, tempbuf_size, ctx_id, NULL); + + TRACE("leave: %s\n", __func__); + + return true; + } + + static bool codec_deinit(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + AVFrame *frame = NULL; + AVCodecParserContext *parserctx = NULL; + + TRACE("enter: %s\n", __func__); + + avctx = CONTEXT(s, ctx_id).avctx; + frame = CONTEXT(s, ctx_id).frame; + parserctx = CONTEXT(s, ctx_id).parser_ctx; + if (!avctx || !frame) { + TRACE("%d of AVCodecContext or AVFrame is NULL. " + " Those resources have been released before.\n", ctx_id); + return false; + } + + INFO("close avcontext of %d\n", ctx_id); + // qemu_mutex_lock(&s->threadpool.mutex); + avcodec_close(avctx); + CONTEXT(s, ctx_id).opened_context = false; + // qemu_mutex_unlock(&s->threadpool.mutex); + + if (avctx->extradata) { + TRACE("free context extradata\n"); + av_free(avctx->extradata); + CONTEXT(s, ctx_id).avctx->extradata = NULL; + } + + if (frame) { + TRACE("free frame\n"); + avcodec_free_frame(&frame); + CONTEXT(s, ctx_id).frame = NULL; + } + + if (avctx) { + TRACE("free codec context\n"); + av_free(avctx); + CONTEXT(s, ctx_id).avctx = NULL; + } + + if (parserctx) { + INFO("close parser context\n"); + av_parser_close(parserctx); + CONTEXT(s, ctx_id).parser_ctx = NULL; + } + + maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id, NULL); + + TRACE("leave: %s\n", __func__); + + return true; + } + + static bool codec_flush_buffers(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + bool ret = true; + + TRACE("enter: %s\n", __func__); + + avctx = CONTEXT(s, ctx_id).avctx; + if (!avctx) { + ERR("%d of AVCodecContext is NULL.\n", ctx_id); + ret = false; + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + ret = false; + } else { + TRACE("flush %d context of buffers.\n", ctx_id); + AVCodecParserContext *pctx = NULL; + uint8_t *poutbuf = NULL; + int poutbuf_size = 0; + int res = 0; + + uint8_t p_inbuf[FF_INPUT_BUFFER_PADDING_SIZE]; + int p_inbuf_size = FF_INPUT_BUFFER_PADDING_SIZE; + + memset(&p_inbuf, 0x00, p_inbuf_size); + + pctx = CONTEXT(s, ctx_id).parser_ctx; + if (pctx) { + res = av_parser_parse2(pctx, avctx, &poutbuf, &poutbuf_size, + p_inbuf, p_inbuf_size, -1, -1, -1); + INFO("before flush buffers, using parser. res: %d\n", res); + } + + avcodec_flush_buffers(avctx); + } + + maru_brill_codec_push_writequeue(s, NULL, 0, ctx_id, NULL); + + TRACE("leave: %s\n", __func__); + + return ret; + } + + static bool codec_decode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + AVFrame *picture = NULL; + AVCodecParserContext *pctx = NULL; + AVPacket avpkt; + + int got_picture = 0, len = -1; + int idx = 0, size = 0; + int64_t in_offset = 0; + uint8_t *inbuf = NULL; + int inbuf_size = 0; + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + int tempbuf_size = 0; + + TRACE("enter: %s\n", __func__); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->opaque) { + memcpy(&inbuf_size, elem->opaque, sizeof(inbuf_size)); + size += sizeof(inbuf_size); + memcpy(&idx, elem->opaque + size, sizeof(idx)); + size += sizeof(idx); + memcpy(&in_offset, elem->opaque + size, sizeof(in_offset)); + size += sizeof(in_offset); + TRACE("decode_video. inbuf_size %d\n", inbuf_size); + + if (inbuf_size > 0) { + inbuf = elem->opaque + size; + } + } else { + TRACE("decode_video. no input buffer\n"); + // FIXME: improve error handling + // return false; + } + + av_init_packet(&avpkt); + avpkt.data = inbuf; + avpkt.size = inbuf_size; + + + avctx = CONTEXT(s, ctx_id).avctx; + picture = CONTEXT(s, ctx_id).frame; + if (!avctx) { + ERR("decode_video. %d of AVCodecContext is NULL.\n", ctx_id); + } else if (!avctx->codec) { + ERR("decode_video. %d of AVCodec is NULL.\n", ctx_id); + } else if (!picture) { + ERR("decode_video. %d of AVFrame is NULL.\n", ctx_id); + } else { + pctx = CONTEXT(s, ctx_id).parser_ctx; + + len = parse_and_decode_video(avctx, picture, pctx, ctx_id, + &avpkt, &got_picture, idx, in_offset); + } + + tempbuf_size = sizeof(len) + sizeof(got_picture) + sizeof(struct video_data); + + tempbuf = g_malloc(tempbuf_size); + if (!tempbuf) { + ERR("failed to allocate decoded audio buffer\n"); + tempbuf_size = 0; + } else { + struct video_data video; + + memcpy(tempbuf, &len, sizeof(len)); + size = sizeof(len); + memcpy(tempbuf + size, &got_picture, sizeof(got_picture)); + size += sizeof(got_picture); + if (avctx) { + deserialize_video_data(avctx, &video); + memcpy(tempbuf + size, &video, sizeof(struct video_data)); + } + } + + maru_brill_codec_push_writequeue(s, tempbuf, tempbuf_size, ctx_id, NULL); + + TRACE("leave: %s\n", __func__); + + return true; + } + + static bool codec_picture_copy (MaruBrillCodecState *s, int ctx_id, void *elem) + { + AVCodecContext *avctx = NULL; + AVPicture *src = NULL; + int pict_size = 0; + bool ret = true; + + TRACE("enter: %s\n", __func__); + + TRACE("copy decoded image of %d context.\n", ctx_id); + + avctx = CONTEXT(s, ctx_id).avctx; + src = (AVPicture *)CONTEXT(s, ctx_id).frame; + if (!avctx) { + ERR("picture_copy. %d of AVCodecContext is NULL.\n", ctx_id); + ret = false; + } else if (!avctx->codec) { + ERR("picture_copy. %d of AVCodec is NULL.\n", ctx_id); + ret = false; + } else if (!src) { + ERR("picture_copy. %d of AVFrame is NULL.\n", ctx_id); + ret = false; + } else { + TRACE("decoded image. pix_fmt: %d width: %d, height: %d\n", + avctx->pix_fmt, avctx->width, avctx->height); + pict_size = avpicture_get_size(avctx->pix_fmt, avctx->width, avctx->height); + + if ((pict_size) < 0) { + ERR("picture size: %d\n", pict_size); + ret = false; + } else { + TRACE("picture size: %d\n", pict_size); + maru_brill_codec_push_writequeue(s, src, pict_size, ctx_id, &default_video_decode_data_handler); + } + } + + TRACE("leave: %s\n", __func__); + + return ret; + } + + /* + * decode_audio >> raw audio_buffer >> resample + * + * audios sink cannot handle planar format, so it is required + * to resample audio buffer into linear format. + */ + static bool codec_decode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx; + AVPacket avpkt; + AVFrame *audio_out = NULL; + uint8_t *inbuf = NULL; + int inbuf_size = 0, size = 0; + int len = -1, got_frame = 0; + + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + int tempbuf_size = 0; + + AVFrame *resample_frame = NULL; + uint8_t *resample_buf = NULL; + int resample_buf_size = 0; + int out_sample_fmt = -1; + + TRACE("enter: %s\n", __func__); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->opaque) { + memcpy(&inbuf_size, elem->opaque, sizeof(inbuf_size)); + size = sizeof(inbuf_size); + TRACE("decode_audio. inbuf_size %d\n", inbuf_size); + + if (inbuf_size > 0) { + inbuf = elem->opaque + size; + } + } else { + ERR("decode_audio. no input buffer\n"); + // FIXME: improve error handling + // return false; + } + + av_init_packet(&avpkt); + avpkt.data = inbuf; + avpkt.size = inbuf_size; + + avctx = CONTEXT(s, ctx_id).avctx; + audio_out = CONTEXT(s, ctx_id).frame; + if (!avctx) { + ERR("decode_audio. %d of AVCodecContext is NULL\n", ctx_id); + } else if (!avctx->codec) { + ERR("decode_audio. %d of AVCodec is NULL\n", ctx_id); + } else if (!audio_out) { + ERR("decode_audio. %d of AVFrame is NULL\n", ctx_id); + } else { + len = avcodec_decode_audio4(avctx, audio_out, &got_frame, &avpkt); + TRACE("decode_audio. len %d, channel_layout %lld got_frame %d\n", + len, avctx->channel_layout, got_frame); + + if (got_frame) { + if (av_sample_fmt_is_planar(avctx->sample_fmt)) { + out_sample_fmt = convert_audio_sample_fmt(avctx->codec, avctx->codec_type, 0); + + if (avctx->channel_layout == 0) { + avctx->channel_layout = av_get_default_channel_layout(avctx->channels); + TRACE("decode_audio. channel_layout %lld channels %d\n", + avctx->channel_layout, avctx->channels); + } + resample_frame = resample_audio(avctx, audio_out, audio_out->linesize[0], + avctx->sample_fmt, NULL, &resample_buf_size, + out_sample_fmt); + if (resample_frame) { + resample_buf = resample_frame->data[0]; + } else { + ERR("failed to resample decoded audio buffer\n"); + len = -1; + got_frame = 0; + } + } else { + INFO("decode_audio. linear audio format\n"); + resample_buf = audio_out->data[0]; + resample_buf_size = audio_out->linesize[0]; + } + } + } + + tempbuf_size = (sizeof(len) + sizeof(got_frame)); + if (len < 0) { + ERR("failed to decode audio. ctx_id: %d len: %d got_frame: %d\n", + ctx_id, len, got_frame); + got_frame = 0; + } else { + tempbuf_size += (sizeof(out_sample_fmt) + sizeof(avctx->sample_rate) + + sizeof(avctx->channels) + sizeof(avctx->channel_layout) + + sizeof(resample_buf_size) + resample_buf_size); + } + + tempbuf = g_malloc(tempbuf_size); + if (!tempbuf) { + ERR("failed to allocate decoded audio buffer\n"); + } else { + memcpy(tempbuf, &len, sizeof(len)); + size = sizeof(len); + memcpy(tempbuf + size, &got_frame, sizeof(got_frame)); + size += sizeof(got_frame); + if (got_frame) { + memcpy(tempbuf + size, &out_sample_fmt, sizeof(out_sample_fmt)); + size += sizeof(out_sample_fmt); + memcpy(tempbuf + size, &avctx->sample_rate, sizeof(avctx->sample_rate)); + size += sizeof(avctx->sample_rate); + memcpy(tempbuf + size, &avctx->channels, sizeof(avctx->channels)); + size += sizeof(avctx->channels); + memcpy(tempbuf + size, &avctx->channel_layout, sizeof(avctx->channel_layout)); + size += sizeof(avctx->channel_layout); + + memcpy(tempbuf + size, &resample_buf_size, sizeof(resample_buf_size)); + size += sizeof(resample_buf_size); + if (resample_buf) { + TRACE("copy resampled audio buffer\n"); + memcpy(tempbuf + size, resample_buf, resample_buf_size); + } + } + } + + maru_brill_codec_push_writequeue(s, tempbuf, tempbuf_size, ctx_id, NULL); + + if (resample_frame) { + TRACE("release decoded frame\n"); + av_free(resample_buf); + av_free(resample_frame); + } + ++ if (audio_out) { ++ avcodec_free_frame(&audio_out); ++ } ++ + TRACE("leave: %s\n", __func__); + return true; + } + + static bool codec_encode_video(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + AVFrame *pict = NULL; + AVPacket avpkt; + uint8_t *inbuf = NULL, *outbuf = NULL; + int inbuf_size = 0, outbuf_size = 0; + int got_frame = 0, ret = 0, size = 0; + int64_t in_timestamp = 0; + int coded_frame = 0, key_frame = 0; + + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + int tempbuf_size = 0; + + TRACE("enter: %s\n", __func__); + + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->opaque) { + memcpy(&inbuf_size, elem->opaque, sizeof(inbuf_size)); + size += sizeof(inbuf_size); + memcpy(&in_timestamp, elem->opaque + size, sizeof(in_timestamp)); + size += sizeof(in_timestamp); + TRACE("encode video. inbuf_size %d\n", inbuf_size); + + if (inbuf_size > 0) { + inbuf = elem->opaque + size; + } + } else { + TRACE("encode video. no input buffer.\n"); + // FIXME: improve error handling + // return false; + } + + // initialize AVPacket + av_init_packet(&avpkt); + avpkt.data = NULL; + avpkt.size = 0; + + avctx = CONTEXT(s, ctx_id).avctx; + pict = CONTEXT(s, ctx_id).frame; + if (!avctx || !pict) { + ERR("%d of context or frame is NULL\n", ctx_id); + } else if (!avctx->codec) { + ERR("%d of AVCodec is NULL.\n", ctx_id); + } else { + TRACE("pixel format: %d inbuf: %p, picture data: %p\n", + avctx->pix_fmt, inbuf, pict->data[0]); + + ret = avpicture_fill((AVPicture *)pict, inbuf, avctx->pix_fmt, + avctx->width, avctx->height); + if (ret < 0) { + ERR("after avpicture_fill, ret:%d\n", ret); + } else { + if (avctx->time_base.num == 0) { + pict->pts = AV_NOPTS_VALUE; + } else { + AVRational bq = + {1, (G_USEC_PER_SEC * G_GINT64_CONSTANT(1000))}; + pict->pts = av_rescale_q(in_timestamp, bq, avctx->time_base); + } + TRACE("encode video. ticks_per_frame:%d, pts:%lld\n", + avctx->ticks_per_frame, pict->pts); + + outbuf_size = + (avctx->width * avctx->height * 6) + FF_MIN_BUFFER_SIZE; + + outbuf = g_malloc0(outbuf_size); + + avpkt.data = outbuf; + avpkt.size = outbuf_size; + + if (!outbuf) { + ERR("failed to allocate a buffer of encoding video.\n"); + } else { + ret = avcodec_encode_video2(avctx, &avpkt, pict, &got_frame); + + TRACE("encode video. ret %d got_picture %d outbuf_size %d\n", ret, got_frame, avpkt.size); + if (avctx->coded_frame) { + TRACE("encode video. keyframe %d\n", avctx->coded_frame->key_frame); + } + } + } + } + + tempbuf_size = sizeof(ret); + if (ret < 0) { + ERR("failed to encode video. ctx_id %d ret %d\n", ctx_id, ret); + } else { + tempbuf_size += avpkt.size + sizeof(coded_frame) + sizeof(key_frame); + } + + // write encoded video data + tempbuf = g_malloc0(tempbuf_size); + if (!tempbuf) { + ERR("encode video. failed to allocate encoded out buffer.\n"); + } else { + memcpy(tempbuf, &avpkt.size, sizeof(avpkt.size)); + size = sizeof(avpkt.size); + + if ((got_frame) && outbuf) { + // inform gstreamer plugin about the status of encoded frames + // A flag for output buffer in gstreamer is depending on the status. + if (avctx->coded_frame) { + coded_frame = 1; + // if key_frame is 0, this frame cannot be decoded independently. + key_frame = avctx->coded_frame->key_frame; + } + memcpy(tempbuf + size, &coded_frame, sizeof(coded_frame)); + size += sizeof(coded_frame); + memcpy(tempbuf + size, &key_frame, sizeof(key_frame)); + size += sizeof(key_frame); + memcpy(tempbuf + size, outbuf, avpkt.size); + } + } + + if (outbuf) { + TRACE("release encoded output buffer. %p\n", outbuf); + g_free(outbuf); + } + + maru_brill_codec_push_writequeue(s, tempbuf, tempbuf_size, ctx_id, NULL); + + TRACE("leave: %s\n", __func__); + return true; + } + + static bool codec_encode_audio(MaruBrillCodecState *s, int ctx_id, void *data_buf) + { + AVCodecContext *avctx = NULL; + AVPacket avpkt; + uint8_t *audio_in = NULL; + int32_t audio_in_size = 0; + int ret = -1, got_pkt = 0, size = 0; + + DeviceMemEntry *elem = NULL; + uint8_t *tempbuf = NULL; + int tempbuf_size = 0; + + AVFrame *in_frame = NULL; + AVFrame *resample_frame = NULL; + int64_t in_timestamp = 0; + + TRACE("enter: %s\n", __func__); + + /* + * copy raw audio data from gstreamer encoder plugin + * audio_in_size: size of raw audio data + * audio_in : raw audio data + */ + elem = (DeviceMemEntry *)data_buf; + if (elem && elem->opaque) { + memcpy(&audio_in_size, elem->opaque, sizeof(audio_in_size)); + size += sizeof(audio_in_size); + + memcpy(&in_timestamp, elem->opaque + size, sizeof(in_timestamp)); + size += sizeof(in_timestamp); + + TRACE("encode_audio. audio_in_size %d\n", audio_in_size); + if (audio_in_size > 0) { + // audio_in = g_malloc0(audio_in_size); + // memcpy(audio_in, elem->buf + size, audio_in_size); + audio_in = elem->opaque + size; + } + } else { + TRACE("encode_audio. no input buffer\n"); - // FIXME: improve error handling - // return false; + } + + avctx = CONTEXT(s, ctx_id).avctx; + if (!avctx) { + ERR("encode_audio. %d of Context is NULL\n", ctx_id); + } else if (!avctx->codec) { + ERR("encode_audio. %d of AVCodec is NULL\n", ctx_id); + } else { + int bytes_per_sample = 0; + int nb_samples = 0; + int audio_in_sample_fmt = AV_SAMPLE_FMT_S16; + // audio input src can generate a buffer as an int format. + + int resample_buf_size = 0; + int resample_sample_fmt = 0; + + bytes_per_sample = av_get_bytes_per_sample(audio_in_sample_fmt); + TRACE("bytes per sample %d, sample format %d\n", bytes_per_sample, audio_in_sample_fmt); + + nb_samples = audio_in_size / (bytes_per_sample * avctx->channels); + TRACE("nb_samples %d\n", nb_samples); + + in_frame = avcodec_alloc_frame(); + if (!in_frame) { + ERR("encode_audio. failed to allocate in_frame\n"); + } else { + // prepare audio_in frame + ret = fill_audio_into_frame(avctx, in_frame, audio_in, audio_in_size, nb_samples, audio_in_sample_fmt); + if (ret < 0) { + ERR("failed to fill audio into frame\n"); + } else { + resample_sample_fmt = + convert_audio_sample_fmt(avctx->codec, avctx->codec_type, 1); + resample_frame = resample_audio(avctx, in_frame, audio_in_size, + audio_in_sample_fmt, NULL, &resample_buf_size, + resample_sample_fmt); + + if (resample_frame) { + av_init_packet(&avpkt); + avpkt.data = NULL; + avpkt.size = 0; + + ret = avcodec_encode_audio2(avctx, &avpkt, (const AVFrame *)resample_frame, &got_pkt); + TRACE("encode audio. ret %d got_pkt %d avpkt.size %d frame_number %d\n", + ret, got_pkt, avpkt.size, avctx->frame_number); + } + } + } + } + + tempbuf_size = sizeof(ret); + if (ret < 0) { + ERR("failed to encode audio. ctx_id %d ret %d\n", ctx_id, ret); + } else { + tempbuf_size += (sizeof(avpkt.size) + avpkt.size); + } + TRACE("encode_audio. writequeue elem buffer size %d\n", tempbuf_size); + + // write encoded audio data + tempbuf = g_malloc0(tempbuf_size); + if (!tempbuf) { + ERR("encode audio. failed to allocate encoded out buffer.\n"); + } else { + memcpy(tempbuf, &ret, sizeof(ret)); + size = sizeof(ret); + if (ret == 0) { + memcpy(tempbuf + size, &avpkt.size, sizeof(avpkt.size)); + size += sizeof(avpkt.size); + + if (got_pkt) { + memcpy(tempbuf + size, avpkt.data, avpkt.size); + av_free_packet(&avpkt); + } + } + } + + maru_brill_codec_push_writequeue(s, tempbuf, tempbuf_size, ctx_id, NULL); + + if (in_frame) { + av_free(in_frame); + } + + if (resample_frame) { + av_free(resample_frame->data[0]); + av_free(resample_frame); + } + + TRACE("[%s] leave:\n", __func__); + + return true; + } + + static AVCodecParserContext *maru_brill_codec_parser_init(AVCodecContext *avctx) + { + AVCodecParserContext *parser = NULL; + + if (!avctx) { + ERR("context is NULL\n"); + return NULL; + } + + switch (avctx->codec_id) { + case CODEC_ID_MPEG4: + case CODEC_ID_VC1: + TRACE("not using parser\n"); + break; + case CODEC_ID_H264: + if (avctx->extradata_size == 0) { + TRACE("H.264 with no extradata, creating parser.\n"); + parser = av_parser_init (avctx->codec_id); + } + break; + default: + parser = av_parser_init(avctx->codec_id); + if (parser) { + INFO("using parser: %s\n", avctx->codec->name); + } + break; + } + + return parser; + } diff --cc tizen/src/util/maru_device_hotplug.c index 0000000000,70d74981b1..f55fd590e2 mode 000000,100644..100644 --- a/tizen/src/util/maru_device_hotplug.c +++ b/tizen/src/util/maru_device_hotplug.c @@@ -1,0 -1,213 +1,286 @@@ + /* + * Maru device hotplug + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + #include "qemu/main-loop.h" + #include "qemu/config-file.h" + #include "hw/qdev.h" + #include "monitor/qdev.h" ++#include "fsdev/qemu-fsdev.h" + #include "qmp-commands.h" + #include "sysemu/blockdev.h" + #include "qemu/event_notifier.h" + + #include "emulator.h" + #include "maru_device_hotplug.h" + + #define HOST_KEYBOARD_DRIVER "virtio-keyboard-pci" + #define HOST_KEYBOARD_DEFAULT_ID "HOSTKBD0" + + #define SDCARD_DRIVE_DEFAULT_ID "SDCARD_DRIVE0" + #define SDCARD_DRIVER "virtio-blk-pci" + #define SDCARD_DEFAULT_ID "SDCARD0" + ++#define FS_MOUNT_TAG "fileshare" ++ + struct maru_device_hotplug { + EventNotifier notifier; + + char *opaque; + int command; + + // FIXME: Should we query device every time ?? + bool host_keyboard_attached; + bool sdcard_attached; ++ bool hds_attached; + }; + + static struct maru_device_hotplug *state; + + static bool do_host_keyboard_attach(void) + { + QDict *qdict = qdict_new(); + qdict_put(qdict, "driver", qstring_from_str(HOST_KEYBOARD_DRIVER)); + qdict_put(qdict, "id", qstring_from_str(HOST_KEYBOARD_DEFAULT_ID)); + + if (do_device_add(default_mon, qdict, NULL)) { + QDECREF(qdict); + // TODO error reporting + return false; + } + + QDECREF(qdict); + + state->host_keyboard_attached = true; + + return true; + } + + static bool do_host_keyboard_detach(void) + { + QDict *qdict = qdict_new(); + qdict_put(qdict, "id", qstring_from_str(HOST_KEYBOARD_DEFAULT_ID)); + + if (qmp_marshal_input_device_del(default_mon, qdict, NULL)) { + QDECREF(qdict); + // TODO error reporting + return false; + } + + QDECREF(qdict); + + state->host_keyboard_attached = false; + + return true; + } + + static bool do_sdcard_attach(const char * const file) + { + QDict *qdict = qdict_new(); + QDict *qdict_file = qdict_new(); + QDict *qdict_options = qdict_new(); + + qdict_put(qdict_file, "driver", qstring_from_str("file")); + qdict_put(qdict_file, "filename", qstring_from_str(file)); + qdict_put(qdict_options, "file", qdict_file); + qdict_put(qdict_options, "driver", qstring_from_str("qcow2")); + qdict_put(qdict_options, "id", qstring_from_str(SDCARD_DRIVE_DEFAULT_ID)); + qdict_put(qdict, "options", qdict_options); + + if (qmp_marshal_input_blockdev_add(default_mon, qdict, NULL)) { + QDECREF(qdict); + } + + QDECREF(qdict); + + qdict = qdict_new(); + qdict_put(qdict, "driver", qstring_from_str(SDCARD_DRIVER)); + qdict_put(qdict, "drive", qstring_from_str(SDCARD_DRIVE_DEFAULT_ID)); + qdict_put(qdict, "id", qstring_from_str(SDCARD_DEFAULT_ID)); + + if (do_device_add(default_mon, qdict, NULL)) { + QDECREF(qdict); + // TODO error reporting + return false; + } + + QDECREF(qdict); + + state->sdcard_attached = true; + + return true; + } + + static bool do_sdcard_detach(void) { + QDict *qdict = qdict_new(); + qdict_put(qdict, "id", qstring_from_str(SDCARD_DEFAULT_ID)); + + if (qmp_marshal_input_device_del(cur_mon, qdict, NULL)) { + QDECREF(qdict); + // TODO error reporting + return false; + } + + QDECREF(qdict); + + state->sdcard_attached = false; + + return true; + } + ++static bool do_hds_attach(const char * const file) ++{ ++ QemuOpts *fsdev; ++ int ret; ++ QDict *qdict = qdict_new(); ++ ++ fsdev = qemu_opts_create(qemu_find_opts("fsdev"), ++ FS_MOUNT_TAG, 0, NULL); ++ if (!fsdev) { ++ return false; ++ } ++ ++ qemu_opt_set(fsdev, "fsdriver", "local"); ++ qemu_opt_set(fsdev, "path", file); ++ qemu_opt_set(fsdev, "security_model", "none"); ++ ++ ret = qemu_fsdev_add(fsdev); ++ if (ret != 0) { ++ return false; ++ } ++ ++ qdict = qdict_new(); ++ qdict_put(qdict, "driver", qstring_from_str("virtio-9p-pci")); ++ qdict_put(qdict, "fsdev", qstring_from_str(FS_MOUNT_TAG)); ++ qdict_put(qdict, "mount_tag", qstring_from_str(FS_MOUNT_TAG)); ++ qdict_put(qdict, "id", qstring_from_str(FS_MOUNT_TAG)); ++ ++ if (do_device_add(default_mon, qdict, NULL)) { ++ QDECREF(qdict); ++ return false; ++ } ++ ++ QDECREF(qdict); ++ ++ state->hds_attached = true; ++ ++ return true; ++} ++ ++static bool do_hds_detach(void) ++{ ++ QDict *qdict = qdict_new(); ++ qemu_fsdev_remove(FS_MOUNT_TAG); ++ ++ qdict_put(qdict, "id", qstring_from_str(FS_MOUNT_TAG)); ++ ++ if (qmp_marshal_input_device_del(cur_mon, qdict, NULL)) { ++ QDECREF(qdict); ++ return false; ++ } ++ ++ QDECREF(qdict); ++ ++ state->hds_attached = false; ++ ++ return true; ++} ++ + void do_hotplug(int command, void *opaque, size_t size) + { + if (command == ATTACH_SDCARD) { + state->opaque = g_malloc(size); + memcpy(state->opaque, opaque, size); + } + state->command = command; + + event_notifier_set(&state->notifier); + } + + static void device_hotplug_handler(EventNotifier *e) + { + event_notifier_test_and_clear(e); + + switch(state->command) { + case ATTACH_HOST_KEYBOARD: + do_host_keyboard_attach(); + break; + case DETACH_HOST_KEYBOARD: + do_host_keyboard_detach(); + break; + case ATTACH_SDCARD: + do_sdcard_attach(state->opaque); + g_free(state->opaque); + break; + case DETACH_SDCARD: + do_sdcard_detach(); + break; ++ case ATTACH_HDS: ++ do_hds_attach(state->opaque); ++ break; ++ case DETACH_HDS: ++ do_hds_detach(); ++ break; + default: + break; + } + } + + static void maru_device_hotplug_deinit(Notifier *notifier, void *data) + { + event_notifier_cleanup(&state->notifier); + + g_free(state); + } + + static Notifier maru_device_hotplug_exit = { .notify = maru_device_hotplug_deinit }; + + void maru_device_hotplug_init(void) + { + state = g_malloc0(sizeof(struct maru_device_hotplug)); + + event_notifier_init(&state->notifier, 0); + event_notifier_set_handler(&state->notifier, device_hotplug_handler); + + emulator_add_exit_notifier(&maru_device_hotplug_exit); + } + + bool is_host_keyboard_attached(void) + { + return state->host_keyboard_attached; + } + + bool is_sdcard_attached(void) + { + return state->sdcard_attached; + } + ++bool is_hds_attached(void) ++{ ++ return state->hds_attached; ++} ++ diff --cc tizen/src/util/maru_device_hotplug.h index 0000000000,462baf3e80..69c8a97b08 mode 000000,100644..100644 --- a/tizen/src/util/maru_device_hotplug.h +++ b/tizen/src/util/maru_device_hotplug.h @@@ -1,0 -1,46 +1,49 @@@ + /* + * Maru device hotplug + * + * Copyright (C) 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + #ifndef _MARU_DEVICE_HOTPLUG_H_ + #define _MARU_DEVICE_HOTPLUG_H_ + + enum command { + ATTACH_HOST_KEYBOARD, + DETACH_HOST_KEYBOARD, + ATTACH_SDCARD, + DETACH_SDCARD, ++ ATTACH_HDS, ++ DETACH_HDS, + }; + + void maru_device_hotplug_init(void); + + void do_hotplug(int command, void *opaque, size_t size); + + bool is_host_keyboard_attached(void); + bool is_sdcard_attached(void); ++bool is_hds_attached(void); + + #endif // _MARU_DEVICE_HOTPLUG_H_ diff --cc tizen/src/util/osutil-darwin.c index 0000000000,b98f9b396c..9c86f1efb5 mode 000000,100644..100644 --- a/tizen/src/util/osutil-darwin.c +++ b/tizen/src/util/osutil-darwin.c @@@ -1,0 -1,393 +1,393 @@@ + /* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + /** + @file osutil-darwin.c + @brief Collection of utilities for darwin + */ + + #include "emulator_common.h" + #include "osutil.h" + #include "emulator.h" + #include "emul_state.h" + #include "debug_ch.h" + #include "maru_err_table.h" + #include "sdb.h" + + #ifndef CONFIG_DARWIN + #error + #endif + + #include + #include + #include + #include + #include + + MULTI_DEBUG_CHANNEL(qemu, osutil); + + static int g_shmid; + static CFDictionaryRef proxySettings; + + extern char tizen_target_img_path[]; + + static char *cfstring_to_cstring(CFStringRef str) { + if (str == NULL) { + return NULL; + } + + CFIndex length = CFStringGetLength(str); + CFIndex maxSize = CFStringGetMaximumSizeForEncoding(length, kCFStringEncodingUTF8); + char *buffer = (char *)malloc(maxSize); + if (CFStringGetCString(str, buffer, maxSize, kCFStringEncodingUTF8)) + return buffer; + return NULL; + } + + static int cfnumber_to_int(CFNumberRef num) { + if (!num) + return 0; + + int value; + CFNumberGetValue(num, kCFNumberIntType, &value); + return value; + } + + void check_vm_lock_os(void) + { + /* TODO: */ + } + + void make_vm_lock_os(void) + { + char *shared_memory; + int base_port; + base_port = get_emul_vm_base_port(); + g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT); + if (g_shmid == -1) { + ERR("shmget failed\n"); + perror("osutil-darwin: "); + return; + } + + shared_memory = shmat(g_shmid, (char *)0x00, 0); + if (shared_memory == (void *)-1) { + ERR("shmat failed\n"); + perror("osutil-darwin: "); + return; + } + g_sprintf(shared_memory, "%s", tizen_target_img_path); + INFO("shared memory key: %d, value: %s\n", base_port, (char *)shared_memory); + + if (shmdt(shared_memory) == -1) { + ERR("shmdt failed\n"); + perror("osutil-darwin: "); + } + + } + + void remove_vm_lock_os(void) + { + if (shmctl(g_shmid, IPC_RMID, 0) == -1) { + ERR("shmctl failed\n"); + perror("osutil-linux: "); + } + } + + void set_bin_path_os(char const *const exec_argv) + { + gchar *file_name = NULL; + + if (!exec_argv) { + return; + } + + char *data = g_strdup(exec_argv); + if (!data) { + ERR("Fail to strdup for paring a binary directory.\n"); + return; + } + + file_name = g_strrstr(data, "/"); + if (!file_name) { + free(data); + return; + } + + g_strlcpy(bin_path, data, strlen(data) - strlen(file_name) + 1); + + g_strlcat(bin_path, "/", PATH_MAX); + free(data); + } + + int get_number_of_processors(void) + { + int mib[2], sys_num = 0; + size_t len; + + mib[0] = CTL_HW; + mib[1] = HW_AVAILCPU; + + sysctl(mib, 2, &sys_num, &len, NULL, 0); + if (sys_num < 1) { + mib[1] = HW_NCPU; + sysctl(mib, 2, &sys_num, &len, NULL, 0); + + if (sys_num < 1) { + sys_num = 1; + } + } + INFO("* Number of processors : %d\n", sys_num); + + return sys_num; + } + + void print_system_info_os(void) + { + INFO("* Mac\n"); + + /* uname */ + INFO("* Host machine uname :\n"); + char const *const uname_cmd = "uname -a"; + if(system(uname_cmd) < 0) { + INFO("system function command '%s' \ + returns error !", uname_cmd); + } + + /* hw information */ + int mib[2]; + size_t len; + char *sys_info; + int sys_num = 0; + + mib[0] = CTL_HW; + mib[1] = HW_MODEL; + sysctl(mib, 2, NULL, &len, NULL, 0); + sys_info = malloc(len * sizeof(char)); + if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { + INFO("* Machine model : %s\n", sys_info); + } + free(sys_info); + + mib[0] = CTL_HW; + mib[1] = HW_MACHINE; + sysctl(mib, 2, NULL, &len, NULL, 0); + sys_info = malloc(len * sizeof(char)); + if (sysctl(mib, 2, sys_info, &len, NULL, 0) >= 0) { + INFO("* Machine class : %s\n", sys_info); + } + free(sys_info); + + #if 0 + mib[0] = CTL_HW; + mib[1] = HW_NCPU; + len = sizeof(sys_num); + if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { + INFO("* Number of processors : %d\n", sys_num); + } + #endif + get_number_of_processors(); + + mib[0] = CTL_HW; + mib[1] = HW_PHYSMEM; + len = sizeof(sys_num); + if (sysctl(mib, 2, &sys_num, &len, NULL, 0) >= 0) { + INFO("* Total memory : %llu bytes\n", sys_num); + } + + /* java version */ + INFO("* Java version :\n"); + char const *const lspci_cmd = "java -version"; + + fflush(stdout); + if(system(lspci_cmd) < 0) { + INFO("system function command '%s' \ + returns error !", lspci_cmd); + } + } + + static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + char type[DEFAULTBUFLEN]; + char proxy[DEFAULTBUFLEN]; + char line[DEFAULTBUFLEN]; + FILE *fp_pacfile; + char *p = NULL; + + CFStringRef pacURL = (CFStringRef)CFDictionaryGetValue(proxySettings, + kSCPropNetProxiesProxyAutoConfigURLString); + if (pacURL) { + char url[DEFAULTBUFLEN] = {}; + CFStringGetCString(pacURL, url, sizeof url, kCFStringEncodingASCII); + INFO("pac address: %s\n", (char*)url); + download_url(url); + } + + fp_pacfile = fopen(pac_tempfile, "r"); + if(fp_pacfile != NULL) { + while(fgets(line, DEFAULTBUFLEN, fp_pacfile) != NULL) { + if( (strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { + INFO("line found %s", line); + sscanf(line, "%*[^\"]\"%s %s", type, proxy); + } + } + + if(g_str_has_prefix(type, DIRECT)) { + INFO("auto proxy is set to direct mode\n"); + fclose(fp_pacfile); + } + else if(g_str_has_prefix(type, PROXY)) { + INFO("auto proxy is set to proxy mode\n"); + INFO("type: %s, proxy: %s\n", type, proxy); + p = strtok(proxy, "\";"); + if(p != NULL) { + INFO("auto proxy to set: %s\n",p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + fclose(fp_pacfile); + } + else + { + ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); + fclose(fp_pacfile); + } + } + else { + ERR("fail to get pacfile fp\n"); + return -1; + } + + remove(pac_tempfile); + return 0; + } + + static void get_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + char *hostname; + int port; + CFNumberRef isEnable; + CFStringRef proxyHostname; + CFNumberRef proxyPort; + CFDictionaryRef proxySettings; + proxySettings = SCDynamicStoreCopyProxies(NULL); + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(http_proxy, DEFAULTBUFLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("http proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesHTTPSPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(https_proxy, DEFAULTBUFLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("https proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesFTPPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(ftp_proxy, DEFAULTBUFLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("ftp proxy is null\n"); + } + + isEnable = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSEnable); + if (cfnumber_to_int(isEnable)) { + // Get proxy hostname + proxyHostname = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSProxy); + hostname = cfstring_to_cstring(proxyHostname); + // Get proxy port + proxyPort = CFDictionaryGetValue(proxySettings, kSCPropNetProxiesSOCKSPort); + port = cfnumber_to_int(proxyPort); + // Save hostname & port + snprintf(socks_proxy, DEFAULTBUFLEN, "%s:%d", hostname, port); + + free(hostname); + } else { + INFO("socks proxy is null\n"); + } + CFRelease(proxySettings); + } + + void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + int ret; + proxySettings = SCDynamicStoreCopyProxies(NULL); + if(proxySettings) { + INFO("AUTO PROXY MODE\n"); + ret = get_auto_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + if(strlen(http_proxy) == 0 && ret < 0) { + INFO("MANUAL PROXY MODE\n"); + get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + } + } + + bool make_sdcard_lock_os(char *sdcard) + { - return make_sdcard_lock(sdcard); ++ return make_sdcard_lock_posix(sdcard); + } + + int remove_sdcard_lock_os(char *sdcard) + { - return remove_sdcard_lock(sdcard); ++ return remove_sdcard_lock_posix(sdcard); + } diff --cc tizen/src/util/osutil-linux.c index 0000000000,2cd47b1f37..a84379c791 mode 000000,100644..100644 --- a/tizen/src/util/osutil-linux.c +++ b/tizen/src/util/osutil-linux.c @@@ -1,0 -1,669 +1,670 @@@ + /* + * Emulator + * + * Copyright (C) 2012 - 2014 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + /** + @file osutil-linux.c + @brief Collection of utilities for linux + */ + + #include + #include "osutil.h" + #include "emulator.h" + #include "emul_state.h" + #include "debug_ch.h" + #include "maru_err_table.h" + #include "sdb.h" + + #ifndef CONFIG_LINUX + #error + #endif + #include + #include + #include + #include + #include + #include + #include + #ifdef CONFIG_SPICE + #include + #endif + + MULTI_DEBUG_CHANNEL(emulator, osutil); + + static int g_shmid; + static char *g_shared_memory; + static int gproxytool = GSETTINGS; + + extern char tizen_target_img_path[]; + + /* Getting proxy commands */ + static const char* gproxycmds[][2] = { + { "gconftool-2 -g /system/proxy/mode" , "gsettings get org.gnome.system.proxy mode" }, + { "gconftool-2 -g /system/proxy/autoconfig_url", "gsettings get org.gnome.system.proxy autoconfig-url" }, + { "gconftool-2 -g /system/http_proxy/host", "gsettings get org.gnome.system.proxy.http host" }, + { "gconftool-2 -g /system/http_proxy/port", "gsettings get org.gnome.system.proxy.http port"}, + { "gconftool-2 -g /system/proxy/secure_host", "gsettings get org.gnome.system.proxy.https host" }, + { "gconftool-2 -g /system/proxy/secure_port", "gsettings get org.gnome.system.proxy.https port" }, + { "gconftool-2 -g /system/proxy/ftp_host", "gsettings get org.gnome.system.proxy.ftp host" }, + { "gconftool-2 -g /system/proxy/ftp_port", "gsettings get org.gnome.system.proxy.ftp port" }, + { "gconftool-2 -g /system/proxy/socks_host", "gsettings get org.gnome.system.proxy.socks host" }, + { "gconftool-2 -g /system/proxy/socks_port", "gsettings get org.gnome.system.proxy.socks port" }, + }; + + void check_vm_lock_os(void) + { + int shm_id; + void *shm_addr; + uint32_t port; + int val; + struct shmid_ds shm_info; + + for (port = 26100; port < 26200; port += 10) { + shm_id = shmget((key_t)port, 0, 0); + if (shm_id != -1) { + shm_addr = shmat(shm_id, (void *)0, 0); + if ((void *)-1 == shm_addr) { + ERR("error occured at shmat()\n"); + break; + } + + val = shmctl(shm_id, IPC_STAT, &shm_info); + if (val != -1) { + INFO("count of process that use shared memory : %d\n", + shm_info.shm_nattch); + if ((shm_info.shm_nattch > 0) && + g_strcmp0(tizen_target_img_path, (char *)shm_addr) == 0) { + if (check_port_bind_listen(port + 1) > 0) { + shmdt(shm_addr); + continue; + } + shmdt(shm_addr); + maru_register_exit_msg(MARU_EXIT_UNKNOWN, + "Can not execute this VM.\n" + "The same name is running now."); + exit(0); + } else { + shmdt(shm_addr); + } + } + } + } + } + + void make_vm_lock_os(void) + { + int base_port; + + base_port = get_emul_vm_base_port(); + + g_shmid = shmget((key_t)base_port, getpagesize(), 0666|IPC_CREAT); + if (g_shmid == -1) { + ERR("shmget failed\n"); + perror("osutil-linux: "); + return; + } + + g_shared_memory = shmat(g_shmid, (char *)0x00, 0); + if (g_shared_memory == (void *)-1) { + ERR("shmat failed\n"); + perror("osutil-linux: "); + return; + } + + g_sprintf(g_shared_memory, "%s", tizen_target_img_path); + INFO("shared memory key: %d value: %s\n", + base_port, (char *)g_shared_memory); + + if (shmdt(g_shared_memory) == -1) { + ERR("shmdt failed\n"); + perror("osutil-linux: "); + } + } + + void remove_vm_lock_os(void) + { + if (shmctl(g_shmid, IPC_RMID, 0) == -1) { + ERR("shmctl failed\n"); + perror("osutil-linux: "); + } + } + + void set_bin_path_os(char const *const exec_argv) + { + gchar link_path[PATH_MAX] = { 0, }; + char *file_name = NULL; + + ssize_t len = readlink("/proc/self/exe", link_path, sizeof(link_path) - 1); + + if (len < 0 || len > (sizeof(link_path) - 1)) { + perror("set_bin_path error : "); + return; + } + + link_path[len] = '\0'; + + file_name = g_strrstr(link_path, "/"); + g_strlcpy(bin_path, link_path, strlen(link_path) - strlen(file_name) + 1); + + g_strlcat(bin_path, "/", PATH_MAX); + + #ifdef CONFIG_SPICE + g_strlcpy(remote_bin_path, link_path, strlen(link_path) - strlen(file_name) - 2); + g_strlcat(remote_bin_path, "remote/bin/", PATH_MAX); + #endif + } + + int get_number_of_processors(void) + { + int num_processors = 0; + + num_processors = sysconf(_SC_NPROCESSORS_ONLN); + if (num_processors < 1) { + num_processors = 1; + } + TRACE("Number of processors : %d\n", num_processors); + + return num_processors; + } + + void print_system_info_os(void) + { + INFO("* Linux\n"); + + INFO("* LibPNG Version : %s\n", PNG_LIBPNG_VER_STRING); + + /* depends on building */ + INFO("* QEMU build machine linux kernel version : (%d, %d, %d)\n", + LINUX_VERSION_CODE >> 16, + (LINUX_VERSION_CODE >> 8) & 0xff, + LINUX_VERSION_CODE & 0xff); + + /* depends on launching */ + struct utsname host_uname_buf; + if (uname(&host_uname_buf) == 0) { + INFO("* Host machine uname : %s %s %s %s %s\n", + host_uname_buf.sysname, host_uname_buf.nodename, + host_uname_buf.release, host_uname_buf.version, + host_uname_buf.machine); + } + + struct sysinfo sys_info; + if (sysinfo(&sys_info) == 0) { + INFO("* Total Ram : %llu kB, Free: %llu kB\n", + sys_info.totalram * (unsigned long long)sys_info.mem_unit / 1024, + sys_info.freeram * (unsigned long long)sys_info.mem_unit / 1024); + } + + /* get linux distribution information */ + INFO("* Linux distribution infomation :\n"); + char const *const lsb_release_cmd = "lsb_release -d -r -c"; + gchar *buffer = NULL; + gint buffer_size = strlen(lsb_release_cmd) + 1; + + buffer = g_malloc(buffer_size); + + g_snprintf(buffer, buffer_size, "%s", lsb_release_cmd); + + if (system(buffer) < 0) { + INFO("system function command '%s' \ + returns error !", buffer); + } + g_free(buffer); + + /* pci device description */ + INFO("* Host PCI devices :\n"); + char const *const lspci_cmd = "lspci"; + buffer_size = strlen(lspci_cmd) + 1; + + buffer = g_malloc(buffer_size); + + g_snprintf(buffer, buffer_size, "%s", lspci_cmd); + + fflush(stdout); + if (system(buffer) < 0) { + INFO("system function command '%s' \ + returns error !", buffer); + } + g_free(buffer); + } + + static void process_string(char *buf) + { + char tmp_buf[DEFAULTBUFLEN]; + + /* remove single quotes of strings gotten by gsettings */ + if (gproxytool == GSETTINGS) { + remove_string(buf, tmp_buf, "\'"); + memset(buf, 0, DEFAULTBUFLEN); + strncpy(buf, tmp_buf, strlen(tmp_buf)-1); + } + } + + static int get_auto_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + char type[DEFAULTBUFLEN]; + char proxy[DEFAULTBUFLEN]; + char line[DEFAULTBUFLEN]; + FILE *fp_pacfile; + char *p = NULL; + FILE *output; + char buf[DEFAULTBUFLEN]; + + output = popen(gproxycmds[GNOME_PROXY_AUTOCONFIG_URL][gproxytool], "r"); + if (fscanf(output, "%s", buf) > 0) { + process_string(buf); + INFO("pac address: %s\n", buf); + download_url(buf); + } + + pclose(output); + fp_pacfile = fopen(pac_tempfile, "r"); + if (fp_pacfile != NULL) { + while (fgets(line, DEFAULTBUFLEN, fp_pacfile) != NULL) { + if ((strstr(line, "return") != NULL) && (strstr(line, "if") == NULL)) { + INFO("line found %s", line); + sscanf(line, "%*[^\"]\"%s %s", type, proxy); + } + } + + if (g_str_has_prefix(type, DIRECT)) { + INFO("auto proxy is set to direct mode\n"); + fclose(fp_pacfile); + } else if (g_str_has_prefix(type, PROXY)) { + INFO("auto proxy is set to proxy mode\n"); + INFO("type: %s, proxy: %s\n", type, proxy); + + p = strtok(proxy, "\";"); + if (p != NULL) { + INFO("auto proxy to set: %s\n",p); + strcpy(http_proxy, p); + strcpy(https_proxy, p); + strcpy(ftp_proxy, p); + strcpy(socks_proxy, p); + } + fclose(fp_pacfile); + } else { + ERR("pac file is not wrong! It could be the wrong pac address or pac file format\n"); + fclose(fp_pacfile); + } + } else { + ERR("fail to get pacfile fp\n"); + return -1; + } + + if (remove(pac_tempfile) < 0) { + WARN("fail to remove the temporary pacfile\n"); + } + + return 0; + } + + static void get_proxy(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + char buf[DEFAULTBUFLEN] = {0,}; + char buf_port[MAXPORTLEN] = {0,}; + char buf_proxy[DEFAULTBUFLEN] = {0,}; + char *buf_proxy_bak; + char *proxy; + FILE *output; + int MAXPROXYLEN = DEFAULTBUFLEN + MAXPORTLEN; + + output = popen(gproxycmds[GNOME_PROXY_HTTP_HOST][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + process_string(buf); + snprintf(buf_proxy, DEFAULTBUFLEN, "%s", buf); + } + pclose(output); + + output = popen(gproxycmds[GNOME_PROXY_HTTP_PORT][gproxytool], "r"); + if(fscanf(output, "%s", buf_port) <= 0) { + //for abnormal case: if can't find the key of http port, get from environment value. + buf_proxy_bak = getenv("http_proxy"); + INFO("http_proxy from env: %s\n", buf_proxy_bak); + if(buf_proxy_bak != NULL) { + proxy = malloc(DEFAULTBUFLEN); + remove_string(buf_proxy_bak, proxy, HTTP_PREFIX); + strncpy(http_proxy, proxy, strlen(proxy)-1); + INFO("final http_proxy value: %s\n", http_proxy); + free(proxy); + } + else { + INFO("http_proxy is not set on env.\n"); + pclose(output); + return; + } + + } + else { + snprintf(http_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf_port); + memset(buf_proxy, 0, DEFAULTBUFLEN); + INFO("http_proxy: %s\n", http_proxy); + } + pclose(output); + + memset(buf, 0, DEFAULTBUFLEN); + + output = popen(gproxycmds[GNOME_PROXY_HTTPS_HOST][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + process_string(buf); + snprintf(buf_proxy, DEFAULTBUFLEN, "%s", buf); + } + pclose(output); + + output = popen(gproxycmds[GNOME_PROXY_HTTPS_PORT][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(https_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + memset(buf, 0, DEFAULTBUFLEN); + memset(buf_proxy, 0, DEFAULTBUFLEN); + INFO("https_proxy : %s\n", https_proxy); + + output = popen(gproxycmds[GNOME_PROXY_FTP_HOST][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + process_string(buf); + snprintf(buf_proxy, DEFAULTBUFLEN, "%s", buf); + } + pclose(output); + + output = popen(gproxycmds[GNOME_PROXY_FTP_PORT][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(ftp_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + memset(buf, 0, DEFAULTBUFLEN); + memset(buf_proxy, 0, DEFAULTBUFLEN); + INFO("ftp_proxy : %s\n", ftp_proxy); + + output = popen(gproxycmds[GNOME_PROXY_SOCKS_HOST][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + process_string(buf); + snprintf(buf_proxy, DEFAULTBUFLEN, "%s", buf); + } + pclose(output); + + output = popen(gproxycmds[GNOME_PROXY_SOCKS_PORT][gproxytool], "r"); + if(fscanf(output, "%s", buf) > 0) { + snprintf(socks_proxy, MAXPROXYLEN, "%s:%s", buf_proxy, buf); + } + pclose(output); + INFO("socks_proxy : %s\n", socks_proxy); + } + + + void get_host_proxy_os(char *http_proxy, char *https_proxy, char *ftp_proxy, char *socks_proxy) + { + char buf[DEFAULTBUFLEN]; + FILE *output; + int ret; + + output = popen(gproxycmds[GNOME_PROXY_MODE][gproxytool], "r"); + ret = fscanf(output, "%s", buf); + if (ret <= 0) { + pclose(output); + INFO("Try to use gsettings to get proxy\n"); + gproxytool = GSETTINGS; + output = popen(gproxycmds[GNOME_PROXY_MODE][gproxytool], "r"); + ret = fscanf(output, "%s", buf); + } + if (ret > 0) { + process_string(buf); + //priority : auto > manual > none + if (strcmp(buf, "auto") == 0) { + INFO("AUTO PROXY MODE\n"); + get_auto_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + else if (strcmp(buf, "manual") == 0) { + INFO("MANUAL PROXY MODE\n"); + get_proxy(http_proxy, https_proxy, ftp_proxy, socks_proxy); + } + else if (strcmp(buf, "none") == 0) { + INFO("DIRECT PROXY MODE\n"); + } + } + pclose(output); + } + + #ifdef CONFIG_SPICE + #define PID_MAX_COUNT 256 + const char *execution_file_websocket = "websockify.py"; + const char *execution_file_node = "node"; + const char *node_proc_name = "emulator-x86-web"; + + void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount) + { + char cmdline[2048], dir_name[255]; + int total_len = 0, current_len = 0; + struct dirent *dir_entry_p; + DIR *dir_p; + FILE *fp; + char *mptr; + + dir_p = opendir("/proc/"); + while (NULL != (dir_entry_p = readdir(dir_p))) { + /* Checking for numbered directories */ + if (strspn(dir_entry_p->d_name, "0123456789") == strlen(dir_entry_p->d_name)) { + strcpy(dir_name, "/proc/"); + strcat(dir_name, dir_entry_p->d_name); + strcat(dir_name, "/cmdline"); + + fp = fopen(dir_name, "rb"); + if (fp == NULL) { + continue; + } + + total_len = 0; + memset(cmdline, 0, sizeof(cmdline)); + while (!feof(fp)) { + cmdline[total_len++] = fgetc(fp); + } + + fclose(fp); + current_len = strlen(cmdline); + mptr = cmdline; + do { + if (strstr(mptr, process_name) != NULL) { + if (!first_param || strstr(&cmdline[current_len + 1], first_param) != NULL) { + if (sizeof(pid) < *pscount + 1) { + WARN("PID array size is not enough.\n"); + return; + } + pid[*pscount] = atoi(dir_entry_p->d_name); + INFO("get_process_id(%s %s) :Found. id = %d\n", process_name, first_param, pid[*pscount]); + (*pscount)++; + } + break; + } + + mptr = &cmdline[current_len + 1]; + current_len += strlen(mptr) + 1; + } while (current_len < total_len); + } + } + + closedir(dir_p); + if (*pscount == 0) { + INFO("get_process_id(%s %s) : id = 0 (could not find process)\n", process_name, first_param); + } + } + + void execute_websocket(int port) + { + char const *remote_bin_dir = get_remote_bin_path(); + char const *relative_path = "../websocket/"; + char websocket_path[strlen(remote_bin_dir) + strlen(execution_file_websocket) + strlen(relative_path) + 1]; + int ret = -1; + char local_port[32]; + char websocket_port[16]; + + memset(websocket_port, 0, sizeof(websocket_port)); + sprintf(websocket_port, "%d", port); + + memset(local_port, 0, sizeof(local_port)); + sprintf(local_port, "localhost:%d", get_emul_spice_port()); + + memset(websocket_path, 0, sizeof(websocket_path)); + sprintf(websocket_path, "%s%s%s", remote_bin_dir, relative_path, execution_file_websocket); + + INFO("Exec [%s %s %s]\n", websocket_path, websocket_port, local_port); + + ret = execl(websocket_path, execution_file_websocket, websocket_port, local_port, (char *)0); + if (ret == 127) { + WARN("Can't execute websocket.\n"); + } else if (ret == -1) { + WARN("Fork error!\n"); + } + } + + void execute_nodejs(void) + { + char const *remote_bin_dir = get_remote_bin_path(); + char const *relative_path = "../web-viewer/bin/emul"; + char webviewer_script[strlen(remote_bin_dir) + strlen(relative_path) + 1]; + char nodejs_path[strlen(remote_bin_dir) + strlen(execution_file_node) + 1]; + int ret = -1; + + memset(webviewer_script, 0, sizeof(webviewer_script)); + sprintf(webviewer_script, "%s%s", remote_bin_dir, relative_path); + + memset(nodejs_path, 0, sizeof(nodejs_path)); + sprintf(nodejs_path, "%s%s", remote_bin_dir, execution_file_node); + + INFO("Exec [%s %s]\n", nodejs_path, webviewer_script); + + ret = execl(nodejs_path, execution_file_node, webviewer_script, (char *)0); + if (ret == 127) { + WARN("Can't execute node server.\n"); + } else if (ret == -1) { + WARN("Fork error!\n"); + } + } + + void clean_websocket_port(int signal) + { + char websocket_port[16]; + memset(websocket_port, 0, sizeof(websocket_port)); + sprintf(websocket_port, "%d", get_emul_websocket_port()); + + int pscount = 0, i = 0; + int pid[PID_MAX_COUNT]; + + memset(pid, 0, PID_MAX_COUNT); + get_process_id(execution_file_websocket, websocket_port, pid, &pscount); + if (pscount > 0) { + for (i = 0; i < pscount; i++) { + INFO("Will be killed PID: %d\n", pid[i]); + kill(pid[i], signal); + } + } + } + + static void websocket_notify_exit(Notifier *notifier, void *data) + { + clean_websocket_port(SIGTERM); + } + + static void nodejs_notify_exit(Notifier *notifier, void *data) + { + int pscount = 0, i = 0; + int pid[PID_MAX_COUNT]; + + memset(pid, 0, sizeof(pid)); + get_process_id("spicevmc", NULL, pid, &pscount); + if (pscount == 1) { + INFO("Detected the last spice emulator.\n"); + pid[0] = 0; + pscount = 0; + get_process_id(node_proc_name, NULL, pid, &pscount); + for (i = 0; i < pscount; i++) { + INFO("Will be killed %s, PID: %d\n", node_proc_name, pid[i]); + kill(pid[i], SIGTERM); + } + } + } + + static Notifier websocket_exit = { .notify = websocket_notify_exit }; + static Notifier nodejs_exit = { .notify = nodejs_notify_exit }; + + void websocket_init(void) + { + int pscount = 0; + char websocket_port[16]; + int pid[PID_MAX_COUNT]; + + memset(websocket_port, 0, sizeof(websocket_port)); + sprintf(websocket_port, "%d", get_emul_websocket_port()); + + memset(pid, 0, sizeof(pid)); + get_process_id(execution_file_websocket, websocket_port, pid, &pscount); + emulator_add_exit_notifier(&websocket_exit); + + if (pscount == 0) { + int pid = fork(); + if (pid == 0) { + setsid(); + execute_websocket(get_emul_websocket_port()); + } + } else { + INFO("Aleady running websokify %s localhost:%d\n", websocket_port, get_emul_spice_port()); + } + } + + void nodejs_init(void) + { + int pscount = 0; + int pid[PID_MAX_COUNT]; + + memset(pid, 0, sizeof(pid)); + get_process_id(node_proc_name, NULL, pid, &pscount); + emulator_add_exit_notifier(&nodejs_exit); + + if (pscount == 0) { + int pid = fork(); + if (pid == 0) { + setsid(); + execute_nodejs(); + } + } else { + INFO("Aleady running node server.\n"); + } + } + #endif ++ + bool make_sdcard_lock_os(char *sdcard) + { - return make_sdcard_lock(sdcard); ++ return make_sdcard_lock_posix(sdcard); + } + + + int remove_sdcard_lock_os(char *sdcard) + { - return remove_sdcard_lock(sdcard); ++ return remove_sdcard_lock_posix(sdcard); + } diff --cc tizen/src/util/osutil.c index 0000000000,a4d01df83d..f2aa90e80a mode 000000,100644..100644 --- a/tizen/src/util/osutil.c +++ b/tizen/src/util/osutil.c @@@ -1,0 -1,183 +1,183 @@@ + /* + * Emulator + * + * Copyright (C) 2012, 2013 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + /** + @file osutil.c + @brief Common functions for osutil + */ + + #include "osutil.h" + #include "debug_ch.h" + + #include + #include + + MULTI_DEBUG_CHANNEL(emulator, osutil); + + + const char *pac_tempfile = ".autoproxy"; + #ifndef CONFIG_WIN32 + static int g_fd; + #endif + inline size_t write_data(void *ptr, size_t size, size_t nmemb, FILE *stream) + { + size_t written; + written = fwrite(ptr, size, nmemb, stream); + return written; + } + + void download_url(char *url) + { + CURL *curl; + FILE *fp; + CURLcode res; + + curl = curl_easy_init(); + if (curl) { + fp = fopen(pac_tempfile, "wb"); + if(fp == NULL) { + ERR("failed to fopen(): %s\n", pac_tempfile); + return; + } + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data); + /* just in case network does not work */ + curl_easy_setopt(curl, CURLOPT_TIMEOUT_MS, 3000); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp); + + res = curl_easy_perform(curl); + if (res != 0) { + ERR("Fail to download pac file: %s\n", url); + } + + curl_easy_cleanup(curl); + fclose(fp); + } + + return; + } + + inline void remove_string(char *src, char *dst, const char *toremove) + { + int len = strlen(toremove); + int i, j; + int max_len = strlen(src); + + for(i = len, j = 0; i < max_len; i++) + { + dst[j++] = src[i]; + } + + dst[j] = '\0'; + } + + #ifndef CONFIG_WIN32 + static int fd_lock(int fd) + { + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + lock.l_pid = getpid(); + + return fcntl(fd, F_SETLK, &lock); + } + + static int fd_unlock(int fd) + { + struct flock lock; + + lock.l_type = F_UNLCK; + lock.l_start = 0; + lock.l_whence = SEEK_SET; + lock.l_len = 0; + + return fcntl(fd, F_SETLK, &lock); + } + -inline bool make_sdcard_lock(char *sdcard) ++inline bool make_sdcard_lock_posix(char *sdcard) + { + char *lock_file = g_strdup_printf("%s.lck", sdcard); + int fd = open(lock_file, O_CREAT|O_RDWR, 0666); + if (fd == -1) + { + perror("file open error : "); + return false; + } + if (fd_lock(fd) == -1) + { + perror("file is lock "); + close(fd); + return false; + } + + INFO("Get file lock: %s\n", lock_file); + g_fd = fd; + close(fd); + return true; + + } + -inline int remove_sdcard_lock(char *sdcard) ++inline int remove_sdcard_lock_posix(char *sdcard) + { + errno = 0; + char *lock_file = g_strdup_printf("%s.lck", sdcard); + int fd = open(lock_file, O_RDWR, 0666); + if (fd == -1) + { + perror("file open error : "); + if(errno == ENOENT) { + return ERR_NOENT; + } + return ERR_UNLCK; + } + + if (fd_unlock(fd) == -1) + { + perror("file unlock error "); + close(fd); + return ERR_UNLCK; + } + + if (unlink(lock_file) < 0) { + perror("unlink error "); + close(fd); + return ERR_UNLCK; + } + + INFO("unlock success: %s\n", lock_file); + close(fd); + close(g_fd); + return ERR_SUCCESS; + } + #endif diff --cc tizen/src/util/osutil.h index 0000000000,ab4f7d5a14..8e4de94137 mode 000000,100644..100644 --- a/tizen/src/util/osutil.h +++ b/tizen/src/util/osutil.h @@@ -1,0 -1,116 +1,116 @@@ + /* + * Emulator + * + * Copyright (C) 2011, 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * SeokYeon Hwang + * MunKyu Im + * GiWoong Kim + * YeongKyoon Lee + * HyunJun Son + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + + #ifndef __OSUTIL_H__ + #define __OSUTIL_H__ + + #include "qemu-common.h" + + #define HTTP_PROTOCOL "http=" + #define HTTP_PREFIX "http://" + #define HTTPS_PROTOCOL "https=" + #define FTP_PROTOCOL "ftp=" + #define SOCKS_PROTOCOL "socks=" + #define DIRECT "DIRECT" + #define PROXY "PROXY" + #define MAXPORTLEN 6 + #define DEFAULTBUFLEN 512 + + #define GNOME_PROXY_MODE 0 + #define GNOME_PROXY_AUTOCONFIG_URL 1 + #define GNOME_PROXY_HTTP_HOST 2 + #define GNOME_PROXY_HTTP_PORT 3 + #define GNOME_PROXY_HTTPS_HOST 4 + #define GNOME_PROXY_HTTPS_PORT 5 + #define GNOME_PROXY_FTP_HOST 6 + #define GNOME_PROXY_FTP_PORT 7 + #define GNOME_PROXY_SOCKS_HOST 8 + #define GNOME_PROXY_SOCKS_PORT 9 + #define GCONFTOOL 0 + #define GSETTINGS 1 + + #define ERR_SUCCESS 0 + #define ERR_UNLCK 4 + #define ERR_LCK 5 + #define ERR_NOENT 6 + + extern const char *pac_tempfile; + + void check_vm_lock_os(void); + void make_vm_lock_os(void); + void remove_vm_lock_os(void); + bool make_sdcard_lock_os(char *sdcard); + int remove_sdcard_lock_os(char *sdcard); + + void set_bin_path_os(char const *const); + #ifndef CONFIG_WIN32 -bool make_sdcard_lock(char *sdcard); -int remove_sdcard_lock(char *sdcard); ++bool make_sdcard_lock_posix(char *sdcard); ++int remove_sdcard_lock_posix(char *sdcard); + #endif + + void print_system_info_os(void); + + void get_host_proxy_os(char *, char *, char *, char *); + + void download_url(char *); + size_t write_data(void *, size_t, size_t, FILE *); + void remove_string(char *, char *, const char *); + + #if defined(CONFIG_SPICE) && defined(CONFIG_LINUX) + void get_process_id(char const *process_name, char *first_param, int *pid, int *pscount); + void execute_websocket(int port); + void execute_nodejs(void); + void clean_websocket_port(int signal); + void nodejs_init(void); + void websocket_init(void); + #endif + + static inline int get_timeofday(char *buf, size_t size) + { + qemu_timeval tv; + time_t ti; + struct tm *ptm = NULL; + int ret; + + qemu_gettimeofday(&tv); + ti = tv.tv_sec; + + /* In this case, localtime_r() function is not necessary. */ + ptm = localtime(&ti); + ret = strftime(buf, size, "%H:%M:%S", ptm); + + return ret + g_snprintf(buf + ret, size - ret, ".%06ld", (long)tv.tv_usec); + } + + int get_number_of_processors(void); + + #endif // __OS_UTIL_H__ +