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