rotary: Added a new input device
authorjinhyung.jo <jinhyung.jo@samsung.com>
Mon, 29 Dec 2014 11:17:00 +0000 (20:17 +0900)
committerGiWoong Kim <giwoong.kim@samsung.com>
Thu, 30 Apr 2015 02:17:44 +0000 (11:17 +0900)
Added a new input device for the maru board

Change-Id: I61cf8d4041ce246b1f250408e7792301fb7b510f
Signed-off-by: Jinhyung Jo <jinhyung.jo@samsung.com>
tizen/src/hw/maru_device_ids.h
tizen/src/hw/virtio/Makefile.objs
tizen/src/hw/virtio/maru_virtio_pci.c
tizen/src/hw/virtio/maru_virtio_rotary.c [new file with mode: 0644]
tizen/src/hw/virtio/maru_virtio_rotary.h [new file with mode: 0644]
tizen/src/skin/maruskin_operation.c
tizen/src/skin/maruskin_operation.h
tizen/src/skin/maruskin_server.c

index ad6ec0a..0942e39 100644 (file)
@@ -50,6 +50,7 @@
 /* Device ID 0x1000 through 0x103F inclusive is a virtio device */
 #define PCI_DEVICE_ID_VIRTIO_TOUCHSCREEN 0x101D
 #define PCI_DEVICE_ID_VIRTIO_KEYBOARD    0x1020
+#define PCI_DEVICE_ID_VIRTIO_ROTARY      0x1022
 #define PCI_DEVICE_ID_VIRTIO_ESM         0x1024
 #define PCI_DEVICE_ID_VIRTIO_HWKEY       0x1028
 #define PCI_DEVICE_ID_VIRTIO_EVDI        0x102C
@@ -98,5 +99,6 @@
 #define VIRTIO_ID_JACK          39
 #define VIRTIO_ID_POWER         40
 #define VIRTIO_ID_VMODEM        41
+#define VIRTIO_ID_ROTARY        42
 
 #endif /* MARU_DEVICE_IDS_H_ */
index dd29fc4..026af61 100644 (file)
@@ -9,3 +9,4 @@ obj-y += maru_virtio_nfc.o
 obj-y += maru_virtio_power.o
 obj-y += maru_virtio_sensor.o
 obj-y += maru_virtio_vmodem.o
+obj-y += maru_virtio_rotary.o
index 78cac95..4be81af 100644 (file)
@@ -40,6 +40,7 @@
 #include "maru_virtio_power.h"
 #include "maru_virtio_nfc.h"
 #include "maru_virtio_vmodem.h"
+#include "maru_virtio_rotary.h"
 
 typedef struct VirtIOTouchscreenPCI VirtIOTouchscreenPCI;
 typedef struct VirtIOEVDIPCI VirtIOEVDIPCI;
@@ -51,6 +52,7 @@ typedef struct VirtIONFCPCI VirtIONFCPCI;
 typedef struct VirtIOPOWERPCI VirtIOPOWERPCI;
 typedef struct VirtIOJACKPCI VirtIOJACKPCI;
 typedef struct VirtIOVModemPCI VirtIOVModemPCI;
+typedef struct VirtIORotaryPCI VirtIORotaryPCI;
 
 /*
  * virtio-touchscreen-pci: This extends VirtioPCIProxy.
@@ -169,6 +171,17 @@ struct VirtIOVModemPCI {
     VirtIOVModem vdev;
 };
 
+/*
+ * virtio-rotary-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_ROTARY_PCI "virtio-rotary-pci"
+#define VIRTIO_ROTARY_PCI(obj) \
+        OBJECT_CHECK(VirtIORotaryPCI, (obj), TYPE_VIRTIO_ROTARY_PCI)
+struct VirtIORotaryPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIORotary vdev;
+};
+
 
 /* virtio-touchscreen-pci */
 
@@ -612,6 +625,47 @@ static TypeInfo virtio_vmodem_pci_info = {
     .class_init    = virtio_vmodem_pci_class_init,
 };
 
+/* virtio-rotary-pci */
+
+static int virtio_rotary_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIORotaryPCI *dev = VIRTIO_ROTARY_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_rotary_pci_class_init(ObjectClass *klass, void *data)
+{
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_rotary_pci_init;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_ROTARY;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_rotary_pci_instance_init(Object *obj)
+{
+    VirtIORotaryPCI *dev = VIRTIO_ROTARY_PCI(obj);
+    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_ROTARY);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static TypeInfo virtio_rotary_pci_info = {
+    .name          = TYPE_VIRTIO_ROTARY_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIORotaryPCI),
+    .instance_init = virtio_rotary_pci_instance_init,
+    .class_init    = virtio_rotary_pci_class_init,
+};
+
 static void maru_virtio_pci_register_types(void)
 {
     type_register_static(&virtio_evdi_pci_info);
@@ -624,6 +678,7 @@ static void maru_virtio_pci_register_types(void)
     type_register_static(&virtio_jack_pci_info);
     type_register_static(&virtio_power_pci_info);
     type_register_static(&virtio_vmodem_pci_info);
+    type_register_static(&virtio_rotary_pci_info);
 }
 
 type_init(maru_virtio_pci_register_types)
diff --git a/tizen/src/hw/virtio/maru_virtio_rotary.c b/tizen/src/hw/virtio/maru_virtio_rotary.c
new file mode 100644 (file)
index 0000000..ffd1858
--- /dev/null
@@ -0,0 +1,224 @@
+/*
+ * 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);
+
+static VirtIORotary *g_vrtr;
+static VirtQueueElement elem;
+
+static void virtio_rotary_handle(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIORotary *vrtr = VIRTIO_ROTARY(vdev);
+    int index = 0;
+
+    if (virtio_queue_empty(vrtr->vq)) {
+        LOG_INFO("[%s] virtio queue is empty\n", __func__);
+        return;
+    }
+
+    /* Get a queue buffer which is written by guest side. */
+    do {
+        index = virtqueue_pop(vq, &elem);
+        LOG_TRACE("[%s] virtqueue_pop: index(%d)\n", __func__, index);
+    } while (index < ROTARY_QUEUE_SIZE);
+}
+
+void maru_rotary_event(int32_t delta, int32_t type)
+{
+    MrRotaryEvent event = {0, };
+    uint32_t *index = NULL;
+
+    LOG_TRACE("[%s] ENTER: delta(%d), type(%d)\n", __func__, delta, type);
+
+    if (!g_vrtr) {
+        LOG_SEVERE("[%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;
+    }
+
+    index = &(g_vrtr->queue.idx);
+    LOG_TRACE("[%s] wptr(%u)\n", __func__, g_vrtr->queue.wptr);
+
+    if (*index == ROTARY_QUEUE_SIZE) {
+        *index = 0;
+    }
+    event.delta = delta;
+    event.type = type;
+
+    qemu_mutex_lock(&g_vrtr->mutex);
+    memcpy(&g_vrtr->queue.event[*index], &event, sizeof(MrRotaryEvent));
+    LOG_TRACE("[%s] event: delta(%d), type(%d), index(%u)\n",
+        __func__, event.delta, event.type, *index);
+    (*index)++;
+    g_vrtr->queue.wptr++;
+    qemu_mutex_unlock(&g_vrtr->mutex);
+    qemu_bh_schedule(g_vrtr->bh);
+    LOG_TRACE("[%s] LEAVE\n", __func__);
+}
+
+static void virtio_rotary_bh(void *opaque)
+{
+    VirtIORotary *vrtr = (VirtIORotary *)opaque;
+    MrRotaryEvent *cur_event;
+    uint32_t exec_cnt = 0;
+
+    LOG_TRACE("[%s] ENTER\n", __func__);
+
+    if (!vrtr) {
+        LOG_SEVERE("[%s] VirtIORotary instance is NULL\n", __func__);
+    }
+
+    if (unlikely(!virtio_queue_ready(vrtr->vq))) {
+        LOG_WARNING("[%s] virt queue is not ready\n", __func__);
+        return;
+    }
+
+    if (vrtr->queue.rptr == ROTARY_QUEUE_SIZE) {
+        vrtr->queue.rptr = 0;
+    }
+
+    qemu_mutex_lock(&vrtr->mutex);
+    exec_cnt = vrtr->queue.wptr;
+
+    while (exec_cnt--) {
+        cur_event = &vrtr->queue.event[vrtr->queue.rptr];
+
+        if (((MrRotaryEvent *)(elem.in_sg[vrtr->queue.rptr].iov_base))->delta
+            != 0) {
+            LOG_TRACE("[%s] FIXME: virtio queue is full\n", __func__);
+        }
+
+        memcpy(elem.in_sg[vrtr->queue.rptr].iov_base,
+            cur_event,
+            sizeof(MrRotaryEvent));
+        memset(cur_event, 0x00, sizeof(MrRotaryEvent));
+
+        if (vrtr->queue.wptr > 0) {
+            vrtr->queue.wptr--;
+            LOG_TRACE("[%s] exec_cnt(%u), wptr(%u), rptr(%u)\n",
+                    __func__, exec_cnt, vrtr->queue.wptr, vrtr->queue.rptr);
+        }
+
+        vrtr->queue.rptr++;
+        if (vrtr->queue.rptr == ROTARY_QUEUE_SIZE) {
+            vrtr->queue.rptr = 0;
+        }
+    }
+    qemu_mutex_unlock(&vrtr->mutex);
+
+    virtqueue_push(vrtr->vq, &elem, sizeof(MrRotaryEvent));
+    virtio_notify(&vrtr->vdev, vrtr->vq);
+    LOG_TRACE("[%s] LEAVE\n", __func__);
+}
+
+static uint32_t virtio_rotary_get_features(VirtIODevice *vdev,
+                                           uint32_t request_features)
+{
+    return request_features;
+}
+
+static void virtio_rotary_device_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+    VirtIORotary *vrtr = VIRTIO_ROTARY(vdev);
+
+    if (!vrtr) {
+        LOG_SEVERE("failed to initialize rotary device\n");
+        return;
+    }
+
+    virtio_init(vdev, TYPE_VIRTIO_ROTARY, VIRTIO_ID_ROTARY, 0);
+    qemu_mutex_init(&vrtr->mutex);
+
+    vrtr->vq = virtio_add_queue(&vrtr->vdev,
+                                ROTARY_QUEUE_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_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_ROTARY(vdev);
+
+    memset(&vrtr->queue, 0x00, sizeof(VirtIORotaryQueue));
+    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_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)
diff --git a/tizen/src/hw/virtio/maru_virtio_rotary.h b/tizen/src/hw/virtio/maru_virtio_rotary.h
new file mode 100644 (file)
index 0000000..5ba77a6
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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   512
+
+typedef struct MrRotaryEvent {
+    int32_t delta;
+    int32_t type;
+} MrRotaryEvent;
+
+typedef struct VirtIORotaryQueue {
+    uint32_t idx;
+    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;
+    VirtIORotaryQueue   queue;
+} VirtIORotary;
+
+#define TYPE_VIRTIO_ROTARY "virtio-rotary-device"
+#define VIRTIO_ROTARY(obj) \
+        OBJECT_CHECK(VirtIORotary, (obj), TYPE_VIRTIO_ROTARY)
+
+void maru_rotary_event(int32_t delta, int32_t type);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* MARU_ROTARY_H_ */
index 6fde27f..41cfabe 100644 (file)
@@ -52,6 +52,7 @@
 #include "util/maru_device_hotplug.h"
 #include "ecs/ecs.h"
 #include "hw/virtio/maru_virtio_evdi.h"
+#include "hw/virtio/maru_virtio_rotary.h"
 
 #ifdef CONFIG_HAX
 #include "target-i386/hax-i386.h"
@@ -678,3 +679,9 @@ static void send_shutdown_to_emuld(void)
 
     g_free(sndbuf);
 }
+
+void do_rotary_event(int32_t delta, int32_t type)
+{
+    TRACE("rotaty event: delta(%d), type(%d)\n", delta, type);
+    maru_rotary_event(delta, type);
+}
index 27b304e..d710021 100644 (file)
@@ -75,4 +75,5 @@ void request_close(void);
 void shutdown_qemu_gracefully(unsigned int sec);
 int is_requested_shutdown_qemu_gracefully(void);
 
+void do_rotary_event(int32_t delta, int32_t type);
 #endif /* MARUSKIN_OPERATION_H_ */
index 10d10e6..04aa75b 100644 (file)
@@ -1130,8 +1130,9 @@ static void* run_skin_server(void* args)
                     event_type = ntohl(event_type);
                     delta = ntohl(delta);
 
-                    // TODO:
-                    INFO("rotary event : %d\n", delta);
+                    TRACE("rotary event: delta(%d), event_type(%d)\n",
+                            delta, event_type);
+                    do_rotary_event(delta, event_type);
 
                     break;
                 }