Jack/power/sensor: Data is moved into qemu 40/17240/1
authorJinhyung Choi <jinhyung2.choi@samsung.com>
Thu, 6 Mar 2014 05:22:54 +0000 (14:22 +0900)
committerJinhyung Choi <jinhyung2.choi@samsung.com>
Thu, 6 Mar 2014 05:22:54 +0000 (14:22 +0900)
- data is moved into qemu
- evdi logs are separated into debug and error

Change-Id: Ie4ee5af44f454dcd63e34089444dd0c402b38adc
Signed-off-by: Jinhyung Choi <jinhyung2.choi@samsung.com>
drivers/maru/maru_jack.c
drivers/maru/maru_power_supply.c
drivers/maru/maru_virtio_evdi.c
drivers/maru/maru_virtio_sensor.c
include/linux/virtio_ids.h
package/changelog
package/pkginfo.manifest

index f60265a56cf0291633df502564ace766fbcd06e1..6ae299177ae141d44193a426ca36dcf8dad46d61 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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
 
@@ -55,85 +104,175 @@ struct jack_data {
 #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);
@@ -204,12 +343,17 @@ static struct platform_device the_pdev = {
        }
 };
 
-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) {
@@ -234,11 +378,29 @@ static int __init maru_jack_sysfs_init(void)
                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");
@@ -248,9 +410,40 @@ static void __exit maru_jack_sysfs_exit(void)
        }
        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");
index 0c3a5f19353279f74789b28395a2505e8eab3ea5..10429db1f58d5fcc4412e6f65cba29f256d0f72b 100644 (file)
@@ -1,11 +1,11 @@
 /*
- * 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
 
@@ -49,49 +57,184 @@ static struct device* mtd_device;
 #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);
 }
 
@@ -101,44 +244,149 @@ static struct device_attribute ps_device_attributes[] = {
        __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");
index 7ba946d48ef4a3fa17608d8afdaedaeb4979a7bb..a77e8a19a784a6f9453f2d9a3dd306a7bc4a0022 100644 (file)
 
 #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
@@ -145,7 +148,7 @@ int _make_buf_and_kick(void)
        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;
        }
 
@@ -191,11 +194,11 @@ static int evdi_open(struct inode* inode, struct file* filp)
        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)
@@ -215,7 +218,7 @@ static int evdi_open(struct inode* inode, struct file* filp)
                return ret;
 
 
-       LOG("evdi_opened\n");
+       LOGDEBUG("evdi_opened\n");
        return 0;
 }
 
@@ -225,7 +228,7 @@ static int evdi_close(struct inode* i, struct file* filp) {
        evdi_info = filp->private_data;
        evdi_info->guest_connected = false;
 
-       LOG("evdi_closed\n");
+       LOGDEBUG("evdi_closed\n");
        return 0;
 }
 
@@ -246,7 +249,7 @@ static ssize_t evdi_read(struct file *filp, char __user *ubuf, size_t len,
        {
                if (filp->f_flags & O_NONBLOCK)
                {
-                       LOG("list is empty, return EAGAIN\n");
+                       LOGERR("list is empty, return EAGAIN\n");
                        return -EAGAIN;
                }
                return -EFAULT;
@@ -255,7 +258,7 @@ static ssize_t evdi_read(struct file *filp, char __user *ubuf, size_t len,
 
        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;
        }
 
@@ -269,14 +272,11 @@ static ssize_t evdi_read(struct file *filp, char __user *ubuf, size_t len,
 
        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;
 
@@ -293,17 +293,17 @@ static ssize_t evdi_write(struct file *f, const char __user *ubuf, size_t len,
        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;
@@ -319,13 +319,13 @@ static ssize_t evdi_write(struct file *f, const char __user *ubuf, size_t len,
                                &_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;
 }
@@ -347,7 +347,7 @@ static unsigned int evdi_poll(struct file *filp, poll_table *wait)
 
        if (has_readdata(evdi))
        {
-               LOG("POLLIN | POLLRDNORM\n");
+               LOGDEBUG("POLLIN | POLLRDNORM\n");
                ret |= POLLIN | POLLRDNORM;
        }
 
@@ -378,25 +378,24 @@ static void evdi_recv_done(struct virtqueue *rvq) {
 
        _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);
 
@@ -449,7 +448,7 @@ int _init_device(void)
        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;
        }
 
@@ -464,7 +463,7 @@ int _init_device(void)
                pevdi_info[i] = kmalloc(sizeof(struct virtevdi_info), GFP_KERNEL);
 
                if (!pevdi_info[i]) {
-                       LOG("Bad malloc\n");
+                       LOGERR("Bad malloc\n");
                        return -ENOMEM;
                }
 
@@ -483,7 +482,7 @@ int _init_device(void)
                spin_lock_init(&pevdi_info[i]->outvq_lock);
 
                if (ret == -1) {
-                       LOG("Bad cdev\n");
+                       LOGERR("Bad cdev\n");
                        return ret;
                }
 
@@ -508,7 +507,7 @@ static int evdi_probe(struct virtio_device* dev) {
        ret = _init_device();
        if (ret)
        {
-               LOG("failed to _init_device\n");
+               LOGERR("failed to _init_device\n");
                return ret;
        }
        ret = init_vqs(vevdi);
@@ -517,7 +516,7 @@ static int evdi_probe(struct virtio_device* dev) {
                kfree(vevdi);
                dev->priv = NULL;
 
-               LOG("failed to init_vqs\n");
+               LOGERR("failed to init_vqs\n");
                return ret;
        }
 
@@ -536,9 +535,7 @@ static int evdi_probe(struct virtio_device* dev) {
        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;
 }
 
@@ -547,7 +544,7 @@ static void __devexit evdi_remove(struct virtio_device* dev)
        struct virtio_evdi* _evdi = dev->priv;
        if (!_evdi)
        {
-               LOG("evdi is NULL\n");
+               LOGERR("evdi is NULL\n");
                return;
        }
 
@@ -556,7 +553,7 @@ static void __devexit evdi_remove(struct virtio_device* dev)
 
        kfree(_evdi);
 
-       LOG("driver is removed.\n");
+       LOGDEBUG("driver is removed.\n");
 }
 
 MODULE_DEVICE_TABLE(virtio, id_table);
@@ -573,7 +570,7 @@ static struct virtio_driver virtio_evdi_driver = {
 
 static int __init evdi_init(void)
 {
-       LOG("EVDI driver initialized.\n");
+       LOGDEBUG("EVDI driver initialized.\n");
 
        return register_virtio_driver(&virtio_evdi_driver);
 }
@@ -596,7 +593,7 @@ static void __exit evdi_exit(void)
 
        unregister_virtio_driver(&virtio_evdi_driver);
 
-       LOG("EVDI driver is destroyed.\n");
+       LOGDEBUG("EVDI driver is destroyed.\n");
 }
 
 module_init(evdi_init);
index 1c6cdc20272aa772244f586a4911a6c3868b6a8c..db670082e1207d420bba72089f18e4dc2a9921f5 100644 (file)
@@ -37,6 +37,8 @@
 #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>
 
 
@@ -60,7 +62,12 @@ enum sensor_types {
        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,
@@ -82,14 +89,14 @@ struct msg_info {
 
 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,
@@ -99,6 +106,8 @@ struct virtio_sensor *vs;
 
 static struct class* sensor_class;
 
+static DECLARE_WAIT_QUEUE_HEAD(wq);
+
 #define __ATTR_RONLY(_name,_show) { \
        .attr   = { .name = __stringify(_name), .mode = 0444 }, \
        .show   = _show,                                        \
@@ -110,14 +119,112 @@ static struct class* sensor_class;
        .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);
@@ -125,12 +232,13 @@ static ssize_t accel_name_show(struct device *dev, struct device_attribute *attr
 
 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);
 }
 
@@ -146,9 +254,6 @@ static struct device_attribute da_accel [] =
 #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);
@@ -156,23 +261,25 @@ static ssize_t geo_name_show(struct device *dev, struct device_attribute *attr,
 
 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);
 }
 
@@ -191,10 +298,6 @@ static struct device_attribute da_geo [] =
 #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);
@@ -202,34 +305,37 @@ static ssize_t gyro_name_show(struct device *dev, struct device_attribute *attr,
 
 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);
 }
 
@@ -248,9 +354,6 @@ static struct device_attribute da_gyro [] =
 #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);
@@ -258,23 +361,25 @@ static ssize_t light_name_show(struct device *dev, struct device_attribute *attr
 
 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);
 }
 
@@ -294,7 +399,6 @@ static struct device_attribute da_light [] =
 #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)
 {
@@ -314,12 +418,13 @@ static ssize_t enable_store(struct device *dev, struct device_attribute *attr, c
 
 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);
 }
 
@@ -392,155 +497,6 @@ device_err:
        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);
 
@@ -556,6 +512,7 @@ static int sensor_probe(struct virtio_device* dev)
 {
        int err = 0;
        int ret = 0;
+       int index = 0;
 
        LOG(KERN_INFO, "Sensor probe starts");
 
@@ -576,37 +533,30 @@ static int sensor_probe(struct virtio_device* dev)
                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)
index 39fb25407a0e7eb8b04aa204afad7f452f70666c..fffab63242d6b5ac4fa36cd3bdf3c8b91c0cf9e9 100755 (executable)
@@ -48,6 +48,8 @@
 #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 */
index 0de4e3c4d8d91270b2c483c092d6edf809080b9d..ebc37d37f17cac02394bd171c935374917829efc 100644 (file)
@@ -1,3 +1,6 @@
+* 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
index b3157b1fdadd93f1f7ac097c0325b3de50a7c3ae..f0e329dd84939835ce7eef2da85f0e60eba95dba 100644 (file)
@@ -1,4 +1,4 @@
-Version: 1.4.31
+Version: 1.4.32
 Maintainer: Yeong-Kyoon, Lee <yeongkyoon.lee@samsung.com>
 Source: emulator-kernel