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