#include "qmp-commands.h"
#include "ecs.h"
+#include "hw/maru_virtio_evdi.h"
#define OUT_BUF_SIZE 4096
#define READ_BUF_LEN 4096
}
}
+
+bool send_to_all_client(const char* data, const int len)
+{
+ ECS_Client *clii;
+
+ QTAILQ_FOREACH(clii, &clients, next)
+ {
+ send_to_client(clii->client_fd, data);
+ }
+
+ return true;
+}
+
void send_to_client(int fd, const char *str)
{
char c;
return;
}
+
+ // send to evdi
+ data = qdict_get_str(qobject_to_qdict(obj), COMMANDS_DATA);
+ LOG("print data: %s, %d", data, strlen(data));
+
+ int datalen = strlen(data);
+ send_to_evdi(route_ij, data, datalen);
+
+ /*
if (!strcmp(type_name, "Battery")) {
data = qdict_get_str(qobject_to_qdict(obj), COMMANDS_DATA);
- LOG("print data: %s", data);
+ LOG("print data: %s, %d", data, strlen(data));
+
+ int datalen = strlen(data);
+ send_to_evdi(route_ij, data, datalen);
+ return;
+ }
+
+ if (!strcmp(type_name, "Telephony")) {
+ data = qdict_get_str(qobject_to_qdict(obj), COMMANDS_DATA);
+ LOG("print data: %s, %d", data, strlen(data));
+
+ int datalen = strlen(data);
+ send_to_evdi(route_ij, data, datalen);
return;
}
+ */
handle_qmp_command(clii, type_name, get_data_object(obj));
}
*\r
*/\r
\r
+#include <pthread.h>\r
+\r
#include "maru_device_ids.h"\r
#include "maru_virtio_evdi.h"\r
#include "debug_ch.h"\r
+#include "../ecs.h"\r
\r
MULTI_DEBUG_CHANNEL(qemu, virtio-evdi);\r
\r
#define VIRTIO_EVDI_DEVICE_NAME "virtio-evdi"\r
\r
-#define __MAX_BUF_SIZE 1024\r
\r
enum {\r
IOTYPE_INPUT = 0,\r
IOTYPE_OUTPUT = 1\r
};\r
\r
-struct msg_info {\r
- char buf[__MAX_BUF_SIZE];\r
- uint32_t use;\r
-};\r
+\r
+#ifndef min\r
+#define min(a,b) ((a)<(b)?(a):(b))\r
+#endif\r
+\r
\r
typedef struct VirtIO_EVDI{\r
VirtIODevice vdev;\r
\r
VirtIO_EVDI* vio_evdi;\r
\r
-static int g_cnt = 0;\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) evdi_recv_msg_queue =\r
+ QTAILQ_HEAD_INITIALIZER(evdi_recv_msg_queue);\r
+\r
+\r
+static QTAILQ_HEAD(MsgInfoSendHead , MsgInfo) evdi_send_msg_queue =\r
+ QTAILQ_HEAD_INITIALIZER(evdi_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) evdi_in_queue =\r
+ QTAILQ_HEAD_INITIALIZER(evdi_in_queue);\r
+\r
+\r
+static pthread_mutex_t recv_buf_mutex = PTHREAD_MUTEX_INITIALIZER;\r
+static pthread_mutex_t send_buf_mutex = PTHREAD_MUTEX_INITIALIZER;\r
+\r
+/*\r
+bool queue_evdi_buf(VirtIO_EVDI* evdi)\r
+{\r
+ int sg_idx;\r
+ EvdiBuf* ebuf = malloc(sizeof(EvdiBuf));\r
+\r
+ while (sg_idx = virtqueue_pop(evdi->rvq, &ebuf->elem))\r
+\r
+ INFO(">> QueueEvdiBuf : sg_idx = %d\n", sg_idx);\r
+\r
+\r
+ pthread_mutex_lock(&recv_buf_mutex);\r
+\r
+ QTAILQ_INSERT_TAIL(&evdi_in_queue, ebuf, next);\r
+ qemu_bh_schedule(evdi->bh);\r
+\r
+ pthread_mutex_unlock(&recv_buf_mutex);\r
+}\r
+*/\r
+/*\r
+void reset_msg_info(msg_info* info)\r
+{\r
+ info->route = route_ij;\r
+ info->use = 0;\r
+ info->count = 0;\r
+ info->index = 0;\r
+\r
+}\r
+*/\r
+\r
+bool send_to_evdi(const uint32_t route, char* data, const uint32_t len)\r
+{\r
+ int size;\r
+ int left = len;\r
+ int count = 0;\r
+ char* readptr = data;\r
+\r
+ while (left > 0)\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
+ size = min(left, __MAX_BUF_SIZE);\r
+ memcpy(_msg->info.buf, readptr, size);\r
+ readptr += size;\r
+ _msg->info.use = size;\r
+ _msg->info.index = count;\r
+\r
+ pthread_mutex_lock(&recv_buf_mutex);\r
+\r
+ QTAILQ_INSERT_TAIL(&evdi_recv_msg_queue, _msg, next);\r
+\r
+ pthread_mutex_unlock(&recv_buf_mutex);\r
+\r
+ left -= size;\r
+ count ++;\r
+ }\r
+\r
+ qemu_bh_schedule(vio_evdi->bh);\r
+\r
+ return true;\r
+}\r
+\r
+\r
+//static int g_cnt = 0;\r
+\r
+static void flush_evdi_recv_queue(void)\r
+{\r
+ int index;\r
+ TRACE("nothing to do.\n");\r
+\r
+ if (unlikely(!virtio_queue_ready(vio_evdi->rvq))) {\r
+ INFO("virtio queue is not ready\n");\r
+ return;\r
+ }\r
+\r
+ if (unlikely(virtio_queue_empty(vio_evdi->rvq))) {\r
+ TRACE("virtqueue is empty\n");\r
+ return;\r
+ }\r
+\r
+\r
+ pthread_mutex_lock(&recv_buf_mutex);\r
+\r
+ while (!QTAILQ_EMPTY(&evdi_recv_msg_queue))\r
+ {\r
+ MsgInfo* msginfo = QTAILQ_FIRST(&evdi_recv_msg_queue);\r
+ if (!msginfo)\r
+ break;\r
+\r
+ VirtQueueElement elem;\r
+ index = virtqueue_pop(vio_evdi->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 use = %d, msg = %s, iov_len = %d \n",\r
+ msginfo->info.use, msginfo->info.buf, elem.in_sg[0].iov_len);\r
+\r
+ virtqueue_push(vio_evdi->rvq, &elem, sizeof(msg_info));\r
+ virtio_notify(&vio_evdi->vdev, vio_evdi->rvq);\r
+\r
+ QTAILQ_REMOVE(&evdi_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_evdi_recv(VirtIODevice *vdev, VirtQueue *vq)\r
{\r
+ INFO(">> evdirecv : virtio_evdi_recv\n");\r
+\r
+ if (!QTAILQ_EMPTY(&evdi_recv_msg_queue))\r
+ return;\r
+\r
+ flush_evdi_recv_queue();\r
+\r
+ INFO("enf of virtio_evdi_recv\n");\r
+}\r
+\r
+/*\r
+static void virtio_evdi_recv(VirtIODevice *vdev, VirtQueue *vq)\r
+{\r
int index = 0;\r
\r
struct msg_info _msg;\r
INFO("enf of virtio_evdi_recv\n");\r
}\r
\r
+*/\r
\r
static void virtio_evdi_send(VirtIODevice *vdev, VirtQueue *vq)\r
{\r
int index = 0;\r
struct msg_info _msg;\r
\r
+ if (virtio_queue_empty(vevdi->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_all_client(_msg.buf, _msg.use);\r
+ }\r
+\r
+ virtqueue_push(vq, &elem, sizeof(VirtIO_EVDI));\r
+ virtio_notify(&vio_evdi->vdev, vq);\r
+}\r
+\r
+/*\r
+static void virtio_evdi_send(VirtIODevice *vdev, VirtQueue *vq)\r
+{\r
+ VirtIO_EVDI *vevdi = (VirtIO_EVDI *)vdev;\r
+ int index = 0;\r
+ struct msg_info _msg;\r
+\r
INFO("<< evdisend : virtio_evdi_send \n");\r
if (virtio_queue_empty(vevdi->svq)) {\r
INFO("<< evdisend : virtqueue is empty.\n");\r
virtqueue_push(vq, &elem, sizeof(VirtIO_EVDI));\r
virtio_notify(&vio_evdi->vdev, vq);\r
}\r
-\r
-static void maru_virtio_evdi_notify(void)\r
-{\r
- TRACE("nothing to do.\n");\r
-}\r
+*/\r
\r
static uint32_t virtio_evdi_get_features(VirtIODevice *vdev,\r
uint32_t request_feature)\r
\r
static void maru_evdi_bh(void *opaque)\r
{\r
- maru_virtio_evdi_notify();\r
+ flush_evdi_recv_queue();\r
}\r
\r
VirtIODevice *virtio_evdi_init(DeviceState *dev)\r