From 1dedfe909f0a9f72bb9a9dbcb41e4943d1af31f0 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Mon, 8 Jul 2013 22:53:49 +0900 Subject: [PATCH] sensor virtual device is added and all the handling for the device Signed-off-by: Jinhyung Choi --- hw/virtio-pci.c | 44 +++++ hw/virtio.h | 1 + tizen/src/Makefile.tizen | 3 +- tizen/src/ecs.c | 42 ++++ tizen/src/ecs.h | 25 ++- tizen/src/ecs_sensor.c | 312 ++++++++++++++++++++++++++++++ tizen/src/hw/maru_device_ids.h | 2 + tizen/src/hw/maru_virtio_sensor.c | 283 +++++++++++++++++++++++++++ tizen/src/hw/maru_virtio_sensor.h | 109 +++++++++++ 9 files changed, 818 insertions(+), 3 deletions(-) create mode 100644 tizen/src/ecs_sensor.c create mode 100644 tizen/src/hw/maru_virtio_sensor.c create mode 100644 tizen/src/hw/maru_virtio_sensor.h diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index f8ad8347c0..233009a3eb 100755 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -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 } diff --git a/hw/virtio.h b/hw/virtio.h index 0b035618cf..40ac7fbb9b 100755 --- a/hw/virtio.h +++ b/hw/virtio.h @@ -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 diff --git a/tizen/src/Makefile.tizen b/tizen/src/Makefile.tizen index 87292a1529..79b8dce41c 100755 --- a/tizen/src/Makefile.tizen +++ b/tizen/src/Makefile.tizen @@ -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 diff --git a/tizen/src/ecs.c b/tizen/src/ecs.c index b2b82cae3e..0315308e5b 100644 --- a/tizen/src/ecs.c +++ b/tizen/src/ecs.c @@ -20,6 +20,7 @@ #include "qint.h" #include "ecs.h" #include "hw/maru_virtio_evdi.h" +#include "hw/maru_virtio_sensor.h" #include #include #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 { diff --git a/tizen/src/ecs.h b/tizen/src/ecs.h index fb9a56c830..68dd4522dd 100644 --- a/tizen/src/ecs.h +++ b/tizen/src/ecs.h @@ -39,14 +39,33 @@ #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 index 0000000000..256b58f23a --- /dev/null +++ b/tizen/src/ecs_sensor.c @@ -0,0 +1,312 @@ +/* + * Emulator Control Server - Sensor Device Handler + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung choi + * Daiyoung Kim + * YeongKyoon Lee + * + * 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; + } +} + diff --git a/tizen/src/hw/maru_device_ids.h b/tizen/src/hw/maru_device_ids.h index deda8024d6..5baffa3e4c 100755 --- a/tizen/src/hw/maru_device_ids.h +++ b/tizen/src/hw/maru_device_ids.h @@ -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 index 0000000000..4a276cf691 --- /dev/null +++ b/tizen/src/hw/maru_virtio_sensor.c @@ -0,0 +1,283 @@ +/* + * Virtio Sensor Device + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung Choi + * Daiyoung Kim + * YeongKyoon Lee + * + * 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 index 0000000000..c60bc8be2c --- /dev/null +++ b/tizen/src/hw/maru_virtio_sensor.h @@ -0,0 +1,109 @@ +/* + * Virtio Sensor Device + * + * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: + * Jinhyung choi + * Daiyoung Kim + * YeongKyoon Lee + * + * 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 -- 2.34.1