History

Add virtio-input driver.

virtio-input is basically evdev-events-over-virtio, so this driver isn't much more than reading configuration from config space and forwarding incoming events to the linux input layer.

Gerd Hoffmann committed 11 years ago

Commit 271c8651 parent 2f921b57 files · +479 −0Browse files

Unified · Split

7 files
  1. MAINTAINERS +6 −0
  2. drivers/virtio/Kconfig +10 −0
  3. drivers/virtio/Makefile +1 −0
  4. drivers/virtio/virtio_input.c +384 −0
  5. include/uapi/linux/Kbuild +1 −0
  6. include/uapi/linux/virtio_ids.h +1 −0
  7. include/uapi/linux/virtio_input.h +76 −0
MAINTAINERS+6−0
@@ -10435,6 +10435,12 @@ S: Maintained · 10434 unmodified lines
10435F: drivers/vhost/10435F: drivers/vhost/
10436F: include/uapi/linux/vhost.h10436F: include/uapi/linux/vhost.h
10437 10437
10438VIRTIO INPUT DRIVER
10439M: Gerd Hoffmann <kraxel@redhat.com>
10440S: Maintained
10441F: drivers/virtio/virtio_input.c
10442F: include/uapi/linux/virtio_input.h
10443
10438VIA RHINE NETWORK DRIVER10444VIA RHINE NETWORK DRIVER
10439M: Roger Luethi <rl@hellgate.ch>10445M: Roger Luethi <rl@hellgate.ch>
10440S: Maintained10446S: Maintained
drivers/virtio/Kconfig+10−0
@@ -48,6 +48,16 @@ config VIRTIO_BALLOON · 47 unmodified lines
48 48
49 If unsure, say M.49 If unsure, say M.
50 50
51config VIRTIO_INPUT
52 tristate "Virtio input driver"
53 depends on VIRTIO
54 depends on INPUT
55 ---help---
56 This driver supports virtio input devices such as
57 keyboards, mice and tablets.
58
59 If unsure, say M.
60
51 config VIRTIO_MMIO61 config VIRTIO_MMIO
52 tristate "Platform bus driver for memory mapped virtio devices"62 tristate "Platform bus driver for memory mapped virtio devices"
53 depends on HAS_IOMEM63 depends on HAS_IOMEM
drivers/virtio/Makefile+1−0
@@ -4,3 +4,4 @@ obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o · 3 unmodified lines
4virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o4virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
5virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o5virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
6obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o6obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
7obj-$(CONFIG_VIRTIO_INPUT) += virtio_input.o
drivers/virtio/virtio_input.c+384−0
@@ -0,0 +1,384 @@
1#include <linux/module.h>
2#include <linux/virtio.h>
3#include <linux/virtio_config.h>
4#include <linux/input.h>
5
6#include <uapi/linux/virtio_ids.h>
7#include <uapi/linux/virtio_input.h>
8
9struct virtio_input {
10 struct virtio_device *vdev;
11 struct input_dev *idev;
12 char name[64];
13 char serial[64];
14 char phys[64];
15 struct virtqueue *evt, *sts;
16 struct virtio_input_event evts[64];
17 spinlock_t lock;
18 bool ready;
19};
20
21static void virtinput_queue_evtbuf(struct virtio_input *vi,
22 struct virtio_input_event *evtbuf)
23{
24 struct scatterlist sg[1];
25
26 sg_init_one(sg, evtbuf, sizeof(*evtbuf));
27 virtqueue_add_inbuf(vi->evt, sg, 1, evtbuf, GFP_ATOMIC);
28}
29
30static void virtinput_recv_events(struct virtqueue *vq)
31{
32 struct virtio_input *vi = vq->vdev->priv;
33 struct virtio_input_event *event;
34 unsigned long flags;
35 unsigned int len;
36
37 spin_lock_irqsave(&vi->lock, flags);
38 if (vi->ready) {
39 while ((event = virtqueue_get_buf(vi->evt, &len)) != NULL) {
40 spin_unlock_irqrestore(&vi->lock, flags);
41 input_event(vi->idev,
42 le16_to_cpu(event->type),
43 le16_to_cpu(event->code),
44 le32_to_cpu(event->value));
45 spin_lock_irqsave(&vi->lock, flags);
46 virtinput_queue_evtbuf(vi, event);
47 }
48 virtqueue_kick(vq);
49 }
50 spin_unlock_irqrestore(&vi->lock, flags);
51}
52
53/*
54 * On error we are losing the status update, which isn't critical as
55 * this is typically used for stuff like keyboard leds.
56 */
57static int virtinput_send_status(struct virtio_input *vi,
58 u16 type, u16 code, s32 value)
59{
60 struct virtio_input_event *stsbuf;
61 struct scatterlist sg[1];
62 unsigned long flags;
63 int rc;
64
65 stsbuf = kzalloc(sizeof(*stsbuf), GFP_ATOMIC);
66 if (!stsbuf)
67 return -ENOMEM;
68
69 stsbuf->type = cpu_to_le16(type);
70 stsbuf->code = cpu_to_le16(code);
71 stsbuf->value = cpu_to_le32(value);
72 sg_init_one(sg, stsbuf, sizeof(*stsbuf));
73
74 spin_lock_irqsave(&vi->lock, flags);
75 if (vi->ready) {
76 rc = virtqueue_add_outbuf(vi->sts, sg, 1, stsbuf, GFP_ATOMIC);
77 virtqueue_kick(vi->sts);
78 } else {
79 rc = -ENODEV;
80 }
81 spin_unlock_irqrestore(&vi->lock, flags);
82
83 if (rc != 0)
84 kfree(stsbuf);
85 return rc;
86}
87
88static void virtinput_recv_status(struct virtqueue *vq)
89{
90 struct virtio_input *vi = vq->vdev->priv;
91 struct virtio_input_event *stsbuf;
92 unsigned long flags;
93 unsigned int len;
94
95 spin_lock_irqsave(&vi->lock, flags);
96 while ((stsbuf = virtqueue_get_buf(vi->sts, &len)) != NULL)
97 kfree(stsbuf);
98 spin_unlock_irqrestore(&vi->lock, flags);
99}
100
101static int virtinput_status(struct input_dev *idev, unsigned int type,
102 unsigned int code, int value)
103{
104 struct virtio_input *vi = input_get_drvdata(idev);
105
106 return virtinput_send_status(vi, type, code, value);
107}
108
109static u8 virtinput_cfg_select(struct virtio_input *vi,
110 u8 select, u8 subsel)
111{
112 u8 size;
113
114 virtio_cwrite(vi->vdev, struct virtio_input_config, select, &select);
115 virtio_cwrite(vi->vdev, struct virtio_input_config, subsel, &subsel);
116 virtio_cread(vi->vdev, struct virtio_input_config, size, &size);
117 return size;
118}
119
120static void virtinput_cfg_bits(struct virtio_input *vi, int select, int subsel,
121 unsigned long *bits, unsigned int bitcount)
122{
123 unsigned int bit;
124 u8 *virtio_bits;
125 u8 bytes;
126
127 bytes = virtinput_cfg_select(vi, select, subsel);
128 if (!bytes)
129 return;
130 if (bitcount > bytes * 8)
131 bitcount = bytes * 8;
132
133 /*
134 * Bitmap in virtio config space is a simple stream of bytes,
135 * with the first byte carrying bits 0-7, second bits 8-15 and
136 * so on.
137 */
138 virtio_bits = kzalloc(bytes, GFP_KERNEL);
139 if (!virtio_bits)
140 return;
141 virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
142 u.bitmap),
143 virtio_bits, bytes);
144 for (bit = 0; bit < bitcount; bit++) {
145 if (virtio_bits[bit / 8] & (1 << (bit % 8)))
146 __set_bit(bit, bits);
147 }
148 kfree(virtio_bits);
149
150 if (select == VIRTIO_INPUT_CFG_EV_BITS)
151 __set_bit(subsel, vi->idev->evbit);
152}
153
154static void virtinput_cfg_abs(struct virtio_input *vi, int abs)
155{
156 u32 mi, ma, re, fu, fl;
157
158 virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ABS_INFO, abs);
159 virtio_cread(vi->vdev, struct virtio_input_config, u.abs.min, &mi);
160 virtio_cread(vi->vdev, struct virtio_input_config, u.abs.max, &ma);
161 virtio_cread(vi->vdev, struct virtio_input_config, u.abs.res, &re);
162 virtio_cread(vi->vdev, struct virtio_input_config, u.abs.fuzz, &fu);
163 virtio_cread(vi->vdev, struct virtio_input_config, u.abs.flat, &fl);
164 input_set_abs_params(vi->idev, abs, mi, ma, fu, fl);
165 input_abs_set_res(vi->idev, abs, re);
166}
167
168static int virtinput_init_vqs(struct virtio_input *vi)
169{
170 struct virtqueue *vqs[2];
171 vq_callback_t *cbs[] = { virtinput_recv_events,
172 virtinput_recv_status };
173 static const char *names[] = { "events", "status" };
174 int err;
175
176 err = vi->vdev->config->find_vqs(vi->vdev, 2, vqs, cbs, names);
177 if (err)
178 return err;
179 vi->evt = vqs[0];
180 vi->sts = vqs[1];
181
182 return 0;
183}
184
185static void virtinput_fill_evt(struct virtio_input *vi)
186{
187 unsigned long flags;
188 int i, size;
189
190 spin_lock_irqsave(&vi->lock, flags);
191 size = virtqueue_get_vring_size(vi->evt);
192 if (size > ARRAY_SIZE(vi->evts))
193 size = ARRAY_SIZE(vi->evts);
194 for (i = 0; i < size; i++)
195 virtinput_queue_evtbuf(vi, &vi->evts[i]);
196 virtqueue_kick(vi->evt);
197 spin_unlock_irqrestore(&vi->lock, flags);
198}
199
200static int virtinput_probe(struct virtio_device *vdev)
201{
202 struct virtio_input *vi;
203 unsigned long flags;
204 size_t size;
205 int abs, err;
206
207 if (!virtio_has_feature(vdev, VIRTIO_F_VERSION_1))
208 return -ENODEV;
209
210 vi = kzalloc(sizeof(*vi), GFP_KERNEL);
211 if (!vi)
212 return -ENOMEM;
213
214 vdev->priv = vi;
215 vi->vdev = vdev;
216 spin_lock_init(&vi->lock);
217
218 err = virtinput_init_vqs(vi);
219 if (err)
220 goto err_init_vq;
221
222 vi->idev = input_allocate_device();
223 if (!vi->idev) {
224 err = -ENOMEM;
225 goto err_input_alloc;
226 }
227 input_set_drvdata(vi->idev, vi);
228
229 size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_NAME, 0);
230 virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
231 u.string),
232 vi->name, min(size, sizeof(vi->name)));
233 size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_SERIAL, 0);
234 virtio_cread_bytes(vi->vdev, offsetof(struct virtio_input_config,
235 u.string),
236 vi->serial, min(size, sizeof(vi->serial)));
237 snprintf(vi->phys, sizeof(vi->phys),
238 "virtio%d/input0", vdev->index);
239 vi->idev->name = vi->name;
240 vi->idev->phys = vi->phys;
241 vi->idev->uniq = vi->serial;
242
243 size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_ID_DEVIDS, 0);
244 if (size >= sizeof(struct virtio_input_devids)) {
245 virtio_cread(vi->vdev, struct virtio_input_config,
246 u.ids.bustype, &vi->idev->id.bustype);
247 virtio_cread(vi->vdev, struct virtio_input_config,
248 u.ids.vendor, &vi->idev->id.vendor);
249 virtio_cread(vi->vdev, struct virtio_input_config,
250 u.ids.product, &vi->idev->id.product);
251 virtio_cread(vi->vdev, struct virtio_input_config,
252 u.ids.version, &vi->idev->id.version);
253 } else {
254 vi->idev->id.bustype = BUS_VIRTUAL;
255 }
256
257 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_PROP_BITS, 0,
258 vi->idev->propbit, INPUT_PROP_CNT);
259 size = virtinput_cfg_select(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_REP);
260 if (size)
261 __set_bit(EV_REP, vi->idev->evbit);
262
263 vi->idev->dev.parent = &vdev->dev;
264 vi->idev->event = virtinput_status;
265
266 /* device -> kernel */
267 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_KEY,
268 vi->idev->keybit, KEY_CNT);
269 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_REL,
270 vi->idev->relbit, REL_CNT);
271 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_ABS,
272 vi->idev->absbit, ABS_CNT);
273 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_MSC,
274 vi->idev->mscbit, MSC_CNT);
275 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_SW,
276 vi->idev->swbit, SW_CNT);
277
278 /* kernel -> device */
279 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_LED,
280 vi->idev->ledbit, LED_CNT);
281 virtinput_cfg_bits(vi, VIRTIO_INPUT_CFG_EV_BITS, EV_SND,
282 vi->idev->sndbit, SND_CNT);
283
284 if (test_bit(EV_ABS, vi->idev->evbit)) {
285 for (abs = 0; abs < ABS_CNT; abs++) {
286 if (!test_bit(abs, vi->idev->absbit))
287 continue;
288 virtinput_cfg_abs(vi, abs);
289 }
290 }
291
292 virtio_device_ready(vdev);
293 vi->ready = true;
294 err = input_register_device(vi->idev);
295 if (err)
296 goto err_input_register;
297
298 virtinput_fill_evt(vi);
299 return 0;
300
301err_input_register:
302 spin_lock_irqsave(&vi->lock, flags);
303 vi->ready = false;
304 spin_unlock_irqrestore(&vi->lock, flags);
305 input_free_device(vi->idev);
306err_input_alloc:
307 vdev->config->del_vqs(vdev);
308err_init_vq:
309 kfree(vi);
310 return err;
311}
312
313static void virtinput_remove(struct virtio_device *vdev)
314{
315 struct virtio_input *vi = vdev->priv;
316 unsigned long flags;
317
318 spin_lock_irqsave(&vi->lock, flags);
319 vi->ready = false;
320 spin_unlock_irqrestore(&vi->lock, flags);
321
322 input_unregister_device(vi->idev);
323 vdev->config->del_vqs(vdev);
324 kfree(vi);
325}
326
327#ifdef CONFIG_PM_SLEEP
328static int virtinput_freeze(struct virtio_device *vdev)
329{
330 struct virtio_input *vi = vdev->priv;
331 unsigned long flags;
332
333 spin_lock_irqsave(&vi->lock, flags);
334 vi->ready = false;
335 spin_unlock_irqrestore(&vi->lock, flags);
336
337 vdev->config->del_vqs(vdev);
338 return 0;
339}
340
341static int virtinput_restore(struct virtio_device *vdev)
342{
343 struct virtio_input *vi = vdev->priv;
344 int err;
345
346 err = virtinput_init_vqs(vi);
347 if (err)
348 return err;
349
350 virtio_device_ready(vdev);
351 vi->ready = true;
352 virtinput_fill_evt(vi);
353 return 0;
354}
355#endif
356
357static unsigned int features[] = {
358 /* none */
359};
360static struct virtio_device_id id_table[] = {
361 { VIRTIO_ID_INPUT, VIRTIO_DEV_ANY_ID },
362 { 0 },
363};
364
365static struct virtio_driver virtio_input_driver = {
366 .driver.name = KBUILD_MODNAME,
367 .driver.owner = THIS_MODULE,
368 .feature_table = features,
369 .feature_table_size = ARRAY_SIZE(features),
370 .id_table = id_table,
371 .probe = virtinput_probe,
372 .remove = virtinput_remove,
373#ifdef CONFIG_PM_SLEEP
374 .freeze = virtinput_freeze,
375 .restore = virtinput_restore,
376#endif
377};
378
379module_virtio_driver(virtio_input_driver);
380MODULE_DEVICE_TABLE(virtio, id_table);
381
382MODULE_LICENSE("GPL");
383MODULE_DESCRIPTION("Virtio input device driver");
384MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
include/uapi/linux/Kbuild+1−0
@@ -430,6 +430,7 @@ header-y += virtio_blk.h · 429 unmodified lines
430header-y += virtio_config.h430header-y += virtio_config.h
431header-y += virtio_console.h431header-y += virtio_console.h
432header-y += virtio_ids.h432header-y += virtio_ids.h
433header-y += virtio_input.h
433header-y += virtio_net.h434header-y += virtio_net.h
434header-y += virtio_pci.h435header-y += virtio_pci.h
435header-y += virtio_ring.h436header-y += virtio_ring.h
include/uapi/linux/virtio_ids.h+1−0
@@ -39,5 +39,6 @@ · 38 unmodified lines
39#define VIRTIO_ID_9P 9 /* 9p virtio console */39#define VIRTIO_ID_9P 9 /* 9p virtio console */
40#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */40#define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
41#define VIRTIO_ID_CAIF 12 /* Virtio caif */41#define VIRTIO_ID_CAIF 12 /* Virtio caif */
42#define VIRTIO_ID_INPUT 18 /* virtio input */
42 43
43#endif /* _LINUX_VIRTIO_IDS_H */44#endif /* _LINUX_VIRTIO_IDS_H */
include/uapi/linux/virtio_input.h+76−0
@@ -0,0 +1,76 @@
1#ifndef _LINUX_VIRTIO_INPUT_H
2#define _LINUX_VIRTIO_INPUT_H
3/* This header is BSD licensed so anyone can use the definitions to implement
4 * compatible drivers/servers.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. Neither the name of IBM nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
27 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE. */
29
30#include <linux/types.h>
31
32enum virtio_input_config_select {
33 VIRTIO_INPUT_CFG_UNSET = 0x00,
34 VIRTIO_INPUT_CFG_ID_NAME = 0x01,
35 VIRTIO_INPUT_CFG_ID_SERIAL = 0x02,
36 VIRTIO_INPUT_CFG_ID_DEVIDS = 0x03,
37 VIRTIO_INPUT_CFG_PROP_BITS = 0x10,
38 VIRTIO_INPUT_CFG_EV_BITS = 0x11,
39 VIRTIO_INPUT_CFG_ABS_INFO = 0x12,
40};
41
42struct virtio_input_absinfo {
43 __u32 min;
44 __u32 max;
45 __u32 fuzz;
46 __u32 flat;
47 __u32 res;
48};
49
50struct virtio_input_devids {
51 __u16 bustype;
52 __u16 vendor;
53 __u16 product;
54 __u16 version;
55};
56
57struct virtio_input_config {
58 __u8 select;
59 __u8 subsel;
60 __u8 size;
61 __u8 reserved[5];
62 union {
63 char string[128];
64 __u8 bitmap[128];
65 struct virtio_input_absinfo abs;
66 struct virtio_input_devids ids;
67 } u;
68};
69
70struct virtio_input_event {
71 __le16 type;
72 __le16 code;
73 __le32 value;
74};
75
76#endif /* _LINUX_VIRTIO_INPUT_H */

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t