From: Kitae Kim Date: Fri, 26 Oct 2012 06:45:19 +0000 (+0900) Subject: maru_virtio_keyboard : add virtio-keyboard driver. X-Git-Tag: 2.2.1_release^2~83^2~8 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=39d409ee93f8c47304ceaef5daa3da2a297c71c8;p=sdk%2Femulator%2Femulator-kernel.git maru_virtio_keyboard : add virtio-keyboard driver. Implement a driver for virtio-keyboard device. In addition to this, enable CONFIG_HOTPLUG_PCI_ACPI to support pci hotplug feature. Signed-off-by : Kitae Kim --- diff --git a/arch/x86/configs/i386_emul_defconfig b/arch/x86/configs/i386_emul_defconfig index 33a326c8df2d..c81834e9bedb 100644 --- a/arch/x86/configs/i386_emul_defconfig +++ b/arch/x86/configs/i386_emul_defconfig @@ -481,7 +481,7 @@ CONFIG_ACPI_THERMAL=y # CONFIG_ACPI_CUSTOM_DSDT is not set CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set -# CONFIG_ACPI_PCI_SLOT is not set +CONFIG_ACPI_PCI_SLOT=y CONFIG_X86_PM_TIMER=y CONFIG_ACPI_CONTAINER=y # CONFIG_ACPI_SBS is not set @@ -596,7 +596,8 @@ CONFIG_PCCARD_NONSTATIC=y CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set # CONFIG_HOTPLUG_PCI_COMPAQ is not set -# CONFIG_HOTPLUG_PCI_ACPI is not set +CONFIG_HOTPLUG_PCI_ACPI=y +# CONFIG_HOTPLUG_PCI_ACPI_IBM is not set # CONFIG_HOTPLUG_PCI_CPCI is not set # CONFIG_HOTPLUG_PCI_SHPC is not set # CONFIG_RAPIDIO is not set @@ -2775,6 +2776,7 @@ CONFIG_MARU_JACK=y CONFIG_MARU_POWER_SUPPLY=y CONFIG_MARU_USB_MASS_STORAGE=y CONFIG_MARU_USB_MODE=y +CONFIG_MARU_VIRTIO_KEYBOARD=y # # Firmware Drivers diff --git a/drivers/maru/Kconfig b/drivers/maru/Kconfig index 8313e4e23f24..c51aa27c57d4 100644 --- a/drivers/maru/Kconfig +++ b/drivers/maru/Kconfig @@ -55,3 +55,7 @@ config MARU_USB_MASS_STORAGE config MARU_USB_MODE tristate "MARU Usb mode Driver" depends on MARU != n + +config MARU_VIRTIO_KEYBOARD + tristate "MARU VirtIO Keyboard Driver" + depends on MARU != n diff --git a/drivers/maru/Makefile b/drivers/maru/Makefile index 5659e94e060b..8ae7d3c1d328 100644 --- a/drivers/maru/Makefile +++ b/drivers/maru/Makefile @@ -10,3 +10,4 @@ obj-$(CONFIG_MARU_JACK) += maru_jack.o obj-$(CONFIG_MARU_POWER_SUPPLY) += maru_power_supply.o obj-$(CONFIG_MARU_USB_MASS_STORAGE) += maru_usb_mass_storage.o obj-$(CONFIG_MARU_USB_MODE) += maru_usb_mode.o +obj-$(CONFIG_MARU_VIRTIO_KEYBOARD) += maru_virtio_keyboard.o diff --git a/drivers/maru/maru_virtio_keyboard.c b/drivers/maru/maru_virtio_keyboard.c new file mode 100644 index 000000000000..c7fc6515a219 --- /dev/null +++ b/drivers/maru/maru_virtio_keyboard.c @@ -0,0 +1,275 @@ +/* + * Maru Virtio Keyboard Device Driver + * + * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * Kitae Kim + * SeokYeon Hwang + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +MODULE_LICENSE("GPL2"); +MODULE_AUTHOR("Kitae Kim "); +MODULE_DESCRIPTION("Emulator Virtio Keyboard driver"); + +#define DEVICE_NAME "virtio-keyboard" + +struct EmulKbdEvent +{ + uint16_t code; + uint16_t value; +}; + +struct virtio_keyboard +{ + struct virtio_device *vdev; + struct virtqueue *vq; + struct input_dev *idev; + + struct EmulKbdEvent kbdevt; + struct scatterlist sg[2]; +}; + +struct virtio_keyboard *vkbd; + + +static struct virtio_device_id id_table[] = { + { VIRTIO_ID_KEYBOARD, VIRTIO_DEV_ANY_ID }, + { 0 }, +}; + +static void vq_keyboard_handle(struct virtqueue *vq) +{ + int err = 0; + int len = 0; + void *data; + + printk(KERN_INFO "virtio-keyboard: virtqueue callback\n"); + + data = virtqueue_get_buf(vq, &len); + if (!data) { + printk(KERN_INFO "virtio-keyboard: there is no used buffer.\n"); + return; + } + + printk(KERN_INFO "virtio-keyboard: keyboard event code: %d, value:%d\n", + vkbd->kbdevt.code, vkbd->kbdevt.value); + + /* how to get keycode and value. */ + input_event(vkbd->idev, EV_KEY, vkbd->kbdevt.code, vkbd->kbdevt.value); + input_sync(vkbd->idev); + + // TODO : need to improve codes which are about to buffer transfer. + err = virtqueue_add_buf (vq, vkbd->sg, 0, 1, (void *)1, GFP_ATOMIC); + if (err < 0) { + printk(KERN_ERR "virtio-keyboard: failed to add buffer to virtqueue.\n"); + return; + } + +#if 0 + err = virtqueue_add_buf (vq, &kbd->sg, 0, 1, (void *)1, GFP_ATOMIC); + if (err < 0) { + printk(KERN_ERR "virtio-keyboard: failed to add buffer to virtqueue.\n"); + return; + } + + virtqueue_kick(kbd->vq); + + while (!virtqueue_get_buf(kbd->vq, &len)) + cpu_relax(); +#endif + +} + +static int virtio_keyboard_open(struct inode *inode, struct file *file) +{ + printk(KERN_INFO "virtio-keyboard: opened\n"); + return 0; +} + +static int virtio_keyboard_release(struct inode *inode, struct file *file) +{ + printk(KERN_INFO "virtio-keyboard: closed\n"); + return 0; +} + +static int input_keyboard_open(struct input_dev *dev) +{ + printk(KERN_INFO "virtio-keyboard: input_keyboard_open\n"); + return 0; +} + +static void input_keyboard_close(struct input_dev *dev) +{ + printk(KERN_INFO "virtio-keyboard: input_keyboard_close\n"); +} + +struct file_operations virtio_keyboard_fops = { + .owner = THIS_MODULE, + .open = virtio_keyboard_open, + .release = virtio_keyboard_release, +}; + +static int virtio_keyboard_probe(struct virtio_device *vdev) +{ + int ret = 0; + + printk(KERN_INFO "virtio-keyboard: driver is probed\n"); + + vdev->priv = vkbd = kmalloc(sizeof(struct virtio_keyboard), GFP_KERNEL); + if (!vkbd) { + return -ENOMEM; + } + + vkbd->vdev = vdev; + + /* determine whether callback func needs or not */ + vkbd->vq = virtio_find_single_vq(vkbd->vdev, vq_keyboard_handle, "virtio-keyboard-vq"); + if (IS_ERR(vkbd->vq)) { + ret = PTR_ERR(vkbd->vq); + goto error1; + } + + /* register for input device */ + vkbd->idev = input_allocate_device(); + if (!vkbd->idev) { + printk(KERN_ERR "virtio-keyboard: failed to allocate a input device.\n"); + ret = -1; + goto error1; + } + + vkbd->idev->name = "Maru VirtIO Keyboard"; + vkbd->idev->dev.parent = &(vdev->dev); + + input_set_drvdata(vkbd->idev, vkbd); + vkbd->idev->open = input_keyboard_open; + vkbd->idev->close = input_keyboard_close; + + /* initialize a device as a keyboard device. + * refer to struct input_dev from input.h. */ + vkbd->idev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) + | BIT_MASK(EV_MSC) | BIT_MASK(EV_LED); + vkbd->idev->ledbit[0] = BIT_MASK(LED_NUML) | BIT_MASK(LED_CAPSL) + | BIT_MASK(LED_SCROLLL) | BIT_MASK(LED_COMPOSE) + | BIT_MASK(LED_KANA); + set_bit(MSC_SCAN, vkbd->idev->mscbit); + + // TODO : need to change keybit field. not to input fixed value. + vkbd->idev->keybit[0] = 0xfffffffe; + vkbd->idev->keybit[1] = 0xffffffff; + vkbd->idev->keybit[2] = 0xffefffff; + vkbd->idev->keybit[3] = 0xfebeffdf; + vkbd->idev->keybit[4] = 0xc14057ff; + vkbd->idev->keybit[5] = 0xff9f207a; + vkbd->idev->keybit[6] = 0x7; + vkbd->idev->keybit[7] = 0x10000; + + ret = input_register_device(vkbd->idev); + if (ret) { + printk(KERN_ERR "virtio-keyboard: failed to register a input device.\n"); + ret = -1; + goto error2; + } + +#if 1 + sg_init_table(vkbd->sg, 2); + sg_set_buf(vkbd->sg, &vkbd->kbdevt, sizeof(struct EmulKbdEvent) * 2); +#endif + + ret = virtqueue_add_buf(vkbd->vq, &vkbd->sg, 0, 1, (void *)1, GFP_ATOMIC); + if (ret < 0) { + printk(KERN_ERR "virtio-keyboard: failed to add buffer to virtqueue.\n"); + goto error3; + } + + virtqueue_kick(vkbd->vq); + + return 0; + +error3: + input_unregister_device(vkbd->idev); +error2: + input_free_device(vkbd->idev); +error1: + kfree(vkbd); + vdev->priv = NULL; + + return ret; +} + +static void __devexit virtio_keyboard_remove(struct virtio_device *vdev) +{ + struct virtio_keyboard *vkbd = vdev->priv; + + printk(KERN_INFO "virtio-keyboard: driver is removed.\n"); + + vdev->config->reset(vdev); + vdev->config->del_vqs(vdev); + + input_unregister_device(vkbd->idev); + input_free_device(vkbd->idev); +} + +MODULE_DEVICE_TABLE(virtio, id_table); + +static struct virtio_driver virtio_keyboard_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE, + }, + .id_table = id_table, + .probe = virtio_keyboard_probe, + .remove = virtio_keyboard_remove, +#if 0 +#ifdef CONFIG_PM + .freeze = virtio_codec_freeze, + .restore = virtio_codec_restore, +#endif +#endif +}; + +static int __init virtio_keyboard_init(void) +{ + printk(KERN_INFO "virtio-keyboard: driver is initialized.\n"); + return register_virtio_driver(&virtio_keyboard_driver); +} + +static void __exit virtio_keyboard_exit(void) +{ + printk(KERN_INFO "virtio-keyboard: driver is destroyed.\n"); + unregister_virtio_driver(&virtio_keyboard_driver); +} + +module_init(virtio_keyboard_init); +module_exit(virtio_keyboard_exit); diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h index 64858993c09f..7c0f21105689 100644 --- a/include/linux/virtio_ids.h +++ b/include/linux/virtio_ids.h @@ -41,7 +41,8 @@ #ifdef CONFIG_MARU /* Maru devices */ -#define VIRTIO_ID_TOUCHSCREEN 11 /* virtio touchscreen */ +#define VIRTIO_ID_TOUCHSCREEN 11 /* virtio touchscreen */ +#define VIRTIO_ID_KEYBOARD 12 /* virtio keyboard */ #endif #endif /* _LINUX_VIRTIO_IDS_H */