input: rewrite virtio touchscreen / keyboard device
authorSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 15 Jun 2016 08:36:13 +0000 (17:36 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Thu, 16 Jun 2016 02:09:44 +0000 (11:09 +0900)
Simplified input processing and delivering logics.
Used proper virtio APIs.

Change-Id: Iebb5dede2b34d0e1a9243d65258bffd3180f56df
Signed-off-by: SeokYeon Hwang <syeon.hwang@samsung.com>
tizen/src/emul_state.c
tizen/src/hw/virtio/maru_virtio_keyboard.c
tizen/src/hw/virtio/maru_virtio_keyboard.h
tizen/src/hw/virtio/maru_virtio_touchscreen.c
tizen/src/hw/virtio/maru_virtio_touchscreen.h

index d948275..94852d5 100644 (file)
@@ -69,11 +69,7 @@ static EmulatorConfigState _emul_state;
 
 int get_max_touch_point(void)
 {
-    if (ts) {
-        return ts->max_finger;
-    } else {
-        return 1;
-    }
+    return virtio_touchscreen_get_max_touch_point();
 }
 
 /* current emulator condition */
index 812335f..ab9af1b 100644 (file)
@@ -1,15 +1,11 @@
 /*
  * Virtio Keyboard Device
  *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
- *  SungMin Ha <sungmin82.ha@samsung.com>
- *  Kitae Kim <kt920.kim@samsung.com>
- *  GiWoong Kim <giwoong.kim@samsung.com>
  *  SeokYeon Hwang <syeon.hwang@samsung.com>
- *  SangHo Park <sangho.p@samsung.com>
- *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *  SungMin Ha <sungmin82.ha@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  *
  */
 
+#include "qemu/iov.h"
 #include "hw/maru_device_ids.h"
 #include "maru_virtio_keyboard.h"
-#include "debug_ch.h"
 
+#include "debug_ch.h"
 
 MULTI_DEBUG_CHANNEL(qemu, keyboard);
 
+#define VIRTIO_MARU_KEYBOARD(obj) \
+        OBJECT_CHECK(VirtIOKeyboard, (obj), TYPE_VIRTIO_MARU_KEYBOARD)
+
+#define MAX_EVENT_CNT 256
+
+typedef struct EmulKbdEvent {
+    uint16_t code;
+    uint16_t type;
+} EmulKbdEvent;
+
+typedef struct VirtIOKbdList {
+    VirtIOKeyboard *vkbd;
+    struct VirtIOKbdList *next;
+} VirtIOKbdList;
+
 static VirtIOKbdList *head = NULL;
 static VirtIOKbdList *curr = NULL;
-VirtQueueElement elem;
+
+
+typedef struct KeyboardEventEntry {
+    EmulKbdEvent event;
+
+    QTAILQ_ENTRY(KeyboardEventEntry) node;
+} KeyboardEventEntry;
+
+static KeyboardEventEntry events_buf[MAX_EVENT_CNT];
+static QTAILQ_HEAD(, KeyboardEventEntry) events_queue =
+    QTAILQ_HEAD_INITIALIZER(events_queue);
+
+
+void virtio_keyboard_event(int keycode)
+{
+    KeyboardEventEntry *entry = NULL;
+    VirtIOKeyboard *vkbd;
+    EmulKbdEvent *kbdevt;
+
+    if (unlikely(!curr || !(vkbd = curr->vkbd))) {
+        LOG_TRACE("The keyboard device is not realized.\n");
+        return;
+    }
+
+    if (unlikely(!virtio_queue_ready(vkbd->vq))) {
+        LOG_INFO("virtqueue is not ready, dropping event.\n");
+        return;
+    }
+
+    ++(vkbd->event_cnt);
+
+    if ((vkbd->avail_buf_cnt)-- == 0) {
+        LOG_SEVERE("event queue is not available, dropping event.\n");
+        ++(vkbd->avail_buf_cnt);
+        return;
+    }
+
+    entry = &(events_buf[vkbd->event_cnt % MAX_EVENT_CNT]);
+    kbdevt = &entry->event;
+
+    if (keycode < 0xe0) {
+        if (vkbd->extension_key) {
+            switch (keycode & 0x7f) {
+            case 28:    /* KP_Enter */
+                kbdevt->code = 96;
+                break;
+            case 29:    /* Right Ctrl */
+                kbdevt->code = 97;
+                break;
+            case 56:    /* Right Alt */
+                kbdevt->code = 100;
+                break;
+            case 71:    /* Home */
+                kbdevt->code = 102;
+                break;
+            case 72:    /* Up */
+                kbdevt->code = 103;
+                break;
+            case 73:    /* Page Up */
+                kbdevt->code = 104;
+                break;
+            case 75:    /* Left */
+                kbdevt->code = 105;
+                break;
+            case 77:    /* Right */
+                kbdevt->code = 106;
+                break;
+            case 79:    /* End */
+                kbdevt->code = 107;
+                break;
+            case 80:    /* Down */
+                kbdevt->code = 108;
+                break;
+            case 81:    /* Page Down */
+                kbdevt->code = 109;
+                break;
+            case 82:    /* Insert */
+                kbdevt->code = 110;
+                break;
+            case 83:    /* Delete */
+                kbdevt->code = 111;
+                break;
+            default:
+                WARN("There is no keymap for this keycode %d.\n", keycode);
+            }
+            vkbd->extension_key = 0;
+        } else {
+            kbdevt->code = keycode & 0x7f;
+        }
+
+        if (!(keycode & 0x80)) {
+            kbdevt->type = 1;    /* KEY_PRESSED */
+        } else {
+            kbdevt->type = 0;    /* KEY_RELEASED */
+        }
+    } else {
+        TRACE("Extension key.\n");
+        kbdevt->code = keycode;
+        vkbd->extension_key = 1;
+    }
+
+    qemu_mutex_lock(&vkbd->event_mutex);
+
+    QTAILQ_INSERT_TAIL(&events_queue, entry, node);
+
+    qemu_mutex_unlock(&vkbd->event_mutex);
+
+    qemu_bh_schedule(vkbd->bh);
+}
 
 static VirtIOKbdList* create_list(VirtIOKeyboard *vkbd)
 {
@@ -136,182 +256,37 @@ static int delete_from_list(VirtIOKeyboard *vkbd)
 
 static void virtio_keyboard_handle(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIOKeyboard *vkbd = (VirtIOKeyboard *)vdev;
-
-    if (virtio_queue_empty(vkbd->vq)) {
-        INFO("virtqueue is empty.\n");
-        return;
-    }
-
-    /* Get a queue buffer which is written by guest side. */
-    // Logics should be re-written soon
-    while (virtqueue_pop(vq, &elem)) {
-        TRACE("virtqueue pop.\n");
-    };
+    // nothing to do
 }
 
-void virtio_keyboard_notify(void *opaque)
+static void virtio_keyboard_send(void *opaque)
 {
     VirtIOKeyboard *vkbd = (VirtIOKeyboard *)opaque;
-    EmulKbdEvent *kbdevt;
-    int written_cnt = 0;
+    KeyboardEventEntry *entry = NULL;
+    int len = 0;
 
-    if (!vkbd) {
-        ERR("VirtIOKeyboard is NULL.\n");
-        return;
-    }
-
-    TRACE("[Enter] virtqueue notifier.\n");
-
-    if (!virtio_queue_ready(vkbd->vq)) {
-        INFO("virtqueue is not ready.\n");
-        return;
-    }
-
-    if (vkbd->kbdqueue.rptr == VIRTIO_KBD_QUEUE_SIZE) {
-        vkbd->kbdqueue.rptr = 0;
-    }
+    LOG_TRACE("%s\n", __func__);
 
     qemu_mutex_lock(&vkbd->event_mutex);
-    written_cnt = vkbd->kbdqueue.wptr;
-
-    while ((written_cnt--)) {
-        kbdevt = &vkbd->kbdqueue.kbdevent[vkbd->kbdqueue.rptr];
-
-        if (((EmulKbdEvent*)(elem.in_sg[vkbd->kbdqueue.rptr].iov_base))->code != 0) {
-            TRACE("FIXME: virtio queue is full.\n");
-        }
-
-        /* Copy keyboard data into guest side. */
-        TRACE("copy: keycode %d, type %d, elem_index %d\n",
-            kbdevt->code, kbdevt->type, vkbd->kbdqueue.rptr);
-        memcpy(elem.in_sg[vkbd->kbdqueue.rptr].iov_base, kbdevt, sizeof(EmulKbdEvent));
-        memset(kbdevt, 0x00, sizeof(EmulKbdEvent));
-
-        if (vkbd->kbdqueue.wptr > 0) {
-            vkbd->kbdqueue.wptr--;
-            TRACE("written_cnt: %d, wptr: %d, qemu_index: %d\n",
-                written_cnt, vkbd->kbdqueue.wptr, vkbd->kbdqueue.rptr);
-        }
-
-        vkbd->kbdqueue.rptr++;
-        if (vkbd->kbdqueue.rptr == VIRTIO_KBD_QUEUE_SIZE) {
-            vkbd->kbdqueue.rptr = 0;
-        }
-    }
-    qemu_mutex_unlock(&vkbd->event_mutex);
-
-    virtqueue_push(vkbd->vq, &elem, sizeof(EmulKbdEvent));
-    virtio_notify(&vkbd->vdev, vkbd->vq);
-
-    TRACE("[Leave] virtqueue notifier.\n");
-}
-
-void virtio_keyboard_event(int keycode)
-{
-    EmulKbdEvent kbdevt = {0};
-    int *index = NULL;
-
-    if (!curr) {
-        TRACE("The keyboard device is not realized.\n");
-        return;
-    }
-
-    VirtIOKeyboard *vkbd = curr->vkbd;
-    if (!vkbd) {
-        ERR("VirtIOKeyboard is NULL.\n");
-        return;
-    }
-
-    if (!virtio_queue_ready(vkbd->vq)) {
-        INFO("virtqueue is not ready.\n");
-        return;
-    }
-
-    index = &(vkbd->kbdqueue.index);
-    TRACE("[Enter] input_event handler. cnt %d\n", vkbd->kbdqueue.wptr);
-
-    if (*index < 0) {
-        ERR("keyboard queue is overflow.\n");
-        return;
-    }
-
-    if (*index == VIRTIO_KBD_QUEUE_SIZE) {
-        *index = 0;
-    }
-
-    if (keycode < 0xe0) {
-        if (vkbd->extension_key) {
-            switch (keycode & 0x7f) {
-            case 28:    /* KP_Enter */
-                kbdevt.code = 96;
-                break;
-            case 29:    /* Right Ctrl */
-                kbdevt.code = 97;
-                break;
-            case 56:    /* Right Alt */
-                kbdevt.code = 100;
-                break;
-            case 71:    /* Home */
-                kbdevt.code = 102;
-                break;
-            case 72:    /* Up */
-                kbdevt.code = 103;
-                break;
-            case 73:    /* Page Up */
-                kbdevt.code = 104;
-                break;
-            case 75:    /* Left */
-                kbdevt.code = 105;
-                break;
-            case 77:    /* Right */
-                kbdevt.code = 106;
-                break;
-            case 79:    /* End */
-                kbdevt.code = 107;
-                break;
-            case 80:    /* Down */
-                kbdevt.code = 108;
-                break;
-            case 81:    /* Page Down */
-                kbdevt.code = 109;
-                break;
-            case 82:    /* Insert */
-                kbdevt.code = 110;
-                break;
-            case 83:    /* Delete */
-                kbdevt.code = 111;
-                break;
-            default:
-                WARN("There is no keymap for this keycode %d.\n", keycode);
-            }
-            vkbd->extension_key = 0;
+    QTAILQ_FOREACH(entry, &events_queue, node) {
+        VirtQueueElement element;
+        EmulKbdEvent *event = &entry->event;
+
+        if (virtqueue_pop(vkbd->vq, &element)) {
+            len = iov_from_buf(element.in_sg, element.in_num,
+                    0, event, sizeof(EmulKbdEvent));
+            virtqueue_push(vkbd->vq, &element, len);
         } else {
-            kbdevt.code = keycode & 0x7f;
+            ERR("virtqueue is not available, dropping event.\n");
+            break;
         }
 
-        if (!(keycode & 0x80)) {
-            kbdevt.type = 1;    /* KEY_PRESSED */
-        } else {
-            kbdevt.type = 0;    /* KEY_RELEASED */
-        }
-    } else {
-        TRACE("Extension key.\n");
-        kbdevt.code = keycode;
-        vkbd->extension_key = 1;
+        ++(vkbd->avail_buf_cnt);
     }
-
-    qemu_mutex_lock(&vkbd->event_mutex);
-    memcpy(&vkbd->kbdqueue.kbdevent[(*index)++], &kbdevt, sizeof(kbdevt));
-    TRACE("event: keycode %d, type %d, index %d.\n",
-        kbdevt.code, kbdevt.type, ((*index) - 1));
-
-    vkbd->kbdqueue.wptr++;
+    QTAILQ_INIT(&events_queue);
     qemu_mutex_unlock(&vkbd->event_mutex);
 
-    TRACE("[Leave] input_event handler. cnt:%d\n", vkbd->kbdqueue.wptr);
-
-    qemu_bh_schedule(vkbd->bh);
+    virtio_notify(VIRTIO_DEVICE(vkbd), vkbd->vq);
 }
 
 static uint64_t virtio_keyboard_get_features(VirtIODevice *vdev,
@@ -323,7 +298,7 @@ static uint64_t virtio_keyboard_get_features(VirtIODevice *vdev,
 
 static void virtio_keyboard_bh(void *opaque)
 {
-    virtio_keyboard_notify(opaque);
+    virtio_keyboard_send(opaque);
 }
 
 static void virtio_keyboard_device_realize(DeviceState *dev, Error **errp)
@@ -340,9 +315,7 @@ static void virtio_keyboard_device_realize(DeviceState *dev, Error **errp)
 
     virtio_init(vdev, TYPE_VIRTIO_MARU_KEYBOARD, VIRTIO_ID_MARU_KEYBOARD, 0);
 
-    memset(&vkbd->kbdqueue, 0x00, sizeof(vkbd->kbdqueue));
     vkbd->extension_key = 0;
-    qemu_mutex_init(&vkbd->event_mutex);
 
     vkbd->vq = virtio_add_queue(vdev, 128, virtio_keyboard_handle);
     vkbd->qdev = dev;
@@ -355,6 +328,8 @@ static void virtio_keyboard_device_realize(DeviceState *dev, Error **errp)
     } else {
         add_to_list(vkbd, true);
     }
+
+    qemu_mutex_init(&vkbd->event_mutex);
 }
 
 static void virtio_keyboard_device_unrealize(DeviceState *dev, Error **errp)
@@ -379,12 +354,16 @@ static void virtio_keyboard_device_unrealize(DeviceState *dev, Error **errp)
 
 static void virtio_keyboard_device_reset(VirtIODevice *vdev)
 {
-    VirtIOKeyboard *vkbd = curr->vkbd;
-    vkbd = VIRTIO_MARU_KEYBOARD(vdev);
+    VirtIOKeyboard *vkbd = (VirtIOKeyboard *)vdev;
 
     INFO("reset keyboard device\n");
-    vkbd->kbdqueue.rptr = 0;
-    vkbd->kbdqueue.index = 0;
+
+    qemu_mutex_lock(&vkbd->event_mutex);
+    vkbd->event_cnt = 0;
+    vkbd->avail_buf_cnt = MAX_EVENT_CNT;
+
+    QTAILQ_INIT(&events_queue);
+    qemu_mutex_unlock(&vkbd->event_mutex);
 }
 
 static void virtio_keyboard_class_init(ObjectClass *klass, void *data)
index a4d016e..3193675 100644 (file)
@@ -1,13 +1,11 @@
 /*
  * Virtio Keyboard Device
  *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
- *  Kitae Kim <kt920.kim@samsung.com>
- *  GiWoong Kim <giwoong.kim@samsung.com>
  *  SeokYeon Hwang <syeon.hwang@samsung.com>
- *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
+ *  SungMin Ha <sungmin82.ha@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -39,42 +37,22 @@ extern "C" {
 #include "hw/virtio/virtio.h"
 
 #define TYPE_VIRTIO_MARU_KEYBOARD "virtio-maru-keyboard-device"
-#define VIRTIO_MARU_KEYBOARD(obj) \
-        OBJECT_CHECK(VirtIOKeyboard, (obj), TYPE_VIRTIO_MARU_KEYBOARD)
-#define VIRTIO_KBD_QUEUE_SIZE  100
-
-typedef struct EmulKbdEvent {
-    uint16_t code;
-    uint16_t type;
-} EmulKbdEvent;
-
-typedef struct VirtIOKbdQueue {
-    EmulKbdEvent kbdevent[VIRTIO_KBD_QUEUE_SIZE];
-    int index;
-    int rptr, wptr;
-} VirtIOKbdQueue;
 
 typedef struct VirtIOKeyboard {
     VirtIODevice    vdev;
     VirtQueue       *vq;
     DeviceState     *qdev;
-    uint16_t        extension_key;
 
-    VirtIOKbdQueue  kbdqueue;
     QemuMutex       event_mutex;
     QEMUBH          *bh;
-} VirtIOKeyboard;
 
-typedef struct VirtIOKbdList {
-    VirtIOKeyboard *vkbd;
-    struct VirtIOKbdList *next;
-} VirtIOKbdList;
+    uint16_t        extension_key;
 
-VirtIODevice *virtio_keyboard_init(DeviceState *dev);
-void virtio_keyboard_exit(VirtIODevice *vdev);
+    unsigned int    event_cnt;
+    unsigned int    avail_buf_cnt;
+} VirtIOKeyboard;
 
 void virtio_keyboard_event(int keycode);
-void virtio_keyboard_notify(void *opaque);
 
 #ifdef __cplusplus
 }
index 910afab..7243405 100644 (file)
@@ -1,11 +1,11 @@
 /*
  * Maru Virtio Touchscreen Device
  *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
  *  GiWoong Kim <giwoong.kim@samsung.com>
- *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  */
 
 
-#include <pthread.h>
+#include "qemu/iov.h"
 #include "maru_virtio_touchscreen.h"
 #include "hw/maru_device_ids.h"
+
 #include "debug_ch.h"
 
-MULTI_DEBUG_CHANNEL(qemu, tsp);
+DECLARE_DEBUG_CHANNEL(tsp);
 
 
 #define DEVICE_NAME "virtio-touchscreen"
+#define VIRTIO_MARU_TOUCHSCREEN(obj) \
+        OBJECT_CHECK(VirtIOTouchscreen, (obj), TYPE_VIRTIO_MARU_TOUCHSCREEN)
+
+#define TOUCHSCREEN_OPTION_NAME "max_point"
+#define MAX_EVENT_CNT 256
+
+/* This structure must match the kernel definitions */
+typedef struct EmulTouchEvent {
+    uint16_t x, y, z;
+    uint8_t state;
+} EmulTouchEvent;
+
 
 /*
  * touch event queue
  */
 typedef struct TouchEventEntry {
-    unsigned int index;
-    EmulTouchEvent touch;
+    EmulTouchEvent event;
 
     QTAILQ_ENTRY(TouchEventEntry) node;
 } TouchEventEntry;
 
-/* the maximum number of touch event that can be put into a queue */
-#define MAX_TOUCH_EVENT_CNT 256
-
-static TouchEventEntry _events_buf[MAX_TOUCH_EVENT_CNT];
+static TouchEventEntry events_buf[MAX_EVENT_CNT];
 static QTAILQ_HEAD(, TouchEventEntry) events_queue =
     QTAILQ_HEAD_INITIALIZER(events_queue);
 
-static unsigned int event_ringbuf_cnt; /* _events_buf */
-static unsigned int event_queue_cnt; /* events_queue */
-
-/*
- * VirtQueueElement queue
- */
-typedef struct ElementEntry {
-    unsigned int el_index;
-    unsigned int sg_index;
-    VirtQueueElement elem;
-
-    QTAILQ_ENTRY(ElementEntry) node;
-} ElementEntry;
-
-static ElementEntry _elem_buf[10];
-static QTAILQ_HEAD(, ElementEntry) elem_queue =
-    QTAILQ_HEAD_INITIALIZER(elem_queue);
-
-static unsigned int elem_ringbuf_cnt; /* _elem_buf */
-static unsigned int elem_queue_cnt; /* elem_queue */
-
-
-VirtIOTouchscreen *ts;
-
-/* lock for between communication thread and IO thread */
-static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
-static pthread_mutex_t elem_mutex = PTHREAD_MUTEX_INITIALIZER;
+static VirtIOTouchscreen *ts;
 
 bool virtio_touchscreen_ready(void)
 {
@@ -91,201 +74,95 @@ bool virtio_touchscreen_ready(void)
     return virtio_queue_ready(ts->vq) != 0;
 }
 
+int virtio_touchscreen_get_max_touch_point(void)
+{
+    if (ts) {
+        return ts->max_finger;
+    } else {
+        return 1;
+    }
+}
+
 void virtio_touchscreen_event(int x, int y, int z, int buttons_state)
 {
     TouchEventEntry *entry = NULL;
 
     if (unlikely(!virtio_queue_ready(ts->vq))) {
-        ERR("virtio queue is not ready\n");
+        LOG_INFO("virtqueue is not ready, dropping event.\n");
         return;
     }
 
-    if (unlikely(event_queue_cnt >= MAX_TOUCH_EVENT_CNT)) {
-        INFO("full touch event queue, lose event\n", event_queue_cnt);
+    ++(ts->event_cnt);
 
-        qemu_bh_schedule(ts->bh);
+    if ((ts->avail_buf_cnt)-- == 0) {
+        LOG_SEVERE("event queue is not available, dropping event.\n");
+        ++(ts->avail_buf_cnt);
         return;
     }
 
-    entry = &(_events_buf[event_ringbuf_cnt % MAX_TOUCH_EVENT_CNT]);
-    event_ringbuf_cnt++;
+    entry = &(events_buf[ts->event_cnt % MAX_EVENT_CNT]);
 
     /* mouse event is copied into the queue */
-    entry->touch.x = x;
-    entry->touch.y = y;
-    entry->touch.z = z;
-    entry->touch.state = buttons_state;
+    entry->event.x = x;
+    entry->event.y = y;
+    entry->event.z = z;
+    entry->event.state = buttons_state;
 
-    pthread_mutex_lock(&event_mutex);
-
-    entry->index = ++event_queue_cnt; /* 1 ~ */
+    qemu_mutex_lock(&ts->event_mutex);
 
     QTAILQ_INSERT_TAIL(&events_queue, entry, node);
 
-    pthread_mutex_unlock(&event_mutex);
+    qemu_mutex_unlock(&ts->event_mutex);
 
-    /* call maru_virtio_touchscreen_notify */
+    /* call maru_virtio_touchscreen_send */
     qemu_bh_schedule(ts->bh);
 
-    TRACE("touch event (%d) : x=%d, y=%d, z=%d, state=%d\n",
-        entry->index, entry->touch.x, entry->touch.y,
-        entry->touch.z, entry->touch.state);
+    LOG_TRACE("touch event: x=%d, y=%d, z=%d, state=%d\n",
+        entry->event.x, entry->event.y,
+        entry->event.z, entry->event.state);
 }
 
 static void maru_virtio_touchscreen_handle(VirtIODevice *vdev, VirtQueue *vq)
 {
-#if 0 /* not used yet */
-    if (ts->eh_entry == NULL) {
-        void *vbuf = NULL;
-        VirtQueueElement elem;
-        int max_trkid = 0;
-
-        virtqueue_pop(ts->vq, &elem);
-        vbuf = elem.in_sg[0].iov_base;
-        memcpy(&max_trkid, vbuf, sizeof(max_trkid));
-
-        if (max_trkid > 0) {
-            INFO("virtio touchscreen's maximum of tracking id = %d\n", max_trkid);
-
-            /* register a event handler */
-            ts->eh_entry = qemu_add_mouse_event_handler(
-                virtio_touchscreen_event, ts, 1, "QEMU Virtio Touchscreen");
-            qemu_activate_mouse_event_handler(ts->eh_entry);
-
-            //TODO:
-            virtqueue_push(ts->vq, &elem, 0);
-            virtio_notify(&(ts->vdev), ts->vq);
-        } else {
-            INFO("virtio touchscreen is not added to qemu mouse event handler\n");
-        }
-    }
-#endif
-
-    int virt_sg_index = 0;
-    ElementEntry *elem_entry = NULL;
-
-    TRACE("maru_virtio_touchscreen_handle\n");
-
-    if (unlikely(virtio_queue_empty(ts->vq))) {
-        TRACE("virtqueue is empty\n");
-        return;
-    }
-
-    while (true) {
-        elem_entry = &(_elem_buf[elem_ringbuf_cnt % 10]);
-        elem_ringbuf_cnt++;
-
-        virt_sg_index = virtqueue_pop(ts->vq, &elem_entry->elem);
-        if (virt_sg_index == 0) {
-            elem_ringbuf_cnt--;
-            break;
-        } else if (virt_sg_index < 0) {
-            ERR("virtqueue is broken\n");
-            elem_ringbuf_cnt--;
-            return;
-        }
-
-        pthread_mutex_lock(&elem_mutex);
-
-        elem_entry->el_index = ++elem_queue_cnt;
-        elem_entry->sg_index = (unsigned int)virt_sg_index;
-
-        /* save VirtQueueElement */
-        QTAILQ_INSERT_TAIL(&elem_queue, elem_entry, node);
-
-        if (ts->waitBuf == true) {
-            ts->waitBuf = false;
-
-            /* call maru_virtio_touchscreen_notify */
-            qemu_bh_schedule(ts->bh);
-        }
-
-        pthread_mutex_unlock(&elem_mutex);
-    }
+    // do nothing
 }
 
-void maru_virtio_touchscreen_notify(void)
+static void maru_virtio_touchscreen_send(void *opaque)
 {
-    ElementEntry *elem_entry = NULL;
-    unsigned int ii = 0;
+    VirtIOTouchscreen *ts = (VirtIOTouchscreen *)opaque;
+    TouchEventEntry *entry = NULL;
+    int len = 0;
 
-    TRACE("maru_virtio_touchscreen_notify\n");
+    LOG_TRACE("%s\n", __func__);
 
-    if (unlikely(!virtio_queue_ready(ts->vq))) {
-        ERR("virtio queue is not ready\n");
-        return;
-    }
-
-    while (true) {
-        if (event_queue_cnt == 0) {
-            TRACE("no event\n");
-            break;
-        } else if (elem_queue_cnt == 0) {
-            TRACE("no buffer\n");
+    qemu_mutex_lock(&ts->event_mutex);
+    QTAILQ_FOREACH(entry, &events_queue, node) {
+        VirtQueueElement element;
+        EmulTouchEvent *event = &entry->event;
 
-            pthread_mutex_lock(&elem_mutex);
-            /* maybe next time */
-            ts->waitBuf = true;
-            pthread_mutex_unlock(&elem_mutex);
+        if (virtqueue_pop(ts->vq, &element)) {
+            len = iov_from_buf(element.in_sg, element.in_num,
+                    0, event, sizeof(EmulTouchEvent));
+            virtqueue_push(ts->vq, &element, len);
+        } else {
+            ERR("virtqueue is not available, dropping event.\n");
             break;
         }
 
-        elem_entry = QTAILQ_FIRST(&elem_queue);
-
-        if (elem_entry->sg_index > 0) {
-            TouchEventEntry *event_entry = NULL;
-            VirtQueueElement *element = NULL;
-            void *vbuf = NULL;
-
-            element = &elem_entry->elem;
-            vbuf = element->in_sg[elem_entry->sg_index - 1].iov_base;
-
-            /* get touch event from host queue */
-            event_entry = QTAILQ_FIRST(&events_queue);
-
-            TRACE("touch(%d) : x=%d, y=%d, z=%d, state=%d | \
-                event_queue_cnt=%d, elem.index=%d, elem.in_num=%d, sg_index=%d\n",
-                event_entry->index, event_entry->touch.x, event_entry->touch.y,
-                event_entry->touch.z, event_entry->touch.state,
-                event_queue_cnt, element->index, element->in_num,
-                elem_entry->sg_index);
-
-            /* copy event into virtio buffer */
-            memcpy(vbuf, &(event_entry->touch), sizeof(event_entry->touch));
-
-            pthread_mutex_lock(&event_mutex);
-
-            /* remove host event */
-            QTAILQ_REMOVE(&events_queue, event_entry, node);
-            event_queue_cnt--;
-
-            pthread_mutex_unlock(&event_mutex);
-
-            /* put buffer into virtio queue */
-            virtqueue_fill(ts->vq, element, sizeof(EmulTouchEvent), ii++);
-        }
-
-        pthread_mutex_lock(&elem_mutex);
-
-        QTAILQ_REMOVE(&elem_queue, elem_entry, node);
-        elem_queue_cnt--;
-
-        pthread_mutex_unlock(&elem_mutex);
+        ++(ts->avail_buf_cnt);
     }
+    QTAILQ_INIT(&events_queue);
+    qemu_mutex_unlock(&ts->event_mutex);
 
-    if (ii != 0) {
-        /* signal other side */
-        virtqueue_flush(ts->vq, ii);
-        /* notify to guest */
-        virtio_notify(&(ts->vdev), ts->vq);
-    }
+    virtio_notify(VIRTIO_DEVICE(ts), ts->vq);
 }
 
 static void virtio_touchscreen_get_config(
     VirtIODevice *vdev, uint8_t *config_data)
 {
     int max_trkid = 10;
-    INFO("virtio_touchscreen_get_config\n");
+
+    LOG_TRACE("%s\n", __func__);
 
     max_trkid = ts->max_finger;
     memcpy(config_data, &max_trkid, 4);
@@ -307,9 +184,7 @@ static uint64_t virtio_touchscreen_get_features(
 
 static void maru_touchscreen_bh(void *opaque)
 {
-    //TouchscreenState *ts = (TouchscreenState *)opaque;
-
-    maru_virtio_touchscreen_notify();
+    maru_virtio_touchscreen_send(opaque);
 }
 
 static void virtio_touchscreen_device_realize(DeviceState *dev, Error **errp)
@@ -317,13 +192,9 @@ static void virtio_touchscreen_device_realize(DeviceState *dev, Error **errp)
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     ts = VIRTIO_MARU_TOUCHSCREEN(dev);
 
-    INFO("initialize touchscreen device : %d\n", ts->max_finger);
+    LOG_INFO("%s: %d\n", __func__, ts->max_finger);
 
     virtio_init(vdev, DEVICE_NAME, VIRTIO_ID_MARU_TOUCHSCREEN, 4);
-    /*if (ts == NULL) {
-        ERR("failed to initialize the touchscreen device\n");
-        return NULL;
-    }*/
 
     // TODO: reduce size
     ts->vq = virtio_add_queue(&ts->vdev, 64, maru_virtio_touchscreen_handle);
@@ -331,22 +202,24 @@ static void virtio_touchscreen_device_realize(DeviceState *dev, Error **errp)
 
     /* bottom halves */
     ts->bh = qemu_bh_new(maru_touchscreen_bh, ts);
+
+    qemu_mutex_init(&ts->event_mutex);
 }
 
 static void virtio_touchscreen_device_unrealize(DeviceState *dev, Error **errp)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIOTouchscreen *ts = VIRTIO_MARU_TOUCHSCREEN(vdev);
 
-    INFO("exit the touchscreen device\n");
+    LOG_INFO("%s\n", __func__);
 
     if (ts->bh) {
         qemu_bh_delete(ts->bh);
     }
 
-    virtio_cleanup(vdev);
+    qemu_mutex_destroy(&ts->event_mutex);
 
-    pthread_mutex_destroy(&event_mutex);
-    pthread_mutex_destroy(&elem_mutex);
+    virtio_cleanup(vdev);
 }
 
 static Property virtio_touchscreen_properties[] = {
@@ -357,35 +230,18 @@ static Property virtio_touchscreen_properties[] = {
 
 static void virtio_touchscreen_device_reset(VirtIODevice *vdev)
 {
-    TouchEventEntry *event_entry = NULL;
-    ElementEntry *elem_entry = NULL;
+    VirtIOTouchscreen *ts = VIRTIO_MARU_TOUCHSCREEN(vdev);
 
-    INFO("reset the touchscreen device\n");
+    LOG_INFO("%s\n", __func__);
 
+    qemu_mutex_lock(&ts->event_mutex);
     /* reset the counters */
-    event_ringbuf_cnt = 0;
-    elem_ringbuf_cnt = 0;
+    ts->event_cnt = 0;
+    ts->avail_buf_cnt = MAX_EVENT_CNT;
 
     /* reset queue */
-    pthread_mutex_lock(&event_mutex);
-    while (event_queue_cnt > 0) {
-        event_entry = QTAILQ_FIRST(&events_queue);
-        QTAILQ_REMOVE(&events_queue, event_entry, node);
-
-        event_queue_cnt--;
-    }
-    pthread_mutex_unlock(&event_mutex);
-
-    pthread_mutex_lock(&elem_mutex);
-    while (elem_queue_cnt > 0) {
-        elem_entry = QTAILQ_FIRST(&elem_queue);
-        QTAILQ_REMOVE(&elem_queue, elem_entry, node);
-
-        elem_queue_cnt--;
-    }
-
-    ts->waitBuf = false;
-    pthread_mutex_unlock(&elem_mutex);
+    QTAILQ_INIT(&events_queue);
+    qemu_mutex_unlock(&ts->event_mutex);
 }
 
 static void virtio_touchscreen_class_init(ObjectClass *klass, void *data)
index 2cabc56..14537d3 100644 (file)
@@ -1,11 +1,11 @@
 /*
  * Maru Virtio Touchscreen Device
  *
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd All Rights Reserved
  *
  * Contact:
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
  *  GiWoong Kim <giwoong.kim@samsung.com>
- *  YeongKyoon Lee <yeongkyoon.lee@samsung.com>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
 #ifndef MARU_TOUCHSCREEN_H_
 #define MARU_TOUCHSCREEN_H_
 
+#include <stdbool.h>
 #include "hw/virtio/virtio.h"
 
 #define TYPE_VIRTIO_MARU_TOUCHSCREEN "virtio-maru-touchscreen-device"
-#define VIRTIO_MARU_TOUCHSCREEN(obj) \
-        OBJECT_CHECK(VirtIOTouchscreen, (obj), TYPE_VIRTIO_MARU_TOUCHSCREEN)
-
-#define TOUCHSCREEN_OPTION_NAME "max_point"
 #define DEFAULT_MAX_FINGER (1)
 
 typedef struct VirtIOTouchscreen {
     VirtIODevice vdev;
-    /* simply a queue into which buffers are posted
-    by the guest for consumption by the host */
     VirtQueue *vq;
-    bool waitBuf;
+    DeviceState *qdev;
 
+    QemuMutex event_mutex;
     QEMUBH *bh;
-    DeviceState *qdev;
 
     unsigned int max_finger;
+
+    unsigned int event_cnt;
+    unsigned int avail_buf_cnt;
 } VirtIOTouchscreen;
 
-/* This structure must match the kernel definitions */
-typedef struct EmulTouchEvent {
-    uint16_t x, y, z;
-    uint8_t state;
-} EmulTouchEvent;
 
 bool virtio_touchscreen_ready(void);
 void virtio_touchscreen_event(int x, int y, int z, int buttons_state);
-void maru_virtio_touchscreen_notify(void);
-
-extern VirtIOTouchscreen *ts;
+int virtio_touchscreen_get_max_touch_point(void);
 
 #endif /* MARU_TOUCHSCREEN_H_ */