4 * Copyright (C) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
7 * Kitae Kim <kt920.kim@samsung.com>
8 * GiWoong Kim <giwoong.kim@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.
35 #include <netinet/in.h>
36 #include <sys/ioctl.h>
40 #include "qemu-common.h"
43 #include "mloop_event.h"
45 #include "emul_state.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"
57 MULTI_DEBUG_CHANNEL(qemu, mloop_event);
61 unsigned short portno;
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
71 #define PACKET_LEN 512
75 char data[PACKET_LEN-4];
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
90 static struct mloop_evsock mloop = {-1, 0, 0};
92 static int mloop_evsock_create(struct mloop_evsock *ev)
97 unsigned long nonblock = 1;
100 ERR("null pointer\n");
104 ev->sockno = socket(AF_INET, SOCK_DGRAM, 0);
105 if ( ev->sockno == -1 ) {
106 ERR("socket() failed\n");
111 ioctlsocket(ev->sockno, FIONBIO, &nonblock );
113 ioctl(ev->sockno, FIONBIO, &nonblock);
117 setsockopt( ev->sockno, SOL_SOCKET, SO_REUSEADDR, (char *)&nonblock, sizeof(nonblock) ) ;
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);
125 ret = bind(ev->sockno, &sa, sa_size);
127 ERR("bind() failed\n");
129 closesocket(ev->sockno);
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);
144 ret = connect(ev->sockno, (struct sockaddr *) &sa, sa_size);
146 ERR("connect() failed\n");
148 closesocket(ev->sockno);
157 ev->status = MLOOP_EVSOCK_CONNECTED;
161 static void mloop_evsock_remove(struct mloop_evsock *ev)
167 if (ev->sockno > 0) {
169 shutdown(ev->sockno, SD_BOTH);
170 closesocket(ev->sockno);
172 shutdown(ev->sockno, SHUT_RDWR);
180 static int mloop_evsock_send(struct mloop_evsock *ev, struct mloop_evpack *p)
184 if (ev == NULL || ev->sockno == -1) {
185 ERR("invalid mloop_evsock\n");
189 if (p == NULL || p->size <= 0) {
190 ERR("invalid mloop_evpack\n");
195 ret = send(ev->sockno, p, p->size, 0);
197 } while (ret == -1 && (WSAGetLastError() == WSAEWOULDBLOCK));
199 } while (ret == -1 && (errno == EWOULDBLOCK || errno == EINTR));
205 static USBDevice *usbkbd = NULL;
206 static USBDevice *usbdisk = NULL;
207 static PCIDevice *hostkbd = NULL;
209 static void mloop_evhandle_usb_add(char *name)
212 ERR("Packet data for usb device is NULL\n");
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);
222 } else if (strncmp(name, "disk:", 5) == 0) {
223 if (usbdisk == NULL) {
224 usbdisk = usbdevice_create(name);
227 WARN("There is no usb-device for %s.\n", name);
231 static void mloop_evhandle_usb_del(char *name)
234 ERR("Packet data for usb device is NULL\n");
238 if (strcmp(name, "keyboard") == 0) {
239 if (usbkbd && usbkbd->attached != 0) {
240 usb_device_detach(usbkbd);
242 } else if (strncmp(name, "disk:", 5) == 0) {
244 qdev_free(&usbdisk->qdev);
247 WARN("There is no usb-device for %s.\n", name);
251 static void mloop_evhandle_intr_up(long data)
257 qemu_irq_raise((qemu_irq)data);
260 static void mloop_evhandle_intr_down(long data)
266 qemu_irq_lower((qemu_irq)data);
269 static void mloop_evhandle_hwkey(struct mloop_evpack* pack)
274 memcpy(&event_type, pack->data, sizeof(int));
275 memcpy(&keycode, pack->data + sizeof(int), sizeof(int));
277 if (KEY_PRESSED == event_type) {
278 if (kbd_mouse_is_absolute()) {
279 ps2kbd_put_keycode(keycode & 0x7f);
281 } else if (KEY_RELEASED == event_type) {
282 if (kbd_mouse_is_absolute()) {
283 ps2kbd_put_keycode(keycode | 0x80);
286 ERR("Unknown hardkey event type.[event_type:%d, keycode:%d]\n",
287 event_type, keycode);
291 static void mloop_evhandle_touch(struct mloop_evpack* pack)
293 maru_virtio_touchscreen_notify();
296 static void mloop_evhandle_keyboard(long data)
298 virtio_keyboard_notify((void*)data);
302 static void mloop_evhandle_kbd_add(char *name)
304 TRACE("mloop_evhandle_kbd_add\n");
307 ERR("packet data is NULL.\n");
312 INFO("virtio-keyboard has already been added.\n");
316 if (strcmp(name, "keyboard") == 0) {
317 QDict *qdict = qdict_new();
319 qdict_put(qdict, "pci_addr", qstring_from_str("auto"));
320 qdict_put(qdict, "type", qstring_from_str(name));
322 TRACE("hot_add keyboard device.\n");
323 pci_device_hot_add(cur_mon, qdict);
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));
330 ERR("failed to hot_add keyboard device.\n");
335 WARN("There is no %s device.\n", name);
339 static void mloop_evhandle_kbd_del(char *name)
341 TRACE("mloop_evhandle_kbd_del\n");
344 ERR("packet data is NULL.\n");
349 ERR("Failed to remove keyboard"
350 "because the keyboard device is not created.\n");
354 if (strcmp(name, "keyboard") == 0) {
355 QDict *qdict = qdict_new();
357 char slotbuf[4] = {0,};
360 slot = PCI_SLOT(hostkbd->devfn);
361 snprintf(slotbuf, sizeof(slotbuf), "%x", slot);
362 TRACE("virtio-keyboard slot %s.\n", slotbuf);
365 qdict_put(qdict, "pci_addr", qstring_from_str(slotbuf));
367 TRACE("hot_remove keyboard.\n");
368 do_pci_device_hot_remove(cur_mon, qdict);
372 WARN("There is no %s device.\n", name);
378 static void mloop_evhandle_ramdump(struct mloop_evpack* pack)
381 INFO("dumping...\n");
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];
389 char* dump_path = g_path_get_dirname(get_log_path());
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);
396 FILE *dump_file = fopen(dump_fullpath, "w+");
398 fprintf(stderr, "Dump file create failed [%s]\n", dump_fullpath);
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);
410 fprintf(stdout, "Dump file create success [%s, %d bytes]\n", dump_fullpath, size);
415 /* notify to skin process */
416 notify_ramdump_completed();
419 static void mloop_evcb_recv(struct mloop_evsock *ev)
421 struct mloop_evpack pack;
425 ret = recv(ev->sockno, (void *)&pack, sizeof(pack), 0);
427 } while (ret == -1 && WSAGetLastError() == WSAEINTR);
429 } while (ret == -1 && errno == EINTR);
441 case MLOOP_EVTYPE_USB_ADD:
442 mloop_evhandle_usb_add(pack.data);
444 case MLOOP_EVTYPE_USB_DEL:
445 mloop_evhandle_usb_del(pack.data);
447 case MLOOP_EVTYPE_INTR_UP:
448 mloop_evhandle_intr_up(*(long*)&pack.data[0]);
450 case MLOOP_EVTYPE_INTR_DOWN:
451 mloop_evhandle_intr_down(*(long*)&pack.data[0]);
453 case MLOOP_EVTYPE_HWKEY:
454 mloop_evhandle_hwkey(&pack);
456 case MLOOP_EVTYPE_TOUCH:
457 mloop_evhandle_touch(&pack);
459 case MLOOP_EVTYPE_KEYBOARD:
460 mloop_evhandle_keyboard(*(uint64_t*)&pack.data[0]);
463 case MLOOP_EVTYPE_KBD_ADD:
464 mloop_evhandle_kbd_add(pack.data);
466 case MLOOP_EVTYPE_KBD_DEL:
467 mloop_evhandle_kbd_del(pack.data);
470 case MLOOP_EVTYPE_RAMDUMP:
471 mloop_evhandle_ramdump(&pack);
478 void mloop_ev_init(void)
480 int ret = mloop_evsock_create(&mloop);
482 qemu_set_fd_handler(mloop.sockno, (IOHandler *)mloop_evcb_recv, NULL, &mloop);
486 void mloop_ev_stop(void)
488 qemu_set_fd_handler(mloop.sockno, NULL, NULL, NULL);
489 mloop_evsock_remove(&mloop);
492 void mloop_evcmd_raise_intr(void *irq)
494 struct mloop_evpack pack;
495 memset((void*)&pack, 0, sizeof(struct mloop_evpack));
496 pack.type = MLOOP_EVTYPE_INTR_UP;
498 *(long*)&pack.data[0] = (long)irq;
499 mloop_evsock_send(&mloop, &pack);
502 void mloop_evcmd_lower_intr(void *irq)
504 struct mloop_evpack pack;
505 memset((void*)&pack, 0, sizeof(struct mloop_evpack));
506 pack.type = MLOOP_EVTYPE_INTR_DOWN;
508 *(long*)&pack.data[0] = (long)irq;
509 mloop_evsock_send(&mloop, &pack);
512 void mloop_evcmd_usbkbd(int on)
514 struct mloop_evpack pack = { MLOOP_EVTYPE_USB_ADD, 13, "keyboard" };
516 pack.type = MLOOP_EVTYPE_USB_DEL;
518 mloop_evsock_send(&mloop, &pack);
521 void mloop_evcmd_hostkbd(int on)
523 struct mloop_evpack pack
524 = {MLOOP_EVTYPE_KBD_ADD, 13, "keyboard"};
526 pack.type = MLOOP_EVTYPE_KBD_DEL;
528 mloop_evsock_send(&mloop, &pack);
531 void mloop_evcmd_usbdisk(char *img)
533 struct mloop_evpack pack;
536 if (strlen(img) > PACKET_LEN-5) {
538 ERR("The length of disk image path is greater than "
539 "lenth of maximum packet.\n");
543 pack.type = MLOOP_EVTYPE_USB_ADD;
544 pack.size = 5 + sprintf(pack.data, "disk:%s", img);
546 pack.type = MLOOP_EVTYPE_USB_DEL;
547 pack.size = 5 + sprintf(pack.data, "disk:");
550 mloop_evsock_send(&mloop, &pack);
553 int mloop_evcmd_get_usbkbd_status(void)
555 return (usbkbd && usbkbd->attached ? 1 : 0);
558 void mloop_evcmd_set_usbkbd(void *dev)
560 usbkbd = (USBDevice *)dev;
563 void mloop_evcmd_set_usbdisk(void *dev)
565 usbdisk = (USBDevice *)dev;
568 int mloop_evcmd_get_hostkbd_status(void)
570 return hostkbd ? 1 : 0;
573 void mloop_evcmd_set_hostkbd(void *dev)
575 hostkbd = (PCIDevice *)dev;
578 void mloop_evcmd_hwkey(int event_type, int keycode)
580 struct mloop_evpack pack;
582 pack.type = MLOOP_EVTYPE_HWKEY;
583 pack.size = 5 + 8; //TODO: ?
585 memcpy(pack.data, &event_type, sizeof(int));
586 memcpy(pack.data + sizeof(int), &keycode, sizeof(int));
588 mloop_evsock_send(&mloop, &pack);
591 void mloop_evcmd_touch(void)
593 struct mloop_evpack pack;
594 memset(&pack, 0, sizeof(struct mloop_evpack));
596 pack.type = MLOOP_EVTYPE_TOUCH;
598 mloop_evsock_send(&mloop, &pack);
601 void mloop_evcmd_keyboard(void *data)
603 struct mloop_evpack pack;
604 memset(&pack, 0, sizeof(struct mloop_evpack));
606 pack.type = MLOOP_EVTYPE_KEYBOARD;
608 *((VirtIOKeyboard **)pack.data) = (VirtIOKeyboard *)data;
609 mloop_evsock_send(&mloop, &pack);
612 void mloop_evcmd_ramdump(void)
614 struct mloop_evpack pack;
615 memset(&pack, 0, sizeof(struct mloop_evpack));
617 pack.type = MLOOP_EVTYPE_RAMDUMP;
619 mloop_evsock_send(&mloop, &pack);