update source for tizen_2.1
[sdk/emulator/qemu.git] / tizen / src / mloop_event.c
1 /*
2  * mainloop_evhandle.c
3  *
4  * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  * Kitae Kim <kt920.kim@samsung.com>
8  * GiWoong Kim <giwoong.kim@samsung.com>
9  * DoHyung Hong
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
31 #ifdef _WIN32
32 #include <winsock.h>
33 #define socklen_t     int
34 #else
35 #include <netinet/in.h>
36 #include <sys/ioctl.h>
37 #endif
38
39 #include "qobject.h"
40 #include "qemu-common.h"
41 #include "hw/usb.h"
42 #include "hw/irq.h"
43 #include "mloop_event.h"
44 #include "console.h"
45 #include "emul_state.h"
46 #include "debug_ch.h"
47 #include "monitor.h"
48 #include "pci.h"
49 #include "sysemu.h"
50
51 #include "emulator.h"
52 #include "guest_debug.h"
53 #include "skin/maruskin_server.h"
54 #include "hw/maru_virtio_touchscreen.h"
55 #include "hw/maru_virtio_keyboard.h"
56
57 MULTI_DEBUG_CHANNEL(qemu, mloop_event);
58
59 struct mloop_evsock {
60     int sockno;
61     unsigned short portno;
62     unsigned char status;
63 };
64
65 #define MLOOP_EVSOCK_NULL        0
66 #define MLOOP_EVSOCK_CREATED    1
67 #define MLOOP_EVSOCK_NOTBOUND    2
68 #define MLOOP_EVSOCK_BOUND        3
69 #define MLOOP_EVSOCK_CONNECTED    4
70
71 #define PACKET_LEN 512
72 struct mloop_evpack {
73     short type;
74     short size;
75     char data[PACKET_LEN-4];
76 };
77
78 #define MLOOP_EVTYPE_USB_ADD    1
79 #define MLOOP_EVTYPE_USB_DEL    2
80 #define MLOOP_EVTYPE_INTR_UP    3
81 #define MLOOP_EVTYPE_INTR_DOWN  4
82 #define MLOOP_EVTYPE_HWKEY      5
83 #define MLOOP_EVTYPE_TOUCH      6
84 #define MLOOP_EVTYPE_KEYBOARD   7
85 #define MLOOP_EVTYPE_KBD_ADD    8
86 #define MLOOP_EVTYPE_KBD_DEL    9
87 #define MLOOP_EVTYPE_RAMDUMP    10
88
89
90 static struct mloop_evsock mloop = {-1, 0, 0};
91
92 static int mloop_evsock_create(struct mloop_evsock *ev)
93 {
94     struct sockaddr sa;
95     socklen_t sa_size;
96     int ret;
97     unsigned long nonblock = 1;
98
99     if (ev == NULL) {
100         ERR("null pointer\n");
101         return -1;
102     }
103
104     ev->sockno = socket(AF_INET, SOCK_DGRAM, 0);
105     if ( ev->sockno == -1 ) {
106         ERR("socket() failed\n");
107         return -1;
108     }
109
110 #ifdef _WIN32
111     ioctlsocket(ev->sockno, FIONBIO, &nonblock );
112 #else
113     ioctl(ev->sockno, FIONBIO, &nonblock);
114 #endif // _WIN32
115
116     nonblock = 1 ;
117     setsockopt( ev->sockno, SOL_SOCKET, SO_REUSEADDR, (char *)&nonblock, sizeof(nonblock) ) ;
118
119     memset(&sa, '\0', sizeof(sa));
120     ((struct sockaddr_in *) &sa)->sin_family = AF_INET;
121     memcpy(&((struct sockaddr_in *) &sa)->sin_addr, "\177\000\000\001", 4); // 127.0.0.1
122     ((struct sockaddr_in *) &sa)->sin_port = htons(ev->portno);
123     sa_size = sizeof(struct sockaddr_in);
124
125     ret = bind(ev->sockno, &sa, sa_size);
126     if (ret) {
127         ERR("bind() failed\n");
128 #ifdef _WIN32
129         closesocket(ev->sockno);
130 #else
131         close(ev->sockno);
132 #endif
133         ev->sockno = -1;
134         ev->status = 0;
135         return ret;
136     }
137
138     if (ev->portno == 0) {
139         memset(&sa, '\0', sizeof(sa));
140         getsockname(ev->sockno, (struct sockaddr *) &sa, &sa_size);
141         ev->portno = ntohs(((struct sockaddr_in *) &sa)->sin_port);
142     }
143
144     ret = connect(ev->sockno, (struct sockaddr *) &sa, sa_size);
145     if (ret) {
146         ERR("connect() failed\n");
147 #ifdef _WIN32
148         closesocket(ev->sockno);
149 #else
150         close(ev->sockno);
151 #endif
152         ev->sockno = -1;
153         ev->status = 0;
154         return ret;
155     }
156
157     ev->status = MLOOP_EVSOCK_CONNECTED;
158     return 0;
159 }
160
161 static void mloop_evsock_remove(struct mloop_evsock *ev)
162 {
163     if (!ev) {
164         return ;
165     }
166
167     if (ev->sockno > 0) {
168 #ifdef _WIN32
169         shutdown(ev->sockno, SD_BOTH);
170         closesocket(ev->sockno);
171 #else
172         shutdown(ev->sockno, SHUT_RDWR);
173         close(ev->sockno);
174 #endif
175         ev->sockno = -1;
176         ev->status = 0;
177     }
178 }
179
180 static int mloop_evsock_send(struct mloop_evsock *ev, struct mloop_evpack *p)
181 {
182     int ret;
183
184     if (ev == NULL || ev->sockno == -1) {
185         ERR("invalid mloop_evsock\n");
186         return -1;
187     }
188
189     if (p == NULL || p->size <= 0) {
190         ERR("invalid mloop_evpack\n");
191         return -1;
192     }
193
194     do {
195         ret = send(ev->sockno, p, p->size, 0);
196 #ifdef _WIN32
197     } while (ret == -1 && (WSAGetLastError() == WSAEWOULDBLOCK));
198 #else
199     } while (ret == -1 && (errno == EWOULDBLOCK || errno == EINTR));
200 #endif // _WIN32
201
202     return ret;
203 }
204
205 static USBDevice *usbkbd = NULL;
206 static USBDevice *usbdisk = NULL;
207 static PCIDevice *hostkbd = NULL;
208
209 static void mloop_evhandle_usb_add(char *name)
210 {
211     if (name == NULL) {
212         ERR("Packet data for usb device is NULL\n");
213         return;
214     }
215
216     if (strcmp(name, "keyboard") == 0) {
217         if (usbkbd == NULL) {
218             usbkbd = usbdevice_create(name);
219         } else if (usbkbd->attached == 0) {
220             usb_device_attach(usbkbd);
221         }
222     } else if (strncmp(name, "disk:", 5) == 0) {
223         if (usbdisk == NULL) {
224             usbdisk = usbdevice_create(name);
225         }
226     } else {
227         WARN("There is no usb-device for %s.\n", name);
228      }
229 }
230
231 static void mloop_evhandle_usb_del(char *name)
232 {
233     if (name == NULL) {
234         ERR("Packet data for usb device is NULL\n");
235         return;
236     }
237
238     if (strcmp(name, "keyboard") == 0) {
239         if (usbkbd && usbkbd->attached != 0) {
240             usb_device_detach(usbkbd);
241         }
242     } else if (strncmp(name, "disk:", 5) == 0) {
243         if (usbdisk) {
244             qdev_free(&usbdisk->qdev);
245         }
246     } else {
247         WARN("There is no usb-device for %s.\n", name);
248     }
249 }
250
251 static void mloop_evhandle_intr_up(long data)
252 {
253     if (data == 0) {
254         return;
255     }
256
257     qemu_irq_raise((qemu_irq)data);
258 }
259
260 static void mloop_evhandle_intr_down(long data)
261 {
262     if (data == 0) {
263         return;
264     }
265
266     qemu_irq_lower((qemu_irq)data);
267 }
268
269 static void mloop_evhandle_hwkey(struct mloop_evpack* pack)
270 {
271     int event_type = 0;
272     int keycode = 0;
273
274     memcpy(&event_type, pack->data, sizeof(int));
275     memcpy(&keycode, pack->data + sizeof(int), sizeof(int));
276
277     if (KEY_PRESSED == event_type) {
278         if (kbd_mouse_is_absolute()) {
279             ps2kbd_put_keycode(keycode & 0x7f);
280         }
281     } else if (KEY_RELEASED == event_type) {
282         if (kbd_mouse_is_absolute()) {
283             ps2kbd_put_keycode(keycode | 0x80);
284         }
285     } else {
286         ERR("Unknown hardkey event type.[event_type:%d, keycode:%d]\n",
287             event_type, keycode);
288     }
289 }
290
291 static void mloop_evhandle_touch(struct mloop_evpack* pack)
292 {
293     maru_virtio_touchscreen_notify();
294 }
295
296 static void mloop_evhandle_keyboard(long data)
297 {
298     virtio_keyboard_notify((void*)data);
299 }
300
301 #ifdef TARGET_I386
302 static void mloop_evhandle_kbd_add(char *name)
303 {
304     TRACE("mloop_evhandle_kbd_add\n");
305
306     if (name == NULL) {
307         ERR("packet data is NULL.\n");
308         return;
309     }
310
311     if (hostkbd) {
312         INFO("virtio-keyboard has already been added.\n");
313         return;
314     }
315
316     if (strcmp(name, "keyboard") == 0) {
317         QDict *qdict = qdict_new();
318
319         qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
320         qdict_put(qdict, "type", qstring_from_str(name));
321
322         TRACE("hot_add keyboard device.\n");
323         pci_device_hot_add(cur_mon, qdict);
324
325         if (hostkbd) {
326             TRACE("virtio-keyboard device: domain %d, bus %d, slot %d, function %d\n",
327                     pci_find_domain(hostkbd->bus), pci_bus_num(hostkbd->bus),
328                     PCI_SLOT(hostkbd->devfn), PCI_FUNC(hostkbd->devfn));
329         } else {
330             ERR("failed to hot_add keyboard device.\n");
331         }
332
333         QDECREF(qdict);
334     } else {
335         WARN("There is no %s device.\n", name);
336     }
337 }
338
339 static void mloop_evhandle_kbd_del(char *name)
340 {
341     TRACE("mloop_evhandle_kbd_del\n");
342
343     if (name == NULL) {
344         ERR("packet data is NULL.\n");
345         return;
346     }
347
348     if (!hostkbd) {
349         ERR("Failed to remove keyboard"
350             "because the keyboard device is not created.\n");
351         return;
352     }
353
354     if (strcmp(name, "keyboard") == 0) {
355         QDict *qdict = qdict_new();
356         int slot = 0;
357         char slotbuf[4] = {0,};
358
359         if (hostkbd) {
360             slot = PCI_SLOT(hostkbd->devfn);
361             snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
362             TRACE("virtio-keyboard slot %s.\n", slotbuf);
363         }
364
365         qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
366
367         TRACE("hot_remove keyboard.\n");
368         do_pci_device_hot_remove(cur_mon, qdict);
369
370         QDECREF(qdict);
371     } else {
372         WARN("There is no %s device.\n", name);
373     }
374 }
375 #endif
376
377
378 static void mloop_evhandle_ramdump(struct mloop_evpack* pack)
379 {
380 #define MAX_PATH 256
381     INFO("dumping...\n");
382
383 #if defined(CONFIG_LINUX) && !defined(TARGET_ARM) /* FIXME: Handle ARM ram as list */
384     MemoryRegion* rm = get_ram_memory();
385     unsigned int size = rm->size.lo;
386     char dump_fullpath[MAX_PATH];
387     char dump_filename[MAX_PATH];
388
389     char* dump_path = g_path_get_dirname(get_log_path());
390
391     sprintf(dump_filename, "0x%08x%s0x%08x%s", rm->ram_addr, "-",
392         rm->ram_addr + size, "_RAM.dump");
393     sprintf(dump_fullpath, "%s/%s", dump_path, dump_filename);
394     free(dump_path);
395
396     FILE *dump_file = fopen(dump_fullpath, "w+");
397     if(!dump_file) {
398         fprintf(stderr, "Dump file create failed [%s]\n", dump_fullpath);
399
400         return;
401     }
402
403     size_t written;
404     written = fwrite(qemu_get_ram_ptr(rm->ram_addr), sizeof(char), size, dump_file);
405     fprintf(stdout, "Dump file written [%08x][%d bytes]\n", rm->ram_addr, written);
406     if(written != size) {
407         fprintf(stderr, "Dump file size error [%d, %d, %d]\n", written, size, errno);
408     }
409
410     fprintf(stdout, "Dump file create success [%s, %d bytes]\n", dump_fullpath, size);
411
412     fclose(dump_file);
413 #endif
414
415     /* notify to skin process */
416     notify_ramdump_completed();
417 }
418
419 static void mloop_evcb_recv(struct mloop_evsock *ev)
420 {
421     struct mloop_evpack pack;
422     int ret;
423
424     do {
425         ret = recv(ev->sockno, (void *)&pack, sizeof(pack), 0);
426 #ifdef _WIN32
427     } while (ret == -1 && WSAGetLastError() == WSAEINTR);
428 #else
429     } while (ret == -1 && errno == EINTR);
430 #endif // _WIN32
431
432     if (ret == -1) {
433         return;
434     }
435
436     if (ret == 0) {
437         return;
438     }
439
440     switch (pack.type) {
441     case MLOOP_EVTYPE_USB_ADD:
442         mloop_evhandle_usb_add(pack.data);
443         break;
444     case MLOOP_EVTYPE_USB_DEL:
445         mloop_evhandle_usb_del(pack.data);
446         break;
447     case MLOOP_EVTYPE_INTR_UP:
448         mloop_evhandle_intr_up(*(long*)&pack.data[0]);
449         break;
450     case MLOOP_EVTYPE_INTR_DOWN:
451         mloop_evhandle_intr_down(*(long*)&pack.data[0]);
452         break;
453     case MLOOP_EVTYPE_HWKEY:
454         mloop_evhandle_hwkey(&pack);
455         break;
456     case MLOOP_EVTYPE_TOUCH:
457         mloop_evhandle_touch(&pack);
458         break;
459     case MLOOP_EVTYPE_KEYBOARD:
460         mloop_evhandle_keyboard(*(uint64_t*)&pack.data[0]);
461         break;
462 #ifdef TARGET_I386
463     case MLOOP_EVTYPE_KBD_ADD:
464         mloop_evhandle_kbd_add(pack.data);
465         break;
466     case MLOOP_EVTYPE_KBD_DEL:
467         mloop_evhandle_kbd_del(pack.data);
468         break;
469 #endif
470     case MLOOP_EVTYPE_RAMDUMP:
471         mloop_evhandle_ramdump(&pack);
472         break;
473     default:
474         break;
475     }
476 }
477
478 void mloop_ev_init(void)
479 {
480     int ret = mloop_evsock_create(&mloop);
481     if (ret == 0) {
482         qemu_set_fd_handler(mloop.sockno, (IOHandler *)mloop_evcb_recv, NULL, &mloop);
483     }
484 }
485
486 void mloop_ev_stop(void)
487 {
488     qemu_set_fd_handler(mloop.sockno, NULL, NULL, NULL);
489     mloop_evsock_remove(&mloop);
490 }
491
492 void mloop_evcmd_raise_intr(void *irq)
493 {
494     struct mloop_evpack pack;
495     memset((void*)&pack, 0, sizeof(struct mloop_evpack));
496     pack.type = MLOOP_EVTYPE_INTR_UP;
497     pack.size = 8;
498     *(long*)&pack.data[0] = (long)irq;
499     mloop_evsock_send(&mloop, &pack);
500 }
501
502 void mloop_evcmd_lower_intr(void *irq)
503 {
504     struct mloop_evpack pack;
505     memset((void*)&pack, 0, sizeof(struct mloop_evpack));
506     pack.type = MLOOP_EVTYPE_INTR_DOWN;
507     pack.size = 8;
508     *(long*)&pack.data[0] = (long)irq;
509     mloop_evsock_send(&mloop, &pack);
510 }
511
512 void mloop_evcmd_usbkbd(int on)
513 {
514     struct mloop_evpack pack = { MLOOP_EVTYPE_USB_ADD, 13, "keyboard" };
515     if (on == 0) {
516         pack.type = MLOOP_EVTYPE_USB_DEL;
517     }
518     mloop_evsock_send(&mloop, &pack);
519 }
520
521 void mloop_evcmd_hostkbd(int on)
522 {
523     struct mloop_evpack pack
524         = {MLOOP_EVTYPE_KBD_ADD, 13, "keyboard"};
525     if (on == 0) {
526         pack.type = MLOOP_EVTYPE_KBD_DEL;
527     }
528     mloop_evsock_send(&mloop, &pack);
529 }
530
531 void mloop_evcmd_usbdisk(char *img)
532 {
533     struct mloop_evpack pack;
534
535     if (img) {
536         if (strlen(img) > PACKET_LEN-5) {
537             // Need log
538             ERR("The length of disk image path is greater than "
539                 "lenth of maximum packet.\n");
540             return;
541         }
542
543         pack.type = MLOOP_EVTYPE_USB_ADD;
544         pack.size = 5 + sprintf(pack.data, "disk:%s", img);
545     } else {
546         pack.type = MLOOP_EVTYPE_USB_DEL;
547         pack.size = 5 + sprintf(pack.data, "disk:");
548     }
549
550     mloop_evsock_send(&mloop, &pack);
551 }
552
553 int mloop_evcmd_get_usbkbd_status(void)
554 {
555     return (usbkbd && usbkbd->attached ? 1 : 0);
556 }
557
558 void mloop_evcmd_set_usbkbd(void *dev)
559 {
560     usbkbd = (USBDevice *)dev;
561 }
562
563 void mloop_evcmd_set_usbdisk(void *dev)
564 {
565     usbdisk = (USBDevice *)dev;
566 }
567
568 int mloop_evcmd_get_hostkbd_status(void)
569 {
570     return hostkbd ? 1 : 0;
571 }
572
573 void mloop_evcmd_set_hostkbd(void *dev)
574 {
575     hostkbd = (PCIDevice *)dev;
576 }
577
578 void mloop_evcmd_hwkey(int event_type, int keycode)
579 {
580     struct mloop_evpack pack;
581
582     pack.type = MLOOP_EVTYPE_HWKEY;
583     pack.size = 5 + 8; //TODO: ?
584
585     memcpy(pack.data, &event_type, sizeof(int));
586     memcpy(pack.data + sizeof(int), &keycode, sizeof(int));
587
588     mloop_evsock_send(&mloop, &pack);
589 }
590
591 void mloop_evcmd_touch(void)
592 {
593     struct mloop_evpack pack;
594     memset(&pack, 0, sizeof(struct mloop_evpack));
595
596     pack.type = MLOOP_EVTYPE_TOUCH;
597     pack.size = 5;
598     mloop_evsock_send(&mloop, &pack);
599 }
600
601 void mloop_evcmd_keyboard(void *data)
602 {
603     struct mloop_evpack pack;
604     memset(&pack, 0, sizeof(struct mloop_evpack));
605
606     pack.type = MLOOP_EVTYPE_KEYBOARD;
607     pack.size = 4 + 8;
608     *((VirtIOKeyboard **)pack.data) = (VirtIOKeyboard *)data;
609     mloop_evsock_send(&mloop, &pack);
610 }
611
612 void mloop_evcmd_ramdump(void)
613 {
614     struct mloop_evpack pack;
615     memset(&pack, 0, sizeof(struct mloop_evpack));
616
617     pack.type = MLOOP_EVTYPE_RAMDUMP;
618     pack.size = 5;
619     mloop_evsock_send(&mloop, &pack);
620 }
621