From 90ef98af956a8a2f17c6da84e1a43648a8c08c7b Mon Sep 17 00:00:00 2001 From: "jinhyung.jo" Date: Mon, 29 Dec 2014 20:17:00 +0900 Subject: [PATCH] rotary: Added a new input device Added a new input device for the maru board Change-Id: I61cf8d4041ce246b1f250408e7792301fb7b510f Signed-off-by: Jinhyung Jo --- tizen/src/hw/maru_device_ids.h | 2 + tizen/src/hw/virtio/Makefile.objs | 1 + tizen/src/hw/virtio/maru_virtio_pci.c | 55 ++++++++ tizen/src/hw/virtio/maru_virtio_rotary.c | 224 +++++++++++++++++++++++++++++++ tizen/src/hw/virtio/maru_virtio_rotary.h | 74 ++++++++++ tizen/src/skin/maruskin_operation.c | 7 + tizen/src/skin/maruskin_operation.h | 1 + tizen/src/skin/maruskin_server.c | 5 +- 8 files changed, 367 insertions(+), 2 deletions(-) create mode 100644 tizen/src/hw/virtio/maru_virtio_rotary.c create mode 100644 tizen/src/hw/virtio/maru_virtio_rotary.h diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index ad6ec0a..0942e39 100644 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -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_ */ diff --git a/tizen/src/hw/virtio/Makefile.objs b/tizen/src/hw/virtio/Makefile.objs index dd29fc4..026af61 100644 --- a/tizen/src/hw/virtio/Makefile.objs +++ b/tizen/src/hw/virtio/Makefile.objs @@ -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 diff --git a/tizen/src/hw/virtio/maru_virtio_pci.c b/tizen/src/hw/virtio/maru_virtio_pci.c index 78cac95..4be81af 100644 --- a/tizen/src/hw/virtio/maru_virtio_pci.c +++ b/tizen/src/hw/virtio/maru_virtio_pci.c @@ -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 index 0000000..ffd1858 --- /dev/null +++ b/tizen/src/hw/virtio/maru_virtio_rotary.c @@ -0,0 +1,224 @@ +/* + * Maru Virtio Rotary Device + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * 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 index 0000000..5ba77a6 --- /dev/null +++ b/tizen/src/hw/virtio/maru_virtio_rotary.h @@ -0,0 +1,74 @@ +/* + * Maru Virtio Rotary Device + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Jo + * Sangho Park + * + * 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_ */ diff --git a/tizen/src/skin/maruskin_operation.c b/tizen/src/skin/maruskin_operation.c index 6fde27f..41cfabe 100644 --- a/tizen/src/skin/maruskin_operation.c +++ b/tizen/src/skin/maruskin_operation.c @@ -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); +} diff --git a/tizen/src/skin/maruskin_operation.h b/tizen/src/skin/maruskin_operation.h index 27b304e..d710021 100644 --- a/tizen/src/skin/maruskin_operation.h +++ b/tizen/src/skin/maruskin_operation.h @@ -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_ */ diff --git a/tizen/src/skin/maruskin_server.c b/tizen/src/skin/maruskin_server.c index 10d10e6..04aa75b 100644 --- a/tizen/src/skin/maruskin_server.c +++ b/tizen/src/skin/maruskin_server.c @@ -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; } -- 2.7.4