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"
9 #include <linux/input.h>
12 #include "qemu/bswap.h"
13 #include "qemu/sockets.h"
14 #include "libvhost-user-glib.h"
15 #include "standard-headers/linux/virtio_input.h"
16 #include "qapi/error.h"
19 VHOST_USER_INPUT_MAX_QUEUES
= 2,
22 typedef struct virtio_input_event virtio_input_event
;
23 typedef struct virtio_input_config virtio_input_config
;
25 typedef struct VuInput
{
30 virtio_input_config
*sel_config
;
32 virtio_input_event event
;
35 uint32_t qindex
, qsize
;
38 static void vi_input_send(VuInput
*vi
, struct virtio_input_event
*event
)
40 VuDev
*dev
= &vi
->dev
.parent
;
41 VuVirtq
*vq
= vu_get_queue(dev
, 0);
45 /* queue up events ... */
46 if (vi
->qindex
== vi
->qsize
) {
48 vi
->queue
= g_realloc_n(vi
->queue
, vi
->qsize
, sizeof(vi
->queue
[0]));
50 vi
->queue
[vi
->qindex
++].event
= *event
;
52 /* ... until we see a report sync ... */
53 if (event
->type
!= htole16(EV_SYN
) ||
54 event
->code
!= htole16(SYN_REPORT
)) {
58 /* ... then check available space ... */
59 for (i
= 0; i
< vi
->qindex
; i
++) {
60 elem
= vu_queue_pop(dev
, vq
, sizeof(VuVirtqElement
));
63 vu_queue_unpop(dev
, vq
, vi
->queue
[i
].elem
, 0);
66 g_warning("virtio-input queue full");
69 vi
->queue
[i
].elem
= elem
;
72 /* ... and finally pass them to the guest */
73 for (i
= 0; i
< vi
->qindex
; i
++) {
74 elem
= vi
->queue
[i
].elem
;
75 len
= iov_from_buf(elem
->in_sg
, elem
->in_num
,
76 0, &vi
->queue
[i
].event
, sizeof(virtio_input_event
));
77 vu_queue_push(dev
, vq
, elem
, len
);
81 vu_queue_notify(&vi
->dev
.parent
, vq
);
86 vi_evdev_watch(VuDev
*dev
, int condition
, void *data
)
91 g_debug("Got evdev condition %x", condition
);
93 struct virtio_input_event virtio
;
94 struct input_event evdev
;
98 rc
= read(fd
, &evdev
, sizeof(evdev
));
99 if (rc
!= sizeof(evdev
)) {
103 g_debug("input %d %d %d", evdev
.type
, evdev
.code
, evdev
.value
);
105 virtio
.type
= htole16(evdev
.type
);
106 virtio
.code
= htole16(evdev
.code
);
107 virtio
.value
= htole32(evdev
.value
);
108 vi_input_send(vi
, &virtio
);
113 static void vi_handle_status(VuInput
*vi
, virtio_input_event
*event
)
115 struct input_event evdev
;
118 if (gettimeofday(&evdev
.time
, NULL
)) {
119 perror("vi_handle_status: gettimeofday");
123 evdev
.type
= le16toh(event
->type
);
124 evdev
.code
= le16toh(event
->code
);
125 evdev
.value
= le32toh(event
->value
);
127 rc
= write(vi
->evdevfd
, &evdev
, sizeof(evdev
));
129 perror("vi_host_handle_status: write");
133 static void vi_handle_sts(VuDev
*dev
, int qidx
)
135 VuInput
*vi
= container_of(dev
, VuInput
, dev
.parent
);
136 VuVirtq
*vq
= vu_get_queue(dev
, qidx
);
137 virtio_input_event event
;
138 VuVirtqElement
*elem
;
141 g_debug("%s", G_STRFUNC
);
144 elem
= vu_queue_pop(dev
, vq
, sizeof(VuVirtqElement
));
149 memset(&event
, 0, sizeof(event
));
150 len
= iov_to_buf(elem
->out_sg
, elem
->out_num
,
151 0, &event
, sizeof(event
));
152 vi_handle_status(vi
, &event
);
153 vu_queue_push(dev
, vq
, elem
, len
);
157 vu_queue_notify(&vi
->dev
.parent
, vq
);
161 vi_panic(VuDev
*dev
, const char *msg
)
163 g_critical("%s\n", msg
);
168 vi_queue_set_started(VuDev
*dev
, int qidx
, bool started
)
170 VuInput
*vi
= container_of(dev
, VuInput
, dev
.parent
);
171 VuVirtq
*vq
= vu_get_queue(dev
, qidx
);
173 g_debug("queue started %d:%d", qidx
, started
);
176 vu_set_queue_handler(dev
, vq
, started
? vi_handle_sts
: NULL
);
179 started
= vu_queue_started(dev
, vu_get_queue(dev
, 0)) &&
180 vu_queue_started(dev
, vu_get_queue(dev
, 1));
182 if (started
&& !vi
->evsrc
) {
183 vi
->evsrc
= vug_source_new(&vi
->dev
, vi
->evdevfd
,
184 G_IO_IN
, vi_evdev_watch
, vi
);
187 if (!started
&& vi
->evsrc
) {
188 vug_source_destroy(vi
->evsrc
);
193 static virtio_input_config
*
194 vi_find_config(VuInput
*vi
, uint8_t select
, uint8_t subsel
)
196 virtio_input_config
*cfg
;
199 for (i
= 0; i
< vi
->config
->len
; i
++) {
200 cfg
= &g_array_index(vi
->config
, virtio_input_config
, i
);
201 if (select
== cfg
->select
&& subsel
== cfg
->subsel
) {
209 static int vi_get_config(VuDev
*dev
, uint8_t *config
, uint32_t len
)
211 VuInput
*vi
= container_of(dev
, VuInput
, dev
.parent
);
213 if (len
> sizeof(*vi
->sel_config
)) {
217 if (vi
->sel_config
) {
218 memcpy(config
, vi
->sel_config
, len
);
220 memset(config
, 0, len
);
226 static int vi_set_config(VuDev
*dev
, const uint8_t *data
,
227 uint32_t offset
, uint32_t size
,
230 VuInput
*vi
= container_of(dev
, VuInput
, dev
.parent
);
231 virtio_input_config
*config
= (virtio_input_config
*)data
;
233 vi
->sel_config
= vi_find_config(vi
, config
->select
, config
->subsel
);
238 static const VuDevIface vuiface
= {
239 .queue_set_started
= vi_queue_set_started
,
240 .get_config
= vi_get_config
,
241 .set_config
= vi_set_config
,
245 vi_bits_config(VuInput
*vi
, int type
, int count
)
247 virtio_input_config bits
;
250 memset(&bits
, 0, sizeof(bits
));
251 rc
= ioctl(vi
->evdevfd
, EVIOCGBIT(type
, count
/ 8), bits
.u
.bitmap
);
256 for (i
= 0; i
< count
/ 8; i
++) {
257 if (bits
.u
.bitmap
[i
]) {
265 bits
.select
= VIRTIO_INPUT_CFG_EV_BITS
;
268 g_array_append_val(vi
->config
, bits
);
271 static char *opt_evdev
;
272 static int opt_fdnum
= -1;
273 static char *opt_socket_path
;
274 static gboolean opt_nograb
;
275 static gboolean opt_print_caps
;
277 static GOptionEntry entries
[] = {
278 { "print-capabilities", 'c', 0, G_OPTION_ARG_NONE
, &opt_print_caps
,
279 "Print capabilities", NULL
},
280 { "no-grab", 'n', 0, G_OPTION_ARG_NONE
, &opt_nograb
,
281 "Don't grab device", NULL
},
282 { "fd", 'f', 0, G_OPTION_ARG_INT
, &opt_fdnum
,
283 "Use inherited fd socket", "FDNUM" },
284 { "socket-path", 's', 0, G_OPTION_ARG_FILENAME
, &opt_socket_path
,
285 "Use UNIX socket path", "PATH" },
286 { "evdev-path", 'p', 0, G_OPTION_ARG_FILENAME
, &opt_evdev
,
287 "evdev input device path", "PATH" },
292 main(int argc
, char *argv
[])
294 GMainLoop
*loop
= NULL
;
297 virtio_input_config id
;
299 GError
*error
= NULL
;
300 GOptionContext
*context
;
302 context
= g_option_context_new(NULL
);
303 g_option_context_add_main_entries(context
, entries
, NULL
);
304 if (!g_option_context_parse(context
, &argc
, &argv
, &error
)) {
305 g_printerr("Option parsing failed: %s\n", error
->message
);
308 if (opt_print_caps
) {
310 g_print(" \"type\": \"input\",\n");
311 g_print(" \"features\": [\n");
312 g_print(" \"evdev-path\",\n");
313 g_print(" \"no-grab\"\n");
319 g_printerr("Please specify an evdev path\n");
322 if ((!!opt_socket_path
+ (opt_fdnum
!= -1)) != 1) {
323 g_printerr("Please specify either --fd or --socket-path\n");
327 vi
.evdevfd
= open(opt_evdev
, O_RDWR
);
328 if (vi
.evdevfd
< 0) {
329 g_printerr("Failed to open evdev: %s\n", g_strerror(errno
));
333 rc
= ioctl(vi
.evdevfd
, EVIOCGVERSION
, &ver
);
335 g_printerr("%s: is not an evdev device\n", argv
[1]);
340 rc
= ioctl(vi
.evdevfd
, EVIOCGRAB
, 1);
342 g_printerr("Failed to grab device\n");
347 vi
.config
= g_array_new(false, false, sizeof(virtio_input_config
));
348 memset(&id
, 0, sizeof(id
));
349 if (ioctl(vi
.evdevfd
, EVIOCGNAME(sizeof(id
.u
.string
) - 1),
351 g_printerr("Failed to get evdev name: %s\n", g_strerror(errno
));
354 id
.select
= VIRTIO_INPUT_CFG_ID_NAME
;
355 id
.size
= strlen(id
.u
.string
);
356 g_array_append_val(vi
.config
, id
);
358 if (ioctl(vi
.evdevfd
, EVIOCGID
, &ids
) == 0) {
359 memset(&id
, 0, sizeof(id
));
360 id
.select
= VIRTIO_INPUT_CFG_ID_DEVIDS
;
361 id
.size
= sizeof(struct virtio_input_devids
);
362 id
.u
.ids
.bustype
= cpu_to_le16(ids
.bustype
);
363 id
.u
.ids
.vendor
= cpu_to_le16(ids
.vendor
);
364 id
.u
.ids
.product
= cpu_to_le16(ids
.product
);
365 id
.u
.ids
.version
= cpu_to_le16(ids
.version
);
366 g_array_append_val(vi
.config
, id
);
369 vi_bits_config(&vi
, EV_KEY
, KEY_CNT
);
370 vi_bits_config(&vi
, EV_REL
, REL_CNT
);
371 vi_bits_config(&vi
, EV_ABS
, ABS_CNT
);
372 vi_bits_config(&vi
, EV_MSC
, MSC_CNT
);
373 vi_bits_config(&vi
, EV_SW
, SW_CNT
);
374 g_debug("config length: %u", vi
.config
->len
);
376 if (opt_socket_path
) {
377 int lsock
= unix_listen(opt_socket_path
, &error_fatal
);
379 g_printerr("Failed to listen on %s.\n", opt_socket_path
);
382 fd
= accept(lsock
, NULL
, NULL
);
388 g_printerr("Invalid vhost-user socket.\n");
392 if (!vug_init(&vi
.dev
, VHOST_USER_INPUT_MAX_QUEUES
, fd
, vi_panic
,
394 g_printerr("Failed to initialize libvhost-user-glib.\n");
398 loop
= g_main_loop_new(NULL
, FALSE
);
399 g_main_loop_run(loop
);
400 g_main_loop_unref(loop
);
404 vug_source_destroy(vi
.evsrc
);
405 g_array_free(vi
.config
, TRUE
);