1 /* Emulator Control Server
3 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
6 * Jinhyung choi <jinhyung2.choi@samsung.com>
7 * MunKyu Im <munkyu.im@samsung.com>
8 * Daiyoung Kim <daiyoung777.kim@samsung.com>
9 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
30 #include "qemu-common.h"
32 #include "hw/virtio/maru_virtio_vmodem.h"
33 #include "hw/virtio/maru_virtio_evdi.h"
34 #include "hw/virtio/maru_virtio_jack.h"
35 #include "hw/virtio/maru_virtio_power.h"
37 #include "util/maru_device_hotplug.h"
38 #include "emul_state.h"
41 #include "util/osutil.h"
43 MULTI_DEBUG_CHANNEL(qemu, ecs);
45 extern QemuMutex mutex_guest_connection;
46 static int guest_connection = 0;
48 extern QemuMutex mutex_location_data;
49 static char location_data[MAX_INJECTOR_REQ_DATA];
50 static void send_gen_injector_ntf(const char* cmd, int cmdlen, int grp, int act, char* on)
52 int msglen = 0, datalen = 0;
53 type_length length = 0;
54 type_group group = grp;
55 type_action action = act;
57 if (cmd == NULL || cmdlen > 10)
64 length = (unsigned short)datalen;
66 msglen = datalen + 15;
69 char* status_msg = (char*) malloc(msglen);
73 memset(status_msg, 0, msglen);
75 memcpy(status_msg, cmd, cmdlen);
76 memcpy(status_msg + 10, &length, sizeof(unsigned short));
77 memcpy(status_msg + 12, &group, sizeof(unsigned char));
78 memcpy(status_msg + 13, &action, sizeof(unsigned char));
81 memcpy(status_msg + 14, on, datalen);
84 send_injector_ntf(status_msg, msglen);
89 static void msgproc_injector_ans(ECS_Client* ccli, const char* category, bool succeed)
95 ECS__Master master = ECS__MASTER__INIT;
96 ECS__InjectorAns ans = ECS__INJECTOR_ANS__INIT;
98 TRACE("injector ans - category : %s, succed : %d\n", category, succeed);
100 catlen = strlen(category);
101 ans.category = (char*) g_malloc0(catlen + 1);
102 memcpy(ans.category, category, catlen);
104 ans.errcode = !succeed;
105 master.type = ECS__MASTER__TYPE__INJECTOR_ANS;
106 master.injector_ans = &ans;
108 pb_to_all_clients(&master);
111 g_free(ans.category);
114 static bool injector_send(ECS_Client* ccli, ECS__InjectorReq* msg, char* cmd)
116 int sndlen = 15; // HEADER(CMD + LENGTH + GROUP + ACTION) + 1
117 const char* msg_data;
122 group = (type_group) (msg->group & 0xff);
124 if (msg->has_data && msg->data.data && msg->data.len > 0)
125 sndlen += msg->data.len;
127 sndbuf = (char*) g_malloc0(sndlen);
129 msgproc_injector_ans(ccli, cmd, false);
133 memcpy(sndbuf, cmd, 10);
134 memcpy(sndbuf + 10, &msg->length, 2);
135 memcpy(sndbuf + 12, &msg->group, 1);
136 memcpy(sndbuf + 13, &msg->action, 1);
138 if (msg->has_data && msg->data.data && msg->data.len > 0) {
139 msg_data = (const char*)msg->data.data;
140 memcpy(sndbuf + 14, msg_data, msg->data.len);
141 TRACE(">> print len = %zd, data\" %s\"\n", msg->data.len, msg_data);
144 if(strcmp(cmd, "telephony") == 0) {
145 TRACE("telephony msg >>");
146 ret = send_to_vmodem(route_ij, sndbuf, sndlen);
148 TRACE("evdi msg >> %s", cmd);
149 ret = send_to_evdi(route_ij, sndbuf, sndlen);
154 if (group != MSG_GROUP_STATUS) {
155 msgproc_injector_ans(ccli, cmd, ret);
165 static char* get_emulator_sdcard_path(void)
167 char *emulator_sdcard_path = NULL;
168 char *tizen_sdk_data = NULL;
171 char emulator_sdcard[] = "/emulator/sdcard/";
173 char emulator_sdcard[] = "\\emulator\\sdcard\\";
176 TRACE("emulator_sdcard: %s, %zu\n", emulator_sdcard, sizeof(emulator_sdcard));
178 tizen_sdk_data = get_tizen_sdk_data_path();
179 if (!tizen_sdk_data) {
180 ERR("failed to get tizen-sdk-data path.\n");
184 emulator_sdcard_path =
185 g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_sdcard) + 1);
186 if (!emulator_sdcard_path) {
187 ERR("failed to allocate memory.\n");
191 g_snprintf(emulator_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_sdcard),
192 "%s%s", tizen_sdk_data, emulator_sdcard);
194 g_free(tizen_sdk_data);
196 TRACE("sdcard path: %s\n", emulator_sdcard_path);
197 return emulator_sdcard_path;
200 static char *get_old_tizen_sdk_data_path(void)
202 char *tizen_sdk_data_path = NULL;
204 INFO("try to search tizen-sdk-data path in another way.\n");
207 char tizen_sdk_data[] = "/tizen-sdk-data";
208 int tizen_sdk_data_len = 0;
211 home_dir = (char *)g_getenv("HOME");
213 home_dir = (char *)g_get_home_dir();
216 tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1;
217 tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
218 if (!tizen_sdk_data_path) {
219 ERR("failed to allocate memory.\n");
222 g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len);
223 g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
226 char tizen_sdk_data[] = "\\tizen-sdk-data\\";
227 gint tizen_sdk_data_len = 0;
229 char strLocalAppDataPath[1024] = { 0 };
230 DWORD dwBufLen = 1024;
232 RegOpenKeyEx(HKEY_CURRENT_USER,
233 "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
234 0, KEY_QUERY_VALUE, &hKey);
236 RegQueryValueEx(hKey, "Local AppData", NULL,
237 NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen);
240 tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1;
241 tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
242 if (!tizen_sdk_data_path) {
243 ERR("failed to allocate memory.\n");
247 g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len);
248 g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
251 INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
252 return tizen_sdk_data_path;
256 * get tizen-sdk-data path from sdk.info.
258 char *get_tizen_sdk_data_path(void)
260 char const *emul_bin_path = NULL;
261 char *sdk_info_file_path = NULL;
262 char *tizen_sdk_data_path = NULL;
264 const char *sdk_info = "../../../sdk.info";
266 const char *sdk_info = "..\\..\\..\\sdk.info";
268 const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH";
270 FILE *sdk_info_fp = NULL;
271 int sdk_info_path_len = 0;
273 TRACE("%s\n", __func__);
275 emul_bin_path = get_bin_path();
276 if (!emul_bin_path) {
277 ERR("failed to get emulator path.\n");
281 sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1;
282 sdk_info_file_path = g_malloc(sdk_info_path_len);
283 if (!sdk_info_file_path) {
284 ERR("failed to allocate sdk-data buffer.\n");
288 g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s",
289 emul_bin_path, sdk_info);
290 INFO("sdk.info path: %s\n", sdk_info_file_path);
292 sdk_info_fp = fopen(sdk_info_file_path, "r");
293 g_free(sdk_info_file_path);
296 TRACE("Succeeded to open [sdk.info].\n");
298 char tmp[256] = { '\0', };
299 char *tmpline = NULL;
300 while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) {
301 if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) {
302 tmpline += strlen(sdk_data_var) + 1; // 1 for '='
308 if (tmpline[strlen(tmpline) - 1] == '\n') {
309 tmpline[strlen(tmpline) - 1] = '\0';
311 if (tmpline[strlen(tmpline) - 1] == '\r') {
312 tmpline[strlen(tmpline) - 1] = '\0';
315 tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1);
316 g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1);
318 INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
321 return tizen_sdk_data_path;
328 ERR("Failed to open [sdk.info].\n");
330 return get_old_tizen_sdk_data_path();
333 static char* get_sdcard_img_path(char* sdcard_img_name, size_t dataLen) {
334 char* sdcard_img_path = NULL;
335 char* sdcard_path = NULL;
336 if (sdcard_img_name == NULL || dataLen < 3) {
339 dataLen = dataLen - 3;
340 if (sdcard_img_name[dataLen] == '\n') {
341 sdcard_img_name[dataLen] = '\0';
342 TRACE("sdcard_img_name: %s\n", sdcard_img_name);
344 ERR("wrong sdcard message!\n");
348 sdcard_path = get_emulator_sdcard_path();
349 if (sdcard_path != NULL) {
350 sdcard_img_path = g_malloc(DEFAULTBUFLEN);
351 g_strlcpy(sdcard_img_path, sdcard_path, DEFAULTBUFLEN);
352 g_strlcat(sdcard_img_path, sdcard_img_name, DEFAULTBUFLEN);
353 TRACE("sdcard img path: [%s] length: %d\n", sdcard_img_path, strlen(sdcard_img_path));
355 return sdcard_img_path;
360 static int handle_sdcard(char* dataBuf, size_t dataLen)
364 if (dataBuf != NULL){
369 INFO("datalen: %d\n", dataLen);
370 char* sdcard_img_path = get_sdcard_img_path(dataBuf + 2, dataLen);
371 err_no = remove_sdcard_lock_os(sdcard_img_path);
372 if (errno == 0 && is_sdcard_attached()) {
373 do_hotplug(DETACH_SDCARD, NULL, 0);
375 ERR("failed to umount: %s\n", sdcard_img_path);
376 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, err_no, NULL);
379 g_free(sdcard_img_path);
380 } else if (ret == '1') {
382 INFO("datalen: %d\n", dataLen);
383 char* sdcard_img_path = get_sdcard_img_path(dataBuf + 2, dataLen);
384 if ( !is_sdcard_attached() && make_sdcard_lock_os(sdcard_img_path)) {
385 do_hotplug(ATTACH_SDCARD, sdcard_img_path, strlen(sdcard_img_path) + 1);
386 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 0, NULL);
388 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 5, NULL);
391 g_free(sdcard_img_path);
393 } else if (ret == '2') {
394 TRACE("sdcard status 2 bypass\n" );
396 ERR("!!! unknown command : %c\n", ret);
400 ERR("!!! unknown data : %c\n", ret);
406 static bool injector_req_sdcard(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
409 TRACE("msg(%zu) : %s\n", msg->data.len, msg->data.data);
410 if (handle_sdcard((char*) msg->data.data, msg->data.len) > 0) {
417 injector_send(ccli, msg, cmd);
422 static void send_status_injector_ntf(const char* cmd, int cmdlen, int act, char* on)
424 int msglen = 0, datalen = 0;
425 type_length length = 0;
426 type_group group = MSG_GROUP_STATUS;
427 type_action action = act;
429 if (cmd == NULL || cmdlen > 10)
435 datalen = strlen(on);
436 length = (unsigned short)datalen;
438 msglen = datalen + 15;
441 char* status_msg = (char*) malloc(msglen);
445 memset(status_msg, 0, msglen);
447 memcpy(status_msg, cmd, cmdlen);
448 memcpy(status_msg + 10, &length, sizeof(unsigned short));
449 memcpy(status_msg + 12, &group, sizeof(unsigned char));
450 memcpy(status_msg + 13, &action, sizeof(unsigned char));
453 memcpy(status_msg + 14, on, datalen);
456 send_injector_ntf(status_msg, msglen);
461 static bool injector_req_sensor(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
463 char data[MAX_INJECTOR_REQ_DATA];
467 memset(data, 0, MAX_INJECTOR_REQ_DATA);
468 group = (type_group) (msg->group & 0xff);
469 action = (type_action) (msg->action & 0xff);
471 if (group == MSG_GROUP_STATUS) {
473 case MSG_ACT_BATTERY_LEVEL:
474 sprintf(data, "%d", get_power_capacity());
476 case MSG_ACT_BATTERY_CHARGER:
477 sprintf(data, "%d", get_jack_charger());
480 sprintf(data, "%d", get_jack_usb());
482 case MSG_ACT_EARJACK:
483 sprintf(data, "%d", get_jack_earjack());
485 case MSG_ACT_LOCATION:
486 qemu_mutex_lock(&mutex_location_data);
487 sprintf(data, "%s", location_data);
488 qemu_mutex_unlock(&mutex_location_data);
491 return injector_send(ccli, msg, cmd);
493 TRACE("status : %s\n", data);
494 send_status_injector_ntf(MSG_TYPE_SENSOR, 6, action, data);
496 } else if (msg->data.data && msg->data.len > 0) {
497 set_injector_data((char*) msg->data.data);
498 return injector_send(ccli, msg, cmd);
504 static bool injector_req_guest(void)
507 qemu_mutex_lock(&mutex_guest_connection);
508 value = guest_connection;
509 qemu_mutex_unlock(&mutex_guest_connection);
510 send_status_injector_ntf(MSG_TYPE_GUEST, 5, value, NULL);
514 static bool injector_req_location(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
516 if (msg->data.data != NULL && msg->data.len > 0) {
517 qemu_mutex_lock(&mutex_location_data);
518 snprintf(location_data, msg->data.len + 1, "%s", (char*)msg->data.data);
519 qemu_mutex_unlock(&mutex_location_data);
520 return injector_send(ccli, msg, cmd);
526 bool msgproc_injector_req(ECS_Client* ccli, ECS__InjectorReq* msg)
531 strncpy(cmd, msg->category, sizeof(cmd) - 1);
533 if (!strcmp(cmd, MSG_TYPE_SDCARD)) {
534 ret = injector_req_sdcard(ccli, msg, cmd);
535 } else if (!strcmp(cmd, MSG_TYPE_SENSOR)) {
536 ret = injector_req_sensor(ccli, msg, cmd);
537 } else if (!strcmp(cmd, MSG_TYPE_GUEST)) {
538 ret = injector_req_guest();
539 } else if (!strcmp(cmd, MSG_TYPE_LOCATION)) {
540 ret = injector_req_location(ccli, msg, cmd);
542 ret = injector_send(ccli, msg, cmd);
548 void ecs_suspend_lock_state(int state)
552 ECS__InjectorReq msg = ECS__INJECTOR_REQ__INIT;
553 const char* category = "suspend";
555 catlen = strlen(category);
556 msg.category = (char*) g_malloc0(catlen + 1);
557 memcpy(msg.category, category, catlen);
562 msgproc_injector_req(NULL, &msg);
565 #define MSG_GROUP_HDS 100
566 static bool injector_req_handle(char* cat, type_action action)
568 /*SD CARD msg process*/
569 if (!strcmp(cat, MSG_TYPE_SDCARD)) {
571 } else if (!strcmp(cat, "suspend")) {
572 ecs_suspend_lock_state(ecs_get_suspend_state());
574 } else if (!strcmp(cat, "boot")) {
575 LOG_INFO("emulator booting done.\n");
576 set_emulator_condition(BOOT_COMPLETED);
578 } else if (!strcmp(cat, MSG_TYPE_GUEST)) {
579 INFO("emuld connection is %d\n", action);
580 qemu_mutex_lock(&mutex_guest_connection);
581 guest_connection = action;
583 set_emulator_condition(BOOT_COMPLETED);
585 set_emulator_condition(RESET);
587 qemu_mutex_unlock(&mutex_guest_connection);
589 } else if (!strcmp(cat, "hds")) {
590 INFO("hds status is %d\n", action);
593 make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL);
596 do_hotplug(DETACH_HDS, NULL, 0);
597 make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL);
600 do_hotplug(DETACH_HDS, NULL, 0);
601 make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL);
604 make_send_device_ntf(cat, MSG_GROUP_HDS, action, NULL);
607 ERR("unknown action: %s.\n", action);
616 bool send_injector_ntf(const char* data, const int len)
618 type_length length = 0;
619 type_group group = 0;
620 type_action action = 0;
622 const int catsize = 10;
623 char cat[catsize + 1];
624 memset(cat, 0, catsize + 1);
626 read_val_str(data, cat, catsize);
627 read_val_short(data + catsize, &length);
628 read_val_char(data + catsize + 2, &group);
629 read_val_char(data + catsize + 2 + 1, &action);
631 if (injector_req_handle(cat, action)) {
635 const char* ijdata = (data + catsize + 2 + 1 + 1);
637 TRACE("<< header cat = %s, length = %d, action=%d, group=%d\n", cat, length,action, group);
639 ECS__Master master = ECS__MASTER__INIT;
640 ECS__InjectorNtf ntf = ECS__INJECTOR_NTF__INIT;
642 ntf.category = (char*) g_malloc(catsize + 1);
643 strncpy(ntf.category, cat, 10);
653 ntf.data.data = g_malloc(length);
654 ntf.data.len = length;
655 memcpy(ntf.data.data, ijdata, length);
658 master.type = ECS__MASTER__TYPE__INJECTOR_NTF;
659 master.injector_ntf = &ntf;
661 pb_to_all_clients(&master);
663 if (ntf.data.len > 0)
665 g_free(ntf.data.data);
668 g_free(ntf.category);