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
1043510435 F: drivers/vhost/
1043610436 F: include/uapi/linux/vhost.h
1043710437
10438+VIRTIO INPUT DRIVER
10439+M: Gerd Hoffmann <kraxel@redhat.com>
10440+S: Maintained
10441+F: drivers/virtio/virtio_input.c
10442+F: include/uapi/linux/virtio_input.h
10443+
1043810444 VIA RHINE NETWORK DRIVER
1043910445 M: Roger Luethi <rl@hellgate.ch>
1044010446 S: Maintained
drivers/virtio/Kconfig+10−0
@@ -48,6 +48,16 @@ config VIRTIO_BALLOON · 47 unmodified lines
4848
4949 If unsure, say M.
5050
51+config 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+
5161 config VIRTIO_MMIO
5262 tristate "Platform bus driver for memory mapped virtio devices"
5363 depends on HAS_IOMEM
drivers/virtio/Makefile+1−0
@@ -4,3 +4,4 @@ obj-$(CONFIG_VIRTIO_PCI) += virtio_pci.o · 3 unmodified lines
44 virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o
55 virtio_pci-$(CONFIG_VIRTIO_PCI_LEGACY) += virtio_pci_legacy.o
66 obj-$(CONFIG_VIRTIO_BALLOON) += virtio_balloon.o
7+obj-$(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+
9+struct 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+
21+static 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+
30+static 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+ */
57+static 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+
88+static 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+
101+static 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+
109+static 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+
120+static 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+
154+static 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+
168+static 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+
185+static 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+
200+static 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+
301+err_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);
306+err_input_alloc:
307+ vdev->config->del_vqs(vdev);
308+err_init_vq:
309+ kfree(vi);
310+ return err;
311+}
312+
313+static 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
328+static 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+
341+static 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+
357+static unsigned int features[] = {
358+ /* none */
359+};
360+static struct virtio_device_id id_table[] = {
361+ { VIRTIO_ID_INPUT, VIRTIO_DEV_ANY_ID },
362+ { 0 },
363+};
364+
365+static 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+
379+module_virtio_driver(virtio_input_driver);
380+MODULE_DEVICE_TABLE(virtio, id_table);
381+
382+MODULE_LICENSE("GPL");
383+MODULE_DESCRIPTION("Virtio input device driver");
384+MODULE_AUTHOR("Gerd Hoffmann <kraxel@redhat.com>");
include/uapi/linux/Kbuild+1−0
@@ -430,6 +430,7 @@ header-y += virtio_blk.h · 429 unmodified lines
430430 header-y += virtio_config.h
431431 header-y += virtio_console.h
432432 header-y += virtio_ids.h
433+header-y += virtio_input.h
433434 header-y += virtio_net.h
434435 header-y += virtio_pci.h
435436 header-y += virtio_ring.h
include/uapi/linux/virtio_ids.h+1−0
@@ -39,5 +39,6 @@ · 38 unmodified lines
3939 #define VIRTIO_ID_9P 9 /* 9p virtio console */
4040 #define VIRTIO_ID_RPROC_SERIAL 11 /* virtio remoteproc serial link */
4141 #define VIRTIO_ID_CAIF 12 /* Virtio caif */
42+#define VIRTIO_ID_INPUT 18 /* virtio input */
4243
4344 #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+
32+enum 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+
42+struct virtio_input_absinfo {
43+ __u32 min;
44+ __u32 max;
45+ __u32 fuzz;
46+ __u32 flat;
47+ __u32 res;
48+};
49+
50+struct virtio_input_devids {
51+ __u16 bustype;
52+ __u16 vendor;
53+ __u16 product;
54+ __u16 version;
55+};
56+
57+struct 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+
70+struct 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