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