2 * SPDX-License-Identifier: BSD-2-Clause
4 * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer
12 * in this position and unchanged.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * virtio input device emulation.
34 #include <sys/cdefs.h>
35 #include <sys/param.h>
36 #ifndef WITHOUT_CAPSICUM
37 #include <sys/capsicum.h>
39 #include <capsicum_helpers.h>
41 #include <sys/ioctl.h>
42 #include <sys/linker_set.h>
45 #include <dev/evdev/input.h>
66 #define VTINPUT_RINGSZ 64
68 #define VTINPUT_MAX_PKT_LEN 10
73 #define VTINPUT_EVENTQ 0
74 #define VTINPUT_STATUSQ 1
76 #define VTINPUT_MAXQ 2
78 static int pci_vtinput_debug;
79 #define DPRINTF(params) \
80 if (pci_vtinput_debug) \
82 #define WPRINTF(params) PRINTLN params
84 enum vtinput_config_select {
85 VTINPUT_CFG_UNSET = 0x00,
86 VTINPUT_CFG_ID_NAME = 0x01,
87 VTINPUT_CFG_ID_SERIAL = 0x02,
88 VTINPUT_CFG_ID_DEVIDS = 0x03,
89 VTINPUT_CFG_PROP_BITS = 0x10,
90 VTINPUT_CFG_EV_BITS = 0x11,
91 VTINPUT_CFG_ABS_INFO = 0x12
94 struct vtinput_absinfo {
102 struct vtinput_devids {
109 struct vtinput_config {
117 struct vtinput_absinfo abs;
118 struct vtinput_devids ids;
122 struct vtinput_event {
128 struct vtinput_event_elem {
129 struct vtinput_event event;
134 struct vtinput_eventqueue {
135 struct vtinput_event_elem *events;
143 struct pci_vtinput_softc {
144 struct virtio_softc vsc_vs;
145 struct vqueue_info vsc_queues[VTINPUT_MAXQ];
146 pthread_mutex_t vsc_mtx;
147 const char *vsc_evdev;
149 struct vtinput_config vsc_config;
150 int vsc_config_valid;
151 struct mevent *vsc_evp;
152 struct vtinput_eventqueue vsc_eventqueue;
155 static void pci_vtinput_reset(void *);
156 static int pci_vtinput_cfgread(void *, int, int, uint32_t *);
157 static int pci_vtinput_cfgwrite(void *, int, int, uint32_t);
159 static struct virtio_consts vtinput_vi_consts = {
160 .vc_name = "vtinput",
161 .vc_nvq = VTINPUT_MAXQ,
162 .vc_cfgsize = sizeof(struct vtinput_config),
163 .vc_reset = pci_vtinput_reset,
164 .vc_cfgread = pci_vtinput_cfgread,
165 .vc_cfgwrite = pci_vtinput_cfgwrite,
170 pci_vtinput_reset(void *vsc)
172 struct pci_vtinput_softc *sc = vsc;
174 DPRINTF(("%s: device reset requested", __func__));
175 vi_reset_dev(&sc->vsc_vs);
179 pci_vtinput_notify_eventq(void *vsc __unused, struct vqueue_info *vq __unused)
181 DPRINTF(("%s", __func__));
185 pci_vtinput_notify_statusq(void *vsc, struct vqueue_info *vq)
187 struct pci_vtinput_softc *sc = vsc;
189 while (vq_has_descs(vq)) {
190 /* get descriptor chain */
193 const int n = vq_getchain(vq, &iov, 1, &req);
195 WPRINTF(("%s: invalid descriptor: %d", __func__, n));
200 struct vtinput_event event;
201 memcpy(&event, iov.iov_base, sizeof(event));
204 * on multi touch devices:
205 * - host send EV_MSC to guest
206 * - guest sends EV_MSC back to host
207 * - host writes EV_MSC to evdev
208 * - evdev saves EV_MSC in it's event buffer
209 * - host receives an extra EV_MSC by reading the evdev event
211 * - frames become larger and larger
212 * avoid endless loops by ignoring EV_MSC
214 if (event.type == EV_MSC) {
215 vq_relchain(vq, req.idx, sizeof(event));
219 /* send event to evdev */
220 struct input_event host_event;
221 host_event.type = event.type;
222 host_event.code = event.code;
223 host_event.value = event.value;
224 if (gettimeofday(&host_event.time, NULL) != 0) {
225 WPRINTF(("%s: failed gettimeofday", __func__));
227 if (write(sc->vsc_fd, &host_event, sizeof(host_event)) == -1) {
228 WPRINTF(("%s: failed to write host_event", __func__));
231 vq_relchain(vq, req.idx, sizeof(event));
237 pci_vtinput_get_bitmap(struct pci_vtinput_softc *sc, int cmd, int count)
239 if (count <= 0 || !sc) {
244 memset(sc->vsc_config.u.bitmap, 0, sizeof(sc->vsc_config.u.bitmap));
245 if (ioctl(sc->vsc_fd, cmd, sc->vsc_config.u.bitmap) < 0) {
249 /* get number of set bytes in bitmap */
250 for (int i = count - 1; i >= 0; i--) {
251 if (sc->vsc_config.u.bitmap[i]) {
260 pci_vtinput_read_config_id_name(struct pci_vtinput_softc *sc)
263 if (ioctl(sc->vsc_fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
267 memcpy(sc->vsc_config.u.string, name, sizeof(name));
268 sc->vsc_config.size = strnlen(name, sizeof(name));
274 pci_vtinput_read_config_id_serial(struct pci_vtinput_softc *sc)
276 /* serial isn't supported */
277 sc->vsc_config.size = 0;
283 pci_vtinput_read_config_id_devids(struct pci_vtinput_softc *sc)
285 struct input_id devids;
286 if (ioctl(sc->vsc_fd, EVIOCGID, &devids)) {
290 sc->vsc_config.u.ids.bustype = devids.bustype;
291 sc->vsc_config.u.ids.vendor = devids.vendor;
292 sc->vsc_config.u.ids.product = devids.product;
293 sc->vsc_config.u.ids.version = devids.version;
294 sc->vsc_config.size = sizeof(struct vtinput_devids);
300 pci_vtinput_read_config_prop_bits(struct pci_vtinput_softc *sc)
303 * Evdev bitmap countains 1 bit per count. Additionally evdev bitmaps
304 * are arrays of longs instead of chars. Calculate how many longs are
305 * required for evdev bitmap. Multiply that with sizeof(long) to get the
306 * number of elements.
308 const int count = howmany(INPUT_PROP_CNT, sizeof(long) * 8) *
310 const unsigned int cmd = EVIOCGPROP(count);
311 const int size = pci_vtinput_get_bitmap(sc, cmd, count);
316 sc->vsc_config.size = size;
322 pci_vtinput_read_config_ev_bits(struct pci_vtinput_softc *sc, uint8_t type)
350 * Evdev bitmap countains 1 bit per count. Additionally evdev bitmaps
351 * are arrays of longs instead of chars. Calculate how many longs are
352 * required for evdev bitmap. Multiply that with sizeof(long) to get the
353 * number of elements.
355 count = howmany(count, sizeof(long) * 8) * sizeof(long);
356 const unsigned int cmd = EVIOCGBIT(sc->vsc_config.subsel, count);
357 const int size = pci_vtinput_get_bitmap(sc, cmd, count);
362 sc->vsc_config.size = size;
368 pci_vtinput_read_config_abs_info(struct pci_vtinput_softc *sc)
370 /* check if evdev has EV_ABS */
371 if (!pci_vtinput_read_config_ev_bits(sc, EV_ABS)) {
375 /* get abs information */
376 struct input_absinfo abs;
377 if (ioctl(sc->vsc_fd, EVIOCGABS(sc->vsc_config.subsel), &abs) < 0) {
381 /* save abs information */
382 sc->vsc_config.u.abs.min = abs.minimum;
383 sc->vsc_config.u.abs.max = abs.maximum;
384 sc->vsc_config.u.abs.fuzz = abs.fuzz;
385 sc->vsc_config.u.abs.flat = abs.flat;
386 sc->vsc_config.u.abs.res = abs.resolution;
387 sc->vsc_config.size = sizeof(struct vtinput_absinfo);
393 pci_vtinput_read_config(struct pci_vtinput_softc *sc)
395 switch (sc->vsc_config.select) {
396 case VTINPUT_CFG_UNSET:
398 case VTINPUT_CFG_ID_NAME:
399 return pci_vtinput_read_config_id_name(sc);
400 case VTINPUT_CFG_ID_SERIAL:
401 return pci_vtinput_read_config_id_serial(sc);
402 case VTINPUT_CFG_ID_DEVIDS:
403 return pci_vtinput_read_config_id_devids(sc);
404 case VTINPUT_CFG_PROP_BITS:
405 return pci_vtinput_read_config_prop_bits(sc);
406 case VTINPUT_CFG_EV_BITS:
407 return pci_vtinput_read_config_ev_bits(
408 sc, sc->vsc_config.subsel);
409 case VTINPUT_CFG_ABS_INFO:
410 return pci_vtinput_read_config_abs_info(sc);
417 pci_vtinput_cfgread(void *vsc, int offset, int size, uint32_t *retval)
419 struct pci_vtinput_softc *sc = vsc;
421 /* check for valid offset and size */
422 if (offset + size > (int)sizeof(struct vtinput_config)) {
423 WPRINTF(("%s: read to invalid offset/size %d/%d", __func__,
425 memset(retval, 0, size);
429 /* read new config values, if select and subsel changed. */
430 if (!sc->vsc_config_valid) {
431 if (pci_vtinput_read_config(sc) != 0) {
432 DPRINTF(("%s: could not read config %d/%d", __func__,
433 sc->vsc_config.select, sc->vsc_config.subsel));
434 memset(retval, 0, size);
437 sc->vsc_config_valid = 1;
440 uint8_t *ptr = (uint8_t *)&sc->vsc_config;
441 memcpy(retval, ptr + offset, size);
447 pci_vtinput_cfgwrite(void *vsc, int offset, int size, uint32_t value)
449 struct pci_vtinput_softc *sc = vsc;
451 /* guest can only write to select and subsel fields */
452 if (offset + size > 2) {
453 WPRINTF(("%s: write to readonly reg %d", __func__, offset));
457 /* copy value into config */
458 uint8_t *ptr = (uint8_t *)&sc->vsc_config;
459 memcpy(ptr + offset, &value, size);
461 /* select/subsel changed, query new config on next cfgread */
462 sc->vsc_config_valid = 0;
468 vtinput_eventqueue_add_event(
469 struct vtinput_eventqueue *queue, struct input_event *e)
471 /* check if queue is full */
472 if (queue->idx >= queue->size) {
473 /* alloc new elements for queue */
474 const uint32_t newSize = queue->idx;
475 void *newPtr = realloc(queue->events,
476 queue->size * sizeof(struct vtinput_event_elem));
477 if (newPtr == NULL) {
478 WPRINTF(("%s: realloc memory for eventqueue failed!",
482 queue->events = newPtr;
483 queue->size = newSize;
487 struct vtinput_event *event = &queue->events[queue->idx].event;
488 event->type = e->type;
489 event->code = e->code;
490 event->value = e->value;
497 vtinput_eventqueue_clear(struct vtinput_eventqueue *queue)
499 /* just reset index to clear queue */
504 vtinput_eventqueue_send_events(
505 struct vtinput_eventqueue *queue, struct vqueue_info *vq)
508 * First iteration through eventqueue:
509 * Get descriptor chains.
511 for (uint32_t i = 0; i < queue->idx; ++i) {
513 if (!vq_has_descs(vq)) {
515 * We don't have enough descriptors for all events.
516 * Return chains back to guest.
520 "%s: not enough available descriptors, dropping %d events",
521 __func__, queue->idx));
525 /* get descriptor chain */
528 const int n = vq_getchain(vq, &iov, 1, &req);
530 WPRINTF(("%s: invalid descriptor: %d", __func__, n));
535 ("%s: invalid number of descriptors in chain: %d",
537 /* release invalid chain */
538 vq_relchain(vq, req.idx, 0);
541 if (iov.iov_len < sizeof(struct vtinput_event)) {
542 WPRINTF(("%s: invalid descriptor length: %lu", __func__,
544 /* release invalid chain */
545 vq_relchain(vq, req.idx, 0);
549 /* save descriptor */
550 queue->events[i].iov = iov;
551 queue->events[i].idx = req.idx;
555 * Second iteration through eventqueue:
556 * Send events to guest by releasing chains
558 for (uint32_t i = 0; i < queue->idx; ++i) {
559 struct vtinput_event_elem event = queue->events[i];
560 memcpy(event.iov.iov_base, &event.event,
561 sizeof(struct vtinput_event));
562 vq_relchain(vq, event.idx, sizeof(struct vtinput_event));
565 /* clear queue and send interrupt to guest */
566 vtinput_eventqueue_clear(queue);
571 vtinput_read_event_from_host(int fd, struct input_event *event)
573 const int len = read(fd, event, sizeof(struct input_event));
574 if (len != sizeof(struct input_event)) {
575 if (len == -1 && errno != EAGAIN) {
576 WPRINTF(("%s: event read failed! len = %d, errno = %d",
577 __func__, len, errno));
580 /* host doesn't have more events for us */
588 vtinput_read_event(int fd __attribute((unused)),
589 enum ev_type t __attribute__((unused)), void *arg __attribute__((unused)))
591 struct pci_vtinput_softc *sc = arg;
593 /* skip if driver isn't ready */
594 if (!(sc->vsc_vs.vs_status & VIRTIO_CONFIG_STATUS_DRIVER_OK))
597 /* read all events from host */
598 struct input_event event;
599 while (vtinput_read_event_from_host(sc->vsc_fd, &event) == 0) {
600 /* add events to our queue */
601 vtinput_eventqueue_add_event(&sc->vsc_eventqueue, &event);
603 /* only send events to guest on EV_SYN or SYN_REPORT */
604 if (event.type != EV_SYN || event.type != SYN_REPORT) {
608 /* send host events to guest */
609 vtinput_eventqueue_send_events(
610 &sc->vsc_eventqueue, &sc->vsc_queues[VTINPUT_EVENTQ]);
615 pci_vtinput_legacy_config(nvlist_t *nvl, const char *opts)
622 * virtio-input,/dev/input/eventX
624 char *cp = strchr(opts, ',');
626 set_config_value_node(nvl, "path", opts);
629 char *path = strndup(opts, cp - opts);
630 set_config_value_node(nvl, "path", path);
633 return (pci_parse_legacy_config(nvl, cp + 1));
637 pci_vtinput_init(struct pci_devinst *pi, nvlist_t *nvl)
639 struct pci_vtinput_softc *sc;
643 * Else it's possible to access it uninitialized by jumping to failed.
645 pthread_mutexattr_t mtx_attr = NULL;
647 sc = calloc(1, sizeof(struct pci_vtinput_softc));
649 sc->vsc_evdev = get_config_value_node(nvl, "path");
650 if (sc->vsc_evdev == NULL) {
651 WPRINTF(("%s: missing required path config value", __func__));
656 * open evdev by using non blocking I/O:
657 * read from /dev/input/eventX would block our thread otherwise
659 sc->vsc_fd = open(sc->vsc_evdev, O_RDWR | O_NONBLOCK);
660 if (sc->vsc_fd < 0) {
661 WPRINTF(("%s: failed to open %s", __func__, sc->vsc_evdev));
665 /* check if evdev is really a evdev */
667 int error = ioctl(sc->vsc_fd, EVIOCGVERSION, &evversion);
669 WPRINTF(("%s: %s is no evdev", __func__, sc->vsc_evdev));
673 /* gain exclusive access to evdev */
674 error = ioctl(sc->vsc_fd, EVIOCGRAB, 1);
676 WPRINTF(("%s: failed to grab %s", __func__, sc->vsc_evdev));
680 if (pthread_mutexattr_init(&mtx_attr)) {
681 WPRINTF(("%s: init mutexattr failed", __func__));
684 if (pthread_mutexattr_settype(&mtx_attr, PTHREAD_MUTEX_RECURSIVE)) {
685 WPRINTF(("%s: settype mutexattr failed", __func__));
688 if (pthread_mutex_init(&sc->vsc_mtx, &mtx_attr)) {
689 WPRINTF(("%s: init mutex failed", __func__));
694 sc->vsc_eventqueue.idx = 0;
695 sc->vsc_eventqueue.size = VTINPUT_MAX_PKT_LEN;
696 sc->vsc_eventqueue.events = calloc(
697 sc->vsc_eventqueue.size, sizeof(struct vtinput_event_elem));
698 sc->vsc_config_valid = 0;
699 if (sc->vsc_eventqueue.events == NULL) {
700 WPRINTF(("%s: failed to alloc eventqueue", __func__));
704 /* register event handler */
705 sc->vsc_evp = mevent_add(sc->vsc_fd, EVF_READ, vtinput_read_event, sc);
706 if (sc->vsc_evp == NULL) {
707 WPRINTF(("%s: could not register mevent", __func__));
711 #ifndef WITHOUT_CAPSICUM
713 cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ, CAP_WRITE);
714 if (caph_rights_limit(sc->vsc_fd, &rights) == -1) {
715 errx(EX_OSERR, "Unable to apply rights for sandbox");
719 /* link virtio to softc */
721 &sc->vsc_vs, &vtinput_vi_consts, sc, pi, sc->vsc_queues);
722 sc->vsc_vs.vs_mtx = &sc->vsc_mtx;
724 /* init virtio queues */
725 sc->vsc_queues[VTINPUT_EVENTQ].vq_qsize = VTINPUT_RINGSZ;
726 sc->vsc_queues[VTINPUT_EVENTQ].vq_notify = pci_vtinput_notify_eventq;
727 sc->vsc_queues[VTINPUT_STATUSQ].vq_qsize = VTINPUT_RINGSZ;
728 sc->vsc_queues[VTINPUT_STATUSQ].vq_notify = pci_vtinput_notify_statusq;
730 /* initialize config space */
731 pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_INPUT);
732 pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR);
733 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_INPUTDEV);
734 pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_INPUTDEV_OTHER);
735 pci_set_cfgdata8(pi, PCIR_REVID, VIRTIO_REV_INPUT);
736 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_SUBDEV_INPUT);
737 pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_SUBVEN_INPUT);
739 /* add MSI-X table BAR */
740 if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix()))
742 /* add virtio register */
743 vi_set_io_bar(&sc->vsc_vs, 0);
753 mevent_delete(sc->vsc_evp);
754 if (sc->vsc_eventqueue.events)
755 free(sc->vsc_eventqueue.events);
757 pthread_mutex_destroy(&sc->vsc_mtx);
759 pthread_mutexattr_destroy(&mtx_attr);
768 static const struct pci_devemu pci_de_vinput = {
769 .pe_emu = "virtio-input",
770 .pe_init = pci_vtinput_init,
771 .pe_legacy_config = pci_vtinput_legacy_config,
772 .pe_barwrite = vi_pci_write,
773 .pe_barread = vi_pci_read,
775 PCI_EMUL_SET(pci_de_vinput);