/*
- * Virtual device node for event injector of emulator
+ * Virtual device node
*
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
- * SooYoung Ha <yoosah.ha@samsung.com>
* JinHyung Choi <jinhyung2.choi@samsung.com>
+ * SooYoung Ha <yoosah.ha@samsung.com>
* Sungmin Ha <sungmin82.ha@samsung.com>
* YeongKyoon Lee <yeongkyoon.lee@samsung.com
*
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#define __MAX_BUF_SIZE 1024
+
+struct msg_info {
+ char buf[__MAX_BUF_SIZE];
+
+ uint16_t type;
+ uint16_t req;
+};
-int charger_online = 0;
-int earjack_online = 0;
-int earkey_online = 0;
-int hdmi_online = 0;
-int usb_online = 0;
+struct virtio_jack {
+ struct virtio_device* vdev;
+ struct virtqueue* vq;
+
+ struct msg_info msginfo;
+
+ struct scatterlist sg_vq[2];
+
+ int flags;
+ struct mutex lock;
+};
+
+enum jack_types {
+ jack_type_charger = 0,
+ jack_type_earjack,
+ jack_type_earkey,
+ jack_type_hdmi,
+ jack_type_usb,
+ jack_type_max
+};
+
+enum request_cmd {
+ request_get = 0,
+ request_set,
+ request_answer
+};
struct jack_data {
int no;
char buffer[50];
};
+struct virtio_jack *v_jack;
+
+static char jack_data [PAGE_SIZE];
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static struct virtio_device_id id_table[] = { { VIRTIO_ID_JACK,
+ VIRTIO_DEV_ANY_ID }, { 0 }, };
+
#define DEVICE_NAME "jack"
#define JACK_DEBUG
#define DLOG(level, fmt, ...)
#endif
+static void jack_vq_done(struct virtqueue *vq) {
+ unsigned int len;
+ struct msg_info* msg;
+
+ msg = (struct msg_info*) virtqueue_get_buf(v_jack->vq, &len);
+ if (msg == NULL) {
+ DLOG(KERN_ERR, "failed to virtqueue_get_buf");
+ return;
+ }
+
+ if (msg->req != request_answer || msg->buf == NULL) {
+ return;
+ }
+
+ DLOG(KERN_DEBUG, "msg buf: %s, req: %d, type: %d", msg->buf, msg->req, msg->type);
+
+ mutex_lock(&v_jack->lock);
+ strcpy(jack_data, msg->buf);
+ v_jack->flags ++;
+ DLOG(KERN_DEBUG, "flags : %d", v_jack->flags);
+ mutex_unlock(&v_jack->lock);
+
+ wake_up_interruptible(&wq);
+}
+
+static void set_jack_data(int type, const char* buf)
+{
+ int err = 0;
+
+ if (buf == NULL) {
+ DLOG(KERN_ERR, "set_jack buf is NULL.");
+ return;
+ }
+
+ if (v_jack == NULL) {
+ DLOG(KERN_ERR, "Invalid jack handle");
+ return;
+ }
+
+ mutex_lock(&v_jack->lock);
+ memset(jack_data, 0, PAGE_SIZE);
+ memset(&v_jack->msginfo, 0, sizeof(v_jack->msginfo));
+
+ strcpy(jack_data, buf);
+
+ v_jack->msginfo.req = request_set;
+ v_jack->msginfo.type = type;
+ strcpy(v_jack->msginfo.buf, buf);
+ mutex_unlock(&v_jack->lock);
+
+ DLOG(KERN_DEBUG, "set_jack_data type: %d, req: %d, buf: %s",
+ v_jack->msginfo.type, v_jack->msginfo.req, v_jack->msginfo.buf);
+
+ err = virtqueue_add_buf(v_jack->vq, v_jack->sg_vq, 1, 0, &v_jack->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ DLOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(v_jack->vq);
+}
+
+static void get_jack_data(int type)
+{
+ int err = 0;
+
+ if (v_jack == NULL) {
+ DLOG(KERN_ERR, "Invalid jack handle");
+ return;
+ }
+
+ mutex_lock(&v_jack->lock);
+ memset(jack_data, 0, PAGE_SIZE);
+ memset(&v_jack->msginfo, 0, sizeof(v_jack->msginfo));
+
+ v_jack->msginfo.req = request_get;
+ v_jack->msginfo.type = type;
+
+ mutex_unlock(&v_jack->lock);
+
+ DLOG(KERN_DEBUG, "get_jack_data type: %d, req: %d",
+ v_jack->msginfo.type, v_jack->msginfo.req);
+
+ err = virtqueue_add_buf(v_jack->vq, v_jack->sg_vq, 1, 1, &v_jack->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ DLOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(v_jack->vq);
+
+ wait_event_interruptible(wq, v_jack->flags != 0);
+
+ mutex_lock(&v_jack->lock);
+ v_jack->flags --;
+ DLOG(KERN_DEBUG, "flags : %d", v_jack->flags);
+ mutex_unlock(&v_jack->lock);
+}
+
static ssize_t show_charger_online(struct device *dev,
struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get charger_online: %d\n", charger_online);
- return snprintf(buf, PAGE_SIZE, "%d", charger_online);
+ get_jack_data(jack_type_charger);
+ return snprintf(buf, PAGE_SIZE, "%s", jack_data);
}
static ssize_t store_charger_online(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &charger_online);
- DLOG(KERN_INFO, "set charger_online: %d\n", charger_online);
-
+ set_jack_data(jack_type_charger, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_earjack_online(struct device *dev,
struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get earjack_online: %d\n", earjack_online);
- return snprintf(buf, PAGE_SIZE, "%d", earjack_online);
+ get_jack_data(jack_type_earjack);
+ return snprintf(buf, PAGE_SIZE, "%s", jack_data);
}
static ssize_t store_earjack_online(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &earjack_online);
- DLOG(KERN_INFO, "set earjack_online: %d\n", earjack_online);
-
+ set_jack_data(jack_type_earjack, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_earkey_online(struct device *dev,
struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get earkey_online: %d\n", earkey_online);
- return snprintf(buf, PAGE_SIZE, "%d", earkey_online);
+ get_jack_data(jack_type_earkey);
+ return snprintf(buf, PAGE_SIZE, "%s", jack_data);
}
static ssize_t store_earkey_online(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &earkey_online);
- DLOG(KERN_INFO, "set earkey_online: %d\n", earkey_online);
-
+ set_jack_data(jack_type_earkey, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_hdmi_online(struct device *dev,
struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get hdmi_online: %d\n", hdmi_online);
- return snprintf(buf, PAGE_SIZE, "%d", hdmi_online);
+ get_jack_data(jack_type_hdmi);
+ return snprintf(buf, PAGE_SIZE, "%s", jack_data);
}
static ssize_t store_hdmi_online(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &hdmi_online);
- DLOG(KERN_INFO, "set hdmi_online: %d\n", hdmi_online);
-
+ set_jack_data(jack_type_hdmi, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_usb_online(struct device *dev,
struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get usb_online: %d\n", usb_online);
- return snprintf(buf, PAGE_SIZE, "%d", usb_online);
+ get_jack_data(jack_type_usb);
+ return snprintf(buf, PAGE_SIZE, "%s", jack_data);
}
static ssize_t store_usb_online(struct device *dev,
struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &usb_online);
- DLOG(KERN_INFO, "set usb_online: %d\n", usb_online);
-
+ set_jack_data(jack_type_usb, buf);
return strnlen(buf, PAGE_SIZE);
}
+
static DEVICE_ATTR(charger_online, S_IRUGO | S_IWUSR, show_charger_online, store_charger_online);
static DEVICE_ATTR(earjack_online, S_IRUGO | S_IWUSR, show_earjack_online, store_earjack_online);
static DEVICE_ATTR(earkey_online, S_IRUGO | S_IWUSR, show_earkey_online, store_earkey_online);
}
};
-static int __init maru_jack_sysfs_init(void)
-{
- int err = 0;
+static int jack_probe(struct virtio_device* dev){
+ int err = 0, index = 0;
struct jack_data *data;
- DLOG(KERN_INFO, "sysfs_init\n");
+ DLOG(KERN_INFO, "jack_probe\n");
+
+ v_jack = kmalloc(sizeof(struct virtio_jack), GFP_KERNEL);
+
+ v_jack->vdev = dev;
+ dev->priv = v_jack;
+ v_jack->flags = 0;
err = platform_device_register(&the_pdev);
if (err) {
return err;
}
+ v_jack->vq = virtio_find_single_vq(dev, jack_vq_done, "jack");
+ if (IS_ERR(v_jack->vq)) {
+ DLOG(KERN_ERR, "virtio queue is not found.\n");
+ kfree(data);
+ platform_device_unregister(&the_pdev);
+ return err;
+ }
+
+ virtqueue_enable_cb(v_jack->vq);
+
+ memset(&v_jack->msginfo, 0x00, sizeof(v_jack->msginfo));
+
+ sg_init_table(v_jack->sg_vq, 2);
+ for (; index < 2; index++) {
+ sg_set_buf(&v_jack->sg_vq[index], &v_jack->msginfo, sizeof(v_jack->msginfo));
+ }
+
+ mutex_init(&v_jack->lock);
+
return 0;
}
-static void __exit maru_jack_sysfs_exit(void)
-{
+static void jack_remove(struct virtio_device* dev){
void *data = dev_get_drvdata(&the_pdev.dev);
DLOG(KERN_INFO, "sysfs_exit\n");
}
maru_jack_sysfs_remove_file(&the_pdev.dev);
platform_device_unregister(&the_pdev);
+
+ if (v_jack) {
+ kfree(v_jack);
+ v_jack = NULL;
+ }
+}
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+static struct virtio_driver virtio_jack_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE ,
+ },
+ .id_table = id_table,
+ .probe = jack_probe,
+ .remove = jack_remove,
+};
+
+static int __init maru_jack_init(void)
+{
+ DLOG(KERN_INFO, "maru_%s: init\n", DEVICE_NAME);
+ return register_virtio_driver(&virtio_jack_driver);
+}
+
+static void __exit maru_jack_exit(void)
+{
+ DLOG(KERN_INFO, "maru_%s: exit\n", DEVICE_NAME);
+ unregister_virtio_driver(&virtio_jack_driver);
}
-module_init(maru_jack_sysfs_init);
-module_exit(maru_jack_sysfs_exit);
+module_init(maru_jack_init);
+module_exit(maru_jack_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL2");
+MODULE_AUTHOR("Jinhyung Choi <jinhyung2.choi@samsung.com>");
+MODULE_DESCRIPTION("Emulator Virtio Power Driver");
/*
- * Virtual device node for event injector of emulator
+ * Virtual device node
*
- * Copyright (c) 2011 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
- * SooYoung Ha <yoosah.ha@samsung.com>
* JinHyung Choi <jinhyung2.choi@samsung.com>
+ * SooYoung Ha <yoosah.ha@samsung.com>
* Sungmin Ha <sungmin82.ha@samsung.com>
* YeongKyoon Lee <yeongkyoon.lee@samsung.com
*
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/fs.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
-static struct class *mtd_class;
-static struct device* mtd_device;
#define DEVICE_NAME "power_supply"
#define FILE_PERMISSION (S_IRUGO | S_IWUSR)
-#define HALF_CAPACITY 50
//#define DEBUG_MARU_POWER_SUPPLY
#define DLOG(level, fmt, ...)
#endif
-static int capacity = HALF_CAPACITY;
-static int charge_full = 0;
-static int charge_now = 0;
+#define __MAX_BUF_SIZE 1024
+
+static struct virtio_device_id id_table[] = { { VIRTIO_ID_POWER,
+ VIRTIO_DEV_ANY_ID }, { 0 }, };
+
+struct msg_info {
+ char buf[__MAX_BUF_SIZE];
+
+ uint16_t type;
+ uint16_t req;
+};
+
+struct virtio_power {
+ struct virtio_device* vdev;
+ struct virtqueue* vq;
+
+ struct msg_info msginfo;
+
+ struct scatterlist sg_vq[2];
+
+ int flags;
+ struct mutex lock;
+};
+
+enum power_types {
+ power_type_capacity = 0,
+ power_type_charge_full,
+ power_type_charge_now,
+ power_type_max
+};
+
+enum request_cmd {
+ request_get = 0,
+ request_set,
+ request_answer
+};
+
+struct virtio_power *v_power;
+
+static struct class* power_class;
+static struct device* power_device;
+
+static char power_data [PAGE_SIZE];
+
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
+static void power_vq_done(struct virtqueue *vq) {
+ unsigned int len;
+ struct msg_info* msg;
+
+ msg = (struct msg_info*) virtqueue_get_buf(v_power->vq, &len);
+ if (msg == NULL) {
+ DLOG(KERN_ERR, "failed to virtqueue_get_buf");
+ return;
+ }
+
+ if (msg->req != request_answer || msg->buf == NULL) {
+ return;
+ }
+
+ DLOG(KERN_DEBUG, "msg buf: %s, req: %d, type: %d", msg->buf, msg->req, msg->type);
+
+ mutex_lock(&v_power->lock);
+ strcpy(power_data, msg->buf);
+ v_power->flags ++;
+ DLOG(KERN_DEBUG, "flags : %d", v_power->flags);
+ mutex_unlock(&v_power->lock);
+
+ wake_up_interruptible(&wq);
+}
+
+static void set_power_data(int type, const char* buf)
+{
+ int err = 0;
+
+ if (buf == NULL) {
+ DLOG(KERN_ERR, "set_power buf is NULL.");
+ return;
+ }
+
+ if (v_power == NULL) {
+ DLOG(KERN_ERR, "Invalid power handle");
+ return;
+ }
+
+ mutex_lock(&v_power->lock);
+ memset(power_data, 0, PAGE_SIZE);
+ memset(&v_power->msginfo, 0, sizeof(v_power->msginfo));
+
+ strcpy(power_data, buf);
+
+ v_power->msginfo.req = request_set;
+ v_power->msginfo.type = type;
+ strcpy(v_power->msginfo.buf, buf);
+ mutex_unlock(&v_power->lock);
+
+ DLOG(KERN_DEBUG, "set_power_data type: %d, req: %d, buf: %s",
+ v_power->msginfo.type, v_power->msginfo.req, v_power->msginfo.buf);
+
+ err = virtqueue_add_buf(v_power->vq, v_power->sg_vq, 1, 0, &v_power->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ DLOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(v_power->vq);
+}
+
+static void get_power_data(int type)
+{
+ int err = 0;
+
+ if (v_power == NULL) {
+ DLOG(KERN_ERR, "Invalid power handle");
+ return;
+ }
+
+ mutex_lock(&v_power->lock);
+ memset(power_data, 0, PAGE_SIZE);
+ memset(&v_power->msginfo, 0, sizeof(v_power->msginfo));
+
+ v_power->msginfo.req = request_get;
+ v_power->msginfo.type = type;
+
+ mutex_unlock(&v_power->lock);
+
+ DLOG(KERN_DEBUG, "get_power_data type: %d, req: %d",
+ v_power->msginfo.type, v_power->msginfo.req);
+
+ err = virtqueue_add_buf(v_power->vq, v_power->sg_vq, 1, 1, &v_power->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ DLOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(v_power->vq);
+
+ wait_event_interruptible(wq, v_power->flags != 0);
+
+ mutex_lock(&v_power->lock);
+ v_power->flags --;
+ DLOG(KERN_DEBUG, "flags : %d", v_power->flags);
+ mutex_unlock(&v_power->lock);
+}
static ssize_t show_capacity(struct device *dev, struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get capacity: %d\n", capacity);
- return snprintf(buf, PAGE_SIZE, "%d", capacity);
+ get_power_data(power_type_capacity);
+ return snprintf(buf, PAGE_SIZE, "%s", power_data);
}
static ssize_t store_capacity(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &capacity);
- DLOG(KERN_INFO, "set capacity: %d\n", capacity);
-
+ set_power_data(power_type_capacity, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_charge_full(struct device *dev, struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get capacity_full: %d\n", capacity);
- return snprintf(buf, PAGE_SIZE, "%d", charge_full);
+ get_power_data(power_type_charge_full);
+ return snprintf(buf, PAGE_SIZE, "%s", power_data);
}
static ssize_t store_charge_full(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &charge_full);
- DLOG(KERN_INFO, "set capacity_full: %d\n", capacity);
-
+ set_power_data(power_type_charge_full, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t show_charge_now(struct device *dev, struct device_attribute *attr, char *buf)
{
- DLOG(KERN_INFO, "get capacity_now: %d\n", capacity);
- return snprintf(buf, PAGE_SIZE, "%d", charge_now);
+ get_power_data(power_type_charge_now);
+ return snprintf(buf, PAGE_SIZE, "%s", power_data);
}
static ssize_t store_charge_now(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &charge_now);
- DLOG(KERN_INFO, "set capacity_now: %d\n", capacity);
-
+ set_power_data(power_type_charge_now, buf);
return strnlen(buf, PAGE_SIZE);
}
__ATTR(charge_now, FILE_PERMISSION, show_charge_now, store_charge_now),
};
-struct device new_device_dev;
-
-static int __init maru_power_supply_sysfs_init(void)
+static void class_cleanup (void)
{
- int err = 0, i = 0;
+ int i = 2;
+
+ for (; i > 0; i--) {
+
+ if (power_device == NULL)
+ continue;
+
+ device_remove_file(power_device, &ps_device_attributes[i]);
- printk(KERN_INFO "maru_%s: sysfs_init\n", DEVICE_NAME);
+ device_unregister(power_device);
- mtd_class = class_create(THIS_MODULE, DEVICE_NAME);
- mtd_device = device_create(mtd_class, NULL, (dev_t)NULL, NULL, "battery");
+ device_destroy(power_class, (dev_t)NULL);
+ }
+
+ class_destroy(power_class);
+ power_class = NULL;
+}
+
+static int init_device(void)
+{
+ int err = 0, i = 0;
+ power_device = device_create(power_class, NULL, (dev_t)NULL, NULL, "battery");
for (i = 0; i < 3; i++) {
- err = device_create_file(mtd_device, &ps_device_attributes[i]);
+ err = device_create_file(power_device, &ps_device_attributes[i]);
if (err) {
printk(KERN_ERR
"maru_%s: failed to create power_supply files\n", DEVICE_NAME);
- break;
+ goto device_err;
}
}
- if (i != 3) {
- while (--i >= 0) {
- device_remove_file(mtd_device, &ps_device_attributes[i]);
- }
+ return err;
+device_err:
+ class_cleanup();
+ return -1;
+}
+
+static void cleanup(struct virtio_device* dev) {
+ dev->config->del_vqs(dev);
- device_unregister(mtd_device);
+ if (v_power) {
+ kfree(v_power);
+ v_power = NULL;
}
+ class_cleanup();
+}
+
+static int power_probe(struct virtio_device* dev)
+{
+ int err = 0;
+ int ret = 0;
+ int index = 0;
+
+ DLOG(KERN_INFO, "Power probe starts");
+
+ v_power = kmalloc(sizeof(struct virtio_power), GFP_KERNEL);
+
+ v_power->vdev = dev;
+ dev->priv = v_power;
+ v_power->flags = 0;
+
+ power_class = class_create(THIS_MODULE, DEVICE_NAME);
+ if (power_class == NULL) {
+ DLOG(KERN_ERR, "Power class creation is failed.");
+ return -1;
+ }
+
+ ret = init_device();
+ if (ret) {
+ cleanup(dev);
+ return ret;
+ }
+
+ v_power->vq = virtio_find_single_vq(dev, power_vq_done, "power");
+ if (IS_ERR(v_power->vq)) {
+ cleanup(dev);
+ DLOG(KERN_ERR, "failed to init virt queue");
+ return ret;
+ }
+
+ virtqueue_enable_cb(v_power->vq);
+
+ memset(&v_power->msginfo, 0x00, sizeof(v_power->msginfo));
+
+ sg_init_table(v_power->sg_vq, 2);
+ for (; index < 2; index++) {
+ sg_set_buf(&v_power->sg_vq[index], &v_power->msginfo, sizeof(v_power->msginfo));
+ }
+
+ mutex_init(&v_power->lock);
+
+ DLOG(KERN_INFO, "Power probe completes");
+
return err;
}
-static void __exit maru_power_supply_sysfs_exit(void)
+static void power_remove(struct virtio_device* dev)
+{
+ struct virtio_power* v_power = dev->priv;
+ if (!v_power)
+ {
+ DLOG(KERN_ERR, "virtio_power is NULL");
+ return;
+ }
+
+ dev->config->reset(dev);
+
+ cleanup(dev);
+
+ DLOG(KERN_INFO, "Power driver is removed.");
+}
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+
+static struct virtio_driver virtio_power_driver = {
+ .driver = {
+ .name = KBUILD_MODNAME,
+ .owner = THIS_MODULE ,
+ },
+ .id_table = id_table,
+ .probe = power_probe,
+ .remove = power_remove,
+};
+
+static int __init maru_power_supply_init(void)
+{
+ DLOG(KERN_INFO, "maru_%s: init\n", DEVICE_NAME);
+ return register_virtio_driver(&virtio_power_driver);
+}
+
+static void __exit maru_power_supply_exit(void)
{
- printk(KERN_INFO "maru_%s: sysfs_exit\n", DEVICE_NAME);
- class_destroy(mtd_class);
+ DLOG(KERN_INFO, "maru_%s: exit\n", DEVICE_NAME);
+ unregister_virtio_driver(&virtio_power_driver);
}
-module_init(maru_power_supply_sysfs_init);
-module_exit(maru_power_supply_sysfs_exit);
+module_init(maru_power_supply_init);
+module_exit(maru_power_supply_exit);
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL2");
+MODULE_AUTHOR("Jinhyung Choi <jinhyung2.choi@samsung.com>");
+MODULE_DESCRIPTION("Emulator Virtio Power Driver");
#define DRIVER_NAME "EVDI"
-#define LOG(fmt, ...) \
+#define LOGDEBUG(fmt, ...) \
+ printk(KERN_DEBUG "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
+
+#define LOGERR(fmt, ...) \
printk(KERN_ERR "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__)
#define NUM_OF_EVDI 2
ret = virtqueue_add_buf(vevdi->rvq, vevdi->sg_read, 0, 1, &vevdi->read_msginfo,
GFP_ATOMIC );
if (ret < 0) {
- LOG("failed to add buffer to virtqueue.(%d)\n", ret);
+ LOGERR("failed to add buffer to virtqueue.(%d)\n", ret);
return ret;
}
struct cdev *cdev = inode->i_cdev;
evdi_info = NULL;
- LOG("evdi_open\n");
+ LOGDEBUG("evdi_open\n");
for (i = 0; i < NUM_OF_EVDI; i++)
{
- LOG("evdi info index = %d, cdev dev = %d, inode dev = %d\n",
+ LOGDEBUG("evdi info index = %d, cdev dev = %d, inode dev = %d\n",
i, pevdi_info[i]->cdev.dev, cdev->dev);
if (pevdi_info[i]->cdev.dev == cdev->dev)
return ret;
- LOG("evdi_opened\n");
+ LOGDEBUG("evdi_opened\n");
return 0;
}
evdi_info = filp->private_data;
evdi_info->guest_connected = false;
- LOG("evdi_closed\n");
+ LOGDEBUG("evdi_closed\n");
return 0;
}
{
if (filp->f_flags & O_NONBLOCK)
{
- LOG("list is empty, return EAGAIN\n");
+ LOGERR("list is empty, return EAGAIN\n");
return -EAGAIN;
}
return -EFAULT;
next = list_first_entry(&vevdi->read_list, struct msg_buf, list);
if (next == NULL) {
- LOG("invliad list entry\n");
+ LOGERR("invliad list entry\n");
return -EFAULT;
}
if (add_inbuf(vevdi->rvq, &vevdi->read_msginfo) < 0)
{
- LOG("failed add_buf\n");
+ LOGERR("failed add_buf\n");
}
spin_unlock_irqrestore(&pevdi_info[EVID_READ]->inbuf_lock, flags);
-
- //LOG("evdi_read count = %d!\n", ++g_read_count);
-
if (ret < 0)
return -EFAULT;
int err = 0;
ssize_t ret = 0;
- //LOG("start of evdi_write len= %d, msglen = %d\n", len, sizeof(vevdi->send_msginfo));
+ LOGDEBUG("start of evdi_write len= %d, msglen = %d\n", len, sizeof(vevdi->send_msginfo));
if (vevdi == NULL) {
- LOG("invalid evdi handle\n");
+ LOGERR("invalid evdi handle\n");
return 0;
}
memset(&vevdi->send_msginfo, 0, sizeof(vevdi->send_msginfo));
ret = copy_from_user(&vevdi->send_msginfo, ubuf, sizeof(vevdi->send_msginfo));
- //LOG("copy_from_user ret = %d, msg = %s", ret, vevdi->send_msginfo.buf);
+ LOGDEBUG("copy_from_user ret = %d, msg = %s", ret, vevdi->send_msginfo.buf);
if (ret) {
ret = -EFAULT;
&_msg, GFP_ATOMIC);*/
if (err < 0) {
- LOG("failed to add buffer to virtqueue (err = %d)\n", err);
+ LOGERR("failed to add buffer to virtqueue (err = %d)\n", err);
return 0;
}
virtqueue_kick(vevdi->svq);
- //LOG("send to host\n");
+ LOGDEBUG("send to host\n");
return len;
}
if (has_readdata(evdi))
{
- LOG("POLLIN | POLLRDNORM\n");
+ LOGDEBUG("POLLIN | POLLRDNORM\n");
ret |= POLLIN | POLLRDNORM;
}
_msg = (struct msg_info*) virtqueue_get_buf(vevdi->rvq, &len);
if (_msg == NULL ) {
- LOG("failed to virtqueue_get_buf\n");
+ LOGERR("failed to virtqueue_get_buf\n");
return;
}
do {
- //LOG("msg use = %d\n", _msg->use);
- //LOG("msg data = %s\n", _msg->buf);
+ LOGDEBUG("msg use = %d\n", _msg->use);
+ LOGDEBUG("msg data = %s\n", _msg->buf);
/* insert into queue */
msgbuf = (struct msg_buf*) __xmalloc(SIZEOF_MSG_BUF);
memset(msgbuf, 0x00, sizeof(*msgbuf));
memcpy(&(msgbuf->msg), _msg, sizeof(*_msg));
- //LOG("copied msg data = %s, %s\n", msgbuf->msg.buf, _msg->buf);
+ LOGDEBUG("copied msg data = %s, %s\n", msgbuf->msg.buf, _msg->buf);
spin_lock_irqsave(&pevdi_info[EVID_READ]->inbuf_lock, flags);
list_add_tail(&msgbuf->list, &vevdi->read_list);
- //LOG("== wake_up_interruptible = %d!\n", ++g_wake_up_interruptible_count);
spin_unlock_irqrestore(&pevdi_info[EVID_READ]->inbuf_lock, flags);
int i, ret;
if (alloc_chrdev_region(&evdi_dev_number, 0, NUM_OF_EVDI, DEVICE_NAME) < 0) {
- LOG("fail to alloc_chrdev_region\n");
+ LOGERR("fail to alloc_chrdev_region\n");
return -1;
}
pevdi_info[i] = kmalloc(sizeof(struct virtevdi_info), GFP_KERNEL);
if (!pevdi_info[i]) {
- LOG("Bad malloc\n");
+ LOGERR("Bad malloc\n");
return -ENOMEM;
}
spin_lock_init(&pevdi_info[i]->outvq_lock);
if (ret == -1) {
- LOG("Bad cdev\n");
+ LOGERR("Bad cdev\n");
return ret;
}
ret = _init_device();
if (ret)
{
- LOG("failed to _init_device\n");
+ LOGERR("failed to _init_device\n");
return ret;
}
ret = init_vqs(vevdi);
kfree(vevdi);
dev->priv = NULL;
- LOG("failed to init_vqs\n");
+ LOGERR("failed to init_vqs\n");
return ret;
}
sg_init_one(vevdi->sg_read, &vevdi->read_msginfo, sizeof(vevdi->read_msginfo));
sg_init_one(vevdi->sg_send, &vevdi->send_msginfo, sizeof(vevdi->send_msginfo));
-
-
- LOG("EVDI Probe completed");
+ LOGDEBUG("EVDI Probe completed");
return 0;
}
struct virtio_evdi* _evdi = dev->priv;
if (!_evdi)
{
- LOG("evdi is NULL\n");
+ LOGERR("evdi is NULL\n");
return;
}
kfree(_evdi);
- LOG("driver is removed.\n");
+ LOGDEBUG("driver is removed.\n");
}
MODULE_DEVICE_TABLE(virtio, id_table);
static int __init evdi_init(void)
{
- LOG("EVDI driver initialized.\n");
+ LOGDEBUG("EVDI driver initialized.\n");
return register_virtio_driver(&virtio_evdi_driver);
}
unregister_virtio_driver(&virtio_evdi_driver);
- LOG("EVDI driver is destroyed.\n");
+ LOGDEBUG("EVDI driver is destroyed.\n");
}
module_init(evdi_init);
#include <linux/virtio.h>
#include <linux/virtio_ids.h>
#include <linux/virtio_config.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
#include <linux/cdev.h>
sensor_type_accel = 0,
sensor_type_geo,
sensor_type_gyro,
+ sensor_type_gyro_x,
+ sensor_type_gyro_y,
+ sensor_type_gyro_z,
sensor_type_light,
+ sensor_type_light_adc,
+ sensor_type_light_level,
sensor_type_proxi,
sensor_type_mag,
sensor_type_tilt,
struct virtio_sensor {
struct virtio_device* vdev;
- struct virtqueue* rvq;
- struct virtqueue* svq;
+ struct virtqueue* vq;
- struct msg_info read_msginfo;
- struct msg_info send_msginfo;
+ struct msg_info msginfo;
- struct scatterlist sg_read[2];
- struct scatterlist sg_send[2];
+ struct scatterlist sg_vq[2];
+
+ int flags;
+ struct mutex lock;
};
static struct virtio_device_id id_table[] = { { VIRTIO_ID_SENSOR,
static struct class* sensor_class;
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
#define __ATTR_RONLY(_name,_show) { \
.attr = { .name = __stringify(_name), .mode = 0444 }, \
.show = _show, \
.store = _name##_store, \
}
+static char sensor_data [PAGE_SIZE];
+
+static void sensor_vq_done(struct virtqueue *rvq) {
+ unsigned int len;
+ struct msg_info* msg;
+
+ msg = (struct msg_info*) virtqueue_get_buf(vs->vq, &len);
+ if (msg == NULL) {
+ LOG(KERN_ERR, "failed to virtqueue_get_buf");
+ return;
+ }
+
+ if (msg->req != request_answer || msg->buf == NULL) {
+ LOG(KERN_ERR, "message from host is cracked.");
+ return;
+ }
+
+ LOG(KERN_DEBUG, "msg buf: %s, req: %d, type: %d", msg->buf, msg->req, msg->type);
+
+ mutex_lock(&vs->lock);
+ strcpy(sensor_data, msg->buf);
+ vs->flags = 1;
+ mutex_unlock(&vs->lock);
+
+ wake_up_interruptible(&wq);
+}
+
+static void set_sensor_data(int type, const char* buf)
+{
+ int err = 0;
+
+ if (buf == NULL) {
+ LOG(KERN_ERR, "set_sensor buf is NULL.");
+ return;
+ }
+
+ if (vs == NULL) {
+ LOG(KERN_ERR, "Invalid sensor handle");
+ return;
+ }
+
+ mutex_lock(&vs->lock);
+ memset(sensor_data, 0, PAGE_SIZE);
+ memset(&vs->msginfo, 0, sizeof(vs->msginfo));
+
+ strcpy(sensor_data, buf);
+
+ vs->msginfo.req = request_set;
+ vs->msginfo.type = type;
+ strcpy(vs->msginfo.buf, buf);
+ mutex_unlock(&vs->lock);
+
+ LOG(KERN_DEBUG, "set_sensor_data type: %d, req: %d, buf: %s",
+ vs->msginfo.type, vs->msginfo.req, vs->msginfo.buf);
+
+ err = virtqueue_add_buf(vs->vq, vs->sg_vq, 1, 0, &vs->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ LOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(vs->vq);
+}
+
+static void get_sensor_data(int type)
+{
+ int err = 0;
+
+ if (vs == NULL) {
+ LOG(KERN_ERR, "Invalid sensor handle");
+ return;
+ }
+
+ mutex_lock(&vs->lock);
+ memset(sensor_data, 0, PAGE_SIZE);
+ memset(&vs->msginfo, 0, sizeof(vs->msginfo));
+
+ vs->msginfo.req = request_get;
+ vs->msginfo.type = type;
+
+ mutex_unlock(&vs->lock);
+
+ LOG(KERN_DEBUG, "get_sensor_data type: %d, req: %d",
+ vs->msginfo.type, vs->msginfo.req);
+
+ err = virtqueue_add_buf(vs->vq, vs->sg_vq, 1, 1, &vs->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ LOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(vs->vq);
+
+ wait_event_interruptible(wq, vs->flags != 0);
+
+ mutex_lock(&vs->lock);
+ vs->flags = 0;
+ mutex_unlock(&vs->lock);
+}
+
/*
* Accelerometer
*/
#define ACCEL_NAME_STR "accel_sim"
#define ACCEL_FILE_NUM 2
-static char accel_xyz [__MAX_BUF_SENSOR] = {'0',',','9','8','0','6','6','5',',','0'};
-
static ssize_t accel_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, ACCEL_NAME_STR);
static ssize_t xyz_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s", accel_xyz);
+ get_sensor_data(sensor_type_accel);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t xyz_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- strcpy(accel_xyz, buf);
+ set_sensor_data(sensor_type_accel, buf);
return strnlen(buf, PAGE_SIZE);
}
#define GEO_NAME_STR "geo_sim"
#define GEO_FILE_NUM 3
-static char geo_raw [__MAX_BUF_SENSOR] = {'0',' ','-','9','0',' ','0',' ','3'};
-static char geo_tesla [__MAX_BUF_SENSOR] = {'1',' ','0',' ','-','1','0'};
-
static ssize_t geo_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, GEO_NAME_STR);
static ssize_t raw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s", geo_raw);
+ get_sensor_data(sensor_type_tilt);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- strcpy(geo_raw, buf);
+ set_sensor_data(sensor_type_tilt, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t tesla_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%s", geo_tesla);
+ get_sensor_data(sensor_type_mag);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t tesla_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- strcpy(geo_tesla, buf);
+ set_sensor_data(sensor_type_mag, buf);
return strnlen(buf, PAGE_SIZE);
}
#define GYRO_NAME_STR "gyro_sim"
#define GYRO_FILE_NUM 4
-static int gyro_x_raw = 0;
-static int gyro_y_raw = 0;
-static int gyro_z_raw = 0;
-
static ssize_t gyro_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, GYRO_NAME_STR);
static ssize_t gyro_x_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", gyro_x_raw);
+ get_sensor_data(sensor_type_gyro_x);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t gyro_x_raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &gyro_x_raw);
+ set_sensor_data(sensor_type_gyro_x, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t gyro_y_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", gyro_y_raw);
+ get_sensor_data(sensor_type_gyro_y);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t gyro_y_raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &gyro_y_raw);
+ set_sensor_data(sensor_type_gyro_y, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t gyro_z_raw_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", gyro_z_raw);
+ get_sensor_data(sensor_type_gyro_z);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t gyro_z_raw_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &gyro_z_raw);
+ set_sensor_data(sensor_type_gyro_z, buf);
return strnlen(buf, PAGE_SIZE);
}
#define LIGHT_NAME_STR "light_sim"
#define LIGHT_FILE_NUM 3
-static int light_adc = 65535;
-static int light_level = 10;
-
static ssize_t light_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
return snprintf(buf, PAGE_SIZE, LIGHT_NAME_STR);
static ssize_t adc_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", light_adc);
+ get_sensor_data(sensor_type_light_adc);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t adc_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &light_adc);
+ set_sensor_data(sensor_type_light_adc, buf);
return strnlen(buf, PAGE_SIZE);
}
static ssize_t level_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", light_level);
+ get_sensor_data(sensor_type_light_level);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t level_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &light_level);
+ set_sensor_data(sensor_type_light_level, buf);
return strnlen(buf, PAGE_SIZE);
}
#define PROXI_FILE_NUM 3
static int proxi_enable = 1;
-static int proxi_vo = 8;
static ssize_t proxi_name_show(struct device *dev, struct device_attribute *attr, char *buf)
{
static ssize_t vo_show(struct device *dev, struct device_attribute *attr, char *buf)
{
- return snprintf(buf, PAGE_SIZE, "%d", proxi_vo);
+ get_sensor_data(sensor_type_proxi);
+ return snprintf(buf, PAGE_SIZE, "%s", sensor_data);
}
static ssize_t vo_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
- sscanf(buf, "%d", &proxi_vo);
+ set_sensor_data(sensor_type_proxi, buf);
return strnlen(buf, PAGE_SIZE);
}
return -1;
}
-static int _make_buf_and_kick(void)
-{
- int ret;
- memset(&vs->read_msginfo, 0x00, sizeof(vs->read_msginfo));
- ret = virtqueue_add_buf(vs->rvq, vs->sg_read, 0, 1, &vs->read_msginfo, GFP_ATOMIC );
- if (ret < 0) {
- LOG(KERN_ERR, "failed to add buffer to virtqueue.(%d)\n", ret);
- return ret;
- }
-
- virtqueue_kick(vs->rvq);
-
- return 0;
-}
-
-static void get_sensor_value(int type)
-{
- int err = 0;
-
- if (vs == NULL) {
- LOG(KERN_ERR, "Invalid sensor handle");
- return;
- }
-
- memset(&vs->send_msginfo, 0, sizeof(vs->send_msginfo));
-
- vs->send_msginfo.req = request_answer;
-
- switch (type) {
- case sensor_type_accel:
- vs->send_msginfo.type = sensor_type_accel;
- strcpy(vs->send_msginfo.buf, accel_xyz);
- break;
- case sensor_type_mag:
- vs->send_msginfo.type = sensor_type_mag;
- strcpy(vs->send_msginfo.buf, geo_tesla);
- break;
- case sensor_type_gyro:
- vs->send_msginfo.type = sensor_type_gyro;
- sprintf(vs->send_msginfo.buf, "%d, %d, %d", gyro_x_raw, gyro_y_raw, gyro_z_raw);
- break;
- case sensor_type_light:
- vs->send_msginfo.type = sensor_type_light;
- sprintf(vs->send_msginfo.buf, "%d", light_adc);
- break;
- case sensor_type_proxi:
- vs->send_msginfo.type = sensor_type_proxi;
- sprintf(vs->send_msginfo.buf, "%d", proxi_vo);
- break;
- default:
- return;
- }
-
- LOG(KERN_INFO, "vs->send_msginfo type: %d, req: %d, buf: %s",
- vs->send_msginfo.type, vs->send_msginfo.req, vs->send_msginfo.buf);
-
- err = virtqueue_add_buf(vs->svq, vs->sg_send, 1, 0, &vs->send_msginfo, GFP_ATOMIC);
- if (err < 0) {
- LOG(KERN_ERR, "failed to add buffer to virtqueue (err = %d)", err);
- return;
- }
-
- virtqueue_kick(vs->svq);
-}
-
-static void set_sensor_value(char* buf, int type)
-{
-
- LOG(KERN_INFO, "set_sensor_value- type: %d, buf: %s", type, buf);
-
- switch (type) {
- case sensor_type_accel:
- strcpy(accel_xyz, buf);
- break;
- case sensor_type_gyro:
- sscanf(buf, "%d %d %d", &gyro_x_raw, &gyro_y_raw, &gyro_z_raw);
- break;
- case sensor_type_light:
- sscanf(buf, "%d", &light_adc);
- light_level = (light_adc / 6554) % 10 + 1;
- break;
- case sensor_type_proxi:
- sscanf(buf, "%d", &proxi_vo);
- break;
- case sensor_type_mag:
- strcpy(geo_tesla, buf);
- break;
- case sensor_type_tilt:
- strcpy(geo_raw, buf);
- break;
- default:
- return;
- }
-
-}
-
-static void message_handler(char* buf, int req, int type)
-{
- if (req == request_get) {
- get_sensor_value(type);
- } else if (req == request_set) {
- set_sensor_value(buf, type);
- } else {
- LOG(KERN_INFO, "wrong message request");
- }
-}
-
-static void sensor_recv_done(struct virtqueue *rvq) {
- unsigned int len;
- struct msg_info* msg;
-
- msg = (struct msg_info*) virtqueue_get_buf(vs->rvq, &len);
- if (msg == NULL ) {
- LOG(KERN_ERR, "failed to virtqueue_get_buf");
- return;
- }
-
- LOG(KERN_INFO, "msg buf: %s, req: %d, type: %d", msg->buf, msg->req, msg->type);
-
- message_handler(msg->buf, msg->req, msg->type);
-
- _make_buf_and_kick();
-}
-
-static void sensor_send_done(struct virtqueue *svq) {
- unsigned int len = 0;
-
- virtqueue_get_buf(svq, &len);
-}
-
-static int init_vqs(struct virtio_sensor *vsensor) {
- struct virtqueue *vqs[2];
- vq_callback_t *vq_callbacks[] = { sensor_recv_done, sensor_send_done };
- const char *vq_names[] = { "sensor_input", "sensor_output" };
- int err;
-
- err = vs->vdev->config->find_vqs(vs->vdev, 2, vqs, vq_callbacks, vq_names);
- if (err < 0)
- return err;
-
- vs->rvq = vqs[0];
- vs->svq = vqs[1];
-
- virtqueue_enable_cb(vs->rvq);
- virtqueue_enable_cb(vs->svq);
-
- return 0;
-}
-
static void cleanup(struct virtio_device* dev) {
dev->config->del_vqs(dev);
{
int err = 0;
int ret = 0;
+ int index = 0;
LOG(KERN_INFO, "Sensor probe starts");
return ret;
}
- ret = init_vqs(vs);
- if (ret) {
+ vs->vq = virtio_find_single_vq(dev, sensor_vq_done, "sensor");
+ if (IS_ERR(vs->vq)) {
cleanup(dev);
- LOG(KERN_ERR, "failed to init vqs");
+ LOG(KERN_ERR, "failed to init virt queue");
return ret;
}
- memset(&vs->read_msginfo, 0x00, sizeof(vs->read_msginfo));
- sg_set_buf(vs->sg_read, &vs->read_msginfo, sizeof(struct msg_info));
+ virtqueue_enable_cb(vs->vq);
- memset(&vs->send_msginfo, 0x00, sizeof(vs->send_msginfo));
- sg_set_buf(vs->sg_send, &vs->send_msginfo, sizeof(struct msg_info));
+ memset(&vs->msginfo, 0x00, sizeof(vs->msginfo));
- sg_init_one(vs->sg_read, &vs->read_msginfo, sizeof(vs->read_msginfo));
- sg_init_one(vs->sg_send, &vs->send_msginfo, sizeof(vs->send_msginfo));
-
- ret = _make_buf_and_kick();
- if (ret) {
- cleanup(dev);
- LOG(KERN_ERR, "failed to send buf");
- return ret;
+ sg_init_table(vs->sg_vq, 2);
+ for (; index < 2; index++) {
+ sg_set_buf(&vs->sg_vq[index], &vs->msginfo, sizeof(vs->msginfo));
}
+ mutex_init(&vs->lock);
+
LOG(KERN_INFO, "Sensor probe completes");
return err;
}
-
-
-static void __devexit sensor_remove(struct virtio_device* dev)
+static void sensor_remove(struct virtio_device* dev)
{
struct virtio_sensor* vs = dev->priv;
if (!vs)
#define VIRTIO_ID_GL 36 /* virtio glmem */
#define VIRTIO_ID_SENSOR 37 /* virtio sensor */
#define VIRTIO_ID_NFC 38 /* virtio nfc */
+#define VIRTIO_ID_JACK 39 /* virtio jack */
+#define VIRTIO_ID_POWER 40 /* virtio power supply */
#endif
#endif /* _LINUX_VIRTIO_IDS_H */
+* 1.4.32
+- Data is moved into qemu for jacks, battery, and sensors
+== Jinhyung Choi <jinhyung2.choi@samsung.com> 2014-03-06
* 1.4.31
- Implemented multicore rendering and fences
== GiWoong Kim <giwoong.kim@samsung.com> 2014-01-17
-Version: 1.4.31
+Version: 1.4.32
Maintainer: Yeong-Kyoon, Lee <yeongkyoon.lee@samsung.com>
Source: emulator-kernel