linux/drivers/input/serio/userio.c
<<
>>
Prefs
   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");
 286