Merge "skin: added tv-1920x1080 layout XML file for Qt UI" into tizen_2.4_develop
[sdk/emulator/qemu.git] / tizen / src / ecs / ecs_msg_injector.c
1 /* Emulator Control Server
2  *
3  * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
4  *
5  * Contact:
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>
10  *
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.
15  *
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.
20  *
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.
24  *
25  * Contributors:
26  * - S-Core Co., Ltd
27  *
28  */
29
30 #include <string.h>
31 #include <stdlib.h>
32
33 #include "qemu-common.h"
34 #include "fsdev/qemu-fsdev.h"
35
36 #include "hw/virtio/maru_virtio_vmodem.h"
37 #include "hw/virtio/maru_virtio_evdi.h"
38 #include "hw/virtio/maru_virtio_jack.h"
39 #include "hw/virtio/maru_virtio_power.h"
40
41 #include "util/maru_device_hotplug.h"
42 #include "util/hds.h"
43 #include "emul_state.h"
44 #include "ecs.h"
45 #include "debug_ch.h"
46 #include "util/osutil.h"
47
48 #include "skin/maruskin_client.h"
49
50 MULTI_DEBUG_CHANNEL(qemu, ecs);
51
52 #define MAX_PKGS_LIST       1024
53 #define MAX_SDB_TRIAL       10
54 #define SLEEP_WAIT_SDB      500 // ms
55 #define SLEEP_CONNECT_SDB   1000 // ms
56
57 static QemuThread sdb_thread_id;
58 static QemuThread hds_thread_id;
59
60 extern QemuMutex mutex_location_data;
61 static char location_data[MAX_INJECTOR_REQ_DATA];
62 static void send_gen_injector_ntf(const char* cmd, int cmdlen, int grp, int act, char* on)
63 {
64     int msglen = 0, datalen = 0;
65     type_length length  = 0;
66     type_group group = grp;
67     type_action action = act;
68
69     if (cmd == NULL || cmdlen > 10)
70         return;
71
72     if (on == NULL) {
73         msglen = 14;
74     } else {
75         datalen = strlen(on);
76         length  = (unsigned short)datalen;
77
78         msglen = datalen + 15;
79     }
80
81     char* status_msg = (char*) malloc(msglen);
82     if(!status_msg)
83         return;
84
85     memset(status_msg, 0, msglen);
86
87     memcpy(status_msg, cmd, cmdlen);
88     memcpy(status_msg + 10, &length, sizeof(unsigned short));
89     memcpy(status_msg + 12, &group, sizeof(unsigned char));
90     memcpy(status_msg + 13, &action, sizeof(unsigned char));
91
92     if (on != NULL) {
93         memcpy(status_msg + 14, on, datalen);
94     }
95
96     send_injector_ntf(status_msg, msglen);
97
98     free(status_msg);
99 }
100
101 static void msgproc_injector_ans(ECS_Client* ccli, const char* category, bool succeed)
102 {
103     if (ccli == NULL) {
104         return;
105     }
106     int catlen = 0;
107     ECS__Master master = ECS__MASTER__INIT;
108     ECS__InjectorAns ans = ECS__INJECTOR_ANS__INIT;
109
110     LOG_TRACE("injector ans - category : %s, succed : %d\n", category, succeed);
111
112     catlen = strlen(category);
113     ans.category = (char*) g_malloc0(catlen + 1);
114     memcpy(ans.category, category, catlen);
115
116     ans.errcode = !succeed;
117     master.type = ECS__MASTER__TYPE__INJECTOR_ANS;
118     master.injector_ans = &ans;
119
120     pb_to_all_clients(&master);
121
122     if (ans.category)
123         g_free(ans.category);
124 }
125
126 static bool injector_send(ECS_Client* ccli, ECS__InjectorReq* msg, char* cmd)
127 {
128     int sndlen = 15; // HEADER(CMD + LENGTH + GROUP + ACTION) + 1
129     const char* msg_data;
130     char* sndbuf;
131     bool ret = false;
132     type_group group;
133
134     group = (type_group) (msg->group & 0xff);
135
136     if (msg->has_data && msg->data.data && msg->data.len > 0)
137         sndlen += msg->data.len;
138
139     sndbuf = (char*) g_malloc0(sndlen);
140     if (!sndbuf) {
141         msgproc_injector_ans(ccli, cmd, false);
142         return false;
143     }
144
145     memcpy(sndbuf, cmd, 10);
146     memcpy(sndbuf + 10, &msg->length, 2);
147     memcpy(sndbuf + 12, &msg->group, 1);
148     memcpy(sndbuf + 13, &msg->action, 1);
149
150     if (msg->has_data && msg->data.data && msg->data.len > 0) {
151         msg_data = (const char*)msg->data.data;
152         memcpy(sndbuf + 14, msg_data, msg->data.len);
153         LOG_TRACE(">> print len = %zd, data\" %s\"\n", msg->data.len, msg_data);
154     }
155
156     if(strcmp(cmd, "telephony") == 0) {
157         LOG_TRACE("telephony msg >>");
158         ret = send_to_vmodem(route_ij, sndbuf, sndlen);
159     } else {
160         LOG_TRACE("evdi msg >> %s", cmd);
161         ret = send_to_evdi(route_ij, sndbuf, sndlen);
162     }
163
164     g_free(sndbuf);
165
166     if (group != MSG_GROUP_STATUS) {
167         msgproc_injector_ans(ccli, cmd, ret);
168     }
169
170     if (!ret) {
171         return false;
172     }
173
174     return true;
175 }
176
177 static char* get_emulator_sdcard_path(void)
178 {
179     char *emulator_sdcard_path = NULL;
180     char *tizen_sdk_data = NULL;
181
182 #ifndef CONFIG_WIN32
183     char emulator_sdcard[] = "/emulator/sdcard/";
184 #else
185     char emulator_sdcard[] = "\\emulator\\sdcard\\";
186 #endif
187
188     LOG_TRACE("emulator_sdcard: %s, %zu\n", emulator_sdcard, sizeof(emulator_sdcard));
189
190     tizen_sdk_data = get_tizen_sdk_data_path();
191     if (!tizen_sdk_data) {
192         LOG_SEVERE("failed to get tizen-sdk-data path.\n");
193         return NULL;
194     }
195
196     emulator_sdcard_path =
197         g_malloc(strlen(tizen_sdk_data) + sizeof(emulator_sdcard) + 1);
198     if (!emulator_sdcard_path) {
199         LOG_SEVERE("failed to allocate memory.\n");
200         return NULL;
201     }
202
203     g_snprintf(emulator_sdcard_path, strlen(tizen_sdk_data) + sizeof(emulator_sdcard),
204              "%s%s", tizen_sdk_data, emulator_sdcard);
205
206     g_free(tizen_sdk_data);
207
208     LOG_TRACE("sdcard path: %s\n", emulator_sdcard_path);
209     return emulator_sdcard_path;
210 }
211
212 static char *get_old_tizen_sdk_data_path(void)
213 {
214     char *tizen_sdk_data_path = NULL;
215
216     LOG_INFO("try to search tizen-sdk-data path in another way.\n");
217
218 #ifndef CONFIG_WIN32
219     char tizen_sdk_data[] = "/tizen-sdk-data";
220     int tizen_sdk_data_len = 0;
221     char *home_dir;
222
223     home_dir = (char *)g_getenv("HOME");
224     if (!home_dir) {
225         home_dir = (char *)g_get_home_dir();
226     }
227
228     tizen_sdk_data_len = strlen(home_dir) + sizeof(tizen_sdk_data) + 1;
229     tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
230     if (!tizen_sdk_data_path) {
231         LOG_SEVERE("failed to allocate memory.\n");
232         return NULL;
233     }
234     g_strlcpy(tizen_sdk_data_path, home_dir, tizen_sdk_data_len);
235     g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
236
237 #else
238     char tizen_sdk_data[] = "\\tizen-sdk-data\\";
239     gint tizen_sdk_data_len = 0;
240     HKEY hKey;
241     char strLocalAppDataPath[1024] = { 0 };
242     DWORD dwBufLen = 1024;
243
244     RegOpenKeyEx(HKEY_CURRENT_USER,
245         "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders",
246         0, KEY_QUERY_VALUE, &hKey);
247
248     RegQueryValueEx(hKey, "Local AppData", NULL,
249                     NULL, (LPBYTE)strLocalAppDataPath, &dwBufLen);
250     RegCloseKey(hKey);
251
252     tizen_sdk_data_len = strlen(strLocalAppDataPath) + sizeof(tizen_sdk_data) + 1;
253     tizen_sdk_data_path = g_malloc(tizen_sdk_data_len);
254     if (!tizen_sdk_data_path) {
255         LOG_SEVERE("failed to allocate memory.\n");
256         return NULL;
257     }
258
259     g_strlcpy(tizen_sdk_data_path, strLocalAppDataPath, tizen_sdk_data_len);
260     g_strlcat(tizen_sdk_data_path, tizen_sdk_data, tizen_sdk_data_len);
261 #endif
262
263     LOG_INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
264     return tizen_sdk_data_path;
265 }
266
267 /*
268  *  get tizen-sdk-data path from sdk.info.
269  */
270 char *get_tizen_sdk_data_path(void)
271 {
272     char const *emul_bin_path = NULL;
273     char *sdk_info_file_path = NULL;
274     char *tizen_sdk_data_path = NULL;
275 #ifndef CONFIG_WIN32
276     const char *sdk_info = "../../../../../sdk.info";
277 #else
278     const char *sdk_info = "..\\..\\..\\..\\..\\sdk.info";
279 #endif
280     const char sdk_data_var[] = "TIZEN_SDK_DATA_PATH";
281
282     FILE *sdk_info_fp = NULL;
283     int sdk_info_path_len = 0;
284
285     LOG_TRACE("%s\n", __func__);
286
287     emul_bin_path = get_bin_path();
288     if (!emul_bin_path) {
289         LOG_SEVERE("failed to get emulator path.\n");
290         return NULL;
291     }
292
293     sdk_info_path_len = strlen(emul_bin_path) + strlen(sdk_info) + 1;
294     sdk_info_file_path = g_malloc(sdk_info_path_len);
295     if (!sdk_info_file_path) {
296         LOG_SEVERE("failed to allocate sdk-data buffer.\n");
297         return NULL;
298     }
299
300     g_snprintf(sdk_info_file_path, sdk_info_path_len, "%s%s",
301                 emul_bin_path, sdk_info);
302     LOG_INFO("sdk.info path: %s\n", sdk_info_file_path);
303
304     sdk_info_fp = fopen(sdk_info_file_path, "r");
305     g_free(sdk_info_file_path);
306
307     if (sdk_info_fp) {
308         LOG_TRACE("Succeeded to open [sdk.info].\n");
309
310         char tmp[256] = { '\0', };
311         char *tmpline = NULL;
312         while (fgets(tmp, sizeof(tmp), sdk_info_fp) != NULL) {
313             if ((tmpline = g_strstr_len(tmp, sizeof(tmp), sdk_data_var))) {
314                 tmpline += strlen(sdk_data_var) + 1; // 1 for '='
315                 break;
316             }
317         }
318
319         if (tmpline) {
320             if (tmpline[strlen(tmpline) - 1] == '\n') {
321                 tmpline[strlen(tmpline) - 1] = '\0';
322             }
323             if (tmpline[strlen(tmpline) - 1] == '\r') {
324                 tmpline[strlen(tmpline) - 1] = '\0';
325             }
326
327             tizen_sdk_data_path = g_malloc(strlen(tmpline) + 1);
328             g_strlcpy(tizen_sdk_data_path, tmpline, strlen(tmpline) + 1);
329
330             LOG_INFO("tizen-sdk-data path: %s\n", tizen_sdk_data_path);
331
332             fclose(sdk_info_fp);
333             return tizen_sdk_data_path;
334         }
335
336         fclose(sdk_info_fp);
337     }
338
339     // legacy mode
340     LOG_SEVERE("Failed to open [sdk.info].\n");
341
342     return get_old_tizen_sdk_data_path();
343 }
344
345 static char* get_sdcard_img_path(char* sdcard_img_name, size_t dataLen) {
346     char* sdcard_img_path = NULL;
347     char* sdcard_path = NULL;
348     if (sdcard_img_name == NULL || dataLen < 3) {
349         return NULL;
350     }
351     dataLen = dataLen - 3;
352     if (sdcard_img_name[dataLen] == '\n') {
353         sdcard_img_name[dataLen] = '\0';
354         LOG_TRACE("sdcard_img_name: %s\n", sdcard_img_name);
355     } else {
356         LOG_SEVERE("wrong sdcard message!\n");
357         return NULL;
358     }
359
360     sdcard_path = get_emulator_sdcard_path();
361     if (sdcard_path != NULL) {
362         sdcard_img_path = g_malloc(DEFAULTBUFLEN);
363         g_strlcpy(sdcard_img_path, sdcard_path, DEFAULTBUFLEN);
364         g_strlcat(sdcard_img_path, sdcard_img_name, DEFAULTBUFLEN);
365         LOG_TRACE("sdcard img path: [%s] length: %d\n", sdcard_img_path, strlen(sdcard_img_path));
366         g_free(sdcard_path);
367         return sdcard_img_path;
368     }
369     return NULL;
370 }
371
372 static int handle_sdcard(char* dataBuf, size_t dataLen)
373 {
374     int err_no = 0;
375     char ret = 0;
376     if (dataBuf != NULL){
377         ret = dataBuf[0];
378
379         if (ret == '0' ) {
380             /* umount sdcard */
381             LOG_INFO("datalen: %d\n", dataLen);
382             char* sdcard_img_path = get_sdcard_img_path(dataBuf + 2, dataLen);
383             err_no = remove_sdcard_lock_os(sdcard_img_path);
384             if (errno == 0 && is_sdcard_attached()) {
385                 do_hotplug(DETACH_SDCARD, NULL, 0);
386             } else {
387                 LOG_SEVERE("failed to umount: %s\n", sdcard_img_path);
388                 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, err_no, NULL);
389                 return err_no;
390             }
391             g_free(sdcard_img_path);
392         } else if (ret == '1') {
393             /* mount sdcard */
394             LOG_INFO("datalen: %d\n", dataLen);
395             char* sdcard_img_path = get_sdcard_img_path(dataBuf + 2, dataLen);
396             if ( !is_sdcard_attached() && make_sdcard_lock_os(sdcard_img_path)) {
397                 do_hotplug(ATTACH_SDCARD, sdcard_img_path, strlen(sdcard_img_path) + 1);
398                 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 0, NULL);
399             } else {
400                 send_gen_injector_ntf(MSG_TYPE_SDCARD, 6, 11, 5, NULL);
401                 return ERR_LCK;
402             }
403             g_free(sdcard_img_path);
404
405         } else if (ret == '2') {
406             LOG_TRACE("sdcard status 2 bypass\n" );
407         } else {
408             LOG_SEVERE("!!! unknown command : %c\n", ret);
409             return ret;
410         }
411     } else {
412         LOG_SEVERE("!!! unknown data : %c\n", ret);
413         return ret;
414     }
415     return ERR_SUCCESS;
416 }
417
418 static bool injector_req_sdcard(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
419 {
420     if (msg->has_data) {
421         LOG_TRACE("msg(%zu) : %s\n", msg->data.len, msg->data.data);
422         if (handle_sdcard((char*) msg->data.data, msg->data.len) > 0) {
423             return false;
424         }
425     } else {
426         LOG_SEVERE("has no msg\n");
427     }
428
429     injector_send(ccli, msg, cmd);
430
431     return true;
432 }
433
434 static void send_status_injector_ntf(const char* cmd, int cmdlen, int act, char* on)
435 {
436     int msglen = 0, datalen = 0;
437     type_length length  = 0;
438     type_group group = MSG_GROUP_STATUS;
439     type_action action = act;
440
441     if (cmd == NULL || cmdlen > 10)
442         return;
443
444     if (on == NULL) {
445         msglen = 14;
446     } else {
447         datalen = strlen(on);
448         length  = (unsigned short)datalen;
449
450         msglen = datalen + 15;
451     }
452
453     char* status_msg = (char*) malloc(msglen);
454     if(!status_msg)
455         return;
456
457     memset(status_msg, 0, msglen);
458
459     memcpy(status_msg, cmd, cmdlen);
460     memcpy(status_msg + 10, &length, sizeof(unsigned short));
461     memcpy(status_msg + 12, &group, sizeof(unsigned char));
462     memcpy(status_msg + 13, &action, sizeof(unsigned char));
463
464     if (on != NULL) {
465         memcpy(status_msg + 14, on, datalen);
466     }
467
468     send_injector_ntf(status_msg, msglen);
469
470     free(status_msg);
471 }
472
473 static bool injector_req_sensor(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
474 {
475     char data[MAX_INJECTOR_REQ_DATA];
476     type_group group;
477     type_action action;
478
479     memset(data, 0, MAX_INJECTOR_REQ_DATA);
480     group = (type_group) (msg->group & 0xff);
481     action = (type_action) (msg->action & 0xff);
482
483     if (group == MSG_GROUP_STATUS) {
484         switch (action) {
485         case MSG_ACT_BATTERY_LEVEL:
486             sprintf(data, "%d", get_power_capacity());
487             break;
488         case MSG_ACT_BATTERY_CHARGER:
489             sprintf(data, "%d", get_jack_charger());
490             break;
491         case MSG_ACT_USB:
492             sprintf(data, "%d", get_jack_usb());
493             break;
494         case MSG_ACT_EARJACK:
495             sprintf(data, "%d", get_jack_earjack());
496             break;
497         case MSG_ACT_LOCATION:
498             qemu_mutex_lock(&mutex_location_data);
499             sprintf(data, "%s", location_data);
500             qemu_mutex_unlock(&mutex_location_data);
501             break;
502         default:
503             return injector_send(ccli, msg, cmd);
504         }
505         LOG_TRACE("status : %s\n", data);
506         send_status_injector_ntf(MSG_TYPE_SENSOR, 6, action, data);
507         return true;
508     } else if (msg->data.data && msg->data.len > 0) {
509         set_injector_data((char*) msg->data.data);
510         return injector_send(ccli, msg, cmd);
511     }
512
513     return false;
514 }
515
516 static bool injector_req_guest(void)
517 {
518     send_status_injector_ntf(MSG_TYPE_GUEST, 5, get_emuld_connection(), NULL);
519     return true;
520 }
521
522 static bool injector_req_location(ECS_Client* ccli, ECS__InjectorReq* msg, char *cmd)
523 {
524     if (msg->data.data != NULL && msg->data.len > 0) {
525         qemu_mutex_lock(&mutex_location_data);
526         snprintf(location_data, msg->data.len + 1, "%s", (char*)msg->data.data);
527         qemu_mutex_unlock(&mutex_location_data);
528         return injector_send(ccli, msg, cmd);
529     }
530
531     return false;
532 }
533
534 bool msgproc_injector_req(ECS_Client* ccli, ECS__InjectorReq* msg)
535 {
536     char cmd[11];
537     bool ret = false;
538
539     strncpy(cmd, msg->category, sizeof(cmd) - 1);
540
541     if (!strcmp(cmd, MSG_TYPE_SDCARD)) {
542         ret = injector_req_sdcard(ccli, msg, cmd);
543     } else if (!strcmp(cmd, MSG_TYPE_SENSOR)) {
544         ret = injector_req_sensor(ccli, msg, cmd);
545     } else if (!strcmp(cmd, MSG_TYPE_GUEST)) {
546         ret = injector_req_guest();
547     } else if (!strcmp(cmd, MSG_TYPE_LOCATION)) {
548         ret = injector_req_location(ccli, msg, cmd);
549     } else {
550         ret = injector_send(ccli, msg, cmd);
551     }
552
553     return ret;
554 }
555
556 void ecs_suspend_lock_state(int state)
557 {
558     int catlen;
559
560     ECS__InjectorReq msg = ECS__INJECTOR_REQ__INIT;
561     const char* category = "suspend";
562
563     catlen = strlen(category);
564     msg.category = (char*) g_malloc0(catlen + 1);
565     memcpy(msg.category, category, catlen);
566
567     msg.group = 5;
568     msg.action = state;
569
570     msgproc_injector_req(NULL, &msg);
571 }
572
573 static void send_hds_mount_request(char* list)
574 {
575     int len = 0;
576     char token[] = ",";
577     char emuld_data [OUT_BUF_SIZE];
578     char* id;
579     char* host;
580     char* guest;
581
582     LOG_INFO("handling mount request: %s\n", list);
583
584     id = strtok(list, token);
585     if (id == NULL) {
586         LOG_SEVERE("cannot send mount request because of id\n");
587         return;
588     }
589
590     host = strtok(NULL, token);
591     if (host == NULL) {
592         LOG_SEVERE("cannot send mount request because of host\n");
593         return;
594     }
595
596     guest = strtok(NULL, token);
597     if (guest == NULL) {
598         LOG_SEVERE("cannot send mount request because of guest\n");
599         return;
600     }
601
602     len = snprintf(emuld_data, sizeof(emuld_data), "%s\n%s\n", id, guest);
603     send_msg_to_guest(MSG_TYPE_HDS, MSG_GROUP_HDS, HDS_ACTION_MOUNT, emuld_data, len + 1);
604 }
605
606 static void* hds_mount_request_thread(void* args)
607 {
608     char* list = (char*)args;
609     char token[] = "\n";
610     char* hds_list;
611
612     hds_list = strtok(list, token);
613     if (hds_list == NULL) {
614         LOG_INFO("no hds mount request\n");
615         free(list);
616         return NULL;
617     }
618
619     send_hds_mount_request(hds_list);
620
621     while((hds_list = strtok(NULL, token)) != NULL) {
622         send_hds_mount_request(hds_list);
623     }
624
625     free(list);
626     return NULL;
627 }
628
629 #define MSG_GROUP_HDS   100
630 #define DEFAULT_STATIC_HDS_ID   "fsdef0"
631 static void do_hds(char* cat, type_action action, const char* data)
632 {
633     FsDriverEntry *entry;
634     char msg [OUT_BUF_SIZE];
635     char *host;
636     char *guest;
637     char* list;
638
639     LOG_INFO("hds status is %d, %s\n", action, data);
640     switch (action) {
641         case 0: // get list from devices
642             list = get_hds_lists();
643             if (strlen(list) == 0) {
644                 LOG_INFO("none of mount candidates available.\n");
645                 break;
646             }
647             qemu_thread_create(&hds_thread_id, "hds_mount", hds_mount_request_thread, (void*)list, QEMU_THREAD_DETACHED);
648             break;
649         case 99: // add list for default hds
650             entry = get_fsdev_fsentry((char*)DEFAULT_STATIC_HDS_ID);
651             if (entry == NULL) {
652                 LOG_SEVERE("cannot find fsdev entry.\n");
653                 break;
654             }
655
656             if (!add_hds_list(DEFAULT_STATIC_HDS_ID, entry->path, DEFAULT_HDS_GUEST_PATH)) {
657                 LOG_SEVERE("cannot add into hds list.\n");
658                 break;
659             }
660
661             set_hds_attached(DEFAULT_STATIC_HDS_ID, true);
662             data = DEFAULT_STATIC_HDS_ID;
663
664             // pass-through
665         case 1: // mount success
666             if (data == NULL) {
667                 LOG_SEVERE("error: hds data is null.\n");
668                 break;
669             }
670             host = get_host_path_by_id((char*)data);
671             if (host == NULL)
672                 LOG_SEVERE("get_host_path_by_id failed with %s, %s\n", data, host);
673             guest = get_guest_path_by_id((char*)data);
674             if (guest == NULL)
675                 LOG_SEVERE("get_guest_path_by_id failed with %s, %s\n", data, guest);
676             snprintf(msg, sizeof(msg), "%s,%s,%s", data, host, guest);
677             make_send_device_ntf(cat, MSG_GROUP_HDS, action, msg);
678             break;
679         case 2: // mount failed.
680         case 11: // not exist on the possible path
681         case 12: // not a vaild path
682             if (data == NULL) {
683                 LOG_SEVERE("error: hds data is null.\n");
684                 break;
685             }
686             remove_hds_list((char*)data);
687             do_hotplug(DETACH_HDS, (char*)data, strlen(data) + 1);
688             make_send_device_ntf(cat, MSG_GROUP_HDS, action, (char*)data);
689             break;
690         case 3: // unmount success
691             if (data == NULL) {
692                 LOG_SEVERE("error: hds data is null.\n");
693                 break;
694             }
695             do_hotplug(DETACH_HDS, (char*)data, strlen(data) + 1);
696             make_send_device_ntf(cat, MSG_GROUP_HDS, action, (char*)data);
697             break;
698         case 4: // unmount failed.
699             if (data == NULL) {
700                 LOG_SEVERE("error: hds data is null.\n");
701                 break;
702             }
703             make_send_device_ntf(cat, MSG_GROUP_HDS, action, (char*)data);
704             break;
705         default:
706             LOG_SEVERE("unknown action: %s.\n", action);
707             break;
708     }
709 }
710
711 static bool do_push_package(char* cmd)
712 {
713     char buf[MAX_PKGS_LIST];
714     FILE* fp = popen(cmd, "r");
715     if (fp == NULL) {
716         LOG_SEVERE("Failed to popen push packages\n");
717         return false;
718     }
719
720     memset(buf, 0, sizeof(buf));
721     while(fgets(buf, sizeof(buf), fp) != NULL) {
722         LOG_INFO("[pkgs]%s\n", buf);
723         if (!strncmp(buf, "error", 5)){
724             pclose(fp);
725             return false;
726         }
727         memset(buf, 0, sizeof(buf));
728     }
729
730     pclose(fp);
731     return true;
732 }
733
734 static bool push_package(const char* data)
735 {
736     int index = 0;
737     int ret = 0;
738     char cmd[MAX_PKGS_LIST];
739     char token[] = ", ";
740 #ifndef CONFIG_WIN32
741     const char* sdb_path = "../../../../../tools/sdb";
742     const char* platform_path = "../../../";
743     const char* addon_path = "/emulator-images/add-ons/";
744 #else
745     const char* sdb_path = "..\\..\\..\\..\\..\\tools\\sdb.exe";
746     const char* platform_path = "..\\..\\..\\";
747     const char* addon_path = "\\emulator-images\\add-ons\\";
748 #endif
749     const char* bin_dir = get_bin_path();
750
751     memset(cmd, 0, sizeof(cmd));
752
753     char* addon = strtok((char*)data, token);
754
755     ret = sprintf(cmd, "%s%s -s emulator-%d push %s%s%s%s%s /opt/usr/apps/tmp/sdk_tools/%s 2>&1",
756             bin_dir, sdb_path, get_device_serial_number(),
757             bin_dir, platform_path, get_emul_profile(), addon_path, addon,
758             addon);
759     if (ret < 0) {
760         LOG_SEVERE("SDB push command is wrong: %s\n", cmd);
761         return false;
762     }
763
764     LOG_INFO("[pkgs] SDB push command: %s\n", cmd);
765
766     if (do_push_package(cmd)) {
767         LOG_INFO("[pkgs] SDB push SUCCESS\n");
768         return true;
769     }
770
771     /*
772      * FIXME: unnecessary sdb connection waiting sleep.
773      *        If SDB runs faster, it should be changed/removed.
774      */
775     while(!get_sdb_connection() && index != MAX_SDB_TRIAL) {
776         LOG_INFO("[pkgs] Waiting SDB connection...%d\n", index + 1);
777 #ifdef CONFIG_WIN32
778         Sleep(SLEEP_WAIT_SDB);
779 #else
780         usleep(SLEEP_WAIT_SDB * 1000);
781 #endif
782         index++;
783     }
784
785     index = 0;
786 #ifdef CONFIG_WIN32
787     Sleep(SLEEP_WAIT_SDB);
788 #else
789     usleep(SLEEP_WAIT_SDB * 1000);
790 #endif
791
792     while(index != MAX_SDB_TRIAL) {
793         if (do_push_package(cmd)) {
794             LOG_INFO("[pkgs] SDB push SUCCESS.\n");
795             return true;
796         }
797         LOG_INFO("[pkgs] Try to send package ...%d\n", index + 1);
798         index++;
799 #ifdef CONFIG_WIN32
800         Sleep(SLEEP_CONNECT_SDB);
801 #else
802         usleep(SLEEP_CONNECT_SDB * 1000);
803 #endif
804     }
805
806     return false;
807 }
808
809 static void show_error_popup(char* data)
810 {
811     char fail_msg[MAX_PKGS_LIST];
812     char token[] = ", ";
813     char* addon = strtok(data, token);
814
815     memset(fail_msg, 0, sizeof(fail_msg));
816     strcpy(fail_msg, "Extra package installation is failed.\n");
817     strcat(fail_msg, addon);
818     strcat(fail_msg, " must be installed MANUALLY!");
819
820     start_simple_client(fail_msg);
821 }
822
823 static void* push_pkgs_thread(void* args)
824 {
825     char* pkg_data = (char*)args;
826     char* data = strdup(pkg_data);
827     if (pkg_data == NULL || data == NULL) {
828         LOG_SEVERE("pkg data strdup is failed.\n");
829         return NULL;
830     }
831
832     if (!push_package(pkg_data)) {
833         LOG_SEVERE("file upload is failed. %s\n", data);
834         show_error_popup(data);
835         free(pkg_data);
836         free(data);
837         return NULL;
838     }
839
840     // request to install rpms
841     LOG_INFO("[pkgs] Request to install : %s\n", data);
842     send_msg_to_guest(MSG_TYPE_PACKAGE, 0, 2, data, strlen(data) + 1);
843
844     free(pkg_data);
845     free(data);
846
847     return NULL;
848 }
849
850 static void do_package(char* cat, type_action action, const char* data)
851 {
852     if (data == NULL || strlen(data) <= 0) {
853         LOG_SEVERE("data is corrupted.\n");
854         return;
855     }
856
857     if (action == 1) {
858         LOG_INFO("[pkgs] Already installed: %s\n", data);
859     } else if (action == 2) {
860         LOG_INFO("[pkgs] Needed to install: %s\n", data);
861         char* pkgs = g_malloc0(MAX_PKGS_LIST);
862         strncpy(pkgs, data, MAX_PKGS_LIST - 1);
863         qemu_thread_create(&sdb_thread_id, "sdb_push", push_pkgs_thread, (void*)pkgs, QEMU_THREAD_DETACHED);
864     } else if (action == 3) {
865         LOG_INFO("[pkgs] Package Installation Success: %s\n", data);
866     } else if (action == 4) {
867         LOG_INFO("[pkgs] Package Installation Failed: %s\n", data);
868         show_error_popup((char*)data);
869     } else {
870         LOG_SEVERE("unknown pkgs action: %d\n", action);
871     }
872 }
873
874 static bool injector_req_handle(char* cat, type_action action, const char* data)
875 {
876     if (!strcmp(cat, "suspend")) {
877         ecs_suspend_lock_state(ecs_get_suspend_state());
878         return true;
879     } else if (!strcmp(cat, "boot")) {
880         LOG_INFO("emulator booting done.\n");
881         set_emulator_condition(BOOT_COMPLETED);
882         return true;
883     } else if (!strcmp(cat, MSG_TYPE_GUEST)) {
884         LOG_INFO("emuld connection is %d\n", action);
885         set_emuld_connection(action);
886     } else if (!strcmp(cat, "hds")) {
887         do_hds(cat, action, data);
888         return true;
889     } else if (!strcmp(cat, MSG_TYPE_PACKAGE)) {
890         do_package(cat, action, data);
891         return true;
892     } else if (!strcmp(cat, MSG_TYPE_GUESTIP)) {
893         if (data != NULL && strlen(data) > 0) {
894             LOG_INFO("guest ip: %s\n", data);
895             set_emul_guest_ip((char*)data);
896         } else {
897             LOG_SEVERE("guest ip is null!\n");
898         }
899         return true;
900     }
901     return false;
902 }
903
904 bool send_injector_ntf(const char* data, const int len)
905 {
906     type_length length = 0;
907     type_group group = 0;
908     type_action action = 0;
909
910     const int catsize = 10;
911     char cat[catsize + 1];
912     memset(cat, 0, catsize + 1);
913
914     read_val_str(data, cat, catsize);
915     read_val_short(data + catsize, &length);
916     read_val_char(data + catsize + 2, &group);
917     read_val_char(data + catsize + 2 + 1, &action);
918
919     const char* ijdata = (data + catsize + 2 + 1 + 1);
920
921     if (!is_ecs_running()) {
922         LOG_SEVERE("ECS is not running.\n");
923         return false;
924     }
925
926     if (injector_req_handle(cat, action, ijdata)) {
927         return true;
928     }
929
930     LOG_TRACE("<< header cat = %s, length = %d, action=%d, group=%d\n", cat, length,action, group);
931
932     ECS__Master master = ECS__MASTER__INIT;
933     ECS__InjectorNtf ntf = ECS__INJECTOR_NTF__INIT;
934
935     ntf.category = (char*) g_malloc(catsize + 1);
936     strncpy(ntf.category, cat, 10);
937
938     ntf.length = length;
939     ntf.group = group;
940     ntf.action = action;
941
942     if (length > 0)
943     {
944         ntf.has_data = 1;
945
946         ntf.data.data = g_malloc(length);
947         ntf.data.len = length;
948         memcpy(ntf.data.data, ijdata, length);
949     }
950
951     master.type = ECS__MASTER__TYPE__INJECTOR_NTF;
952     master.injector_ntf = &ntf;
953
954     pb_to_all_clients(&master);
955
956     if (ntf.data.len > 0)
957     {
958         g_free(ntf.data.data);
959     }
960
961     g_free(ntf.category);
962
963     return true;
964 }
965