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/iov.h" 9 10 #include "hw/qdev.h" 11 #include "hw/virtio/virtio.h" 12 #include "hw/virtio/virtio-input.h" 13 14 #include "standard-headers/linux/input.h" 15 16 /* ----------------------------------------------------------------- */ 17 18 void virtio_input_send(VirtIOInput *vinput, virtio_input_event *event) 19 { 20 VirtQueueElement *elem; 21 unsigned have, need; 22 int i, len; 23 24 if (!vinput->active) { 25 return; 26 } 27 28 /* queue up events ... */ 29 if (vinput->qindex == vinput->qsize) { 30 vinput->qsize++; 31 vinput->queue = realloc(vinput->queue, vinput->qsize * 32 sizeof(virtio_input_event)); 33 } 34 vinput->queue[vinput->qindex++] = *event; 35 36 /* ... until we see a report sync ... */ 37 if (event->type != cpu_to_le16(EV_SYN) || 38 event->code != cpu_to_le16(SYN_REPORT)) { 39 return; 40 } 41 42 /* ... then check available space ... */ 43 need = sizeof(virtio_input_event) * vinput->qindex; 44 virtqueue_get_avail_bytes(vinput->evt, &have, NULL, need, 0); 45 if (have < need) { 46 vinput->qindex = 0; 47 fprintf(stderr, "%s: ENOSPC in vq, dropping events\n", __func__); 48 return; 49 } 50 51 /* ... and finally pass them to the guest */ 52 for (i = 0; i < vinput->qindex; i++) { 53 elem = virtqueue_pop(vinput->evt, sizeof(VirtQueueElement)); 54 if (!elem) { 55 /* should not happen, we've checked for space beforehand */ 56 fprintf(stderr, "%s: Huh? No vq elem available ...\n", __func__); 57 return; 58 } 59 len = iov_from_buf(elem->in_sg, elem->in_num, 60 0, vinput->queue+i, sizeof(virtio_input_event)); 61 virtqueue_push(vinput->evt, elem, len); 62 g_free(elem); 63 } 64 virtio_notify(VIRTIO_DEVICE(vinput), vinput->evt); 65 vinput->qindex = 0; 66 } 67 68 static void virtio_input_handle_evt(VirtIODevice *vdev, VirtQueue *vq) 69 { 70 /* nothing */ 71 } 72 73 static void virtio_input_handle_sts(VirtIODevice *vdev, VirtQueue *vq) 74 { 75 VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vdev); 76 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 77 virtio_input_event event; 78 VirtQueueElement *elem; 79 int len; 80 81 for (;;) { 82 elem = virtqueue_pop(vinput->sts, sizeof(VirtQueueElement)); 83 if (!elem) { 84 break; 85 } 86 87 memset(&event, 0, sizeof(event)); 88 len = iov_to_buf(elem->out_sg, elem->out_num, 89 0, &event, sizeof(event)); 90 if (vic->handle_status) { 91 vic->handle_status(vinput, &event); 92 } 93 virtqueue_push(vinput->sts, elem, len); 94 g_free(elem); 95 } 96 virtio_notify(vdev, vinput->sts); 97 } 98 99 static virtio_input_config *virtio_input_find_config(VirtIOInput *vinput, 100 uint8_t select, 101 uint8_t subsel) 102 { 103 VirtIOInputConfig *cfg; 104 105 QTAILQ_FOREACH(cfg, &vinput->cfg_list, node) { 106 if (select == cfg->config.select && 107 subsel == cfg->config.subsel) { 108 return &cfg->config; 109 } 110 } 111 return NULL; 112 } 113 114 void virtio_input_add_config(VirtIOInput *vinput, 115 virtio_input_config *config) 116 { 117 VirtIOInputConfig *cfg; 118 119 if (virtio_input_find_config(vinput, config->select, config->subsel)) { 120 /* should not happen */ 121 fprintf(stderr, "%s: duplicate config: %d/%d\n", 122 __func__, config->select, config->subsel); 123 abort(); 124 } 125 126 cfg = g_new0(VirtIOInputConfig, 1); 127 cfg->config = *config; 128 QTAILQ_INSERT_TAIL(&vinput->cfg_list, cfg, node); 129 } 130 131 void virtio_input_init_config(VirtIOInput *vinput, 132 virtio_input_config *config) 133 { 134 int i = 0; 135 136 QTAILQ_INIT(&vinput->cfg_list); 137 while (config[i].select) { 138 virtio_input_add_config(vinput, config + i); 139 i++; 140 } 141 } 142 143 void virtio_input_idstr_config(VirtIOInput *vinput, 144 uint8_t select, const char *string) 145 { 146 virtio_input_config id; 147 148 if (!string) { 149 return; 150 } 151 memset(&id, 0, sizeof(id)); 152 id.select = select; 153 id.size = snprintf(id.u.string, sizeof(id.u.string), "%s", string); 154 virtio_input_add_config(vinput, &id); 155 } 156 157 static void virtio_input_get_config(VirtIODevice *vdev, uint8_t *config_data) 158 { 159 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 160 virtio_input_config *config; 161 162 config = virtio_input_find_config(vinput, vinput->cfg_select, 163 vinput->cfg_subsel); 164 if (config) { 165 memcpy(config_data, config, vinput->cfg_size); 166 } else { 167 memset(config_data, 0, vinput->cfg_size); 168 } 169 } 170 171 static void virtio_input_set_config(VirtIODevice *vdev, 172 const uint8_t *config_data) 173 { 174 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 175 virtio_input_config *config = (virtio_input_config *)config_data; 176 177 vinput->cfg_select = config->select; 178 vinput->cfg_subsel = config->subsel; 179 virtio_notify_config(vdev); 180 } 181 182 static uint64_t virtio_input_get_features(VirtIODevice *vdev, uint64_t f, 183 Error **errp) 184 { 185 return f; 186 } 187 188 static void virtio_input_set_status(VirtIODevice *vdev, uint8_t val) 189 { 190 VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vdev); 191 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 192 193 if (val & VIRTIO_CONFIG_S_DRIVER_OK) { 194 if (!vinput->active) { 195 vinput->active = true; 196 if (vic->change_active) { 197 vic->change_active(vinput); 198 } 199 } 200 } 201 } 202 203 static void virtio_input_reset(VirtIODevice *vdev) 204 { 205 VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(vdev); 206 VirtIOInput *vinput = VIRTIO_INPUT(vdev); 207 208 if (vinput->active) { 209 vinput->active = false; 210 if (vic->change_active) { 211 vic->change_active(vinput); 212 } 213 } 214 } 215 216 static void virtio_input_device_realize(DeviceState *dev, Error **errp) 217 { 218 VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); 219 VirtIODevice *vdev = VIRTIO_DEVICE(dev); 220 VirtIOInput *vinput = VIRTIO_INPUT(dev); 221 VirtIOInputConfig *cfg; 222 Error *local_err = NULL; 223 224 if (vic->realize) { 225 vic->realize(dev, &local_err); 226 if (local_err) { 227 error_propagate(errp, local_err); 228 return; 229 } 230 } 231 232 virtio_input_idstr_config(vinput, VIRTIO_INPUT_CFG_ID_SERIAL, 233 vinput->serial); 234 235 QTAILQ_FOREACH(cfg, &vinput->cfg_list, node) { 236 if (vinput->cfg_size < cfg->config.size) { 237 vinput->cfg_size = cfg->config.size; 238 } 239 } 240 vinput->cfg_size += 8; 241 assert(vinput->cfg_size <= sizeof(virtio_input_config)); 242 243 virtio_init(vdev, "virtio-input", VIRTIO_ID_INPUT, 244 vinput->cfg_size); 245 vinput->evt = virtio_add_queue(vdev, 64, virtio_input_handle_evt); 246 vinput->sts = virtio_add_queue(vdev, 64, virtio_input_handle_sts); 247 } 248 249 static void virtio_input_device_unrealize(DeviceState *dev, Error **errp) 250 { 251 VirtIOInputClass *vic = VIRTIO_INPUT_GET_CLASS(dev); 252 VirtIODevice *vdev = VIRTIO_DEVICE(dev); 253 Error *local_err = NULL; 254 255 if (vic->unrealize) { 256 vic->unrealize(dev, &local_err); 257 if (local_err) { 258 error_propagate(errp, local_err); 259 return; 260 } 261 } 262 virtio_cleanup(vdev); 263 } 264 265 static Property virtio_input_properties[] = { 266 DEFINE_PROP_STRING("serial", VirtIOInput, serial), 267 DEFINE_PROP_END_OF_LIST(), 268 }; 269 270 static void virtio_input_class_init(ObjectClass *klass, void *data) 271 { 272 DeviceClass *dc = DEVICE_CLASS(klass); 273 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); 274 275 dc->props = virtio_input_properties; 276 set_bit(DEVICE_CATEGORY_INPUT, dc->categories); 277 vdc->realize = virtio_input_device_realize; 278 vdc->unrealize = virtio_input_device_unrealize; 279 vdc->get_config = virtio_input_get_config; 280 vdc->set_config = virtio_input_set_config; 281 vdc->get_features = virtio_input_get_features; 282 vdc->set_status = virtio_input_set_status; 283 vdc->reset = virtio_input_reset; 284 } 285 286 static const TypeInfo virtio_input_info = { 287 .name = TYPE_VIRTIO_INPUT, 288 .parent = TYPE_VIRTIO_DEVICE, 289 .instance_size = sizeof(VirtIOInput), 290 .class_size = sizeof(VirtIOInputClass), 291 .class_init = virtio_input_class_init, 292 .abstract = true, 293 }; 294 295 /* ----------------------------------------------------------------- */ 296 297 static void virtio_register_types(void) 298 { 299 type_register_static(&virtio_input_info); 300 } 301 302 type_init(virtio_register_types) 303