From: munkyu.im Date: Thu, 11 Jul 2013 15:34:01 +0000 (+0900) Subject: nfc: apply nfc driver X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=80aedd3ac1f05cda3c72b101a522d3b6f31c34dd;p=sdk%2Femulator%2Femulator-kernel.git nfc: apply nfc driver Signed-off-by: munkyu.im --- diff --git a/drivers/maru/Kconfig b/drivers/maru/Kconfig index 9e80ddf320ff..954a1d1f587a 100644 --- a/drivers/maru/Kconfig +++ b/drivers/maru/Kconfig @@ -75,3 +75,7 @@ config MARU_VIRTIO_EVDI 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 diff --git a/drivers/maru/Makefile b/drivers/maru/Makefile index 0af73629e04a..ed0854d8d635 100644 --- a/drivers/maru/Makefile +++ b/drivers/maru/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_MARU_VIRTIO_KEYBOARD) += maru_virtio_keyboard.o obj-$(CONFIG_MARU_VIRTIO_ESM) += maru_virtio_esm.o obj-$(CONFIG_MARU_VIRTIO_EVDI) += maru_virtio_evdi.o obj-$(CONFIG_MARU_VIRTIO_EVDI) += maru_virtio_sensor.o +obj-$(CONFIG_MARU_VIRTIO_NFC) += maru_virtio_nfc.o diff --git a/drivers/maru/maru_virtio_nfc.c b/drivers/maru/maru_virtio_nfc.c new file mode 100755 index 000000000000..2192c576dec5 --- /dev/null +++ b/drivers/maru/maru_virtio_nfc.c @@ -0,0 +1,367 @@ +/* + * Maru Virtio NFC Device Driver + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd. All rights reserved. + * + * Contact: + * DaiYoung Kim + * YeongKyoon Lee + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributors: + * - S-Core Co., Ltd + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "NFC" + +#define LOG(fmt, ...) \ + printk(KERN_ERR "%s: " fmt, DRIVER_NAME, ##__VA_ARGS__) + +#define CLASS_NAME "network" +#define DEVICE_NAME "nfc" +#define NFC_DATA_FILE "/sys/devices/virtual/network/nfc/data" + +/* device protocol */ +#define __MAX_BUF_SIZE 4096 + +enum +{ + route_qemu = 0, + route_control_server = 1, + route_monitor = 2 +}; + +enum request_cmd { + request_get = 0, + request_set, + request_answer +}; + +typedef unsigned int CSCliSN; + +struct msg_info { + char buf[__MAX_BUF_SIZE]; + + uint32_t route; + uint32_t use; + uint16_t count; + uint16_t index; + + CSCliSN cclisn; +}; + +static struct device* device; + +static char data[PAGE_SIZE] = {0,}; + +static ssize_t show_data(struct device *dev, struct device_attribute *attr, char *buf) +{ + printk("NFC-[%s] \n", __FUNCTION__); + return snprintf(buf, PAGE_SIZE, "%s", data); +} + +static ssize_t store_data(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) +{ + printk("NFC-[%s] \n", __FUNCTION__); + strncpy(data, buf, count); + return strnlen(buf, PAGE_SIZE); +} + +static struct device_attribute da = __ATTR(data, 0644, show_data, store_data); + +/* device protocol */ + +#define SIZEOF_MSG_INFO sizeof(struct msg_info) + +struct virtio_nfc { + struct virtio_device* vdev; + struct virtqueue* rvq; + struct virtqueue* svq; + + struct msg_info read_msginfo; + struct msg_info send_msginfo; + + struct list_head read_list; + struct list_head write_list; + + struct scatterlist sg_read[2]; + struct scatterlist sg_send[2]; + + void *private; +}; + +struct virtio_nfc *vnfc; + +static struct virtio_device_id id_table[] = { { VIRTIO_ID_NFC, + VIRTIO_DEV_ANY_ID }, { 0 }, }; + +static struct class* nfc_class; + + +int make_buf_and_kick(void) +{ + int ret; + memset(&vnfc->read_msginfo, 0x00, sizeof(vnfc->read_msginfo)); + ret = virtqueue_add_buf(vnfc->rvq, vnfc->sg_read, 0, 1, &vnfc->read_msginfo, + GFP_ATOMIC ); + if (ret < 0) { + LOG("failed to add buffer to virtqueue.(%d)\n", ret); + return ret; + } + + virtqueue_kick(vnfc->rvq); + + return 0; +} + +static void write_file(char *filename, char *data, int len) +{ + struct file *file; + loff_t pos = 0; + int fd; + + mm_segment_t old_fs = get_fs(); + set_fs(KERNEL_DS); + + fd = sys_open(filename, O_WRONLY|O_CREAT, 0644); + if (fd >= 0) { + sys_write(fd, data, strlen(data)); + file = fget(fd); + if (file) { + vfs_write(file, data, len, &pos); + fput(file); + file_update_time(file); + } + sys_close(fd); + } + set_fs(old_fs); +} + +static void nfc_recv_done(struct virtqueue *rvq) { + + unsigned int len; + struct msg_info* msg; + int err; + msg = (struct msg_info*) virtqueue_get_buf(vnfc->rvq, &len); + if (msg == NULL ) { + LOG("failed to virtqueue_get_buf\n"); + return; + } + + if(msg->route == request_set) { + memset(data, 0x00, sizeof(data)); + write_file(NFC_DATA_FILE, msg->buf, len); + }else if(msg->route == request_get) { + memset(&vnfc->send_msginfo, 0, sizeof(vnfc->send_msginfo)); + vnfc->send_msginfo.route = request_answer; + strcpy(vnfc->send_msginfo.buf, data); + err = virtqueue_add_buf(vnfc->svq, vnfc->sg_send, 1, 0, &vnfc->send_msginfo, GFP_ATOMIC); + if (err < 0) { + LOG("failed to add buffer to virtqueue (err = %d)", err); + return; + } + + virtqueue_kick(vnfc->svq); + + } + + LOG("msg buf: %sroute: %d, len: %d", msg->buf, msg->route, msg->use); + + make_buf_and_kick(); +} + +static void nfc_send_done(struct virtqueue *svq) { + unsigned int len = 0; + + virtqueue_get_buf(svq, &len); +} + +/* + * + */ + +static int init_vqs(struct virtio_nfc *nfc) { + struct virtqueue *vqs[2]; + vq_callback_t *callbacks[] = { nfc_recv_done, nfc_send_done }; + const char *names[] = { "nfc_input", "nfc_output" }; + int err; + + err = nfc->vdev->config->find_vqs(nfc->vdev, 2, vqs, callbacks, names); + if (err < 0) + return err; + + nfc->rvq = vqs[0]; + nfc->svq = vqs[1]; + + return 0; +} + +static int init_device(void) +{ + int ret; + + nfc_class = class_create(THIS_MODULE, CLASS_NAME); + + device = device_create(nfc_class, NULL, (dev_t)NULL, NULL, DEVICE_NAME); + if (device < 0) { + LOG("NFC device creation is failed."); + return -1; + } + + ret = device_create_file(device, &da); + if (ret) { + device_destroy(nfc_class, (dev_t)NULL); + class_destroy(nfc_class); + return -1; + } + + return 0; +} + + +static int nfc_probe(struct virtio_device* dev) { + int ret; + + vnfc = kmalloc(sizeof(struct virtio_nfc), GFP_KERNEL); + + INIT_LIST_HEAD(&vnfc->read_list); + + vnfc->vdev = dev; + dev->priv = vnfc; + + ret = init_device(); + if (ret) + { + LOG("failed to _init_device\n"); + return ret; + } + ret = init_vqs(vnfc); + if (ret) { + dev->config->del_vqs(dev); + kfree(vnfc); + dev->priv = NULL; + + LOG("failed to init_vqs\n"); + return ret; + } + + /* enable callback */ + virtqueue_enable_cb(vnfc->rvq); + virtqueue_enable_cb(vnfc->svq); + + memset(&vnfc->read_msginfo, 0x00, sizeof(vnfc->read_msginfo)); + sg_set_buf(vnfc->sg_read, &vnfc->read_msginfo, sizeof(struct msg_info)); + + memset(&vnfc->send_msginfo, 0x00, sizeof(vnfc->send_msginfo)); + sg_set_buf(vnfc->sg_send, &vnfc->send_msginfo, sizeof(struct msg_info)); + + + sg_init_one(vnfc->sg_read, &vnfc->read_msginfo, sizeof(vnfc->read_msginfo)); + sg_init_one(vnfc->sg_send, &vnfc->send_msginfo, sizeof(vnfc->send_msginfo)); + + ret = make_buf_and_kick(); + if (ret) { + dev->config->del_vqs(dev); + kfree(vnfc); + dev->priv = NULL; + LOG("failed to send buf"); + return ret; + } + + LOG("NFC Probe completed"); + return 0; +} + +static void __devexit nfc_remove(struct virtio_device* dev) +{ + struct virtio_nfc* _nfc = dev->priv; + if (!_nfc) + { + LOG("nfc is NULL\n"); + return; + } + + dev->config->reset(dev); + dev->config->del_vqs(dev); + + kfree(_nfc); + + LOG("driver is removed.\n"); +} + +MODULE_DEVICE_TABLE(virtio, id_table); + +static struct virtio_driver virtio_nfc_driver = { + .driver = { + .name = KBUILD_MODNAME, + .owner = THIS_MODULE , + }, + .id_table = id_table, + .probe = nfc_probe, + .remove = nfc_remove, +}; + +static int __init nfc_init(void) +{ + LOG("NFC driver initialized.\n"); + + return register_virtio_driver(&virtio_nfc_driver); +} + +static void __exit nfc_exit(void) +{ + device_destroy(nfc_class, (dev_t)NULL); + + /*device_destroy(nfc_class, nfc_dev_number);*/ + + class_destroy(nfc_class); + + unregister_virtio_driver(&virtio_nfc_driver); + + LOG("NFC driver is destroyed.\n"); +} + +module_init(nfc_init); +module_exit(nfc_exit); + +MODULE_LICENSE("GPL2"); +MODULE_AUTHOR("DaiYoung Kim "); +MODULE_DESCRIPTION("Emulator Virtio EmulatorVirtualDeviceInterface Driver"); + diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h index 9b9833cedcfe..c185ffbb460f 100755 --- a/include/linux/virtio_ids.h +++ b/include/linux/virtio_ids.h @@ -47,6 +47,7 @@ #define VIRTIO_ID_HWKEY 14 /* virtio hwkey */ #define VIRTIO_ID_EVDI 15 /* virtio evdi */ #define VIRTIO_ID_SENSOR 16 /* virtio sensor */ +#define VIRTIO_ID_NFC 17 /* virtio NFC */ #endif