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