diff options
| -rw-r--r-- | Documentation/input/userio.txt | 70 | ||||
| -rw-r--r-- | MAINTAINERS | 6 | ||||
| -rw-r--r-- | drivers/input/serio/Kconfig | 14 | ||||
| -rw-r--r-- | drivers/input/serio/Makefile | 1 | ||||
| -rw-r--r-- | drivers/input/serio/userio.c | 285 | ||||
| -rw-r--r-- | include/linux/miscdevice.h | 1 | ||||
| -rw-r--r-- | include/uapi/linux/userio.h | 44 |
7 files changed, 421 insertions, 0 deletions
diff --git a/Documentation/input/userio.txt b/Documentation/input/userio.txt new file mode 100644 index 000000000000..0880c0f447a6 --- /dev/null +++ b/Documentation/input/userio.txt | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | The userio Protocol | ||
| 2 | (c) 2015 Stephen Chandler Paul <thatslyude@gmail.com> | ||
| 3 | Sponsored by Red Hat | ||
| 4 | -------------------------------------------------------------------------------- | ||
| 5 | |||
| 6 | 1. Introduction | ||
| 7 | ~~~~~~~~~~~~~~~ | ||
| 8 | This module is intended to try to make the lives of input driver developers | ||
| 9 | easier by allowing them to test various serio devices (mainly the various | ||
| 10 | touchpads found on laptops) without having to have the physical device in front | ||
| 11 | of them. userio accomplishes this by allowing any privileged userspace program | ||
| 12 | to directly interact with the kernel's serio driver and control a virtual serio | ||
| 13 | port from there. | ||
| 14 | |||
| 15 | 2. Usage overview | ||
| 16 | ~~~~~~~~~~~~~~~~~ | ||
| 17 | In order to interact with the userio kernel module, one simply opens the | ||
| 18 | /dev/userio character device in their applications. Commands are sent to the | ||
| 19 | kernel module by writing to the device, and any data received from the serio | ||
| 20 | driver is read as-is from the /dev/userio device. All of the structures and | ||
| 21 | macros you need to interact with the device are defined in <linux/userio.h> and | ||
| 22 | <linux/serio.h>. | ||
| 23 | |||
| 24 | 3. Command Structure | ||
| 25 | ~~~~~~~~~~~~~~~~~~~~ | ||
| 26 | The struct used for sending commands to /dev/userio is as follows: | ||
| 27 | |||
| 28 | struct userio_cmd { | ||
| 29 | __u8 type; | ||
| 30 | __u8 data; | ||
| 31 | }; | ||
| 32 | |||
| 33 | "type" describes the type of command that is being sent. This can be any one | ||
| 34 | of the USERIO_CMD macros defined in <linux/userio.h>. "data" is the argument | ||
| 35 | that goes along with the command. In the event that the command doesn't have an | ||
| 36 | argument, this field can be left untouched and will be ignored by the kernel. | ||
| 37 | Each command should be sent by writing the struct directly to the character | ||
| 38 | device. In the event that the command you send is invalid, an error will be | ||
| 39 | returned by the character device and a more descriptive error will be printed | ||
| 40 | to the kernel log. Only one command can be sent at a time, any additional data | ||
| 41 | written to the character device after the initial command will be ignored. | ||
| 42 | To close the virtual serio port, just close /dev/userio. | ||
| 43 | |||
| 44 | 4. Commands | ||
| 45 | ~~~~~~~~~~~ | ||
| 46 | |||
| 47 | 4.1 USERIO_CMD_REGISTER | ||
| 48 | ~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 49 | Registers the port with the serio driver and begins transmitting data back and | ||
| 50 | forth. Registration can only be performed once a port type is set with | ||
| 51 | USERIO_CMD_SET_PORT_TYPE. Has no argument. | ||
| 52 | |||
| 53 | 4.2 USERIO_CMD_SET_PORT_TYPE | ||
| 54 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 55 | Sets the type of port we're emulating, where "data" is the port type being | ||
| 56 | set. Can be any of the macros from <linux/serio.h>. For example: SERIO_8042 | ||
| 57 | would set the port type to be a normal PS/2 port. | ||
| 58 | |||
| 59 | 4.3 USERIO_CMD_SEND_INTERRUPT | ||
| 60 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
| 61 | Sends an interrupt through the virtual serio port to the serio driver, where | ||
| 62 | "data" is the interrupt data being sent. | ||
| 63 | |||
| 64 | 5. Userspace tools | ||
| 65 | ~~~~~~~~~~~~~~~~~~ | ||
| 66 | The userio userspace tools are able to record PS/2 devices using some of the | ||
| 67 | debugging information from i8042, and play back the devices on /dev/userio. The | ||
| 68 | latest version of these tools can be found at: | ||
| 69 | |||
| 70 | https://github.com/Lyude/ps2emu | ||
diff --git a/MAINTAINERS b/MAINTAINERS index 797236befd27..ba59bd7b3557 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
| @@ -11100,6 +11100,12 @@ S: Maintained | |||
| 11100 | F: drivers/media/v4l2-core/videobuf2-* | 11100 | F: drivers/media/v4l2-core/videobuf2-* |
| 11101 | F: include/media/videobuf2-* | 11101 | F: include/media/videobuf2-* |
| 11102 | 11102 | ||
| 11103 | VIRTUAL SERIO DEVICE DRIVER | ||
| 11104 | M: Stephen Chandler Paul <thatslyude@gmail.com> | ||
| 11105 | S: Maintained | ||
| 11106 | F: drivers/input/serio/userio.c | ||
| 11107 | F: include/uapi/linux/userio.h | ||
| 11108 | |||
| 11103 | VIRTIO CONSOLE DRIVER | 11109 | VIRTIO CONSOLE DRIVER |
| 11104 | M: Amit Shah <amit.shah@redhat.com> | 11110 | M: Amit Shah <amit.shah@redhat.com> |
| 11105 | L: virtualization@lists.linux-foundation.org | 11111 | L: virtualization@lists.linux-foundation.org |
diff --git a/drivers/input/serio/Kconfig b/drivers/input/serio/Kconfig index 200841b77edb..c3d05b4d3118 100644 --- a/drivers/input/serio/Kconfig +++ b/drivers/input/serio/Kconfig | |||
| @@ -292,4 +292,18 @@ config SERIO_SUN4I_PS2 | |||
| 292 | To compile this driver as a module, choose M here: the | 292 | To compile this driver as a module, choose M here: the |
| 293 | module will be called sun4i-ps2. | 293 | module will be called sun4i-ps2. |
| 294 | 294 | ||
| 295 | config USERIO | ||
| 296 | tristate "User space serio port driver support" | ||
| 297 | help | ||
| 298 | Say Y here if you want to support user level drivers for serio | ||
| 299 | subsystem accessible under char device 10:240 - /dev/userio. Using | ||
| 300 | this facility userspace programs can implement serio ports that | ||
| 301 | will be used by the standard in-kernel serio consumer drivers, | ||
| 302 | such as psmouse and atkbd. | ||
| 303 | |||
| 304 | To compile this driver as a module, choose M here: the module will be | ||
| 305 | called userio. | ||
| 306 | |||
| 307 | If you are unsure, say N. | ||
| 308 | |||
| 295 | endif | 309 | endif |
diff --git a/drivers/input/serio/Makefile b/drivers/input/serio/Makefile index c600089b7a34..2374ef9b33d7 100644 --- a/drivers/input/serio/Makefile +++ b/drivers/input/serio/Makefile | |||
| @@ -30,3 +30,4 @@ obj-$(CONFIG_SERIO_APBPS2) += apbps2.o | |||
| 30 | obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o | 30 | obj-$(CONFIG_SERIO_OLPC_APSP) += olpc_apsp.o |
| 31 | obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o | 31 | obj-$(CONFIG_HYPERV_KEYBOARD) += hyperv-keyboard.o |
| 32 | obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o | 32 | obj-$(CONFIG_SERIO_SUN4I_PS2) += sun4i-ps2.o |
| 33 | obj-$(CONFIG_USERIO) += userio.o | ||
diff --git a/drivers/input/serio/userio.c b/drivers/input/serio/userio.c new file mode 100644 index 000000000000..df1fd41860ac --- /dev/null +++ b/drivers/input/serio/userio.c | |||
| @@ -0,0 +1,285 @@ | |||
| 1 | /* | ||
| 2 | * userio kernel serio device emulation module | ||
| 3 | * Copyright (C) 2015 Red Hat | ||
| 4 | * Copyright (C) 2015 Stephen Chandler Paul <thatslyude@gmail.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU Lesser General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License, or (at | ||
| 9 | * your option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but | ||
| 12 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | ||
| 14 | * General Public License for more details. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/circ_buf.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/kernel.h> | ||
| 22 | #include <linux/serio.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/fs.h> | ||
| 25 | #include <linux/miscdevice.h> | ||
| 26 | #include <linux/sched.h> | ||
| 27 | #include <linux/poll.h> | ||
| 28 | #include <uapi/linux/userio.h> | ||
| 29 | |||
| 30 | #define USERIO_NAME "userio" | ||
| 31 | #define USERIO_BUFSIZE 16 | ||
| 32 | |||
| 33 | static struct miscdevice userio_misc; | ||
| 34 | |||
| 35 | struct userio_device { | ||
| 36 | struct serio *serio; | ||
| 37 | struct mutex mutex; | ||
| 38 | |||
| 39 | bool running; | ||
| 40 | |||
| 41 | u8 head; | ||
| 42 | u8 tail; | ||
| 43 | |||
| 44 | spinlock_t buf_lock; | ||
| 45 | unsigned char buf[USERIO_BUFSIZE]; | ||
| 46 | |||
| 47 | wait_queue_head_t waitq; | ||
| 48 | }; | ||
| 49 | |||
| 50 | /** | ||
| 51 | * userio_device_write - Write data from serio to a userio device in userspace | ||
| 52 | * @id: The serio port for the userio device | ||
| 53 | * @val: The data to write to the device | ||
| 54 | */ | ||
| 55 | static int userio_device_write(struct serio *id, unsigned char val) | ||
| 56 | { | ||
| 57 | struct userio_device *userio = id->port_data; | ||
| 58 | unsigned long flags; | ||
| 59 | |||
| 60 | spin_lock_irqsave(&userio->buf_lock, flags); | ||
| 61 | |||
| 62 | userio->buf[userio->head] = val; | ||
| 63 | userio->head = (userio->head + 1) % USERIO_BUFSIZE; | ||
| 64 | |||
| 65 | if (userio->head == userio->tail) | ||
| 66 | dev_warn(userio_misc.this_device, | ||
| 67 | "Buffer overflowed, userio client isn't keeping up"); | ||
| 68 | |||
| 69 | spin_unlock_irqrestore(&userio->buf_lock, flags); | ||
| 70 | |||
| 71 | wake_up_interruptible(&userio->waitq); | ||
| 72 | |||
| 73 | return 0; | ||
| 74 | } | ||
| 75 | |||
| 76 | static int userio_char_open(struct inode *inode, struct file *file) | ||
| 77 | { | ||
| 78 | struct userio_device *userio; | ||
| 79 | |||
| 80 | userio = kzalloc(sizeof(struct userio_device), GFP_KERNEL); | ||
| 81 | if (!userio) | ||
| 82 | return -ENOMEM; | ||
| 83 | |||
| 84 | mutex_init(&userio->mutex); | ||
| 85 | spin_lock_init(&userio->buf_lock); | ||
| 86 | init_waitqueue_head(&userio->waitq); | ||
| 87 | |||
| 88 | userio->serio = kzalloc(sizeof(struct serio), GFP_KERNEL); | ||
| 89 | if (!userio->serio) { | ||
| 90 | kfree(userio); | ||
| 91 | return -ENOMEM; | ||
| 92 | } | ||
| 93 | |||
| 94 | userio->serio->write = userio_device_write; | ||
| 95 | userio->serio->port_data = userio; | ||
| 96 | |||
| 97 | file->private_data = userio; | ||
| 98 | |||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | |||
| 102 | static int userio_char_release(struct inode *inode, struct file *file) | ||
| 103 | { | ||
| 104 | struct userio_device *userio = file->private_data; | ||
| 105 | |||
| 106 | if (userio->running) { | ||
| 107 | /* | ||
| 108 | * Don't free the serio port here, serio_unregister_port() | ||
| 109 | * does it for us. | ||
| 110 | */ | ||
| 111 | serio_unregister_port(userio->serio); | ||
| 112 | } else { | ||
| 113 | kfree(userio->serio); | ||
| 114 | } | ||
| 115 | |||
| 116 | kfree(userio); | ||
| 117 | |||
| 118 | return 0; | ||
| 119 | } | ||
| 120 | |||
| 121 | static ssize_t userio_char_read(struct file *file, char __user *user_buffer, | ||
| 122 | size_t count, loff_t *ppos) | ||
| 123 | { | ||
| 124 | struct userio_device *userio = file->private_data; | ||
| 125 | int error; | ||
| 126 | size_t nonwrap_len, copylen; | ||
| 127 | unsigned char buf[USERIO_BUFSIZE]; | ||
| 128 | unsigned long flags; | ||
| 129 | |||
| 130 | /* | ||
| 131 | * By the time we get here, the data that was waiting might have | ||
| 132 | * been taken by another thread. Grab the buffer lock and check if | ||
| 133 | * there's still any data waiting, otherwise repeat this process | ||
| 134 | * until we have data (unless the file descriptor is non-blocking | ||
| 135 | * of course). | ||
| 136 | */ | ||
| 137 | for (;;) { | ||
| 138 | spin_lock_irqsave(&userio->buf_lock, flags); | ||
| 139 | |||
| 140 | nonwrap_len = CIRC_CNT_TO_END(userio->head, | ||
| 141 | userio->tail, | ||
| 142 | USERIO_BUFSIZE); | ||
| 143 | copylen = min(nonwrap_len, count); | ||
| 144 | if (copylen) { | ||
| 145 | memcpy(buf, &userio->buf[userio->tail], copylen); | ||
| 146 | userio->tail = (userio->tail + copylen) % | ||
| 147 | USERIO_BUFSIZE; | ||
| 148 | } | ||
| 149 | |||
| 150 | spin_unlock_irqrestore(&userio->buf_lock, flags); | ||
| 151 | |||
| 152 | if (nonwrap_len) | ||
| 153 | break; | ||
| 154 | |||
| 155 | /* buffer was/is empty */ | ||
| 156 | if (file->f_flags & O_NONBLOCK) | ||
| 157 | return -EAGAIN; | ||
| 158 | |||
| 159 | /* | ||
| 160 | * count == 0 is special - no IO is done but we check | ||
| 161 | * for error conditions (see above). | ||
| 162 | */ | ||
| 163 | if (count == 0) | ||
| 164 | return 0; | ||
| 165 | |||
| 166 | error = wait_event_interruptible(userio->waitq, | ||
| 167 | userio->head != userio->tail); | ||
| 168 | if (error) | ||
| 169 | return error; | ||
| 170 | } | ||
| 171 | |||
| 172 | if (copylen) | ||
| 173 | if (copy_to_user(user_buffer, buf, copylen)) | ||
| 174 | return -EFAULT; | ||
| 175 | |||
| 176 | return copylen; | ||
| 177 | } | ||
| 178 | |||
| 179 | static ssize_t userio_char_write(struct file *file, const char __user *buffer, | ||
| 180 | size_t count, loff_t *ppos) | ||
| 181 | { | ||
| 182 | struct userio_device *userio = file->private_data; | ||
| 183 | struct userio_cmd cmd; | ||
| 184 | int error; | ||
| 185 | |||
| 186 | if (count != sizeof(cmd)) { | ||
| 187 | dev_warn(userio_misc.this_device, "Invalid payload size\n"); | ||
| 188 | return -EINVAL; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (copy_from_user(&cmd, buffer, sizeof(cmd))) | ||
| 192 | return -EFAULT; | ||
| 193 | |||
| 194 | error = mutex_lock_interruptible(&userio->mutex); | ||
| 195 | if (error) | ||
| 196 | return error; | ||
| 197 | |||
| 198 | switch (cmd.type) { | ||
| 199 | case USERIO_CMD_REGISTER: | ||
| 200 | if (!userio->serio->id.type) { | ||
| 201 | dev_warn(userio_misc.this_device, | ||
| 202 | "No port type given on /dev/userio\n"); | ||
| 203 | |||
| 204 | error = -EINVAL; | ||
| 205 | goto out; | ||
| 206 | } | ||
| 207 | |||
| 208 | if (userio->running) { | ||
| 209 | dev_warn(userio_misc.this_device, | ||
| 210 | "Begin command sent, but we're already running\n"); | ||
| 211 | error = -EBUSY; | ||
| 212 | goto out; | ||
| 213 | } | ||
| 214 | |||
| 215 | userio->running = true; | ||
| 216 | serio_register_port(userio->serio); | ||
| 217 | break; | ||
| 218 | |||
| 219 | case USERIO_CMD_SET_PORT_TYPE: | ||
| 220 | if (userio->running) { | ||
| 221 | dev_warn(userio_misc.this_device, | ||
| 222 | "Can't change port type on an already running userio instance\n"); | ||
| 223 | error = -EBUSY; | ||
| 224 | goto out; | ||
| 225 | } | ||
| 226 | |||
| 227 | userio->serio->id.type = cmd.data; | ||
| 228 | break; | ||
| 229 | |||
| 230 | case USERIO_CMD_SEND_INTERRUPT: | ||
| 231 | if (!userio->running) { | ||
| 232 | dev_warn(userio_misc.this_device, | ||
| 233 | "The device must be registered before sending interrupts\n"); | ||
| 234 | error = -ENODEV; | ||
| 235 | goto out; | ||
| 236 | } | ||
| 237 | |||
| 238 | serio_interrupt(userio->serio, cmd.data, 0); | ||
| 239 | break; | ||
| 240 | |||
| 241 | default: | ||
| 242 | error = -EOPNOTSUPP; | ||
| 243 | goto out; | ||
| 244 | } | ||
| 245 | |||
| 246 | out: | ||
| 247 | mutex_unlock(&userio->mutex); | ||
| 248 | return error ?: count; | ||
| 249 | } | ||
| 250 | |||
| 251 | static unsigned int userio_char_poll(struct file *file, poll_table *wait) | ||
| 252 | { | ||
| 253 | struct userio_device *userio = file->private_data; | ||
| 254 | |||
| 255 | poll_wait(file, &userio->waitq, wait); | ||
| 256 | |||
| 257 | if (userio->head != userio->tail) | ||
| 258 | return POLLIN | POLLRDNORM; | ||
| 259 | |||
| 260 | return 0; | ||
| 261 | } | ||
| 262 | |||
| 263 | static const struct file_operations userio_fops = { | ||
| 264 | .owner = THIS_MODULE, | ||
| 265 | .open = userio_char_open, | ||
| 266 | .release = userio_char_release, | ||
| 267 | .read = userio_char_read, | ||
| 268 | .write = userio_char_write, | ||
| 269 | .poll = userio_char_poll, | ||
| 270 | .llseek = no_llseek, | ||
| 271 | }; | ||
| 272 | |||
| 273 | static struct miscdevice userio_misc = { | ||
| 274 | .fops = &userio_fops, | ||
| 275 | .minor = USERIO_MINOR, | ||
| 276 | .name = USERIO_NAME, | ||
| 277 | }; | ||
| 278 | module_driver(userio_misc, misc_register, misc_deregister); | ||
| 279 | |||
| 280 | MODULE_ALIAS_MISCDEV(USERIO_MINOR); | ||
| 281 | MODULE_ALIAS("devname:" USERIO_NAME); | ||
| 282 | |||
| 283 | MODULE_AUTHOR("Stephen Chandler Paul <thatslyude@gmail.com>"); | ||
| 284 | MODULE_DESCRIPTION("Virtual Serio Device Support"); | ||
| 285 | MODULE_LICENSE("GPL"); | ||
diff --git a/include/linux/miscdevice.h b/include/linux/miscdevice.h index 81f6e427ba6b..543037465973 100644 --- a/include/linux/miscdevice.h +++ b/include/linux/miscdevice.h | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #define LOOP_CTRL_MINOR 237 | 49 | #define LOOP_CTRL_MINOR 237 |
| 50 | #define VHOST_NET_MINOR 238 | 50 | #define VHOST_NET_MINOR 238 |
| 51 | #define UHID_MINOR 239 | 51 | #define UHID_MINOR 239 |
| 52 | #define USERIO_MINOR 240 | ||
| 52 | #define MISC_DYNAMIC_MINOR 255 | 53 | #define MISC_DYNAMIC_MINOR 255 |
| 53 | 54 | ||
| 54 | struct device; | 55 | struct device; |
diff --git a/include/uapi/linux/userio.h b/include/uapi/linux/userio.h new file mode 100644 index 000000000000..37d147f0a13a --- /dev/null +++ b/include/uapi/linux/userio.h | |||
| @@ -0,0 +1,44 @@ | |||
| 1 | /* | ||
| 2 | * userio: virtual serio device support | ||
| 3 | * Copyright (C) 2015 Red Hat | ||
| 4 | * Copyright (C) 2015 Lyude (Stephen Chandler Paul) <cpaul@redhat.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify it | ||
| 7 | * under the terms of the GNU Lesser General Public License as published by the | ||
| 8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 9 | * option) any later version. | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
| 13 | * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more | ||
| 14 | * details. | ||
| 15 | * | ||
| 16 | * This is the public header used for user-space communication with the userio | ||
| 17 | * driver. __attribute__((__packed__)) is used for all structs to keep ABI | ||
| 18 | * compatibility between all architectures. | ||
| 19 | */ | ||
| 20 | |||
| 21 | #ifndef _USERIO_H | ||
| 22 | #define _USERIO_H | ||
| 23 | |||
| 24 | #include <linux/types.h> | ||
| 25 | |||
| 26 | enum userio_cmd_type { | ||
| 27 | USERIO_CMD_REGISTER = 0, | ||
| 28 | USERIO_CMD_SET_PORT_TYPE = 1, | ||
| 29 | USERIO_CMD_SEND_INTERRUPT = 2 | ||
| 30 | }; | ||
| 31 | |||
| 32 | /* | ||
| 33 | * userio Commands | ||
| 34 | * All commands sent to /dev/userio are encoded using this structure. The type | ||
| 35 | * field should contain a USERIO_CMD* value that indicates what kind of command | ||
| 36 | * is being sent to userio. The data field should contain the accompanying | ||
| 37 | * argument for the command, if there is one. | ||
| 38 | */ | ||
| 39 | struct userio_cmd { | ||
| 40 | __u8 type; | ||
| 41 | __u8 data; | ||
| 42 | } __attribute__((__packed__)); | ||
| 43 | |||
| 44 | #endif /* !_USERIO_H */ | ||
