]> git.ipfire.org Git - thirdparty/qemu.git/blob - hw/input/virtio-input-host.c
include/qemu/osdep.h: Don't include qapi/error.h
[thirdparty/qemu.git] / hw / input / virtio-input-host.c
1 /*
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
4 * top-level directory.
5 */
6
7 #include "qemu/osdep.h"
8 #include "qapi/error.h"
9 #include "qemu-common.h"
10 #include "qemu/sockets.h"
11
12 #include "hw/qdev.h"
13 #include "hw/virtio/virtio.h"
14 #include "hw/virtio/virtio-input.h"
15
16 #include <sys/ioctl.h>
17 #include "standard-headers/linux/input.h"
18
19 /* ----------------------------------------------------------------- */
20
21 static struct virtio_input_config virtio_input_host_config[] = {
22 { /* empty list */ },
23 };
24
25 static void virtio_input_host_event(void *opaque)
26 {
27 VirtIOInputHost *vih = opaque;
28 VirtIOInput *vinput = VIRTIO_INPUT(vih);
29 struct virtio_input_event virtio;
30 struct input_event evdev;
31 int rc;
32
33 for (;;) {
34 rc = read(vih->fd, &evdev, sizeof(evdev));
35 if (rc != sizeof(evdev)) {
36 break;
37 }
38
39 virtio.type = cpu_to_le16(evdev.type);
40 virtio.code = cpu_to_le16(evdev.code);
41 virtio.value = cpu_to_le32(evdev.value);
42 virtio_input_send(vinput, &virtio);
43 }
44 }
45
46 static void virtio_input_bits_config(VirtIOInputHost *vih,
47 int type, int count)
48 {
49 virtio_input_config bits;
50 int rc, i, size = 0;
51
52 memset(&bits, 0, sizeof(bits));
53 rc = ioctl(vih->fd, EVIOCGBIT(type, count/8), bits.u.bitmap);
54 if (rc < 0) {
55 return;
56 }
57
58 for (i = 0; i < count/8; i++) {
59 if (bits.u.bitmap[i]) {
60 size = i+1;
61 }
62 }
63 if (size == 0) {
64 return;
65 }
66
67 bits.select = VIRTIO_INPUT_CFG_EV_BITS;
68 bits.subsel = type;
69 bits.size = size;
70 virtio_input_add_config(VIRTIO_INPUT(vih), &bits);
71 }
72
73 static void virtio_input_host_realize(DeviceState *dev, Error **errp)
74 {
75 VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev);
76 VirtIOInput *vinput = VIRTIO_INPUT(dev);
77 virtio_input_config id;
78 struct input_id ids;
79 int rc, ver;
80
81 if (!vih->evdev) {
82 error_setg(errp, "evdev property is required");
83 return;
84 }
85
86 vih->fd = open(vih->evdev, O_RDWR);
87 if (vih->fd < 0) {
88 error_setg_file_open(errp, errno, vih->evdev);
89 return;
90 }
91 qemu_set_nonblock(vih->fd);
92
93 rc = ioctl(vih->fd, EVIOCGVERSION, &ver);
94 if (rc < 0) {
95 error_setg(errp, "%s: is not an evdev device", vih->evdev);
96 goto err_close;
97 }
98
99 rc = ioctl(vih->fd, EVIOCGRAB, 1);
100 if (rc < 0) {
101 error_setg_errno(errp, errno, "%s: failed to get exclusive access",
102 vih->evdev);
103 goto err_close;
104 }
105
106 memset(&id, 0, sizeof(id));
107 ioctl(vih->fd, EVIOCGNAME(sizeof(id.u.string)-1), id.u.string);
108 id.select = VIRTIO_INPUT_CFG_ID_NAME;
109 id.size = strlen(id.u.string);
110 virtio_input_add_config(vinput, &id);
111
112 if (ioctl(vih->fd, EVIOCGID, &ids) == 0) {
113 memset(&id, 0, sizeof(id));
114 id.select = VIRTIO_INPUT_CFG_ID_DEVIDS;
115 id.size = sizeof(struct virtio_input_devids);
116 id.u.ids.bustype = cpu_to_le16(ids.bustype);
117 id.u.ids.vendor = cpu_to_le16(ids.vendor);
118 id.u.ids.product = cpu_to_le16(ids.product);
119 id.u.ids.version = cpu_to_le16(ids.version);
120 virtio_input_add_config(vinput, &id);
121 }
122
123 virtio_input_bits_config(vih, EV_KEY, KEY_CNT);
124 virtio_input_bits_config(vih, EV_REL, REL_CNT);
125 virtio_input_bits_config(vih, EV_ABS, ABS_CNT);
126 virtio_input_bits_config(vih, EV_MSC, MSC_CNT);
127 virtio_input_bits_config(vih, EV_SW, SW_CNT);
128
129 qemu_set_fd_handler(vih->fd, virtio_input_host_event, NULL, vih);
130 return;
131
132 err_close:
133 close(vih->fd);
134 vih->fd = -1;
135 return;
136 }
137
138 static void virtio_input_host_unrealize(DeviceState *dev, Error **errp)
139 {
140 VirtIOInputHost *vih = VIRTIO_INPUT_HOST(dev);
141
142 if (vih->fd > 0) {
143 qemu_set_fd_handler(vih->fd, NULL, NULL, NULL);
144 close(vih->fd);
145 }
146 }
147
148 static const VMStateDescription vmstate_virtio_input_host = {
149 .name = "virtio-input-host",
150 .unmigratable = 1,
151 };
152
153 static Property virtio_input_host_properties[] = {
154 DEFINE_PROP_STRING("evdev", VirtIOInputHost, evdev),
155 DEFINE_PROP_END_OF_LIST(),
156 };
157
158 static void virtio_input_host_class_init(ObjectClass *klass, void *data)
159 {
160 VirtIOInputClass *vic = VIRTIO_INPUT_CLASS(klass);
161 DeviceClass *dc = DEVICE_CLASS(klass);
162
163 dc->vmsd = &vmstate_virtio_input_host;
164 dc->props = virtio_input_host_properties;
165 vic->realize = virtio_input_host_realize;
166 vic->unrealize = virtio_input_host_unrealize;
167 }
168
169 static void virtio_input_host_init(Object *obj)
170 {
171 VirtIOInput *vinput = VIRTIO_INPUT(obj);
172
173 virtio_input_init_config(vinput, virtio_input_host_config);
174 }
175
176 static const TypeInfo virtio_input_host_info = {
177 .name = TYPE_VIRTIO_INPUT_HOST,
178 .parent = TYPE_VIRTIO_INPUT,
179 .instance_size = sizeof(VirtIOInputHost),
180 .instance_init = virtio_input_host_init,
181 .class_init = virtio_input_host_class_init,
182 };
183
184 /* ----------------------------------------------------------------- */
185
186 static void virtio_register_types(void)
187 {
188 type_register_static(&virtio_input_host_info);
189 }
190
191 type_init(virtio_register_types)