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
7 #include "qemu/osdep.h"
8 #include "qapi/error.h"
10 #include "qemu/module.h"
13 #include "hw/virtio/virtio.h"
14 #include "hw/qdev-properties.h"
15 #include "hw/virtio/virtio-input.h"
17 #include "standard-headers/linux/input.h"
19 #define VIRTIO_INPUT_VM_VERSION 1
21 /* ----------------------------------------------------------------- */
23 void virtio_input_send(VirtIOInput
*vinput
, virtio_input_event
*event
)
25 VirtQueueElement
*elem
;
28 if (!vinput
->active
) {
32 /* queue up events ... */
33 if (vinput
->qindex
== vinput
->qsize
) {
35 vinput
->queue
= g_realloc(vinput
->queue
, vinput
->qsize
*
36 sizeof(vinput
->queue
[0]));
38 vinput
->queue
[vinput
->qindex
++].event
= *event
;
40 /* ... until we see a report sync ... */
41 if (event
->type
!= cpu_to_le16(EV_SYN
) ||
42 event
->code
!= cpu_to_le16(SYN_REPORT
)) {
46 /* ... then check available space ... */
47 for (i
= 0; i
< vinput
->qindex
; i
++) {
48 elem
= virtqueue_pop(vinput
->evt
, sizeof(VirtQueueElement
));
51 virtqueue_unpop(vinput
->evt
, vinput
->queue
[i
].elem
, 0);
54 trace_virtio_input_queue_full();
57 vinput
->queue
[i
].elem
= elem
;
60 /* ... and finally pass them to the guest */
61 for (i
= 0; i
< vinput
->qindex
; i
++) {
62 elem
= vinput
->queue
[i
].elem
;
63 len
= iov_from_buf(elem
->in_sg
, elem
->in_num
,
64 0, &vinput
->queue
[i
].event
, sizeof(virtio_input_event
));
65 virtqueue_push(vinput
->evt
, elem
, len
);
68 virtio_notify(VIRTIO_DEVICE(vinput
), vinput
->evt
);
72 static void virtio_input_handle_evt(VirtIODevice
*vdev
, VirtQueue
*vq
)
77 static void virtio_input_handle_sts(VirtIODevice
*vdev
, VirtQueue
*vq
)
79 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
80 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
81 virtio_input_event event
;
82 VirtQueueElement
*elem
;
86 elem
= virtqueue_pop(vinput
->sts
, sizeof(VirtQueueElement
));
91 memset(&event
, 0, sizeof(event
));
92 len
= iov_to_buf(elem
->out_sg
, elem
->out_num
,
93 0, &event
, sizeof(event
));
94 if (vic
->handle_status
) {
95 vic
->handle_status(vinput
, &event
);
97 virtqueue_push(vinput
->sts
, elem
, len
);
100 virtio_notify(vdev
, vinput
->sts
);
103 virtio_input_config
*virtio_input_find_config(VirtIOInput
*vinput
,
107 VirtIOInputConfig
*cfg
;
109 QTAILQ_FOREACH(cfg
, &vinput
->cfg_list
, node
) {
110 if (select
== cfg
->config
.select
&&
111 subsel
== cfg
->config
.subsel
) {
118 void virtio_input_add_config(VirtIOInput
*vinput
,
119 virtio_input_config
*config
)
121 VirtIOInputConfig
*cfg
;
123 if (virtio_input_find_config(vinput
, config
->select
, config
->subsel
)) {
124 /* should not happen */
125 fprintf(stderr
, "%s: duplicate config: %d/%d\n",
126 __func__
, config
->select
, config
->subsel
);
130 cfg
= g_new0(VirtIOInputConfig
, 1);
131 cfg
->config
= *config
;
132 QTAILQ_INSERT_TAIL(&vinput
->cfg_list
, cfg
, node
);
135 void virtio_input_init_config(VirtIOInput
*vinput
,
136 virtio_input_config
*config
)
140 QTAILQ_INIT(&vinput
->cfg_list
);
141 while (config
[i
].select
) {
142 virtio_input_add_config(vinput
, config
+ i
);
147 void virtio_input_idstr_config(VirtIOInput
*vinput
,
148 uint8_t select
, const char *string
)
150 virtio_input_config id
;
155 memset(&id
, 0, sizeof(id
));
157 id
.size
= snprintf(id
.u
.string
, sizeof(id
.u
.string
), "%s", string
);
158 virtio_input_add_config(vinput
, &id
);
161 static void virtio_input_get_config(VirtIODevice
*vdev
, uint8_t *config_data
)
163 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
164 virtio_input_config
*config
;
166 config
= virtio_input_find_config(vinput
, vinput
->cfg_select
,
169 memcpy(config_data
, config
, vinput
->cfg_size
);
171 memset(config_data
, 0, vinput
->cfg_size
);
175 static void virtio_input_set_config(VirtIODevice
*vdev
,
176 const uint8_t *config_data
)
178 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
179 virtio_input_config
*config
= (virtio_input_config
*)config_data
;
181 vinput
->cfg_select
= config
->select
;
182 vinput
->cfg_subsel
= config
->subsel
;
183 virtio_notify_config(vdev
);
186 static uint64_t virtio_input_get_features(VirtIODevice
*vdev
, uint64_t f
,
192 static void virtio_input_set_status(VirtIODevice
*vdev
, uint8_t val
)
194 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
195 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
197 if (val
& VIRTIO_CONFIG_S_DRIVER_OK
) {
198 if (!vinput
->active
) {
199 vinput
->active
= true;
200 if (vic
->change_active
) {
201 vic
->change_active(vinput
);
207 static void virtio_input_reset(VirtIODevice
*vdev
)
209 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
210 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
212 if (vinput
->active
) {
213 vinput
->active
= false;
214 if (vic
->change_active
) {
215 vic
->change_active(vinput
);
220 static int virtio_input_post_load(void *opaque
, int version_id
)
222 VirtIOInput
*vinput
= opaque
;
223 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vinput
);
224 VirtIODevice
*vdev
= VIRTIO_DEVICE(vinput
);
226 vinput
->active
= vdev
->status
& VIRTIO_CONFIG_S_DRIVER_OK
;
227 if (vic
->change_active
) {
228 vic
->change_active(vinput
);
233 static void virtio_input_device_realize(DeviceState
*dev
, Error
**errp
)
235 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(dev
);
236 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
237 VirtIOInput
*vinput
= VIRTIO_INPUT(dev
);
238 VirtIOInputConfig
*cfg
;
239 Error
*local_err
= NULL
;
242 vic
->realize(dev
, &local_err
);
244 error_propagate(errp
, local_err
);
249 virtio_input_idstr_config(vinput
, VIRTIO_INPUT_CFG_ID_SERIAL
,
252 QTAILQ_FOREACH(cfg
, &vinput
->cfg_list
, node
) {
253 if (vinput
->cfg_size
< cfg
->config
.size
) {
254 vinput
->cfg_size
= cfg
->config
.size
;
257 vinput
->cfg_size
+= 8;
258 assert(vinput
->cfg_size
<= sizeof(virtio_input_config
));
260 virtio_init(vdev
, VIRTIO_ID_INPUT
, vinput
->cfg_size
);
261 vinput
->evt
= virtio_add_queue(vdev
, 64, virtio_input_handle_evt
);
262 vinput
->sts
= virtio_add_queue(vdev
, 64, virtio_input_handle_sts
);
265 static void virtio_input_finalize(Object
*obj
)
267 VirtIOInput
*vinput
= VIRTIO_INPUT(obj
);
268 VirtIOInputConfig
*cfg
, *next
;
270 QTAILQ_FOREACH_SAFE(cfg
, &vinput
->cfg_list
, node
, next
) {
271 QTAILQ_REMOVE(&vinput
->cfg_list
, cfg
, node
);
275 g_free(vinput
->queue
);
278 static void virtio_input_device_unrealize(DeviceState
*dev
)
280 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(dev
);
281 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
282 VirtIOInput
*vinput
= VIRTIO_INPUT(dev
);
284 if (vic
->unrealize
) {
287 virtio_delete_queue(vinput
->evt
);
288 virtio_delete_queue(vinput
->sts
);
289 virtio_cleanup(vdev
);
292 static const VMStateDescription vmstate_virtio_input
= {
293 .name
= "virtio-input",
294 .minimum_version_id
= VIRTIO_INPUT_VM_VERSION
,
295 .version_id
= VIRTIO_INPUT_VM_VERSION
,
296 .fields
= (VMStateField
[]) {
297 VMSTATE_VIRTIO_DEVICE
,
298 VMSTATE_END_OF_LIST()
300 .post_load
= virtio_input_post_load
,
303 static Property virtio_input_properties
[] = {
304 DEFINE_PROP_STRING("serial", VirtIOInput
, serial
),
305 DEFINE_PROP_END_OF_LIST(),
308 static void virtio_input_class_init(ObjectClass
*klass
, void *data
)
310 DeviceClass
*dc
= DEVICE_CLASS(klass
);
311 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
313 device_class_set_props(dc
, virtio_input_properties
);
314 dc
->vmsd
= &vmstate_virtio_input
;
315 set_bit(DEVICE_CATEGORY_INPUT
, dc
->categories
);
316 vdc
->realize
= virtio_input_device_realize
;
317 vdc
->unrealize
= virtio_input_device_unrealize
;
318 vdc
->get_config
= virtio_input_get_config
;
319 vdc
->set_config
= virtio_input_set_config
;
320 vdc
->get_features
= virtio_input_get_features
;
321 vdc
->set_status
= virtio_input_set_status
;
322 vdc
->reset
= virtio_input_reset
;
325 static const TypeInfo virtio_input_info
= {
326 .name
= TYPE_VIRTIO_INPUT
,
327 .parent
= TYPE_VIRTIO_DEVICE
,
328 .instance_size
= sizeof(VirtIOInput
),
329 .class_size
= sizeof(VirtIOInputClass
),
330 .class_init
= virtio_input_class_init
,
332 .instance_finalize
= virtio_input_finalize
,
335 /* ----------------------------------------------------------------- */
337 static void virtio_register_types(void)
339 type_register_static(&virtio_input_info
);
342 type_init(virtio_register_types
)