From 00b7f2169caa54deb7f2e9d64908e7c6d2ff9d8e Mon Sep 17 00:00:00 2001 From: SeokYeon Hwang Date: Wed, 15 Jun 2016 17:36:13 +0900 Subject: [PATCH] input: rewrite virtio touchscreen / keyboard device Simplified input processing and delivering logics. Used proper virtio APIs. Change-Id: Iebb5dede2b34d0e1a9243d65258bffd3180f56df Signed-off-by: SeokYeon Hwang --- tizen/src/emul_state.c | 6 +- tizen/src/hw/virtio/maru_virtio_keyboard.c | 335 ++++++++++++-------------- tizen/src/hw/virtio/maru_virtio_keyboard.h | 34 +-- tizen/src/hw/virtio/maru_virtio_touchscreen.c | 308 +++++++---------------- tizen/src/hw/virtio/maru_virtio_touchscreen.h | 27 +-- 5 files changed, 255 insertions(+), 455 deletions(-) diff --git a/tizen/src/emul_state.c b/tizen/src/emul_state.c index d948275..94852d5 100644 --- a/tizen/src/emul_state.c +++ b/tizen/src/emul_state.c @@ -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 */ diff --git a/tizen/src/hw/virtio/maru_virtio_keyboard.c b/tizen/src/hw/virtio/maru_virtio_keyboard.c index 812335f..ab9af1b 100644 --- a/tizen/src/hw/virtio/maru_virtio_keyboard.c +++ b/tizen/src/hw/virtio/maru_virtio_keyboard.c @@ -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 - * Kitae Kim - * GiWoong Kim * SeokYeon Hwang - * SangHo Park - * YeongKyoon Lee + * SungMin Ha * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,16 +26,140 @@ * */ +#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) diff --git a/tizen/src/hw/virtio/maru_virtio_keyboard.h b/tizen/src/hw/virtio/maru_virtio_keyboard.h index a4d016e..3193675 100644 --- a/tizen/src/hw/virtio/maru_virtio_keyboard.h +++ b/tizen/src/hw/virtio/maru_virtio_keyboard.h @@ -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 - * GiWoong Kim * SeokYeon Hwang - * YeongKyoon Lee + * SungMin Ha * * 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 } diff --git a/tizen/src/hw/virtio/maru_virtio_touchscreen.c b/tizen/src/hw/virtio/maru_virtio_touchscreen.c index 910afab..7243405 100644 --- a/tizen/src/hw/virtio/maru_virtio_touchscreen.c +++ b/tizen/src/hw/virtio/maru_virtio_touchscreen.c @@ -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 * GiWoong Kim - * YeongKyoon Lee * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -27,60 +27,43 @@ */ -#include +#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) diff --git a/tizen/src/hw/virtio/maru_virtio_touchscreen.h b/tizen/src/hw/virtio/maru_virtio_touchscreen.h index 2cabc56..14537d3 100644 --- a/tizen/src/hw/virtio/maru_virtio_touchscreen.h +++ b/tizen/src/hw/virtio/maru_virtio_touchscreen.h @@ -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 * GiWoong Kim - * YeongKyoon Lee * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -30,38 +30,29 @@ #ifndef MARU_TOUCHSCREEN_H_ #define MARU_TOUCHSCREEN_H_ +#include #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_ */ -- 2.7.4