* top-level directory.
*/
+#include "qemu/osdep.h"
+#include "qapi/error.h"
#include "qemu/iov.h"
+#include "trace.h"
#include "hw/qdev.h"
#include "hw/virtio/virtio.h"
#include "standard-headers/linux/input.h"
+#define VIRTIO_INPUT_VM_VERSION 1
+
/* ----------------------------------------------------------------- */
void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event)
{
- VirtQueueElement elem;
+ VirtQueueElement *elem;
unsigned have, need;
int i, len;
+ if (!vinput->active) {
+ return;
+ }
+
/* queue up events ... */
if (vinput->qindex == vinput->qsize) {
vinput->qsize++;
virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0);
if (have < need) {
vinput->qindex = 0;
- fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__);
+ trace_virtio_input_queue_full();
return;
}
/* ... and finally pass them to the guest */
for (i = 0; i < vinput->qindex; i++) {
- if (!virtqueue_pop(vinput->evt, &elem)) {
+ elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement));
+ if (!elem) {
/* should not happen, we've checked for space beforehand */
fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__);
return;
}
- len = iov_from_buf(elem.in_sg, elem.in_num,
+ len = iov_from_buf(elem->in_sg, elem->in_num,
0, vinput->queue+i, sizeof(virtio_input_event));
- virtqueue_push(vinput->evt, &elem, len);
+ virtqueue_push(vinput->evt, elem, len);
+ g_free(elem);
}
virtio_notify(VIRTIO_DEVICE(vinput), vinput->evt);
vinput->qindex = 0;
VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vdev);
VirtIOInput *vinput = VIRTIO_INPUT(vdev);
virtio_input_event event;
- VirtQueueElement elem;
+ VirtQueueElement *elem;
int len;
- while (virtqueue_pop(vinput->sts, &elem)) {
+ for (;;) {
+ elem = virtqueue_pop(vinput->sts, sizeof(VirtQueueElement));
+ if (!elem) {
+ break;
+ }
+
memset(&event, 0, sizeof(event));
- len = iov_to_buf(elem.out_sg, elem.out_num,
+ len = iov_to_buf(elem->out_sg, elem->out_num,
0, &event, sizeof(event));
if (vic->handle_status) {
vic->handle_status(vinput, &event);
}
- virtqueue_push(vinput->sts, &elem, len);
+ virtqueue_push(vinput->sts, elem, len);
+ g_free(elem);
}
virtio_notify(vdev, vinput->sts);
}
-static virtio_input_config *virtio_input_find_config(VirtIOInput *vinput,
- uint8_t select,
- uint8_t subsel)
+virtio_input_config *virtio_input_find_config(VirtIOInput *vinput,
+ uint8_t select,
+ uint8_t subsel)
{
VirtIOInputConfig *cfg;
virtio_notify_config(vdev);
}
-static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f)
+static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f,
+ Error **errp)
{
return f;
}
}
}
+static int virtio_input_load(QEMUFile *f, void *opaque, size_t size)
+{
+ VirtIOInput *vinput = opaque;
+ VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vinput);
+ VirtIODevice *vdev = VIRTIO_DEVICE(vinput);
+ int ret;
+
+ ret = virtio_load(vdev, f, VIRTIO_INPUT_VM_VERSION);
+ if (ret) {
+ return ret;
+ }
+
+ /* post_load() */
+ vinput->active = vdev->status & VIRTIO_CONFIG_S_DRIVER_OK;
+ if (vic->change_active) {
+ vic->change_active(vinput);
+ }
+ return 0;
+}
+
static void virtio_input_device_realize(DeviceState *dev, Error **errp)
{
VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev);
virtio_cleanup(vdev);
}
+VMSTATE_VIRTIO_DEVICE(input, VIRTIO_INPUT_VM_VERSION, virtio_input_load,
+ virtio_vmstate_save);
+
static Property virtio_input_properties[] = {
DEFINE_PROP_STRING("serial", VirtIOInput, serial),
DEFINE_PROP_END_OF_LIST(),
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
dc->props = virtio_input_properties;
+ dc->vmsd = &vmstate_virtio_input;
set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
vdc->realize = virtio_input_device_realize;
vdc->unrealize = virtio_input_device_unrealize;