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[] = {
.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 */
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
}
#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
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)
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
#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"
}
} else {
+
// set data
memcpy(sndbuf, cmd, 10);
memcpy(sndbuf + 10, &length, 2);
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;
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 {
#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;
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__ */
--- /dev/null
+/*
+ * 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;
+ }
+}
+
#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 */
/*
#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_ */
--- /dev/null
+/*
+ * 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);
+}
+
--- /dev/null
+/*
+ * 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