root/drivers/input/serio/userio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. userio_device_write
  2. userio_char_open
  3. userio_char_release
  4. userio_char_read
  5. userio_char_write
  6. userio_char_poll

   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 __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 
 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");

/* [<][>][^][v][top][bottom][index][help] */