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
ioh_callback(void * opaque,int fd,unsigned events)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
qemu_set_fd_handler(int fd,IOHandler * fd_read,IOHandler * fd_write,void * opaque)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
gui_update(void * opaque)152 static void gui_update(void *opaque)
153 {
154 LoopTimer* timer = opaque;
155 qframebuffer_pulse();
156 loopTimer_startRelative(timer, GUI_REFRESH_INTERVAL);
157 }
158
init_gui_timer(Looper * looper)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 */
qemu_system_shutdown_request(void)167 void qemu_system_shutdown_request(void)
168 {
169 looper_forceQuit(mainLooper);
170 }
171
172 #ifndef _WIN32
173
termsig_handler(int signal)174 static void termsig_handler(int signal)
175 {
176 qemu_system_shutdown_request();
177 }
178
sigchld_handler(int signal)179 static void sigchld_handler(int signal)
180 {
181 waitpid(-1, NULL, WNOHANG);
182 }
183
sighandler_setup(void)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
qemu_ctrl_handler(DWORD type)202 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
203 {
204 exit(STATUS_CONTROL_C_EXIT);
205 return TRUE;
206 }
207 #endif
208
qemu_main(int argc,char ** argv,char ** envp)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