sensor virtual device is added and all the handling for the device
authorJinhyung Choi <jinhyung2.choi@samsung.com>
Mon, 8 Jul 2013 13:53:49 +0000 (22:53 +0900)
committerJinhyung Choi <jinhyung2.choi@samsung.com>
Mon, 8 Jul 2013 13:53:49 +0000 (22:53 +0900)
Signed-off-by: Jinhyung Choi <jinhyung2.choi@samsung.com>
hw/virtio-pci.c
hw/virtio.h
tizen/src/Makefile.tizen
tizen/src/ecs.c
tizen/src/ecs.h
tizen/src/ecs_sensor.c [new file with mode: 0644]
tizen/src/hw/maru_device_ids.h
tizen/src/hw/maru_virtio_sensor.c [new file with mode: 0644]
tizen/src/hw/maru_virtio_sensor.h [new file with mode: 0644]

index f8ad8347c036c90192f62d39412d56c7fa4d52a9..233009a3ebe494d786c772debc5579b0be1d6210 100755 (executable)
@@ -1016,6 +1016,28 @@ static void virtio_evdi_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
+static int virtio_sensor_init_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+    VirtIODevice *vdev;
+
+    vdev = virtio_sensor_init(&pci_dev->qdev);
+    if (!vdev) {
+        return -1;
+    }
+    virtio_init_pci(proxy, vdev);
+    return 0;
+}
+
+static void virtio_sensor_exit_pci(PCIDevice *pci_dev)
+{
+    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
+
+    virtio_pci_stop_ioeventfd(proxy);
+    virtio_sensor_exit(proxy->vdev);
+    virtio_exit_pci(pci_dev);
+}
+
 #endif
 
 static Property virtio_blk_properties[] = {
@@ -1333,6 +1355,27 @@ static TypeInfo virtio_evdi_info = {
     .class_init    = virtio_evdi_class_init,
 };
 
+static void virtio_sensor_class_init(ObjectClass *klass, void *data) {
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+
+    k->init = virtio_sensor_init_pci;
+    k->exit = virtio_sensor_exit_pci;
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_SENSOR;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_OTHERS;
+    dc->reset = virtio_pci_reset;
+       dc->desc = "Emulator Sensor Virtual Device";
+}
+
+
+static TypeInfo virtio_sensor_info = {
+    .name          = "virtio-sensor-pci",
+    .parent        = TYPE_PCI_DEVICE,
+    .instance_size = sizeof(VirtIOPCIProxy),
+    .class_init    = virtio_sensor_class_init,
+};
 
 #endif /* CONFIG_MARU */
 
@@ -1352,6 +1395,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_esm_info);
     type_register_static(&virtio_hwkey_info);
     type_register_static(&virtio_evdi_info);
+    type_register_static(&virtio_sensor_info);
 #endif
 }
 
index 0b035618cf7e95221c9cc53e78025c1b528e907c..40ac7fbb9b9cdd93f5373b52c2d101e180727cc8 100755 (executable)
@@ -222,6 +222,7 @@ void virtio_scsi_exit(VirtIODevice *vdev);
 #include "tizen/src/hw/maru_virtio_keyboard.h"
 #include "tizen/src/hw/maru_virtio_esm.h"
 #include "tizen/src/hw/maru_virtio_hwkey.h"
+#include "tizen/src/hw/maru_virtio_sensor.h"
 #endif
 
 
index 87292a1529cb1143d262a4570d5175ba1182f06b..79b8dce41c80481b59185b6eb90a4c789f261702 100755 (executable)
@@ -105,7 +105,7 @@ endif
 obj-y += debug_ch.o
 
 # ecs
-obj-y += ecs_msg.o ecs.o ecs-json-streamer.o qmp_handler.o
+obj-y += ecs_msg.o ecs.o ecs-json-streamer.o qmp_handler.o ecs_sensor.o
 
 # maru hardware
 include $(SRC_PATH)/tizen/src/Makefile.tizen.$(TARGET_BASE_ARCH)
@@ -117,6 +117,7 @@ obj-y += maru_codec.o
 obj-y += maru_virtio_esm.o
 obj-y += maru_virtio_hwkey.o
 obj-y += maru_virtio_evdi.o
+obj-y += maru_virtio_sensor.o
 
 obj-$(CONFIG_PCI) += maru_camera_common_pci.o
 obj-$(CONFIG_LINUX) += maru_camera_linux_pci.o
index b2b82cae3e1db3a02df7a53ccbeaea430249b7a0..0315308e5b583b5600ff4963dc989a80b9dace8a 100644 (file)
@@ -20,6 +20,7 @@
 #include "qint.h"
 #include "ecs.h"
 #include "hw/maru_virtio_evdi.h"
+#include "hw/maru_virtio_sensor.h"
 #include <stdbool.h>
 #include <pthread.h>
 #include "base64.h"
@@ -808,6 +809,7 @@ static bool injector_command_proc(ECS_Client *clii, QObject *obj) {
         }
 
     } else {
+
         // set data
         memcpy(sndbuf, cmd, 10);
         memcpy(sndbuf + 10, &length, 2);
@@ -838,6 +840,44 @@ static bool control_command_proc(ECS_Client *clii, QObject *obj) {
        return true;
 }
 
+static bool device_command_proc(ECS_Client *clii, QObject *obj) {
+       QDict* header = qdict_get_qdict(qobject_to_qdict(obj), "header");
+
+       char cmd[10];
+       memset(cmd, 0, 10);
+       strcpy(cmd, qdict_get_str(header, "cat"));
+       type_length length = (type_length) qdict_get_int(header, "length");
+       type_group group = (type_action) (qdict_get_int(header, "group") & 0xff);
+       type_action action = (type_group) (qdict_get_int(header, "action") & 0xff);
+
+       // get data
+       const char* data = qdict_get_str(qobject_to_qdict(obj), COMMANDS_DATA);
+       LOG(">> count= %d", ++ijcount);
+       LOG(">> print len = %d, data\" %s\"", strlen(data), data);
+       LOG(">> header = cmd = %s, length = %d, action=%d, group=%d", cmd, length,
+                       action, group);
+       if (!strncmp(cmd, MSG_TYPE_SENSOR, 6)) {
+               if (group == MSG_GROUP_STATUS) {
+                       if (action ==MSG_ACTION_ACCEL) {
+                               get_sensor_accel();
+                       } else if (action == MSG_ACTION_GYRO) {
+                               get_sensor_gyro();
+                       } else if (action == MSG_ACTION_MAG) {
+                               get_sensor_mag();
+                       } else if (action == MSG_ACTION_LIGHT) {
+                               get_sensor_light();
+                       } else if (action == MSG_ACTION_PROXI) {
+                               get_sensor_proxi();
+                       }
+               } else {
+                       set_sensor_data(length, data);
+               }
+       }
+
+       return true;
+}
+
 static void handle_ecs_command(JSONMessageParser *parser, QList *tokens,
                void *opaque) {
        const char *type_name;
@@ -900,6 +940,8 @@ static void handle_ecs_command(JSONMessageParser *parser, QList *tokens,
                control_command_proc(clii, obj);
        } else if (!strcmp(type_name, COMMAND_TYPE_MONITOR)) {
                handle_qmp_command(clii, type_name, get_data_object(obj));
+       } else if (!strcmp(type_name, COMMAND_TYPE_DEVICE)) {
+               device_command_proc(clii, obj);
        } else if (!strcmp(type_name, ECS_MSG_STARTINFO_REQ)) {
                ecs_startinfo_req(clii);
        } else {
index fb9a56c8301ca3c4866599d3581ee098715e8ba9..68dd4522dd5958f17f5c938466886db137d8053e 100644 (file)
 #define COMMAND_TYPE_INJECTOR  "injector"
 #define COMMAND_TYPE_CONTROL   "control"
 #define COMMAND_TYPE_MONITOR   "monitor"
+#define COMMAND_TYPE_DEVICE            "device"
 
-#define ECS_MSG_STARTINFO_REQ "startinfo_req"
-#define ECS_MSG_STARTINFO_ANS "startinfo_ans"
+#define ECS_MSG_STARTINFO_REQ  "startinfo_req"
+#define ECS_MSG_STARTINFO_ANS  "startinfo_ans"
 
+#define MSG_TYPE_SENSOR                        "sensor"
+
+#define MSG_GROUP_STATUS               15
+
+#define MSG_ACTION_ACCEL               110
+#define MSG_ACTION_GYRO                        111
+#define MSG_ACTION_MAG                 112
+#define MSG_ACTION_LIGHT               113
+#define MSG_ACTION_PROXI               114
 
 #define TIMER_ALIVE_S                  60      
 #define TYPE_DATA_SELF                 "self"
 
+enum sensor_level {
+       level_accel = 1,
+       level_proxi = 2,
+       level_light = 3,
+       level_gyro = 4,
+       level_geo = 5,
+       level_tilt = 12,
+       level_magnetic = 13
+};
 
 typedef unsigned short type_length;
 typedef unsigned char  type_group;
@@ -124,4 +143,6 @@ enum{
 void ecs_startinfo_req(ECS_Client *clii);
 void control_host_keyboard_onoff_req(ECS_Client *clii, QDict* data);
 
+void set_sensor_data(int length, const char* data);
+
 #endif /* __ECS_H__ */
diff --git a/tizen/src/ecs_sensor.c b/tizen/src/ecs_sensor.c
new file mode 100644 (file)
index 0000000..256b58f
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * Emulator Control Server - Sensor Device Handler
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Jinhyung choi      <jinhyung2.choi@samsung.com>
+ *  Daiyoung Kim       <daiyoung777.kim@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 "qemu-common.h"
+#include "qemu_socket.h"
+#include "qemu-queue.h"
+#include "qemu-option.h"
+#include "qemu-config.h"
+#include "qemu-timer.h"
+
+#include "ecs.h"
+#include "hw/maru_virtio_sensor.h"
+
+#define TEMP_BUF_SIZE  255
+#define MAX_VAL_LENGTH 40
+
+#define ACCEL_ADJUST   100000
+#define ACCEL_MAX              1961330
+
+#define GYRO_ADJUST            17.50
+
+static int parse_val(const char *buff, unsigned char data, char *parsbuf)
+{
+       int count=0;
+
+       while(1)
+       {
+               if(count > MAX_VAL_LENGTH)
+                       return -1;
+               if(buff[count] == data)
+               {
+                       count++;
+                       strncpy(parsbuf, buff, count);
+                       return count;
+               }
+               count++;
+       }
+
+       return 0;
+}
+
+static int get_parse_val (const char* buf, char* tmp)
+{
+       int index = 0;
+
+       memset(tmp, 0, sizeof(TEMP_BUF_SIZE));
+
+       index = parse_val(buf, 0x0a, tmp); 
+
+       return index;
+}
+
+static int accel_min_max(char* tmp)
+{
+       int value = (int)(atof(tmp) * ACCEL_ADJUST);
+
+       if (value > ACCEL_MAX)
+               value = ACCEL_MAX;
+
+       if (value < -ACCEL_MAX)
+               value = -ACCEL_MAX;
+
+       return value;
+}
+
+static void req_set_sensor_accel(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x, y, z;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = accel_min_max(tmp);
+
+       // y
+       len += get_parse_val(data + len, tmp);
+       y = accel_min_max(tmp);
+
+       // z
+       len += get_parse_val(data + len, tmp);
+       z = accel_min_max(tmp);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d, %d, %d", x, y, z);
+
+       set_sensor_accel(tmp, strlen(tmp));
+}
+
+static void req_set_sensor_proxi(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // vo
+       len += get_parse_val(data + len, tmp);
+
+       set_sensor_proxi(tmp, strlen(tmp));
+}
+
+static void req_set_sensor_light(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = atoi(tmp);
+
+       if (x == 2) {
+               // y
+               len += get_parse_val(data + len, tmp);
+
+               set_sensor_light(tmp, strlen(tmp));
+       }
+}
+
+static void req_set_sensor_gyro(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x, y, z;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = (int)(atoi(tmp) / GYRO_ADJUST);
+
+       // y
+       len += get_parse_val(data + len, tmp);
+       y = (int)(atoi(tmp) / GYRO_ADJUST);
+
+       // z
+       len += get_parse_val(data + len, tmp);
+       z = (int)(atoi(tmp) / GYRO_ADJUST);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d %d %d", x, y, z);
+
+       set_sensor_gyro(tmp, strlen(tmp));
+}
+
+static void req_set_sensor_geo(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x, y, z, accuracy, t_north, t_east, t_vertical;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = atoi(tmp);
+
+       // y
+       len += get_parse_val(data + len, tmp);
+       y = atoi(tmp);
+
+       // z
+       len += get_parse_val(data + len, tmp);
+       z = atoi(tmp);
+
+       len += get_parse_val(data + len, tmp);
+       accuracy = atoi(tmp);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d %d %d %d", x, y, z, accuracy);
+
+       set_sensor_tilt(tmp, strlen(tmp));
+
+       // tesla_north
+       len += get_parse_val(data + len, tmp);
+       t_north = atoi(tmp);
+
+       // tesla_east
+       len += get_parse_val(data + len, tmp);
+       t_east = atoi(tmp);
+
+       // tesla_vertical
+       len += get_parse_val(data + len, tmp);
+       t_vertical = atoi(tmp);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d %d %d", t_north, t_east, t_vertical);
+
+       set_sensor_mag(tmp, strlen(tmp));
+}
+
+static void req_set_sensor_tilt(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x, y, z, accuracy = 3;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = atoi(tmp);
+
+       // y
+       len += get_parse_val(data + len, tmp);
+       y = atoi(tmp);
+
+       // z
+       len += get_parse_val(data + len, tmp);
+       z = atoi(tmp);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d %d %d %d", x, y, z, accuracy);
+
+       set_sensor_tilt(tmp, strlen(tmp));
+}
+
+static void req_set_sensor_mag(int len, const char* data)
+{
+       char tmp[TEMP_BUF_SIZE];
+       int x, y, z;
+
+       // get sensor level
+       len += get_parse_val(data + len, tmp);
+
+       // x
+       len += get_parse_val(data + len, tmp);
+       x = atoi(tmp);
+
+       // y
+       len += get_parse_val(data + len, tmp);
+       y = atoi(tmp);
+
+       // z
+       len += get_parse_val(data + len, tmp);
+       z = atoi(tmp);
+
+       memset(tmp, 0, TEMP_BUF_SIZE);
+
+       sprintf(tmp, "%d %d %d", x, y, z);
+
+       set_sensor_mag(tmp, strlen(tmp));
+}
+
+void set_sensor_data(int length, const char* data)
+{
+       char tmpbuf[TEMP_BUF_SIZE];
+       int len = get_parse_val(data, tmpbuf);
+
+       switch(atoi(tmpbuf)) {
+               case level_accel:
+                       req_set_sensor_accel(len, data);
+                       break;
+               case level_proxi:
+                       req_set_sensor_proxi(len, data);
+                       break;
+               case level_light:
+                       req_set_sensor_light(len, data);
+                       break;
+               case level_gyro:
+                       req_set_sensor_gyro(len, data);
+                       break;
+               case level_geo:
+                       req_set_sensor_geo(len, data);
+                       break;
+               case level_tilt:
+                       req_set_sensor_tilt(len, data);
+                       break;
+               case level_magnetic:
+                       req_set_sensor_mag(len, data);
+                       break;
+               default:
+                       break;
+       }
+}
+
index deda8024d6132caf6d1fd0ebab68239bdf5d5069..5baffa3e4c580a945b2138ea9cfa6c25506403fc 100755 (executable)
@@ -54,6 +54,7 @@
 #define PCI_DEVICE_ID_VIRTIO_ESM         0x1024
 #define PCI_DEVICE_ID_VIRTIO_HWKEY       0x1028
 #define PCI_DEVICE_ID_VIRTIO_EVDI        0x102C
+#define PCI_DEVICE_ID_VIRTIO_SENSOR      0x1030
 
 /* Virtio */
 /*
@@ -87,5 +88,6 @@
 #define VIRTIO_ID_ESM           13
 #define VIRTIO_ID_HWKEY         14
 #define VIRTIO_ID_EVDI          15
+#define VIRTIO_ID_SENSOR        16
 
 #endif /* MARU_DEVICE_IDS_H_ */
diff --git a/tizen/src/hw/maru_virtio_sensor.c b/tizen/src/hw/maru_virtio_sensor.c
new file mode 100644 (file)
index 0000000..4a276cf
--- /dev/null
@@ -0,0 +1,283 @@
+/*
+ * Virtio Sensor Device
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Jinhyung Choi <jinhyung2.choi@samsung.com>
+ *  Daiyoung Kim <daiyoung777.kim@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 "pci.h"
+
+#include "maru_device_ids.h"
+#include "maru_virtio_sensor.h"
+#include "debug_ch.h"
+#include "../ecs.h"
+
+MULTI_DEBUG_CHANNEL(qemu, virtio-sensor);
+
+#define VIRTIO_SENSOR_DEVICE_NAME      "sensor"
+#define _MAX_BUF                                       1024
+
+typedef struct VirtIOSensor {
+    VirtIODevice    vdev;
+    VirtQueue       *rvq;
+    VirtQueue       *svq;
+    DeviceState     *qdev;
+
+       QEMUBH                  *bh;
+} VirtIO_Sensor;
+
+VirtIO_Sensor* vsensor;
+
+typedef struct msg_info {
+       char buf[_MAX_BUF];
+
+       uint16_t type;
+       uint16_t req;
+
+       QTAILQ_ENTRY(msg_info) next;
+} msg_info;
+
+
+static QTAILQ_HEAD(msgInfoRecvHead , msg_info) sensor_msg_queue =
+    QTAILQ_HEAD_INITIALIZER(sensor_msg_queue);
+
+static pthread_mutex_t buf_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static void add_msg_queue(msg_info* msg)
+{
+       pthread_mutex_lock(&buf_mutex);
+       QTAILQ_INSERT_TAIL(&sensor_msg_queue, msg, next);
+       pthread_mutex_unlock(&buf_mutex);
+
+       qemu_bh_schedule(vsensor->bh);
+}
+
+void req_sensor_data (enum sensor_types type, enum request_cmd req, char* data, int len)
+{
+       if (type >= sensor_type_max || (req != request_get && req != request_set)) {
+               ERR("unavailable sensor type request.\n");
+       }
+
+       msg_info* msg = (msg_info*) malloc(sizeof(msg_info));
+       if (!msg) {
+               ERR("The allocation of msg_info is failed.\n");
+               return;
+       }
+
+       memset(msg, 0, sizeof(msg_info));
+
+       if (req == request_set) {
+               if (len > _MAX_BUF) {
+                       ERR("The data is too big to send.\n");
+                       return;
+               }
+               memcpy(msg->buf, data, len);
+       }
+
+       msg->type = type;
+       msg->req = req;
+
+       add_msg_queue(msg);
+}
+
+static uint32_t virtio_sensor_get_features(VirtIODevice *vdev,
+                                            uint32_t request_feature)
+{
+    TRACE("virtio_sensor_get_features.\n");
+    return 0;
+}
+
+static void flush_sensor_recv_queue(void)
+{
+       int index;
+
+    if (unlikely(!virtio_queue_ready(vsensor->rvq))) {
+        INFO("virtio queue is not ready\n");
+        return;
+    }
+
+       if (unlikely(virtio_queue_empty(vsensor->rvq))) {
+               INFO("virtqueue is empty\n");
+               return;
+       }
+
+       pthread_mutex_lock(&buf_mutex);
+       while (!QTAILQ_EMPTY(&sensor_msg_queue))
+       {
+               msg_info* msginfo = QTAILQ_FIRST(&sensor_msg_queue);
+               if (!msginfo) {
+                       ERR("msginfo is NULL!\n");
+                       break;
+               }
+
+               INFO("sending message: %s, type: %d, req: %d\n", msginfo->buf, msginfo->type, msginfo->req);
+
+               VirtQueueElement elem;
+               index = virtqueue_pop(vsensor->rvq, &elem);
+               if (index == 0)
+                       break;
+
+               memcpy(elem.in_sg[0].iov_base, msginfo, sizeof(struct msg_info));
+
+               virtqueue_push(vsensor->rvq, &elem, sizeof(msg_info));
+               virtio_notify(&vsensor->vdev, vsensor->rvq);
+
+               QTAILQ_REMOVE(&sensor_msg_queue, msginfo, next);
+               if (msginfo)
+                       free(msginfo);
+       }
+       pthread_mutex_unlock(&buf_mutex);
+}
+
+static void virtio_sensor_recv(VirtIODevice *vdev, VirtQueue *vq)
+{
+       flush_sensor_recv_queue();
+}
+
+static void maru_sensor_bh(void *opaque)
+{
+       flush_sensor_recv_queue();
+}
+
+static int get_action(enum sensor_types type)
+{
+       int action = 0;
+
+       switch (type) {
+       case sensor_type_accel:
+               action = ACTION_ACCEL;
+               break;
+       case sensor_type_gyro:
+               action = ACTION_GYRO;
+               break;
+       case sensor_type_mag:
+               action = ACTION_MAG;
+               break;
+       case sensor_type_light:
+               action = ACTION_LIGHT;
+               break;
+       case sensor_type_proxi:
+               action = ACTION_PROXI;
+               break;
+       default:
+               break;
+       }
+
+       return action;
+}
+
+static void send_to_ecs(struct msg_info* msg)
+{
+       int buf_len;
+       char data_len [2];
+       char group [1] = { GROUP_STATUS };
+       char action [1];
+       int message_len = 0;
+
+       char* ecs_message = NULL;
+
+       buf_len = strlen(msg->buf);
+       message_len =  buf_len + 14;
+
+       ecs_message = (char*) malloc(message_len + 1);
+       if (!ecs_message)
+               return;
+
+       memset(ecs_message, 0, message_len + 1);
+
+       data_len[0] = buf_len;
+       action[0] = get_action(msg->type);
+
+       memcpy(ecs_message, MESSAGE_TYPE_SENSOR, 10);
+       memcpy(ecs_message + 10, &data_len, 2);
+       memcpy(ecs_message + 12, &group, 1);
+       memcpy(ecs_message + 13, &action, 1);
+       memcpy(ecs_message + 14, msg->buf, buf_len);
+
+       INFO("ntf_to_injector- bufnum: %s, group: %s, action: %s, data: %s\n", data_len, group, action, msg->buf);
+
+       ntf_to_injector(ecs_message, message_len);
+
+       if (ecs_message)
+               free(ecs_message);
+}
+
+static void virtio_sensor_send(VirtIODevice *vdev, VirtQueue *vq)
+{
+       VirtIO_Sensor *vsensor = (VirtIO_Sensor *)vdev;
+       struct msg_info msg;
+    VirtQueueElement elem;
+       int index = 0;
+
+    if (virtio_queue_empty(vsensor->svq)) {
+        INFO("<< virtqueue is empty.\n");
+        return;
+    }
+
+    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);
+
+               INFO("send to ecs: %s, len: %d, type: %d, req: %d\n", msg.buf, strlen(msg.buf), msg.type, msg.req);
+               send_to_ecs(&msg);
+    }
+
+       virtqueue_push(vq, &elem, sizeof(VirtIO_Sensor));
+       virtio_notify(&vsensor->vdev, vq);
+}
+
+VirtIODevice *virtio_sensor_init(DeviceState *dev)
+{
+    INFO("initialize virtio-sensor device\n");
+
+    vsensor = (VirtIO_Sensor *)virtio_common_init(VIRTIO_SENSOR_DEVICE_NAME,
+            VIRTIO_ID_SENSOR, 0, sizeof(VirtIO_Sensor));
+    if (vsensor == NULL) {
+        ERR("failed to initialize sensor device\n");
+        return NULL;
+    }
+
+    vsensor->vdev.get_features = virtio_sensor_get_features;
+    vsensor->rvq = virtio_add_queue(&vsensor->vdev, 64, virtio_sensor_recv);
+    vsensor->svq = virtio_add_queue(&vsensor->vdev, 64, virtio_sensor_send);
+    vsensor->qdev = dev;
+
+    vsensor->bh = qemu_bh_new(maru_sensor_bh, vsensor);
+
+    return &vsensor->vdev;
+}
+
+void virtio_sensor_exit(VirtIODevice *vdev)
+{
+    INFO("destroy sensor device\n");
+
+       if (vsensor->bh)
+               qemu_bh_delete(vsensor->bh);
+
+    virtio_cleanup(vdev);
+}
+
diff --git a/tizen/src/hw/maru_virtio_sensor.h b/tizen/src/hw/maru_virtio_sensor.h
new file mode 100644 (file)
index 0000000..c60bc8b
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Virtio Sensor Device
+ *
+ * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Contact:
+ *  Jinhyung choi      <jinhyung2.choi@samsung.com>
+ *  Daiyoung Kim       <daiyoung777.kim@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_SENSOR_H_
+#define MARU_VIRTIO_SENSOR_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "hw/virtio.h"
+
+enum request_cmd {
+       request_get = 0,
+       request_set,
+       request_answer
+};
+
+enum sensor_types {
+       sensor_type_accel = 0,
+       sensor_type_geo,
+       sensor_type_gyro,
+       sensor_type_light,
+       sensor_type_proxi,
+       sensor_type_mag,
+       sensor_type_tilt,
+       sensor_type_max
+};
+
+#define MESSAGE_TYPE_SENSOR    "sensor"
+
+#define GROUP_STATUS           15
+
+#define ACTION_ACCEL           110
+#define ACTION_GYRO                    111
+#define ACTION_MAG                     112
+#define ACTION_LIGHT           113
+#define ACTION_PROXI           114
+
+VirtIODevice *virtio_sensor_init(DeviceState *dev);
+
+void virtio_sensor_exit(VirtIODevice *vdev);
+
+void req_sensor_data(enum sensor_types type, enum request_cmd req, char* data, int len);
+
+#define get_sensor_accel()     \
+       req_sensor_data(sensor_type_accel, request_get, NULL, 0);
+
+#define get_sensor_gyro()      \
+       req_sensor_data(sensor_type_gyro, request_get, NULL, 0);
+
+#define get_sensor_mag()       \
+       req_sensor_data(sensor_type_mag, request_get, NULL, 0);
+
+#define get_sensor_light()     \
+       req_sensor_data(sensor_type_light, request_get, NULL, 0);
+
+#define get_sensor_proxi()     \
+       req_sensor_data(sensor_type_proxi, request_get, NULL, 0);
+
+#define set_sensor_accel(data, len)    \
+       req_sensor_data(sensor_type_accel, request_set, data, len);
+
+#define set_sensor_proxi(data, len)    \
+       req_sensor_data(sensor_type_proxi, request_set, data, len);
+
+#define set_sensor_light(data, len)    \
+       req_sensor_data(sensor_type_light, request_set, data, len);
+
+#define set_sensor_gyro(data, len)     \
+       req_sensor_data(sensor_type_gyro, request_set, data, len);
+
+#define set_sensor_tilt(data, len)     \
+       req_sensor_data(sensor_type_tilt, request_set, data, len);
+
+#define set_sensor_mag(data, len)      \
+       req_sensor_data(sensor_type_mag, request_set, data, len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif