|  | /* | 
|  | * 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 "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_FRONTEND); | 
|  | if (ret) { | 
|  | error_report("vhost-user-input: set device config space failed"); | 
|  | return; | 
|  | } | 
|  |  | 
|  | virtio_notify_config(vdev); | 
|  | } | 
|  |  | 
|  | static struct vhost_dev *vhost_input_get_vhost(VirtIODevice *vdev) | 
|  | { | 
|  | VHostUserInput *vhi = VHOST_USER_INPUT(vdev); | 
|  | return &vhi->vhost->dev; | 
|  | } | 
|  |  | 
|  | 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; | 
|  | vdc->get_vhost = vhost_input_get_vhost; | 
|  | 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) |