vmodem: enable the vmodem device using virtio. 64/23064/5
authorSooyoung Ha <yoosah.ha@samsung.com>
Mon, 16 Jun 2014 13:33:02 +0000 (22:33 +0900)
committerSooyoung Ha <yoosah.ha@samsung.com>
Wed, 18 Jun 2014 09:20:17 +0000 (18:20 +0900)
Now, the telephony virtual modem will use the vmodem device to communicate
with ECP, not emulator daemon.

Change-Id: Icadf54f977f4da84da4cd9745e72b20e0b672548
Signed-off-by: Sooyoung Ha <yoosah.ha@samsung.com>
hw/virtio/virtio-pci.c
hw/virtio/virtio-pci.h
tizen/src/Makefile.tizen
tizen/src/ecs/ecs_msg.c
tizen/src/hw/maru_device_ids.h
tizen/src/hw/maru_virtio_vmodem.c [new file with mode: 0644]
tizen/src/hw/maru_virtio_vmodem.h [new file with mode: 0644]

index f61d281..f3b08c7 100644 (file)
@@ -1931,6 +1931,46 @@ static TypeInfo virtio_power_pci_info = {
     .class_init    = virtio_power_pci_class_init,
 };
 
+/* virtio-vmodem-pci */
+
+static int virtio_vmodem_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIOVModemPCI *dev = VIRTIO_VMODEM_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_vmodem_pci_class_init(ObjectClass *klass, void *data)
+{
+    VirtioPCIClass *k = VIRTIO_PCI_CLASS(klass);
+    PCIDeviceClass *pcidev_k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_vmodem_pci_init;
+    pcidev_k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    pcidev_k->device_id = PCI_DEVICE_ID_VIRTIO_VMODEM;
+    pcidev_k->revision = VIRTIO_PCI_ABI_VERSION;
+    pcidev_k->class_id = PCI_CLASS_OTHERS;
+}
+
+static void virtio_vmodem_pci_instance_init(Object *obj)
+{
+    VirtIOVModemPCI *dev = VIRTIO_VMODEM_PCI(obj);
+    object_initialize(&dev->vdev, sizeof(dev->vdev), TYPE_VIRTIO_VMODEM);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static TypeInfo virtio_vmodem_pci_info = {
+    .name          = TYPE_VIRTIO_VMODEM_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIOVModemPCI),
+    .instance_init = virtio_vmodem_pci_instance_init,
+    .class_init    = virtio_vmodem_pci_class_init,
+};
 
 #endif
 
@@ -2001,6 +2041,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_nfc_pci_info);
     type_register_static(&virtio_jack_pci_info);
     type_register_static(&virtio_power_pci_info);
+    type_register_static(&virtio_vmodem_pci_info);
 #endif
 }
 
index c423213..685bef9 100644 (file)
@@ -43,6 +43,7 @@
 #include "../tizen/src/hw/maru_virtio_jack.h"
 #include "../tizen/src/hw/maru_virtio_power.h"
 #include "../tizen/src/hw/maru_virtio_nfc.h"
+#include "../tizen/src/hw/maru_virtio_vmodem.h"
 #endif
 
 typedef struct VirtIOPCIProxy VirtIOPCIProxy;
@@ -64,6 +65,7 @@ typedef struct VirtIOSENSORPCI VirtIOSENSORPCI;
 typedef struct VirtIONFCPCI VirtIONFCPCI;
 typedef struct VirtIOPOWERPCI VirtIOPOWERPCI;
 typedef struct VirtIOJACKPCI VirtIOJACKPCI;
+typedef struct VirtIOVModemPCI VirtIOVModemPCI;
 #endif
 
 /* virtio-pci-bus */
@@ -333,6 +335,17 @@ struct VirtIOPOWERPCI {
     VirtIOPOWER vdev;
 };
 
+/*
+ * virtio-vmodem-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_VMODEM_PCI "virtio-vmodem-pci"
+#define VIRTIO_VMODEM_PCI(obj) \
+        OBJECT_CHECK(VirtIOVModemPCI, (obj), TYPE_VIRTIO_VMODEM_PCI)
+struct VirtIOVModemPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIOVModem vdev;
+};
+
 #endif
 
 /* Virtio ABI version, if we increment this, we break the guest driver. */
index 43abc06..bffd2ea 100644 (file)
@@ -90,6 +90,7 @@ obj-y += maru_virtio_nfc.o
 obj-y += maru_virtio_jack.o
 obj-y += maru_virtio_power.o
 obj-y += maru_virtio_esm.o
+obj-y += maru_virtio_vmodem.o
 #obj-y += maru_brill_codec.o
 obj-$(CONFIG_LIBAV) += maru_brill_codec.o
 
index 23f9df1..6f40be1 100644 (file)
@@ -66,6 +66,7 @@
 #include "hw/maru_virtio_jack.h"
 #include "hw/maru_virtio_power.h"
 #include "hw/maru_virtio_nfc.h"
+#include "hw/maru_virtio_vmodem.h"
 #include "skin/maruskin_operation.h"
 #include "skin/maruskin_server.h"
 #include "emulator.h"
@@ -334,7 +335,14 @@ injector_send:
         }
     }
 
-    ret = send_to_evdi(route_ij, sndbuf, sndlen);
+    if(strcmp(cmd, "telephony") == 0) {
+       TRACE("telephony msg >>");
+       ret = send_to_vmodem(route_ij, sndbuf, sndlen);
+    } else {
+       TRACE("evdi msg >> %s", cmd);
+       ret = send_to_evdi(route_ij, sndbuf, sndlen);
+    }
+
 
     g_free(sndbuf);
 
index 9f4306f..ad6ec0a 100644 (file)
@@ -57,6 +57,7 @@
 #define PCI_DEVICE_ID_VIRTIO_POWER       0x1035
 #define PCI_DEVICE_ID_VIRTIO_JACK        0x1036
 #define PCI_DEVICE_ID_VIRTIO_NFC         0x1038
+#define PCI_DEVICE_ID_VIRTIO_VMODEM      0x103C
 #define PCI_DEVICE_ID_VIRTUAL_BRILL_CODEC  0x1040
 
 /* Virtio */
@@ -96,5 +97,6 @@
 #define VIRTIO_ID_NFC           38
 #define VIRTIO_ID_JACK          39
 #define VIRTIO_ID_POWER         40
+#define VIRTIO_ID_VMODEM        41
 
 #endif /* MARU_DEVICE_IDS_H_ */
diff --git a/tizen/src/hw/maru_virtio_vmodem.c b/tizen/src/hw/maru_virtio_vmodem.c
new file mode 100644 (file)
index 0000000..dd93d06
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * Virtio Virtual Modem Device
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Sooyoung Ha <yoosah.ha@samsung.com>
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
+ *  Sangho Park <sangho1206.park@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 "maru_device_ids.h"
+#include "maru_virtio_vmodem.h"
+#include "maru_virtio_evdi.h"
+#include "debug_ch.h"
+#include "../ecs/ecs.h"
+
+MULTI_DEBUG_CHANNEL(qemu, virtio-vmodem);
+
+#define VMODEM_DEVICE_NAME "virtio-vmodem"
+
+enum {
+    IOTYPE_INPUT = 0,
+    IOTYPE_OUTPUT = 1
+};
+
+#ifndef min
+#define min(a,b) ((a)<(b)?(a):(b))
+#endif
+
+VirtIOVModem *vio_vmodem;
+
+typedef struct MsgInfo
+{
+    msg_info info;
+    QTAILQ_ENTRY(MsgInfo) next;
+}MsgInfo;
+
+static QTAILQ_HEAD(MsgInfoRecvHead , MsgInfo) vmodem_recv_msg_queue =
+    QTAILQ_HEAD_INITIALIZER(vmodem_recv_msg_queue);
+
+typedef struct EvdiBuf {
+    VirtQueueElement elem;
+
+    QTAILQ_ENTRY(EvdiBuf) next;
+} EvdiBuf;
+
+static QTAILQ_HEAD(EvdiMsgHead , EvdiBuf) vmodem_in_queue =
+    QTAILQ_HEAD_INITIALIZER(vmodem_in_queue);
+
+bool send_to_vmodem(const uint32_t route, char *data, const uint32_t len)
+{
+    int size;
+    int left = len;
+    int count = 0;
+    char *readptr = data;
+
+    while (left > 0) {
+        MsgInfo *_msg = (MsgInfo*) malloc(sizeof(MsgInfo));
+        if (!_msg) {
+            ERR("malloc failed\n");
+            return false;
+        }
+
+        memset(&_msg->info, 0, sizeof(msg_info));
+
+        size = min(left, __MAX_BUF_SIZE);
+        memcpy(_msg->info.buf, readptr, size);
+        readptr += size;
+        _msg->info.use = size;
+        _msg->info.index = count;
+
+        qemu_mutex_lock(&vio_vmodem->mutex);
+
+        QTAILQ_INSERT_TAIL(&vmodem_recv_msg_queue, _msg, next);
+
+        qemu_mutex_unlock(&vio_vmodem->mutex);
+
+        left -= size;
+        count ++;
+    }
+
+    qemu_bh_schedule(vio_vmodem->bh);
+
+    return true;
+}
+
+static void flush_vmodem_recv_queue(void)
+{
+    int index;
+
+    if (unlikely(!virtio_queue_ready(vio_vmodem->rvq))) {
+        ERR("virtio queue is not ready\n");
+        return;
+    }
+
+    if (unlikely(virtio_queue_empty(vio_vmodem->rvq))) {
+        ERR("virtqueue is empty\n");
+        return;
+    }
+
+    qemu_mutex_lock(&vio_vmodem->mutex);
+
+    while (!QTAILQ_EMPTY(&vmodem_recv_msg_queue))
+    {
+        MsgInfo *msginfo = QTAILQ_FIRST(&vmodem_recv_msg_queue);
+        if (!msginfo)
+            break;
+
+        VirtQueueElement elem;
+        index = virtqueue_pop(vio_vmodem->rvq, &elem);
+        if (index == 0) {
+            break;
+        }
+
+        memset(elem.in_sg[0].iov_base, 0, elem.in_sg[0].iov_len);
+        memcpy(elem.in_sg[0].iov_base, &msginfo->info, sizeof(struct msg_info));
+
+        virtqueue_push(vio_vmodem->rvq, &elem, sizeof(msg_info));
+        virtio_notify(&vio_vmodem->vdev, vio_vmodem->rvq);
+
+        QTAILQ_REMOVE(&vmodem_recv_msg_queue, msginfo, next);
+        if (msginfo)
+            free(msginfo);
+    }
+    qemu_mutex_unlock(&vio_vmodem->mutex);
+}
+
+
+static void virtio_vmodem_recv(VirtIODevice *vdev, VirtQueue *vq)
+{
+    flush_vmodem_recv_queue();
+}
+
+static void virtio_vmodem_send(VirtIODevice *vdev, VirtQueue *vq)
+{
+    VirtIOVModem *vvmodem = (VirtIOVModem *)vdev;
+    int index = 0;
+    struct msg_info _msg;
+
+    if (virtio_queue_empty(vvmodem->svq)) {
+        ERR("virtqueue is empty.\n");
+        return;
+    }
+
+    VirtQueueElement elem;
+
+    while ((index = virtqueue_pop(vq, &elem))) {
+        memset(&_msg, 0x00, sizeof(_msg));
+        memcpy(&_msg, elem.out_sg[0].iov_base, elem.out_sg[0].iov_len);
+
+        TRACE("vmodem send to ecp.\n");
+        send_injector_ntf(_msg.buf, _msg.use);
+    }
+
+    virtqueue_push(vq, &elem, sizeof(VirtIOVModem));
+    virtio_notify(&vio_vmodem->vdev, vq);
+}
+
+static uint32_t virtio_vmodem_get_features(VirtIODevice *vdev,
+                                            uint32_t request_feature)
+{
+    TRACE("virtio_vmodem_get_features.\n");
+    return 0;
+}
+
+static void maru_vmodem_bh(void *opaque)
+{
+    flush_vmodem_recv_queue();
+}
+
+static void virtio_vmodem_realize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+
+    vio_vmodem = VIRTIO_VMODEM(vdev);
+
+    if (vio_vmodem == NULL) {
+        ERR("failed to initialize vmodem device\n");
+        return;
+    }
+
+    virtio_init(vdev, TYPE_VIRTIO_VMODEM, VIRTIO_ID_VMODEM, 0); //VMODEM_DEVICE_NAME
+    qemu_mutex_init(&vio_vmodem->mutex);
+
+    vio_vmodem->rvq = virtio_add_queue(&vio_vmodem->vdev, 256, virtio_vmodem_recv);
+    vio_vmodem->svq = virtio_add_queue(&vio_vmodem->vdev, 256, virtio_vmodem_send);
+    vio_vmodem->qdev = dev;
+
+    vio_vmodem->bh = qemu_bh_new(maru_vmodem_bh, vio_vmodem);
+
+    INFO("finish the vmodem device initialization.\n");
+}
+
+static void virtio_vmodem_unrealize(DeviceState *dev, Error **errp)
+{
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
+
+    INFO("destroy vmodem device\n");
+
+    if (vio_vmodem->bh) {
+        qemu_bh_delete(vio_vmodem->bh);
+    }
+
+    qemu_mutex_destroy(&vio_vmodem->mutex);
+    virtio_cleanup(vdev);
+}
+
+static void virtio_vmodem_reset(VirtIODevice *vdev)
+{
+    INFO("virtio_vmodem_reset.\n");
+}
+
+
+static void virtio_vmodem_class_init(ObjectClass *klass, void *data)
+{
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    vdc->realize = virtio_vmodem_realize;
+    vdc->unrealize = virtio_vmodem_unrealize;
+    vdc->get_features = virtio_vmodem_get_features;
+    vdc->reset = virtio_vmodem_reset;
+}
+
+
+
+static const TypeInfo virtio_device_info = {
+    .name = TYPE_VIRTIO_VMODEM,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIOVModem),
+    .class_init = virtio_vmodem_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_device_info);
+}
+
+type_init(virtio_register_types)
diff --git a/tizen/src/hw/maru_virtio_vmodem.h b/tizen/src/hw/maru_virtio_vmodem.h
new file mode 100644 (file)
index 0000000..6248296
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Virtio Virtual Modem Device
+ *
+ * Copyright (c) 2014 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Sooyoung Ha <yoosah.ha@samsung.com>
+ *  SeokYeon Hwang <syeon.hwang@samsung.com>
+ *  Sangho Park <sangho1206.park@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
+ *
+ */
+
+#ifndef MARU_VIRTIO_VMODEM_H_
+#define MARU_VIRTIO_VMODEM_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "hw/virtio/virtio.h"
+
+typedef struct VirtIOVirtualModem{
+    VirtIODevice    vdev;
+    VirtQueue       *rvq;
+    VirtQueue       *svq;
+    DeviceState     *qdev;
+
+    QemuMutex mutex;
+    QEMUBH *bh;
+} VirtIOVModem;
+
+#define TYPE_VIRTIO_VMODEM "virtio-vmodem-device"
+#define VIRTIO_VMODEM(obj) \
+        OBJECT_CHECK(VirtIOVModem, (obj), TYPE_VIRTIO_VMODEM)
+
+bool send_to_vmodem(const uint32_t route, char *data, const uint32_t len);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* MARU_VIRTIO_VMODEM_H_ */