1 /* 2 * This work is licensed under the terms of the GNU GPL, version 2 or 3 * (at your option) any later version. See the COPYING file in the 4 * top-level directory. 5 */ 6 7 #include "qemu/osdep.h" 8 #include "qemu/error-report.h" 9 #include "qapi/error.h" 10 #include "qemu-common.h" 11 12 #include "hw/virtio/virtio-input.h" 13 14 static int vhost_input_config_change(struct vhost_dev *dev) 15 { 16 error_report("vhost-user-input: unhandled backend config change"); 17 return -1; 18 } 19 20 static const VhostDevConfigOps config_ops = { 21 .vhost_dev_config_notifier = vhost_input_config_change, 22 }; 23 24 static void vhost_input_realize(DeviceState *dev, Error **errp) 25 { 26 VHostUserInput *vhi = VHOST_USER_INPUT(dev); 27 VirtIOInput *vinput = VIRTIO_INPUT(dev); 28 VirtIODevice *vdev = VIRTIO_DEVICE(dev); 29 30 vhost_dev_set_config_notifier(&vhi->vhost->dev, &config_ops); 31 vinput->cfg_size = sizeof_field(virtio_input_config, u); 32 if (vhost_user_backend_dev_init(vhi->vhost, vdev, 2, errp) == -1) { 33 return; 34 } 35 } 36 37 static void vhost_input_change_active(VirtIOInput *vinput) 38 { 39 VHostUserInput *vhi = VHOST_USER_INPUT(vinput); 40 41 if (vinput->active) { 42 vhost_user_backend_start(vhi->vhost); 43 } else { 44 vhost_user_backend_stop(vhi->vhost); 45 } 46 } 47 48 static void vhost_input_get_config(VirtIODevice *vdev, uint8_t *config_data) 49 { 50 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 51 VHostUserInput *vhi = VHOST_USER_INPUT(vdev); 52 Error *local_err = NULL; 53 int ret; 54 55 memset(config_data, 0, vinput->cfg_size); 56 57 ret = vhost_dev_get_config(&vhi->vhost->dev, config_data, vinput->cfg_size, 58 &local_err); 59 if (ret) { 60 error_report_err(local_err); 61 return; 62 } 63 } 64 65 static void vhost_input_set_config(VirtIODevice *vdev, 66 const uint8_t *config_data) 67 { 68 VHostUserInput *vhi = VHOST_USER_INPUT(vdev); 69 int ret; 70 71 ret = vhost_dev_set_config(&vhi->vhost->dev, config_data, 72 0, sizeof(virtio_input_config), 73 VHOST_SET_CONFIG_TYPE_MASTER); 74 if (ret) { 75 error_report("vhost-user-input: set device config space failed"); 76 return; 77 } 78 79 virtio_notify_config(vdev); 80 } 81 82 static const VMStateDescription vmstate_vhost_input = { 83 .name = "vhost-user-input", 84 .unmigratable = 1, 85 }; 86 87 static void vhost_input_class_init(ObjectClass *klass, void *data) 88 { 89 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass); 90 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); 91 DeviceClass *dc = DEVICE_CLASS(klass); 92 93 dc->vmsd = &vmstate_vhost_input; 94 vdc->get_config = vhost_input_get_config; 95 vdc->set_config = vhost_input_set_config; 96 vic->realize = vhost_input_realize; 97 vic->change_active = vhost_input_change_active; 98 } 99 100 static void vhost_input_init(Object *obj) 101 { 102 VHostUserInput *vhi = VHOST_USER_INPUT(obj); 103 104 vhi->vhost = VHOST_USER_BACKEND(object_new(TYPE_VHOST_USER_BACKEND)); 105 object_property_add_alias(obj, "chardev", 106 OBJECT(vhi->vhost), "chardev"); 107 } 108 109 static void vhost_input_finalize(Object *obj) 110 { 111 VHostUserInput *vhi = VHOST_USER_INPUT(obj); 112 113 object_unref(OBJECT(vhi->vhost)); 114 } 115 116 static const TypeInfo vhost_input_info = { 117 .name = TYPE_VHOST_USER_INPUT, 118 .parent = TYPE_VIRTIO_INPUT, 119 .instance_size = sizeof(VHostUserInput), 120 .instance_init = vhost_input_init, 121 .instance_finalize = vhost_input_finalize, 122 .class_init = vhost_input_class_init, 123 }; 124 125 static void vhost_input_register_types(void) 126 { 127 type_register_static(&vhost_input_info); 128 } 129 130 type_init(vhost_input_register_types) 131