userio.c (6678B)
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 33static struct miscdevice userio_misc; 34 35struct 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 */ 55static 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 76static 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 102static 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 121static 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 179static 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 246out: 247 mutex_unlock(&userio->mutex); 248 return error ?: count; 249} 250 251static __poll_t 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 EPOLLIN | EPOLLRDNORM; 259 260 return 0; 261} 262 263static 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 273static struct miscdevice userio_misc = { 274 .fops = &userio_fops, 275 .minor = USERIO_MINOR, 276 .name = USERIO_NAME, 277}; 278module_driver(userio_misc, misc_register, misc_deregister); 279 280MODULE_ALIAS_MISCDEV(USERIO_MINOR); 281MODULE_ALIAS("devname:" USERIO_NAME); 282 283MODULE_AUTHOR("Stephen Chandler Paul <thatslyude@gmail.com>"); 284MODULE_DESCRIPTION("Virtual Serio Device Support"); 285MODULE_LICENSE("GPL");