*
* Contact:
* SeokYeon Hwang <syeon.hwang@samsung.com>
+ * Jinhyung Jo <Jinhyung Jo@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
// INPUT COMMON
//
-#define MAX_EVENT_CNT 256
+#define MAX_EVENT_CNT 128
#define TYPE_VIRTIO_MARU_INPUT "virtio-maru-input-device"
//
+// ROTARY
+//
+
+#define VIRTIO_MARU_ROTARY(obj) \
+ OBJECT_CHECK(VirtIORotary, (obj), TYPE_VIRTIO_MARU_ROTARY)
+
+static VirtIORotary *rotary;
+static rotary_event rotary_events[MAX_EVENT_CNT];
+
+void maru_rotary_event(int32_t delta, int32_t type)
+{
+ VirtIOMaruInput *input = &rotary->input;
+ rotary_event *event;
+
+ /* skip useless data */
+ if (!delta && !type) {
+ return;
+ }
+
+ if (!check_ready(input)) {
+ return;
+ }
+
+ qemu_mutex_lock(&input->event_mutex);
+
+ event = &rotary_events[input->buf_index++];
+
+ event->delta = delta;
+ event->type = type;
+
+ qemu_mutex_unlock(&input->event_mutex);
+
+ push_event(input);
+
+ LOG_TRACE("[%s] delta(%d), type(%d)\n", __func__, delta, type);
+}
+
+static void virtio_rotary_device_realize(DeviceState *dev, Error **errp)
+{
+ rotary = VIRTIO_MARU_ROTARY(dev);
+
+ LOG_INFO("%s\n", __func__);
+
+ input_common_realize(dev, TYPE_VIRTIO_MARU_ROTARY,
+ VIRTIO_ID_MARU_ROTARY, NULL, NULL,
+ rotary_events, sizeof(rotary_event));
+}
+
+static void virtio_rotary_device_unrealize(DeviceState *dev, Error **errp)
+{
+ LOG_INFO("%s\n", __func__);
+
+ input_common_unrealize(dev);
+}
+
+static void virtio_rotary_device_reset(VirtIODevice *vdev)
+{
+ LOG_INFO("%s\n", __func__);
+
+ input_common_reset(vdev);
+}
+
+static void virtio_rotary_class_init(ObjectClass *klass, void *data)
+{
+ VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+ vdc->unrealize = virtio_rotary_device_unrealize;
+ vdc->realize = virtio_rotary_device_realize;
+ vdc->reset = virtio_rotary_device_reset;
+ vdc->get_config = default_get_config;
+ vdc->set_config = default_set_config;
+ vdc->get_features = default_get_features;
+}
+
+static const TypeInfo virtio_rotary_info = {
+ .name = TYPE_VIRTIO_MARU_ROTARY,
+ .parent = TYPE_VIRTIO_DEVICE,
+ .instance_size = sizeof(VirtIORotary),
+ .class_init = virtio_rotary_class_init,
+};
+
+
+
+//
// Register devices
//
type_register_static(&virtio_touchscreen_info);
type_register_static(&virtio_keyboard_info);
type_register_static(&virtio_hwkey_info);
+ type_register_static(&virtio_rotary_info);
}
type_init(virtio_register_types)
+++ /dev/null
-/*
- * Maru Virtio Rotary Device
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * Jinhyung Jo <Jinhyung Jo@samsung.com>
- * Sangho Park <sangho1206.park@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-
-#include "hw/maru_device_ids.h"
-#include "maru_virtio_rotary.h"
-#include "util/new_debug_ch.h"
-
-DECLARE_DEBUG_CHANNEL(rotary);
-
-#define EVENT_BUF_SIZE (ROTARY_QUEUE_SIZE * sizeof(MrRotaryEvent))
-
-static VirtIORotary *g_vrtr;
-
-/* really simple queue implementation, stability is not considered */
-static void rotaryqueue_reset(VirtIORotaryQueue *q)
-{
- /* reset all: count, write pointer, read pointer & event datas */
- memset(q, 0x00, sizeof(VirtIORotaryQueue));
-}
-
-static int rotaryqueue_push_tail(VirtIORotaryQueue *q, MrRotaryEvent *e)
-{
- if (q->count > ROTARY_QUEUE_SIZE) {
- return -1;
- }
- memcpy(&q->event[q->wptr++], e, sizeof(MrRotaryEvent));
- q->count++;
- LOG_TRACE("[%s] count(%d), wptr(%d)\n", __func__, q->count, q->wptr);
-
- return 0;
-}
-
-static int rotaryqueue_check_avail(VirtIORotaryQueue *q)
-{
- return q->count;
-}
-
-static MrRotaryEvent *rotaryqueue_pop_head(VirtIORotaryQueue *q)
-{
- MrRotaryEvent *e = NULL;
- if (q->count) {
- e = &q->event[q->rptr++];
- q->count--;
- }
-
- return e;
-}
-
-static void virtio_rotary_handle(VirtIODevice *vdev, VirtQueue *vq)
-{
- VirtIORotary *vrtr = VIRTIO_MARU_ROTARY(vdev);
-
- if (virtio_queue_empty(vrtr->vq)) {
- LOG_INFO("[%s] virtio queue is empty\n", __func__);
- return;
- }
-
- qemu_mutex_lock(&vrtr->mutex);
- vrtr->avail = true;
- qemu_mutex_unlock(&vrtr->mutex);
-}
-
-void maru_rotary_event(int32_t delta, int32_t type)
-{
- MrRotaryEvent event = {0, };
- int ret;
-
- /* skip useless data */
- if (!delta && !type) {
- return;
- }
- if (!g_vrtr) {
- LOG_WARNING("[%s] VirtIORotary instance is NULL\n", __func__);
- return;
- }
- if (!virtio_queue_ready(g_vrtr->vq)) {
- LOG_INFO("[%s] virtqueue is not ready\n", __func__);
- return;
- }
-
- LOG_TRACE("[%s] delta(%d), type(%d)\n", __func__, delta, type);
- event.delta = delta;
- event.type = type;
-
- qemu_mutex_lock(&g_vrtr->mutex);
- ret = rotaryqueue_push_tail(&g_vrtr->queue, &event);
- qemu_mutex_unlock(&g_vrtr->mutex);
- if (ret) {
- LOG_WARNING("failed to process rotary event: rotaryqueue is full\n");
- return;
- }
- qemu_bh_schedule(g_vrtr->bh);
-}
-
-static void virtio_rotary_bh(void *opaque)
-{
- VirtIORotary *vrtr = (VirtIORotary *)opaque;
- MrRotaryEvent *event;
- VirtQueueElement elem;
- int sg_num;
- uint32_t push_len = 0;
-
- if (!vrtr) {
- LOG_WARNING("[%s] VirtIORotary instance is NULL\n", __func__);
- }
- if (unlikely(!virtio_queue_ready(vrtr->vq))) {
- LOG_WARNING("[%s] virtio queue is not ready\n", __func__);
- return;
- }
- qemu_mutex_lock(&vrtr->mutex);
- if (!vrtr->avail) {
- LOG_TRACE("[%s] guest inbuf is not ready\n", __func__);
- qemu_mutex_unlock(&vrtr->mutex);
- return;
- }
- qemu_mutex_unlock(&vrtr->mutex);
-
- /* get a queue buffer which is written by guest side. */
- do {
- sg_num = virtqueue_pop(vrtr->vq, &elem);
- LOG_TRACE("[%s] virtqueue_pop: sg_num(%d)\n", __func__, sg_num);
- } while (sg_num != 0);
-
- qemu_mutex_lock(&vrtr->mutex);
- while (rotaryqueue_check_avail(&vrtr->queue)) {
- event = rotaryqueue_pop_head(&vrtr->queue);
- /* rotary kernel driver has only one scattergather list */
- memcpy(elem.in_sg[0].iov_base + push_len,
- event, sizeof(MrRotaryEvent));
- push_len += sizeof(MrRotaryEvent);
- }
-
- /* length which is really written to the guest */
- virtqueue_push(vrtr->vq, &elem, push_len);
- virtio_notify(&vrtr->vdev, vrtr->vq);
- rotaryqueue_reset(&vrtr->queue);
- vrtr->avail = false;
- qemu_mutex_unlock(&vrtr->mutex);
-
- LOG_TRACE("[%s] push len(%d), push events(%d)\n",
- __func__, push_len, push_len / sizeof(MrRotaryEvent));
-}
-
-static uint64_t virtio_rotary_get_features(VirtIODevice *vdev,
- uint64_t request_features, Error **errp)
-{
- return request_features;
-}
-
-static void virtio_rotary_device_realize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- VirtIORotary *vrtr = VIRTIO_MARU_ROTARY(vdev);
-
- if (g_vrtr) {
- LOG_WARNING("rotary device is already exist, skip\n");
- }
-
- if (!vrtr) {
- LOG_SEVERE("failed to initialize rotary device\n");
- return;
- }
-
- virtio_init(vdev, TYPE_VIRTIO_MARU_ROTARY, VIRTIO_ID_MARU_ROTARY, 0);
- qemu_mutex_init(&vrtr->mutex);
-
- vrtr->avail = false;
- vrtr->vq = virtio_add_queue(&vrtr->vdev,
- EVENT_BUF_SIZE,
- virtio_rotary_handle);
- vrtr->qdev = dev;
- vrtr->bh = qemu_bh_new(virtio_rotary_bh, vrtr);
- g_vrtr = vrtr;
-
- LOG_INFO("initialize rotary device\n");
-}
-
-static void virtio_rotary_device_unrealize(DeviceState *dev, Error **errp)
-{
- VirtIODevice *vdev = VIRTIO_DEVICE(dev);
- VirtIORotary *vrtr = VIRTIO_MARU_ROTARY(vdev);
-
- if (vrtr->bh) {
- qemu_bh_delete(vrtr->bh);
- }
-
- qemu_mutex_destroy(&vrtr->mutex);
- virtio_cleanup(vdev);
-
- LOG_INFO("exit rotaty device\n");
-}
-
-static void virtio_rotary_device_reset(VirtIODevice *vdev)
-{
- VirtIORotary *vrtr = VIRTIO_MARU_ROTARY(vdev);
-
- vrtr->avail = false;
- rotaryqueue_reset(&vrtr->queue);
- LOG_INFO("reset roraty device\n");
-}
-
-static void virtio_rotary_class_init(ObjectClass *klass, void *data)
-{
- VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
- vdc->unrealize = virtio_rotary_device_unrealize;
- vdc->realize = virtio_rotary_device_realize;
- vdc->reset = virtio_rotary_device_reset;
- vdc->get_features = virtio_rotary_get_features;
-}
-
-static const TypeInfo virtio_rotary_info = {
- .name = TYPE_VIRTIO_MARU_ROTARY,
- .parent = TYPE_VIRTIO_DEVICE,
- .instance_size = sizeof(VirtIORotary),
- .class_init = virtio_rotary_class_init,
-};
-
-static void virtio_register_types(void)
-{
- type_register_static(&virtio_rotary_info);
-}
-
-type_init(virtio_register_types)
+++ /dev/null
-/*
- * Maru Virtio Rotary Device
- *
- * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
- *
- * Contact:
- * Jinhyung Jo <jinhyung.jo@samsung.com>
- * Sangho Park <sangho1206.park@samsung.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contributors:
- * - S-Core Co., Ltd
- *
- */
-
-
-#ifndef MARU_ROTARY_H_
-#define MARU_ROTARY_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "hw/virtio/virtio.h"
-
-/* number of queue must be power of 2 */
-#define ROTARY_QUEUE_SIZE 32
-
-typedef struct MrRotaryEvent {
- int32_t delta;
- int32_t type;
-} MrRotaryEvent;
-
-typedef struct VirtIORotaryQueue {
- uint32_t count;
- uint32_t rptr;
- uint32_t wptr;
- MrRotaryEvent event[ROTARY_QUEUE_SIZE];
-} VirtIORotaryQueue;
-
-typedef struct VirtIORotary {
- VirtIODevice vdev;
- VirtQueue *vq;
- DeviceState *qdev;
-
- QEMUBH *bh;
- QemuMutex mutex;
- bool avail; /* is guest inbuf avail */
- VirtIORotaryQueue queue;
-} VirtIORotary;
-
-#define TYPE_VIRTIO_MARU_ROTARY "virtio-maru-rotary-device"
-#define VIRTIO_MARU_ROTARY(obj) \
- OBJECT_CHECK(VirtIORotary, (obj), TYPE_VIRTIO_MARU_ROTARY)
-
-void maru_rotary_event(int32_t delta, int32_t type);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* MARU_ROTARY_H_ */