From 41d2a8f8321d1b8209b411bb5ecec4a004d871e7 Mon Sep 17 00:00:00 2001 From: "giwoong.kim" Date: Tue, 19 Feb 2013 15:24:43 +0900 Subject: [PATCH] hwkey: added virtio hwkey device added virtio hwkey device Signed-off-by: GiWoong Kim --- hw/virtio-pci.c | 46 ++++++ tizen/src/Makefile.tizen | 1 + tizen/src/hw/maru_device_ids.h | 6 +- tizen/src/hw/maru_vga.c | 0 tizen/src/hw/maru_virtio_hwkey.c | 191 +++++++++++++++++++++++++ tizen/src/hw/maru_virtio_hwkey.h | 60 ++++++++ tizen/src/hw/maru_virtio_touchscreen.h | 4 +- 7 files changed, 304 insertions(+), 4 deletions(-) mode change 100755 => 100644 tizen/src/hw/maru_vga.c create mode 100644 tizen/src/hw/maru_virtio_hwkey.c create mode 100644 tizen/src/hw/maru_virtio_hwkey.h diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index 8ff80d9319..eb6e23603a 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -970,6 +970,29 @@ static void virtio_esm_exit_pci(PCIDevice *pci_dev) virtio_esm_exit(proxy->vdev); virtio_exit_pci(pci_dev); } + +static int virtio_hwkey_init_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + VirtIODevice *vdev; + + vdev = maru_virtio_hwkey_init(&pci_dev->qdev); + if (!vdev) { + return -1; + } + virtio_init_pci(proxy, vdev); + return 0; +} + +static void virtio_hwkey_exit_pci(PCIDevice *pci_dev) +{ + VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev); + + virtio_pci_stop_ioeventfd(proxy); + maru_virtio_hwkey_exit(proxy->vdev); + virtio_exit_pci(pci_dev); +} + #endif static Property virtio_blk_properties[] = { @@ -1245,6 +1268,28 @@ static TypeInfo virtio_esm_info = { .instance_size = sizeof(VirtIOPCIProxy), .class_init = virtio_esm_class_init, }; + +static void virtio_hwkey_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = virtio_hwkey_init_pci; + k->exit = virtio_hwkey_exit_pci; + k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET; + k->device_id = PCI_DEVICE_ID_VIRTIO_HWKEY; + k->revision = VIRTIO_PCI_ABI_VERSION; + k->class_id = PCI_CLASS_OTHERS; + dc->reset = virtio_pci_reset; +} + +static TypeInfo virtio_hwkey_info = { + .name = "virtio-hwkey-pci", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(VirtIOPCIProxy), + .class_init = virtio_hwkey_class_init, +}; + #endif /* CONFIG_MARU */ static void virtio_pci_register_types(void) @@ -1261,6 +1306,7 @@ static void virtio_pci_register_types(void) type_register_static(&maru_virtio_touchscreen_info); type_register_static(&virtio_keyboard_info); type_register_static(&virtio_esm_info); + type_register_static(&virtio_hwkey_info); #endif } diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen index dc1864a045..292f4621a1 100755 --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -112,6 +112,7 @@ obj-y += maru_usb_touchscreen.o maru_virtio_touchscreen.o obj-y += maru_virtio_keyboard.o obj-y += maru_codec.o obj-y += maru_virtio_esm.o +obj-y += maru_virtio_hwkey.o obj-$(CONFIG_PCI) += maru_camera_common_pci.o obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index 0fc77de5f9..8a2a0bd8e9 100644 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -1,7 +1,7 @@ /* * Maru Device IDs * - * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (C) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved. * * Contact: * SeokYeon Hwang @@ -49,8 +49,9 @@ #define PCI_DEVICE_ID_VIRTUAL_CODEC 0x101C /* 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_KEYBOARD 0x1020 #define PCI_DEVICE_ID_VIRTIO_ESM 0x1024 +#define PCI_DEVICE_ID_VIRTIO_HWKEY 0x1028 /* Virtio */ /* @@ -82,5 +83,6 @@ #define VIRTIO_ID_TOUCHSCREEN 11 #define VIRTIO_ID_KEYBOARD 12 #define VIRTIO_ID_ESM 13 +#define VIRTIO_ID_HWKEY 14 #endif /* MARU_DEVICE_IDS_H_ */ diff --git a/tizen/src/hw/maru_vga.c b/tizen/src/hw/maru_vga.c old mode 100755 new mode 100644 diff --git a/tizen/src/hw/maru_virtio_hwkey.c b/tizen/src/hw/maru_virtio_hwkey.c new file mode 100644 index 0000000000..a882820e62 --- /dev/null +++ b/tizen/src/hw/maru_virtio_hwkey.c @@ -0,0 +1,191 @@ +/* + * Maru Virtio HW Key Device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * 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 + * 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 +#include "console.h" +#include "emul_state.h" +#include "maru_virtio_hwkey.h" +#include "maru_device_ids.h" +#include "debug_ch.h" + +MULTI_DEBUG_CHANNEL(qemu, hwkey); + + +#define DEVICE_NAME "virtio-hwkey" + +/* + * HW key event queue + */ +typedef struct HwKeyEventEntry { + unsigned int index; + EmulHwKeyEvent hwkey; + + QTAILQ_ENTRY(HwKeyEventEntry) node; +} HwKeyEventEntry; + +/* the maximum number of HW key event that can be put into a queue */ +#define MAX_HWKEY_EVENT_CNT 64 + +static HwKeyEventEntry _events_buf[MAX_HWKEY_EVENT_CNT]; +static QTAILQ_HEAD(, HwKeyEventEntry) events_queue = + QTAILQ_HEAD_INITIALIZER(events_queue); + +static unsigned int event_ringbuf_cnt; /* _events_buf */ +static unsigned int event_queue_cnt; /* events_queue */ + +VirtIOHwKey *vhk; + +/* lock for between communication thread and IO thread */ +static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER; + + +void maru_hwkey_event(int event_type, int keycode) +{ + HwKeyEventEntry *entry = NULL; + + if (unlikely(event_queue_cnt >= MAX_HWKEY_EVENT_CNT)) { + INFO("full hwkey event queue, lose event\n", event_queue_cnt); + + qemu_bh_schedule(vhk->bh); + return; + } + + entry = &(_events_buf[event_ringbuf_cnt % MAX_HWKEY_EVENT_CNT]); + event_ringbuf_cnt++; + + /* hwkey event is copied into the queue */ + entry->hwkey.keycode = keycode; + entry->hwkey.event_type = event_type; + + pthread_mutex_lock(&event_mutex); + + entry->index = ++event_queue_cnt; // 1 ~ + + QTAILQ_INSERT_TAIL(&events_queue, entry, node); + + pthread_mutex_unlock(&event_mutex); + + /* call maru_virtio_hwkey_notify */ + qemu_bh_schedule(vhk->bh); + + TRACE("hwkey event (%d) : keycode=%d, event_type=%d\n", + entry->index, entry->hwkey.keycode, entry->hwkey.event_type); +} + +void maru_virtio_hwkey_notify(void) +{ + HwKeyEventEntry *event_entry = NULL; + + TRACE("maru_virtio_hwkey_notify\n"); + + while (true) { + if (event_queue_cnt == 0) { + TRACE("no event\n"); + break; + } + + /* get touch event from host queue */ + event_entry = QTAILQ_FIRST(&events_queue); + + TRACE("hwkey(%d) : keycode=%d, event_type=%d | \ + event_queue_cnt=%d\n", + event_entry->index, + event_entry->hwkey.keycode, event_entry->hwkey.event_type, + event_queue_cnt); + + /* copy event into virtio buffer */ + //memcpy(vbuf, &(event_entry->touch), sizeof(event_entry->touch)); + /* TODO: */ + if (KEY_PRESSED == event_entry->hwkey.event_type) { + ps2kbd_put_keycode(event_entry->hwkey.keycode & 0x7f); + } else if (KEY_RELEASED == event_entry->hwkey.event_type) { + ps2kbd_put_keycode(event_entry->hwkey.keycode | 0x80); + } else { + ERR("Unknown hwkey event type : keycode=%d, event_type=%d\n", + event_entry->hwkey.keycode, event_entry->hwkey.event_type); + } + + pthread_mutex_lock(&event_mutex); + + /* remove host event */ + QTAILQ_REMOVE(&events_queue, event_entry, node); + event_queue_cnt--; + + pthread_mutex_unlock(&event_mutex); + } +} + +static uint32_t virtio_hwkey_get_features( + VirtIODevice *vdev, uint32_t request_features) +{ + // TODO: + return request_features; +} + +static void maru_hwkey_bh(void *opaque) +{ + maru_virtio_hwkey_notify(); +} + +VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev) +{ + INFO("initialize the hwkey device\n"); + + vhk = (VirtIOHwKey *)virtio_common_init(DEVICE_NAME, + VIRTIO_ID_HWKEY, 0 /*config_size*/, sizeof(VirtIOHwKey)); + + if (vhk == NULL) { + ERR("failed to initialize the hwkey device\n"); + return NULL; + } + + vhk->vdev.get_features = virtio_hwkey_get_features; + vhk->qdev = dev; + + /* bottom-half */ + vhk->bh = qemu_bh_new(maru_hwkey_bh, vhk); + + return &(vhk->vdev); +} + +void maru_virtio_hwkey_exit(VirtIODevice *vdev) +{ + VirtIOHwKey *vhk = (VirtIOHwKey *)vdev; + + INFO("exit the hwkey device\n"); + + if (vhk->bh) { + qemu_bh_delete(vhk->bh); + } + + virtio_cleanup(vdev); + + pthread_mutex_destroy(&event_mutex); +} + diff --git a/tizen/src/hw/maru_virtio_hwkey.h b/tizen/src/hw/maru_virtio_hwkey.h new file mode 100644 index 0000000000..d80866aa3d --- /dev/null +++ b/tizen/src/hw/maru_virtio_hwkey.h @@ -0,0 +1,60 @@ +/* + * Maru Virtio HW Key Device + * + * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * 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 + * 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_HWKEY_H_ +#define MARU_HWKEY_H_ + +#include "console.h" +#include "hw/virtio.h" + +typedef struct VirtIOHwKey +{ + VirtIODevice vdev; + /* simply a queue into which buffers are posted + by the guest for consumption by the host */ + VirtQueue *vq; + + QEMUBH *bh; + DeviceState *qdev; +} VirtIOHwKey; + +/* This structure must match the kernel definitions */ +typedef struct EmulHwKeyEvent { + uint8_t event_type; + uint32_t keycode; +} EmulHwKeyEvent; + + +VirtIODevice *maru_virtio_hwkey_init(DeviceState *dev); +void maru_virtio_hwkey_exit(VirtIODevice *vdev); + +void maru_hwkey_event(int event_type, int keycode); +void maru_virtio_hwkey_notify(void); + +#endif /* MARU_HWKEY_H_ */ diff --git a/tizen/src/hw/maru_virtio_touchscreen.h b/tizen/src/hw/maru_virtio_touchscreen.h index 84c938ad25..b78abadc6d 100644 --- a/tizen/src/hw/maru_virtio_touchscreen.h +++ b/tizen/src/hw/maru_virtio_touchscreen.h @@ -1,7 +1,7 @@ /* - * Maru Virtual Virtio Touchscreen emulation + * Maru Virtio Touchscreen Device * - * Copyright (c) 2011 -2013 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd All Rights Reserved * * Contact: * GiWoong Kim -- 2.34.1