1/* 2 * comedi/comedi_fops.c 3 * comedi kernel module 4 * 5 * COMEDI - Linux Control and Measurement Device Interface 6 * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org> 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 20 21#include "comedi_compat32.h" 22 23#include <linux/module.h> 24#include <linux/errno.h> 25#include <linux/kernel.h> 26#include <linux/sched.h> 27#include <linux/fcntl.h> 28#include <linux/delay.h> 29#include <linux/mm.h> 30#include <linux/slab.h> 31#include <linux/kmod.h> 32#include <linux/poll.h> 33#include <linux/init.h> 34#include <linux/device.h> 35#include <linux/vmalloc.h> 36#include <linux/fs.h> 37#include "comedidev.h" 38#include <linux/cdev.h> 39#include <linux/stat.h> 40 41#include <linux/io.h> 42#include <linux/uaccess.h> 43 44#include "comedi_internal.h" 45 46/** 47 * struct comedi_file - per-file private data for comedi device 48 * @dev: comedi_device struct 49 * @read_subdev: current "read" subdevice 50 * @write_subdev: current "write" subdevice 51 * @last_detach_count: last known detach count 52 * @last_attached: last known attached/detached state 53 */ 54struct comedi_file { 55 struct comedi_device *dev; 56 struct comedi_subdevice *read_subdev; 57 struct comedi_subdevice *write_subdev; 58 unsigned int last_detach_count; 59 bool last_attached:1; 60}; 61 62#define COMEDI_NUM_MINORS 0x100 63#define COMEDI_NUM_SUBDEVICE_MINORS \ 64 (COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS) 65 66static int comedi_num_legacy_minors; 67module_param(comedi_num_legacy_minors, int, S_IRUGO); 68MODULE_PARM_DESC(comedi_num_legacy_minors, 69 "number of comedi minor devices to reserve for non-auto-configured devices (default 0)" 70 ); 71 72unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB; 73module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR); 74MODULE_PARM_DESC(comedi_default_buf_size_kb, 75 "default asynchronous buffer size in KiB (default " 76 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")"); 77 78unsigned int comedi_default_buf_maxsize_kb 79 = CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB; 80module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR); 81MODULE_PARM_DESC(comedi_default_buf_maxsize_kb, 82 "default maximum size of asynchronous buffer in KiB (default " 83 __MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")"); 84 85static DEFINE_MUTEX(comedi_board_minor_table_lock); 86static struct comedi_device 87*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS]; 88 89static DEFINE_MUTEX(comedi_subdevice_minor_table_lock); 90/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */ 91static struct comedi_subdevice 92*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS]; 93 94static struct class *comedi_class; 95static struct cdev comedi_cdev; 96 97static void comedi_device_init(struct comedi_device *dev) 98{ 99 kref_init(&dev->refcount); 100 spin_lock_init(&dev->spinlock); 101 mutex_init(&dev->mutex); 102 init_rwsem(&dev->attach_lock); 103 dev->minor = -1; 104} 105 106static void comedi_dev_kref_release(struct kref *kref) 107{ 108 struct comedi_device *dev = 109 container_of(kref, struct comedi_device, refcount); 110 111 mutex_destroy(&dev->mutex); 112 put_device(dev->class_dev); 113 kfree(dev); 114} 115 116/** 117 * comedi_dev_put - release a use of a comedi device structure 118 * @dev: comedi_device struct 119 * 120 * Must be called when a user of a comedi device is finished with it. 121 * When the last user of the comedi device calls this function, the 122 * comedi device is destroyed. 123 * 124 * Return 1 if the comedi device is destroyed by this call or dev is 125 * NULL, otherwise return 0. Callers must not assume the comedi 126 * device is still valid if this function returns 0. 127 */ 128int comedi_dev_put(struct comedi_device *dev) 129{ 130 if (dev) 131 return kref_put(&dev->refcount, comedi_dev_kref_release); 132 return 1; 133} 134EXPORT_SYMBOL_GPL(comedi_dev_put); 135 136static struct comedi_device *comedi_dev_get(struct comedi_device *dev) 137{ 138 if (dev) 139 kref_get(&dev->refcount); 140 return dev; 141} 142 143static void comedi_device_cleanup(struct comedi_device *dev) 144{ 145 struct module *driver_module = NULL; 146 147 if (!dev) 148 return; 149 mutex_lock(&dev->mutex); 150 if (dev->attached) 151 driver_module = dev->driver->module; 152 comedi_device_detach(dev); 153 if (driver_module && dev->use_count) 154 module_put(driver_module); 155 mutex_unlock(&dev->mutex); 156} 157 158static bool comedi_clear_board_dev(struct comedi_device *dev) 159{ 160 unsigned int i = dev->minor; 161 bool cleared = false; 162 163 mutex_lock(&comedi_board_minor_table_lock); 164 if (dev == comedi_board_minor_table[i]) { 165 comedi_board_minor_table[i] = NULL; 166 cleared = true; 167 } 168 mutex_unlock(&comedi_board_minor_table_lock); 169 return cleared; 170} 171 172static struct comedi_device *comedi_clear_board_minor(unsigned minor) 173{ 174 struct comedi_device *dev; 175 176 mutex_lock(&comedi_board_minor_table_lock); 177 dev = comedi_board_minor_table[minor]; 178 comedi_board_minor_table[minor] = NULL; 179 mutex_unlock(&comedi_board_minor_table_lock); 180 return dev; 181} 182 183static void comedi_free_board_dev(struct comedi_device *dev) 184{ 185 if (dev) { 186 comedi_device_cleanup(dev); 187 if (dev->class_dev) { 188 device_destroy(comedi_class, 189 MKDEV(COMEDI_MAJOR, dev->minor)); 190 } 191 comedi_dev_put(dev); 192 } 193} 194 195static struct comedi_subdevice 196*comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned minor) 197{ 198 struct comedi_subdevice *s; 199 unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; 200 201 BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); 202 mutex_lock(&comedi_subdevice_minor_table_lock); 203 s = comedi_subdevice_minor_table[i]; 204 if (s && s->device != dev) 205 s = NULL; 206 mutex_unlock(&comedi_subdevice_minor_table_lock); 207 return s; 208} 209 210static struct comedi_device *comedi_dev_get_from_board_minor(unsigned minor) 211{ 212 struct comedi_device *dev; 213 214 BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); 215 mutex_lock(&comedi_board_minor_table_lock); 216 dev = comedi_dev_get(comedi_board_minor_table[minor]); 217 mutex_unlock(&comedi_board_minor_table_lock); 218 return dev; 219} 220 221static struct comedi_device *comedi_dev_get_from_subdevice_minor(unsigned minor) 222{ 223 struct comedi_device *dev; 224 struct comedi_subdevice *s; 225 unsigned int i = minor - COMEDI_NUM_BOARD_MINORS; 226 227 BUG_ON(i >= COMEDI_NUM_SUBDEVICE_MINORS); 228 mutex_lock(&comedi_subdevice_minor_table_lock); 229 s = comedi_subdevice_minor_table[i]; 230 dev = comedi_dev_get(s ? s->device : NULL); 231 mutex_unlock(&comedi_subdevice_minor_table_lock); 232 return dev; 233} 234 235/** 236 * comedi_dev_get_from_minor - get comedi device by minor device number 237 * @minor: minor device number 238 * 239 * Finds the comedi device associated by the minor device number, if any, 240 * and increments its reference count. The comedi device is prevented from 241 * being freed until a matching call is made to comedi_dev_put(). 242 * 243 * Return a pointer to the comedi device if it exists, with its usage 244 * reference incremented. Return NULL if no comedi device exists with the 245 * specified minor device number. 246 */ 247struct comedi_device *comedi_dev_get_from_minor(unsigned minor) 248{ 249 if (minor < COMEDI_NUM_BOARD_MINORS) 250 return comedi_dev_get_from_board_minor(minor); 251 252 return comedi_dev_get_from_subdevice_minor(minor); 253} 254EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor); 255 256static struct comedi_subdevice * 257comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor) 258{ 259 struct comedi_subdevice *s; 260 261 if (minor >= COMEDI_NUM_BOARD_MINORS) { 262 s = comedi_subdevice_from_minor(dev, minor); 263 if (!s || (s->subdev_flags & SDF_CMD_READ)) 264 return s; 265 } 266 return dev->read_subdev; 267} 268 269static struct comedi_subdevice * 270comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor) 271{ 272 struct comedi_subdevice *s; 273 274 if (minor >= COMEDI_NUM_BOARD_MINORS) { 275 s = comedi_subdevice_from_minor(dev, minor); 276 if (!s || (s->subdev_flags & SDF_CMD_WRITE)) 277 return s; 278 } 279 return dev->write_subdev; 280} 281 282static void comedi_file_reset(struct file *file) 283{ 284 struct comedi_file *cfp = file->private_data; 285 struct comedi_device *dev = cfp->dev; 286 struct comedi_subdevice *s, *read_s, *write_s; 287 unsigned int minor = iminor(file_inode(file)); 288 289 read_s = dev->read_subdev; 290 write_s = dev->write_subdev; 291 if (minor >= COMEDI_NUM_BOARD_MINORS) { 292 s = comedi_subdevice_from_minor(dev, minor); 293 if (!s || s->subdev_flags & SDF_CMD_READ) 294 read_s = s; 295 if (!s || s->subdev_flags & SDF_CMD_WRITE) 296 write_s = s; 297 } 298 cfp->last_attached = dev->attached; 299 cfp->last_detach_count = dev->detach_count; 300 ACCESS_ONCE(cfp->read_subdev) = read_s; 301 ACCESS_ONCE(cfp->write_subdev) = write_s; 302} 303 304static void comedi_file_check(struct file *file) 305{ 306 struct comedi_file *cfp = file->private_data; 307 struct comedi_device *dev = cfp->dev; 308 309 if (cfp->last_attached != dev->attached || 310 cfp->last_detach_count != dev->detach_count) 311 comedi_file_reset(file); 312} 313 314static struct comedi_subdevice *comedi_file_read_subdevice(struct file *file) 315{ 316 struct comedi_file *cfp = file->private_data; 317 318 comedi_file_check(file); 319 return ACCESS_ONCE(cfp->read_subdev); 320} 321 322static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file) 323{ 324 struct comedi_file *cfp = file->private_data; 325 326 comedi_file_check(file); 327 return ACCESS_ONCE(cfp->write_subdev); 328} 329 330static int resize_async_buffer(struct comedi_device *dev, 331 struct comedi_subdevice *s, unsigned new_size) 332{ 333 struct comedi_async *async = s->async; 334 int retval; 335 336 if (new_size > async->max_bufsize) 337 return -EPERM; 338 339 if (s->busy) { 340 dev_dbg(dev->class_dev, 341 "subdevice is busy, cannot resize buffer\n"); 342 return -EBUSY; 343 } 344 if (comedi_buf_is_mmapped(s)) { 345 dev_dbg(dev->class_dev, 346 "subdevice is mmapped, cannot resize buffer\n"); 347 return -EBUSY; 348 } 349 350 /* make sure buffer is an integral number of pages (we round up) */ 351 new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK; 352 353 retval = comedi_buf_alloc(dev, s, new_size); 354 if (retval < 0) 355 return retval; 356 357 if (s->buf_change) { 358 retval = s->buf_change(dev, s); 359 if (retval < 0) 360 return retval; 361 } 362 363 dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n", 364 s->index, async->prealloc_bufsz); 365 return 0; 366} 367 368/* sysfs attribute files */ 369 370static ssize_t max_read_buffer_kb_show(struct device *csdev, 371 struct device_attribute *attr, char *buf) 372{ 373 unsigned int minor = MINOR(csdev->devt); 374 struct comedi_device *dev; 375 struct comedi_subdevice *s; 376 unsigned int size = 0; 377 378 dev = comedi_dev_get_from_minor(minor); 379 if (!dev) 380 return -ENODEV; 381 382 mutex_lock(&dev->mutex); 383 s = comedi_read_subdevice(dev, minor); 384 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) 385 size = s->async->max_bufsize / 1024; 386 mutex_unlock(&dev->mutex); 387 388 comedi_dev_put(dev); 389 return snprintf(buf, PAGE_SIZE, "%u\n", size); 390} 391 392static ssize_t max_read_buffer_kb_store(struct device *csdev, 393 struct device_attribute *attr, 394 const char *buf, size_t count) 395{ 396 unsigned int minor = MINOR(csdev->devt); 397 struct comedi_device *dev; 398 struct comedi_subdevice *s; 399 unsigned int size; 400 int err; 401 402 err = kstrtouint(buf, 10, &size); 403 if (err) 404 return err; 405 if (size > (UINT_MAX / 1024)) 406 return -EINVAL; 407 size *= 1024; 408 409 dev = comedi_dev_get_from_minor(minor); 410 if (!dev) 411 return -ENODEV; 412 413 mutex_lock(&dev->mutex); 414 s = comedi_read_subdevice(dev, minor); 415 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) 416 s->async->max_bufsize = size; 417 else 418 err = -EINVAL; 419 mutex_unlock(&dev->mutex); 420 421 comedi_dev_put(dev); 422 return err ? err : count; 423} 424static DEVICE_ATTR_RW(max_read_buffer_kb); 425 426static ssize_t read_buffer_kb_show(struct device *csdev, 427 struct device_attribute *attr, char *buf) 428{ 429 unsigned int minor = MINOR(csdev->devt); 430 struct comedi_device *dev; 431 struct comedi_subdevice *s; 432 unsigned int size = 0; 433 434 dev = comedi_dev_get_from_minor(minor); 435 if (!dev) 436 return -ENODEV; 437 438 mutex_lock(&dev->mutex); 439 s = comedi_read_subdevice(dev, minor); 440 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) 441 size = s->async->prealloc_bufsz / 1024; 442 mutex_unlock(&dev->mutex); 443 444 comedi_dev_put(dev); 445 return snprintf(buf, PAGE_SIZE, "%u\n", size); 446} 447 448static ssize_t read_buffer_kb_store(struct device *csdev, 449 struct device_attribute *attr, 450 const char *buf, size_t count) 451{ 452 unsigned int minor = MINOR(csdev->devt); 453 struct comedi_device *dev; 454 struct comedi_subdevice *s; 455 unsigned int size; 456 int err; 457 458 err = kstrtouint(buf, 10, &size); 459 if (err) 460 return err; 461 if (size > (UINT_MAX / 1024)) 462 return -EINVAL; 463 size *= 1024; 464 465 dev = comedi_dev_get_from_minor(minor); 466 if (!dev) 467 return -ENODEV; 468 469 mutex_lock(&dev->mutex); 470 s = comedi_read_subdevice(dev, minor); 471 if (s && (s->subdev_flags & SDF_CMD_READ) && s->async) 472 err = resize_async_buffer(dev, s, size); 473 else 474 err = -EINVAL; 475 mutex_unlock(&dev->mutex); 476 477 comedi_dev_put(dev); 478 return err ? err : count; 479} 480static DEVICE_ATTR_RW(read_buffer_kb); 481 482static ssize_t max_write_buffer_kb_show(struct device *csdev, 483 struct device_attribute *attr, 484 char *buf) 485{ 486 unsigned int minor = MINOR(csdev->devt); 487 struct comedi_device *dev; 488 struct comedi_subdevice *s; 489 unsigned int size = 0; 490 491 dev = comedi_dev_get_from_minor(minor); 492 if (!dev) 493 return -ENODEV; 494 495 mutex_lock(&dev->mutex); 496 s = comedi_write_subdevice(dev, minor); 497 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) 498 size = s->async->max_bufsize / 1024; 499 mutex_unlock(&dev->mutex); 500 501 comedi_dev_put(dev); 502 return snprintf(buf, PAGE_SIZE, "%u\n", size); 503} 504 505static ssize_t max_write_buffer_kb_store(struct device *csdev, 506 struct device_attribute *attr, 507 const char *buf, size_t count) 508{ 509 unsigned int minor = MINOR(csdev->devt); 510 struct comedi_device *dev; 511 struct comedi_subdevice *s; 512 unsigned int size; 513 int err; 514 515 err = kstrtouint(buf, 10, &size); 516 if (err) 517 return err; 518 if (size > (UINT_MAX / 1024)) 519 return -EINVAL; 520 size *= 1024; 521 522 dev = comedi_dev_get_from_minor(minor); 523 if (!dev) 524 return -ENODEV; 525 526 mutex_lock(&dev->mutex); 527 s = comedi_write_subdevice(dev, minor); 528 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) 529 s->async->max_bufsize = size; 530 else 531 err = -EINVAL; 532 mutex_unlock(&dev->mutex); 533 534 comedi_dev_put(dev); 535 return err ? err : count; 536} 537static DEVICE_ATTR_RW(max_write_buffer_kb); 538 539static ssize_t write_buffer_kb_show(struct device *csdev, 540 struct device_attribute *attr, char *buf) 541{ 542 unsigned int minor = MINOR(csdev->devt); 543 struct comedi_device *dev; 544 struct comedi_subdevice *s; 545 unsigned int size = 0; 546 547 dev = comedi_dev_get_from_minor(minor); 548 if (!dev) 549 return -ENODEV; 550 551 mutex_lock(&dev->mutex); 552 s = comedi_write_subdevice(dev, minor); 553 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) 554 size = s->async->prealloc_bufsz / 1024; 555 mutex_unlock(&dev->mutex); 556 557 comedi_dev_put(dev); 558 return snprintf(buf, PAGE_SIZE, "%u\n", size); 559} 560 561static ssize_t write_buffer_kb_store(struct device *csdev, 562 struct device_attribute *attr, 563 const char *buf, size_t count) 564{ 565 unsigned int minor = MINOR(csdev->devt); 566 struct comedi_device *dev; 567 struct comedi_subdevice *s; 568 unsigned int size; 569 int err; 570 571 err = kstrtouint(buf, 10, &size); 572 if (err) 573 return err; 574 if (size > (UINT_MAX / 1024)) 575 return -EINVAL; 576 size *= 1024; 577 578 dev = comedi_dev_get_from_minor(minor); 579 if (!dev) 580 return -ENODEV; 581 582 mutex_lock(&dev->mutex); 583 s = comedi_write_subdevice(dev, minor); 584 if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async) 585 err = resize_async_buffer(dev, s, size); 586 else 587 err = -EINVAL; 588 mutex_unlock(&dev->mutex); 589 590 comedi_dev_put(dev); 591 return err ? err : count; 592} 593static DEVICE_ATTR_RW(write_buffer_kb); 594 595static struct attribute *comedi_dev_attrs[] = { 596 &dev_attr_max_read_buffer_kb.attr, 597 &dev_attr_read_buffer_kb.attr, 598 &dev_attr_max_write_buffer_kb.attr, 599 &dev_attr_write_buffer_kb.attr, 600 NULL, 601}; 602ATTRIBUTE_GROUPS(comedi_dev); 603 604static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s, 605 unsigned bits) 606{ 607 s->runflags &= ~bits; 608} 609 610static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s, 611 unsigned bits) 612{ 613 s->runflags |= bits; 614} 615 616static void comedi_update_subdevice_runflags(struct comedi_subdevice *s, 617 unsigned mask, unsigned bits) 618{ 619 unsigned long flags; 620 621 spin_lock_irqsave(&s->spin_lock, flags); 622 __comedi_clear_subdevice_runflags(s, mask); 623 __comedi_set_subdevice_runflags(s, bits & mask); 624 spin_unlock_irqrestore(&s->spin_lock, flags); 625} 626 627static unsigned __comedi_get_subdevice_runflags(struct comedi_subdevice *s) 628{ 629 return s->runflags; 630} 631 632static unsigned comedi_get_subdevice_runflags(struct comedi_subdevice *s) 633{ 634 unsigned long flags; 635 unsigned runflags; 636 637 spin_lock_irqsave(&s->spin_lock, flags); 638 runflags = __comedi_get_subdevice_runflags(s); 639 spin_unlock_irqrestore(&s->spin_lock, flags); 640 return runflags; 641} 642 643static bool comedi_is_runflags_running(unsigned runflags) 644{ 645 return runflags & COMEDI_SRF_RUNNING; 646} 647 648static bool comedi_is_runflags_in_error(unsigned runflags) 649{ 650 return runflags & COMEDI_SRF_ERROR; 651} 652 653/** 654 * comedi_is_subdevice_running - check if async command running on subdevice 655 * @s: comedi_subdevice struct 656 * 657 * Return true if an asynchronous comedi command is active on the comedi 658 * subdevice, else return false. 659 */ 660bool comedi_is_subdevice_running(struct comedi_subdevice *s) 661{ 662 unsigned runflags = comedi_get_subdevice_runflags(s); 663 664 return comedi_is_runflags_running(runflags); 665} 666EXPORT_SYMBOL_GPL(comedi_is_subdevice_running); 667 668static bool __comedi_is_subdevice_running(struct comedi_subdevice *s) 669{ 670 unsigned runflags = __comedi_get_subdevice_runflags(s); 671 672 return comedi_is_runflags_running(runflags); 673} 674 675static bool comedi_is_subdevice_idle(struct comedi_subdevice *s) 676{ 677 unsigned runflags = comedi_get_subdevice_runflags(s); 678 679 return !(runflags & COMEDI_SRF_BUSY_MASK); 680} 681 682/** 683 * comedi_alloc_spriv() - Allocate memory for the subdevice private data. 684 * @s: comedi_subdevice struct 685 * @size: size of the memory to allocate 686 * 687 * This also sets the subdevice runflags to allow the core to automatically 688 * free the private data during the detach. 689 */ 690void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size) 691{ 692 s->private = kzalloc(size, GFP_KERNEL); 693 if (s->private) 694 s->runflags |= COMEDI_SRF_FREE_SPRIV; 695 return s->private; 696} 697EXPORT_SYMBOL_GPL(comedi_alloc_spriv); 698 699/* 700 * This function restores a subdevice to an idle state. 701 */ 702static void do_become_nonbusy(struct comedi_device *dev, 703 struct comedi_subdevice *s) 704{ 705 struct comedi_async *async = s->async; 706 707 comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0); 708 if (async) { 709 comedi_buf_reset(s); 710 async->inttrig = NULL; 711 kfree(async->cmd.chanlist); 712 async->cmd.chanlist = NULL; 713 s->busy = NULL; 714 wake_up_interruptible_all(&async->wait_head); 715 } else { 716 dev_err(dev->class_dev, 717 "BUG: (?) do_become_nonbusy called with async=NULL\n"); 718 s->busy = NULL; 719 } 720} 721 722static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 723{ 724 int ret = 0; 725 726 if (comedi_is_subdevice_running(s) && s->cancel) 727 ret = s->cancel(dev, s); 728 729 do_become_nonbusy(dev, s); 730 731 return ret; 732} 733 734void comedi_device_cancel_all(struct comedi_device *dev) 735{ 736 struct comedi_subdevice *s; 737 int i; 738 739 if (!dev->attached) 740 return; 741 742 for (i = 0; i < dev->n_subdevices; i++) { 743 s = &dev->subdevices[i]; 744 if (s->async) 745 do_cancel(dev, s); 746 } 747} 748 749static int is_device_busy(struct comedi_device *dev) 750{ 751 struct comedi_subdevice *s; 752 int i; 753 754 if (!dev->attached) 755 return 0; 756 757 for (i = 0; i < dev->n_subdevices; i++) { 758 s = &dev->subdevices[i]; 759 if (s->busy) 760 return 1; 761 if (s->async && comedi_buf_is_mmapped(s)) 762 return 1; 763 } 764 765 return 0; 766} 767 768/* 769 * COMEDI_DEVCONFIG ioctl 770 * attaches (and configures) or detaches a legacy device 771 * 772 * arg: 773 * pointer to comedi_devconfig structure (NULL if detaching) 774 * 775 * reads: 776 * comedi_devconfig structure (if attaching) 777 * 778 * writes: 779 * nothing 780 */ 781static int do_devconfig_ioctl(struct comedi_device *dev, 782 struct comedi_devconfig __user *arg) 783{ 784 struct comedi_devconfig it; 785 786 if (!capable(CAP_SYS_ADMIN)) 787 return -EPERM; 788 789 if (!arg) { 790 if (is_device_busy(dev)) 791 return -EBUSY; 792 if (dev->attached) { 793 struct module *driver_module = dev->driver->module; 794 795 comedi_device_detach(dev); 796 module_put(driver_module); 797 } 798 return 0; 799 } 800 801 if (copy_from_user(&it, arg, sizeof(it))) 802 return -EFAULT; 803 804 it.board_name[COMEDI_NAMELEN - 1] = 0; 805 806 if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { 807 dev_warn(dev->class_dev, 808 "comedi_config --init_data is deprecated\n"); 809 return -EINVAL; 810 } 811 812 if (dev->minor >= comedi_num_legacy_minors) 813 /* don't re-use dynamically allocated comedi devices */ 814 return -EBUSY; 815 816 /* This increments the driver module count on success. */ 817 return comedi_device_attach(dev, &it); 818} 819 820/* 821 * COMEDI_BUFCONFIG ioctl 822 * buffer configuration 823 * 824 * arg: 825 * pointer to comedi_bufconfig structure 826 * 827 * reads: 828 * comedi_bufconfig structure 829 * 830 * writes: 831 * modified comedi_bufconfig structure 832 */ 833static int do_bufconfig_ioctl(struct comedi_device *dev, 834 struct comedi_bufconfig __user *arg) 835{ 836 struct comedi_bufconfig bc; 837 struct comedi_async *async; 838 struct comedi_subdevice *s; 839 int retval = 0; 840 841 if (copy_from_user(&bc, arg, sizeof(bc))) 842 return -EFAULT; 843 844 if (bc.subdevice >= dev->n_subdevices) 845 return -EINVAL; 846 847 s = &dev->subdevices[bc.subdevice]; 848 async = s->async; 849 850 if (!async) { 851 dev_dbg(dev->class_dev, 852 "subdevice does not have async capability\n"); 853 bc.size = 0; 854 bc.maximum_size = 0; 855 goto copyback; 856 } 857 858 if (bc.maximum_size) { 859 if (!capable(CAP_SYS_ADMIN)) 860 return -EPERM; 861 862 async->max_bufsize = bc.maximum_size; 863 } 864 865 if (bc.size) { 866 retval = resize_async_buffer(dev, s, bc.size); 867 if (retval < 0) 868 return retval; 869 } 870 871 bc.size = async->prealloc_bufsz; 872 bc.maximum_size = async->max_bufsize; 873 874copyback: 875 if (copy_to_user(arg, &bc, sizeof(bc))) 876 return -EFAULT; 877 878 return 0; 879} 880 881/* 882 * COMEDI_DEVINFO ioctl 883 * device info 884 * 885 * arg: 886 * pointer to comedi_devinfo structure 887 * 888 * reads: 889 * nothing 890 * 891 * writes: 892 * comedi_devinfo structure 893 */ 894static int do_devinfo_ioctl(struct comedi_device *dev, 895 struct comedi_devinfo __user *arg, 896 struct file *file) 897{ 898 struct comedi_subdevice *s; 899 struct comedi_devinfo devinfo; 900 901 memset(&devinfo, 0, sizeof(devinfo)); 902 903 /* fill devinfo structure */ 904 devinfo.version_code = COMEDI_VERSION_CODE; 905 devinfo.n_subdevs = dev->n_subdevices; 906 strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN); 907 strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN); 908 909 s = comedi_file_read_subdevice(file); 910 if (s) 911 devinfo.read_subdevice = s->index; 912 else 913 devinfo.read_subdevice = -1; 914 915 s = comedi_file_write_subdevice(file); 916 if (s) 917 devinfo.write_subdevice = s->index; 918 else 919 devinfo.write_subdevice = -1; 920 921 if (copy_to_user(arg, &devinfo, sizeof(devinfo))) 922 return -EFAULT; 923 924 return 0; 925} 926 927/* 928 * COMEDI_SUBDINFO ioctl 929 * subdevices info 930 * 931 * arg: 932 * pointer to array of comedi_subdinfo structures 933 * 934 * reads: 935 * nothing 936 * 937 * writes: 938 * array of comedi_subdinfo structures 939 */ 940static int do_subdinfo_ioctl(struct comedi_device *dev, 941 struct comedi_subdinfo __user *arg, void *file) 942{ 943 int ret, i; 944 struct comedi_subdinfo *tmp, *us; 945 struct comedi_subdevice *s; 946 947 tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL); 948 if (!tmp) 949 return -ENOMEM; 950 951 /* fill subdinfo structs */ 952 for (i = 0; i < dev->n_subdevices; i++) { 953 s = &dev->subdevices[i]; 954 us = tmp + i; 955 956 us->type = s->type; 957 us->n_chan = s->n_chan; 958 us->subd_flags = s->subdev_flags; 959 if (comedi_is_subdevice_running(s)) 960 us->subd_flags |= SDF_RUNNING; 961#define TIMER_nanosec 5 /* backwards compatibility */ 962 us->timer_type = TIMER_nanosec; 963 us->len_chanlist = s->len_chanlist; 964 us->maxdata = s->maxdata; 965 if (s->range_table) { 966 us->range_type = 967 (i << 24) | (0 << 16) | (s->range_table->length); 968 } else { 969 us->range_type = 0; /* XXX */ 970 } 971 972 if (s->busy) 973 us->subd_flags |= SDF_BUSY; 974 if (s->busy == file) 975 us->subd_flags |= SDF_BUSY_OWNER; 976 if (s->lock) 977 us->subd_flags |= SDF_LOCKED; 978 if (s->lock == file) 979 us->subd_flags |= SDF_LOCK_OWNER; 980 if (!s->maxdata && s->maxdata_list) 981 us->subd_flags |= SDF_MAXDATA; 982 if (s->range_table_list) 983 us->subd_flags |= SDF_RANGETYPE; 984 if (s->do_cmd) 985 us->subd_flags |= SDF_CMD; 986 987 if (s->insn_bits != &insn_inval) 988 us->insn_bits_support = COMEDI_SUPPORTED; 989 else 990 us->insn_bits_support = COMEDI_UNSUPPORTED; 991 } 992 993 ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp)); 994 995 kfree(tmp); 996 997 return ret ? -EFAULT : 0; 998} 999 1000/* 1001 * COMEDI_CHANINFO ioctl 1002 * subdevice channel info 1003 * 1004 * arg: 1005 * pointer to comedi_chaninfo structure 1006 * 1007 * reads: 1008 * comedi_chaninfo structure 1009 * 1010 * writes: 1011 * array of maxdata values to chaninfo->maxdata_list if requested 1012 * array of range table lengths to chaninfo->range_table_list if requested 1013 */ 1014static int do_chaninfo_ioctl(struct comedi_device *dev, 1015 struct comedi_chaninfo __user *arg) 1016{ 1017 struct comedi_subdevice *s; 1018 struct comedi_chaninfo it; 1019 1020 if (copy_from_user(&it, arg, sizeof(it))) 1021 return -EFAULT; 1022 1023 if (it.subdev >= dev->n_subdevices) 1024 return -EINVAL; 1025 s = &dev->subdevices[it.subdev]; 1026 1027 if (it.maxdata_list) { 1028 if (s->maxdata || !s->maxdata_list) 1029 return -EINVAL; 1030 if (copy_to_user(it.maxdata_list, s->maxdata_list, 1031 s->n_chan * sizeof(unsigned int))) 1032 return -EFAULT; 1033 } 1034 1035 if (it.flaglist) 1036 return -EINVAL; /* flaglist not supported */ 1037 1038 if (it.rangelist) { 1039 int i; 1040 1041 if (!s->range_table_list) 1042 return -EINVAL; 1043 for (i = 0; i < s->n_chan; i++) { 1044 int x; 1045 1046 x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) | 1047 (s->range_table_list[i]->length); 1048 if (put_user(x, it.rangelist + i)) 1049 return -EFAULT; 1050 } 1051#if 0 1052 if (copy_to_user(it.rangelist, s->range_type_list, 1053 s->n_chan * sizeof(unsigned int))) 1054 return -EFAULT; 1055#endif 1056 } 1057 1058 return 0; 1059} 1060 1061/* 1062 * COMEDI_BUFINFO ioctl 1063 * buffer information 1064 * 1065 * arg: 1066 * pointer to comedi_bufinfo structure 1067 * 1068 * reads: 1069 * comedi_bufinfo structure 1070 * 1071 * writes: 1072 * modified comedi_bufinfo structure 1073 */ 1074static int do_bufinfo_ioctl(struct comedi_device *dev, 1075 struct comedi_bufinfo __user *arg, void *file) 1076{ 1077 struct comedi_bufinfo bi; 1078 struct comedi_subdevice *s; 1079 struct comedi_async *async; 1080 1081 if (copy_from_user(&bi, arg, sizeof(bi))) 1082 return -EFAULT; 1083 1084 if (bi.subdevice >= dev->n_subdevices) 1085 return -EINVAL; 1086 1087 s = &dev->subdevices[bi.subdevice]; 1088 1089 async = s->async; 1090 1091 if (!async) { 1092 dev_dbg(dev->class_dev, 1093 "subdevice does not have async capability\n"); 1094 bi.buf_write_ptr = 0; 1095 bi.buf_read_ptr = 0; 1096 bi.buf_write_count = 0; 1097 bi.buf_read_count = 0; 1098 bi.bytes_read = 0; 1099 bi.bytes_written = 0; 1100 goto copyback; 1101 } 1102 if (!s->busy) { 1103 bi.bytes_read = 0; 1104 bi.bytes_written = 0; 1105 goto copyback_position; 1106 } 1107 if (s->busy != file) 1108 return -EACCES; 1109 1110 if (bi.bytes_read && !(async->cmd.flags & CMDF_WRITE)) { 1111 bi.bytes_read = comedi_buf_read_alloc(s, bi.bytes_read); 1112 comedi_buf_read_free(s, bi.bytes_read); 1113 1114 if (comedi_is_subdevice_idle(s) && 1115 comedi_buf_n_bytes_ready(s) == 0) { 1116 do_become_nonbusy(dev, s); 1117 } 1118 } 1119 1120 if (bi.bytes_written && (async->cmd.flags & CMDF_WRITE)) { 1121 bi.bytes_written = 1122 comedi_buf_write_alloc(s, bi.bytes_written); 1123 comedi_buf_write_free(s, bi.bytes_written); 1124 } 1125 1126copyback_position: 1127 bi.buf_write_count = async->buf_write_count; 1128 bi.buf_write_ptr = async->buf_write_ptr; 1129 bi.buf_read_count = async->buf_read_count; 1130 bi.buf_read_ptr = async->buf_read_ptr; 1131 1132copyback: 1133 if (copy_to_user(arg, &bi, sizeof(bi))) 1134 return -EFAULT; 1135 1136 return 0; 1137} 1138 1139static int check_insn_config_length(struct comedi_insn *insn, 1140 unsigned int *data) 1141{ 1142 if (insn->n < 1) 1143 return -EINVAL; 1144 1145 switch (data[0]) { 1146 case INSN_CONFIG_DIO_OUTPUT: 1147 case INSN_CONFIG_DIO_INPUT: 1148 case INSN_CONFIG_DISARM: 1149 case INSN_CONFIG_RESET: 1150 if (insn->n == 1) 1151 return 0; 1152 break; 1153 case INSN_CONFIG_ARM: 1154 case INSN_CONFIG_DIO_QUERY: 1155 case INSN_CONFIG_BLOCK_SIZE: 1156 case INSN_CONFIG_FILTER: 1157 case INSN_CONFIG_SERIAL_CLOCK: 1158 case INSN_CONFIG_BIDIRECTIONAL_DATA: 1159 case INSN_CONFIG_ALT_SOURCE: 1160 case INSN_CONFIG_SET_COUNTER_MODE: 1161 case INSN_CONFIG_8254_READ_STATUS: 1162 case INSN_CONFIG_SET_ROUTING: 1163 case INSN_CONFIG_GET_ROUTING: 1164 case INSN_CONFIG_GET_PWM_STATUS: 1165 case INSN_CONFIG_PWM_SET_PERIOD: 1166 case INSN_CONFIG_PWM_GET_PERIOD: 1167 if (insn->n == 2) 1168 return 0; 1169 break; 1170 case INSN_CONFIG_SET_GATE_SRC: 1171 case INSN_CONFIG_GET_GATE_SRC: 1172 case INSN_CONFIG_SET_CLOCK_SRC: 1173 case INSN_CONFIG_GET_CLOCK_SRC: 1174 case INSN_CONFIG_SET_OTHER_SRC: 1175 case INSN_CONFIG_GET_COUNTER_STATUS: 1176 case INSN_CONFIG_PWM_SET_H_BRIDGE: 1177 case INSN_CONFIG_PWM_GET_H_BRIDGE: 1178 case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE: 1179 if (insn->n == 3) 1180 return 0; 1181 break; 1182 case INSN_CONFIG_PWM_OUTPUT: 1183 case INSN_CONFIG_ANALOG_TRIG: 1184 if (insn->n == 5) 1185 return 0; 1186 break; 1187 case INSN_CONFIG_DIGITAL_TRIG: 1188 if (insn->n == 6) 1189 return 0; 1190 break; 1191 /* 1192 * by default we allow the insn since we don't have checks for 1193 * all possible cases yet 1194 */ 1195 default: 1196 pr_warn("No check for data length of config insn id %i is implemented\n", 1197 data[0]); 1198 pr_warn("Add a check to %s in %s\n", __func__, __FILE__); 1199 pr_warn("Assuming n=%i is correct\n", insn->n); 1200 return 0; 1201 } 1202 return -EINVAL; 1203} 1204 1205static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn, 1206 unsigned int *data, void *file) 1207{ 1208 struct comedi_subdevice *s; 1209 int ret = 0; 1210 int i; 1211 1212 if (insn->insn & INSN_MASK_SPECIAL) { 1213 /* a non-subdevice instruction */ 1214 1215 switch (insn->insn) { 1216 case INSN_GTOD: 1217 { 1218 struct timeval tv; 1219 1220 if (insn->n != 2) { 1221 ret = -EINVAL; 1222 break; 1223 } 1224 1225 do_gettimeofday(&tv); 1226 data[0] = tv.tv_sec; 1227 data[1] = tv.tv_usec; 1228 ret = 2; 1229 1230 break; 1231 } 1232 case INSN_WAIT: 1233 if (insn->n != 1 || data[0] >= 100000) { 1234 ret = -EINVAL; 1235 break; 1236 } 1237 udelay(data[0] / 1000); 1238 ret = 1; 1239 break; 1240 case INSN_INTTRIG: 1241 if (insn->n != 1) { 1242 ret = -EINVAL; 1243 break; 1244 } 1245 if (insn->subdev >= dev->n_subdevices) { 1246 dev_dbg(dev->class_dev, 1247 "%d not usable subdevice\n", 1248 insn->subdev); 1249 ret = -EINVAL; 1250 break; 1251 } 1252 s = &dev->subdevices[insn->subdev]; 1253 if (!s->async) { 1254 dev_dbg(dev->class_dev, "no async\n"); 1255 ret = -EINVAL; 1256 break; 1257 } 1258 if (!s->async->inttrig) { 1259 dev_dbg(dev->class_dev, "no inttrig\n"); 1260 ret = -EAGAIN; 1261 break; 1262 } 1263 ret = s->async->inttrig(dev, s, data[0]); 1264 if (ret >= 0) 1265 ret = 1; 1266 break; 1267 default: 1268 dev_dbg(dev->class_dev, "invalid insn\n"); 1269 ret = -EINVAL; 1270 break; 1271 } 1272 } else { 1273 /* a subdevice instruction */ 1274 unsigned int maxdata; 1275 1276 if (insn->subdev >= dev->n_subdevices) { 1277 dev_dbg(dev->class_dev, "subdevice %d out of range\n", 1278 insn->subdev); 1279 ret = -EINVAL; 1280 goto out; 1281 } 1282 s = &dev->subdevices[insn->subdev]; 1283 1284 if (s->type == COMEDI_SUBD_UNUSED) { 1285 dev_dbg(dev->class_dev, "%d not usable subdevice\n", 1286 insn->subdev); 1287 ret = -EIO; 1288 goto out; 1289 } 1290 1291 /* are we locked? (ioctl lock) */ 1292 if (s->lock && s->lock != file) { 1293 dev_dbg(dev->class_dev, "device locked\n"); 1294 ret = -EACCES; 1295 goto out; 1296 } 1297 1298 ret = comedi_check_chanlist(s, 1, &insn->chanspec); 1299 if (ret < 0) { 1300 ret = -EINVAL; 1301 dev_dbg(dev->class_dev, "bad chanspec\n"); 1302 goto out; 1303 } 1304 1305 if (s->busy) { 1306 ret = -EBUSY; 1307 goto out; 1308 } 1309 /* This looks arbitrary. It is. */ 1310 s->busy = &parse_insn; 1311 switch (insn->insn) { 1312 case INSN_READ: 1313 ret = s->insn_read(dev, s, insn, data); 1314 if (ret == -ETIMEDOUT) { 1315 dev_dbg(dev->class_dev, 1316 "subdevice %d read instruction timed out\n", 1317 s->index); 1318 } 1319 break; 1320 case INSN_WRITE: 1321 maxdata = s->maxdata_list 1322 ? s->maxdata_list[CR_CHAN(insn->chanspec)] 1323 : s->maxdata; 1324 for (i = 0; i < insn->n; ++i) { 1325 if (data[i] > maxdata) { 1326 ret = -EINVAL; 1327 dev_dbg(dev->class_dev, 1328 "bad data value(s)\n"); 1329 break; 1330 } 1331 } 1332 if (ret == 0) { 1333 ret = s->insn_write(dev, s, insn, data); 1334 if (ret == -ETIMEDOUT) { 1335 dev_dbg(dev->class_dev, 1336 "subdevice %d write instruction timed out\n", 1337 s->index); 1338 } 1339 } 1340 break; 1341 case INSN_BITS: 1342 if (insn->n != 2) { 1343 ret = -EINVAL; 1344 } else { 1345 /* 1346 * Most drivers ignore the base channel in 1347 * insn->chanspec. Fix this here if 1348 * the subdevice has <= 32 channels. 1349 */ 1350 unsigned int orig_mask = data[0]; 1351 unsigned int shift = 0; 1352 1353 if (s->n_chan <= 32) { 1354 shift = CR_CHAN(insn->chanspec); 1355 if (shift > 0) { 1356 insn->chanspec = 0; 1357 data[0] <<= shift; 1358 data[1] <<= shift; 1359 } 1360 } 1361 ret = s->insn_bits(dev, s, insn, data); 1362 data[0] = orig_mask; 1363 if (shift > 0) 1364 data[1] >>= shift; 1365 } 1366 break; 1367 case INSN_CONFIG: 1368 ret = check_insn_config_length(insn, data); 1369 if (ret) 1370 break; 1371 ret = s->insn_config(dev, s, insn, data); 1372 break; 1373 default: 1374 ret = -EINVAL; 1375 break; 1376 } 1377 1378 s->busy = NULL; 1379 } 1380 1381out: 1382 return ret; 1383} 1384 1385/* 1386 * COMEDI_INSNLIST ioctl 1387 * synchronous instruction list 1388 * 1389 * arg: 1390 * pointer to comedi_insnlist structure 1391 * 1392 * reads: 1393 * comedi_insnlist structure 1394 * array of comedi_insn structures from insnlist->insns pointer 1395 * data (for writes) from insns[].data pointers 1396 * 1397 * writes: 1398 * data (for reads) to insns[].data pointers 1399 */ 1400/* arbitrary limits */ 1401#define MAX_SAMPLES 256 1402static int do_insnlist_ioctl(struct comedi_device *dev, 1403 struct comedi_insnlist __user *arg, void *file) 1404{ 1405 struct comedi_insnlist insnlist; 1406 struct comedi_insn *insns = NULL; 1407 unsigned int *data = NULL; 1408 int i = 0; 1409 int ret = 0; 1410 1411 if (copy_from_user(&insnlist, arg, sizeof(insnlist))) 1412 return -EFAULT; 1413 1414 data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL); 1415 if (!data) { 1416 ret = -ENOMEM; 1417 goto error; 1418 } 1419 1420 insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL); 1421 if (!insns) { 1422 ret = -ENOMEM; 1423 goto error; 1424 } 1425 1426 if (copy_from_user(insns, insnlist.insns, 1427 sizeof(*insns) * insnlist.n_insns)) { 1428 dev_dbg(dev->class_dev, "copy_from_user failed\n"); 1429 ret = -EFAULT; 1430 goto error; 1431 } 1432 1433 for (i = 0; i < insnlist.n_insns; i++) { 1434 if (insns[i].n > MAX_SAMPLES) { 1435 dev_dbg(dev->class_dev, 1436 "number of samples too large\n"); 1437 ret = -EINVAL; 1438 goto error; 1439 } 1440 if (insns[i].insn & INSN_MASK_WRITE) { 1441 if (copy_from_user(data, insns[i].data, 1442 insns[i].n * sizeof(unsigned int))) { 1443 dev_dbg(dev->class_dev, 1444 "copy_from_user failed\n"); 1445 ret = -EFAULT; 1446 goto error; 1447 } 1448 } 1449 ret = parse_insn(dev, insns + i, data, file); 1450 if (ret < 0) 1451 goto error; 1452 if (insns[i].insn & INSN_MASK_READ) { 1453 if (copy_to_user(insns[i].data, data, 1454 insns[i].n * sizeof(unsigned int))) { 1455 dev_dbg(dev->class_dev, 1456 "copy_to_user failed\n"); 1457 ret = -EFAULT; 1458 goto error; 1459 } 1460 } 1461 if (need_resched()) 1462 schedule(); 1463 } 1464 1465error: 1466 kfree(insns); 1467 kfree(data); 1468 1469 if (ret < 0) 1470 return ret; 1471 return i; 1472} 1473 1474/* 1475 * COMEDI_INSN ioctl 1476 * synchronous instruction 1477 * 1478 * arg: 1479 * pointer to comedi_insn structure 1480 * 1481 * reads: 1482 * comedi_insn structure 1483 * data (for writes) from insn->data pointer 1484 * 1485 * writes: 1486 * data (for reads) to insn->data pointer 1487 */ 1488static int do_insn_ioctl(struct comedi_device *dev, 1489 struct comedi_insn __user *arg, void *file) 1490{ 1491 struct comedi_insn insn; 1492 unsigned int *data = NULL; 1493 int ret = 0; 1494 1495 data = kmalloc_array(MAX_SAMPLES, sizeof(unsigned int), GFP_KERNEL); 1496 if (!data) { 1497 ret = -ENOMEM; 1498 goto error; 1499 } 1500 1501 if (copy_from_user(&insn, arg, sizeof(insn))) { 1502 ret = -EFAULT; 1503 goto error; 1504 } 1505 1506 /* This is where the behavior of insn and insnlist deviate. */ 1507 if (insn.n > MAX_SAMPLES) 1508 insn.n = MAX_SAMPLES; 1509 if (insn.insn & INSN_MASK_WRITE) { 1510 if (copy_from_user(data, 1511 insn.data, 1512 insn.n * sizeof(unsigned int))) { 1513 ret = -EFAULT; 1514 goto error; 1515 } 1516 } 1517 ret = parse_insn(dev, &insn, data, file); 1518 if (ret < 0) 1519 goto error; 1520 if (insn.insn & INSN_MASK_READ) { 1521 if (copy_to_user(insn.data, 1522 data, 1523 insn.n * sizeof(unsigned int))) { 1524 ret = -EFAULT; 1525 goto error; 1526 } 1527 } 1528 ret = insn.n; 1529 1530error: 1531 kfree(data); 1532 1533 return ret; 1534} 1535 1536static int __comedi_get_user_cmd(struct comedi_device *dev, 1537 struct comedi_cmd __user *arg, 1538 struct comedi_cmd *cmd) 1539{ 1540 struct comedi_subdevice *s; 1541 1542 if (copy_from_user(cmd, arg, sizeof(*cmd))) { 1543 dev_dbg(dev->class_dev, "bad cmd address\n"); 1544 return -EFAULT; 1545 } 1546 1547 if (cmd->subdev >= dev->n_subdevices) { 1548 dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd->subdev); 1549 return -ENODEV; 1550 } 1551 1552 s = &dev->subdevices[cmd->subdev]; 1553 1554 if (s->type == COMEDI_SUBD_UNUSED) { 1555 dev_dbg(dev->class_dev, "%d not valid subdevice\n", 1556 cmd->subdev); 1557 return -EIO; 1558 } 1559 1560 if (!s->do_cmd || !s->do_cmdtest || !s->async) { 1561 dev_dbg(dev->class_dev, 1562 "subdevice %d does not support commands\n", 1563 cmd->subdev); 1564 return -EIO; 1565 } 1566 1567 /* make sure channel/gain list isn't too long */ 1568 if (cmd->chanlist_len > s->len_chanlist) { 1569 dev_dbg(dev->class_dev, "channel/gain list too long %d > %d\n", 1570 cmd->chanlist_len, s->len_chanlist); 1571 return -EINVAL; 1572 } 1573 1574 /* 1575 * Set the CMDF_WRITE flag to the correct state if the subdevice 1576 * supports only "read" commands or only "write" commands. 1577 */ 1578 switch (s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) { 1579 case SDF_CMD_READ: 1580 cmd->flags &= ~CMDF_WRITE; 1581 break; 1582 case SDF_CMD_WRITE: 1583 cmd->flags |= CMDF_WRITE; 1584 break; 1585 default: 1586 break; 1587 } 1588 1589 return 0; 1590} 1591 1592static int __comedi_get_user_chanlist(struct comedi_device *dev, 1593 struct comedi_subdevice *s, 1594 unsigned int __user *user_chanlist, 1595 struct comedi_cmd *cmd) 1596{ 1597 unsigned int *chanlist; 1598 int ret; 1599 1600 cmd->chanlist = NULL; 1601 chanlist = memdup_user(user_chanlist, 1602 cmd->chanlist_len * sizeof(unsigned int)); 1603 if (IS_ERR(chanlist)) 1604 return PTR_ERR(chanlist); 1605 1606 /* make sure each element in channel/gain list is valid */ 1607 ret = comedi_check_chanlist(s, cmd->chanlist_len, chanlist); 1608 if (ret < 0) { 1609 kfree(chanlist); 1610 return ret; 1611 } 1612 1613 cmd->chanlist = chanlist; 1614 1615 return 0; 1616} 1617 1618/* 1619 * COMEDI_CMD ioctl 1620 * asynchronous acquisition command set-up 1621 * 1622 * arg: 1623 * pointer to comedi_cmd structure 1624 * 1625 * reads: 1626 * comedi_cmd structure 1627 * channel/range list from cmd->chanlist pointer 1628 * 1629 * writes: 1630 * possibly modified comedi_cmd structure (when -EAGAIN returned) 1631 */ 1632static int do_cmd_ioctl(struct comedi_device *dev, 1633 struct comedi_cmd __user *arg, void *file) 1634{ 1635 struct comedi_cmd cmd; 1636 struct comedi_subdevice *s; 1637 struct comedi_async *async; 1638 unsigned int __user *user_chanlist; 1639 int ret; 1640 1641 /* get the user's cmd and do some simple validation */ 1642 ret = __comedi_get_user_cmd(dev, arg, &cmd); 1643 if (ret) 1644 return ret; 1645 1646 /* save user's chanlist pointer so it can be restored later */ 1647 user_chanlist = (unsigned int __user *)cmd.chanlist; 1648 1649 s = &dev->subdevices[cmd.subdev]; 1650 async = s->async; 1651 1652 /* are we locked? (ioctl lock) */ 1653 if (s->lock && s->lock != file) { 1654 dev_dbg(dev->class_dev, "subdevice locked\n"); 1655 return -EACCES; 1656 } 1657 1658 /* are we busy? */ 1659 if (s->busy) { 1660 dev_dbg(dev->class_dev, "subdevice busy\n"); 1661 return -EBUSY; 1662 } 1663 1664 /* make sure channel/gain list isn't too short */ 1665 if (cmd.chanlist_len < 1) { 1666 dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n", 1667 cmd.chanlist_len); 1668 return -EINVAL; 1669 } 1670 1671 async->cmd = cmd; 1672 async->cmd.data = NULL; 1673 1674 /* load channel/gain list */ 1675 ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &async->cmd); 1676 if (ret) 1677 goto cleanup; 1678 1679 ret = s->do_cmdtest(dev, s, &async->cmd); 1680 1681 if (async->cmd.flags & CMDF_BOGUS || ret) { 1682 dev_dbg(dev->class_dev, "test returned %d\n", ret); 1683 cmd = async->cmd; 1684 /* restore chanlist pointer before copying back */ 1685 cmd.chanlist = (unsigned int __force *)user_chanlist; 1686 cmd.data = NULL; 1687 if (copy_to_user(arg, &cmd, sizeof(cmd))) { 1688 dev_dbg(dev->class_dev, "fault writing cmd\n"); 1689 ret = -EFAULT; 1690 goto cleanup; 1691 } 1692 ret = -EAGAIN; 1693 goto cleanup; 1694 } 1695 1696 if (!async->prealloc_bufsz) { 1697 ret = -ENOMEM; 1698 dev_dbg(dev->class_dev, "no buffer (?)\n"); 1699 goto cleanup; 1700 } 1701 1702 comedi_buf_reset(s); 1703 1704 async->cb_mask = COMEDI_CB_BLOCK | COMEDI_CB_CANCEL_MASK; 1705 if (async->cmd.flags & CMDF_WAKE_EOS) 1706 async->cb_mask |= COMEDI_CB_EOS; 1707 1708 comedi_update_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK, 1709 COMEDI_SRF_RUNNING); 1710 1711 /* 1712 * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid 1713 * race with comedi_read() or comedi_write(). 1714 */ 1715 s->busy = file; 1716 ret = s->do_cmd(dev, s); 1717 if (ret == 0) 1718 return 0; 1719 1720cleanup: 1721 do_become_nonbusy(dev, s); 1722 1723 return ret; 1724} 1725 1726/* 1727 * COMEDI_CMDTEST ioctl 1728 * asynchronous aquisition command testing 1729 * 1730 * arg: 1731 * pointer to comedi_cmd structure 1732 * 1733 * reads: 1734 * comedi_cmd structure 1735 * channel/range list from cmd->chanlist pointer 1736 * 1737 * writes: 1738 * possibly modified comedi_cmd structure 1739 */ 1740static int do_cmdtest_ioctl(struct comedi_device *dev, 1741 struct comedi_cmd __user *arg, void *file) 1742{ 1743 struct comedi_cmd cmd; 1744 struct comedi_subdevice *s; 1745 unsigned int __user *user_chanlist; 1746 int ret; 1747 1748 /* get the user's cmd and do some simple validation */ 1749 ret = __comedi_get_user_cmd(dev, arg, &cmd); 1750 if (ret) 1751 return ret; 1752 1753 /* save user's chanlist pointer so it can be restored later */ 1754 user_chanlist = (unsigned int __user *)cmd.chanlist; 1755 1756 s = &dev->subdevices[cmd.subdev]; 1757 1758 /* user_chanlist can be NULL for COMEDI_CMDTEST ioctl */ 1759 if (user_chanlist) { 1760 /* load channel/gain list */ 1761 ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &cmd); 1762 if (ret) 1763 return ret; 1764 } 1765 1766 ret = s->do_cmdtest(dev, s, &cmd); 1767 1768 kfree(cmd.chanlist); /* free kernel copy of user chanlist */ 1769 1770 /* restore chanlist pointer before copying back */ 1771 cmd.chanlist = (unsigned int __force *)user_chanlist; 1772 1773 if (copy_to_user(arg, &cmd, sizeof(cmd))) { 1774 dev_dbg(dev->class_dev, "bad cmd address\n"); 1775 ret = -EFAULT; 1776 } 1777 1778 return ret; 1779} 1780 1781/* 1782 * COMEDI_LOCK ioctl 1783 * lock subdevice 1784 * 1785 * arg: 1786 * subdevice number 1787 * 1788 * reads: 1789 * nothing 1790 * 1791 * writes: 1792 * nothing 1793 */ 1794static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg, 1795 void *file) 1796{ 1797 int ret = 0; 1798 unsigned long flags; 1799 struct comedi_subdevice *s; 1800 1801 if (arg >= dev->n_subdevices) 1802 return -EINVAL; 1803 s = &dev->subdevices[arg]; 1804 1805 spin_lock_irqsave(&s->spin_lock, flags); 1806 if (s->busy || s->lock) 1807 ret = -EBUSY; 1808 else 1809 s->lock = file; 1810 spin_unlock_irqrestore(&s->spin_lock, flags); 1811 1812 return ret; 1813} 1814 1815/* 1816 * COMEDI_UNLOCK ioctl 1817 * unlock subdevice 1818 * 1819 * arg: 1820 * subdevice number 1821 * 1822 * reads: 1823 * nothing 1824 * 1825 * writes: 1826 * nothing 1827 */ 1828static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg, 1829 void *file) 1830{ 1831 struct comedi_subdevice *s; 1832 1833 if (arg >= dev->n_subdevices) 1834 return -EINVAL; 1835 s = &dev->subdevices[arg]; 1836 1837 if (s->busy) 1838 return -EBUSY; 1839 1840 if (s->lock && s->lock != file) 1841 return -EACCES; 1842 1843 if (s->lock == file) 1844 s->lock = NULL; 1845 1846 return 0; 1847} 1848 1849/* 1850 * COMEDI_CANCEL ioctl 1851 * cancel asynchronous acquisition 1852 * 1853 * arg: 1854 * subdevice number 1855 * 1856 * reads: 1857 * nothing 1858 * 1859 * writes: 1860 * nothing 1861 */ 1862static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg, 1863 void *file) 1864{ 1865 struct comedi_subdevice *s; 1866 1867 if (arg >= dev->n_subdevices) 1868 return -EINVAL; 1869 s = &dev->subdevices[arg]; 1870 if (!s->async) 1871 return -EINVAL; 1872 1873 if (!s->busy) 1874 return 0; 1875 1876 if (s->busy != file) 1877 return -EBUSY; 1878 1879 return do_cancel(dev, s); 1880} 1881 1882/* 1883 * COMEDI_POLL ioctl 1884 * instructs driver to synchronize buffers 1885 * 1886 * arg: 1887 * subdevice number 1888 * 1889 * reads: 1890 * nothing 1891 * 1892 * writes: 1893 * nothing 1894 */ 1895static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg, 1896 void *file) 1897{ 1898 struct comedi_subdevice *s; 1899 1900 if (arg >= dev->n_subdevices) 1901 return -EINVAL; 1902 s = &dev->subdevices[arg]; 1903 1904 if (!s->busy) 1905 return 0; 1906 1907 if (s->busy != file) 1908 return -EBUSY; 1909 1910 if (s->poll) 1911 return s->poll(dev, s); 1912 1913 return -EINVAL; 1914} 1915 1916/* 1917 * COMEDI_SETRSUBD ioctl 1918 * sets the current "read" subdevice on a per-file basis 1919 * 1920 * arg: 1921 * subdevice number 1922 * 1923 * reads: 1924 * nothing 1925 * 1926 * writes: 1927 * nothing 1928 */ 1929static int do_setrsubd_ioctl(struct comedi_device *dev, unsigned long arg, 1930 struct file *file) 1931{ 1932 struct comedi_file *cfp = file->private_data; 1933 struct comedi_subdevice *s_old, *s_new; 1934 1935 if (arg >= dev->n_subdevices) 1936 return -EINVAL; 1937 1938 s_new = &dev->subdevices[arg]; 1939 s_old = comedi_file_read_subdevice(file); 1940 if (s_old == s_new) 1941 return 0; /* no change */ 1942 1943 if (!(s_new->subdev_flags & SDF_CMD_READ)) 1944 return -EINVAL; 1945 1946 /* 1947 * Check the file isn't still busy handling a "read" command on the 1948 * old subdevice (if any). 1949 */ 1950 if (s_old && s_old->busy == file && s_old->async && 1951 !(s_old->async->cmd.flags & CMDF_WRITE)) 1952 return -EBUSY; 1953 1954 ACCESS_ONCE(cfp->read_subdev) = s_new; 1955 return 0; 1956} 1957 1958/* 1959 * COMEDI_SETWSUBD ioctl 1960 * sets the current "write" subdevice on a per-file basis 1961 * 1962 * arg: 1963 * subdevice number 1964 * 1965 * reads: 1966 * nothing 1967 * 1968 * writes: 1969 * nothing 1970 */ 1971static int do_setwsubd_ioctl(struct comedi_device *dev, unsigned long arg, 1972 struct file *file) 1973{ 1974 struct comedi_file *cfp = file->private_data; 1975 struct comedi_subdevice *s_old, *s_new; 1976 1977 if (arg >= dev->n_subdevices) 1978 return -EINVAL; 1979 1980 s_new = &dev->subdevices[arg]; 1981 s_old = comedi_file_write_subdevice(file); 1982 if (s_old == s_new) 1983 return 0; /* no change */ 1984 1985 if (!(s_new->subdev_flags & SDF_CMD_WRITE)) 1986 return -EINVAL; 1987 1988 /* 1989 * Check the file isn't still busy handling a "write" command on the 1990 * old subdevice (if any). 1991 */ 1992 if (s_old && s_old->busy == file && s_old->async && 1993 (s_old->async->cmd.flags & CMDF_WRITE)) 1994 return -EBUSY; 1995 1996 ACCESS_ONCE(cfp->write_subdev) = s_new; 1997 return 0; 1998} 1999 2000static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, 2001 unsigned long arg) 2002{ 2003 unsigned minor = iminor(file_inode(file)); 2004 struct comedi_file *cfp = file->private_data; 2005 struct comedi_device *dev = cfp->dev; 2006 int rc; 2007 2008 mutex_lock(&dev->mutex); 2009 2010 /* 2011 * Device config is special, because it must work on 2012 * an unconfigured device. 2013 */ 2014 if (cmd == COMEDI_DEVCONFIG) { 2015 if (minor >= COMEDI_NUM_BOARD_MINORS) { 2016 /* Device config not appropriate on non-board minors. */ 2017 rc = -ENOTTY; 2018 goto done; 2019 } 2020 rc = do_devconfig_ioctl(dev, 2021 (struct comedi_devconfig __user *)arg); 2022 if (rc == 0) { 2023 if (arg == 0 && 2024 dev->minor >= comedi_num_legacy_minors) { 2025 /* 2026 * Successfully unconfigured a dynamically 2027 * allocated device. Try and remove it. 2028 */ 2029 if (comedi_clear_board_dev(dev)) { 2030 mutex_unlock(&dev->mutex); 2031 comedi_free_board_dev(dev); 2032 return rc; 2033 } 2034 } 2035 } 2036 goto done; 2037 } 2038 2039 if (!dev->attached) { 2040 dev_dbg(dev->class_dev, "no driver attached\n"); 2041 rc = -ENODEV; 2042 goto done; 2043 } 2044 2045 switch (cmd) { 2046 case COMEDI_BUFCONFIG: 2047 rc = do_bufconfig_ioctl(dev, 2048 (struct comedi_bufconfig __user *)arg); 2049 break; 2050 case COMEDI_DEVINFO: 2051 rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg, 2052 file); 2053 break; 2054 case COMEDI_SUBDINFO: 2055 rc = do_subdinfo_ioctl(dev, 2056 (struct comedi_subdinfo __user *)arg, 2057 file); 2058 break; 2059 case COMEDI_CHANINFO: 2060 rc = do_chaninfo_ioctl(dev, (void __user *)arg); 2061 break; 2062 case COMEDI_RANGEINFO: 2063 rc = do_rangeinfo_ioctl(dev, (void __user *)arg); 2064 break; 2065 case COMEDI_BUFINFO: 2066 rc = do_bufinfo_ioctl(dev, 2067 (struct comedi_bufinfo __user *)arg, 2068 file); 2069 break; 2070 case COMEDI_LOCK: 2071 rc = do_lock_ioctl(dev, arg, file); 2072 break; 2073 case COMEDI_UNLOCK: 2074 rc = do_unlock_ioctl(dev, arg, file); 2075 break; 2076 case COMEDI_CANCEL: 2077 rc = do_cancel_ioctl(dev, arg, file); 2078 break; 2079 case COMEDI_CMD: 2080 rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file); 2081 break; 2082 case COMEDI_CMDTEST: 2083 rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg, 2084 file); 2085 break; 2086 case COMEDI_INSNLIST: 2087 rc = do_insnlist_ioctl(dev, 2088 (struct comedi_insnlist __user *)arg, 2089 file); 2090 break; 2091 case COMEDI_INSN: 2092 rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg, 2093 file); 2094 break; 2095 case COMEDI_POLL: 2096 rc = do_poll_ioctl(dev, arg, file); 2097 break; 2098 case COMEDI_SETRSUBD: 2099 rc = do_setrsubd_ioctl(dev, arg, file); 2100 break; 2101 case COMEDI_SETWSUBD: 2102 rc = do_setwsubd_ioctl(dev, arg, file); 2103 break; 2104 default: 2105 rc = -ENOTTY; 2106 break; 2107 } 2108 2109done: 2110 mutex_unlock(&dev->mutex); 2111 return rc; 2112} 2113 2114static void comedi_vm_open(struct vm_area_struct *area) 2115{ 2116 struct comedi_buf_map *bm; 2117 2118 bm = area->vm_private_data; 2119 comedi_buf_map_get(bm); 2120} 2121 2122static void comedi_vm_close(struct vm_area_struct *area) 2123{ 2124 struct comedi_buf_map *bm; 2125 2126 bm = area->vm_private_data; 2127 comedi_buf_map_put(bm); 2128} 2129 2130static struct vm_operations_struct comedi_vm_ops = { 2131 .open = comedi_vm_open, 2132 .close = comedi_vm_close, 2133}; 2134 2135static int comedi_mmap(struct file *file, struct vm_area_struct *vma) 2136{ 2137 struct comedi_file *cfp = file->private_data; 2138 struct comedi_device *dev = cfp->dev; 2139 struct comedi_subdevice *s; 2140 struct comedi_async *async; 2141 struct comedi_buf_map *bm = NULL; 2142 unsigned long start = vma->vm_start; 2143 unsigned long size; 2144 int n_pages; 2145 int i; 2146 int retval; 2147 2148 /* 2149 * 'trylock' avoids circular dependency with current->mm->mmap_sem 2150 * and down-reading &dev->attach_lock should normally succeed without 2151 * contention unless the device is in the process of being attached 2152 * or detached. 2153 */ 2154 if (!down_read_trylock(&dev->attach_lock)) 2155 return -EAGAIN; 2156 2157 if (!dev->attached) { 2158 dev_dbg(dev->class_dev, "no driver attached\n"); 2159 retval = -ENODEV; 2160 goto done; 2161 } 2162 2163 if (vma->vm_flags & VM_WRITE) 2164 s = comedi_file_write_subdevice(file); 2165 else 2166 s = comedi_file_read_subdevice(file); 2167 if (!s) { 2168 retval = -EINVAL; 2169 goto done; 2170 } 2171 2172 async = s->async; 2173 if (!async) { 2174 retval = -EINVAL; 2175 goto done; 2176 } 2177 2178 if (vma->vm_pgoff != 0) { 2179 dev_dbg(dev->class_dev, "mmap() offset must be 0.\n"); 2180 retval = -EINVAL; 2181 goto done; 2182 } 2183 2184 size = vma->vm_end - vma->vm_start; 2185 if (size > async->prealloc_bufsz) { 2186 retval = -EFAULT; 2187 goto done; 2188 } 2189 if (size & (~PAGE_MASK)) { 2190 retval = -EFAULT; 2191 goto done; 2192 } 2193 2194 n_pages = size >> PAGE_SHIFT; 2195 2196 /* get reference to current buf map (if any) */ 2197 bm = comedi_buf_map_from_subdev_get(s); 2198 if (!bm || n_pages > bm->n_pages) { 2199 retval = -EINVAL; 2200 goto done; 2201 } 2202 for (i = 0; i < n_pages; ++i) { 2203 struct comedi_buf_page *buf = &bm->page_list[i]; 2204 2205 if (remap_pfn_range(vma, start, 2206 page_to_pfn(virt_to_page(buf->virt_addr)), 2207 PAGE_SIZE, PAGE_SHARED)) { 2208 retval = -EAGAIN; 2209 goto done; 2210 } 2211 start += PAGE_SIZE; 2212 } 2213 2214 vma->vm_ops = &comedi_vm_ops; 2215 vma->vm_private_data = bm; 2216 2217 vma->vm_ops->open(vma); 2218 2219 retval = 0; 2220done: 2221 up_read(&dev->attach_lock); 2222 comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */ 2223 return retval; 2224} 2225 2226static unsigned int comedi_poll(struct file *file, poll_table *wait) 2227{ 2228 unsigned int mask = 0; 2229 struct comedi_file *cfp = file->private_data; 2230 struct comedi_device *dev = cfp->dev; 2231 struct comedi_subdevice *s; 2232 2233 mutex_lock(&dev->mutex); 2234 2235 if (!dev->attached) { 2236 dev_dbg(dev->class_dev, "no driver attached\n"); 2237 goto done; 2238 } 2239 2240 s = comedi_file_read_subdevice(file); 2241 if (s && s->async) { 2242 poll_wait(file, &s->async->wait_head, wait); 2243 if (!s->busy || !comedi_is_subdevice_running(s) || 2244 (s->async->cmd.flags & CMDF_WRITE) || 2245 comedi_buf_read_n_available(s) > 0) 2246 mask |= POLLIN | POLLRDNORM; 2247 } 2248 2249 s = comedi_file_write_subdevice(file); 2250 if (s && s->async) { 2251 unsigned int bps = comedi_bytes_per_sample(s); 2252 2253 poll_wait(file, &s->async->wait_head, wait); 2254 comedi_buf_write_alloc(s, s->async->prealloc_bufsz); 2255 if (!s->busy || !comedi_is_subdevice_running(s) || 2256 !(s->async->cmd.flags & CMDF_WRITE) || 2257 comedi_buf_write_n_allocated(s) >= bps) 2258 mask |= POLLOUT | POLLWRNORM; 2259 } 2260 2261done: 2262 mutex_unlock(&dev->mutex); 2263 return mask; 2264} 2265 2266static ssize_t comedi_write(struct file *file, const char __user *buf, 2267 size_t nbytes, loff_t *offset) 2268{ 2269 struct comedi_subdevice *s; 2270 struct comedi_async *async; 2271 int n, m, count = 0, retval = 0; 2272 DECLARE_WAITQUEUE(wait, current); 2273 struct comedi_file *cfp = file->private_data; 2274 struct comedi_device *dev = cfp->dev; 2275 bool on_wait_queue = false; 2276 bool attach_locked; 2277 unsigned int old_detach_count; 2278 2279 /* Protect against device detachment during operation. */ 2280 down_read(&dev->attach_lock); 2281 attach_locked = true; 2282 old_detach_count = dev->detach_count; 2283 2284 if (!dev->attached) { 2285 dev_dbg(dev->class_dev, "no driver attached\n"); 2286 retval = -ENODEV; 2287 goto out; 2288 } 2289 2290 s = comedi_file_write_subdevice(file); 2291 if (!s || !s->async) { 2292 retval = -EIO; 2293 goto out; 2294 } 2295 2296 async = s->async; 2297 2298 if (!s->busy || !nbytes) 2299 goto out; 2300 if (s->busy != file) { 2301 retval = -EACCES; 2302 goto out; 2303 } 2304 if (!(async->cmd.flags & CMDF_WRITE)) { 2305 retval = -EINVAL; 2306 goto out; 2307 } 2308 2309 add_wait_queue(&async->wait_head, &wait); 2310 on_wait_queue = true; 2311 while (nbytes > 0 && !retval) { 2312 unsigned runflags; 2313 2314 set_current_state(TASK_INTERRUPTIBLE); 2315 2316 runflags = comedi_get_subdevice_runflags(s); 2317 if (!comedi_is_runflags_running(runflags)) { 2318 if (count == 0) { 2319 struct comedi_subdevice *new_s; 2320 2321 if (comedi_is_runflags_in_error(runflags)) 2322 retval = -EPIPE; 2323 else 2324 retval = 0; 2325 /* 2326 * To avoid deadlock, cannot acquire dev->mutex 2327 * while dev->attach_lock is held. Need to 2328 * remove task from the async wait queue before 2329 * releasing dev->attach_lock, as it might not 2330 * be valid afterwards. 2331 */ 2332 remove_wait_queue(&async->wait_head, &wait); 2333 on_wait_queue = false; 2334 up_read(&dev->attach_lock); 2335 attach_locked = false; 2336 mutex_lock(&dev->mutex); 2337 /* 2338 * Become non-busy unless things have changed 2339 * behind our back. Checking dev->detach_count 2340 * is unchanged ought to be sufficient (unless 2341 * there have been 2**32 detaches in the 2342 * meantime!), but check the subdevice pointer 2343 * as well just in case. 2344 */ 2345 new_s = comedi_file_write_subdevice(file); 2346 if (dev->attached && 2347 old_detach_count == dev->detach_count && 2348 s == new_s && new_s->async == async) 2349 do_become_nonbusy(dev, s); 2350 mutex_unlock(&dev->mutex); 2351 } 2352 break; 2353 } 2354 2355 n = nbytes; 2356 2357 m = n; 2358 if (async->buf_write_ptr + m > async->prealloc_bufsz) 2359 m = async->prealloc_bufsz - async->buf_write_ptr; 2360 comedi_buf_write_alloc(s, async->prealloc_bufsz); 2361 if (m > comedi_buf_write_n_allocated(s)) 2362 m = comedi_buf_write_n_allocated(s); 2363 if (m < n) 2364 n = m; 2365 2366 if (n == 0) { 2367 if (file->f_flags & O_NONBLOCK) { 2368 retval = -EAGAIN; 2369 break; 2370 } 2371 schedule(); 2372 if (signal_pending(current)) { 2373 retval = -ERESTARTSYS; 2374 break; 2375 } 2376 if (!s->busy) 2377 break; 2378 if (s->busy != file) { 2379 retval = -EACCES; 2380 break; 2381 } 2382 if (!(async->cmd.flags & CMDF_WRITE)) { 2383 retval = -EINVAL; 2384 break; 2385 } 2386 continue; 2387 } 2388 2389 m = copy_from_user(async->prealloc_buf + async->buf_write_ptr, 2390 buf, n); 2391 if (m) { 2392 n -= m; 2393 retval = -EFAULT; 2394 } 2395 comedi_buf_write_free(s, n); 2396 2397 count += n; 2398 nbytes -= n; 2399 2400 buf += n; 2401 break; /* makes device work like a pipe */ 2402 } 2403out: 2404 if (on_wait_queue) 2405 remove_wait_queue(&async->wait_head, &wait); 2406 set_current_state(TASK_RUNNING); 2407 if (attach_locked) 2408 up_read(&dev->attach_lock); 2409 2410 return count ? count : retval; 2411} 2412 2413static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes, 2414 loff_t *offset) 2415{ 2416 struct comedi_subdevice *s; 2417 struct comedi_async *async; 2418 int n, m, count = 0, retval = 0; 2419 DECLARE_WAITQUEUE(wait, current); 2420 struct comedi_file *cfp = file->private_data; 2421 struct comedi_device *dev = cfp->dev; 2422 unsigned int old_detach_count; 2423 bool become_nonbusy = false; 2424 bool attach_locked; 2425 2426 /* Protect against device detachment during operation. */ 2427 down_read(&dev->attach_lock); 2428 attach_locked = true; 2429 old_detach_count = dev->detach_count; 2430 2431 if (!dev->attached) { 2432 dev_dbg(dev->class_dev, "no driver attached\n"); 2433 retval = -ENODEV; 2434 goto out; 2435 } 2436 2437 s = comedi_file_read_subdevice(file); 2438 if (!s || !s->async) { 2439 retval = -EIO; 2440 goto out; 2441 } 2442 2443 async = s->async; 2444 if (!s->busy || !nbytes) 2445 goto out; 2446 if (s->busy != file) { 2447 retval = -EACCES; 2448 goto out; 2449 } 2450 if (async->cmd.flags & CMDF_WRITE) { 2451 retval = -EINVAL; 2452 goto out; 2453 } 2454 2455 add_wait_queue(&async->wait_head, &wait); 2456 while (nbytes > 0 && !retval) { 2457 set_current_state(TASK_INTERRUPTIBLE); 2458 2459 n = nbytes; 2460 2461 m = comedi_buf_read_n_available(s); 2462 if (async->buf_read_ptr + m > async->prealloc_bufsz) 2463 m = async->prealloc_bufsz - async->buf_read_ptr; 2464 if (m < n) 2465 n = m; 2466 2467 if (n == 0) { 2468 unsigned runflags = comedi_get_subdevice_runflags(s); 2469 2470 if (!comedi_is_runflags_running(runflags)) { 2471 if (comedi_is_runflags_in_error(runflags)) 2472 retval = -EPIPE; 2473 else 2474 retval = 0; 2475 become_nonbusy = true; 2476 break; 2477 } 2478 if (file->f_flags & O_NONBLOCK) { 2479 retval = -EAGAIN; 2480 break; 2481 } 2482 schedule(); 2483 if (signal_pending(current)) { 2484 retval = -ERESTARTSYS; 2485 break; 2486 } 2487 if (!s->busy) { 2488 retval = 0; 2489 break; 2490 } 2491 if (s->busy != file) { 2492 retval = -EACCES; 2493 break; 2494 } 2495 if (async->cmd.flags & CMDF_WRITE) { 2496 retval = -EINVAL; 2497 break; 2498 } 2499 continue; 2500 } 2501 m = copy_to_user(buf, async->prealloc_buf + 2502 async->buf_read_ptr, n); 2503 if (m) { 2504 n -= m; 2505 retval = -EFAULT; 2506 } 2507 2508 comedi_buf_read_alloc(s, n); 2509 comedi_buf_read_free(s, n); 2510 2511 count += n; 2512 nbytes -= n; 2513 2514 buf += n; 2515 break; /* makes device work like a pipe */ 2516 } 2517 remove_wait_queue(&async->wait_head, &wait); 2518 set_current_state(TASK_RUNNING); 2519 if (become_nonbusy || comedi_is_subdevice_idle(s)) { 2520 struct comedi_subdevice *new_s; 2521 2522 /* 2523 * To avoid deadlock, cannot acquire dev->mutex 2524 * while dev->attach_lock is held. 2525 */ 2526 up_read(&dev->attach_lock); 2527 attach_locked = false; 2528 mutex_lock(&dev->mutex); 2529 /* 2530 * Check device hasn't become detached behind our back. 2531 * Checking dev->detach_count is unchanged ought to be 2532 * sufficient (unless there have been 2**32 detaches in the 2533 * meantime!), but check the subdevice pointer as well just in 2534 * case. 2535 */ 2536 new_s = comedi_file_read_subdevice(file); 2537 if (dev->attached && old_detach_count == dev->detach_count && 2538 s == new_s && new_s->async == async) { 2539 if (become_nonbusy || comedi_buf_n_bytes_ready(s) == 0) 2540 do_become_nonbusy(dev, s); 2541 } 2542 mutex_unlock(&dev->mutex); 2543 } 2544out: 2545 if (attach_locked) 2546 up_read(&dev->attach_lock); 2547 2548 return count ? count : retval; 2549} 2550 2551static int comedi_open(struct inode *inode, struct file *file) 2552{ 2553 const unsigned minor = iminor(inode); 2554 struct comedi_file *cfp; 2555 struct comedi_device *dev = comedi_dev_get_from_minor(minor); 2556 int rc; 2557 2558 if (!dev) { 2559 pr_debug("invalid minor number\n"); 2560 return -ENODEV; 2561 } 2562 2563 cfp = kzalloc(sizeof(*cfp), GFP_KERNEL); 2564 if (!cfp) 2565 return -ENOMEM; 2566 2567 cfp->dev = dev; 2568 2569 mutex_lock(&dev->mutex); 2570 if (!dev->attached && !capable(CAP_NET_ADMIN)) { 2571 dev_dbg(dev->class_dev, "not attached and not CAP_NET_ADMIN\n"); 2572 rc = -ENODEV; 2573 goto out; 2574 } 2575 if (dev->attached && dev->use_count == 0) { 2576 if (!try_module_get(dev->driver->module)) { 2577 rc = -ENOSYS; 2578 goto out; 2579 } 2580 if (dev->open) { 2581 rc = dev->open(dev); 2582 if (rc < 0) { 2583 module_put(dev->driver->module); 2584 goto out; 2585 } 2586 } 2587 } 2588 2589 dev->use_count++; 2590 file->private_data = cfp; 2591 comedi_file_reset(file); 2592 rc = 0; 2593 2594out: 2595 mutex_unlock(&dev->mutex); 2596 if (rc) { 2597 comedi_dev_put(dev); 2598 kfree(cfp); 2599 } 2600 return rc; 2601} 2602 2603static int comedi_fasync(int fd, struct file *file, int on) 2604{ 2605 struct comedi_file *cfp = file->private_data; 2606 struct comedi_device *dev = cfp->dev; 2607 2608 return fasync_helper(fd, file, on, &dev->async_queue); 2609} 2610 2611static int comedi_close(struct inode *inode, struct file *file) 2612{ 2613 struct comedi_file *cfp = file->private_data; 2614 struct comedi_device *dev = cfp->dev; 2615 struct comedi_subdevice *s = NULL; 2616 int i; 2617 2618 mutex_lock(&dev->mutex); 2619 2620 if (dev->subdevices) { 2621 for (i = 0; i < dev->n_subdevices; i++) { 2622 s = &dev->subdevices[i]; 2623 2624 if (s->busy == file) 2625 do_cancel(dev, s); 2626 if (s->lock == file) 2627 s->lock = NULL; 2628 } 2629 } 2630 if (dev->attached && dev->use_count == 1) { 2631 if (dev->close) 2632 dev->close(dev); 2633 module_put(dev->driver->module); 2634 } 2635 2636 dev->use_count--; 2637 2638 mutex_unlock(&dev->mutex); 2639 comedi_dev_put(dev); 2640 kfree(cfp); 2641 2642 return 0; 2643} 2644 2645static const struct file_operations comedi_fops = { 2646 .owner = THIS_MODULE, 2647 .unlocked_ioctl = comedi_unlocked_ioctl, 2648 .compat_ioctl = comedi_compat_ioctl, 2649 .open = comedi_open, 2650 .release = comedi_close, 2651 .read = comedi_read, 2652 .write = comedi_write, 2653 .mmap = comedi_mmap, 2654 .poll = comedi_poll, 2655 .fasync = comedi_fasync, 2656 .llseek = noop_llseek, 2657}; 2658 2659/** 2660 * comedi_event - handle events for asynchronous comedi command 2661 * @dev: comedi_device struct 2662 * @s: comedi_subdevice struct associated with dev 2663 * Context: interrupt (usually), s->spin_lock spin-lock not held 2664 * 2665 * If an asynchronous comedi command is active on the subdevice, process 2666 * any COMEDI_CB_... event flags that have been set, usually by an 2667 * interrupt handler. These may change the run state of the asynchronous 2668 * command, wake a task, and/or send a SIGIO signal. 2669 */ 2670void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s) 2671{ 2672 struct comedi_async *async = s->async; 2673 unsigned int events; 2674 int si_code = 0; 2675 unsigned long flags; 2676 2677 spin_lock_irqsave(&s->spin_lock, flags); 2678 2679 events = async->events; 2680 async->events = 0; 2681 if (!__comedi_is_subdevice_running(s)) { 2682 spin_unlock_irqrestore(&s->spin_lock, flags); 2683 return; 2684 } 2685 2686 if (events & COMEDI_CB_CANCEL_MASK) 2687 __comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING); 2688 2689 /* 2690 * Remember if an error event has occurred, so an error can be 2691 * returned the next time the user does a read() or write(). 2692 */ 2693 if (events & COMEDI_CB_ERROR_MASK) 2694 __comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR); 2695 2696 if (async->cb_mask & events) { 2697 wake_up_interruptible(&async->wait_head); 2698 si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN; 2699 } 2700 2701 spin_unlock_irqrestore(&s->spin_lock, flags); 2702 2703 if (si_code) 2704 kill_fasync(&dev->async_queue, SIGIO, si_code); 2705} 2706EXPORT_SYMBOL_GPL(comedi_event); 2707 2708/* Note: the ->mutex is pre-locked on successful return */ 2709struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device) 2710{ 2711 struct comedi_device *dev; 2712 struct device *csdev; 2713 unsigned i; 2714 2715 dev = kzalloc(sizeof(*dev), GFP_KERNEL); 2716 if (!dev) 2717 return ERR_PTR(-ENOMEM); 2718 comedi_device_init(dev); 2719 comedi_set_hw_dev(dev, hardware_device); 2720 mutex_lock(&dev->mutex); 2721 mutex_lock(&comedi_board_minor_table_lock); 2722 for (i = hardware_device ? comedi_num_legacy_minors : 0; 2723 i < COMEDI_NUM_BOARD_MINORS; ++i) { 2724 if (!comedi_board_minor_table[i]) { 2725 comedi_board_minor_table[i] = dev; 2726 break; 2727 } 2728 } 2729 mutex_unlock(&comedi_board_minor_table_lock); 2730 if (i == COMEDI_NUM_BOARD_MINORS) { 2731 mutex_unlock(&dev->mutex); 2732 comedi_device_cleanup(dev); 2733 comedi_dev_put(dev); 2734 dev_err(hardware_device, 2735 "ran out of minor numbers for board device files\n"); 2736 return ERR_PTR(-EBUSY); 2737 } 2738 dev->minor = i; 2739 csdev = device_create(comedi_class, hardware_device, 2740 MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i); 2741 if (!IS_ERR(csdev)) 2742 dev->class_dev = get_device(csdev); 2743 2744 /* Note: dev->mutex needs to be unlocked by the caller. */ 2745 return dev; 2746} 2747 2748static void comedi_free_board_minor(unsigned minor) 2749{ 2750 BUG_ON(minor >= COMEDI_NUM_BOARD_MINORS); 2751 comedi_free_board_dev(comedi_clear_board_minor(minor)); 2752} 2753 2754void comedi_release_hardware_device(struct device *hardware_device) 2755{ 2756 int minor; 2757 struct comedi_device *dev; 2758 2759 for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS; 2760 minor++) { 2761 mutex_lock(&comedi_board_minor_table_lock); 2762 dev = comedi_board_minor_table[minor]; 2763 if (dev && dev->hw_dev == hardware_device) { 2764 comedi_board_minor_table[minor] = NULL; 2765 mutex_unlock(&comedi_board_minor_table_lock); 2766 comedi_free_board_dev(dev); 2767 break; 2768 } 2769 mutex_unlock(&comedi_board_minor_table_lock); 2770 } 2771} 2772 2773int comedi_alloc_subdevice_minor(struct comedi_subdevice *s) 2774{ 2775 struct comedi_device *dev = s->device; 2776 struct device *csdev; 2777 unsigned i; 2778 2779 mutex_lock(&comedi_subdevice_minor_table_lock); 2780 for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) { 2781 if (!comedi_subdevice_minor_table[i]) { 2782 comedi_subdevice_minor_table[i] = s; 2783 break; 2784 } 2785 } 2786 mutex_unlock(&comedi_subdevice_minor_table_lock); 2787 if (i == COMEDI_NUM_SUBDEVICE_MINORS) { 2788 dev_err(dev->class_dev, 2789 "ran out of minor numbers for subdevice files\n"); 2790 return -EBUSY; 2791 } 2792 i += COMEDI_NUM_BOARD_MINORS; 2793 s->minor = i; 2794 csdev = device_create(comedi_class, dev->class_dev, 2795 MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i", 2796 dev->minor, s->index); 2797 if (!IS_ERR(csdev)) 2798 s->class_dev = csdev; 2799 2800 return 0; 2801} 2802 2803void comedi_free_subdevice_minor(struct comedi_subdevice *s) 2804{ 2805 unsigned int i; 2806 2807 if (!s) 2808 return; 2809 if (s->minor < 0) 2810 return; 2811 2812 BUG_ON(s->minor >= COMEDI_NUM_MINORS); 2813 BUG_ON(s->minor < COMEDI_NUM_BOARD_MINORS); 2814 2815 i = s->minor - COMEDI_NUM_BOARD_MINORS; 2816 mutex_lock(&comedi_subdevice_minor_table_lock); 2817 if (s == comedi_subdevice_minor_table[i]) 2818 comedi_subdevice_minor_table[i] = NULL; 2819 mutex_unlock(&comedi_subdevice_minor_table_lock); 2820 if (s->class_dev) { 2821 device_destroy(comedi_class, MKDEV(COMEDI_MAJOR, s->minor)); 2822 s->class_dev = NULL; 2823 } 2824} 2825 2826static void comedi_cleanup_board_minors(void) 2827{ 2828 unsigned i; 2829 2830 for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) 2831 comedi_free_board_minor(i); 2832} 2833 2834static int __init comedi_init(void) 2835{ 2836 int i; 2837 int retval; 2838 2839 pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n"); 2840 2841 if (comedi_num_legacy_minors < 0 || 2842 comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) { 2843 pr_err("invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n", 2844 COMEDI_NUM_BOARD_MINORS); 2845 return -EINVAL; 2846 } 2847 2848 retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2849 COMEDI_NUM_MINORS, "comedi"); 2850 if (retval) 2851 return -EIO; 2852 cdev_init(&comedi_cdev, &comedi_fops); 2853 comedi_cdev.owner = THIS_MODULE; 2854 2855 retval = kobject_set_name(&comedi_cdev.kobj, "comedi"); 2856 if (retval) { 2857 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2858 COMEDI_NUM_MINORS); 2859 return retval; 2860 } 2861 2862 if (cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS)) { 2863 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2864 COMEDI_NUM_MINORS); 2865 return -EIO; 2866 } 2867 comedi_class = class_create(THIS_MODULE, "comedi"); 2868 if (IS_ERR(comedi_class)) { 2869 pr_err("failed to create class\n"); 2870 cdev_del(&comedi_cdev); 2871 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2872 COMEDI_NUM_MINORS); 2873 return PTR_ERR(comedi_class); 2874 } 2875 2876 comedi_class->dev_groups = comedi_dev_groups; 2877 2878 /* XXX requires /proc interface */ 2879 comedi_proc_init(); 2880 2881 /* create devices files for legacy/manual use */ 2882 for (i = 0; i < comedi_num_legacy_minors; i++) { 2883 struct comedi_device *dev; 2884 2885 dev = comedi_alloc_board_minor(NULL); 2886 if (IS_ERR(dev)) { 2887 comedi_cleanup_board_minors(); 2888 cdev_del(&comedi_cdev); 2889 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), 2890 COMEDI_NUM_MINORS); 2891 return PTR_ERR(dev); 2892 } 2893 /* comedi_alloc_board_minor() locked the mutex */ 2894 mutex_unlock(&dev->mutex); 2895 } 2896 2897 return 0; 2898} 2899module_init(comedi_init); 2900 2901static void __exit comedi_cleanup(void) 2902{ 2903 int i; 2904 2905 comedi_cleanup_board_minors(); 2906 for (i = 0; i < COMEDI_NUM_BOARD_MINORS; ++i) 2907 BUG_ON(comedi_board_minor_table[i]); 2908 for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) 2909 BUG_ON(comedi_subdevice_minor_table[i]); 2910 2911 class_destroy(comedi_class); 2912 cdev_del(&comedi_cdev); 2913 unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS); 2914 2915 comedi_proc_cleanup(); 2916} 2917module_exit(comedi_cleanup); 2918 2919MODULE_AUTHOR("http://www.comedi.org"); 2920MODULE_DESCRIPTION("Comedi core module"); 2921MODULE_LICENSE("GPL"); 2922