4 * Copyright (c) 2013 Samsung Electronics Co., Ltd All Rights Reserved
7 * Munkyu Im <munkyu.im@samsung.com>
8 * YeongKyoon Lee <yeongkyoon.lee@samsung.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 #include "hw/maru_device_ids.h"
32 #include "maru_virtio_nfc.h"
36 MULTI_DEBUG_CHANNEL(qemu, nfc);
38 #define NFC_DEVICE_NAME "virtio-nfc"
47 #define min(a,b) ((a)<(b)?(a):(b))
52 typedef struct MsgInfo
55 QTAILQ_ENTRY(MsgInfo) next;
58 static QTAILQ_HEAD(MsgInfoRecvHead , MsgInfo) nfc_recv_msg_queue =
59 QTAILQ_HEAD_INITIALIZER(nfc_recv_msg_queue);
61 typedef struct NFCBuf {
62 VirtQueueElement elem;
63 QTAILQ_ENTRY(NFCBuf) next;
67 static char nfc_data [NFC_MAX_BUF_SIZE] = {'0',};
68 static pthread_mutex_t recv_buf_mutex = PTHREAD_MUTEX_INITIALIZER;
70 static void send_nfc_data_to_ecs(const char* data)
72 type_length length = 0;
73 type_group group = 15;
74 type_action action = 0;
75 int buf_len = strlen(data);
76 int message_len = buf_len + 14;
78 char* ecs_message = (char*) malloc(message_len + 1);
82 memset(ecs_message, 0, message_len + 1);
84 length = (unsigned short) buf_len;
87 memcpy(ecs_message, MESSAGE_TYPE_NFC, 3);
88 memcpy(ecs_message + 10, &length, sizeof(unsigned short));
89 memcpy(ecs_message + 12, &group, sizeof(unsigned char));
90 memcpy(ecs_message + 13, &action, sizeof(unsigned char));
91 memcpy(ecs_message + 14, data, buf_len);
93 TRACE("ntf_to_injector- len: %d, group: %d, action: %d, data: %s\n", length, group, action, data);
95 send_device_ntf(ecs_message, message_len);
101 void get_nfc_data(void)
103 send_nfc_data_to_ecs(nfc_data);
106 bool send_to_nfc(unsigned char id, unsigned char type, const char* data, const uint32_t len)
108 if(vio_nfc == NULL) {
109 ERR("NFC is not initialized\n");
113 if (unlikely(!virtio_queue_ready(vio_nfc->rvq))) {
114 ERR("virtio queue is not ready\n");
118 MsgInfo* _msg = (MsgInfo*) malloc(sizeof(MsgInfo));
123 if(len > NFC_MAX_BUF_SIZE) {
124 ERR("the length of data is longer than max buffer size");
129 memset(&_msg->info, 0, sizeof(nfc_msg_info));
131 memcpy(_msg->info.buf, data, len);
132 _msg->info.use = len;
133 _msg->info.client_id = id;
134 _msg->info.client_type = type;
136 pthread_mutex_lock(&recv_buf_mutex);
137 strcpy(nfc_data, data);
138 QTAILQ_INSERT_TAIL(&nfc_recv_msg_queue, _msg, next);
140 pthread_mutex_unlock(&recv_buf_mutex);
142 qemu_bh_schedule(vio_nfc->bh);
147 static void flush_nfc_recv_queue(void)
151 if (unlikely(!virtio_queue_ready(vio_nfc->rvq))) {
152 INFO("virtio queue is not ready\n");
156 if (unlikely(virtio_queue_empty(vio_nfc->rvq))) {
157 TRACE("virtqueue is empty\n");
162 pthread_mutex_lock(&recv_buf_mutex);
164 while (!QTAILQ_EMPTY(&nfc_recv_msg_queue))
166 MsgInfo* msginfo = QTAILQ_FIRST(&nfc_recv_msg_queue);
171 VirtQueueElement elem;
172 index = virtqueue_pop(vio_nfc->rvq, &elem);
175 //ERR("unexpected empty queue");
179 INFO(">> virtqueue_pop. index: %d, out_num : %d, in_num : %d\n", index, elem.out_num, elem.in_num);
181 memcpy(elem.in_sg[0].iov_base, &msginfo->info, sizeof(struct nfc_msg_info));
183 INFO(">> send to guest use = %d, msg = %s, iov_len = %d \n",
184 msginfo->info.use, msginfo->info.buf, elem.in_sg[0].iov_len);
186 virtqueue_push(vio_nfc->rvq, &elem, sizeof(nfc_msg_info));
187 virtio_notify(&vio_nfc->vdev, vio_nfc->rvq);
189 QTAILQ_REMOVE(&nfc_recv_msg_queue, msginfo, next);
194 pthread_mutex_unlock(&recv_buf_mutex);
199 static void virtio_nfc_recv(VirtIODevice *vdev, VirtQueue *vq)
201 flush_nfc_recv_queue();
204 static void virtio_nfc_send(VirtIODevice *vdev, VirtQueue *vq)
206 VirtIONFC *vnfc = (VirtIONFC *)vdev;
208 struct nfc_msg_info _msg;
210 if (virtio_queue_empty(vnfc->svq)) {
211 INFO("<< virtqueue is empty.\n");
215 VirtQueueElement elem;
217 while ((index = virtqueue_pop(vq, &elem))) {
219 INFO("<< virtqueue pop. index: %d, out_num : %d, in_num : %d\n", index, elem.out_num, elem.in_num);
221 INFO("<< iov_len = %d\n", elem.out_sg[0].iov_len);
223 memset(&_msg, 0x00, sizeof(_msg));
224 memcpy(&_msg, elem.out_sg[0].iov_base, elem.out_sg[0].iov_len);
226 INFO("<< recv from guest len = %d, msg = %s \n", _msg.use, _msg.buf);
231 virtqueue_push(vq, &elem, sizeof(VirtIONFC));
232 virtio_notify(&vio_nfc->vdev, vq);
235 static uint32_t virtio_nfc_get_features(VirtIODevice *vdev,
236 uint32_t request_feature)
238 TRACE("virtio_nfc_get_features.\n");
242 static void maru_nfc_bh(void *opaque)
244 flush_nfc_recv_queue();
247 static void virtio_nfc_realize(DeviceState* dev, Error **errp)
249 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
250 vio_nfc = VIRTIO_NFC(vdev);
251 if (vio_nfc == NULL) {
252 ERR("failed to initialize nfc device\n");
256 INFO("initialize nfc device\n");
258 virtio_init(vdev, NFC_DEVICE_NAME, VIRTIO_ID_NFC, 0);
260 vio_nfc->rvq = virtio_add_queue(&vio_nfc->vdev, 256, virtio_nfc_recv);
261 vio_nfc->svq = virtio_add_queue(&vio_nfc->vdev, 256, virtio_nfc_send);
263 vio_nfc->bh = qemu_bh_new(maru_nfc_bh, vio_nfc);
266 static void virtio_nfc_unrealize(DeviceState* dev, Error **errp)
268 VirtIODevice *vdev = VIRTIO_DEVICE(dev);
270 INFO("destroy nfc device\n");
273 qemu_bh_delete(vio_nfc->bh);
276 virtio_cleanup(vdev);
279 static void virtio_nfc_reset(VirtIODevice *vdev)
281 TRACE("virtio_sensor_reset.\n");
285 static void virtio_nfc_class_init(ObjectClass *klass, void *data)
287 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
288 vdc->realize = virtio_nfc_realize;
289 vdc->unrealize = virtio_nfc_unrealize;
290 vdc->get_features = virtio_nfc_get_features;
291 vdc->reset = virtio_nfc_reset;
294 static const TypeInfo virtio_device_info = {
295 .name = TYPE_VIRTIO_NFC,
296 .parent = TYPE_VIRTIO_DEVICE,
297 .instance_size = sizeof(VirtIONFC),
298 .class_init = virtio_nfc_class_init,
301 static void virtio_register_types(void)
303 type_register_static(&virtio_device_info);
306 type_init(virtio_register_types)