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"
11 #include "hw/virtio/virtio.h"
12 #include "hw/virtio/virtio-input.h"
14 #include "standard-headers/linux/input.h"
16 /* ----------------------------------------------------------------- */
18 void virtio_input_send(VirtIOInput
*vinput
, virtio_input_event
*event
)
20 VirtQueueElement
*elem
;
24 if (!vinput
->active
) {
28 /* queue up events ... */
29 if (vinput
->qindex
== vinput
->qsize
) {
31 vinput
->queue
= realloc(vinput
->queue
, vinput
->qsize
*
32 sizeof(virtio_input_event
));
34 vinput
->queue
[vinput
->qindex
++] = *event
;
36 /* ... until we see a report sync ... */
37 if (event
->type
!= cpu_to_le16(EV_SYN
) ||
38 event
->code
!= cpu_to_le16(SYN_REPORT
)) {
42 /* ... then check available space ... */
43 need
= sizeof(virtio_input_event
) * vinput
->qindex
;
44 virtqueue_get_avail_bytes(vinput
->evt
, &have
, NULL
, need
, 0);
47 fprintf(stderr
, "%s: ENOSPC in vq, dropping events\n", __func__
);
51 /* ... and finally pass them to the guest */
52 for (i
= 0; i
< vinput
->qindex
; i
++) {
53 elem
= virtqueue_pop(vinput
->evt
, sizeof(VirtQueueElement
));
55 /* should not happen, we've checked for space beforehand */
56 fprintf(stderr
, "%s: Huh? No vq elem available ...\n", __func__
);
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
);
64 virtio_notify(VIRTIO_DEVICE(vinput
), vinput
->evt
);
68 static void virtio_input_handle_evt(VirtIODevice
*vdev
, VirtQueue
*vq
)
73 static void virtio_input_handle_sts(VirtIODevice
*vdev
, VirtQueue
*vq
)
75 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
76 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
77 virtio_input_event event
;
78 VirtQueueElement
*elem
;
82 elem
= virtqueue_pop(vinput
->sts
, sizeof(VirtQueueElement
));
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
);
93 virtqueue_push(vinput
->sts
, elem
, len
);
96 virtio_notify(vdev
, vinput
->sts
);
99 static virtio_input_config
*virtio_input_find_config(VirtIOInput
*vinput
,
103 VirtIOInputConfig
*cfg
;
105 QTAILQ_FOREACH(cfg
, &vinput
->cfg_list
, node
) {
106 if (select
== cfg
->config
.select
&&
107 subsel
== cfg
->config
.subsel
) {
114 void virtio_input_add_config(VirtIOInput
*vinput
,
115 virtio_input_config
*config
)
117 VirtIOInputConfig
*cfg
;
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
);
126 cfg
= g_new0(VirtIOInputConfig
, 1);
127 cfg
->config
= *config
;
128 QTAILQ_INSERT_TAIL(&vinput
->cfg_list
, cfg
, node
);
131 void virtio_input_init_config(VirtIOInput
*vinput
,
132 virtio_input_config
*config
)
136 QTAILQ_INIT(&vinput
->cfg_list
);
137 while (config
[i
].select
) {
138 virtio_input_add_config(vinput
, config
+ i
);
143 void virtio_input_idstr_config(VirtIOInput
*vinput
,
144 uint8_t select
, const char *string
)
146 virtio_input_config id
;
151 memset(&id
, 0, sizeof(id
));
153 id
.size
= snprintf(id
.u
.string
, sizeof(id
.u
.string
), "%s", string
);
154 virtio_input_add_config(vinput
, &id
);
157 static void virtio_input_get_config(VirtIODevice
*vdev
, uint8_t *config_data
)
159 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
160 virtio_input_config
*config
;
162 config
= virtio_input_find_config(vinput
, vinput
->cfg_select
,
165 memcpy(config_data
, config
, vinput
->cfg_size
);
167 memset(config_data
, 0, vinput
->cfg_size
);
171 static void virtio_input_set_config(VirtIODevice
*vdev
,
172 const uint8_t *config_data
)
174 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
175 virtio_input_config
*config
= (virtio_input_config
*)config_data
;
177 vinput
->cfg_select
= config
->select
;
178 vinput
->cfg_subsel
= config
->subsel
;
179 virtio_notify_config(vdev
);
182 static uint64_t virtio_input_get_features(VirtIODevice
*vdev
, uint64_t f
,
188 static void virtio_input_set_status(VirtIODevice
*vdev
, uint8_t val
)
190 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
191 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
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
);
203 static void virtio_input_reset(VirtIODevice
*vdev
)
205 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(vdev
);
206 VirtIOInput
*vinput
= VIRTIO_INPUT(vdev
);
208 if (vinput
->active
) {
209 vinput
->active
= false;
210 if (vic
->change_active
) {
211 vic
->change_active(vinput
);
216 static void virtio_input_device_realize(DeviceState
*dev
, Error
**errp
)
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
;
225 vic
->realize(dev
, &local_err
);
227 error_propagate(errp
, local_err
);
232 virtio_input_idstr_config(vinput
, VIRTIO_INPUT_CFG_ID_SERIAL
,
235 QTAILQ_FOREACH(cfg
, &vinput
->cfg_list
, node
) {
236 if (vinput
->cfg_size
< cfg
->config
.size
) {
237 vinput
->cfg_size
= cfg
->config
.size
;
240 vinput
->cfg_size
+= 8;
241 assert(vinput
->cfg_size
<= sizeof(virtio_input_config
));
243 virtio_init(vdev
, "virtio-input", VIRTIO_ID_INPUT
,
245 vinput
->evt
= virtio_add_queue(vdev
, 64, virtio_input_handle_evt
);
246 vinput
->sts
= virtio_add_queue(vdev
, 64, virtio_input_handle_sts
);
249 static void virtio_input_device_unrealize(DeviceState
*dev
, Error
**errp
)
251 VirtIOInputClass
*vic
= VIRTIO_INPUT_GET_CLASS(dev
);
252 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
253 Error
*local_err
= NULL
;
255 if (vic
->unrealize
) {
256 vic
->unrealize(dev
, &local_err
);
258 error_propagate(errp
, local_err
);
262 virtio_cleanup(vdev
);
265 static Property virtio_input_properties
[] = {
266 DEFINE_PROP_STRING("serial", VirtIOInput
, serial
),
267 DEFINE_PROP_END_OF_LIST(),
270 static void virtio_input_class_init(ObjectClass
*klass
, void *data
)
272 DeviceClass
*dc
= DEVICE_CLASS(klass
);
273 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
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
;
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
,
295 /* ----------------------------------------------------------------- */
297 static void virtio_register_types(void)
299 type_register_static(&virtio_input_info
);
302 type_init(virtio_register_types
)