1 /* 2 * QEMU System Emulator 3 * 4 * Copyright (c) 2003-2008 Fabrice Bellard 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 */ 24 25 /* the following is needed on Linux to define ptsname() in stdlib.h */ 26 #if defined(__linux__) 27 #define _GNU_SOURCE 1 28 #endif 29 30 #ifndef _WIN32 31 #include <sys/wait.h> 32 #endif // _WIN32 33 34 #ifdef _WIN32 35 #include <windows.h> 36 #include <sys/timeb.h> 37 #endif 38 39 #include "qemu-common.h" 40 #include "net.h" 41 #include "console.h" 42 #include "qemu-timer.h" 43 #include "qemu-char.h" 44 #include "block.h" 45 #include "sockets.h" 46 #include "audio/audio.h" 47 48 #include "android/android.h" 49 #include "charpipe.h" 50 #include "android/globals.h" 51 #include "android/utils/bufprint.h" 52 #include "android/utils/system.h" 53 #include "android/protocol/core-connection.h" 54 #include "android/protocol/attach-ui-impl.h" 55 #include "android/protocol/fb-updates-impl.h" 56 #include "android/protocol/user-events-proxy.h" 57 #include "android/protocol/core-commands-proxy.h" 58 #include "android/protocol/ui-commands-impl.h" 59 #include "android/qemulator.h" 60 61 static Looper* mainLooper; 62 63 /***********************************************************/ 64 /* I/O handling */ 65 66 typedef struct IOHandlerRecord { 67 LoopIo io[1]; 68 IOHandler* fd_read; 69 IOHandler* fd_write; 70 int running; 71 int deleted; 72 void* opaque; 73 struct IOHandlerRecord *next; 74 } IOHandlerRecord; 75 76 static IOHandlerRecord *first_io_handler; 77 78 static void ioh_callback(void* opaque, int fd, unsigned events) 79 { 80 IOHandlerRecord* ioh = opaque; 81 ioh->running = 1; 82 if ((events & LOOP_IO_READ) != 0) { 83 ioh->fd_read(ioh->opaque); 84 } 85 if (!ioh->deleted && (events & LOOP_IO_WRITE) != 0) { 86 ioh->fd_write(ioh->opaque); 87 } 88 ioh->running = 0; 89 if (ioh->deleted) { 90 loopIo_done(ioh->io); 91 free(ioh); 92 } 93 } 94 95 int qemu_set_fd_handler(int fd, 96 IOHandler *fd_read, 97 IOHandler *fd_write, 98 void *opaque) 99 { 100 IOHandlerRecord **pioh, *ioh; 101 102 if (!fd_read && !fd_write) { 103 pioh = &first_io_handler; 104 for(;;) { 105 ioh = *pioh; 106 if (ioh == NULL) 107 return 0; 108 if (ioh->io->fd == fd) { 109 break; 110 } 111 pioh = &ioh->next; 112 } 113 if (ioh->running) { 114 ioh->deleted = 1; 115 } else { 116 *pioh = ioh->next; 117 loopIo_done(ioh->io); 118 free(ioh); 119 } 120 } else { 121 for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { 122 if (ioh->io->fd == fd) 123 goto found; 124 } 125 ANEW0(ioh); 126 ioh->next = first_io_handler; 127 first_io_handler = ioh; 128 loopIo_init(ioh->io, mainLooper, fd, ioh_callback, ioh); 129 found: 130 ioh->fd_read = fd_read; 131 ioh->fd_write = fd_write; 132 ioh->opaque = opaque; 133 134 if (fd_read != NULL) 135 loopIo_wantRead(ioh->io); 136 else 137 loopIo_dontWantRead(ioh->io); 138 139 if (fd_write != NULL) 140 loopIo_wantWrite(ioh->io); 141 else 142 loopIo_dontWantWrite(ioh->io); 143 } 144 return 0; 145 } 146 147 /***********************************************************/ 148 /* main execution loop */ 149 150 static LoopTimer gui_timer[1]; 151 152 static void gui_update(void *opaque) 153 { 154 LoopTimer* timer = opaque; 155 qframebuffer_pulse(); 156 loopTimer_startRelative(timer, GUI_REFRESH_INTERVAL); 157 } 158 159 static void init_gui_timer(Looper* looper) 160 { 161 loopTimer_init(gui_timer, looper, gui_update, gui_timer); 162 loopTimer_startRelative(gui_timer, 0); 163 qframebuffer_invalidate_all(); 164 } 165 166 /* Called from qemulator.c */ 167 void qemu_system_shutdown_request(void) 168 { 169 looper_forceQuit(mainLooper); 170 } 171 172 #ifndef _WIN32 173 174 static void termsig_handler(int signal) 175 { 176 qemu_system_shutdown_request(); 177 } 178 179 static void sigchld_handler(int signal) 180 { 181 waitpid(-1, NULL, WNOHANG); 182 } 183 184 static void sighandler_setup(void) 185 { 186 struct sigaction act; 187 188 memset(&act, 0, sizeof(act)); 189 act.sa_handler = termsig_handler; 190 sigaction(SIGINT, &act, NULL); 191 sigaction(SIGHUP, &act, NULL); 192 sigaction(SIGTERM, &act, NULL); 193 194 act.sa_handler = sigchld_handler; 195 act.sa_flags = SA_NOCLDSTOP; 196 sigaction(SIGCHLD, &act, NULL); 197 } 198 199 #endif 200 201 #ifdef _WIN32 202 static BOOL WINAPI qemu_ctrl_handler(DWORD type) 203 { 204 exit(STATUS_CONTROL_C_EXIT); 205 return TRUE; 206 } 207 #endif 208 209 int qemu_main(int argc, char **argv, char **envp) 210 { 211 #ifndef _WIN32 212 { 213 struct sigaction act; 214 sigfillset(&act.sa_mask); 215 act.sa_flags = 0; 216 act.sa_handler = SIG_IGN; 217 sigaction(SIGPIPE, &act, NULL); 218 } 219 #else 220 SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE); 221 /* Note: cpu_interrupt() is currently not SMP safe, so we force 222 QEMU to run on a single CPU */ 223 { 224 HANDLE h; 225 DWORD mask, smask; 226 int i; 227 h = GetCurrentProcess(); 228 if (GetProcessAffinityMask(h, &mask, &smask)) { 229 for(i = 0; i < 32; i++) { 230 if (mask & (1 << i)) 231 break; 232 } 233 if (i != 32) { 234 mask = 1 << i; 235 SetProcessAffinityMask(h, mask); 236 } 237 } 238 } 239 #endif 240 241 #ifdef _WIN32 242 socket_init(); 243 #endif 244 245 #ifndef _WIN32 246 /* must be after terminal init, SDL library changes signal handlers */ 247 sighandler_setup(); 248 #endif 249 250 mainLooper = looper_newGeneric(); 251 252 /* Register a timer to call qframebuffer_pulse periodically */ 253 init_gui_timer(mainLooper); 254 255 // Connect to the core's framebuffer service 256 if (fbUpdatesImpl_create(attachUiImpl_get_console_socket(), "-raw", 257 qemulator_get_first_framebuffer(qemulator_get()), 258 mainLooper)) { 259 return -1; 260 } 261 262 // Attach the recepient of UI commands. 263 if (uiCmdImpl_create(attachUiImpl_get_console_socket(), mainLooper)) { 264 return -1; 265 } 266 267 looper_run(mainLooper); 268 269 fbUpdatesImpl_destroy(); 270 userEventsProxy_destroy(); 271 coreCmdProxy_destroy(); 272 uiCmdImpl_destroy(); 273 attachUiImpl_destroy(); 274 275 return 0; 276 } 277