--- /dev/null
+/*
+ * Maru Virtio Input Device Driver
+ *
+ * Copyright (c) 2016 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
+ * GiWoong Kim <giwoong.kim@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_VIRTIO_H
+#define _MARU_VIRTIO_H
+
+#define MAX_BUF_COUNT 64
+
+struct maru_virtio_device {
+ struct virtio_device *vdev;
+ struct virtqueue *vq;
+ struct scatterlist sg[1];
+
+ spinlock_t lock;
+};
+
+// should be called in the lock
+static inline int add_new_buf(struct maru_virtio_device *mdev,
+ void *buf, unsigned int buf_size)
+{
+ int err = 0;
+
+ sg_init_one(mdev->sg, buf, buf_size);
+
+ err = virtqueue_add_inbuf(mdev->vq, mdev->sg,
+ 1, buf, GFP_ATOMIC);
+ if (err < 0) {
+ return err;
+ }
+
+ return 0;
+}
+
+static inline int init_virtio_device(struct virtio_device *vdev,
+ struct maru_virtio_device *mdev, vq_callback_t *c,
+ void *buf, unsigned int buf_size)
+{
+ int index;
+ int err = 0;
+ unsigned long flags;
+
+ spin_lock_init(&mdev->lock);
+
+ mdev->vdev = vdev;
+
+ mdev->vq = virtio_find_single_vq(mdev->vdev, c, "virtio-hwkey-vq");
+ if (IS_ERR(mdev->vq)) {
+ printk(KERN_ERR "failed to find virtqueue\n");
+ return PTR_ERR(mdev->vq);
+ }
+
+ spin_lock_irqsave(&mdev->lock, flags);
+ /* prepare the buffers */
+ for (index = 0; index < MAX_BUF_COUNT; index++) {
+ err = add_new_buf(mdev, buf + (index * buf_size), buf_size);
+ if (err < 0) {
+ spin_unlock_irqrestore(&mdev->lock, flags);
+ return err;
+ }
+ }
+ spin_unlock_irqrestore(&mdev->lock, flags);
+
+ virtqueue_kick(mdev->vq);
+
+ return 0;
+}
+
+static inline void deinit_virtio_device(struct virtio_device *vdev) {
+ vdev->config->reset(vdev);
+ vdev->config->del_vqs(vdev);
+}
+
+#endif //_MARU_VIRTIO_H
* Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
+ * SeokYeon Hwang <syeon.hwang@samsung.com>
* Sungmin Ha <sungmin82.ha@samsung.com>
- * Sangjin Kim <sangjin3.kim@samsung.com>
- * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <linux/virtio_config.h>
#include <linux/kthread.h>
+#include "maru_virtio_device.h"
+
MODULE_LICENSE("GPL2");
-MODULE_AUTHOR("Sungmin Ha <sungmin82.ha@samsung.com>");
+MODULE_AUTHOR("SeokYeon Hwangm <syeon.hwang@samsung.com>");
MODULE_DESCRIPTION("Emulator Virtio Hwkey driver");
#define DEVICE_NAME "virtio-hwkey"
-#define MAX_BUF_COUNT 64
-static int vqidx = 0;
/* This structure must match the qemu definitions */
-typedef struct EmulHwkeyEvent {
+struct hwkey_event {
uint8_t event_type;
uint32_t keycode;
-} EmulHwkeyEvent;
+};
-typedef struct virtio_hwkey
+struct virtio_hwkey
{
- struct virtio_device *vdev;
- struct virtqueue *vq;
- struct input_dev *idev;
+ struct maru_virtio_device *mdev;
- struct scatterlist sg[MAX_BUF_COUNT];
- struct EmulHwkeyEvent vbuf[MAX_BUF_COUNT];
-
- struct mutex event_mutex;
-} virtio_hwkey;
-
-virtio_hwkey *vh;
+ struct input_dev *idev;
+ struct hwkey_event evtbuf[MAX_BUF_COUNT];
+};
static struct virtio_device_id id_table[] = {
{ VIRTIO_ID_HWKEY, VIRTIO_DEV_ANY_ID },
KEY_RELEASED = 2,
};
-static int err = 0;
-static unsigned int index = 0;
-
/**
* @brief : callback for virtqueue
*/
static void vq_hwkey_callback(struct virtqueue *vq)
{
- struct EmulHwkeyEvent hwkey_event;
- unsigned int len = 0;
- void *token = NULL;
-#if 0
- printk(KERN_INFO "vq hwkey callback\n");
-#endif
- while (1) {
- memcpy(&hwkey_event, &vh->vbuf[vqidx], sizeof(hwkey_event));
- if (hwkey_event.event_type == 0) {
- break;
- }
- printk(KERN_INFO "keycode: %d, event_type: %d, vqidx: %d\n", hwkey_event.keycode, hwkey_event.event_type, vqidx);
- if (hwkey_event.event_type == KEY_PRESSED) {
- input_event(vh->idev, EV_KEY, hwkey_event.keycode, true);
+ unsigned int len; /* not used */
+ struct virtio_hwkey *vh = vq->vdev->priv;
+ struct maru_virtio_device *mdev = vh->mdev;
+ struct hwkey_event *event;
+
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&mdev->lock, flags);
+ while ((event = virtqueue_get_buf(mdev->vq, &len)) != NULL) {
+ spin_unlock_irqrestore(&mdev->lock, flags);
+
+ printk(KERN_INFO "keycode: %d, event_type: %d\n",
+ event->keycode, event->event_type);
+ if (event->event_type == KEY_PRESSED) {
+ input_event(vh->idev, EV_KEY, event->keycode, true);
}
- else if (hwkey_event.event_type == KEY_RELEASED) {
- input_event(vh->idev, EV_KEY, hwkey_event.keycode, false);
+ else if (event->event_type == KEY_RELEASED) {
+ input_event(vh->idev, EV_KEY, event->keycode, false);
}
else {
printk(KERN_ERR "Unknown event type\n");
}
input_sync(vh->idev);
- memset(&vh->vbuf[vqidx], 0x00, sizeof(hwkey_event));
- token = virtqueue_get_buf(vh->vq, &len);
- if (len > 0) {
- err = virtqueue_add_inbuf(vh->vq, vh->sg, MAX_BUF_COUNT, token, GFP_ATOMIC);
- }
- vqidx++;
- if (vqidx == MAX_BUF_COUNT) {
- vqidx = 0;
+ // add new buffer
+ spin_lock_irqsave(&mdev->lock, flags);
+ err = add_new_buf(mdev, event, sizeof(*event));
+ if (err < 0) {
+ printk(KERN_ERR "failed to add buffer\n");
}
}
- virtqueue_kick(vh->vq);
-}
-
-static int virtio_hwkey_open(struct inode *inode, struct file *file)
-{
- printk(KERN_INFO "virtio hwkey device is opened\n");
- return 0;
-}
-
-static int virtio_hwkey_release(struct inode *inode, struct file *file)
-{
- printk(KERN_INFO "virtio hwkey device is closed\n");
- return 0;
+ virtqueue_kick(mdev->vq);
+ spin_unlock_irqrestore(&mdev->lock, flags);
}
static int input_hwkey_open(struct input_dev *dev)
printk(KERN_INFO "input hwkey device is closed\n");
}
-struct file_operations virtio_hwkey_fops = {
- .owner = THIS_MODULE,
- .open = virtio_hwkey_open,
- .release = virtio_hwkey_release,
-};
-
static int virtio_hwkey_probe(struct virtio_device *vdev)
{
int ret = 0;
- vqidx = 0;
-
- printk(KERN_INFO "virtio hwkey driver is probed\n");
+ struct virtio_hwkey *vh;
/* init virtio */
- vdev->priv = vh = kmalloc(sizeof(*vh), GFP_KERNEL);
+ vdev->priv = vh = kzalloc(sizeof(*vh), GFP_KERNEL);
if (!vh) {
return -ENOMEM;
}
- memset(&vh->vbuf, 0x00, sizeof(vh->vbuf));
-
- vh->vdev = vdev;
-
- vh->vq = virtio_find_single_vq(vh->vdev, vq_hwkey_callback, "virtio-hwkey-vq");
- if (IS_ERR(vh->vq)) {
- ret = PTR_ERR(vh->vq);
-
- kfree(vh);
- vdev->priv = NULL;
- return ret;
- }
-
- /* enable callback */
- virtqueue_enable_cb(vh->vq);
-
- sg_init_table(vh->sg, MAX_BUF_COUNT);
-
- /* prepare the buffers */
- for (index = 0; index < MAX_BUF_COUNT; index++) {
- sg_set_buf(&vh->sg[index], &vh->vbuf[index], sizeof(EmulHwkeyEvent));
-
- if (err < 0) {
- printk(KERN_ERR "failed to add buffer\n");
-
- kfree(vh);
- vdev->priv = NULL;
- return ret;
- }
+ vh->mdev = kzalloc(sizeof(*vh->mdev), GFP_KERNEL);
+ if (!vh->mdev) {
+ ret = -ENOMEM;
+ goto err3;
}
- err = virtqueue_add_inbuf(vh->vq, vh->sg,
- MAX_BUF_COUNT, (void *)vh->vbuf, GFP_ATOMIC);
-
/* register for input device */
vh->idev = input_allocate_device();
if (!vh->idev) {
printk(KERN_ERR "failed to allocate a input hwkey device\n");
- ret = -1;
-
- kfree(vh);
- vdev->priv = NULL;
- return ret;
+ ret = -ENOMEM;
+ goto err2;
}
vh->idev->name = "Maru Virtio Hwkey";
vh->idev->evbit[0] = BIT_MASK(EV_KEY);
/* to support any keycode */
- memset(vh->idev->keybit, 0xffffffff, sizeof(unsigned long) * BITS_TO_LONGS(KEY_CNT));
+ memset(vh->idev->keybit, 0xffffffff,
+ sizeof(unsigned long) * BITS_TO_LONGS(KEY_CNT));
ret = input_register_device(vh->idev);
if (ret) {
printk(KERN_ERR "input hwkey driver cannot registered\n");
ret = -1;
+ goto err;
+ }
- input_free_device(vh->idev);
- kfree(vh);
- vdev->priv = NULL;
- return ret;
+ ret = init_virtio_device(vdev, vh->mdev, vq_hwkey_callback,
+ vh->evtbuf, sizeof(struct hwkey_event));
+ if (ret) {
+ goto err;
}
- virtqueue_kick(vh->vq);
- index = 0;
+ printk(KERN_INFO "virtio hwkey driver is probed\n");
return 0;
+
+err:
+ input_free_device(vh->idev);
+err2:
+ kfree(vh->mdev);
+err3:
+ kfree(vh);
+ vdev->priv = NULL;
+ return ret;
}
static void virtio_hwkey_remove(struct virtio_device *vdev)
{
- virtio_hwkey *vhk = NULL;
-
- printk(KERN_INFO "virtio hwkey driver is removed\n");
+ struct virtio_hwkey *vh = vdev->priv;
- vhk = vdev->priv;
+ input_unregister_device(vh->idev);
+ deinit_virtio_device(vdev);
- vdev->config->reset(vdev); /* reset device */
- vdev->config->del_vqs(vdev); /* clean up the queues */
+ kfree(vh);
- input_unregister_device(vhk->idev);
-
- kfree(vhk);
+ printk(KERN_INFO "virtio hwkey driver is removed\n");
}
MODULE_DEVICE_TABLE(virtio, id_table);
module_init(virtio_hwkey_init);
module_exit(virtio_hwkey_exit);
-
* Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
- * GiWoong Kim <giwoong.kim@samsung.com>
* SeokYeon Hwang <syeon.hwang@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include "maru_virtio_device.h"
MODULE_LICENSE("GPL2");
MODULE_AUTHOR("SeokYeon Hwangm <syeon.hwang@samsung.com>");
#define VKBD_LOG(log_level, fmt, ...) \
printk(log_level "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
-#define MAX_BUF_COUNT 100
-
//#define DEBUG
-struct EmulKbdEvent
+struct keyboard_event
{
uint16_t code;
uint16_t value;
struct virtio_keyboard
{
- struct virtio_device *vdev;
- struct virtqueue *vq;
- struct input_dev *idev;
+ struct maru_virtio_device *mdev;
- struct scatterlist sg[1];
- struct EmulKbdEvent evtbuf[MAX_BUF_COUNT];
-
- spinlock_t lock;
+ struct input_dev *idev;
+ struct keyboard_event evtbuf[MAX_BUF_COUNT];
};
static struct virtio_device_id id_table[] = {
{ 0 },
};
-static void vq_keyboard_handle(struct virtqueue *vq)
+static void vq_keyboard_callback(struct virtqueue *vq)
{
unsigned int len; /* not used */
struct virtio_keyboard *vkbd = vq->vdev->priv;
- struct EmulKbdEvent *event;
+ struct maru_virtio_device *mdev = vkbd->mdev;
+ struct keyboard_event *event;
unsigned long flags;
int err;
- spin_lock_irqsave(&vkbd->lock, flags);
- while ((event = virtqueue_get_buf(vkbd->vq, &len)) != NULL) {
- spin_unlock_irqrestore(&vkbd->lock, flags);
+ spin_lock_irqsave(&mdev->lock, flags);
+ while ((event = virtqueue_get_buf(mdev->vq, &len)) != NULL) {
+ spin_unlock_irqrestore(&mdev->lock, flags);
#ifdef DEBUG
printk(KERN_ERR "keyboard code = %d, value = %d\n", event->code,
event->value);
#endif
+
input_event(vkbd->idev, EV_KEY, event->code, event->value);
input_sync(vkbd->idev);
// add new buffer
- spin_lock_irqsave(&vkbd->lock, flags);
- sg_init_one(vkbd->sg, event, sizeof(*event));
- err = virtqueue_add_inbuf(vkbd->vq, vkbd->sg,
- 1, event, GFP_ATOMIC);
-
+ spin_lock_irqsave(&mdev->lock, flags);
+ err = add_new_buf(mdev, event, sizeof(*event));
if (err < 0) {
- printk(KERN_ERR "failed to add buffer!\n");
+ printk(KERN_ERR "failed to add buffer\n");
}
}
- virtqueue_kick(vkbd->vq);
- spin_unlock_irqrestore(&vkbd->lock, flags);
+ virtqueue_kick(mdev->vq);
+ spin_unlock_irqrestore(&mdev->lock, flags);
}
static int input_keyboard_open(struct input_dev *dev)
static int virtio_keyboard_probe(struct virtio_device *vdev)
{
int ret = 0;
- int index = 0;
- int err = 0;
- unsigned long flags;
struct virtio_keyboard *vkbd;
VKBD_LOG(KERN_INFO, "driver is probed\n");
if (!vkbd) {
return -ENOMEM;
}
-
- vkbd->vdev = vdev;
-
- vkbd->vq = virtio_find_single_vq(vkbd->vdev, vq_keyboard_handle, "virtio-keyboard-vq");
- if (IS_ERR(vkbd->vq)) {
- ret = PTR_ERR(vkbd->vq);
- kfree(vkbd);
- vdev->priv = NULL;
- return ret;
+ vkbd->mdev = kzalloc(sizeof(*vkbd->mdev), GFP_KERNEL);
+ if (!vkbd->mdev) {
+ ret = -ENOMEM;
+ goto err3;
}
/* register for input device */
vkbd->idev = input_allocate_device();
if (!vkbd->idev) {
VKBD_LOG(KERN_ERR, "failed to allocate a input device.\n");
- kfree(vkbd);
- vdev->priv = NULL;
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err2;
}
vkbd->idev->name = "Maru VirtIO Keyboard";
ret = input_register_device(vkbd->idev);
if (ret) {
VKBD_LOG(KERN_ERR, "failed to register a input device.\n");
- input_free_device(vkbd->idev);
- kfree(vkbd);
- vdev->priv = NULL;
- return ret;
+ goto err;
}
- spin_lock_irqsave(&vkbd->lock, flags);
- for (index = 0; index < MAX_BUF_COUNT; index++) {
- sg_init_one(vkbd->sg, &vkbd->evtbuf[index], sizeof(&vkbd->evtbuf[index]));
-
- err = virtqueue_add_inbuf(vkbd->vq, vkbd->sg,
- 1, &vkbd->evtbuf[index], GFP_ATOMIC);
-
- if (err < 0) {
- printk(KERN_ERR "failed to add buffer\n");
-
- kfree(vkbd);
- vdev->priv = NULL;
- return err;
- }
+ ret = init_virtio_device(vdev, vkbd->mdev, vq_keyboard_callback,
+ vkbd->evtbuf, sizeof(struct keyboard_event));
+ if (ret) {
+ goto err;
}
- spin_unlock_irqrestore(&vkbd->lock, flags);
- virtqueue_kick(vkbd->vq);
+ VKBD_LOG(KERN_INFO, "driver is probed\n");
return 0;
+
+err:
+ input_free_device(vkbd->idev);
+err2:
+ kfree(vkbd->mdev);
+err3:
+ kfree(vkbd);
+ vdev->priv = NULL;
+ return ret;
}
static void virtio_keyboard_remove(struct virtio_device *vdev)
{
struct virtio_keyboard *vkbd = vdev->priv;
- VKBD_LOG(KERN_INFO, "driver is removed.\n");
- if (!vkbd) {
- VKBD_LOG(KERN_ERR, "vkbd is NULL.\n");
- return;
- }
-
- vdev->config->reset(vdev);
- vdev->config->del_vqs(vdev);
-
input_unregister_device(vkbd->idev);
+ deinit_virtio_device(vdev);
kfree(vkbd);
- vkbd = NULL;
+
+ VKBD_LOG(KERN_INFO, "driver is removed.\n");
}
MODULE_DEVICE_TABLE(virtio, id_table);
* Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
- * GiWoong Kim <giwoong.kim@samsung.com>
* SeokYeon Hwang <syeon.hwang@samsung.com>
+ * GiWoong Kim <giwoong.kim@samsung.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
#include <linux/virtio_config.h>
#include <linux/kthread.h>
+#include "maru_virtio_device.h"
MODULE_LICENSE("GPL2");
MODULE_AUTHOR("SeokYeon Hwangm <syeon.hwang@samsung.com>");
#define MAX_TRKID 10
#define ABS_PRESSURE_MAX 255
-#define MAX_BUF_COUNT MAX_TRKID
-
//#define DEBUG
/* This structure must match the qemu definitions */
struct virtio_touchscreen
{
- struct virtio_device *vdev;
- struct input_dev *idev;
+ struct maru_virtio_device *mdev;
- struct virtqueue *vq;
- struct scatterlist sg[1];
+ struct input_dev *idev;
struct touch_event evtbuf[MAX_BUF_COUNT];
-
- spinlock_t lock;
};
static struct virtio_device_id id_table[] = {
unsigned int len; /* not used */
unsigned int finger_id; /* finger id */
struct virtio_touchscreen *vt = vq->vdev->priv;
+ struct maru_virtio_device *mdev = vt->mdev;
struct touch_event *event;
unsigned long flags;
int err;
- spin_lock_irqsave(&vt->lock, flags);
- while ((event = virtqueue_get_buf(vt->vq, &len)) != NULL) {
- spin_unlock_irqrestore(&vt->lock, flags);
+ spin_lock_irqsave(&mdev->lock, flags);
+ while ((event = virtqueue_get_buf(mdev->vq, &len)) != NULL) {
+ spin_unlock_irqrestore(&mdev->lock, flags);
#ifdef DEBUG
printk(KERN_INFO "touchscreen x=%d, y=%d, z=%d, state=%d, len=%d\n",
event->x, event->y, event->z, event->state, len);
}
// add new buffer
- spin_lock_irqsave(&vt->lock, flags);
- sg_init_one(vt->sg, event, sizeof(*event));
- err = virtqueue_add_inbuf(vt->vq, vt->sg,
- 1, event, GFP_ATOMIC);
-
+ spin_lock_irqsave(&mdev->lock, flags);
+ err = add_new_buf(mdev, event, sizeof(*event));
if (err < 0) {
- printk(KERN_ERR "failed to add buffer!\n");
+ printk(KERN_ERR "failed to add buffer\n");
}
}
- virtqueue_kick(vt->vq);
- spin_unlock_irqrestore(&vt->lock, flags);
+ virtqueue_kick(mdev->vq);
+ spin_unlock_irqrestore(&mdev->lock, flags);
}
static int input_touchscreen_open(struct input_dev *dev)
#define VM_RESOLUTION_KEY "vm_resolution="
-static int virtio_touchscreen_probe(struct virtio_device *vdev)
+static void get_resolution(unsigned long *width, unsigned long *height)
{
- unsigned long width = 0;
- unsigned long height = 0;
- char *cmdline = NULL;
- char *value = NULL;
- char *tmp = NULL;
int err = 0;
- int ret = 0;
-
- unsigned long flags;
- int index;
- struct virtio_touchscreen *vt;
-
- printk(KERN_INFO "virtio touchscreen driver is probed\n");
-
- /* init virtio */
- vdev->priv = vt = kzalloc(sizeof(*vt), GFP_KERNEL);
- if (!vt) {
- return -ENOMEM;
- }
-
- spin_lock_init(&vt->lock);
-
- vt->vdev = vdev;
-
- vt->vq = virtio_find_single_vq(vt->vdev,
- vq_touchscreen_callback, "virtio-touchscreen-vq");
- if (IS_ERR(vt->vq)) {
- ret = PTR_ERR(vt->vq);
-
- kfree(vt);
- vdev->priv = NULL;
- return ret;
- }
+ char *tmp = NULL;
+ char *value = NULL;
+ char *cmdline = kzalloc(strlen(saved_command_line) + 1, GFP_KERNEL);
- cmdline = kzalloc(strlen(saved_command_line) + 1, GFP_KERNEL);
if (cmdline) {
/* get VM resolution */
strcpy(cmdline, saved_command_line);
tmp += strlen(VM_RESOLUTION_KEY);
value = strsep(&tmp, "x");
- err = kstrtoul(value, 10, &width);
+ err = kstrtoul(value, 10, width);
if (err) {
printk(KERN_WARNING "vm width option is not defined\n");
- width = 0;
+ *width = 0;
}
value = strsep(&tmp, " ");
- err = kstrtoul(value, 10, &height);
+ err = kstrtoul(value, 10, height);
if (err) {
printk(KERN_WARNING "vm height option is not defined\n");
- height = 0;
+ *height = 0;
}
}
kfree(cmdline);
}
- if (width != 0 && height != 0) {
- printk(KERN_INFO "emul resolution : %lux%lu\n", width, height);
+ if (*width != 0 && *height != 0) {
+ printk(KERN_INFO "emul resolution : %lux%lu\n", *width, *height);
+ }
+}
+
+static int virtio_touchscreen_probe(struct virtio_device *vdev)
+{
+ unsigned long width = 0;
+ unsigned long height = 0;
+ int ret = 0;
+
+ struct virtio_touchscreen *vt;
+
+ /* init virtio */
+ vdev->priv = vt = kzalloc(sizeof(*vt), GFP_KERNEL);
+ if (!vt) {
+ return -ENOMEM;
}
+ vt->mdev = kzalloc(sizeof(*vt->mdev), GFP_KERNEL);
+ if (!vt->mdev) {
+ ret = -ENOMEM;
+ goto err3;
+ }
+
+ get_resolution(&width, &height);
/* register for input device */
vt->idev = input_allocate_device();
if (!vt->idev) {
printk(KERN_ERR "failed to allocate a input touchscreen device\n");
- ret = -1;
-
- kfree(vt);
- vdev->priv = NULL;
- return ret;
+ ret = -ENOMEM;
+ goto err2;
}
vt->idev->name = "Maru Virtio Touchscreen";
if (ret) {
printk(KERN_ERR "input touchscreen driver cannot registered\n");
ret = -1;
-
- input_mt_destroy_slots(vt->idev);
- input_free_device(vt->idev);
- kfree(vt);
- vdev->priv = NULL;
- return ret;
+ goto err;
}
- spin_lock_irqsave(&vt->lock, flags);
- /* prepare the buffers */
- for (index = 0; index < MAX_BUF_COUNT; index++) {
- sg_init_one(vt->sg, &vt->evtbuf[index], sizeof(&vt->evtbuf[index]));
-
- err = virtqueue_add_inbuf(vt->vq, vt->sg,
- 1, &vt->evtbuf[index], GFP_ATOMIC);
-
- if (err < 0) {
- printk(KERN_ERR "failed to add buffer\n");
-
- kfree(vt);
- vdev->priv = NULL;
- return err;
- }
+ ret = init_virtio_device(vdev, vt->mdev, vq_touchscreen_callback,
+ vt->evtbuf, sizeof(struct touch_event));
+ if (ret) {
+ goto err;
}
- spin_unlock_irqrestore(&vt->lock, flags);
- virtqueue_kick(vt->vq);
+ printk(KERN_INFO "virtio touchscreen driver is probed\n");
return 0;
+
+err:
+ input_free_device(vt->idev);
+err2:
+ kfree(vt->mdev);
+err3:
+ kfree(vt);
+ vdev->priv = NULL;
+ return ret;
}
static void virtio_touchscreen_remove(struct virtio_device *vdev)
{
- struct virtio_touchscreen *vt = NULL;
-
- printk(KERN_INFO "virtio touchscreen driver is removed\n");
-
- vt = vdev->priv;
-
- vdev->config->reset(vdev); /* reset device */
- vdev->config->del_vqs(vdev); /* clean up the queues */
+ struct virtio_touchscreen *vt = vdev->priv;
input_unregister_device(vt->idev);
input_mt_destroy_slots(vt->idev);
+ deinit_virtio_device(vdev);
kfree(vt);
+
+ printk(KERN_INFO "virtio touchscreen driver is removed\n");
}
MODULE_DEVICE_TABLE(virtio, id_table);