1/* 2 * Raw serio device providing access to a raw byte stream from underlying 3 * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device 4 * 5 * Copyright (c) 2004 Dmitry Torokhov 6 * 7 * This program is free software; you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License version 2 as published by 9 * the Free Software Foundation. 10 */ 11 12#include <linux/kref.h> 13#include <linux/sched.h> 14#include <linux/slab.h> 15#include <linux/poll.h> 16#include <linux/module.h> 17#include <linux/serio.h> 18#include <linux/major.h> 19#include <linux/device.h> 20#include <linux/miscdevice.h> 21#include <linux/wait.h> 22#include <linux/mutex.h> 23 24#define DRIVER_DESC "Raw serio driver" 25 26MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>"); 27MODULE_DESCRIPTION(DRIVER_DESC); 28MODULE_LICENSE("GPL"); 29 30#define SERIO_RAW_QUEUE_LEN 64 31struct serio_raw { 32 unsigned char queue[SERIO_RAW_QUEUE_LEN]; 33 unsigned int tail, head; 34 35 char name[16]; 36 struct kref kref; 37 struct serio *serio; 38 struct miscdevice dev; 39 wait_queue_head_t wait; 40 struct list_head client_list; 41 struct list_head node; 42 bool dead; 43}; 44 45struct serio_raw_client { 46 struct fasync_struct *fasync; 47 struct serio_raw *serio_raw; 48 struct list_head node; 49}; 50 51static DEFINE_MUTEX(serio_raw_mutex); 52static LIST_HEAD(serio_raw_list); 53 54/********************************************************************* 55 * Interface with userspace (file operations) * 56 *********************************************************************/ 57 58static int serio_raw_fasync(int fd, struct file *file, int on) 59{ 60 struct serio_raw_client *client = file->private_data; 61 62 return fasync_helper(fd, file, on, &client->fasync); 63} 64 65static struct serio_raw *serio_raw_locate(int minor) 66{ 67 struct serio_raw *serio_raw; 68 69 list_for_each_entry(serio_raw, &serio_raw_list, node) { 70 if (serio_raw->dev.minor == minor) 71 return serio_raw; 72 } 73 74 return NULL; 75} 76 77static int serio_raw_open(struct inode *inode, struct file *file) 78{ 79 struct serio_raw *serio_raw; 80 struct serio_raw_client *client; 81 int retval; 82 83 retval = mutex_lock_interruptible(&serio_raw_mutex); 84 if (retval) 85 return retval; 86 87 serio_raw = serio_raw_locate(iminor(inode)); 88 if (!serio_raw) { 89 retval = -ENODEV; 90 goto out; 91 } 92 93 if (serio_raw->dead) { 94 retval = -ENODEV; 95 goto out; 96 } 97 98 client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL); 99 if (!client) { 100 retval = -ENOMEM; 101 goto out; 102 } 103 104 client->serio_raw = serio_raw; 105 file->private_data = client; 106 107 kref_get(&serio_raw->kref); 108 109 serio_pause_rx(serio_raw->serio); 110 list_add_tail(&client->node, &serio_raw->client_list); 111 serio_continue_rx(serio_raw->serio); 112 113out: 114 mutex_unlock(&serio_raw_mutex); 115 return retval; 116} 117 118static void serio_raw_free(struct kref *kref) 119{ 120 struct serio_raw *serio_raw = 121 container_of(kref, struct serio_raw, kref); 122 123 put_device(&serio_raw->serio->dev); 124 kfree(serio_raw); 125} 126 127static int serio_raw_release(struct inode *inode, struct file *file) 128{ 129 struct serio_raw_client *client = file->private_data; 130 struct serio_raw *serio_raw = client->serio_raw; 131 132 serio_pause_rx(serio_raw->serio); 133 list_del(&client->node); 134 serio_continue_rx(serio_raw->serio); 135 136 kfree(client); 137 138 kref_put(&serio_raw->kref, serio_raw_free); 139 140 return 0; 141} 142 143static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c) 144{ 145 bool empty; 146 147 serio_pause_rx(serio_raw->serio); 148 149 empty = serio_raw->head == serio_raw->tail; 150 if (!empty) { 151 *c = serio_raw->queue[serio_raw->tail]; 152 serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN; 153 } 154 155 serio_continue_rx(serio_raw->serio); 156 157 return !empty; 158} 159 160static ssize_t serio_raw_read(struct file *file, char __user *buffer, 161 size_t count, loff_t *ppos) 162{ 163 struct serio_raw_client *client = file->private_data; 164 struct serio_raw *serio_raw = client->serio_raw; 165 char uninitialized_var(c); 166 ssize_t read = 0; 167 int error; 168 169 for (;;) { 170 if (serio_raw->dead) 171 return -ENODEV; 172 173 if (serio_raw->head == serio_raw->tail && 174 (file->f_flags & O_NONBLOCK)) 175 return -EAGAIN; 176 177 if (count == 0) 178 break; 179 180 while (read < count && serio_raw_fetch_byte(serio_raw, &c)) { 181 if (put_user(c, buffer++)) 182 return -EFAULT; 183 read++; 184 } 185 186 if (read) 187 break; 188 189 if (!(file->f_flags & O_NONBLOCK)) { 190 error = wait_event_interruptible(serio_raw->wait, 191 serio_raw->head != serio_raw->tail || 192 serio_raw->dead); 193 if (error) 194 return error; 195 } 196 } 197 198 return read; 199} 200 201static ssize_t serio_raw_write(struct file *file, const char __user *buffer, 202 size_t count, loff_t *ppos) 203{ 204 struct serio_raw_client *client = file->private_data; 205 struct serio_raw *serio_raw = client->serio_raw; 206 int retval = 0; 207 unsigned char c; 208 209 retval = mutex_lock_interruptible(&serio_raw_mutex); 210 if (retval) 211 return retval; 212 213 if (serio_raw->dead) { 214 retval = -ENODEV; 215 goto out; 216 } 217 218 if (count > 32) 219 count = 32; 220 221 while (count--) { 222 if (get_user(c, buffer++)) { 223 retval = -EFAULT; 224 goto out; 225 } 226 227 if (serio_write(serio_raw->serio, c)) { 228 /* Either signal error or partial write */ 229 if (retval == 0) 230 retval = -EIO; 231 goto out; 232 } 233 234 retval++; 235 } 236 237out: 238 mutex_unlock(&serio_raw_mutex); 239 return retval; 240} 241 242static unsigned int serio_raw_poll(struct file *file, poll_table *wait) 243{ 244 struct serio_raw_client *client = file->private_data; 245 struct serio_raw *serio_raw = client->serio_raw; 246 unsigned int mask; 247 248 poll_wait(file, &serio_raw->wait, wait); 249 250 mask = serio_raw->dead ? POLLHUP | POLLERR : POLLOUT | POLLWRNORM; 251 if (serio_raw->head != serio_raw->tail) 252 mask |= POLLIN | POLLRDNORM; 253 254 return mask; 255} 256 257static const struct file_operations serio_raw_fops = { 258 .owner = THIS_MODULE, 259 .open = serio_raw_open, 260 .release = serio_raw_release, 261 .read = serio_raw_read, 262 .write = serio_raw_write, 263 .poll = serio_raw_poll, 264 .fasync = serio_raw_fasync, 265 .llseek = noop_llseek, 266}; 267 268 269/********************************************************************* 270 * Interface with serio port * 271 *********************************************************************/ 272 273static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data, 274 unsigned int dfl) 275{ 276 struct serio_raw *serio_raw = serio_get_drvdata(serio); 277 struct serio_raw_client *client; 278 unsigned int head = serio_raw->head; 279 280 /* we are holding serio->lock here so we are protected */ 281 serio_raw->queue[head] = data; 282 head = (head + 1) % SERIO_RAW_QUEUE_LEN; 283 if (likely(head != serio_raw->tail)) { 284 serio_raw->head = head; 285 list_for_each_entry(client, &serio_raw->client_list, node) 286 kill_fasync(&client->fasync, SIGIO, POLL_IN); 287 wake_up_interruptible(&serio_raw->wait); 288 } 289 290 return IRQ_HANDLED; 291} 292 293static int serio_raw_connect(struct serio *serio, struct serio_driver *drv) 294{ 295 static atomic_t serio_raw_no = ATOMIC_INIT(-1); 296 struct serio_raw *serio_raw; 297 int err; 298 299 serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL); 300 if (!serio_raw) { 301 dev_dbg(&serio->dev, "can't allocate memory for a device\n"); 302 return -ENOMEM; 303 } 304 305 snprintf(serio_raw->name, sizeof(serio_raw->name), 306 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no)); 307 kref_init(&serio_raw->kref); 308 INIT_LIST_HEAD(&serio_raw->client_list); 309 init_waitqueue_head(&serio_raw->wait); 310 311 serio_raw->serio = serio; 312 get_device(&serio->dev); 313 314 serio_set_drvdata(serio, serio_raw); 315 316 err = serio_open(serio, drv); 317 if (err) 318 goto err_free; 319 320 err = mutex_lock_killable(&serio_raw_mutex); 321 if (err) 322 goto err_close; 323 324 list_add_tail(&serio_raw->node, &serio_raw_list); 325 mutex_unlock(&serio_raw_mutex); 326 327 serio_raw->dev.minor = PSMOUSE_MINOR; 328 serio_raw->dev.name = serio_raw->name; 329 serio_raw->dev.parent = &serio->dev; 330 serio_raw->dev.fops = &serio_raw_fops; 331 332 err = misc_register(&serio_raw->dev); 333 if (err) { 334 serio_raw->dev.minor = MISC_DYNAMIC_MINOR; 335 err = misc_register(&serio_raw->dev); 336 } 337 338 if (err) { 339 dev_err(&serio->dev, 340 "failed to register raw access device for %s\n", 341 serio->phys); 342 goto err_unlink; 343 } 344 345 dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n", 346 serio->phys, serio_raw->name, serio_raw->dev.minor); 347 return 0; 348 349err_unlink: 350 list_del_init(&serio_raw->node); 351err_close: 352 serio_close(serio); 353err_free: 354 serio_set_drvdata(serio, NULL); 355 kref_put(&serio_raw->kref, serio_raw_free); 356 return err; 357} 358 359static int serio_raw_reconnect(struct serio *serio) 360{ 361 struct serio_raw *serio_raw = serio_get_drvdata(serio); 362 struct serio_driver *drv = serio->drv; 363 364 if (!drv || !serio_raw) { 365 dev_dbg(&serio->dev, 366 "reconnect request, but serio is disconnected, ignoring...\n"); 367 return -1; 368 } 369 370 /* 371 * Nothing needs to be done here, we just need this method to 372 * keep the same device. 373 */ 374 return 0; 375} 376 377/* 378 * Wake up users waiting for IO so they can disconnect from 379 * dead device. 380 */ 381static void serio_raw_hangup(struct serio_raw *serio_raw) 382{ 383 struct serio_raw_client *client; 384 385 serio_pause_rx(serio_raw->serio); 386 list_for_each_entry(client, &serio_raw->client_list, node) 387 kill_fasync(&client->fasync, SIGIO, POLL_HUP); 388 serio_continue_rx(serio_raw->serio); 389 390 wake_up_interruptible(&serio_raw->wait); 391} 392 393 394static void serio_raw_disconnect(struct serio *serio) 395{ 396 struct serio_raw *serio_raw = serio_get_drvdata(serio); 397 398 misc_deregister(&serio_raw->dev); 399 400 mutex_lock(&serio_raw_mutex); 401 serio_raw->dead = true; 402 list_del_init(&serio_raw->node); 403 mutex_unlock(&serio_raw_mutex); 404 405 serio_raw_hangup(serio_raw); 406 407 serio_close(serio); 408 kref_put(&serio_raw->kref, serio_raw_free); 409 410 serio_set_drvdata(serio, NULL); 411} 412 413static struct serio_device_id serio_raw_serio_ids[] = { 414 { 415 .type = SERIO_8042, 416 .proto = SERIO_ANY, 417 .id = SERIO_ANY, 418 .extra = SERIO_ANY, 419 }, 420 { 421 .type = SERIO_8042_XL, 422 .proto = SERIO_ANY, 423 .id = SERIO_ANY, 424 .extra = SERIO_ANY, 425 }, 426 { 0 } 427}; 428 429MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids); 430 431static struct serio_driver serio_raw_drv = { 432 .driver = { 433 .name = "serio_raw", 434 }, 435 .description = DRIVER_DESC, 436 .id_table = serio_raw_serio_ids, 437 .interrupt = serio_raw_interrupt, 438 .connect = serio_raw_connect, 439 .reconnect = serio_raw_reconnect, 440 .disconnect = serio_raw_disconnect, 441 .manual_bind = true, 442}; 443 444module_serio_driver(serio_raw_drv); 445