#include <linux/io.h>
#include <linux/uaccess.h>
-/* #include "kvmem.h" */
+#include "internal.h"
MODULE_AUTHOR("http://www.comedi.org");
MODULE_DESCRIPTION("Comedi core module");
MODULE_LICENSE("GPL");
+#define DEFAULT_BUF_MAXSIZE_KB 64
+#define DEFAULT_BUF_SIZE_KB 64
+
#ifdef CONFIG_COMEDI_DEBUG
int comedi_debug;
EXPORT_SYMBOL(comedi_debug);
-module_param(comedi_debug, int, 0644);
+module_param(comedi_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_debug,
+ "enable comedi core and driver debugging if non-zero (default 0)"
+ );
#endif
int comedi_autoconfig = 1;
-module_param(comedi_autoconfig, bool, 0444);
-
-int comedi_num_legacy_minors;
-module_param(comedi_num_legacy_minors, int, 0444);
+module_param(comedi_autoconfig, bool, S_IRUGO);
+MODULE_PARM_DESC(comedi_autoconfig,
+ "enable drivers to auto-configure comedi devices (default 1)");
+
+static int comedi_num_legacy_minors;
+module_param(comedi_num_legacy_minors, int, S_IRUGO);
+MODULE_PARM_DESC(comedi_num_legacy_minors,
+ "number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
+ );
+
+unsigned int comedi_default_buf_size_kb = DEFAULT_BUF_SIZE_KB;
+module_param(comedi_default_buf_size_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_default_buf_size_kb,
+ "default asynchronous buffer size in KiB (default "
+ __MODULE_STRING(DEFAULT_BUF_SIZE_KB) ")");
+
+unsigned int comedi_default_buf_maxsize_kb = DEFAULT_BUF_MAXSIZE_KB;
+module_param(comedi_default_buf_maxsize_kb, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
+ "default maximum size of asynchronous buffer in KiB (default "
+ __MODULE_STRING(DEFAULT_BUF_MAXSIZE_KB) ")");
static DEFINE_SPINLOCK(comedi_file_info_table_lock);
static struct comedi_device_file_info
*comedi_file_info_table[COMEDI_NUM_MINORS];
static int do_devconfig_ioctl(struct comedi_device *dev,
- struct comedi_devconfig *arg);
-static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg);
+ struct comedi_devconfig __user *arg);
+static int do_bufconfig_ioctl(struct comedi_device *dev,
+ struct comedi_bufconfig __user *arg);
static int do_devinfo_ioctl(struct comedi_device *dev,
- struct comedi_devinfo *arg, struct file *file);
+ struct comedi_devinfo __user *arg,
+ struct file *file);
static int do_subdinfo_ioctl(struct comedi_device *dev,
- struct comedi_subdinfo *arg, void *file);
+ struct comedi_subdinfo __user *arg, void *file);
static int do_chaninfo_ioctl(struct comedi_device *dev,
- struct comedi_chaninfo *arg);
-static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg);
-static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file);
+ struct comedi_chaninfo __user *arg);
+static int do_bufinfo_ioctl(struct comedi_device *dev,
+ struct comedi_bufinfo __user *arg, void *file);
+static int do_cmd_ioctl(struct comedi_device *dev,
+ struct comedi_cmd __user *arg, void *file);
static int do_lock_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
static int do_unlock_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
static int do_cancel_ioctl(struct comedi_device *dev, unsigned int arg,
void *file);
-static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file);
-static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file);
-static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file);
+static int do_cmdtest_ioctl(struct comedi_device *dev,
+ struct comedi_cmd __user *arg, void *file);
+static int do_insnlist_ioctl(struct comedi_device *dev,
+ struct comedi_insnlist __user *arg, void *file);
+static int do_insn_ioctl(struct comedi_device *dev,
+ struct comedi_insn __user *arg, void *file);
static int do_poll_ioctl(struct comedi_device *dev, unsigned int subd,
void *file);
-extern void do_become_nonbusy(struct comedi_device *dev,
+static void do_become_nonbusy(struct comedi_device *dev,
struct comedi_subdevice *s);
static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
/* Device config is special, because it must work on
* an unconfigured device. */
if (cmd == COMEDI_DEVCONFIG) {
- rc = do_devconfig_ioctl(dev, (void *)arg);
+ rc = do_devconfig_ioctl(dev,
+ (struct comedi_devconfig __user *)arg);
goto done;
}
switch (cmd) {
case COMEDI_BUFCONFIG:
- rc = do_bufconfig_ioctl(dev, (void *)arg);
+ rc = do_bufconfig_ioctl(dev,
+ (struct comedi_bufconfig __user *)arg);
break;
case COMEDI_DEVINFO:
- rc = do_devinfo_ioctl(dev, (void *)arg, file);
+ rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg,
+ file);
break;
case COMEDI_SUBDINFO:
- rc = do_subdinfo_ioctl(dev, (void *)arg, file);
+ rc = do_subdinfo_ioctl(dev,
+ (struct comedi_subdinfo __user *)arg,
+ file);
break;
case COMEDI_CHANINFO:
- rc = do_chaninfo_ioctl(dev, (void *)arg);
+ rc = do_chaninfo_ioctl(dev, (void __user *)arg);
break;
case COMEDI_RANGEINFO:
- rc = do_rangeinfo_ioctl(dev, (void *)arg);
+ rc = do_rangeinfo_ioctl(dev, (void __user *)arg);
break;
case COMEDI_BUFINFO:
- rc = do_bufinfo_ioctl(dev, (void *)arg);
+ rc = do_bufinfo_ioctl(dev,
+ (struct comedi_bufinfo __user *)arg,
+ file);
break;
case COMEDI_LOCK:
rc = do_lock_ioctl(dev, arg, file);
rc = do_cancel_ioctl(dev, arg, file);
break;
case COMEDI_CMD:
- rc = do_cmd_ioctl(dev, (void *)arg, file);
+ rc = do_cmd_ioctl(dev, (struct comedi_cmd __user *)arg, file);
break;
case COMEDI_CMDTEST:
- rc = do_cmdtest_ioctl(dev, (void *)arg, file);
+ rc = do_cmdtest_ioctl(dev, (struct comedi_cmd __user *)arg,
+ file);
break;
case COMEDI_INSNLIST:
- rc = do_insnlist_ioctl(dev, (void *)arg, file);
+ rc = do_insnlist_ioctl(dev,
+ (struct comedi_insnlist __user *)arg,
+ file);
break;
case COMEDI_INSN:
- rc = do_insn_ioctl(dev, (void *)arg, file);
+ rc = do_insn_ioctl(dev, (struct comedi_insn __user *)arg,
+ file);
break;
case COMEDI_POLL:
rc = do_poll_ioctl(dev, arg, file);
none
*/
static int do_devconfig_ioctl(struct comedi_device *dev,
- struct comedi_devconfig *arg)
+ struct comedi_devconfig __user *arg)
{
struct comedi_devconfig it;
int ret;
modified bufconfig at arg
*/
-static int do_bufconfig_ioctl(struct comedi_device *dev, void *arg)
+static int do_bufconfig_ioctl(struct comedi_device *dev,
+ struct comedi_bufconfig __user *arg)
{
struct comedi_bufconfig bc;
struct comedi_async *async;
*/
static int do_devinfo_ioctl(struct comedi_device *dev,
- struct comedi_devinfo *arg, struct file *file)
+ struct comedi_devinfo __user *arg,
+ struct file *file)
{
struct comedi_devinfo devinfo;
const unsigned minor = iminor(file->f_dentry->d_inode);
/* fill devinfo structure */
devinfo.version_code = COMEDI_VERSION_CODE;
devinfo.n_subdevs = dev->n_subdevices;
- memcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
- memcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
+ strlcpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
+ strlcpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
if (read_subdev)
devinfo.read_subdevice = read_subdev - dev->subdevices;
*/
static int do_subdinfo_ioctl(struct comedi_device *dev,
- struct comedi_subdinfo *arg, void *file)
+ struct comedi_subdinfo __user *arg, void *file)
{
int ret, i;
struct comedi_subdinfo *tmp, *us;
*/
static int do_chaninfo_ioctl(struct comedi_device *dev,
- struct comedi_chaninfo *arg)
+ struct comedi_chaninfo __user *arg)
{
struct comedi_subdevice *s;
struct comedi_chaninfo it;
x = (dev->minor << 28) | (it.subdev << 24) | (i << 16) |
(s->range_table_list[i]->length);
- put_user(x, it.rangelist + i);
+ if (put_user(x, it.rangelist + i))
+ return -EFAULT;
}
#if 0
if (copy_to_user(it.rangelist, s->range_type_list,
modified bufinfo at arg
*/
-static int do_bufinfo_ioctl(struct comedi_device *dev, void *arg)
+static int do_bufinfo_ioctl(struct comedi_device *dev,
+ struct comedi_bufinfo __user *arg, void *file)
{
struct comedi_bufinfo bi;
struct comedi_subdevice *s;
return -EINVAL;
s = dev->subdevices + bi.subdevice;
+
+ if (s->lock && s->lock != file)
+ return -EACCES;
+
async = s->async;
if (!async) {
bi.buf_read_ptr = 0;
bi.buf_write_count = 0;
bi.buf_read_count = 0;
+ bi.bytes_read = 0;
+ bi.bytes_written = 0;
goto copyback;
}
+ if (!s->busy) {
+ bi.bytes_read = 0;
+ bi.bytes_written = 0;
+ goto copyback_position;
+ }
+ if (s->busy != file)
+ return -EACCES;
if (bi.bytes_read && (s->subdev_flags & SDF_CMD_READ)) {
bi.bytes_read = comedi_buf_read_alloc(async, bi.bytes_read);
comedi_buf_write_free(async, bi.bytes_written);
}
+copyback_position:
bi.buf_write_count = async->buf_write_count;
bi.buf_write_ptr = async->buf_write_ptr;
bi.buf_read_count = async->buf_read_count;
*/
/* arbitrary limits */
#define MAX_SAMPLES 256
-static int do_insnlist_ioctl(struct comedi_device *dev, void *arg, void *file)
+static int do_insnlist_ioctl(struct comedi_device *dev,
+ struct comedi_insnlist __user *arg, void *file)
{
struct comedi_insnlist insnlist;
struct comedi_insn *insns = NULL;
}
insns =
- kmalloc(sizeof(struct comedi_insn) * insnlist.n_insns, GFP_KERNEL);
+ kcalloc(insnlist.n_insns, sizeof(struct comedi_insn), GFP_KERNEL);
if (!insns) {
DPRINTK("kmalloc failed\n");
ret = -ENOMEM;
case INSN_BITS:
if (insn->n != 2) {
ret = -EINVAL;
- break;
+ } else {
+ /* Most drivers ignore the base channel in
+ * insn->chanspec. Fix this here if
+ * the subdevice has <= 32 channels. */
+ unsigned int shift;
+ unsigned int orig_mask;
+
+ orig_mask = data[0];
+ if (s->n_chan <= 32) {
+ shift = CR_CHAN(insn->chanspec);
+ if (shift > 0) {
+ insn->chanspec = 0;
+ data[0] <<= shift;
+ data[1] <<= shift;
+ }
+ } else
+ shift = 0;
+ ret = s->insn_bits(dev, s, insn, data);
+ data[0] = orig_mask;
+ if (shift > 0)
+ data[1] >>= shift;
}
- ret = s->insn_bits(dev, s, insn, data);
break;
case INSN_CONFIG:
ret = check_insn_config_length(insn, data);
* writes:
* data (for reads)
*/
-static int do_insn_ioctl(struct comedi_device *dev, void *arg, void *file)
+static int do_insn_ioctl(struct comedi_device *dev,
+ struct comedi_insn __user *arg, void *file)
{
struct comedi_insn insn;
unsigned int *data = NULL;
if (insn.n > MAX_SAMPLES)
insn.n = MAX_SAMPLES;
if (insn.insn & INSN_MASK_WRITE) {
- if (copy_from_user
- (data, insn.data, insn.n * sizeof(unsigned int))) {
+ if (copy_from_user(data,
+ insn.data,
+ insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
if (ret < 0)
goto error;
if (insn.insn & INSN_MASK_READ) {
- if (copy_to_user
- (insn.data, data, insn.n * sizeof(unsigned int))) {
+ if (copy_to_user(insn.data,
+ data,
+ insn.n * sizeof(unsigned int))) {
ret = -EFAULT;
goto error;
}
spin_unlock_irqrestore(&s->spin_lock, flags);
}
-/*
- COMEDI_CMD
- command ioctl
-
- arg:
- pointer to cmd structure
-
- reads:
- cmd structure at arg
- channel/range list
-
- writes:
- modified cmd structure at arg
-
-*/
-static int do_cmd_ioctl(struct comedi_device *dev, void *arg, void *file)
+static int do_cmd_ioctl(struct comedi_device *dev,
+ struct comedi_cmd __user *cmd, void *file)
{
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
struct comedi_async *async;
int ret = 0;
- unsigned int *chanlist_saver = NULL;
+ unsigned int __user *chanlist_saver = NULL;
- if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
+ if (copy_from_user(&user_cmd, cmd, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
return -EFAULT;
}
}
/* make sure each element in channel/gain list is valid */
- ret = comedi_check_chanlist(s, async->cmd.chanlist_len, async->cmd.chanlist);
+ ret = comedi_check_chanlist(s,
+ async->cmd.chanlist_len,
+ async->cmd.chanlist);
if (ret < 0) {
DPRINTK("bad chanlist\n");
goto cleanup;
/* restore chanlist pointer before copying back */
user_cmd.chanlist = chanlist_saver;
user_cmd.data = NULL;
- if (copy_to_user(arg, &user_cmd, sizeof(struct comedi_cmd))) {
+ if (copy_to_user(cmd, &user_cmd, sizeof(struct comedi_cmd))) {
DPRINTK("fault writing cmd\n");
ret = -EFAULT;
goto cleanup;
modified cmd structure at arg
*/
-static int do_cmdtest_ioctl(struct comedi_device *dev, void *arg, void *file)
+static int do_cmdtest_ioctl(struct comedi_device *dev,
+ struct comedi_cmd __user *arg, void *file)
{
struct comedi_cmd user_cmd;
struct comedi_subdevice *s;
int ret = 0;
unsigned int *chanlist = NULL;
- unsigned int *chanlist_saver = NULL;
+ unsigned int __user *chanlist_saver = NULL;
if (copy_from_user(&user_cmd, arg, sizeof(struct comedi_cmd))) {
DPRINTK("bad cmd address\n");
s->lock = file;
spin_unlock_irqrestore(&s->spin_lock, flags);
+#if 0
if (ret < 0)
return ret;
-#if 0
if (s->lock_f)
ret = s->lock_f(dev, s);
#endif
return ret;
}
-void comedi_unmap(struct vm_area_struct *area)
+
+static void comedi_vm_open(struct vm_area_struct *area)
+{
+ struct comedi_async *async;
+ struct comedi_device *dev;
+
+ async = area->vm_private_data;
+ dev = async->subdevice->device;
+
+ mutex_lock(&dev->mutex);
+ async->mmap_count++;
+ mutex_unlock(&dev->mutex);
+}
+
+static void comedi_vm_close(struct vm_area_struct *area)
{
struct comedi_async *async;
struct comedi_device *dev;
}
static struct vm_operations_struct comedi_vm_ops = {
- .close = comedi_unmap,
+ .open = comedi_vm_open,
+ .close = comedi_vm_close,
};
static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
{
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
struct comedi_async *async = NULL;
unsigned long start = vma->vm_start;
unsigned long size;
int i;
int retval;
struct comedi_subdevice *s;
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+
+ dev_file_info = comedi_get_device_file_info(minor);
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
mutex_lock(&dev->mutex);
if (!dev->attached) {
{
unsigned int mask = 0;
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
struct comedi_subdevice *read_subdev;
struct comedi_subdevice *write_subdev;
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+ dev_file_info = comedi_get_device_file_info(minor);
+
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
mutex_lock(&dev->mutex);
if (!dev->attached) {
return mask;
}
-static ssize_t comedi_write(struct file *file, const char *buf, size_t nbytes,
- loff_t *offset)
+static ssize_t comedi_write(struct file *file, const char __user *buf,
+ size_t nbytes, loff_t *offset)
{
struct comedi_subdevice *s;
struct comedi_async *async;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+ dev_file_info = comedi_get_device_file_info(minor);
+
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
while (nbytes > 0 && !retval) {
set_current_state(TASK_INTERRUPTIBLE);
+ if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+ if (count == 0) {
+ if (comedi_get_subdevice_runflags(s) &
+ SRF_ERROR) {
+ retval = -EPIPE;
+ } else {
+ retval = 0;
+ }
+ do_become_nonbusy(dev, s);
+ }
+ break;
+ }
+
n = nbytes;
m = n;
n = m;
if (n == 0) {
- if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
- if (comedi_get_subdevice_runflags(s) &
- SRF_ERROR) {
- retval = -EPIPE;
- } else {
- retval = 0;
- }
- do_become_nonbusy(dev, s);
- break;
- }
if (file->f_flags & O_NONBLOCK) {
retval = -EAGAIN;
break;
}
+ schedule();
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
- schedule();
if (!s->busy)
break;
if (s->busy != file) {
return count ? count : retval;
}
-static ssize_t comedi_read(struct file *file, char *buf, size_t nbytes,
+static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
loff_t *offset)
{
struct comedi_subdevice *s;
int n, m, count = 0, retval = 0;
DECLARE_WAITQUEUE(wait, current);
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+ dev_file_info = comedi_get_device_file_info(minor);
+
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
if (!dev->attached) {
DPRINTK("no driver configured on comedi%i\n", dev->minor);
retval = -EAGAIN;
break;
}
+ schedule();
if (signal_pending(current)) {
retval = -ERESTARTSYS;
break;
}
- schedule();
if (!s->busy) {
retval = 0;
break;
}
}
- if (dev->attached && dev->use_count == 0 && dev->open)
- dev->open(dev);
+ if (dev->attached && dev->use_count == 0 && dev->open) {
+ int rc = dev->open(dev);
+ if (rc < 0) {
+ module_put(dev->driver->module);
+ module_put(THIS_MODULE);
+ mutex_unlock(&dev->mutex);
+ return rc;
+ }
+ }
dev->use_count++;
static int comedi_close(struct inode *inode, struct file *file)
{
const unsigned minor = iminor(inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
struct comedi_subdevice *s = NULL;
int i;
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+ dev_file_info = comedi_get_device_file_info(minor);
+
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
mutex_lock(&dev->mutex);
static int comedi_fasync(int fd, struct file *file, int on)
{
const unsigned minor = iminor(file->f_dentry->d_inode);
- struct comedi_device_file_info *dev_file_info =
- comedi_get_device_file_info(minor);
+ struct comedi_device_file_info *dev_file_info;
+ struct comedi_device *dev;
+ dev_file_info = comedi_get_device_file_info(minor);
- struct comedi_device *dev = dev_file_info->device;
+ if (dev_file_info == NULL)
+ return -ENODEV;
+ dev = dev_file_info->device;
+ if (dev == NULL)
+ return -ENODEV;
return fasync_helper(fd, file, on, &dev->async_queue);
}
.mmap = comedi_mmap,
.poll = comedi_poll,
.fasync = comedi_fasync,
+ .llseek = noop_llseek,
};
struct class *comedi_class;
COMEDI_CB_OVERFLOW)) {
runflags_mask |= SRF_RUNNING;
}
- /* remember if an error event has occured, so an error
+ /* 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 | COMEDI_CB_OVERFLOW)) {
runflags_mask |= SRF_ERROR;
return 0;
}
-void comedi_device_init(struct comedi_device *dev)
+static void comedi_device_init(struct comedi_device *dev)
{
memset(dev, 0, sizeof(struct comedi_device));
spin_lock_init(&dev->spinlock);
dev->minor = -1;
}
-void comedi_device_cleanup(struct comedi_device *dev)
+static void comedi_device_cleanup(struct comedi_device *dev)
{
if (dev == NULL)
return;
kfree(info->device);
kfree(info);
printk(KERN_ERR
-
- "comedi: error: ran out of minor numbers for board device files.\n");
+ "comedi: error: "
+ "ran out of minor numbers for board device files.\n");
return -EBUSY;
}
info->device->minor = i;
- csdev = COMEDI_DEVICE_CREATE(comedi_class, NULL,
- MKDEV(COMEDI_MAJOR, i), NULL,
- hardware_device, "comedi%i", i);
+ csdev = device_create(comedi_class, hardware_device,
+ MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
if (!IS_ERR(csdev))
info->device->class_dev = csdev;
dev_set_drvdata(csdev, info);
retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_read_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_read_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_write_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_write_buffer_kb.attr.name);
comedi_free_board_minor(i);
return retval;
}
return i;
}
-EXPORT_SYMBOL_GPL(comedi_alloc_board_minor);
void comedi_free_board_minor(unsigned minor)
{
kfree(info);
}
}
-EXPORT_SYMBOL_GPL(comedi_free_board_minor);
int comedi_alloc_subdevice_minor(struct comedi_device *dev,
struct comedi_subdevice *s)
if (i == COMEDI_NUM_MINORS) {
kfree(info);
printk(KERN_ERR
- "comedi: error: ran out of minor numbers for board device files.\n");
+ "comedi: error: "
+ "ran out of minor numbers for board device files.\n");
return -EBUSY;
}
s->minor = i;
- csdev = COMEDI_DEVICE_CREATE(comedi_class, dev->class_dev,
- MKDEV(COMEDI_MAJOR, i), NULL, NULL,
- "comedi%i_subd%i", dev->minor,
- (int)(s - dev->subdevices));
+ csdev = device_create(comedi_class, dev->class_dev,
+ MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
+ dev->minor, (int)(s - dev->subdevices));
if (!IS_ERR(csdev))
s->class_dev = csdev;
dev_set_drvdata(csdev, info);
retval = device_create_file(csdev, &dev_attr_max_read_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_read_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
retval = device_create_file(csdev, &dev_attr_read_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_read_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
retval = device_create_file(csdev, &dev_attr_max_write_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_max_write_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;
retval = device_create_file(csdev, &dev_attr_write_buffer_kb);
if (retval) {
printk(KERN_ERR
- "comedi: failed to create sysfs attribute file \"%s\".\n",
+ "comedi: "
+ "failed to create sysfs attribute file \"%s\".\n",
dev_attr_write_buffer_kb.attr.name);
comedi_free_subdevice_minor(s);
return retval;