/*
- comedi/comedi_fops.c
- comedi kernel module
-
- COMEDI - Linux Control and Measurement Device Interface
- Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-*/
+ * comedi/comedi_fops.c
+ * comedi kernel module
+ *
+ * COMEDI - Linux Control and Measurement Device Interface
+ * Copyright (C) 1997-2000 David A. Schleef <ds@schleef.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
kfree(dev);
}
+/**
+ * comedi_dev_put - release a use of a comedi device structure
+ * @dev: comedi_device struct
+ *
+ * Must be called when a user of a comedi device is finished with it.
+ * When the last user of the comedi device calls this function, the
+ * comedi device is destroyed.
+ *
+ * Return 1 if the comedi device is destroyed by this call or dev is
+ * NULL, otherwise return 0. Callers must not assume the comedi
+ * device is still valid if this function returns 0.
+ */
int comedi_dev_put(struct comedi_device *dev)
{
if (dev)
return dev;
}
+/**
+ * comedi_dev_get_from_minor - get comedi device by minor device number
+ * @minor: minor device number
+ *
+ * Finds the comedi device associated by the minor device number, if any,
+ * and increments its reference count. The comedi device is prevented from
+ * being freed until a matching call is made to comedi_dev_put().
+ *
+ * Return a pointer to the comedi device if it exists, with its usage
+ * reference incremented. Return NULL if no comedi device exists with the
+ * specified minor device number.
+ */
struct comedi_device *comedi_dev_get_from_minor(unsigned minor)
{
if (minor < COMEDI_NUM_BOARD_MINORS)
return -EBUSY;
}
- /* make sure buffer is an integral number of pages
- * (we round up) */
+ /* make sure buffer is an integral number of pages (we round up) */
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
retval = comedi_buf_alloc(dev, s, new_size);
return runflags;
}
+/**
+ * comedi_is_subdevice_running - check if async command running on subdevice
+ * @s: comedi_subdevice struct
+ *
+ * Return true if an asynchronous comedi command is active on the comedi
+ * subdevice, else return false.
+ */
bool comedi_is_subdevice_running(struct comedi_subdevice *s)
{
unsigned runflags = comedi_get_subdevice_runflags(s);
- return (runflags & SRF_RUNNING) ? true : false;
+ return (runflags & COMEDI_SRF_RUNNING) ? true : false;
}
EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
{
unsigned runflags = comedi_get_subdevice_runflags(s);
- return (runflags & SRF_ERROR) ? true : false;
+ return (runflags & COMEDI_SRF_ERROR) ? true : false;
}
static bool comedi_is_subdevice_idle(struct comedi_subdevice *s)
{
unsigned runflags = comedi_get_subdevice_runflags(s);
- return (runflags & (SRF_ERROR | SRF_RUNNING)) ? false : true;
+ return (runflags & COMEDI_SRF_BUSY_MASK) ? false : true;
}
/**
{
s->private = kzalloc(size, GFP_KERNEL);
if (s->private)
- s->runflags |= SRF_FREE_SPRIV;
+ s->runflags |= COMEDI_SRF_FREE_SPRIV;
return s->private;
}
EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
/*
- This function restores a subdevice to an idle state.
+ * This function restores a subdevice to an idle state.
*/
static void do_become_nonbusy(struct comedi_device *dev,
struct comedi_subdevice *s)
{
struct comedi_async *async = s->async;
- comedi_set_subdevice_runflags(s, SRF_RUNNING, 0);
+ comedi_set_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
if (async) {
comedi_buf_reset(s);
async->inttrig = NULL;
}
/*
- COMEDI_DEVCONFIG
- device config ioctl
-
- arg:
- pointer to devconfig structure
-
- reads:
- devconfig structure at arg
-
- writes:
- none
-*/
+ * COMEDI_DEVCONFIG ioctl
+ * attaches (and configures) or detaches a legacy device
+ *
+ * arg:
+ * pointer to comedi_devconfig structure (NULL if detaching)
+ *
+ * reads:
+ * comedi_devconfig structure (if attaching)
+ *
+ * writes:
+ * nothing
+ */
static int do_devconfig_ioctl(struct comedi_device *dev,
struct comedi_devconfig __user *arg)
{
}
/*
- COMEDI_BUFCONFIG
- buffer configuration ioctl
-
- arg:
- pointer to bufconfig structure
-
- reads:
- bufconfig at arg
-
- writes:
- modified bufconfig at arg
-
-*/
+ * COMEDI_BUFCONFIG ioctl
+ * buffer configuration
+ *
+ * arg:
+ * pointer to comedi_bufconfig structure
+ *
+ * reads:
+ * comedi_bufconfig structure
+ *
+ * writes:
+ * modified comedi_bufconfig structure
+ */
static int do_bufconfig_ioctl(struct comedi_device *dev,
struct comedi_bufconfig __user *arg)
{
}
/*
- COMEDI_DEVINFO
- device info ioctl
-
- arg:
- pointer to devinfo structure
-
- reads:
- none
-
- writes:
- devinfo structure
-
-*/
+ * COMEDI_DEVINFO ioctl
+ * device info
+ *
+ * arg:
+ * pointer to comedi_devinfo structure
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * comedi_devinfo structure
+ */
static int do_devinfo_ioctl(struct comedi_device *dev,
struct comedi_devinfo __user *arg,
struct file *file)
}
/*
- COMEDI_SUBDINFO
- subdevice info ioctl
-
- arg:
- pointer to array of subdevice info structures
-
- reads:
- none
-
- writes:
- array of subdevice info structures at arg
-
-*/
+ * COMEDI_SUBDINFO ioctl
+ * subdevices info
+ *
+ * arg:
+ * pointer to array of comedi_subdinfo structures
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * array of comedi_subdinfo structures
+ */
static int do_subdinfo_ioctl(struct comedi_device *dev,
struct comedi_subdinfo __user *arg, void *file)
{
}
/*
- COMEDI_CHANINFO
- subdevice info ioctl
-
- arg:
- pointer to chaninfo structure
-
- reads:
- chaninfo structure at arg
-
- writes:
- arrays at elements of chaninfo structure
-
-*/
+ * COMEDI_CHANINFO ioctl
+ * subdevice channel info
+ *
+ * arg:
+ * pointer to comedi_chaninfo structure
+ *
+ * reads:
+ * comedi_chaninfo structure
+ *
+ * writes:
+ * array of maxdata values to chaninfo->maxdata_list if requested
+ * array of range table lengths to chaninfo->range_table_list if requested
+ */
static int do_chaninfo_ioctl(struct comedi_device *dev,
struct comedi_chaninfo __user *arg)
{
return 0;
}
- /*
- COMEDI_BUFINFO
- buffer information ioctl
-
- arg:
- pointer to bufinfo structure
-
- reads:
- bufinfo at arg
-
- writes:
- modified bufinfo at arg
-
- */
+/*
+ * COMEDI_BUFINFO ioctl
+ * buffer information
+ *
+ * arg:
+ * pointer to comedi_bufinfo structure
+ *
+ * reads:
+ * comedi_bufinfo structure
+ *
+ * writes:
+ * modified comedi_bufinfo structure
+ */
static int do_bufinfo_ioctl(struct comedi_device *dev,
struct comedi_bufinfo __user *arg, void *file)
{
if (insn->n == 6)
return 0;
break;
- /* by default we allow the insn since we don't have checks for
- * all possible cases yet */
+ /*
+ * by default we allow the insn since we don't have checks for
+ * all possible cases yet
+ */
default:
pr_warn("No check for data length of config insn id %i is implemented\n",
data[0]);
if (insn->n != 2) {
ret = -EINVAL;
} else {
- /* Most drivers ignore the base channel in
+ /*
+ * Most drivers ignore the base channel in
* insn->chanspec. Fix this here if
- * the subdevice has <= 32 channels. */
+ * the subdevice has <= 32 channels.
+ */
unsigned int orig_mask = data[0];
unsigned int shift = 0;
}
/*
- * COMEDI_INSNLIST
- * synchronous instructions
+ * COMEDI_INSNLIST ioctl
+ * synchronous instruction list
*
- * arg:
- * pointer to sync cmd structure
+ * arg:
+ * pointer to comedi_insnlist structure
*
- * reads:
- * sync cmd struct at arg
- * instruction list
- * data (for writes)
+ * reads:
+ * comedi_insnlist structure
+ * array of comedi_insn structures from insnlist->insns pointer
+ * data (for writes) from insns[].data pointers
*
- * writes:
- * data (for reads)
+ * writes:
+ * data (for reads) to insns[].data pointers
*/
/* arbitrary limits */
#define MAX_SAMPLES 256
}
/*
- * COMEDI_INSN
- * synchronous instructions
+ * COMEDI_INSN ioctl
+ * synchronous instruction
*
- * arg:
- * pointer to insn
+ * arg:
+ * pointer to comedi_insn structure
*
- * reads:
- * struct comedi_insn struct at arg
- * data (for writes)
+ * reads:
+ * comedi_insn structure
+ * data (for writes) from insn->data pointer
*
- * writes:
- * data (for reads)
+ * writes:
+ * data (for reads) to insn->data pointer
*/
static int do_insn_ioctl(struct comedi_device *dev,
struct comedi_insn __user *arg, void *file)
return 0;
}
+/*
+ * COMEDI_CMD ioctl
+ * asynchronous acquisition command set-up
+ *
+ * arg:
+ * pointer to comedi_cmd structure
+ *
+ * reads:
+ * comedi_cmd structure
+ * channel/range list from cmd->chanlist pointer
+ *
+ * writes:
+ * possibly modified comedi_cmd structure (when -EAGAIN returned)
+ */
static int do_cmd_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file)
{
if (async->cmd.flags & CMDF_WAKE_EOS)
async->cb_mask |= COMEDI_CB_EOS;
- comedi_set_subdevice_runflags(s, SRF_ERROR | SRF_RUNNING, SRF_RUNNING);
+ comedi_set_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
+ COMEDI_SRF_RUNNING);
- /* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
- * comedi_read() or comedi_write() */
+ /*
+ * Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid
+ * race with comedi_read() or comedi_write().
+ */
s->busy = file;
ret = s->do_cmd(dev, s);
if (ret == 0)
}
/*
- COMEDI_CMDTEST
- command testing ioctl
-
- arg:
- pointer to cmd structure
-
- reads:
- cmd structure at arg
- channel/range list
-
- writes:
- modified cmd structure at arg
-
-*/
+ * COMEDI_CMDTEST ioctl
+ * asynchronous aquisition command testing
+ *
+ * arg:
+ * pointer to comedi_cmd structure
+ *
+ * reads:
+ * comedi_cmd structure
+ * channel/range list from cmd->chanlist pointer
+ *
+ * writes:
+ * possibly modified comedi_cmd structure
+ */
static int do_cmdtest_ioctl(struct comedi_device *dev,
struct comedi_cmd __user *arg, void *file)
{
}
/*
- COMEDI_LOCK
- lock subdevice
-
- arg:
- subdevice number
-
- reads:
- none
-
- writes:
- none
-
-*/
-
+ * COMEDI_LOCK ioctl
+ * lock subdevice
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg,
void *file)
{
}
/*
- COMEDI_UNLOCK
- unlock subdevice
-
- arg:
- subdevice number
-
- reads:
- none
-
- writes:
- none
-
- This function isn't protected by the semaphore, since
- we already own the lock.
-*/
+ * COMEDI_UNLOCK ioctl
+ * unlock subdevice
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg,
void *file)
{
}
/*
- COMEDI_CANCEL
- cancel acquisition ioctl
-
- arg:
- subdevice number
-
- reads:
- nothing
-
- writes:
- nothing
-
-*/
+ * COMEDI_CANCEL ioctl
+ * cancel asynchronous acquisition
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
void *file)
{
}
/*
- COMEDI_POLL ioctl
- instructs driver to synchronize buffers
-
- arg:
- subdevice number
-
- reads:
- nothing
-
- writes:
- nothing
-
-*/
+ * COMEDI_POLL ioctl
+ * instructs driver to synchronize buffers
+ *
+ * arg:
+ * subdevice number
+ *
+ * reads:
+ * nothing
+ *
+ * writes:
+ * nothing
+ */
static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg,
void *file)
{
mutex_lock(&dev->mutex);
- /* Device config is special, because it must work on
- * an unconfigured device. */
+ /*
+ * Device config is special, because it must work on
+ * an unconfigured device.
+ */
if (cmd == COMEDI_DEVCONFIG) {
if (minor >= COMEDI_NUM_BOARD_MINORS) {
/* Device config not appropriate on non-board minors. */
if (rc == 0) {
if (arg == 0 &&
dev->minor >= comedi_num_legacy_minors) {
- /* Successfully unconfigured a dynamically
- * allocated device. Try and remove it. */
+ /*
+ * Successfully unconfigured a dynamically
+ * allocated device. Try and remove it.
+ */
if (comedi_clear_board_dev(dev)) {
mutex_unlock(&dev->mutex);
comedi_free_board_dev(dev);
.llseek = noop_llseek,
};
+/**
+ * comedi_event - handle events for asynchronous comedi command
+ * @dev: comedi_device struct
+ * @s: comedi_subdevice struct associated with dev
+ * Context: interrupt (usually), s->spin_lock spin-lock not held
+ *
+ * If an asynchronous comedi command is active on the subdevice, process
+ * any COMEDI_CB_... event flags that have been set, usually by an
+ * interrupt handler. These may change the run state of the asynchronous
+ * command, wake a task, and/or send a SIGIO signal.
+ */
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
{
struct comedi_async *async = s->async;
return;
if (s->async->events & COMEDI_CB_CANCEL_MASK)
- runflags_mask |= SRF_RUNNING;
+ runflags_mask |= COMEDI_SRF_RUNNING;
/*
* Remember if an error event has occurred, so an error
* can be returned the next time the user does a read().
*/
if (s->async->events & COMEDI_CB_ERROR_MASK) {
- runflags_mask |= SRF_ERROR;
- runflags |= SRF_ERROR;
+ runflags_mask |= COMEDI_SRF_ERROR;
+ runflags |= COMEDI_SRF_ERROR;
}
if (runflags_mask) {
- /*sets SRF_ERROR and SRF_RUNNING together atomically */
+ /*
+ * Sets COMEDI_SRF_ERROR and COMEDI_SRF_RUNNING together
+ * atomically.
+ */
comedi_set_subdevice_runflags(s, runflags_mask, runflags);
}