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