Maru power supply device driver is added, but it is not built.
It will be fixed.
Change-Id: Ib4a10e9c4434d272c445f8551ef9cb74b89b963f
Signed-off-by: Jinhyung Choi <jinhyung2.choi@samsung.com>
CONFIG_MARU_CAMERA=y
CONFIG_MARU_BACKLIGHT=y
CONFIG_MARU_OVERLAY=y
+CONFIG_MARU_JACK=y
+CONFIG_MARU_POWER_SUPPLY=y
CONFIG_MARU_VIRTIO_EVDI=y
CONFIG_MARU_VIRTIO_NFC=y
CONFIG_MARU_VIRTIO_SENSOR=y
tristate "MARU overlay Driver"
depends on MARU != n && VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
-config MARU_VIRTIO_EVDI
- tristate "MARU VirtIO Emulator Virtual Device Interface Driver"
+config MARU_JACK
+ tristate "MARU Jack Driver"
depends on MARU != n
-config MARU_VIRTIO_NFC
- tristate "MARU VirtIO Virtual NFC Device Driver"
+config MARU_POWER_SUPPLY
+ tristate "MARU Power supply Driver"
depends on MARU != n
-config MARU_VIRTIO_SENSOR
- tristate "MARU VirtIO Emulator Sensor Device Driver"
- depends on MARU != n
+
config MARU_VIRTIO_HWKEY
tristate "MARU Virtio HW Key Driver"
tristate "MARU Virtio Keyboard Driver"
depends on MARU != n
+config MARU_VIRTIO_EVDI
+ tristate "MARU VirtIO Emulator Virtual Device Interface Driver"
+ depends on MARU != n
+
+config MARU_VIRTIO_SENSOR
+ tristate "MARU VirtIO Virtual Sensor Device Driver"
+ depends on MARU != n
+
+config MARU_VIRTIO_NFC
+ tristate "MARU VirtIO Virtual NFC Device Driver"
+ depends on MARU != n
+
config MARU_BRILLCODEC
tristate "MARU brillcodec driver"
depends on MARU != n
obj-$(CONFIG_MARU_BACKLIGHT) += maru_bl.o
obj-$(CONFIG_MARU_OVERLAY) += maru_overlay.o
obj-$(CONFIG_MARU_VIRTIO_HWKEY) += maru_virtio_hwkey.o
+obj-$(CONFIG_MARU_JACK) += maru_jack.o
+#obj-$(CONFIG_MARU_POWER_SUPPLY) += maru_power_supply.o
obj-$(CONFIG_MARU_VIRTIO_KEYBOARD) += maru_virtio_keyboard.o
obj-$(CONFIG_MARU_VIRTIO_NFC) += maru_virtio_nfc.o
obj-$(CONFIG_MARU_VIRTIO_EVDI) += maru_virtio_evdi.o
--- /dev/null
+/*
+ * Virtual device node
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JinHyung Choi <jinhyung2.choi@samsung.com>
+ * SooYoung Ha <yoosah.ha@samsung.com>
+ * Sungmin Ha <sungmin82.ha@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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ */
+
+#include <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;
+};
+
+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_list = 0,
+ jack_type_charger,
+ jack_type_earjack,
+ jack_type_earkey,
+ jack_type_hdmi,
+ jack_type_usb,
+ jack_type_max
+};
+
+enum jack_capabilities {
+ jack_cap_charger = 0x01,
+ jack_cap_earjack = 0x02,
+ jack_cap_earkey = 0x04,
+ jack_cap_hdmi = 0x08,
+ jack_cap_usb = 0x10
+};
+
+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 int jack_capability = 0;
+
+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
+
+#ifdef JACK_DEBUG
+#define DLOG(level, fmt, ...) \
+ printk(level "maru_%s: " fmt, DEVICE_NAME, ##__VA_ARGS__)
+#else
+// do nothing
+#define DLOG(level, fmt, ...)
+#endif
+
+static int jack_atoi(const char *name)
+{
+ int val = 0;
+
+ for (;; name++) {
+ switch (*name) {
+ case '0' ... '9':
+ val = 10*val+(*name-'0');
+ break;
+ default:
+ return val;
+ }
+ }
+}
+
+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_outbuf(v_jack->vq, v_jack->sg_vq, 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);
+}
+
+static void get_jack_data(int type)
+{
+ struct scatterlist *sgs[2];
+ 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);
+
+ sgs[0] = &v_jack->sg_vq[0];
+ sgs[1] = &v_jack->sg_vq[1];
+ err = virtqueue_add_sgs(v_jack->vq, sgs, 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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 DEVICE_ATTR(hdmi_online, S_IRUGO | S_IWUSR, show_hdmi_online, store_hdmi_online);
+static DEVICE_ATTR(usb_online, S_IRUGO | S_IWUSR, show_usb_online, store_usb_online);
+
+static int maru_jack_sysfs_create_file(struct device *dev)
+{
+ int result = 0;
+
+ DLOG(KERN_INFO, "sysfs_create_file\n");
+
+ if (jack_capability & jack_cap_charger) {
+ result = device_create_file(dev, &dev_attr_charger_online);
+ if (result){
+ DLOG(KERN_ERR, "failed to create charger_online file\n");
+ return result;
+ }
+ }
+
+ if (jack_capability & jack_cap_earjack) {
+ result = device_create_file(dev, &dev_attr_earjack_online);
+ if (result){
+ DLOG(KERN_ERR, "failed to create earjack_online file\n");
+ return result;
+ }
+ }
+
+ if (jack_capability & jack_cap_earkey) {
+ result = device_create_file(dev, &dev_attr_earkey_online);
+ if (result){
+ DLOG(KERN_ERR, "failed to create earkey_online file\n");
+ return result;
+ }
+ }
+
+ if (jack_capability & jack_cap_hdmi) {
+ result = device_create_file(dev, &dev_attr_hdmi_online);
+ if (result){
+ DLOG(KERN_ERR, "failed to create hdmi_online file\n");
+ return result;
+ }
+ }
+
+ if (jack_capability & jack_cap_usb) {
+ result = device_create_file(dev, &dev_attr_usb_online);
+ if (result){
+ DLOG(KERN_ERR, "failed to create usb_online file\n");
+ return result;
+ }
+ }
+
+ return 0;
+}
+
+
+static void maru_jack_sysfs_remove_file(struct device *dev)
+{
+ DLOG(KERN_INFO, "sysfs_remove_file\n");
+
+ device_remove_file(dev, &dev_attr_charger_online);
+ device_remove_file(dev, &dev_attr_earjack_online);
+ device_remove_file(dev, &dev_attr_earkey_online);
+ device_remove_file(dev, &dev_attr_hdmi_online);
+ device_remove_file(dev, &dev_attr_usb_online);
+}
+
+static void maru_jack_sysfs_dev_release(struct device *dev)
+{
+ DLOG(KERN_INFO, "sysfs_dev_release\n");
+}
+
+static struct platform_device the_pdev = {
+ .name = DEVICE_NAME,
+ .id = -1,
+ .dev = {
+ .release = maru_jack_sysfs_dev_release,
+ }
+};
+
+static int jack_probe(struct virtio_device* dev){
+ int err = 0, index = 0;
+ struct jack_data *data;
+
+ 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) {
+ DLOG(KERN_ERR, "platform_device_register failure\n");
+ return err;
+ }
+
+ data = kzalloc(sizeof(struct jack_data), GFP_KERNEL);
+ if (!data) {
+ DLOG(KERN_ERR, "kzalloc failure\n");
+ platform_device_unregister(&the_pdev);
+ return -ENOMEM;
+ }
+
+ dev_set_drvdata(&the_pdev.dev, (void*)data);
+
+ 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);
+
+ DLOG(KERN_INFO, "request jack capability");
+
+ get_jack_data(jack_type_list);
+ jack_capability = jack_atoi(jack_data);
+ DLOG(KERN_INFO, "jack capability is %02x", jack_capability);
+
+ err = maru_jack_sysfs_create_file(&the_pdev.dev);
+ if (err) {
+ DLOG(KERN_ERR, "sysfs_create_file failure\n");
+ kfree(data);
+ platform_device_unregister(&the_pdev);
+ return err;
+ }
+
+ return 0;
+}
+
+static void jack_remove(struct virtio_device* dev){
+ void *data = dev_get_drvdata(&the_pdev.dev);
+
+ DLOG(KERN_INFO, "sysfs_exit\n");
+
+ if (data) {
+ kfree(data);
+ }
+ 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_init);
+module_exit(maru_jack_exit);
+
+MODULE_LICENSE("GPL2");
+MODULE_AUTHOR("Jinhyung Choi <jinhyung2.choi@samsung.com>");
+MODULE_DESCRIPTION("Emulator Virtio Power Driver");
--- /dev/null
+/*
+ * Virtual device node
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd. All rights reserved.
+ *
+ * Contact:
+ * JinHyung Choi <jinhyung2.choi@samsung.com>
+ * SooYoung Ha <yoosah.ha@samsung.com>
+ * Sungmin Ha <sungmin82.ha@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
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * Contributors:
+ * - S-Core Co., Ltd
+ */
+
+#include <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 DEVICE_NAME "power_supply"
+#define FILE_PERMISSION (S_IRUGO | S_IWUSR)
+
+//#define DEBUG_MARU_POWER_SUPPLY
+
+#ifdef DEBUG_MARU_POWER_SUPPLY
+#define DLOG(level, fmt, ...) \
+ printk(level "maru_%s: " fmt, DEVICE_NAME, ##__VA_ARGS__)
+#else
+// do nothing
+#define DLOG(level, fmt, ...)
+#endif
+
+#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_outbuf(v_power->vq, v_power->sg_vq, 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);
+}
+
+static void get_power_data(int type)
+{
+ struct scatterlist *sgs[2];
+ 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);
+
+ sgs[0] = &v_power->sg_vq[0];
+ sgs[1] = &v_power->sg_vq[1];
+ err = virtqueue_add_sgs(v_power->vq, sgs, 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ 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)
+{
+ set_power_data(power_type_charge_now, buf);
+ return strnlen(buf, PAGE_SIZE);
+}
+
+static struct device_attribute ps_device_attributes[] = {
+ __ATTR(capacity, FILE_PERMISSION, show_capacity, store_capacity),
+ __ATTR(charge_full, FILE_PERMISSION, show_charge_full, store_charge_full),
+ __ATTR(charge_now, FILE_PERMISSION, show_charge_now, store_charge_now),
+};
+
+static void class_cleanup (void)
+{
+ int i = 2;
+
+ for (; i > 0; i--) {
+
+ if (power_device == NULL)
+ continue;
+
+ device_remove_file(power_device, &ps_device_attributes[i]);
+
+ device_unregister(power_device);
+
+ 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(power_device, &ps_device_attributes[i]);
+ if (err) {
+ printk(KERN_ERR
+ "maru_%s: failed to create power_supply files\n", DEVICE_NAME);
+ goto device_err;
+ }
+ }
+
+ return err;
+device_err:
+ class_cleanup();
+ return -1;
+}
+
+static void cleanup(struct virtio_device* dev) {
+ dev->config->del_vqs(dev);
+
+ 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 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)
+{
+ DLOG(KERN_INFO, "maru_%s: exit\n", DEVICE_NAME);
+ unregister_virtio_driver(&virtio_power_driver);
+}
+
+module_init(maru_power_supply_init);
+module_exit(maru_power_supply_exit);
+
+MODULE_LICENSE("GPL2");
+MODULE_AUTHOR("Jinhyung Choi <jinhyung2.choi@samsung.com>");
+MODULE_DESCRIPTION("Emulator Virtio Power Driver");
/*
* Maru Virtio Sensor Device Driver
*
- * Copyright (c) 2014 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved.
*
* Contact:
* Jinhyung Choi <jinhyung2.choi@samsung.com>
#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>
#define DEVICE_COUNT 5
enum sensor_types {
- sensor_type_accel = 0,
+ sensor_type_list = 0,
+ sensor_type_accel,
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,
sensor_type_max
};
+enum sensor_capabilities {
+ sensor_cap_accel = 0x01,
+ sensor_cap_geo = 0x02,
+ sensor_cap_gyro = 0x04,
+ sensor_cap_light = 0x08,
+ sensor_cap_proxi = 0x10
+};
+
+enum sensor_attributes {
+ sensor_attr_accel = 0,
+ sensor_attr_geo,
+ sensor_attr_gyro,
+ sensor_attr_light,
+ sensor_attr_proxi
+};
+
enum request_cmd {
request_get = 0,
request_set,
struct virtio_sensor {
struct virtio_device* vdev;
- struct virtqueue* rvq;
- struct virtqueue* svq;
+ struct virtqueue* vq;
+
+ struct msg_info msginfo;
- struct msg_info read_msginfo;
- struct msg_info send_msginfo;
+ struct scatterlist sg_vq[2];
- struct scatterlist sg_read[2];
- struct scatterlist sg_send[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 int sensor_capability = 0;
+
+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 int sensor_atoi(const char *name)
+{
+ int val = 0;
+
+ for (;; name++) {
+ switch (*name) {
+ case '0' ... '9':
+ val = 10*val+(*name-'0');
+ break;
+ default:
+ return val;
+ }
+ }
+}
+
+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_outbuf(vs->vq, vs->sg_vq, 1, &vs->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ LOG(KERN_ERR, "failed to add out buffer to virtqueue (err = %d)", err);
+ return;
+ }
+
+ virtqueue_kick(vs->vq);
+}
+
+static void get_sensor_data(int type)
+{
+ struct scatterlist *sgs[2];
+ 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);
+
+ sgs[0] = &vs->sg_vq[0];
+ sgs[1] = &vs->sg_vq[1];
+ err = virtqueue_add_sgs(vs->vq, sgs, 1, 1, &vs->msginfo, GFP_ATOMIC);
+ if (err < 0) {
+ LOG(KERN_ERR, "failed to add in 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);
}
int ret = 0;
for (i = 0; i < DEVICE_COUNT; i++) {
-
+ if (i == sensor_attr_accel && !(sensor_capability & sensor_cap_accel)) {
+ continue;
+ } else if (i == sensor_attr_geo && !(sensor_capability & sensor_cap_geo)) {
+ continue;
+ } else if (i == sensor_attr_gyro && !(sensor_capability & sensor_cap_gyro)) {
+ continue;
+ } else if (i == sensor_attr_light && !(sensor_capability & sensor_cap_light)) {
+ continue;
+ } else if (i == sensor_attr_proxi && !(sensor_capability & sensor_cap_proxi)) {
+ continue;
+ }
device_list[i] = device_create(sensor_class, NULL, (dev_t)NULL, NULL, device_name_list[i]);
if (device_list[i] < 0) {
LOG(KERN_ERR, "%dth sensor device creation is failed.", i);
return -1;
}
-static int _make_buf_and_kick(void)
-{
- int ret;
- memset(&vs->read_msginfo, 0x00, sizeof(vs->read_msginfo));
- ret = virtqueue_add_inbuf(vs->rvq, vs->sg_read, 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_outbuf(vs->svq, vs->sg_send, 1, &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 -1;
}
- ret = init_device();
- 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 virt queue");
return ret;
}
- ret = init_vqs(vs);
- if (ret) {
- cleanup(dev);
- LOG(KERN_ERR, "failed to init vqs");
- return ret;
+ virtqueue_enable_cb(vs->vq);
+
+ memset(&vs->msginfo, 0x00, sizeof(vs->msginfo));
+
+ sg_init_table(vs->sg_vq, 2);
+ for (; index < 2; index++) {
+ sg_set_buf(&vs->sg_vq[index], &vs->msginfo, sizeof(vs->msginfo));
}
- memset(&vs->read_msginfo, 0x00, sizeof(vs->read_msginfo));
- sg_set_buf(vs->sg_read, &vs->read_msginfo, sizeof(struct msg_info));
+ mutex_init(&vs->lock);
- memset(&vs->send_msginfo, 0x00, sizeof(vs->send_msginfo));
- sg_set_buf(vs->sg_send, &vs->send_msginfo, sizeof(struct msg_info));
+ LOG(KERN_INFO, "Sensor probe completes");
- 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));
+ get_sensor_data(sensor_type_list);
+ sensor_capability = sensor_atoi(sensor_data);
+ LOG(KERN_INFO, "sensor capability is %02x", sensor_capability);
- ret = _make_buf_and_kick();
+ ret = init_device();
if (ret) {
+ LOG(KERN_ERR, "failed initialing devices");
cleanup(dev);
- LOG(KERN_ERR, "failed to send buf");
return ret;
}
- LOG(KERN_INFO, "Sensor probe completes");
-
return err;
}
#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 */