• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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