xref: /illumos-gate/usr/src/cmd/bhyve/common/pci_virtio_input.c (revision 24ff48fa79a7892de49ea38209d767d49423382a)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2021 Beckhoff Automation GmbH & Co. KG
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
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.
16  *
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
27  * SUCH DAMAGE.
28  */
29 /*
30  * This file and its contents are supplied under the terms of the
31  * Common Development and Distribution License ("CDDL"), version 1.0.
32  * You may only use this file in accordance with the terms of version
33  * 1.0 of the CDDL.
34  *
35  * A full copy of the text of the CDDL should have accompanied this
36  * source.  A copy of the CDDL is also available via the Internet at
37  * http://www.illumos.org/license/CDDL.
38  */
39 /* This file is dual-licensed; see usr/src/contrib/bhyve/LICENSE */
40 
41 /*
42  * Copyright 2026 Oxide Computer Company
43  */
44 
45 /*
46  * virtio input device emulation.
47  */
48 
49 
50 #include <sys/param.h>
51 #ifndef WITHOUT_CAPSICUM
52 #include <sys/capsicum.h>
53 
54 #include <capsicum_helpers.h>
55 #endif
56 #include <sys/ioctl.h>
57 #include <sys/linker_set.h>
58 #include <sys/uio.h>
59 
60 #include <dev/evdev/input.h>
61 
62 #include <assert.h>
63 #include <err.h>
64 #include <errno.h>
65 #include <fcntl.h>
66 #include <pthread.h>
67 #include <stddef.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <sysexits.h>
72 #include <unistd.h>
73 
74 #include "bhyverun.h"
75 #include "config.h"
76 #include "debug.h"
77 #include "mevent.h"
78 #include "pci_emul.h"
79 #include "virtio.h"
80 
81 #define VTINPUT_RINGSZ 64
82 
83 #define VTINPUT_MAX_PKT_LEN 10
84 
85 /*
86  * Queue definitions.
87  */
88 #define VTINPUT_EVENTQ 0
89 #define VTINPUT_STATUSQ 1
90 
91 #define VTINPUT_MAXQ 2
92 
93 static int pci_vtinput_debug;
94 #define DPRINTF(params)        \
95 	if (pci_vtinput_debug) \
96 	PRINTLN params
97 #define WPRINTF(params) PRINTLN params
98 
99 enum vtinput_config_select {
100 	VTINPUT_CFG_UNSET = 0x00,
101 	VTINPUT_CFG_ID_NAME = 0x01,
102 	VTINPUT_CFG_ID_SERIAL = 0x02,
103 	VTINPUT_CFG_ID_DEVIDS = 0x03,
104 	VTINPUT_CFG_PROP_BITS = 0x10,
105 	VTINPUT_CFG_EV_BITS = 0x11,
106 	VTINPUT_CFG_ABS_INFO = 0x12
107 };
108 
109 struct vtinput_absinfo {
110 	uint32_t min;
111 	uint32_t max;
112 	uint32_t fuzz;
113 	uint32_t flat;
114 	uint32_t res;
115 } __packed;
116 
117 struct vtinput_devids {
118 	uint16_t bustype;
119 	uint16_t vendor;
120 	uint16_t product;
121 	uint16_t version;
122 } __packed;
123 
124 struct vtinput_config {
125 	uint8_t select;
126 	uint8_t subsel;
127 	uint8_t size;
128 	uint8_t reserved[5];
129 	union {
130 		char string[128];
131 		uint8_t bitmap[128];
132 		struct vtinput_absinfo abs;
133 		struct vtinput_devids ids;
134 	} u;
135 } __packed;
136 
137 struct vtinput_event {
138 	uint16_t type;
139 	uint16_t code;
140 	uint32_t value;
141 } __packed;
142 
143 struct vtinput_event_elem {
144 	struct vtinput_event event;
145 	struct iovec iov;
146 	uint16_t idx;
147 };
148 
149 struct vtinput_eventqueue {
150 	struct vtinput_event_elem *events;
151 	uint32_t size;
152 	uint32_t idx;
153 };
154 
155 /*
156  * Per-device softc
157  */
158 struct pci_vtinput_softc {
159 	struct virtio_softc vsc_vs;
160 	struct vqueue_info vsc_queues[VTINPUT_MAXQ];
161 	pthread_mutex_t vsc_mtx;
162 	const char *vsc_evdev;
163 	int vsc_fd;
164 	struct vtinput_config vsc_config;
165 	int vsc_config_valid;
166 	struct mevent *vsc_evp;
167 	struct vtinput_eventqueue vsc_eventqueue;
168 };
169 
170 static void pci_vtinput_reset(void *);
171 static int pci_vtinput_cfgread(void *, int, int, uint32_t *);
172 static int pci_vtinput_cfgwrite(void *, int, int, uint32_t);
173 
174 static struct virtio_consts vtinput_vi_consts = {
175 	.vc_name =		"vtinput",
176 	.vc_nvq =		VTINPUT_MAXQ,
177 	.vc_cfgsize =		sizeof(struct vtinput_config),
178 	.vc_reset =		pci_vtinput_reset,
179 	.vc_cfgread =		pci_vtinput_cfgread,
180 	.vc_cfgwrite =		pci_vtinput_cfgwrite,
181 	.vc_hv_caps_legacy =	0,
182 	.vc_hv_caps_modern =	0,
183 };
184 
185 static void
pci_vtinput_reset(void * vsc)186 pci_vtinput_reset(void *vsc)
187 {
188 	struct pci_vtinput_softc *sc = vsc;
189 
190 	DPRINTF(("%s: device reset requested", __func__));
191 	vi_reset_dev(&sc->vsc_vs);
192 }
193 
194 static void
pci_vtinput_notify_eventq(void * vsc __unused,struct vqueue_info * vq __unused)195 pci_vtinput_notify_eventq(void *vsc __unused, struct vqueue_info *vq __unused)
196 {
197 	DPRINTF(("%s", __func__));
198 }
199 
200 static void
pci_vtinput_notify_statusq(void * vsc,struct vqueue_info * vq)201 pci_vtinput_notify_statusq(void *vsc, struct vqueue_info *vq)
202 {
203 	struct pci_vtinput_softc *sc = vsc;
204 
205 	while (vq_has_descs(vq)) {
206 		/* get descriptor chain */
207 		struct iovec iov;
208 		struct vi_req req;
209 		const int n = vq_getchain(vq, &iov, 1, &req);
210 		if (n <= 0) {
211 			WPRINTF(("%s: invalid descriptor: %d", __func__, n));
212 			return;
213 		}
214 
215 		/* get event */
216 		struct vtinput_event event;
217 		memcpy(&event, iov.iov_base, sizeof(event));
218 
219 		/*
220 		 * on multi touch devices:
221 		 * - host send EV_MSC to guest
222 		 * - guest sends EV_MSC back to host
223 		 * - host writes EV_MSC to evdev
224 		 * - evdev saves EV_MSC in it's event buffer
225 		 * - host receives an extra EV_MSC by reading the evdev event
226 		 *   buffer
227 		 * - frames become larger and larger
228 		 * avoid endless loops by ignoring EV_MSC
229 		 */
230 		if (event.type == EV_MSC) {
231 			vq_relchain(vq, req.idx, sizeof(event));
232 			continue;
233 		}
234 
235 		/* send event to evdev */
236 		struct input_event host_event;
237 		host_event.type = event.type;
238 		host_event.code = event.code;
239 		host_event.value = event.value;
240 		if (gettimeofday(&host_event.time, NULL) != 0) {
241 			WPRINTF(("%s: failed gettimeofday", __func__));
242 		}
243 		if (write(sc->vsc_fd, &host_event, sizeof(host_event)) == -1) {
244 			WPRINTF(("%s: failed to write host_event", __func__));
245 		}
246 
247 		vq_relchain(vq, req.idx, sizeof(event));
248 	}
249 	vq_endchains(vq, 1);
250 }
251 
252 static int
pci_vtinput_get_bitmap(struct pci_vtinput_softc * sc,int cmd,int count)253 pci_vtinput_get_bitmap(struct pci_vtinput_softc *sc, int cmd, int count)
254 {
255 	if (count <= 0 || !sc) {
256 		return (-1);
257 	}
258 
259 	/* query bitmap */
260 	memset(sc->vsc_config.u.bitmap, 0, sizeof(sc->vsc_config.u.bitmap));
261 	if (ioctl(sc->vsc_fd, cmd, sc->vsc_config.u.bitmap) < 0) {
262 		return (-1);
263 	}
264 
265 	/* get number of set bytes in bitmap */
266 	for (int i = count - 1; i >= 0; i--) {
267 		if (sc->vsc_config.u.bitmap[i]) {
268 			return i + 1;
269 		}
270 	}
271 
272 	return (-1);
273 }
274 
275 static int
pci_vtinput_read_config_id_name(struct pci_vtinput_softc * sc)276 pci_vtinput_read_config_id_name(struct pci_vtinput_softc *sc)
277 {
278 	char name[128];
279 	if (ioctl(sc->vsc_fd, EVIOCGNAME(sizeof(name) - 1), name) < 0) {
280 		return (1);
281 	}
282 
283 	memcpy(sc->vsc_config.u.string, name, sizeof(name));
284 	sc->vsc_config.size = strnlen(name, sizeof(name));
285 
286 	return (0);
287 }
288 
289 static int
pci_vtinput_read_config_id_serial(struct pci_vtinput_softc * sc)290 pci_vtinput_read_config_id_serial(struct pci_vtinput_softc *sc)
291 {
292 	/* serial isn't supported */
293 	sc->vsc_config.size = 0;
294 
295 	return (0);
296 }
297 
298 static int
pci_vtinput_read_config_id_devids(struct pci_vtinput_softc * sc)299 pci_vtinput_read_config_id_devids(struct pci_vtinput_softc *sc)
300 {
301 	struct input_id devids;
302 	if (ioctl(sc->vsc_fd, EVIOCGID, &devids)) {
303 		return (1);
304 	}
305 
306 	sc->vsc_config.u.ids.bustype = devids.bustype;
307 	sc->vsc_config.u.ids.vendor = devids.vendor;
308 	sc->vsc_config.u.ids.product = devids.product;
309 	sc->vsc_config.u.ids.version = devids.version;
310 	sc->vsc_config.size = sizeof(struct vtinput_devids);
311 
312 	return (0);
313 }
314 
315 static int
pci_vtinput_read_config_prop_bits(struct pci_vtinput_softc * sc)316 pci_vtinput_read_config_prop_bits(struct pci_vtinput_softc *sc)
317 {
318 	/*
319 	 * Evdev bitmap countains 1 bit per count. Additionally evdev bitmaps
320 	 * are arrays of longs instead of chars. Calculate how many longs are
321 	 * required for evdev bitmap. Multiply that with sizeof(long) to get the
322 	 * number of elements.
323 	 */
324 	const int count = howmany(INPUT_PROP_CNT, sizeof(long) * 8) *
325 	    sizeof(long);
326 	const unsigned int cmd = EVIOCGPROP(count);
327 	const int size = pci_vtinput_get_bitmap(sc, cmd, count);
328 	if (size <= 0) {
329 		return (1);
330 	}
331 
332 	sc->vsc_config.size = size;
333 
334 	return (0);
335 }
336 
337 static int
pci_vtinput_read_config_ev_bits(struct pci_vtinput_softc * sc,uint8_t type)338 pci_vtinput_read_config_ev_bits(struct pci_vtinput_softc *sc, uint8_t type)
339 {
340 	int count;
341 
342 	switch (type) {
343 	case EV_KEY:
344 		count = KEY_CNT;
345 		break;
346 	case EV_REL:
347 		count = REL_CNT;
348 		break;
349 	case EV_ABS:
350 		count = ABS_CNT;
351 		break;
352 	case EV_MSC:
353 		count = MSC_CNT;
354 		break;
355 	case EV_SW:
356 		count = SW_CNT;
357 		break;
358 	case EV_LED:
359 		count = LED_CNT;
360 		break;
361 	default:
362 		return (1);
363 	}
364 
365 	/*
366 	 * Evdev bitmap countains 1 bit per count. Additionally evdev bitmaps
367 	 * are arrays of longs instead of chars. Calculate how many longs are
368 	 * required for evdev bitmap. Multiply that with sizeof(long) to get the
369 	 * number of elements.
370 	 */
371 	count = howmany(count, sizeof(long) * 8) * sizeof(long);
372 	const unsigned int cmd = EVIOCGBIT(sc->vsc_config.subsel, count);
373 	const int size = pci_vtinput_get_bitmap(sc, cmd, count);
374 	if (size <= 0) {
375 		return (1);
376 	}
377 
378 	sc->vsc_config.size = size;
379 
380 	return (0);
381 }
382 
383 static int
pci_vtinput_read_config_abs_info(struct pci_vtinput_softc * sc)384 pci_vtinput_read_config_abs_info(struct pci_vtinput_softc *sc)
385 {
386 	/* check if evdev has EV_ABS */
387 	if (!pci_vtinput_read_config_ev_bits(sc, EV_ABS)) {
388 		return (1);
389 	}
390 
391 	/* get abs information */
392 	struct input_absinfo abs;
393 	if (ioctl(sc->vsc_fd, EVIOCGABS(sc->vsc_config.subsel), &abs) < 0) {
394 		return (1);
395 	}
396 
397 	/* save abs information */
398 	sc->vsc_config.u.abs.min = abs.minimum;
399 	sc->vsc_config.u.abs.max = abs.maximum;
400 	sc->vsc_config.u.abs.fuzz = abs.fuzz;
401 	sc->vsc_config.u.abs.flat = abs.flat;
402 	sc->vsc_config.u.abs.res = abs.resolution;
403 	sc->vsc_config.size = sizeof(struct vtinput_absinfo);
404 
405 	return (0);
406 }
407 
408 static int
pci_vtinput_read_config(struct pci_vtinput_softc * sc)409 pci_vtinput_read_config(struct pci_vtinput_softc *sc)
410 {
411 	switch (sc->vsc_config.select) {
412 	case VTINPUT_CFG_UNSET:
413 		return (0);
414 	case VTINPUT_CFG_ID_NAME:
415 		return pci_vtinput_read_config_id_name(sc);
416 	case VTINPUT_CFG_ID_SERIAL:
417 		return pci_vtinput_read_config_id_serial(sc);
418 	case VTINPUT_CFG_ID_DEVIDS:
419 		return pci_vtinput_read_config_id_devids(sc);
420 	case VTINPUT_CFG_PROP_BITS:
421 		return pci_vtinput_read_config_prop_bits(sc);
422 	case VTINPUT_CFG_EV_BITS:
423 		return pci_vtinput_read_config_ev_bits(
424 		    sc, sc->vsc_config.subsel);
425 	case VTINPUT_CFG_ABS_INFO:
426 		return pci_vtinput_read_config_abs_info(sc);
427 	default:
428 		return (1);
429 	}
430 }
431 
432 static int
pci_vtinput_cfgread(void * vsc,int offset,int size,uint32_t * retval)433 pci_vtinput_cfgread(void *vsc, int offset, int size, uint32_t *retval)
434 {
435 	struct pci_vtinput_softc *sc = vsc;
436 
437 	/* check for valid offset and size */
438 	if (offset + size > (int)sizeof(struct vtinput_config)) {
439 		WPRINTF(("%s: read to invalid offset/size %d/%d", __func__,
440 		    offset, size));
441 		memset(retval, 0, size);
442 		return (0);
443 	}
444 
445 	/* read new config values, if select and subsel changed. */
446 	if (!sc->vsc_config_valid) {
447 		if (pci_vtinput_read_config(sc) != 0) {
448 			DPRINTF(("%s: could not read config %d/%d", __func__,
449 			    sc->vsc_config.select, sc->vsc_config.subsel));
450 			memset(retval, 0, size);
451 			return (0);
452 		}
453 		sc->vsc_config_valid = 1;
454 	}
455 
456 	uint8_t *ptr = (uint8_t *)&sc->vsc_config;
457 	memcpy(retval, ptr + offset, size);
458 
459 	return (0);
460 }
461 
462 static int
pci_vtinput_cfgwrite(void * vsc,int offset,int size,uint32_t value)463 pci_vtinput_cfgwrite(void *vsc, int offset, int size, uint32_t value)
464 {
465 	struct pci_vtinput_softc *sc = vsc;
466 
467 	/* guest can only write to select and subsel fields */
468 	if (offset + size > 2) {
469 		WPRINTF(("%s: write to readonly reg %d", __func__, offset));
470 		return (1);
471 	}
472 
473 	/* copy value into config */
474 	uint8_t *ptr = (uint8_t *)&sc->vsc_config;
475 	memcpy(ptr + offset, &value, size);
476 
477 	/* select/subsel changed, query new config on next cfgread */
478 	sc->vsc_config_valid = 0;
479 
480 	/* notify the guest the device configuration has been changed */
481 	vq_devcfg_changed(&sc->vsc_vs);
482 
483 	return (0);
484 }
485 
486 static int
vtinput_eventqueue_add_event(struct vtinput_eventqueue * queue,struct input_event * e)487 vtinput_eventqueue_add_event(
488     struct vtinput_eventqueue *queue, struct input_event *e)
489 {
490 	/* check if queue is full */
491 	if (queue->idx >= queue->size) {
492 		/* alloc new elements for queue */
493 		const uint32_t newSize = queue->idx;
494 		void *newPtr = realloc(queue->events,
495 		    queue->size * sizeof(struct vtinput_event_elem));
496 		if (newPtr == NULL) {
497 			WPRINTF(("%s: realloc memory for eventqueue failed!",
498 			    __func__));
499 			return (1);
500 		}
501 		queue->events = newPtr;
502 		queue->size = newSize;
503 	}
504 
505 	/* save event */
506 	struct vtinput_event *event = &queue->events[queue->idx].event;
507 	event->type = e->type;
508 	event->code = e->code;
509 	event->value = e->value;
510 	queue->idx++;
511 
512 	return (0);
513 }
514 
515 static void
vtinput_eventqueue_clear(struct vtinput_eventqueue * queue)516 vtinput_eventqueue_clear(struct vtinput_eventqueue *queue)
517 {
518 	/* just reset index to clear queue */
519 	queue->idx = 0;
520 }
521 
522 static void
vtinput_eventqueue_send_events(struct vtinput_eventqueue * queue,struct vqueue_info * vq)523 vtinput_eventqueue_send_events(
524     struct vtinput_eventqueue *queue, struct vqueue_info *vq)
525 {
526 	/*
527 	 * First iteration through eventqueue:
528 	 *   Get descriptor chains.
529 	 */
530 	for (uint32_t i = 0; i < queue->idx; ++i) {
531 		/* get descriptor */
532 		if (!vq_has_descs(vq)) {
533 			/*
534 			 * We don't have enough descriptors for all events.
535 			 * Return chains back to guest.
536 			 */
537 			vq_retchains(vq, i);
538 			WPRINTF((
539 			    "%s: not enough available descriptors, dropping %d events",
540 			    __func__, queue->idx));
541 			goto done;
542 		}
543 
544 		/* get descriptor chain */
545 		struct iovec iov;
546 		struct vi_req req;
547 		const int n = vq_getchain(vq, &iov, 1, &req);
548 		if (n <= 0) {
549 			WPRINTF(("%s: invalid descriptor: %d", __func__, n));
550 			return;
551 		}
552 		if (n != 1) {
553 			WPRINTF(
554 			    ("%s: invalid number of descriptors in chain: %d",
555 				__func__, n));
556 			/* release invalid chain */
557 			vq_relchain(vq, req.idx, 0);
558 			return;
559 		}
560 		if (iov.iov_len < sizeof(struct vtinput_event)) {
561 			WPRINTF(("%s: invalid descriptor length: %lu", __func__,
562 			    iov.iov_len));
563 			/* release invalid chain */
564 			vq_relchain(vq, req.idx, 0);
565 			return;
566 		}
567 
568 		/* save descriptor */
569 		queue->events[i].iov = iov;
570 		queue->events[i].idx = req.idx;
571 	}
572 
573 	/*
574 	 * Second iteration through eventqueue:
575 	 *   Send events to guest by releasing chains
576 	 */
577 	for (uint32_t i = 0; i < queue->idx; ++i) {
578 		struct vtinput_event_elem event = queue->events[i];
579 		memcpy(event.iov.iov_base, &event.event,
580 		    sizeof(struct vtinput_event));
581 		vq_relchain(vq, event.idx, sizeof(struct vtinput_event));
582 	}
583 done:
584 	/* clear queue and send interrupt to guest */
585 	vtinput_eventqueue_clear(queue);
586 	vq_endchains(vq, 1);
587 }
588 
589 static int
vtinput_read_event_from_host(int fd,struct input_event * event)590 vtinput_read_event_from_host(int fd, struct input_event *event)
591 {
592 	const int len = read(fd, event, sizeof(struct input_event));
593 	if (len != sizeof(struct input_event)) {
594 		if (len == -1 && errno != EAGAIN) {
595 			WPRINTF(("%s: event read failed! len = %d, errno = %d",
596 			    __func__, len, errno));
597 		}
598 
599 		/* host doesn't have more events for us */
600 		return (1);
601 	}
602 
603 	return (0);
604 }
605 
606 static void
vtinput_read_event(int fd __attribute ((unused)),enum ev_type t,void * arg)607 vtinput_read_event(int fd __attribute((unused)),
608     enum ev_type t __attribute__((unused)), void *arg __attribute__((unused)))
609 {
610 	struct pci_vtinput_softc *sc = arg;
611 
612 	/* skip if driver isn't ready */
613 	if (!(sc->vsc_vs.vs_status & VIRTIO_CONFIG_STATUS_DRIVER_OK))
614 		return;
615 
616 	/* read all events from host */
617 	struct input_event event;
618 	while (vtinput_read_event_from_host(sc->vsc_fd, &event) == 0) {
619 		/* add events to our queue */
620 		vtinput_eventqueue_add_event(&sc->vsc_eventqueue, &event);
621 
622 		/* only send events to guest on EV_SYN or SYN_REPORT */
623 		if (event.type != EV_SYN || event.type != SYN_REPORT) {
624 			continue;
625 		}
626 
627 		/* send host events to guest */
628 		vtinput_eventqueue_send_events(
629 		    &sc->vsc_eventqueue, &sc->vsc_queues[VTINPUT_EVENTQ]);
630 	}
631 }
632 
633 static int
pci_vtinput_legacy_config(nvlist_t * nvl,const char * opts)634 pci_vtinput_legacy_config(nvlist_t *nvl, const char *opts)
635 {
636 	if (opts == NULL)
637 		return (-1);
638 
639 	/*
640 	 * parse opts:
641 	 *   virtio-input,/dev/input/eventX
642 	 */
643 	char *cp = strchr(opts, ',');
644 	if (cp == NULL) {
645 		set_config_value_node(nvl, "path", opts);
646 		return (0);
647 	}
648 	char *path = strndup(opts, cp - opts);
649 	set_config_value_node(nvl, "path", path);
650 	free(path);
651 
652 	return (pci_parse_legacy_config(nvl, cp + 1));
653 }
654 
655 static int
pci_vtinput_init(struct pci_devinst * pi,nvlist_t * nvl)656 pci_vtinput_init(struct pci_devinst *pi, nvlist_t *nvl)
657 {
658 	struct pci_vtinput_softc *sc;
659 
660 	/*
661 	 * Keep it here.
662 	 * Else it's possible to access it uninitialized by jumping to failed.
663 	 */
664 	pthread_mutexattr_t mtx_attr = NULL;
665 
666 	sc = calloc(1, sizeof(struct pci_vtinput_softc));
667 
668 	sc->vsc_evdev = get_config_value_node(nvl, "path");
669 	if (sc->vsc_evdev == NULL) {
670 		WPRINTF(("%s: missing required path config value", __func__));
671 		goto failed;
672 	}
673 
674 	/*
675 	 * open evdev by using non blocking I/O:
676 	 *   read from /dev/input/eventX would block our thread otherwise
677 	 */
678 	sc->vsc_fd = open(sc->vsc_evdev, O_RDWR | O_NONBLOCK);
679 	if (sc->vsc_fd < 0) {
680 		WPRINTF(("%s: failed to open %s", __func__, sc->vsc_evdev));
681 		goto failed;
682 	}
683 
684 	/* check if evdev is really a evdev */
685 	int evversion;
686 	int error = ioctl(sc->vsc_fd, EVIOCGVERSION, &evversion);
687 	if (error < 0) {
688 		WPRINTF(("%s: %s is no evdev", __func__, sc->vsc_evdev));
689 		goto failed;
690 	}
691 
692 	/* gain exclusive access to evdev */
693 	error = ioctl(sc->vsc_fd, EVIOCGRAB, 1);
694 	if (error < 0) {
695 		WPRINTF(("%s: failed to grab %s", __func__, sc->vsc_evdev));
696 		goto failed;
697 	}
698 
699 	if (pthread_mutexattr_init(&mtx_attr)) {
700 		WPRINTF(("%s: init mutexattr failed", __func__));
701 		goto failed;
702 	}
703 	if (pthread_mutexattr_settype(&mtx_attr, PTHREAD_MUTEX_RECURSIVE)) {
704 		WPRINTF(("%s: settype mutexattr failed", __func__));
705 		goto failed;
706 	}
707 	if (pthread_mutex_init(&sc->vsc_mtx, &mtx_attr)) {
708 		WPRINTF(("%s: init mutex failed", __func__));
709 		goto failed;
710 	}
711 
712 	/* init softc */
713 	sc->vsc_eventqueue.idx = 0;
714 	sc->vsc_eventqueue.size = VTINPUT_MAX_PKT_LEN;
715 	sc->vsc_eventqueue.events = calloc(
716 	    sc->vsc_eventqueue.size, sizeof(struct vtinput_event_elem));
717 	sc->vsc_config_valid = 0;
718 	if (sc->vsc_eventqueue.events == NULL) {
719 		WPRINTF(("%s: failed to alloc eventqueue", __func__));
720 		goto failed;
721 	}
722 
723 	/* register event handler */
724 	sc->vsc_evp = mevent_add(sc->vsc_fd, EVF_READ, vtinput_read_event, sc);
725 	if (sc->vsc_evp == NULL) {
726 		WPRINTF(("%s: could not register mevent", __func__));
727 		goto failed;
728 	}
729 
730 #ifndef WITHOUT_CAPSICUM
731 	cap_rights_t rights;
732 	cap_rights_init(&rights, CAP_EVENT, CAP_IOCTL, CAP_READ, CAP_WRITE);
733 	if (caph_rights_limit(sc->vsc_fd, &rights) == -1) {
734 		errx(EX_OSERR, "Unable to apply rights for sandbox");
735 	}
736 #endif
737 
738 	/* link virtio to softc */
739 	vi_softc_linkup(
740 	    &sc->vsc_vs, &vtinput_vi_consts, sc, pi, sc->vsc_queues);
741 	sc->vsc_vs.vs_mtx = &sc->vsc_mtx;
742 
743 	/* init virtio queues */
744 	sc->vsc_queues[VTINPUT_EVENTQ].vq_qsize = VTINPUT_RINGSZ;
745 	sc->vsc_queues[VTINPUT_EVENTQ].vq_notify = pci_vtinput_notify_eventq;
746 	sc->vsc_queues[VTINPUT_STATUSQ].vq_qsize = VTINPUT_RINGSZ;
747 	sc->vsc_queues[VTINPUT_STATUSQ].vq_notify = pci_vtinput_notify_statusq;
748 
749 	/* initialize config space */
750 	vi_pci_init(pi, VIRTIO_MODE_TRANSITIONAL, VIRTIO_DEV_INPUT,
751 	    VIRTIO_ID_INPUT, PCIC_INPUTDEV);
752 	pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_INPUTDEV_OTHER);
753 	pci_set_cfgdata8(pi, PCIR_REVID, VIRTIO_REV_INPUT);
754 	pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_SUBDEV_INPUT);
755 	pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_SUBVEN_INPUT);
756 
757 	/* add MSI-X table BAR */
758 	if (!vi_intr_init(&sc->vsc_vs, fbsdrun_virtio_msix()))
759 		goto failed;
760 	/* add VirtIO BARs */
761 	if (!vi_pcibar_setup(&sc->vsc_vs))
762 		goto failed;
763 
764 	return (0);
765 
766 failed:
767 	if (sc == NULL) {
768 		return (-1);
769 	}
770 
771 	if (sc->vsc_evp)
772 		mevent_delete(sc->vsc_evp);
773 	if (sc->vsc_eventqueue.events)
774 		free(sc->vsc_eventqueue.events);
775 	if (sc->vsc_mtx)
776 		pthread_mutex_destroy(&sc->vsc_mtx);
777 	if (mtx_attr)
778 		pthread_mutexattr_destroy(&mtx_attr);
779 	if (sc->vsc_fd)
780 		close(sc->vsc_fd);
781 
782 	free(sc);
783 
784 	return (-1);
785 }
786 
787 static const struct pci_devemu pci_de_vinput = {
788 	.pe_emu = "virtio-input",
789 	.pe_init = pci_vtinput_init,
790 	.pe_legacy_config = pci_vtinput_legacy_config,
791 	.pe_barwrite = vi_pci_write,
792 	.pe_barread = vi_pci_read,
793 };
794 PCI_EMUL_SET(pci_de_vinput);
795