/*
 * This work is licensed under the terms of the GNU GPL, version 2 or
 * (at your option) any later version.  See the COPYING file in the
 * top-level directory.
 */

#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "qemu-common.h"

#include "hw/virtio/virtio-input.h"

static int vhost_input_config_change(struct vhost_dev *dev)
{
    error_report("vhost-user-input: unhandled backend config change");
    return -1;
}

static const VhostDevConfigOps config_ops = {
    .vhost_dev_config_notifier = vhost_input_config_change,
};

static void vhost_input_realize(DeviceState *dev, Error **errp)
{
    VHostUserInput *vhi = VHOST_USER_INPUT(dev);
    VirtIOInput *vinput = VIRTIO_INPUT(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);

    vhost_dev_set_config_notifier(&vhi->vhost->dev, &config_ops);
    vinput->cfg_size = sizeof_field(virtio_input_config, u);
    if (vhost_user_backend_dev_init(vhi->vhost, vdev, 2, errp) == -1) {
        return;
    }
}

static void vhost_input_change_active(VirtIOInput *vinput)
{
    VHostUserInput *vhi = VHOST_USER_INPUT(vinput);

    if (vinput->active) {
        vhost_user_backend_start(vhi->vhost);
    } else {
        vhost_user_backend_stop(vhi->vhost);
    }
}

static void vhost_input_get_config(VirtIODevice *vdev, uint8_t *config_data)
{
    VirtIOInput *vinput = VIRTIO_INPUT(vdev);
    VHostUserInput *vhi = VHOST_USER_INPUT(vdev);
    Error *local_err = NULL;
    int ret;

    memset(config_data, 0, vinput->cfg_size);

    ret = vhost_dev_get_config(&vhi->vhost->dev, config_data, vinput->cfg_size,
                               &local_err);
    if (ret) {
        error_report_err(local_err);
        return;
    }
}

static void vhost_input_set_config(VirtIODevice *vdev,
                                   const uint8_t *config_data)
{
    VHostUserInput *vhi = VHOST_USER_INPUT(vdev);
    int ret;

    ret = vhost_dev_set_config(&vhi->vhost->dev, config_data,
                               0, sizeof(virtio_input_config),
                               VHOST_SET_CONFIG_TYPE_MASTER);
    if (ret) {
        error_report("vhost-user-input: set device config space failed");
        return;
    }

    virtio_notify_config(vdev);
}

static const VMStateDescription vmstate_vhost_input = {
    .name = "vhost-user-input",
    .unmigratable = 1,
};

static void vhost_input_class_init(ObjectClass *klass, void *data)
{
    VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    DeviceClass *dc = DEVICE_CLASS(klass);

    dc->vmsd = &vmstate_vhost_input;
    vdc->get_config = vhost_input_get_config;
    vdc->set_config = vhost_input_set_config;
    vic->realize = vhost_input_realize;
    vic->change_active = vhost_input_change_active;
}

static void vhost_input_init(Object *obj)
{
    VHostUserInput *vhi = VHOST_USER_INPUT(obj);

    vhi->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND));
    object_property_add_alias(obj, "chardev",
                              OBJECT(vhi->vhost), "chardev");
}

static void vhost_input_finalize(Object *obj)
{
    VHostUserInput *vhi = VHOST_USER_INPUT(obj);

    object_unref(OBJECT(vhi->vhost));
}

static const TypeInfo vhost_input_info = {
    .name          = TYPE_VHOST_USER_INPUT,
    .parent        = TYPE_VIRTIO_INPUT,
    .instance_size = sizeof(VHostUserInput),
    .instance_init = vhost_input_init,
    .instance_finalize = vhost_input_finalize,
    .class_init    = vhost_input_class_init,
};

static void vhost_input_register_types(void)
{
    type_register_static(&vhost_input_info);
}

type_init(vhost_input_register_types)
