MULTI_DEBUG_CHANNEL(qemu, hwkey);
-
#define DEVICE_NAME "virtio-hwkey"
/*
static unsigned int event_ringbuf_cnt; /* _events_buf */
static unsigned int event_queue_cnt; /* events_queue */
+/*
+ * VirtQueueElement queue
+ */
+typedef struct ElementEntry {
+ unsigned int el_index;
+ unsigned int sg_index;
+ VirtQueueElement elem;
+
+ QTAILQ_ENTRY(ElementEntry) node;
+} ElementEntry;
+
+static ElementEntry _elem_buf[10];
+static QTAILQ_HEAD(, ElementEntry) elem_queue =
+ QTAILQ_HEAD_INITIALIZER(elem_queue);
+
+static unsigned int elem_ringbuf_cnt; /* _elem_buf */
+static unsigned int elem_queue_cnt; /* elem_queue */
+
VirtIOHwKey *vhk;
/* lock for between communication thread and IO thread */
static pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
-
+static pthread_mutex_t elem_mutex = PTHREAD_MUTEX_INITIALIZER;
void maru_hwkey_event(int event_type, int keycode)
{
entry->index, entry->hwkey.keycode, entry->hwkey.event_type);
}
+static void maru_virtio_hwkey_handle(VirtIODevice *vdev, VirtQueue *vq)
+{
+ int virt_sg_index = 0;
+ ElementEntry *elem_entry = NULL;
+
+ TRACE("maru_virtio_hwkey_handle\n");
+
+ if (unlikely(virtio_queue_empty(vhk->vq))) {
+ TRACE("virtqueue is empty\n");
+ return;
+ }
+
+ while (true) {
+ elem_entry = &(_elem_buf[elem_ringbuf_cnt % 10]);
+ elem_ringbuf_cnt++;
+
+ virt_sg_index = virtqueue_pop(vhk->vq, &elem_entry->elem);
+ if (virt_sg_index == 0) {
+ elem_ringbuf_cnt--;
+ break;
+ } else if (virt_sg_index < 0) {
+ ERR("virtqueue is broken\n");
+ elem_ringbuf_cnt--;
+ return;
+ }
+
+ pthread_mutex_lock(&elem_mutex);
+
+ elem_entry->el_index = ++elem_queue_cnt;
+ elem_entry->sg_index = (unsigned int)virt_sg_index;
+
+ /* save VirtQueueElement */
+ QTAILQ_INSERT_TAIL(&elem_queue, elem_entry, node);
+ /* call maru_virtio_touchscreen_notify */
+ qemu_bh_schedule(vhk->bh);
+
+ pthread_mutex_unlock(&elem_mutex);
+ }
+}
+
void maru_virtio_hwkey_notify(void)
{
HwKeyEventEntry *event_entry = NULL;
+ ElementEntry *elem_entry = NULL;
+ VirtQueueElement *element = NULL;
+ void *vbuf = NULL;
TRACE("maru_virtio_hwkey_notify\n");
+ if (unlikely(!virtio_queue_ready(vhk->vq))) {
+ ERR("virtio queue is not ready\n");
+ return;
+ }
+
while (true) {
if (event_queue_cnt == 0) {
TRACE("no event\n");
break;
}
- /* get touch event from host queue */
- event_entry = QTAILQ_FIRST(&events_queue);
-
- TRACE("hwkey(%d) : keycode=%d, event_type=%d | \
- event_queue_cnt=%d\n",
- event_entry->index,
- event_entry->hwkey.keycode, event_entry->hwkey.event_type,
- event_queue_cnt);
-
- /* copy event into virtio buffer */
- //memcpy(vbuf, &(event_entry->touch), sizeof(event_entry->touch));
- /* TODO: */
- if (KEY_PRESSED == event_entry->hwkey.event_type) {
- ps2kbd_put_keycode(event_entry->hwkey.keycode & 0x7f);
- } else if (KEY_RELEASED == event_entry->hwkey.event_type) {
- ps2kbd_put_keycode(event_entry->hwkey.keycode | 0x80);
- } else {
- ERR("Unknown hwkey event type : keycode=%d, event_type=%d\n",
- event_entry->hwkey.keycode, event_entry->hwkey.event_type);
- }
+ elem_entry = QTAILQ_FIRST(&elem_queue);
+
+ if ( elem_entry->sg_index > 0) {
+ /* get hwkey event from host queue */
+ event_entry = QTAILQ_FIRST(&events_queue);
+
+ TRACE("hwkey(%d) : keycode=%d, event_type=%d | \
+ event_queue_cnt=%d\n",
+ event_entry->index,
+ event_entry->hwkey.keycode, event_entry->hwkey.event_type,
+ event_queue_cnt);
+
+ element = &elem_entry->elem;
+ vbuf = element->in_sg[elem_entry->sg_index - 1].iov_base;
+
+ /* copy event into virtio buffer */
+ memcpy(vbuf, &(event_entry->hwkey), sizeof(EmulHwKeyEvent));
+
+ virtqueue_push(vhk->vq, element, sizeof(EmulHwKeyEvent));
+ virtio_notify(&vhk->vdev, vhk->vq);
+ }
pthread_mutex_lock(&event_mutex);
}
vhk->vdev.get_features = virtio_hwkey_get_features;
+ vhk->vq = virtio_add_queue(&vhk->vdev, 64, maru_virtio_hwkey_handle);
+
vhk->qdev = dev;
+ /* reset the counters */
+ event_queue_cnt = event_ringbuf_cnt = 0;
+ elem_queue_cnt = elem_ringbuf_cnt = 0;
+
/* bottom-half */
vhk->bh = qemu_bh_new(maru_hwkey_bh, vhk);