virtio_exit_pci(pci_dev);
}
+static int virtio_nfc_init_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+ VirtIODevice *vdev;
+
+ vdev = virtio_nfc_init(&pci_dev->qdev);
+ if (!vdev) {
+ return -1;
+ }
+ virtio_init_pci(proxy, vdev);
+ return 0;
+}
+
+static void virtio_nfc_exit_pci(PCIDevice *pci_dev)
+{
+ VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+ virtio_pci_stop_ioeventfd(proxy);
+ virtio_evdi_exit(proxy->vdev);
+ virtio_exit_pci(pci_dev);
+}
+
+
#endif
static Property virtio_blk_properties[] = {
dc->desc = "Emulator Sensor Virtual Device";
}
+static void virtio_nfc_class_init(ObjectClass *klass, void *data) {
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+ k->init = virtio_nfc_init_pci;
+ k->exit = virtio_nfc_exit_pci;
+ k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+ k->device_id = PCI_DEVICE_ID_VIRTIO_NFC;
+ k->revision = VIRTIO_PCI_ABI_VERSION;
+ k->class_id = PCI_CLASS_OTHERS;
+ dc->reset = virtio_pci_reset;
+}
+
static TypeInfo virtio_sensor_info = {
.name = "virtio-sensor-pci",
.class_init = virtio_sensor_class_init,
};
+static TypeInfo virtio_nfc_info = {
+ .name = "virtio-nfc-pci",
+ .parent = TYPE_PCI_DEVICE,
+ .instance_size = sizeof(VirtIOPCIProxy),
+ .class_init = virtio_nfc_class_init,
+};
+
#endif /* CONFIG_MARU */
static void virtio_pci_register_types(void)
type_register_static(&virtio_hwkey_info);
type_register_static(&virtio_evdi_info);
type_register_static(&virtio_sensor_info);
+ type_register_static(&virtio_nfc_info);
#endif
}
--- /dev/null
+/*\r
+ * Virtio NFC Device\r
+ *\r
+ * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved\r
+ *\r
+ * Contact:\r
+ * DaiYoung Kim <munkyu.im@samsung.com>\r
+ * YeongKyoon Lee <yeongkyoon.lee@samsung.com>\r
+ *\r
+ * This program is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.\r
+ *\r
+ * Contributors:\r
+ * - S-Core Co., Ltd\r
+ *\r
+ */\r
+\r
+#include <pthread.h>\r
+\r
+#include "maru_device_ids.h"\r
+#include "maru_virtio_nfc.h"\r
+#include "debug_ch.h"\r
+#include "../ecs.h"\r
+\r
+MULTI_DEBUG_CHANNEL(qemu, virtio-nfc);\r
+\r
+#define VIRTIO_NFC_DEVICE_NAME "virtio-nfc"\r
+\r
+\r
+enum {\r
+ IOTYPE_INPUT = 0,\r
+ IOTYPE_OUTPUT = 1\r
+};\r
+\r
+\r
+#ifndef min\r
+#define min(a,b) ((a)<(b)?(a):(b))\r
+#endif\r
+\r
+#define MAX_BUF_SIZE 4096\r
+typedef struct VirtIO_NFC{\r
+ VirtIODevice vdev;\r
+ VirtQueue *rvq;\r
+ VirtQueue *svq;\r
+ DeviceState *qdev;\r
+\r
+ QEMUBH *bh;\r
+} VirtIO_NFC;\r
+\r
+\r
+VirtIO_NFC* vio_nfc;\r
+\r
+\r
+typedef unsigned int CSCliSN;\r
+\r
+typedef struct msg_info {\r
+ char buf[MAX_BUF_SIZE];\r
+\r
+ uint32_t route;\r
+ uint32_t use;\r
+ uint16_t count;\r
+ uint16_t index;\r
+\r
+ CSCliSN cclisn;\r
+}msg_info;\r
+\r
+//\r
+\r
+typedef struct MsgInfo\r
+{\r
+ msg_info info;\r
+ QTAILQ_ENTRY(MsgInfo) next;\r
+}MsgInfo;\r
+\r
+static QTAILQ_HEAD(MsgInfoRecvHead , MsgInfo) nfc_recv_msg_queue =\r
+ QTAILQ_HEAD_INITIALIZER(nfc_recv_msg_queue);\r
+\r
+\r
+static QTAILQ_HEAD(MsgInfoSendHead , MsgInfo) nfc_send_msg_queue =\r
+ QTAILQ_HEAD_INITIALIZER(nfc_send_msg_queue);\r
+\r
+\r
+//\r
+\r
+typedef struct EvdiBuf {\r
+ VirtQueueElement elem;\r
+\r
+ QTAILQ_ENTRY(EvdiBuf) next;\r
+} EvdiBuf;\r
+\r
+static QTAILQ_HEAD(EvdiMsgHead , EvdiBuf) nfc_in_queue =\r
+ QTAILQ_HEAD_INITIALIZER(nfc_in_queue);\r
+\r
+static int count = 0;\r
+\r
+static pthread_mutex_t recv_buf_mutex = PTHREAD_MUTEX_INITIALIZER;\r
+\r
+bool send_to_nfc(enum request_cmd req, char* data, const uint32_t len)\r
+{\r
+ MsgInfo* _msg = (MsgInfo*) malloc(sizeof(MsgInfo));\r
+ if (!_msg)\r
+ return false;\r
+\r
+ memset(&_msg->info, 0, sizeof(msg_info));\r
+\r
+ memcpy(_msg->info.buf, data, len);\r
+ _msg->info.use = len;\r
+ _msg->info.index = count++;\r
+ _msg->info.route = req;\r
+ pthread_mutex_lock(&recv_buf_mutex);\r
+\r
+ QTAILQ_INSERT_TAIL(&nfc_recv_msg_queue, _msg, next);\r
+\r
+ pthread_mutex_unlock(&recv_buf_mutex);\r
+\r
+ qemu_bh_schedule(vio_nfc->bh);\r
+\r
+ return true;\r
+}\r
+\r
+\r
+static int g_cnt = 0;\r
+\r
+static void flush_nfc_recv_queue(void)\r
+{\r
+ int index;\r
+\r
+ if (unlikely(!virtio_queue_ready(vio_nfc->rvq))) {\r
+ INFO("virtio queue is not ready\n");\r
+ return;\r
+ }\r
+\r
+ if (unlikely(virtio_queue_empty(vio_nfc->rvq))) {\r
+ TRACE("virtqueue is empty\n");\r
+ return;\r
+ }\r
+\r
+\r
+ pthread_mutex_lock(&recv_buf_mutex);\r
+\r
+ while (!QTAILQ_EMPTY(&nfc_recv_msg_queue))\r
+ {\r
+ MsgInfo* msginfo = QTAILQ_FIRST(&nfc_recv_msg_queue);\r
+ if (!msginfo)\r
+ break;\r
+\r
+ VirtQueueElement elem;\r
+ index = virtqueue_pop(vio_nfc->rvq, &elem);\r
+ if (index == 0)\r
+ {\r
+ //ERR("unexpected empty queue");\r
+ break;\r
+ }\r
+\r
+ INFO(">> virtqueue_pop. index: %d, out_num : %d, in_num : %d\n", index, elem.out_num, elem.in_num);\r
+\r
+ memcpy(elem.in_sg[0].iov_base, &msginfo->info, sizeof(struct msg_info));\r
+\r
+ INFO(">> send to guest count = %d, use = %d, msg = %s, iov_len = %d \n",\r
+ ++g_cnt, msginfo->info.use, msginfo->info.buf, elem.in_sg[0].iov_len);\r
+\r
+ virtqueue_push(vio_nfc->rvq, &elem, sizeof(msg_info));\r
+ virtio_notify(&vio_nfc->vdev, vio_nfc->rvq);\r
+\r
+ QTAILQ_REMOVE(&nfc_recv_msg_queue, msginfo, next);\r
+ if (msginfo)\r
+ free(msginfo);\r
+ }\r
+\r
+ pthread_mutex_unlock(&recv_buf_mutex);\r
+\r
+}\r
+\r
+\r
+static void virtio_nfc_recv(VirtIODevice *vdev, VirtQueue *vq)\r
+{\r
+ flush_nfc_recv_queue();\r
+}\r
+\r
+static void send_to_ecs(struct msg_info* msg)\r
+{\r
+ int buf_len;\r
+ char data_len [2];\r
+ char group [1] = { 15 }; \r
+ char action [1];\r
+ int message_len = 0;\r
+\r
+ char* ecs_message = NULL;\r
+ \r
+ buf_len = strlen(msg->buf);\r
+ message_len = buf_len + 14;\r
+\r
+ ecs_message = (char*) malloc(message_len + 1);\r
+ if (!ecs_message)\r
+ return;\r
+\r
+ memset(ecs_message, 0, message_len + 1);\r
+\r
+ data_len[0] = buf_len;\r
+ action[0] = 0;\r
+\r
+ memcpy(ecs_message, "nfc", 10);\r
+ memcpy(ecs_message + 10, &data_len, 2);\r
+ memcpy(ecs_message + 12, &group, 1);\r
+ memcpy(ecs_message + 13, &action, 1);\r
+ memcpy(ecs_message + 14, msg->buf, buf_len);\r
+\r
+ INFO("ntf_to_injector- bufnum: %s, group: %s, action: %s, data: %s\n", data_len, group, action, msg->buf);\r
+\r
+ ntf_to_injector(ecs_message, message_len);\r
+\r
+ if (ecs_message)\r
+ free(ecs_message);\r
+}\r
+\r
+static void virtio_nfc_send(VirtIODevice *vdev, VirtQueue *vq)\r
+{\r
+ VirtIO_NFC *vnfc = (VirtIO_NFC *)vdev;\r
+ int index = 0;\r
+ struct msg_info _msg;\r
+\r
+ if (virtio_queue_empty(vnfc->svq)) {\r
+ INFO("<< virtqueue is empty.\n");\r
+ return;\r
+ }\r
+\r
+ VirtQueueElement elem;\r
+\r
+ while ((index = virtqueue_pop(vq, &elem))) {\r
+\r
+ INFO("<< virtqueue pop. index: %d, out_num : %d, in_num : %d\n", index, elem.out_num, elem.in_num);\r
+\r
+ if (index == 0) {\r
+ INFO("<< virtqueue break\n");\r
+ break;\r
+ }\r
+\r
+ INFO("<< use=%d, iov_len = %d\n", _msg.use, elem.out_sg[0].iov_len);\r
+\r
+ memset(&_msg, 0x00, sizeof(_msg));\r
+ memcpy(&_msg, elem.out_sg[0].iov_base, elem.out_sg[0].iov_len);\r
+\r
+ INFO("<< recv from guest len = %d, msg = %s \n", _msg.use, _msg.buf);\r
+\r
+ send_to_ecs(&_msg);\r
+\r
+ }\r
+\r
+ virtqueue_push(vq, &elem, sizeof(VirtIO_NFC));\r
+ virtio_notify(&vio_nfc->vdev, vq);\r
+}\r
+\r
+static uint32_t virtio_nfc_get_features(VirtIODevice *vdev,\r
+ uint32_t request_feature)\r
+{\r
+ TRACE("virtio_nfc_get_features.\n");\r
+ return 0;\r
+}\r
+\r
+static void maru_nfc_bh(void *opaque)\r
+{\r
+ flush_nfc_recv_queue();\r
+}\r
+\r
+VirtIODevice *virtio_nfc_init(DeviceState *dev)\r
+{\r
+ INFO("initialize nfc device\n");\r
+\r
+ vio_nfc = (VirtIO_NFC *)virtio_common_init(VIRTIO_NFC_DEVICE_NAME,\r
+ VIRTIO_ID_NFC, 0, sizeof(VirtIO_NFC));\r
+ if (vio_nfc == NULL) {\r
+ ERR("failed to initialize nfc device\n");\r
+ return NULL;\r
+ }\r
+\r
+ vio_nfc->vdev.get_features = virtio_nfc_get_features;\r
+ vio_nfc->rvq = virtio_add_queue(&vio_nfc->vdev, 256, virtio_nfc_recv);\r
+ vio_nfc->svq = virtio_add_queue(&vio_nfc->vdev, 256, virtio_nfc_send);\r
+ vio_nfc->qdev = dev;\r
+\r
+ vio_nfc->bh = qemu_bh_new(maru_nfc_bh, vio_nfc);\r
+\r
+ return &vio_nfc->vdev;\r
+}\r
+\r
+void virtio_nfc_exit(VirtIODevice *vdev)\r
+{\r
+ INFO("destroy nfc device\n");\r
+\r
+ if (vio_nfc->bh) {\r
+ qemu_bh_delete(vio_nfc->bh);\r
+ }\r
+\r
+ virtio_cleanup(vdev);\r
+}\r
+\r