2 * operation for emulator skin
4 * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved.
7 * GiWoong Kim <giwoong.kim@samsung.com>
8 * 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.
31 #include "maru_common.h"
36 #include "maruskin_operation.h"
37 #include "hw/maru_brightness.h"
38 #include "maru_display.h"
42 #include "mloop_event.h"
43 #include "emul_state.h"
44 #include "maruskin_keymap.h"
45 #include "maruskin_server.h"
46 #include "emul_state.h"
47 #include "hw/maru_pm.h"
52 #include "guest_debug.h"
54 #include "target-i386/hax-i386.h"
57 MULTI_DEBUG_CHANNEL(qemu, skin_operation);
59 #define RESUME_KEY_SEND_INTERVAL 500 // milli-seconds
60 #define CLOSE_POWER_KEY_INTERVAL 1200 // milli-seconds
61 #define DATA_DELIMITER "#" // in detail info data
62 #define TIMEOUT_FOR_SHUTDOWN 10 // seconds
64 static int requested_shutdown_qemu_gracefully = 0;
67 static int guest_x, guest_y;
68 static int pressing_x = -1, pressing_y = -1;
69 static int pressing_origin_x = -1, pressing_origin_y = -1;
71 extern pthread_mutex_t mutex_screenshot;
72 extern pthread_cond_t cond_screenshot;
74 static void* run_timed_shutdown_thread(void* args);
75 static void send_to_emuld(const char* request_type, int request_size, const char* send_buf, int buf_size);
77 void start_display(uint64 handle_id, int lcd_size_width, int lcd_size_height, double scale_factor, short rotation_type)
79 INFO("start_display handle_id:%ld, lcd size:%dx%d, scale_factor:%f, rotation_type:%d\n",
80 (long)handle_id, lcd_size_width, lcd_size_height, scale_factor, rotation_type);
82 set_emul_win_scale(scale_factor);
83 maruskin_init(handle_id, lcd_size_width, lcd_size_height, false);
86 void do_mouse_event(int button_type, int event_type,
87 int origin_x, int origin_y, int x, int y, int z)
90 TRACE("reject mouse touch in lcd off = button:%d, type:%d, x:%d, y:%d, z:%d\n",
91 button_type, event_type, x, y, z);
95 TRACE("mouse_event button:%d, type:%d, host:(%d, %d), x:%d, y:%d, z:%d\n",
96 button_type, event_type, origin_x, origin_y, x, y, z);
98 #ifndef CONFIG_USE_SHM
100 if (get_emul_multi_touch_state()->multitouch_enable == 1) {
101 maru_finger_processing_1(event_type, origin_x, origin_y, x, y);
103 } else if (get_emul_multi_touch_state()->multitouch_enable == 2) {
104 maru_finger_processing_2(event_type, origin_x, origin_y, x, y);
113 pressing_x = guest_x = x;
114 pressing_y = guest_y = y;
115 pressing_origin_x = origin_x;
116 pressing_origin_y = origin_y;
118 kbd_mouse_event(x, y, z, 1);
119 TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n",
120 event_type, origin_x, origin_y, x, y, z);
125 pressing_x = pressing_y = -1;
126 pressing_origin_x = pressing_origin_y = -1;
128 kbd_mouse_event(x, y, z, 0);
129 TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n",
130 event_type, origin_x, origin_y, x, y, z);
133 case MOUSE_WHEELDOWN:
139 kbd_mouse_event(x, y, -z, event_type);
140 TRACE("mouse_event event_type:%d, origin:(%d, %d), x:%d, y:%d, z:%d\n\n",
141 event_type, origin_x, origin_y, x, y, z);
144 ERR("undefined mouse event type passed:%d\n", event_type);
157 void do_key_event(int event_type, int keycode, int state_mask, int key_location)
161 TRACE("key_event event_type:%d, keycode:%d, state_mask:%d, key_location:%d\n",
162 event_type, keycode, state_mask, key_location);
164 #ifndef CONFIG_USE_SHM
165 //is multi-touch mode ?
166 if (get_emul_max_touch_point() > 1) {
167 int state_mask_temp = state_mask & ~JAVA_KEYCODE_NO_FOCUS;
169 if ((keycode == JAVA_KEYCODE_BIT_SHIFT &&
170 state_mask_temp == JAVA_KEYCODE_BIT_CTRL) ||
171 (keycode == JAVA_KEYCODE_BIT_CTRL &&
172 state_mask_temp == JAVA_KEYCODE_BIT_SHIFT))
174 if (KEY_PRESSED == event_type) {
175 get_emul_multi_touch_state()->multitouch_enable = 2;
177 /* add a finger before start the multi-touch processing
178 if already exist the pressed touch in display */
179 if (pressing_x != -1 && pressing_y != -1 &&
180 pressing_origin_x != -1 && pressing_origin_y != -1) {
182 pressing_origin_x, pressing_origin_y,
183 pressing_x, pressing_y);
184 pressing_x = pressing_y = -1;
185 pressing_origin_x = pressing_origin_y = -1;
188 INFO("enable multi-touch = mode2\n");
191 else if (keycode == JAVA_KEYCODE_BIT_CTRL ||
192 keycode == JAVA_KEYCODE_BIT_SHIFT)
194 if (KEY_PRESSED == event_type) {
195 get_emul_multi_touch_state()->multitouch_enable = 1;
197 /* add a finger before start the multi-touch processing
198 if already exist the pressed touch in display */
199 if (pressing_x != -1 && pressing_y != -1 &&
200 pressing_origin_x != -1 && pressing_origin_y != -1) {
202 pressing_origin_x, pressing_origin_y,
203 pressing_x, pressing_y);
204 pressing_x = pressing_y = -1;
205 pressing_origin_x = pressing_origin_y = -1;
208 INFO("enable multi-touch = mode1\n");
209 } else if (KEY_RELEASED == event_type) {
210 if (state_mask_temp == (JAVA_KEYCODE_BIT_CTRL | JAVA_KEYCODE_BIT_SHIFT)) {
211 get_emul_multi_touch_state()->multitouch_enable = 1;
212 INFO("enabled multi-touch = mode1\'\n");
214 get_emul_multi_touch_state()->multitouch_enable = 0;
216 INFO("disable multi-touch\n");
224 #if defined(TARGET_I386)
225 if (!mloop_evcmd_get_hostkbd_status()) {
226 TRACE("ignore keyboard input because usb keyboard is dettached.\n");
231 #if defined(TARGET_ARM)
232 if (!mloop_evcmd_get_usbkbd_status()) {
233 TRACE("ignore keyboard input because usb keyboard is dettached.\n");
238 scancode = javakeycode_to_scancode(event_type, keycode, state_mask, key_location);
240 if (scancode == -1) {
241 INFO("cannot find scancode\n");
245 if (KEY_PRESSED == event_type) {
246 TRACE("key pressed: %d\n", scancode);
247 kbd_put_keycode(scancode);
248 } else if (KEY_RELEASED == event_type) {
249 TRACE("key released: %d\n", scancode);
250 kbd_put_keycode(scancode | 0x80);
254 void do_hardkey_event(int event_type, int keycode)
256 INFO("do_hardkey_event event_type:%d, keycode:%d\n",
257 event_type, keycode);
259 if ( is_suspended_state() ) {
260 if ( KEY_PRESSED == event_type ) {
261 if ( kbd_mouse_is_absolute() ) {
262 // home key or power key is used for resume.
263 if ( ( HARD_KEY_HOME == keycode ) || ( HARD_KEY_POWER == keycode ) ) {
264 INFO( "user requests system resume.\n" );
267 Sleep( RESUME_KEY_SEND_INTERVAL );
269 usleep( RESUME_KEY_SEND_INTERVAL * 1000 );
276 mloop_evcmd_hwkey(event_type, keycode);
279 void do_scale_event(double scale_factor)
281 INFO("do_scale_event scale_factor:%lf\n", scale_factor);
283 set_emul_win_scale(scale_factor);
293 void do_rotation_event(int rotation_type)
296 INFO( "do_rotation_event rotation_type:%d\n", rotation_type);
298 char send_buf[32] = { 0 };
300 switch ( rotation_type ) {
301 case ROTATION_PORTRAIT:
302 sprintf( send_buf, "1\n3\n0\n9.80665\n0\n" );
304 case ROTATION_LANDSCAPE:
305 sprintf( send_buf, "1\n3\n9.80665\n0\n0\n" );
307 case ROTATION_REVERSE_PORTRAIT:
308 sprintf( send_buf, "1\n3\n0\n-9.80665\n0\n" );
310 case ROTATION_REVERSE_LANDSCAPE:
311 sprintf(send_buf, "1\n3\n-9.80665\n0\n0\n");
318 send_to_emuld( "sensor\n\n\n\n", 10, send_buf, 32 );
320 set_emul_rotation( rotation_type );
324 QemuSurfaceInfo* get_screenshot_info(void)
326 DisplaySurface* qemu_display_surface = get_qemu_display_surface();
328 if ( !qemu_display_surface ) {
329 ERR( "qemu surface is NULL.\n" );
333 QemuSurfaceInfo* info = (QemuSurfaceInfo*) g_malloc0( sizeof(QemuSurfaceInfo) );
335 ERR( "Fail to malloc for QemuSurfaceInfo.\n");
339 int length = qemu_display_surface->linesize * qemu_display_surface->height;
340 INFO( "screenshot data length:%d\n", length );
344 ERR( "screenshot data ( 0 >=length ). length:%d\n", length );
348 info->pixel_data = (unsigned char*) g_malloc0( length );
349 if ( !info->pixel_data ) {
351 ERR( "Fail to malloc for pixel data.\n");
355 pthread_mutex_lock(&mutex_screenshot);
356 MaruScreenshot* maru_screenshot = get_maru_screenshot();
357 if ( !maru_screenshot || maru_screenshot->isReady != 1) {
358 ERR( "maru screenshot is NULL or not ready.\n" );
359 memset(info->pixel_data, 0x00, length);
361 maru_screenshot->pixel_data = info->pixel_data;
362 maru_screenshot->request_screenshot = 1;
363 pthread_cond_wait(&cond_screenshot, &mutex_screenshot);
365 pthread_mutex_unlock(&mutex_screenshot);
367 info->pixel_data_length = length;
372 void free_screenshot_info(QemuSurfaceInfo* info)
375 if(info->pixel_data) {
376 g_free(info->pixel_data);
383 DetailInfo* get_detail_info(int qemu_argc, char** qemu_argv)
385 DetailInfo* detail_info = g_malloc0( sizeof(DetailInfo) );
386 if ( !detail_info ) {
387 ERR( "Fail to malloc for DetailInfo.\n" );
393 int delimiter_len = strlen( DATA_DELIMITER );
395 /* collect QEMU information */
396 for ( i = 0; i < qemu_argc; i++ ) {
397 total_len += strlen( qemu_argv[i] );
398 total_len += delimiter_len;
402 /* collect HAXM information */
403 const int HAX_LEN = 32;
404 char hax_error[HAX_LEN];
405 memset( hax_error, 0, HAX_LEN );
408 hax_err_len = sprintf( hax_error + hax_err_len, "%s", "hax_error=" );
411 if ( !ret_hax_init ) {
412 if ( -ENOSPC == ret_hax_init ) {
416 hax_err_len += sprintf( hax_error + hax_err_len, "%s#", error ? "true" : "false" );
417 total_len += (hax_err_len + 1);
420 /* collect log path information */
421 #define LOGPATH_TEXT "log_path="
422 char* log_path = get_log_path();
423 int log_path_len = strlen(LOGPATH_TEXT) + strlen(log_path) + delimiter_len;
424 total_len += (log_path_len + 1);
426 /* memory allocation */
427 char* info_data = g_malloc0( total_len + 1 );
429 g_free( detail_info );
430 ERR( "Fail to malloc for info data.\n" );
435 /* write informations */
437 total_len = 0; //recycle
439 for ( i = 0; i < qemu_argc; i++ ) {
440 len = strlen( qemu_argv[i] );
441 sprintf( info_data + total_len, "%s%s", qemu_argv[i], DATA_DELIMITER );
442 total_len += len + delimiter_len;
446 snprintf( info_data + total_len, hax_err_len + 1, "%s#", hax_error );
447 total_len += hax_err_len;
450 snprintf( info_data + total_len, log_path_len + 1, "%s%s#", LOGPATH_TEXT, log_path );
451 total_len += log_path_len;
453 INFO( "################## detail info data ####################\n" );
454 INFO( "%s\n", info_data );
456 detail_info->data = info_data;
457 detail_info->data_length = total_len;
462 void free_detail_info(DetailInfo* detail_info)
465 if (detail_info->data) {
466 g_free(detail_info->data);
473 void do_open_shell(void)
475 INFO("open shell\n");
479 void onoff_host_kbd(int on)
481 INFO("host kbd on/off: %d.\n", on);
483 #if defined(TARGET_ARM)
484 mloop_evcmd_usbkbd(on);
485 #elif defined(TARGET_I386)
486 mloop_evcmd_hostkbd(on);
490 void do_ram_dump(void)
494 mloop_evcmd_ramdump();
497 void do_guestmemory_dump(void)
499 INFO("dump guest memory!\n");
504 void request_close(void)
506 INFO("request_close\n");
508 /* FIXME: convert to device emulatoion */
509 do_hardkey_event(KEY_PRESSED, HARD_KEY_POWER);
512 Sleep(CLOSE_POWER_KEY_INTERVAL);
514 usleep(CLOSE_POWER_KEY_INTERVAL * 1000);
517 do_hardkey_event(KEY_RELEASED, HARD_KEY_POWER);
521 void shutdown_qemu_gracefully( void ) {
523 requested_shutdown_qemu_gracefully = 1;
526 if( 0 > pthread_create( &thread_id, NULL, run_timed_shutdown_thread, NULL ) ) {
527 ERR( "!!! Fail to create run_timed_shutdown_thread. shutdown qemu right now !!!\n" );
528 qemu_system_shutdown_request();
533 int is_requested_shutdown_qemu_gracefully( void ) {
534 return requested_shutdown_qemu_gracefully;
537 static void* run_timed_shutdown_thread( void* args ) {
539 send_to_emuld( "system\n\n\n\n", 10, "shutdown", 8 );
541 int sleep_interval_time = 1000; // milli-seconds
544 for ( i = 0; i < TIMEOUT_FOR_SHUTDOWN; i++ ) {
546 Sleep( sleep_interval_time );
548 usleep( sleep_interval_time * 1000 );
550 // do not use logger to help user see log in console
551 fprintf( stdout, "Wait for shutdown qemu...%d\n", ( i + 1 ) );
554 INFO( "Shutdown qemu !!!\n" );
555 qemu_system_shutdown_request();
561 static void send_to_emuld( const char* request_type, int request_size, const char* send_buf, int buf_size ) {
563 int s = tcp_socket_outgoing( "127.0.0.1", (uint16_t) ( tizen_base_port + SDB_TCP_EMULD_INDEX ) );
566 ERR( "can't create socket to talk to the sdb forwarding session \n" );
567 ERR( "[127.0.0.1:%d/tcp] connect fail (%d:%s)\n" , tizen_base_port + SDB_TCP_EMULD_INDEX , errno, strerror(errno) );
571 socket_send( s, (char*)request_type, request_size );
572 socket_send( s, &buf_size, 4 );
573 socket_send( s, (char*)send_buf, buf_size );
575 INFO( "send to emuld [req_type:%s, send_data:%s, send_size:%d] 127.0.0.1:%d/tcp \n",
576 request_type, send_buf, buf_size, tizen_base_port + SDB_TCP_EMULD_INDEX );