Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/comedi/comedi_fops.c
26278 views
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
* comedi/comedi_fops.c
4
* comedi kernel module
5
*
6
* COMEDI - Linux Control and Measurement Device Interface
7
* Copyright (C) 1997-2007 David A. Schleef <[email protected]>
8
* compat ioctls:
9
* Author: Ian Abbott, MEV Ltd. <[email protected]>
10
* Copyright (C) 2007 MEV Ltd. <http://www.mev.co.uk/>
11
*/
12
13
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14
15
#include <linux/module.h>
16
#include <linux/errno.h>
17
#include <linux/kernel.h>
18
#include <linux/sched/signal.h>
19
#include <linux/fcntl.h>
20
#include <linux/delay.h>
21
#include <linux/mm.h>
22
#include <linux/slab.h>
23
#include <linux/poll.h>
24
#include <linux/device.h>
25
#include <linux/fs.h>
26
#include <linux/comedi/comedidev.h>
27
#include <linux/cdev.h>
28
29
#include <linux/io.h>
30
#include <linux/uaccess.h>
31
#include <linux/compat.h>
32
33
#include "comedi_internal.h"
34
35
/*
36
* comedi_subdevice "runflags"
37
* COMEDI_SRF_RT: DEPRECATED: command is running real-time
38
* COMEDI_SRF_ERROR: indicates an COMEDI_CB_ERROR event has occurred
39
* since the last command was started
40
* COMEDI_SRF_RUNNING: command is running
41
* COMEDI_SRF_FREE_SPRIV: free s->private on detach
42
*
43
* COMEDI_SRF_BUSY_MASK: runflags that indicate the subdevice is "busy"
44
*/
45
#define COMEDI_SRF_RT BIT(1)
46
#define COMEDI_SRF_ERROR BIT(2)
47
#define COMEDI_SRF_RUNNING BIT(27)
48
#define COMEDI_SRF_FREE_SPRIV BIT(31)
49
50
#define COMEDI_SRF_BUSY_MASK (COMEDI_SRF_ERROR | COMEDI_SRF_RUNNING)
51
52
/**
53
* struct comedi_file - Per-file private data for COMEDI device
54
* @dev: COMEDI device.
55
* @read_subdev: Current "read" subdevice.
56
* @write_subdev: Current "write" subdevice.
57
* @last_detach_count: Last known detach count.
58
* @last_attached: Last known attached/detached state.
59
*/
60
struct comedi_file {
61
struct comedi_device *dev;
62
struct comedi_subdevice *read_subdev;
63
struct comedi_subdevice *write_subdev;
64
unsigned int last_detach_count;
65
unsigned int last_attached:1;
66
};
67
68
#define COMEDI_NUM_MINORS 0x100
69
#define COMEDI_NUM_SUBDEVICE_MINORS \
70
(COMEDI_NUM_MINORS - COMEDI_NUM_BOARD_MINORS)
71
72
static unsigned short comedi_num_legacy_minors;
73
module_param(comedi_num_legacy_minors, ushort, 0444);
74
MODULE_PARM_DESC(comedi_num_legacy_minors,
75
"number of comedi minor devices to reserve for non-auto-configured devices (default 0)"
76
);
77
78
unsigned int comedi_default_buf_size_kb = CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB;
79
module_param(comedi_default_buf_size_kb, uint, 0644);
80
MODULE_PARM_DESC(comedi_default_buf_size_kb,
81
"default asynchronous buffer size in KiB (default "
82
__MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_SIZE_KB) ")");
83
84
unsigned int comedi_default_buf_maxsize_kb =
85
CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB;
86
module_param(comedi_default_buf_maxsize_kb, uint, 0644);
87
MODULE_PARM_DESC(comedi_default_buf_maxsize_kb,
88
"default maximum size of asynchronous buffer in KiB (default "
89
__MODULE_STRING(CONFIG_COMEDI_DEFAULT_BUF_MAXSIZE_KB) ")");
90
91
static DEFINE_MUTEX(comedi_board_minor_table_lock);
92
static struct comedi_device
93
*comedi_board_minor_table[COMEDI_NUM_BOARD_MINORS];
94
95
static DEFINE_MUTEX(comedi_subdevice_minor_table_lock);
96
/* Note: indexed by minor - COMEDI_NUM_BOARD_MINORS. */
97
static struct comedi_subdevice
98
*comedi_subdevice_minor_table[COMEDI_NUM_SUBDEVICE_MINORS];
99
100
static struct cdev comedi_cdev;
101
102
static void comedi_device_init(struct comedi_device *dev)
103
{
104
kref_init(&dev->refcount);
105
spin_lock_init(&dev->spinlock);
106
mutex_init(&dev->mutex);
107
init_rwsem(&dev->attach_lock);
108
dev->minor = -1;
109
}
110
111
static void comedi_dev_kref_release(struct kref *kref)
112
{
113
struct comedi_device *dev =
114
container_of(kref, struct comedi_device, refcount);
115
116
mutex_destroy(&dev->mutex);
117
put_device(dev->class_dev);
118
kfree(dev);
119
}
120
121
/**
122
* comedi_dev_put() - Release a use of a COMEDI device
123
* @dev: COMEDI device.
124
*
125
* Must be called when a user of a COMEDI device is finished with it.
126
* When the last user of the COMEDI device calls this function, the
127
* COMEDI device is destroyed.
128
*
129
* Return: 1 if the COMEDI device is destroyed by this call or @dev is
130
* NULL, otherwise return 0. Callers must not assume the COMEDI
131
* device is still valid if this function returns 0.
132
*/
133
int comedi_dev_put(struct comedi_device *dev)
134
{
135
if (dev)
136
return kref_put(&dev->refcount, comedi_dev_kref_release);
137
return 1;
138
}
139
EXPORT_SYMBOL_GPL(comedi_dev_put);
140
141
static struct comedi_device *comedi_dev_get(struct comedi_device *dev)
142
{
143
if (dev)
144
kref_get(&dev->refcount);
145
return dev;
146
}
147
148
static void comedi_device_cleanup(struct comedi_device *dev)
149
{
150
struct module *driver_module = NULL;
151
152
if (!dev)
153
return;
154
mutex_lock(&dev->mutex);
155
if (dev->attached)
156
driver_module = dev->driver->module;
157
comedi_device_detach(dev);
158
if (driver_module && dev->use_count)
159
module_put(driver_module);
160
mutex_unlock(&dev->mutex);
161
}
162
163
static bool comedi_clear_board_dev(struct comedi_device *dev)
164
{
165
unsigned int i = dev->minor;
166
bool cleared = false;
167
168
lockdep_assert_held(&dev->mutex);
169
mutex_lock(&comedi_board_minor_table_lock);
170
if (dev == comedi_board_minor_table[i]) {
171
comedi_board_minor_table[i] = NULL;
172
cleared = true;
173
}
174
mutex_unlock(&comedi_board_minor_table_lock);
175
return cleared;
176
}
177
178
static struct comedi_device *comedi_clear_board_minor(unsigned int minor)
179
{
180
struct comedi_device *dev;
181
182
mutex_lock(&comedi_board_minor_table_lock);
183
dev = comedi_board_minor_table[minor];
184
comedi_board_minor_table[minor] = NULL;
185
mutex_unlock(&comedi_board_minor_table_lock);
186
return dev;
187
}
188
189
static struct comedi_subdevice *
190
comedi_subdevice_from_minor(const struct comedi_device *dev, unsigned int minor)
191
{
192
struct comedi_subdevice *s;
193
unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
194
195
mutex_lock(&comedi_subdevice_minor_table_lock);
196
s = comedi_subdevice_minor_table[i];
197
if (s && s->device != dev)
198
s = NULL;
199
mutex_unlock(&comedi_subdevice_minor_table_lock);
200
return s;
201
}
202
203
static struct comedi_device *comedi_dev_get_from_board_minor(unsigned int minor)
204
{
205
struct comedi_device *dev;
206
207
mutex_lock(&comedi_board_minor_table_lock);
208
dev = comedi_dev_get(comedi_board_minor_table[minor]);
209
mutex_unlock(&comedi_board_minor_table_lock);
210
return dev;
211
}
212
213
static struct comedi_device *
214
comedi_dev_get_from_subdevice_minor(unsigned int minor)
215
{
216
struct comedi_device *dev;
217
struct comedi_subdevice *s;
218
unsigned int i = minor - COMEDI_NUM_BOARD_MINORS;
219
220
mutex_lock(&comedi_subdevice_minor_table_lock);
221
s = comedi_subdevice_minor_table[i];
222
dev = comedi_dev_get(s ? s->device : NULL);
223
mutex_unlock(&comedi_subdevice_minor_table_lock);
224
return dev;
225
}
226
227
/**
228
* comedi_dev_get_from_minor() - Get COMEDI device by minor device number
229
* @minor: Minor device number.
230
*
231
* Finds the COMEDI device associated with the minor device number, if any,
232
* and increments its reference count. The COMEDI device is prevented from
233
* being freed until a matching call is made to comedi_dev_put().
234
*
235
* Return: A pointer to the COMEDI device if it exists, with its usage
236
* reference incremented. Return NULL if no COMEDI device exists with the
237
* specified minor device number.
238
*/
239
struct comedi_device *comedi_dev_get_from_minor(unsigned int minor)
240
{
241
if (minor < COMEDI_NUM_BOARD_MINORS)
242
return comedi_dev_get_from_board_minor(minor);
243
244
return comedi_dev_get_from_subdevice_minor(minor);
245
}
246
EXPORT_SYMBOL_GPL(comedi_dev_get_from_minor);
247
248
static struct comedi_subdevice *
249
comedi_read_subdevice(const struct comedi_device *dev, unsigned int minor)
250
{
251
struct comedi_subdevice *s;
252
253
lockdep_assert_held(&dev->mutex);
254
if (minor >= COMEDI_NUM_BOARD_MINORS) {
255
s = comedi_subdevice_from_minor(dev, minor);
256
if (!s || (s->subdev_flags & SDF_CMD_READ))
257
return s;
258
}
259
return dev->read_subdev;
260
}
261
262
static struct comedi_subdevice *
263
comedi_write_subdevice(const struct comedi_device *dev, unsigned int minor)
264
{
265
struct comedi_subdevice *s;
266
267
lockdep_assert_held(&dev->mutex);
268
if (minor >= COMEDI_NUM_BOARD_MINORS) {
269
s = comedi_subdevice_from_minor(dev, minor);
270
if (!s || (s->subdev_flags & SDF_CMD_WRITE))
271
return s;
272
}
273
return dev->write_subdev;
274
}
275
276
static void comedi_file_reset(struct file *file)
277
{
278
struct comedi_file *cfp = file->private_data;
279
struct comedi_device *dev = cfp->dev;
280
struct comedi_subdevice *s, *read_s, *write_s;
281
unsigned int minor = iminor(file_inode(file));
282
283
read_s = dev->read_subdev;
284
write_s = dev->write_subdev;
285
if (minor >= COMEDI_NUM_BOARD_MINORS) {
286
s = comedi_subdevice_from_minor(dev, minor);
287
if (!s || s->subdev_flags & SDF_CMD_READ)
288
read_s = s;
289
if (!s || s->subdev_flags & SDF_CMD_WRITE)
290
write_s = s;
291
}
292
cfp->last_attached = dev->attached;
293
cfp->last_detach_count = dev->detach_count;
294
WRITE_ONCE(cfp->read_subdev, read_s);
295
WRITE_ONCE(cfp->write_subdev, write_s);
296
}
297
298
static void comedi_file_check(struct file *file)
299
{
300
struct comedi_file *cfp = file->private_data;
301
struct comedi_device *dev = cfp->dev;
302
303
if (cfp->last_attached != dev->attached ||
304
cfp->last_detach_count != dev->detach_count)
305
comedi_file_reset(file);
306
}
307
308
static struct comedi_subdevice *comedi_file_read_subdevice(struct file *file)
309
{
310
struct comedi_file *cfp = file->private_data;
311
312
comedi_file_check(file);
313
return READ_ONCE(cfp->read_subdev);
314
}
315
316
static struct comedi_subdevice *comedi_file_write_subdevice(struct file *file)
317
{
318
struct comedi_file *cfp = file->private_data;
319
320
comedi_file_check(file);
321
return READ_ONCE(cfp->write_subdev);
322
}
323
324
static int resize_async_buffer(struct comedi_device *dev,
325
struct comedi_subdevice *s,
326
unsigned int new_size)
327
{
328
struct comedi_async *async = s->async;
329
int retval;
330
331
lockdep_assert_held(&dev->mutex);
332
333
if (new_size > async->max_bufsize)
334
return -EPERM;
335
336
if (s->busy) {
337
dev_dbg(dev->class_dev,
338
"subdevice is busy, cannot resize buffer\n");
339
return -EBUSY;
340
}
341
if (comedi_buf_is_mmapped(s)) {
342
dev_dbg(dev->class_dev,
343
"subdevice is mmapped, cannot resize buffer\n");
344
return -EBUSY;
345
}
346
347
/* make sure buffer is an integral number of pages (we round up) */
348
new_size = (new_size + PAGE_SIZE - 1) & PAGE_MASK;
349
350
retval = comedi_buf_alloc(dev, s, new_size);
351
if (retval < 0)
352
return retval;
353
354
if (s->buf_change) {
355
retval = s->buf_change(dev, s);
356
if (retval < 0)
357
return retval;
358
}
359
360
dev_dbg(dev->class_dev, "subd %d buffer resized to %i bytes\n",
361
s->index, async->prealloc_bufsz);
362
return 0;
363
}
364
365
/* sysfs attribute files */
366
367
static ssize_t max_read_buffer_kb_show(struct device *csdev,
368
struct device_attribute *attr, char *buf)
369
{
370
unsigned int minor = MINOR(csdev->devt);
371
struct comedi_device *dev;
372
struct comedi_subdevice *s;
373
unsigned int size = 0;
374
375
dev = comedi_dev_get_from_minor(minor);
376
if (!dev)
377
return -ENODEV;
378
379
mutex_lock(&dev->mutex);
380
s = comedi_read_subdevice(dev, minor);
381
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
382
size = s->async->max_bufsize / 1024;
383
mutex_unlock(&dev->mutex);
384
385
comedi_dev_put(dev);
386
return sysfs_emit(buf, "%u\n", size);
387
}
388
389
static ssize_t max_read_buffer_kb_store(struct device *csdev,
390
struct device_attribute *attr,
391
const char *buf, size_t count)
392
{
393
unsigned int minor = MINOR(csdev->devt);
394
struct comedi_device *dev;
395
struct comedi_subdevice *s;
396
unsigned int size;
397
int err;
398
399
err = kstrtouint(buf, 10, &size);
400
if (err)
401
return err;
402
if (size > (UINT_MAX / 1024))
403
return -EINVAL;
404
size *= 1024;
405
406
dev = comedi_dev_get_from_minor(minor);
407
if (!dev)
408
return -ENODEV;
409
410
mutex_lock(&dev->mutex);
411
s = comedi_read_subdevice(dev, minor);
412
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
413
s->async->max_bufsize = size;
414
else
415
err = -EINVAL;
416
mutex_unlock(&dev->mutex);
417
418
comedi_dev_put(dev);
419
return err ? err : count;
420
}
421
static DEVICE_ATTR_RW(max_read_buffer_kb);
422
423
static ssize_t read_buffer_kb_show(struct device *csdev,
424
struct device_attribute *attr, char *buf)
425
{
426
unsigned int minor = MINOR(csdev->devt);
427
struct comedi_device *dev;
428
struct comedi_subdevice *s;
429
unsigned int size = 0;
430
431
dev = comedi_dev_get_from_minor(minor);
432
if (!dev)
433
return -ENODEV;
434
435
mutex_lock(&dev->mutex);
436
s = comedi_read_subdevice(dev, minor);
437
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
438
size = s->async->prealloc_bufsz / 1024;
439
mutex_unlock(&dev->mutex);
440
441
comedi_dev_put(dev);
442
return sysfs_emit(buf, "%u\n", size);
443
}
444
445
static ssize_t read_buffer_kb_store(struct device *csdev,
446
struct device_attribute *attr,
447
const char *buf, size_t count)
448
{
449
unsigned int minor = MINOR(csdev->devt);
450
struct comedi_device *dev;
451
struct comedi_subdevice *s;
452
unsigned int size;
453
int err;
454
455
err = kstrtouint(buf, 10, &size);
456
if (err)
457
return err;
458
if (size > (UINT_MAX / 1024))
459
return -EINVAL;
460
size *= 1024;
461
462
dev = comedi_dev_get_from_minor(minor);
463
if (!dev)
464
return -ENODEV;
465
466
mutex_lock(&dev->mutex);
467
s = comedi_read_subdevice(dev, minor);
468
if (s && (s->subdev_flags & SDF_CMD_READ) && s->async)
469
err = resize_async_buffer(dev, s, size);
470
else
471
err = -EINVAL;
472
mutex_unlock(&dev->mutex);
473
474
comedi_dev_put(dev);
475
return err ? err : count;
476
}
477
static DEVICE_ATTR_RW(read_buffer_kb);
478
479
static ssize_t max_write_buffer_kb_show(struct device *csdev,
480
struct device_attribute *attr,
481
char *buf)
482
{
483
unsigned int minor = MINOR(csdev->devt);
484
struct comedi_device *dev;
485
struct comedi_subdevice *s;
486
unsigned int size = 0;
487
488
dev = comedi_dev_get_from_minor(minor);
489
if (!dev)
490
return -ENODEV;
491
492
mutex_lock(&dev->mutex);
493
s = comedi_write_subdevice(dev, minor);
494
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
495
size = s->async->max_bufsize / 1024;
496
mutex_unlock(&dev->mutex);
497
498
comedi_dev_put(dev);
499
return sysfs_emit(buf, "%u\n", size);
500
}
501
502
static ssize_t max_write_buffer_kb_store(struct device *csdev,
503
struct device_attribute *attr,
504
const char *buf, size_t count)
505
{
506
unsigned int minor = MINOR(csdev->devt);
507
struct comedi_device *dev;
508
struct comedi_subdevice *s;
509
unsigned int size;
510
int err;
511
512
err = kstrtouint(buf, 10, &size);
513
if (err)
514
return err;
515
if (size > (UINT_MAX / 1024))
516
return -EINVAL;
517
size *= 1024;
518
519
dev = comedi_dev_get_from_minor(minor);
520
if (!dev)
521
return -ENODEV;
522
523
mutex_lock(&dev->mutex);
524
s = comedi_write_subdevice(dev, minor);
525
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
526
s->async->max_bufsize = size;
527
else
528
err = -EINVAL;
529
mutex_unlock(&dev->mutex);
530
531
comedi_dev_put(dev);
532
return err ? err : count;
533
}
534
static DEVICE_ATTR_RW(max_write_buffer_kb);
535
536
static ssize_t write_buffer_kb_show(struct device *csdev,
537
struct device_attribute *attr, char *buf)
538
{
539
unsigned int minor = MINOR(csdev->devt);
540
struct comedi_device *dev;
541
struct comedi_subdevice *s;
542
unsigned int size = 0;
543
544
dev = comedi_dev_get_from_minor(minor);
545
if (!dev)
546
return -ENODEV;
547
548
mutex_lock(&dev->mutex);
549
s = comedi_write_subdevice(dev, minor);
550
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
551
size = s->async->prealloc_bufsz / 1024;
552
mutex_unlock(&dev->mutex);
553
554
comedi_dev_put(dev);
555
return sysfs_emit(buf, "%u\n", size);
556
}
557
558
static ssize_t write_buffer_kb_store(struct device *csdev,
559
struct device_attribute *attr,
560
const char *buf, size_t count)
561
{
562
unsigned int minor = MINOR(csdev->devt);
563
struct comedi_device *dev;
564
struct comedi_subdevice *s;
565
unsigned int size;
566
int err;
567
568
err = kstrtouint(buf, 10, &size);
569
if (err)
570
return err;
571
if (size > (UINT_MAX / 1024))
572
return -EINVAL;
573
size *= 1024;
574
575
dev = comedi_dev_get_from_minor(minor);
576
if (!dev)
577
return -ENODEV;
578
579
mutex_lock(&dev->mutex);
580
s = comedi_write_subdevice(dev, minor);
581
if (s && (s->subdev_flags & SDF_CMD_WRITE) && s->async)
582
err = resize_async_buffer(dev, s, size);
583
else
584
err = -EINVAL;
585
mutex_unlock(&dev->mutex);
586
587
comedi_dev_put(dev);
588
return err ? err : count;
589
}
590
static DEVICE_ATTR_RW(write_buffer_kb);
591
592
static struct attribute *comedi_dev_attrs[] = {
593
&dev_attr_max_read_buffer_kb.attr,
594
&dev_attr_read_buffer_kb.attr,
595
&dev_attr_max_write_buffer_kb.attr,
596
&dev_attr_write_buffer_kb.attr,
597
NULL,
598
};
599
ATTRIBUTE_GROUPS(comedi_dev);
600
601
static const struct class comedi_class = {
602
.name = "comedi",
603
.dev_groups = comedi_dev_groups,
604
};
605
606
static void comedi_free_board_dev(struct comedi_device *dev)
607
{
608
if (dev) {
609
comedi_device_cleanup(dev);
610
if (dev->class_dev) {
611
device_destroy(&comedi_class,
612
MKDEV(COMEDI_MAJOR, dev->minor));
613
}
614
comedi_dev_put(dev);
615
}
616
}
617
618
static void __comedi_clear_subdevice_runflags(struct comedi_subdevice *s,
619
unsigned int bits)
620
{
621
s->runflags &= ~bits;
622
}
623
624
static void __comedi_set_subdevice_runflags(struct comedi_subdevice *s,
625
unsigned int bits)
626
{
627
s->runflags |= bits;
628
}
629
630
static void comedi_update_subdevice_runflags(struct comedi_subdevice *s,
631
unsigned int mask,
632
unsigned int bits)
633
{
634
unsigned long flags;
635
636
spin_lock_irqsave(&s->spin_lock, flags);
637
__comedi_clear_subdevice_runflags(s, mask);
638
__comedi_set_subdevice_runflags(s, bits & mask);
639
spin_unlock_irqrestore(&s->spin_lock, flags);
640
}
641
642
static unsigned int __comedi_get_subdevice_runflags(struct comedi_subdevice *s)
643
{
644
return s->runflags;
645
}
646
647
static unsigned int comedi_get_subdevice_runflags(struct comedi_subdevice *s)
648
{
649
unsigned long flags;
650
unsigned int runflags;
651
652
spin_lock_irqsave(&s->spin_lock, flags);
653
runflags = __comedi_get_subdevice_runflags(s);
654
spin_unlock_irqrestore(&s->spin_lock, flags);
655
return runflags;
656
}
657
658
static bool comedi_is_runflags_running(unsigned int runflags)
659
{
660
return runflags & COMEDI_SRF_RUNNING;
661
}
662
663
static bool comedi_is_runflags_in_error(unsigned int runflags)
664
{
665
return runflags & COMEDI_SRF_ERROR;
666
}
667
668
/**
669
* comedi_is_subdevice_running() - Check if async command running on subdevice
670
* @s: COMEDI subdevice.
671
*
672
* Return: %true if an asynchronous COMEDI command is active on the
673
* subdevice, else %false.
674
*/
675
bool comedi_is_subdevice_running(struct comedi_subdevice *s)
676
{
677
unsigned int runflags = comedi_get_subdevice_runflags(s);
678
679
return comedi_is_runflags_running(runflags);
680
}
681
EXPORT_SYMBOL_GPL(comedi_is_subdevice_running);
682
683
static bool __comedi_is_subdevice_running(struct comedi_subdevice *s)
684
{
685
unsigned int runflags = __comedi_get_subdevice_runflags(s);
686
687
return comedi_is_runflags_running(runflags);
688
}
689
690
bool comedi_can_auto_free_spriv(struct comedi_subdevice *s)
691
{
692
unsigned int runflags = __comedi_get_subdevice_runflags(s);
693
694
return runflags & COMEDI_SRF_FREE_SPRIV;
695
}
696
697
/**
698
* comedi_set_spriv_auto_free() - Mark subdevice private data as freeable
699
* @s: COMEDI subdevice.
700
*
701
* Mark the subdevice as having a pointer to private data that can be
702
* automatically freed when the COMEDI device is detached from the low-level
703
* driver.
704
*/
705
void comedi_set_spriv_auto_free(struct comedi_subdevice *s)
706
{
707
__comedi_set_subdevice_runflags(s, COMEDI_SRF_FREE_SPRIV);
708
}
709
EXPORT_SYMBOL_GPL(comedi_set_spriv_auto_free);
710
711
/**
712
* comedi_alloc_spriv - Allocate memory for the subdevice private data
713
* @s: COMEDI subdevice.
714
* @size: Size of the memory to allocate.
715
*
716
* Allocate memory for the subdevice private data and point @s->private
717
* to it. The memory will be freed automatically when the COMEDI device
718
* is detached from the low-level driver.
719
*
720
* Return: A pointer to the allocated memory @s->private on success.
721
* Return NULL on failure.
722
*/
723
void *comedi_alloc_spriv(struct comedi_subdevice *s, size_t size)
724
{
725
s->private = kzalloc(size, GFP_KERNEL);
726
if (s->private)
727
comedi_set_spriv_auto_free(s);
728
return s->private;
729
}
730
EXPORT_SYMBOL_GPL(comedi_alloc_spriv);
731
732
/*
733
* This function restores a subdevice to an idle state.
734
*/
735
static void do_become_nonbusy(struct comedi_device *dev,
736
struct comedi_subdevice *s)
737
{
738
struct comedi_async *async = s->async;
739
740
lockdep_assert_held(&dev->mutex);
741
comedi_update_subdevice_runflags(s, COMEDI_SRF_RUNNING, 0);
742
if (async) {
743
comedi_buf_reset(s);
744
async->inttrig = NULL;
745
kfree(async->cmd.chanlist);
746
async->cmd.chanlist = NULL;
747
s->busy = NULL;
748
wake_up_interruptible_all(&async->wait_head);
749
} else {
750
dev_err(dev->class_dev,
751
"BUG: (?) %s called with async=NULL\n", __func__);
752
s->busy = NULL;
753
}
754
}
755
756
static int do_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
757
{
758
int ret = 0;
759
760
lockdep_assert_held(&dev->mutex);
761
if (comedi_is_subdevice_running(s) && s->cancel)
762
ret = s->cancel(dev, s);
763
764
do_become_nonbusy(dev, s);
765
766
return ret;
767
}
768
769
void comedi_device_cancel_all(struct comedi_device *dev)
770
{
771
struct comedi_subdevice *s;
772
int i;
773
774
lockdep_assert_held(&dev->mutex);
775
if (!dev->attached)
776
return;
777
778
for (i = 0; i < dev->n_subdevices; i++) {
779
s = &dev->subdevices[i];
780
if (s->async)
781
do_cancel(dev, s);
782
}
783
}
784
785
static int is_device_busy(struct comedi_device *dev)
786
{
787
struct comedi_subdevice *s;
788
int i;
789
790
lockdep_assert_held_write(&dev->attach_lock);
791
lockdep_assert_held(&dev->mutex);
792
if (!dev->attached)
793
return 0;
794
795
for (i = 0; i < dev->n_subdevices; i++) {
796
s = &dev->subdevices[i];
797
if (s->busy)
798
return 1;
799
if (!s->async)
800
continue;
801
if (comedi_buf_is_mmapped(s))
802
return 1;
803
/*
804
* There may be tasks still waiting on the subdevice's wait
805
* queue, although they should already be about to be removed
806
* from it since the subdevice has no active async command.
807
*/
808
if (wq_has_sleeper(&s->async->wait_head))
809
return 1;
810
}
811
812
return 0;
813
}
814
815
/*
816
* COMEDI_DEVCONFIG ioctl
817
* attaches (and configures) or detaches a legacy device
818
*
819
* arg:
820
* pointer to comedi_devconfig structure (NULL if detaching)
821
*
822
* reads:
823
* comedi_devconfig structure (if attaching)
824
*
825
* writes:
826
* nothing
827
*/
828
static int do_devconfig_ioctl(struct comedi_device *dev,
829
struct comedi_devconfig __user *arg)
830
{
831
struct comedi_devconfig it;
832
833
lockdep_assert_held(&dev->mutex);
834
if (!capable(CAP_SYS_ADMIN))
835
return -EPERM;
836
837
if (!arg) {
838
int rc = 0;
839
840
if (dev->attached) {
841
down_write(&dev->attach_lock);
842
if (is_device_busy(dev)) {
843
rc = -EBUSY;
844
} else {
845
struct module *driver_module =
846
dev->driver->module;
847
848
comedi_device_detach_locked(dev);
849
module_put(driver_module);
850
}
851
up_write(&dev->attach_lock);
852
}
853
return rc;
854
}
855
856
if (copy_from_user(&it, arg, sizeof(it)))
857
return -EFAULT;
858
859
it.board_name[COMEDI_NAMELEN - 1] = 0;
860
861
if (it.options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) {
862
dev_warn(dev->class_dev,
863
"comedi_config --init_data is deprecated\n");
864
return -EINVAL;
865
}
866
867
if (dev->minor >= comedi_num_legacy_minors)
868
/* don't re-use dynamically allocated comedi devices */
869
return -EBUSY;
870
871
/* This increments the driver module count on success. */
872
return comedi_device_attach(dev, &it);
873
}
874
875
/*
876
* COMEDI_BUFCONFIG ioctl
877
* buffer configuration
878
*
879
* arg:
880
* pointer to comedi_bufconfig structure
881
*
882
* reads:
883
* comedi_bufconfig structure
884
*
885
* writes:
886
* modified comedi_bufconfig structure
887
*/
888
static int do_bufconfig_ioctl(struct comedi_device *dev,
889
struct comedi_bufconfig __user *arg)
890
{
891
struct comedi_bufconfig bc;
892
struct comedi_async *async;
893
struct comedi_subdevice *s;
894
int retval = 0;
895
896
lockdep_assert_held(&dev->mutex);
897
if (copy_from_user(&bc, arg, sizeof(bc)))
898
return -EFAULT;
899
900
if (bc.subdevice >= dev->n_subdevices)
901
return -EINVAL;
902
903
s = &dev->subdevices[bc.subdevice];
904
async = s->async;
905
906
if (!async) {
907
dev_dbg(dev->class_dev,
908
"subdevice does not have async capability\n");
909
bc.size = 0;
910
bc.maximum_size = 0;
911
goto copyback;
912
}
913
914
if (bc.maximum_size) {
915
if (!capable(CAP_SYS_ADMIN))
916
return -EPERM;
917
918
async->max_bufsize = bc.maximum_size;
919
}
920
921
if (bc.size) {
922
retval = resize_async_buffer(dev, s, bc.size);
923
if (retval < 0)
924
return retval;
925
}
926
927
bc.size = async->prealloc_bufsz;
928
bc.maximum_size = async->max_bufsize;
929
930
copyback:
931
if (copy_to_user(arg, &bc, sizeof(bc)))
932
return -EFAULT;
933
934
return 0;
935
}
936
937
/*
938
* COMEDI_DEVINFO ioctl
939
* device info
940
*
941
* arg:
942
* pointer to comedi_devinfo structure
943
*
944
* reads:
945
* nothing
946
*
947
* writes:
948
* comedi_devinfo structure
949
*/
950
static int do_devinfo_ioctl(struct comedi_device *dev,
951
struct comedi_devinfo __user *arg,
952
struct file *file)
953
{
954
struct comedi_subdevice *s;
955
struct comedi_devinfo devinfo;
956
957
lockdep_assert_held(&dev->mutex);
958
memset(&devinfo, 0, sizeof(devinfo));
959
960
/* fill devinfo structure */
961
devinfo.version_code = COMEDI_VERSION_CODE;
962
devinfo.n_subdevs = dev->n_subdevices;
963
strscpy(devinfo.driver_name, dev->driver->driver_name, COMEDI_NAMELEN);
964
strscpy(devinfo.board_name, dev->board_name, COMEDI_NAMELEN);
965
966
s = comedi_file_read_subdevice(file);
967
if (s)
968
devinfo.read_subdevice = s->index;
969
else
970
devinfo.read_subdevice = -1;
971
972
s = comedi_file_write_subdevice(file);
973
if (s)
974
devinfo.write_subdevice = s->index;
975
else
976
devinfo.write_subdevice = -1;
977
978
if (copy_to_user(arg, &devinfo, sizeof(devinfo)))
979
return -EFAULT;
980
981
return 0;
982
}
983
984
/*
985
* COMEDI_SUBDINFO ioctl
986
* subdevices info
987
*
988
* arg:
989
* pointer to array of comedi_subdinfo structures
990
*
991
* reads:
992
* nothing
993
*
994
* writes:
995
* array of comedi_subdinfo structures
996
*/
997
static int do_subdinfo_ioctl(struct comedi_device *dev,
998
struct comedi_subdinfo __user *arg, void *file)
999
{
1000
int ret, i;
1001
struct comedi_subdinfo *tmp, *us;
1002
struct comedi_subdevice *s;
1003
1004
lockdep_assert_held(&dev->mutex);
1005
tmp = kcalloc(dev->n_subdevices, sizeof(*tmp), GFP_KERNEL);
1006
if (!tmp)
1007
return -ENOMEM;
1008
1009
/* fill subdinfo structs */
1010
for (i = 0; i < dev->n_subdevices; i++) {
1011
s = &dev->subdevices[i];
1012
us = tmp + i;
1013
1014
us->type = s->type;
1015
us->n_chan = s->n_chan;
1016
us->subd_flags = s->subdev_flags;
1017
if (comedi_is_subdevice_running(s))
1018
us->subd_flags |= SDF_RUNNING;
1019
#define TIMER_nanosec 5 /* backwards compatibility */
1020
us->timer_type = TIMER_nanosec;
1021
us->len_chanlist = s->len_chanlist;
1022
us->maxdata = s->maxdata;
1023
if (s->range_table) {
1024
us->range_type =
1025
(i << 24) | (0 << 16) | (s->range_table->length);
1026
} else {
1027
us->range_type = 0; /* XXX */
1028
}
1029
1030
if (s->busy)
1031
us->subd_flags |= SDF_BUSY;
1032
if (s->busy == file)
1033
us->subd_flags |= SDF_BUSY_OWNER;
1034
if (s->lock)
1035
us->subd_flags |= SDF_LOCKED;
1036
if (s->lock == file)
1037
us->subd_flags |= SDF_LOCK_OWNER;
1038
if (!s->maxdata && s->maxdata_list)
1039
us->subd_flags |= SDF_MAXDATA;
1040
if (s->range_table_list)
1041
us->subd_flags |= SDF_RANGETYPE;
1042
if (s->do_cmd)
1043
us->subd_flags |= SDF_CMD;
1044
1045
if (s->insn_bits != &insn_inval)
1046
us->insn_bits_support = COMEDI_SUPPORTED;
1047
else
1048
us->insn_bits_support = COMEDI_UNSUPPORTED;
1049
}
1050
1051
ret = copy_to_user(arg, tmp, dev->n_subdevices * sizeof(*tmp));
1052
1053
kfree(tmp);
1054
1055
return ret ? -EFAULT : 0;
1056
}
1057
1058
/*
1059
* COMEDI_CHANINFO ioctl
1060
* subdevice channel info
1061
*
1062
* arg:
1063
* pointer to comedi_chaninfo structure
1064
*
1065
* reads:
1066
* comedi_chaninfo structure
1067
*
1068
* writes:
1069
* array of maxdata values to chaninfo->maxdata_list if requested
1070
* array of range table lengths to chaninfo->range_table_list if requested
1071
*/
1072
static int do_chaninfo_ioctl(struct comedi_device *dev,
1073
struct comedi_chaninfo *it)
1074
{
1075
struct comedi_subdevice *s;
1076
1077
lockdep_assert_held(&dev->mutex);
1078
1079
if (it->subdev >= dev->n_subdevices)
1080
return -EINVAL;
1081
s = &dev->subdevices[it->subdev];
1082
1083
if (it->maxdata_list) {
1084
if (s->maxdata || !s->maxdata_list)
1085
return -EINVAL;
1086
if (copy_to_user(it->maxdata_list, s->maxdata_list,
1087
s->n_chan * sizeof(unsigned int)))
1088
return -EFAULT;
1089
}
1090
1091
if (it->flaglist)
1092
return -EINVAL; /* flaglist not supported */
1093
1094
if (it->rangelist) {
1095
int i;
1096
1097
if (!s->range_table_list)
1098
return -EINVAL;
1099
for (i = 0; i < s->n_chan; i++) {
1100
int x;
1101
1102
x = (dev->minor << 28) | (it->subdev << 24) | (i << 16) |
1103
(s->range_table_list[i]->length);
1104
if (put_user(x, it->rangelist + i))
1105
return -EFAULT;
1106
}
1107
}
1108
1109
return 0;
1110
}
1111
1112
/*
1113
* COMEDI_BUFINFO ioctl
1114
* buffer information
1115
*
1116
* arg:
1117
* pointer to comedi_bufinfo structure
1118
*
1119
* reads:
1120
* comedi_bufinfo structure
1121
*
1122
* writes:
1123
* modified comedi_bufinfo structure
1124
*/
1125
static int do_bufinfo_ioctl(struct comedi_device *dev,
1126
struct comedi_bufinfo __user *arg, void *file)
1127
{
1128
struct comedi_bufinfo bi;
1129
struct comedi_subdevice *s;
1130
struct comedi_async *async;
1131
unsigned int runflags;
1132
int retval = 0;
1133
bool become_nonbusy = false;
1134
1135
lockdep_assert_held(&dev->mutex);
1136
if (copy_from_user(&bi, arg, sizeof(bi)))
1137
return -EFAULT;
1138
1139
if (bi.subdevice >= dev->n_subdevices)
1140
return -EINVAL;
1141
1142
s = &dev->subdevices[bi.subdevice];
1143
1144
async = s->async;
1145
1146
if (!async || s->busy != file)
1147
return -EINVAL;
1148
1149
runflags = comedi_get_subdevice_runflags(s);
1150
if (!(async->cmd.flags & CMDF_WRITE)) {
1151
/* command was set up in "read" direction */
1152
if (bi.bytes_read) {
1153
comedi_buf_read_alloc(s, bi.bytes_read);
1154
bi.bytes_read = comedi_buf_read_free(s, bi.bytes_read);
1155
}
1156
/*
1157
* If nothing left to read, and command has stopped, and
1158
* {"read" position not updated or command stopped normally},
1159
* then become non-busy.
1160
*/
1161
if (comedi_buf_read_n_available(s) == 0 &&
1162
!comedi_is_runflags_running(runflags) &&
1163
(bi.bytes_read == 0 ||
1164
!comedi_is_runflags_in_error(runflags))) {
1165
become_nonbusy = true;
1166
if (comedi_is_runflags_in_error(runflags))
1167
retval = -EPIPE;
1168
}
1169
bi.bytes_written = 0;
1170
} else {
1171
/* command was set up in "write" direction */
1172
if (!comedi_is_runflags_running(runflags)) {
1173
bi.bytes_written = 0;
1174
become_nonbusy = true;
1175
if (comedi_is_runflags_in_error(runflags))
1176
retval = -EPIPE;
1177
} else if (bi.bytes_written) {
1178
comedi_buf_write_alloc(s, bi.bytes_written);
1179
bi.bytes_written =
1180
comedi_buf_write_free(s, bi.bytes_written);
1181
}
1182
bi.bytes_read = 0;
1183
}
1184
1185
bi.buf_write_count = async->buf_write_count;
1186
bi.buf_write_ptr = async->buf_write_ptr;
1187
bi.buf_read_count = async->buf_read_count;
1188
bi.buf_read_ptr = async->buf_read_ptr;
1189
1190
if (become_nonbusy)
1191
do_become_nonbusy(dev, s);
1192
1193
if (retval)
1194
return retval;
1195
1196
if (copy_to_user(arg, &bi, sizeof(bi)))
1197
return -EFAULT;
1198
1199
return 0;
1200
}
1201
1202
static int check_insn_config_length(struct comedi_insn *insn,
1203
unsigned int *data)
1204
{
1205
if (insn->n < 1)
1206
return -EINVAL;
1207
1208
switch (data[0]) {
1209
case INSN_CONFIG_DIO_OUTPUT:
1210
case INSN_CONFIG_DIO_INPUT:
1211
case INSN_CONFIG_DISARM:
1212
case INSN_CONFIG_RESET:
1213
if (insn->n == 1)
1214
return 0;
1215
break;
1216
case INSN_CONFIG_ARM:
1217
case INSN_CONFIG_DIO_QUERY:
1218
case INSN_CONFIG_BLOCK_SIZE:
1219
case INSN_CONFIG_FILTER:
1220
case INSN_CONFIG_SERIAL_CLOCK:
1221
case INSN_CONFIG_BIDIRECTIONAL_DATA:
1222
case INSN_CONFIG_ALT_SOURCE:
1223
case INSN_CONFIG_SET_COUNTER_MODE:
1224
case INSN_CONFIG_8254_READ_STATUS:
1225
case INSN_CONFIG_SET_ROUTING:
1226
case INSN_CONFIG_GET_ROUTING:
1227
case INSN_CONFIG_GET_PWM_STATUS:
1228
case INSN_CONFIG_PWM_SET_PERIOD:
1229
case INSN_CONFIG_PWM_GET_PERIOD:
1230
if (insn->n == 2)
1231
return 0;
1232
break;
1233
case INSN_CONFIG_SET_GATE_SRC:
1234
case INSN_CONFIG_GET_GATE_SRC:
1235
case INSN_CONFIG_SET_CLOCK_SRC:
1236
case INSN_CONFIG_GET_CLOCK_SRC:
1237
case INSN_CONFIG_SET_OTHER_SRC:
1238
case INSN_CONFIG_GET_COUNTER_STATUS:
1239
case INSN_CONFIG_GET_PWM_OUTPUT:
1240
case INSN_CONFIG_PWM_SET_H_BRIDGE:
1241
case INSN_CONFIG_PWM_GET_H_BRIDGE:
1242
case INSN_CONFIG_GET_HARDWARE_BUFFER_SIZE:
1243
if (insn->n == 3)
1244
return 0;
1245
break;
1246
case INSN_CONFIG_PWM_OUTPUT:
1247
case INSN_CONFIG_ANALOG_TRIG:
1248
case INSN_CONFIG_TIMER_1:
1249
if (insn->n == 5)
1250
return 0;
1251
break;
1252
case INSN_CONFIG_DIGITAL_TRIG:
1253
if (insn->n == 6)
1254
return 0;
1255
break;
1256
case INSN_CONFIG_GET_CMD_TIMING_CONSTRAINTS:
1257
if (insn->n >= 4)
1258
return 0;
1259
break;
1260
/*
1261
* by default we allow the insn since we don't have checks for
1262
* all possible cases yet
1263
*/
1264
default:
1265
pr_warn("No check for data length of config insn id %i is implemented\n",
1266
data[0]);
1267
pr_warn("Add a check to %s in %s\n", __func__, __FILE__);
1268
pr_warn("Assuming n=%i is correct\n", insn->n);
1269
return 0;
1270
}
1271
return -EINVAL;
1272
}
1273
1274
static int check_insn_device_config_length(struct comedi_insn *insn,
1275
unsigned int *data)
1276
{
1277
if (insn->n < 1)
1278
return -EINVAL;
1279
1280
switch (data[0]) {
1281
case INSN_DEVICE_CONFIG_TEST_ROUTE:
1282
case INSN_DEVICE_CONFIG_CONNECT_ROUTE:
1283
case INSN_DEVICE_CONFIG_DISCONNECT_ROUTE:
1284
if (insn->n == 3)
1285
return 0;
1286
break;
1287
case INSN_DEVICE_CONFIG_GET_ROUTES:
1288
/*
1289
* Big enough for config_id and the length of the userland
1290
* memory buffer. Additional length should be in factors of 2
1291
* to communicate any returned route pairs (source,destination).
1292
*/
1293
if (insn->n >= 2)
1294
return 0;
1295
break;
1296
}
1297
return -EINVAL;
1298
}
1299
1300
/**
1301
* get_valid_routes() - Calls low-level driver get_valid_routes function to
1302
* either return a count of valid routes to user, or copy
1303
* of list of all valid device routes to buffer in
1304
* userspace.
1305
* @dev: comedi device pointer
1306
* @data: data from user insn call. The length of the data must be >= 2.
1307
* data[0] must contain the INSN_DEVICE_CONFIG config_id.
1308
* data[1](input) contains the number of _pairs_ for which memory is
1309
* allotted from the user. If the user specifies '0', then only
1310
* the number of pairs available is returned.
1311
* data[1](output) returns either the number of pairs available (if none
1312
* where requested) or the number of _pairs_ that are copied back
1313
* to the user.
1314
* data[2::2] returns each (source, destination) pair.
1315
*
1316
* Return: -EINVAL if low-level driver does not allocate and return routes as
1317
* expected. Returns 0 otherwise.
1318
*/
1319
static int get_valid_routes(struct comedi_device *dev, unsigned int *data)
1320
{
1321
lockdep_assert_held(&dev->mutex);
1322
data[1] = dev->get_valid_routes(dev, data[1], data + 2);
1323
return 0;
1324
}
1325
1326
static int parse_insn(struct comedi_device *dev, struct comedi_insn *insn,
1327
unsigned int *data, void *file)
1328
{
1329
struct comedi_subdevice *s;
1330
int ret = 0;
1331
int i;
1332
1333
lockdep_assert_held(&dev->mutex);
1334
if (insn->insn & INSN_MASK_SPECIAL) {
1335
/* a non-subdevice instruction */
1336
1337
switch (insn->insn) {
1338
case INSN_GTOD:
1339
{
1340
struct timespec64 tv;
1341
1342
if (insn->n != 2) {
1343
ret = -EINVAL;
1344
break;
1345
}
1346
1347
ktime_get_real_ts64(&tv);
1348
/* unsigned data safe until 2106 */
1349
data[0] = (unsigned int)tv.tv_sec;
1350
data[1] = tv.tv_nsec / NSEC_PER_USEC;
1351
ret = 2;
1352
1353
break;
1354
}
1355
case INSN_WAIT:
1356
if (insn->n != 1 || data[0] >= 100000) {
1357
ret = -EINVAL;
1358
break;
1359
}
1360
udelay(data[0] / 1000);
1361
ret = 1;
1362
break;
1363
case INSN_INTTRIG:
1364
if (insn->n != 1) {
1365
ret = -EINVAL;
1366
break;
1367
}
1368
if (insn->subdev >= dev->n_subdevices) {
1369
dev_dbg(dev->class_dev,
1370
"%d not usable subdevice\n",
1371
insn->subdev);
1372
ret = -EINVAL;
1373
break;
1374
}
1375
s = &dev->subdevices[insn->subdev];
1376
if (!s->async) {
1377
dev_dbg(dev->class_dev, "no async\n");
1378
ret = -EINVAL;
1379
break;
1380
}
1381
if (!s->async->inttrig) {
1382
dev_dbg(dev->class_dev, "no inttrig\n");
1383
ret = -EAGAIN;
1384
break;
1385
}
1386
ret = s->async->inttrig(dev, s, data[0]);
1387
if (ret >= 0)
1388
ret = 1;
1389
break;
1390
case INSN_DEVICE_CONFIG:
1391
ret = check_insn_device_config_length(insn, data);
1392
if (ret)
1393
break;
1394
1395
if (data[0] == INSN_DEVICE_CONFIG_GET_ROUTES) {
1396
/*
1397
* data[1] should be the number of _pairs_ that
1398
* the memory can hold.
1399
*/
1400
data[1] = (insn->n - 2) / 2;
1401
ret = get_valid_routes(dev, data);
1402
break;
1403
}
1404
1405
/* other global device config instructions. */
1406
ret = dev->insn_device_config(dev, insn, data);
1407
break;
1408
default:
1409
dev_dbg(dev->class_dev, "invalid insn\n");
1410
ret = -EINVAL;
1411
break;
1412
}
1413
} else {
1414
/* a subdevice instruction */
1415
unsigned int maxdata;
1416
1417
if (insn->subdev >= dev->n_subdevices) {
1418
dev_dbg(dev->class_dev, "subdevice %d out of range\n",
1419
insn->subdev);
1420
ret = -EINVAL;
1421
goto out;
1422
}
1423
s = &dev->subdevices[insn->subdev];
1424
1425
if (s->type == COMEDI_SUBD_UNUSED) {
1426
dev_dbg(dev->class_dev, "%d not usable subdevice\n",
1427
insn->subdev);
1428
ret = -EIO;
1429
goto out;
1430
}
1431
1432
/* are we locked? (ioctl lock) */
1433
if (s->lock && s->lock != file) {
1434
dev_dbg(dev->class_dev, "device locked\n");
1435
ret = -EACCES;
1436
goto out;
1437
}
1438
1439
ret = comedi_check_chanlist(s, 1, &insn->chanspec);
1440
if (ret < 0) {
1441
ret = -EINVAL;
1442
dev_dbg(dev->class_dev, "bad chanspec\n");
1443
goto out;
1444
}
1445
1446
if (s->busy) {
1447
ret = -EBUSY;
1448
goto out;
1449
}
1450
/* This looks arbitrary. It is. */
1451
s->busy = parse_insn;
1452
switch (insn->insn) {
1453
case INSN_READ:
1454
ret = s->insn_read(dev, s, insn, data);
1455
if (ret == -ETIMEDOUT) {
1456
dev_dbg(dev->class_dev,
1457
"subdevice %d read instruction timed out\n",
1458
s->index);
1459
}
1460
break;
1461
case INSN_WRITE:
1462
maxdata = s->maxdata_list
1463
? s->maxdata_list[CR_CHAN(insn->chanspec)]
1464
: s->maxdata;
1465
for (i = 0; i < insn->n; ++i) {
1466
if (data[i] > maxdata) {
1467
ret = -EINVAL;
1468
dev_dbg(dev->class_dev,
1469
"bad data value(s)\n");
1470
break;
1471
}
1472
}
1473
if (ret == 0) {
1474
ret = s->insn_write(dev, s, insn, data);
1475
if (ret == -ETIMEDOUT) {
1476
dev_dbg(dev->class_dev,
1477
"subdevice %d write instruction timed out\n",
1478
s->index);
1479
}
1480
}
1481
break;
1482
case INSN_BITS:
1483
if (insn->n != 2) {
1484
ret = -EINVAL;
1485
} else {
1486
/*
1487
* Most drivers ignore the base channel in
1488
* insn->chanspec. Fix this here if
1489
* the subdevice has <= 32 channels.
1490
*/
1491
unsigned int orig_mask = data[0];
1492
unsigned int shift = 0;
1493
1494
if (s->n_chan <= 32) {
1495
shift = CR_CHAN(insn->chanspec);
1496
if (shift > 0) {
1497
insn->chanspec = 0;
1498
data[0] <<= shift;
1499
data[1] <<= shift;
1500
}
1501
}
1502
ret = s->insn_bits(dev, s, insn, data);
1503
data[0] = orig_mask;
1504
if (shift > 0)
1505
data[1] >>= shift;
1506
}
1507
break;
1508
case INSN_CONFIG:
1509
ret = check_insn_config_length(insn, data);
1510
if (ret)
1511
break;
1512
ret = s->insn_config(dev, s, insn, data);
1513
break;
1514
default:
1515
ret = -EINVAL;
1516
break;
1517
}
1518
1519
s->busy = NULL;
1520
}
1521
1522
out:
1523
return ret;
1524
}
1525
1526
/*
1527
* COMEDI_INSNLIST ioctl
1528
* synchronous instruction list
1529
*
1530
* arg:
1531
* pointer to comedi_insnlist structure
1532
*
1533
* reads:
1534
* comedi_insnlist structure
1535
* array of comedi_insn structures from insnlist->insns pointer
1536
* data (for writes) from insns[].data pointers
1537
*
1538
* writes:
1539
* data (for reads) to insns[].data pointers
1540
*/
1541
/* arbitrary limits */
1542
#define MIN_SAMPLES 16
1543
#define MAX_SAMPLES 65536
1544
static int do_insnlist_ioctl(struct comedi_device *dev,
1545
struct comedi_insn *insns,
1546
unsigned int n_insns,
1547
void *file)
1548
{
1549
unsigned int *data = NULL;
1550
unsigned int max_n_data_required = MIN_SAMPLES;
1551
int i = 0;
1552
int ret = 0;
1553
1554
lockdep_assert_held(&dev->mutex);
1555
1556
/* Determine maximum memory needed for all instructions. */
1557
for (i = 0; i < n_insns; ++i) {
1558
if (insns[i].n > MAX_SAMPLES) {
1559
dev_dbg(dev->class_dev,
1560
"number of samples too large\n");
1561
ret = -EINVAL;
1562
goto error;
1563
}
1564
max_n_data_required = max(max_n_data_required, insns[i].n);
1565
}
1566
1567
/* Allocate scratch space for all instruction data. */
1568
data = kmalloc_array(max_n_data_required, sizeof(unsigned int),
1569
GFP_KERNEL);
1570
if (!data) {
1571
ret = -ENOMEM;
1572
goto error;
1573
}
1574
1575
for (i = 0; i < n_insns; ++i) {
1576
unsigned int n = insns[i].n;
1577
1578
if (insns[i].insn & INSN_MASK_WRITE) {
1579
if (copy_from_user(data, insns[i].data,
1580
n * sizeof(unsigned int))) {
1581
dev_dbg(dev->class_dev,
1582
"copy_from_user failed\n");
1583
ret = -EFAULT;
1584
goto error;
1585
}
1586
if (n < MIN_SAMPLES) {
1587
memset(&data[n], 0, (MIN_SAMPLES - n) *
1588
sizeof(unsigned int));
1589
}
1590
} else {
1591
memset(data, 0, max_t(unsigned int, n, MIN_SAMPLES) *
1592
sizeof(unsigned int));
1593
}
1594
ret = parse_insn(dev, insns + i, data, file);
1595
if (ret < 0)
1596
goto error;
1597
if (insns[i].insn & INSN_MASK_READ) {
1598
if (copy_to_user(insns[i].data, data,
1599
n * sizeof(unsigned int))) {
1600
dev_dbg(dev->class_dev,
1601
"copy_to_user failed\n");
1602
ret = -EFAULT;
1603
goto error;
1604
}
1605
}
1606
if (need_resched())
1607
schedule();
1608
}
1609
1610
error:
1611
kfree(data);
1612
1613
if (ret < 0)
1614
return ret;
1615
return i;
1616
}
1617
1618
#define MAX_INSNS MAX_SAMPLES
1619
static int check_insnlist_len(struct comedi_device *dev, unsigned int n_insns)
1620
{
1621
if (n_insns > MAX_INSNS) {
1622
dev_dbg(dev->class_dev, "insnlist length too large\n");
1623
return -EINVAL;
1624
}
1625
return 0;
1626
}
1627
1628
/*
1629
* COMEDI_INSN ioctl
1630
* synchronous instruction
1631
*
1632
* arg:
1633
* pointer to comedi_insn structure
1634
*
1635
* reads:
1636
* comedi_insn structure
1637
* data (for writes) from insn->data pointer
1638
*
1639
* writes:
1640
* data (for reads) to insn->data pointer
1641
*/
1642
static int do_insn_ioctl(struct comedi_device *dev,
1643
struct comedi_insn *insn, void *file)
1644
{
1645
unsigned int *data = NULL;
1646
unsigned int n_data = MIN_SAMPLES;
1647
int ret = 0;
1648
1649
lockdep_assert_held(&dev->mutex);
1650
1651
n_data = max(n_data, insn->n);
1652
1653
/* This is where the behavior of insn and insnlist deviate. */
1654
if (insn->n > MAX_SAMPLES) {
1655
insn->n = MAX_SAMPLES;
1656
n_data = MAX_SAMPLES;
1657
}
1658
1659
data = kmalloc_array(n_data, sizeof(unsigned int), GFP_KERNEL);
1660
if (!data) {
1661
ret = -ENOMEM;
1662
goto error;
1663
}
1664
1665
if (insn->insn & INSN_MASK_WRITE) {
1666
if (copy_from_user(data,
1667
insn->data,
1668
insn->n * sizeof(unsigned int))) {
1669
ret = -EFAULT;
1670
goto error;
1671
}
1672
if (insn->n < MIN_SAMPLES) {
1673
memset(&data[insn->n], 0,
1674
(MIN_SAMPLES - insn->n) * sizeof(unsigned int));
1675
}
1676
} else {
1677
memset(data, 0, n_data * sizeof(unsigned int));
1678
}
1679
ret = parse_insn(dev, insn, data, file);
1680
if (ret < 0)
1681
goto error;
1682
if (insn->insn & INSN_MASK_READ) {
1683
if (copy_to_user(insn->data,
1684
data,
1685
insn->n * sizeof(unsigned int))) {
1686
ret = -EFAULT;
1687
goto error;
1688
}
1689
}
1690
ret = insn->n;
1691
1692
error:
1693
kfree(data);
1694
1695
return ret;
1696
}
1697
1698
static int __comedi_get_user_cmd(struct comedi_device *dev,
1699
struct comedi_cmd *cmd)
1700
{
1701
struct comedi_subdevice *s;
1702
1703
lockdep_assert_held(&dev->mutex);
1704
if (cmd->subdev >= dev->n_subdevices) {
1705
dev_dbg(dev->class_dev, "%d no such subdevice\n", cmd->subdev);
1706
return -ENODEV;
1707
}
1708
1709
s = &dev->subdevices[cmd->subdev];
1710
1711
if (s->type == COMEDI_SUBD_UNUSED) {
1712
dev_dbg(dev->class_dev, "%d not valid subdevice\n",
1713
cmd->subdev);
1714
return -EIO;
1715
}
1716
1717
if (!s->do_cmd || !s->do_cmdtest || !s->async) {
1718
dev_dbg(dev->class_dev,
1719
"subdevice %d does not support commands\n",
1720
cmd->subdev);
1721
return -EIO;
1722
}
1723
1724
/* make sure channel/gain list isn't too long */
1725
if (cmd->chanlist_len > s->len_chanlist) {
1726
dev_dbg(dev->class_dev, "channel/gain list too long %d > %d\n",
1727
cmd->chanlist_len, s->len_chanlist);
1728
return -EINVAL;
1729
}
1730
1731
/*
1732
* Set the CMDF_WRITE flag to the correct state if the subdevice
1733
* supports only "read" commands or only "write" commands.
1734
*/
1735
switch (s->subdev_flags & (SDF_CMD_READ | SDF_CMD_WRITE)) {
1736
case SDF_CMD_READ:
1737
cmd->flags &= ~CMDF_WRITE;
1738
break;
1739
case SDF_CMD_WRITE:
1740
cmd->flags |= CMDF_WRITE;
1741
break;
1742
default:
1743
break;
1744
}
1745
1746
return 0;
1747
}
1748
1749
static int __comedi_get_user_chanlist(struct comedi_device *dev,
1750
struct comedi_subdevice *s,
1751
unsigned int __user *user_chanlist,
1752
struct comedi_cmd *cmd)
1753
{
1754
unsigned int *chanlist;
1755
int ret;
1756
1757
lockdep_assert_held(&dev->mutex);
1758
cmd->chanlist = NULL;
1759
chanlist = memdup_array_user(user_chanlist,
1760
cmd->chanlist_len, sizeof(unsigned int));
1761
if (IS_ERR(chanlist))
1762
return PTR_ERR(chanlist);
1763
1764
/* make sure each element in channel/gain list is valid */
1765
ret = comedi_check_chanlist(s, cmd->chanlist_len, chanlist);
1766
if (ret < 0) {
1767
kfree(chanlist);
1768
return ret;
1769
}
1770
1771
cmd->chanlist = chanlist;
1772
1773
return 0;
1774
}
1775
1776
/*
1777
* COMEDI_CMD ioctl
1778
* asynchronous acquisition command set-up
1779
*
1780
* arg:
1781
* pointer to comedi_cmd structure
1782
*
1783
* reads:
1784
* comedi_cmd structure
1785
* channel/range list from cmd->chanlist pointer
1786
*
1787
* writes:
1788
* possibly modified comedi_cmd structure (when -EAGAIN returned)
1789
*/
1790
static int do_cmd_ioctl(struct comedi_device *dev,
1791
struct comedi_cmd *cmd, bool *copy, void *file)
1792
{
1793
struct comedi_subdevice *s;
1794
struct comedi_async *async;
1795
unsigned int __user *user_chanlist;
1796
int ret;
1797
1798
lockdep_assert_held(&dev->mutex);
1799
1800
/* do some simple cmd validation */
1801
ret = __comedi_get_user_cmd(dev, cmd);
1802
if (ret)
1803
return ret;
1804
1805
/* save user's chanlist pointer so it can be restored later */
1806
user_chanlist = (unsigned int __user *)cmd->chanlist;
1807
1808
s = &dev->subdevices[cmd->subdev];
1809
async = s->async;
1810
1811
/* are we locked? (ioctl lock) */
1812
if (s->lock && s->lock != file) {
1813
dev_dbg(dev->class_dev, "subdevice locked\n");
1814
return -EACCES;
1815
}
1816
1817
/* are we busy? */
1818
if (s->busy) {
1819
dev_dbg(dev->class_dev, "subdevice busy\n");
1820
return -EBUSY;
1821
}
1822
1823
/* make sure channel/gain list isn't too short */
1824
if (cmd->chanlist_len < 1) {
1825
dev_dbg(dev->class_dev, "channel/gain list too short %u < 1\n",
1826
cmd->chanlist_len);
1827
return -EINVAL;
1828
}
1829
1830
async->cmd = *cmd;
1831
async->cmd.data = NULL;
1832
1833
/* load channel/gain list */
1834
ret = __comedi_get_user_chanlist(dev, s, user_chanlist, &async->cmd);
1835
if (ret)
1836
goto cleanup;
1837
1838
ret = s->do_cmdtest(dev, s, &async->cmd);
1839
1840
if (async->cmd.flags & CMDF_BOGUS || ret) {
1841
dev_dbg(dev->class_dev, "test returned %d\n", ret);
1842
*cmd = async->cmd;
1843
/* restore chanlist pointer before copying back */
1844
cmd->chanlist = (unsigned int __force *)user_chanlist;
1845
cmd->data = NULL;
1846
*copy = true;
1847
ret = -EAGAIN;
1848
goto cleanup;
1849
}
1850
1851
if (!async->prealloc_bufsz) {
1852
ret = -ENOMEM;
1853
dev_dbg(dev->class_dev, "no buffer (?)\n");
1854
goto cleanup;
1855
}
1856
1857
comedi_buf_reset(s);
1858
1859
async->cb_mask = COMEDI_CB_BLOCK | COMEDI_CB_CANCEL_MASK;
1860
if (async->cmd.flags & CMDF_WAKE_EOS)
1861
async->cb_mask |= COMEDI_CB_EOS;
1862
1863
comedi_update_subdevice_runflags(s, COMEDI_SRF_BUSY_MASK,
1864
COMEDI_SRF_RUNNING);
1865
1866
/*
1867
* Set s->busy _after_ setting COMEDI_SRF_RUNNING flag to avoid
1868
* race with comedi_read() or comedi_write().
1869
*/
1870
s->busy = file;
1871
ret = s->do_cmd(dev, s);
1872
if (ret == 0)
1873
return 0;
1874
1875
cleanup:
1876
do_become_nonbusy(dev, s);
1877
1878
return ret;
1879
}
1880
1881
/*
1882
* COMEDI_CMDTEST ioctl
1883
* asynchronous acquisition command testing
1884
*
1885
* arg:
1886
* pointer to comedi_cmd structure
1887
*
1888
* reads:
1889
* comedi_cmd structure
1890
* channel/range list from cmd->chanlist pointer
1891
*
1892
* writes:
1893
* possibly modified comedi_cmd structure
1894
*/
1895
static int do_cmdtest_ioctl(struct comedi_device *dev,
1896
struct comedi_cmd *cmd, bool *copy, void *file)
1897
{
1898
struct comedi_subdevice *s;
1899
unsigned int __user *user_chanlist;
1900
int ret;
1901
1902
lockdep_assert_held(&dev->mutex);
1903
1904
/* do some simple cmd validation */
1905
ret = __comedi_get_user_cmd(dev, cmd);
1906
if (ret)
1907
return ret;
1908
1909
/* save user's chanlist pointer so it can be restored later */
1910
user_chanlist = (unsigned int __user *)cmd->chanlist;
1911
1912
s = &dev->subdevices[cmd->subdev];
1913
1914
/* user_chanlist can be NULL for COMEDI_CMDTEST ioctl */
1915
if (user_chanlist) {
1916
/* load channel/gain list */
1917
ret = __comedi_get_user_chanlist(dev, s, user_chanlist, cmd);
1918
if (ret)
1919
return ret;
1920
}
1921
1922
ret = s->do_cmdtest(dev, s, cmd);
1923
1924
kfree(cmd->chanlist); /* free kernel copy of user chanlist */
1925
1926
/* restore chanlist pointer before copying back */
1927
cmd->chanlist = (unsigned int __force *)user_chanlist;
1928
*copy = true;
1929
1930
return ret;
1931
}
1932
1933
/*
1934
* COMEDI_LOCK ioctl
1935
* lock subdevice
1936
*
1937
* arg:
1938
* subdevice number
1939
*
1940
* reads:
1941
* nothing
1942
*
1943
* writes:
1944
* nothing
1945
*/
1946
static int do_lock_ioctl(struct comedi_device *dev, unsigned long arg,
1947
void *file)
1948
{
1949
int ret = 0;
1950
unsigned long flags;
1951
struct comedi_subdevice *s;
1952
1953
lockdep_assert_held(&dev->mutex);
1954
if (arg >= dev->n_subdevices)
1955
return -EINVAL;
1956
s = &dev->subdevices[arg];
1957
1958
spin_lock_irqsave(&s->spin_lock, flags);
1959
if (s->busy || s->lock)
1960
ret = -EBUSY;
1961
else
1962
s->lock = file;
1963
spin_unlock_irqrestore(&s->spin_lock, flags);
1964
1965
return ret;
1966
}
1967
1968
/*
1969
* COMEDI_UNLOCK ioctl
1970
* unlock subdevice
1971
*
1972
* arg:
1973
* subdevice number
1974
*
1975
* reads:
1976
* nothing
1977
*
1978
* writes:
1979
* nothing
1980
*/
1981
static int do_unlock_ioctl(struct comedi_device *dev, unsigned long arg,
1982
void *file)
1983
{
1984
struct comedi_subdevice *s;
1985
1986
lockdep_assert_held(&dev->mutex);
1987
if (arg >= dev->n_subdevices)
1988
return -EINVAL;
1989
s = &dev->subdevices[arg];
1990
1991
if (s->busy)
1992
return -EBUSY;
1993
1994
if (s->lock && s->lock != file)
1995
return -EACCES;
1996
1997
if (s->lock == file)
1998
s->lock = NULL;
1999
2000
return 0;
2001
}
2002
2003
/*
2004
* COMEDI_CANCEL ioctl
2005
* cancel asynchronous acquisition
2006
*
2007
* arg:
2008
* subdevice number
2009
*
2010
* reads:
2011
* nothing
2012
*
2013
* writes:
2014
* nothing
2015
*/
2016
static int do_cancel_ioctl(struct comedi_device *dev, unsigned long arg,
2017
void *file)
2018
{
2019
struct comedi_subdevice *s;
2020
2021
lockdep_assert_held(&dev->mutex);
2022
if (arg >= dev->n_subdevices)
2023
return -EINVAL;
2024
s = &dev->subdevices[arg];
2025
if (!s->async)
2026
return -EINVAL;
2027
2028
if (!s->busy)
2029
return 0;
2030
2031
if (s->busy != file)
2032
return -EBUSY;
2033
2034
return do_cancel(dev, s);
2035
}
2036
2037
/*
2038
* COMEDI_POLL ioctl
2039
* instructs driver to synchronize buffers
2040
*
2041
* arg:
2042
* subdevice number
2043
*
2044
* reads:
2045
* nothing
2046
*
2047
* writes:
2048
* nothing
2049
*/
2050
static int do_poll_ioctl(struct comedi_device *dev, unsigned long arg,
2051
void *file)
2052
{
2053
struct comedi_subdevice *s;
2054
2055
lockdep_assert_held(&dev->mutex);
2056
if (arg >= dev->n_subdevices)
2057
return -EINVAL;
2058
s = &dev->subdevices[arg];
2059
2060
if (!s->busy)
2061
return 0;
2062
2063
if (s->busy != file)
2064
return -EBUSY;
2065
2066
if (s->poll)
2067
return s->poll(dev, s);
2068
2069
return -EINVAL;
2070
}
2071
2072
/*
2073
* COMEDI_SETRSUBD ioctl
2074
* sets the current "read" subdevice on a per-file basis
2075
*
2076
* arg:
2077
* subdevice number
2078
*
2079
* reads:
2080
* nothing
2081
*
2082
* writes:
2083
* nothing
2084
*/
2085
static int do_setrsubd_ioctl(struct comedi_device *dev, unsigned long arg,
2086
struct file *file)
2087
{
2088
struct comedi_file *cfp = file->private_data;
2089
struct comedi_subdevice *s_old, *s_new;
2090
2091
lockdep_assert_held(&dev->mutex);
2092
if (arg >= dev->n_subdevices)
2093
return -EINVAL;
2094
2095
s_new = &dev->subdevices[arg];
2096
s_old = comedi_file_read_subdevice(file);
2097
if (s_old == s_new)
2098
return 0; /* no change */
2099
2100
if (!(s_new->subdev_flags & SDF_CMD_READ))
2101
return -EINVAL;
2102
2103
/*
2104
* Check the file isn't still busy handling a "read" command on the
2105
* old subdevice (if any).
2106
*/
2107
if (s_old && s_old->busy == file && s_old->async &&
2108
!(s_old->async->cmd.flags & CMDF_WRITE))
2109
return -EBUSY;
2110
2111
WRITE_ONCE(cfp->read_subdev, s_new);
2112
return 0;
2113
}
2114
2115
/*
2116
* COMEDI_SETWSUBD ioctl
2117
* sets the current "write" subdevice on a per-file basis
2118
*
2119
* arg:
2120
* subdevice number
2121
*
2122
* reads:
2123
* nothing
2124
*
2125
* writes:
2126
* nothing
2127
*/
2128
static int do_setwsubd_ioctl(struct comedi_device *dev, unsigned long arg,
2129
struct file *file)
2130
{
2131
struct comedi_file *cfp = file->private_data;
2132
struct comedi_subdevice *s_old, *s_new;
2133
2134
lockdep_assert_held(&dev->mutex);
2135
if (arg >= dev->n_subdevices)
2136
return -EINVAL;
2137
2138
s_new = &dev->subdevices[arg];
2139
s_old = comedi_file_write_subdevice(file);
2140
if (s_old == s_new)
2141
return 0; /* no change */
2142
2143
if (!(s_new->subdev_flags & SDF_CMD_WRITE))
2144
return -EINVAL;
2145
2146
/*
2147
* Check the file isn't still busy handling a "write" command on the
2148
* old subdevice (if any).
2149
*/
2150
if (s_old && s_old->busy == file && s_old->async &&
2151
(s_old->async->cmd.flags & CMDF_WRITE))
2152
return -EBUSY;
2153
2154
WRITE_ONCE(cfp->write_subdev, s_new);
2155
return 0;
2156
}
2157
2158
static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd,
2159
unsigned long arg)
2160
{
2161
unsigned int minor = iminor(file_inode(file));
2162
struct comedi_file *cfp = file->private_data;
2163
struct comedi_device *dev = cfp->dev;
2164
int rc;
2165
2166
mutex_lock(&dev->mutex);
2167
2168
/*
2169
* Device config is special, because it must work on
2170
* an unconfigured device.
2171
*/
2172
if (cmd == COMEDI_DEVCONFIG) {
2173
if (minor >= COMEDI_NUM_BOARD_MINORS) {
2174
/* Device config not appropriate on non-board minors. */
2175
rc = -ENOTTY;
2176
goto done;
2177
}
2178
rc = do_devconfig_ioctl(dev,
2179
(struct comedi_devconfig __user *)arg);
2180
if (rc == 0) {
2181
if (arg == 0 &&
2182
dev->minor >= comedi_num_legacy_minors) {
2183
/*
2184
* Successfully unconfigured a dynamically
2185
* allocated device. Try and remove it.
2186
*/
2187
if (comedi_clear_board_dev(dev)) {
2188
mutex_unlock(&dev->mutex);
2189
comedi_free_board_dev(dev);
2190
return rc;
2191
}
2192
}
2193
}
2194
goto done;
2195
}
2196
2197
if (!dev->attached) {
2198
dev_dbg(dev->class_dev, "no driver attached\n");
2199
rc = -ENODEV;
2200
goto done;
2201
}
2202
2203
switch (cmd) {
2204
case COMEDI_BUFCONFIG:
2205
rc = do_bufconfig_ioctl(dev,
2206
(struct comedi_bufconfig __user *)arg);
2207
break;
2208
case COMEDI_DEVINFO:
2209
rc = do_devinfo_ioctl(dev, (struct comedi_devinfo __user *)arg,
2210
file);
2211
break;
2212
case COMEDI_SUBDINFO:
2213
rc = do_subdinfo_ioctl(dev,
2214
(struct comedi_subdinfo __user *)arg,
2215
file);
2216
break;
2217
case COMEDI_CHANINFO: {
2218
struct comedi_chaninfo it;
2219
2220
if (copy_from_user(&it, (void __user *)arg, sizeof(it)))
2221
rc = -EFAULT;
2222
else
2223
rc = do_chaninfo_ioctl(dev, &it);
2224
break;
2225
}
2226
case COMEDI_RANGEINFO: {
2227
struct comedi_rangeinfo it;
2228
2229
if (copy_from_user(&it, (void __user *)arg, sizeof(it)))
2230
rc = -EFAULT;
2231
else
2232
rc = do_rangeinfo_ioctl(dev, &it);
2233
break;
2234
}
2235
case COMEDI_BUFINFO:
2236
rc = do_bufinfo_ioctl(dev,
2237
(struct comedi_bufinfo __user *)arg,
2238
file);
2239
break;
2240
case COMEDI_LOCK:
2241
rc = do_lock_ioctl(dev, arg, file);
2242
break;
2243
case COMEDI_UNLOCK:
2244
rc = do_unlock_ioctl(dev, arg, file);
2245
break;
2246
case COMEDI_CANCEL:
2247
rc = do_cancel_ioctl(dev, arg, file);
2248
break;
2249
case COMEDI_CMD: {
2250
struct comedi_cmd cmd;
2251
bool copy = false;
2252
2253
if (copy_from_user(&cmd, (void __user *)arg, sizeof(cmd))) {
2254
rc = -EFAULT;
2255
break;
2256
}
2257
rc = do_cmd_ioctl(dev, &cmd, &copy, file);
2258
if (copy && copy_to_user((void __user *)arg, &cmd, sizeof(cmd)))
2259
rc = -EFAULT;
2260
break;
2261
}
2262
case COMEDI_CMDTEST: {
2263
struct comedi_cmd cmd;
2264
bool copy = false;
2265
2266
if (copy_from_user(&cmd, (void __user *)arg, sizeof(cmd))) {
2267
rc = -EFAULT;
2268
break;
2269
}
2270
rc = do_cmdtest_ioctl(dev, &cmd, &copy, file);
2271
if (copy && copy_to_user((void __user *)arg, &cmd, sizeof(cmd)))
2272
rc = -EFAULT;
2273
break;
2274
}
2275
case COMEDI_INSNLIST: {
2276
struct comedi_insnlist insnlist;
2277
struct comedi_insn *insns = NULL;
2278
2279
if (copy_from_user(&insnlist, (void __user *)arg,
2280
sizeof(insnlist))) {
2281
rc = -EFAULT;
2282
break;
2283
}
2284
rc = check_insnlist_len(dev, insnlist.n_insns);
2285
if (rc)
2286
break;
2287
insns = kcalloc(insnlist.n_insns, sizeof(*insns), GFP_KERNEL);
2288
if (!insns) {
2289
rc = -ENOMEM;
2290
break;
2291
}
2292
if (copy_from_user(insns, insnlist.insns,
2293
sizeof(*insns) * insnlist.n_insns)) {
2294
rc = -EFAULT;
2295
kfree(insns);
2296
break;
2297
}
2298
rc = do_insnlist_ioctl(dev, insns, insnlist.n_insns, file);
2299
kfree(insns);
2300
break;
2301
}
2302
case COMEDI_INSN: {
2303
struct comedi_insn insn;
2304
2305
if (copy_from_user(&insn, (void __user *)arg, sizeof(insn)))
2306
rc = -EFAULT;
2307
else
2308
rc = do_insn_ioctl(dev, &insn, file);
2309
break;
2310
}
2311
case COMEDI_POLL:
2312
rc = do_poll_ioctl(dev, arg, file);
2313
break;
2314
case COMEDI_SETRSUBD:
2315
rc = do_setrsubd_ioctl(dev, arg, file);
2316
break;
2317
case COMEDI_SETWSUBD:
2318
rc = do_setwsubd_ioctl(dev, arg, file);
2319
break;
2320
default:
2321
rc = -ENOTTY;
2322
break;
2323
}
2324
2325
done:
2326
mutex_unlock(&dev->mutex);
2327
return rc;
2328
}
2329
2330
static void comedi_vm_open(struct vm_area_struct *area)
2331
{
2332
struct comedi_buf_map *bm;
2333
2334
bm = area->vm_private_data;
2335
comedi_buf_map_get(bm);
2336
}
2337
2338
static void comedi_vm_close(struct vm_area_struct *area)
2339
{
2340
struct comedi_buf_map *bm;
2341
2342
bm = area->vm_private_data;
2343
comedi_buf_map_put(bm);
2344
}
2345
2346
static int comedi_vm_access(struct vm_area_struct *vma, unsigned long addr,
2347
void *buf, int len, int write)
2348
{
2349
struct comedi_buf_map *bm = vma->vm_private_data;
2350
unsigned long offset =
2351
addr - vma->vm_start + (vma->vm_pgoff << PAGE_SHIFT);
2352
2353
if (len < 0)
2354
return -EINVAL;
2355
if (len > vma->vm_end - addr)
2356
len = vma->vm_end - addr;
2357
return comedi_buf_map_access(bm, offset, buf, len, write);
2358
}
2359
2360
static const struct vm_operations_struct comedi_vm_ops = {
2361
.open = comedi_vm_open,
2362
.close = comedi_vm_close,
2363
.access = comedi_vm_access,
2364
};
2365
2366
static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
2367
{
2368
struct comedi_file *cfp = file->private_data;
2369
struct comedi_device *dev = cfp->dev;
2370
struct comedi_subdevice *s;
2371
struct comedi_async *async;
2372
struct comedi_buf_map *bm = NULL;
2373
struct comedi_buf_page *buf;
2374
unsigned long start = vma->vm_start;
2375
unsigned long size;
2376
int n_pages;
2377
int i;
2378
int retval = 0;
2379
2380
/*
2381
* 'trylock' avoids circular dependency with current->mm->mmap_lock
2382
* and down-reading &dev->attach_lock should normally succeed without
2383
* contention unless the device is in the process of being attached
2384
* or detached.
2385
*/
2386
if (!down_read_trylock(&dev->attach_lock))
2387
return -EAGAIN;
2388
2389
if (!dev->attached) {
2390
dev_dbg(dev->class_dev, "no driver attached\n");
2391
retval = -ENODEV;
2392
goto done;
2393
}
2394
2395
if (vma->vm_flags & VM_WRITE)
2396
s = comedi_file_write_subdevice(file);
2397
else
2398
s = comedi_file_read_subdevice(file);
2399
if (!s) {
2400
retval = -EINVAL;
2401
goto done;
2402
}
2403
2404
async = s->async;
2405
if (!async) {
2406
retval = -EINVAL;
2407
goto done;
2408
}
2409
2410
if (vma->vm_pgoff != 0) {
2411
dev_dbg(dev->class_dev, "mmap() offset must be 0.\n");
2412
retval = -EINVAL;
2413
goto done;
2414
}
2415
2416
size = vma->vm_end - vma->vm_start;
2417
if (size > async->prealloc_bufsz) {
2418
retval = -EFAULT;
2419
goto done;
2420
}
2421
if (offset_in_page(size)) {
2422
retval = -EFAULT;
2423
goto done;
2424
}
2425
2426
n_pages = vma_pages(vma);
2427
2428
/* get reference to current buf map (if any) */
2429
bm = comedi_buf_map_from_subdev_get(s);
2430
if (!bm || n_pages > bm->n_pages) {
2431
retval = -EINVAL;
2432
goto done;
2433
}
2434
if (bm->dma_dir != DMA_NONE) {
2435
unsigned long vm_start = vma->vm_start;
2436
unsigned long vm_end = vma->vm_end;
2437
2438
/*
2439
* Buffer pages are not contiguous, so temporarily modify VMA
2440
* start and end addresses for each buffer page.
2441
*/
2442
for (i = 0; i < n_pages; ++i) {
2443
buf = &bm->page_list[i];
2444
vma->vm_start = start;
2445
vma->vm_end = start + PAGE_SIZE;
2446
retval = dma_mmap_coherent(bm->dma_hw_dev, vma,
2447
buf->virt_addr,
2448
buf->dma_addr, PAGE_SIZE);
2449
if (retval)
2450
break;
2451
2452
start += PAGE_SIZE;
2453
}
2454
vma->vm_start = vm_start;
2455
vma->vm_end = vm_end;
2456
} else {
2457
for (i = 0; i < n_pages; ++i) {
2458
unsigned long pfn;
2459
2460
buf = &bm->page_list[i];
2461
pfn = page_to_pfn(virt_to_page(buf->virt_addr));
2462
retval = remap_pfn_range(vma, start, pfn, PAGE_SIZE,
2463
PAGE_SHARED);
2464
if (retval)
2465
break;
2466
2467
start += PAGE_SIZE;
2468
}
2469
}
2470
2471
#ifdef CONFIG_MMU
2472
/*
2473
* Leaving behind a partial mapping of a buffer we're about to drop is
2474
* unsafe, see remap_pfn_range_notrack(). We need to zap the range
2475
* here ourselves instead of relying on the automatic zapping in
2476
* remap_pfn_range() because we call remap_pfn_range() in a loop.
2477
*/
2478
if (retval)
2479
zap_vma_ptes(vma, vma->vm_start, size);
2480
#endif
2481
2482
if (retval == 0) {
2483
vma->vm_ops = &comedi_vm_ops;
2484
vma->vm_private_data = bm;
2485
2486
vma->vm_ops->open(vma);
2487
}
2488
2489
done:
2490
up_read(&dev->attach_lock);
2491
comedi_buf_map_put(bm); /* put reference to buf map - okay if NULL */
2492
return retval;
2493
}
2494
2495
static __poll_t comedi_poll(struct file *file, poll_table *wait)
2496
{
2497
__poll_t mask = 0;
2498
struct comedi_file *cfp = file->private_data;
2499
struct comedi_device *dev = cfp->dev;
2500
struct comedi_subdevice *s, *s_read;
2501
2502
down_read(&dev->attach_lock);
2503
2504
if (!dev->attached) {
2505
dev_dbg(dev->class_dev, "no driver attached\n");
2506
goto done;
2507
}
2508
2509
s = comedi_file_read_subdevice(file);
2510
s_read = s;
2511
if (s && s->async) {
2512
poll_wait(file, &s->async->wait_head, wait);
2513
if (s->busy != file || !comedi_is_subdevice_running(s) ||
2514
(s->async->cmd.flags & CMDF_WRITE) ||
2515
comedi_buf_read_n_available(s) > 0)
2516
mask |= EPOLLIN | EPOLLRDNORM;
2517
}
2518
2519
s = comedi_file_write_subdevice(file);
2520
if (s && s->async) {
2521
unsigned int bps = comedi_bytes_per_sample(s);
2522
2523
if (s != s_read)
2524
poll_wait(file, &s->async->wait_head, wait);
2525
if (s->busy != file || !comedi_is_subdevice_running(s) ||
2526
!(s->async->cmd.flags & CMDF_WRITE) ||
2527
comedi_buf_write_n_available(s) >= bps)
2528
mask |= EPOLLOUT | EPOLLWRNORM;
2529
}
2530
2531
done:
2532
up_read(&dev->attach_lock);
2533
return mask;
2534
}
2535
2536
static unsigned int comedi_buf_copy_to_user(struct comedi_subdevice *s,
2537
void __user *dest, unsigned int src_offset, unsigned int n)
2538
{
2539
struct comedi_buf_map *bm = s->async->buf_map;
2540
struct comedi_buf_page *buf_page_list = bm->page_list;
2541
unsigned int page = src_offset >> PAGE_SHIFT;
2542
unsigned int offset = offset_in_page(src_offset);
2543
2544
while (n) {
2545
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
2546
unsigned int uncopied;
2547
2548
uncopied = copy_to_user(dest, buf_page_list[page].virt_addr +
2549
offset, copy_amount);
2550
copy_amount -= uncopied;
2551
n -= copy_amount;
2552
if (uncopied)
2553
break;
2554
2555
dest += copy_amount;
2556
page++;
2557
if (page == bm->n_pages)
2558
page = 0; /* buffer wraparound */
2559
offset = 0;
2560
}
2561
return n;
2562
}
2563
2564
static unsigned int comedi_buf_copy_from_user(struct comedi_subdevice *s,
2565
unsigned int dst_offset, const void __user *src, unsigned int n)
2566
{
2567
struct comedi_buf_map *bm = s->async->buf_map;
2568
struct comedi_buf_page *buf_page_list = bm->page_list;
2569
unsigned int page = dst_offset >> PAGE_SHIFT;
2570
unsigned int offset = offset_in_page(dst_offset);
2571
2572
while (n) {
2573
unsigned int copy_amount = min(n, PAGE_SIZE - offset);
2574
unsigned int uncopied;
2575
2576
uncopied = copy_from_user(buf_page_list[page].virt_addr +
2577
offset, src, copy_amount);
2578
copy_amount -= uncopied;
2579
n -= copy_amount;
2580
if (uncopied)
2581
break;
2582
2583
src += copy_amount;
2584
page++;
2585
if (page == bm->n_pages)
2586
page = 0; /* buffer wraparound */
2587
offset = 0;
2588
}
2589
return n;
2590
}
2591
2592
static ssize_t comedi_write(struct file *file, const char __user *buf,
2593
size_t nbytes, loff_t *offset)
2594
{
2595
struct comedi_subdevice *s;
2596
struct comedi_async *async;
2597
unsigned int n, m;
2598
ssize_t count = 0;
2599
int retval = 0;
2600
DECLARE_WAITQUEUE(wait, current);
2601
struct comedi_file *cfp = file->private_data;
2602
struct comedi_device *dev = cfp->dev;
2603
bool become_nonbusy = false;
2604
bool attach_locked;
2605
unsigned int old_detach_count;
2606
2607
/* Protect against device detachment during operation. */
2608
down_read(&dev->attach_lock);
2609
attach_locked = true;
2610
old_detach_count = dev->detach_count;
2611
2612
if (!dev->attached) {
2613
dev_dbg(dev->class_dev, "no driver attached\n");
2614
retval = -ENODEV;
2615
goto out;
2616
}
2617
2618
s = comedi_file_write_subdevice(file);
2619
if (!s || !s->async) {
2620
retval = -EIO;
2621
goto out;
2622
}
2623
2624
async = s->async;
2625
if (s->busy != file || !(async->cmd.flags & CMDF_WRITE)) {
2626
retval = -EINVAL;
2627
goto out;
2628
}
2629
2630
add_wait_queue(&async->wait_head, &wait);
2631
while (count == 0 && !retval) {
2632
unsigned int runflags;
2633
2634
set_current_state(TASK_INTERRUPTIBLE);
2635
2636
runflags = comedi_get_subdevice_runflags(s);
2637
if (!comedi_is_runflags_running(runflags)) {
2638
if (comedi_is_runflags_in_error(runflags))
2639
retval = -EPIPE;
2640
if (retval || nbytes)
2641
become_nonbusy = true;
2642
break;
2643
}
2644
if (nbytes == 0)
2645
break;
2646
2647
/* Allocate all free buffer space. */
2648
comedi_buf_write_alloc(s, async->prealloc_bufsz);
2649
m = comedi_buf_write_n_allocated(s);
2650
n = min_t(size_t, m, nbytes);
2651
2652
if (n == 0) {
2653
if (file->f_flags & O_NONBLOCK) {
2654
retval = -EAGAIN;
2655
break;
2656
}
2657
schedule();
2658
if (signal_pending(current)) {
2659
retval = -ERESTARTSYS;
2660
break;
2661
}
2662
if (s->busy != file ||
2663
!(async->cmd.flags & CMDF_WRITE)) {
2664
retval = -EINVAL;
2665
break;
2666
}
2667
continue;
2668
}
2669
2670
set_current_state(TASK_RUNNING);
2671
m = comedi_buf_copy_from_user(s, async->buf_write_ptr, buf, n);
2672
if (m) {
2673
n -= m;
2674
retval = -EFAULT;
2675
}
2676
comedi_buf_write_free(s, n);
2677
2678
count += n;
2679
nbytes -= n;
2680
2681
buf += n;
2682
}
2683
remove_wait_queue(&async->wait_head, &wait);
2684
set_current_state(TASK_RUNNING);
2685
if (become_nonbusy && count == 0) {
2686
struct comedi_subdevice *new_s;
2687
2688
/*
2689
* To avoid deadlock, cannot acquire dev->mutex
2690
* while dev->attach_lock is held.
2691
*/
2692
up_read(&dev->attach_lock);
2693
attach_locked = false;
2694
mutex_lock(&dev->mutex);
2695
/*
2696
* Check device hasn't become detached behind our back.
2697
* Checking dev->detach_count is unchanged ought to be
2698
* sufficient (unless there have been 2**32 detaches in the
2699
* meantime!), but check the subdevice pointer as well just in
2700
* case.
2701
*
2702
* Also check the subdevice is still in a suitable state to
2703
* become non-busy in case it changed behind our back.
2704
*/
2705
new_s = comedi_file_write_subdevice(file);
2706
if (dev->attached && old_detach_count == dev->detach_count &&
2707
s == new_s && new_s->async == async && s->busy == file &&
2708
(async->cmd.flags & CMDF_WRITE) &&
2709
!comedi_is_subdevice_running(s))
2710
do_become_nonbusy(dev, s);
2711
mutex_unlock(&dev->mutex);
2712
}
2713
out:
2714
if (attach_locked)
2715
up_read(&dev->attach_lock);
2716
2717
return count ? count : retval;
2718
}
2719
2720
static ssize_t comedi_read(struct file *file, char __user *buf, size_t nbytes,
2721
loff_t *offset)
2722
{
2723
struct comedi_subdevice *s;
2724
struct comedi_async *async;
2725
unsigned int n, m;
2726
ssize_t count = 0;
2727
int retval = 0;
2728
DECLARE_WAITQUEUE(wait, current);
2729
struct comedi_file *cfp = file->private_data;
2730
struct comedi_device *dev = cfp->dev;
2731
unsigned int old_detach_count;
2732
bool become_nonbusy = false;
2733
bool attach_locked;
2734
2735
/* Protect against device detachment during operation. */
2736
down_read(&dev->attach_lock);
2737
attach_locked = true;
2738
old_detach_count = dev->detach_count;
2739
2740
if (!dev->attached) {
2741
dev_dbg(dev->class_dev, "no driver attached\n");
2742
retval = -ENODEV;
2743
goto out;
2744
}
2745
2746
s = comedi_file_read_subdevice(file);
2747
if (!s || !s->async) {
2748
retval = -EIO;
2749
goto out;
2750
}
2751
2752
async = s->async;
2753
if (s->busy != file || (async->cmd.flags & CMDF_WRITE)) {
2754
retval = -EINVAL;
2755
goto out;
2756
}
2757
2758
add_wait_queue(&async->wait_head, &wait);
2759
while (count == 0 && !retval) {
2760
set_current_state(TASK_INTERRUPTIBLE);
2761
2762
m = comedi_buf_read_n_available(s);
2763
n = min_t(size_t, m, nbytes);
2764
2765
if (n == 0) {
2766
unsigned int runflags =
2767
comedi_get_subdevice_runflags(s);
2768
2769
if (!comedi_is_runflags_running(runflags)) {
2770
if (comedi_is_runflags_in_error(runflags))
2771
retval = -EPIPE;
2772
if (retval || nbytes)
2773
become_nonbusy = true;
2774
break;
2775
}
2776
if (nbytes == 0)
2777
break;
2778
if (file->f_flags & O_NONBLOCK) {
2779
retval = -EAGAIN;
2780
break;
2781
}
2782
schedule();
2783
if (signal_pending(current)) {
2784
retval = -ERESTARTSYS;
2785
break;
2786
}
2787
if (s->busy != file ||
2788
(async->cmd.flags & CMDF_WRITE)) {
2789
retval = -EINVAL;
2790
break;
2791
}
2792
continue;
2793
}
2794
2795
set_current_state(TASK_RUNNING);
2796
m = comedi_buf_copy_to_user(s, buf, async->buf_read_ptr, n);
2797
if (m) {
2798
n -= m;
2799
retval = -EFAULT;
2800
}
2801
2802
comedi_buf_read_alloc(s, n);
2803
comedi_buf_read_free(s, n);
2804
2805
count += n;
2806
nbytes -= n;
2807
2808
buf += n;
2809
}
2810
remove_wait_queue(&async->wait_head, &wait);
2811
set_current_state(TASK_RUNNING);
2812
if (become_nonbusy && count == 0) {
2813
struct comedi_subdevice *new_s;
2814
2815
/*
2816
* To avoid deadlock, cannot acquire dev->mutex
2817
* while dev->attach_lock is held.
2818
*/
2819
up_read(&dev->attach_lock);
2820
attach_locked = false;
2821
mutex_lock(&dev->mutex);
2822
/*
2823
* Check device hasn't become detached behind our back.
2824
* Checking dev->detach_count is unchanged ought to be
2825
* sufficient (unless there have been 2**32 detaches in the
2826
* meantime!), but check the subdevice pointer as well just in
2827
* case.
2828
*
2829
* Also check the subdevice is still in a suitable state to
2830
* become non-busy in case it changed behind our back.
2831
*/
2832
new_s = comedi_file_read_subdevice(file);
2833
if (dev->attached && old_detach_count == dev->detach_count &&
2834
s == new_s && new_s->async == async && s->busy == file &&
2835
!(async->cmd.flags & CMDF_WRITE) &&
2836
!comedi_is_subdevice_running(s) &&
2837
comedi_buf_read_n_available(s) == 0)
2838
do_become_nonbusy(dev, s);
2839
mutex_unlock(&dev->mutex);
2840
}
2841
out:
2842
if (attach_locked)
2843
up_read(&dev->attach_lock);
2844
2845
return count ? count : retval;
2846
}
2847
2848
static int comedi_open(struct inode *inode, struct file *file)
2849
{
2850
const unsigned int minor = iminor(inode);
2851
struct comedi_file *cfp;
2852
struct comedi_device *dev = comedi_dev_get_from_minor(minor);
2853
int rc;
2854
2855
if (!dev) {
2856
pr_debug("invalid minor number\n");
2857
return -ENODEV;
2858
}
2859
2860
cfp = kzalloc(sizeof(*cfp), GFP_KERNEL);
2861
if (!cfp) {
2862
comedi_dev_put(dev);
2863
return -ENOMEM;
2864
}
2865
2866
cfp->dev = dev;
2867
2868
mutex_lock(&dev->mutex);
2869
if (!dev->attached && !capable(CAP_SYS_ADMIN)) {
2870
dev_dbg(dev->class_dev, "not attached and not CAP_SYS_ADMIN\n");
2871
rc = -ENODEV;
2872
goto out;
2873
}
2874
if (dev->attached && dev->use_count == 0) {
2875
if (!try_module_get(dev->driver->module)) {
2876
rc = -ENXIO;
2877
goto out;
2878
}
2879
if (dev->open) {
2880
rc = dev->open(dev);
2881
if (rc < 0) {
2882
module_put(dev->driver->module);
2883
goto out;
2884
}
2885
}
2886
}
2887
2888
dev->use_count++;
2889
file->private_data = cfp;
2890
comedi_file_reset(file);
2891
rc = 0;
2892
2893
out:
2894
mutex_unlock(&dev->mutex);
2895
if (rc) {
2896
comedi_dev_put(dev);
2897
kfree(cfp);
2898
}
2899
return rc;
2900
}
2901
2902
static int comedi_fasync(int fd, struct file *file, int on)
2903
{
2904
struct comedi_file *cfp = file->private_data;
2905
struct comedi_device *dev = cfp->dev;
2906
2907
return fasync_helper(fd, file, on, &dev->async_queue);
2908
}
2909
2910
static int comedi_close(struct inode *inode, struct file *file)
2911
{
2912
struct comedi_file *cfp = file->private_data;
2913
struct comedi_device *dev = cfp->dev;
2914
struct comedi_subdevice *s = NULL;
2915
int i;
2916
2917
mutex_lock(&dev->mutex);
2918
2919
if (dev->subdevices) {
2920
for (i = 0; i < dev->n_subdevices; i++) {
2921
s = &dev->subdevices[i];
2922
2923
if (s->busy == file)
2924
do_cancel(dev, s);
2925
if (s->lock == file)
2926
s->lock = NULL;
2927
}
2928
}
2929
if (dev->attached && dev->use_count == 1) {
2930
if (dev->close)
2931
dev->close(dev);
2932
module_put(dev->driver->module);
2933
}
2934
2935
dev->use_count--;
2936
2937
mutex_unlock(&dev->mutex);
2938
comedi_dev_put(dev);
2939
kfree(cfp);
2940
2941
return 0;
2942
}
2943
2944
#ifdef CONFIG_COMPAT
2945
2946
#define COMEDI32_CHANINFO _IOR(CIO, 3, struct comedi32_chaninfo_struct)
2947
#define COMEDI32_RANGEINFO _IOR(CIO, 8, struct comedi32_rangeinfo_struct)
2948
/*
2949
* N.B. COMEDI32_CMD and COMEDI_CMD ought to use _IOWR, not _IOR.
2950
* It's too late to change it now, but it only affects the command number.
2951
*/
2952
#define COMEDI32_CMD _IOR(CIO, 9, struct comedi32_cmd_struct)
2953
/*
2954
* N.B. COMEDI32_CMDTEST and COMEDI_CMDTEST ought to use _IOWR, not _IOR.
2955
* It's too late to change it now, but it only affects the command number.
2956
*/
2957
#define COMEDI32_CMDTEST _IOR(CIO, 10, struct comedi32_cmd_struct)
2958
#define COMEDI32_INSNLIST _IOR(CIO, 11, struct comedi32_insnlist_struct)
2959
#define COMEDI32_INSN _IOR(CIO, 12, struct comedi32_insn_struct)
2960
2961
struct comedi32_chaninfo_struct {
2962
unsigned int subdev;
2963
compat_uptr_t maxdata_list; /* 32-bit 'unsigned int *' */
2964
compat_uptr_t flaglist; /* 32-bit 'unsigned int *' */
2965
compat_uptr_t rangelist; /* 32-bit 'unsigned int *' */
2966
unsigned int unused[4];
2967
};
2968
2969
struct comedi32_rangeinfo_struct {
2970
unsigned int range_type;
2971
compat_uptr_t range_ptr; /* 32-bit 'void *' */
2972
};
2973
2974
struct comedi32_cmd_struct {
2975
unsigned int subdev;
2976
unsigned int flags;
2977
unsigned int start_src;
2978
unsigned int start_arg;
2979
unsigned int scan_begin_src;
2980
unsigned int scan_begin_arg;
2981
unsigned int convert_src;
2982
unsigned int convert_arg;
2983
unsigned int scan_end_src;
2984
unsigned int scan_end_arg;
2985
unsigned int stop_src;
2986
unsigned int stop_arg;
2987
compat_uptr_t chanlist; /* 32-bit 'unsigned int *' */
2988
unsigned int chanlist_len;
2989
compat_uptr_t data; /* 32-bit 'short *' */
2990
unsigned int data_len;
2991
};
2992
2993
struct comedi32_insn_struct {
2994
unsigned int insn;
2995
unsigned int n;
2996
compat_uptr_t data; /* 32-bit 'unsigned int *' */
2997
unsigned int subdev;
2998
unsigned int chanspec;
2999
unsigned int unused[3];
3000
};
3001
3002
struct comedi32_insnlist_struct {
3003
unsigned int n_insns;
3004
compat_uptr_t insns; /* 32-bit 'struct comedi_insn *' */
3005
};
3006
3007
/* Handle 32-bit COMEDI_CHANINFO ioctl. */
3008
static int compat_chaninfo(struct file *file, unsigned long arg)
3009
{
3010
struct comedi_file *cfp = file->private_data;
3011
struct comedi_device *dev = cfp->dev;
3012
struct comedi32_chaninfo_struct chaninfo32;
3013
struct comedi_chaninfo chaninfo;
3014
int err;
3015
3016
if (copy_from_user(&chaninfo32, compat_ptr(arg), sizeof(chaninfo32)))
3017
return -EFAULT;
3018
3019
memset(&chaninfo, 0, sizeof(chaninfo));
3020
chaninfo.subdev = chaninfo32.subdev;
3021
chaninfo.maxdata_list = compat_ptr(chaninfo32.maxdata_list);
3022
chaninfo.flaglist = compat_ptr(chaninfo32.flaglist);
3023
chaninfo.rangelist = compat_ptr(chaninfo32.rangelist);
3024
3025
mutex_lock(&dev->mutex);
3026
err = do_chaninfo_ioctl(dev, &chaninfo);
3027
mutex_unlock(&dev->mutex);
3028
return err;
3029
}
3030
3031
/* Handle 32-bit COMEDI_RANGEINFO ioctl. */
3032
static int compat_rangeinfo(struct file *file, unsigned long arg)
3033
{
3034
struct comedi_file *cfp = file->private_data;
3035
struct comedi_device *dev = cfp->dev;
3036
struct comedi32_rangeinfo_struct rangeinfo32;
3037
struct comedi_rangeinfo rangeinfo;
3038
int err;
3039
3040
if (copy_from_user(&rangeinfo32, compat_ptr(arg), sizeof(rangeinfo32)))
3041
return -EFAULT;
3042
memset(&rangeinfo, 0, sizeof(rangeinfo));
3043
rangeinfo.range_type = rangeinfo32.range_type;
3044
rangeinfo.range_ptr = compat_ptr(rangeinfo32.range_ptr);
3045
3046
mutex_lock(&dev->mutex);
3047
err = do_rangeinfo_ioctl(dev, &rangeinfo);
3048
mutex_unlock(&dev->mutex);
3049
return err;
3050
}
3051
3052
/* Copy 32-bit cmd structure to native cmd structure. */
3053
static int get_compat_cmd(struct comedi_cmd *cmd,
3054
struct comedi32_cmd_struct __user *cmd32)
3055
{
3056
struct comedi32_cmd_struct v32;
3057
3058
if (copy_from_user(&v32, cmd32, sizeof(v32)))
3059
return -EFAULT;
3060
3061
cmd->subdev = v32.subdev;
3062
cmd->flags = v32.flags;
3063
cmd->start_src = v32.start_src;
3064
cmd->start_arg = v32.start_arg;
3065
cmd->scan_begin_src = v32.scan_begin_src;
3066
cmd->scan_begin_arg = v32.scan_begin_arg;
3067
cmd->convert_src = v32.convert_src;
3068
cmd->convert_arg = v32.convert_arg;
3069
cmd->scan_end_src = v32.scan_end_src;
3070
cmd->scan_end_arg = v32.scan_end_arg;
3071
cmd->stop_src = v32.stop_src;
3072
cmd->stop_arg = v32.stop_arg;
3073
cmd->chanlist = (unsigned int __force *)compat_ptr(v32.chanlist);
3074
cmd->chanlist_len = v32.chanlist_len;
3075
cmd->data = compat_ptr(v32.data);
3076
cmd->data_len = v32.data_len;
3077
return 0;
3078
}
3079
3080
/* Copy native cmd structure to 32-bit cmd structure. */
3081
static int put_compat_cmd(struct comedi32_cmd_struct __user *cmd32,
3082
struct comedi_cmd *cmd)
3083
{
3084
struct comedi32_cmd_struct v32;
3085
3086
memset(&v32, 0, sizeof(v32));
3087
v32.subdev = cmd->subdev;
3088
v32.flags = cmd->flags;
3089
v32.start_src = cmd->start_src;
3090
v32.start_arg = cmd->start_arg;
3091
v32.scan_begin_src = cmd->scan_begin_src;
3092
v32.scan_begin_arg = cmd->scan_begin_arg;
3093
v32.convert_src = cmd->convert_src;
3094
v32.convert_arg = cmd->convert_arg;
3095
v32.scan_end_src = cmd->scan_end_src;
3096
v32.scan_end_arg = cmd->scan_end_arg;
3097
v32.stop_src = cmd->stop_src;
3098
v32.stop_arg = cmd->stop_arg;
3099
/* Assume chanlist pointer is unchanged. */
3100
v32.chanlist = ptr_to_compat((unsigned int __user *)cmd->chanlist);
3101
v32.chanlist_len = cmd->chanlist_len;
3102
v32.data = ptr_to_compat(cmd->data);
3103
v32.data_len = cmd->data_len;
3104
if (copy_to_user(cmd32, &v32, sizeof(v32)))
3105
return -EFAULT;
3106
return 0;
3107
}
3108
3109
/* Handle 32-bit COMEDI_CMD ioctl. */
3110
static int compat_cmd(struct file *file, unsigned long arg)
3111
{
3112
struct comedi_file *cfp = file->private_data;
3113
struct comedi_device *dev = cfp->dev;
3114
struct comedi_cmd cmd;
3115
bool copy = false;
3116
int rc, err;
3117
3118
rc = get_compat_cmd(&cmd, compat_ptr(arg));
3119
if (rc)
3120
return rc;
3121
3122
mutex_lock(&dev->mutex);
3123
rc = do_cmd_ioctl(dev, &cmd, &copy, file);
3124
mutex_unlock(&dev->mutex);
3125
if (copy) {
3126
/* Special case: copy cmd back to user. */
3127
err = put_compat_cmd(compat_ptr(arg), &cmd);
3128
if (err)
3129
rc = err;
3130
}
3131
return rc;
3132
}
3133
3134
/* Handle 32-bit COMEDI_CMDTEST ioctl. */
3135
static int compat_cmdtest(struct file *file, unsigned long arg)
3136
{
3137
struct comedi_file *cfp = file->private_data;
3138
struct comedi_device *dev = cfp->dev;
3139
struct comedi_cmd cmd;
3140
bool copy = false;
3141
int rc, err;
3142
3143
rc = get_compat_cmd(&cmd, compat_ptr(arg));
3144
if (rc)
3145
return rc;
3146
3147
mutex_lock(&dev->mutex);
3148
rc = do_cmdtest_ioctl(dev, &cmd, &copy, file);
3149
mutex_unlock(&dev->mutex);
3150
if (copy) {
3151
err = put_compat_cmd(compat_ptr(arg), &cmd);
3152
if (err)
3153
rc = err;
3154
}
3155
return rc;
3156
}
3157
3158
/* Copy 32-bit insn structure to native insn structure. */
3159
static int get_compat_insn(struct comedi_insn *insn,
3160
struct comedi32_insn_struct __user *insn32)
3161
{
3162
struct comedi32_insn_struct v32;
3163
3164
/* Copy insn structure. Ignore the unused members. */
3165
if (copy_from_user(&v32, insn32, sizeof(v32)))
3166
return -EFAULT;
3167
memset(insn, 0, sizeof(*insn));
3168
insn->insn = v32.insn;
3169
insn->n = v32.n;
3170
insn->data = compat_ptr(v32.data);
3171
insn->subdev = v32.subdev;
3172
insn->chanspec = v32.chanspec;
3173
return 0;
3174
}
3175
3176
/* Handle 32-bit COMEDI_INSNLIST ioctl. */
3177
static int compat_insnlist(struct file *file, unsigned long arg)
3178
{
3179
struct comedi_file *cfp = file->private_data;
3180
struct comedi_device *dev = cfp->dev;
3181
struct comedi32_insnlist_struct insnlist32;
3182
struct comedi32_insn_struct __user *insn32;
3183
struct comedi_insn *insns;
3184
unsigned int n;
3185
int rc;
3186
3187
if (copy_from_user(&insnlist32, compat_ptr(arg), sizeof(insnlist32)))
3188
return -EFAULT;
3189
3190
rc = check_insnlist_len(dev, insnlist32.n_insns);
3191
if (rc)
3192
return rc;
3193
insns = kcalloc(insnlist32.n_insns, sizeof(*insns), GFP_KERNEL);
3194
if (!insns)
3195
return -ENOMEM;
3196
3197
/* Copy insn structures. */
3198
insn32 = compat_ptr(insnlist32.insns);
3199
for (n = 0; n < insnlist32.n_insns; n++) {
3200
rc = get_compat_insn(insns + n, insn32 + n);
3201
if (rc) {
3202
kfree(insns);
3203
return rc;
3204
}
3205
}
3206
3207
mutex_lock(&dev->mutex);
3208
rc = do_insnlist_ioctl(dev, insns, insnlist32.n_insns, file);
3209
mutex_unlock(&dev->mutex);
3210
kfree(insns);
3211
return rc;
3212
}
3213
3214
/* Handle 32-bit COMEDI_INSN ioctl. */
3215
static int compat_insn(struct file *file, unsigned long arg)
3216
{
3217
struct comedi_file *cfp = file->private_data;
3218
struct comedi_device *dev = cfp->dev;
3219
struct comedi_insn insn;
3220
int rc;
3221
3222
rc = get_compat_insn(&insn, (void __user *)arg);
3223
if (rc)
3224
return rc;
3225
3226
mutex_lock(&dev->mutex);
3227
rc = do_insn_ioctl(dev, &insn, file);
3228
mutex_unlock(&dev->mutex);
3229
return rc;
3230
}
3231
3232
/*
3233
* compat_ioctl file operation.
3234
*
3235
* Returns -ENOIOCTLCMD for unrecognised ioctl codes.
3236
*/
3237
static long comedi_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3238
{
3239
int rc;
3240
3241
switch (cmd) {
3242
case COMEDI_DEVCONFIG:
3243
case COMEDI_DEVINFO:
3244
case COMEDI_SUBDINFO:
3245
case COMEDI_BUFCONFIG:
3246
case COMEDI_BUFINFO:
3247
/* Just need to translate the pointer argument. */
3248
arg = (unsigned long)compat_ptr(arg);
3249
rc = comedi_unlocked_ioctl(file, cmd, arg);
3250
break;
3251
case COMEDI_LOCK:
3252
case COMEDI_UNLOCK:
3253
case COMEDI_CANCEL:
3254
case COMEDI_POLL:
3255
case COMEDI_SETRSUBD:
3256
case COMEDI_SETWSUBD:
3257
/* No translation needed. */
3258
rc = comedi_unlocked_ioctl(file, cmd, arg);
3259
break;
3260
case COMEDI32_CHANINFO:
3261
rc = compat_chaninfo(file, arg);
3262
break;
3263
case COMEDI32_RANGEINFO:
3264
rc = compat_rangeinfo(file, arg);
3265
break;
3266
case COMEDI32_CMD:
3267
rc = compat_cmd(file, arg);
3268
break;
3269
case COMEDI32_CMDTEST:
3270
rc = compat_cmdtest(file, arg);
3271
break;
3272
case COMEDI32_INSNLIST:
3273
rc = compat_insnlist(file, arg);
3274
break;
3275
case COMEDI32_INSN:
3276
rc = compat_insn(file, arg);
3277
break;
3278
default:
3279
rc = -ENOIOCTLCMD;
3280
break;
3281
}
3282
return rc;
3283
}
3284
#else
3285
#define comedi_compat_ioctl NULL
3286
#endif
3287
3288
static const struct file_operations comedi_fops = {
3289
.owner = THIS_MODULE,
3290
.unlocked_ioctl = comedi_unlocked_ioctl,
3291
.compat_ioctl = comedi_compat_ioctl,
3292
.open = comedi_open,
3293
.release = comedi_close,
3294
.read = comedi_read,
3295
.write = comedi_write,
3296
.mmap = comedi_mmap,
3297
.poll = comedi_poll,
3298
.fasync = comedi_fasync,
3299
.llseek = noop_llseek,
3300
};
3301
3302
/**
3303
* comedi_event() - Handle events for asynchronous COMEDI command
3304
* @dev: COMEDI device.
3305
* @s: COMEDI subdevice.
3306
* Context: in_interrupt() (usually), @s->spin_lock spin-lock not held.
3307
*
3308
* If an asynchronous COMEDI command is active on the subdevice, process
3309
* any %COMEDI_CB_... event flags that have been set, usually by an
3310
* interrupt handler. These may change the run state of the asynchronous
3311
* command, wake a task, and/or send a %SIGIO signal.
3312
*/
3313
void comedi_event(struct comedi_device *dev, struct comedi_subdevice *s)
3314
{
3315
struct comedi_async *async = s->async;
3316
unsigned int events;
3317
int si_code = 0;
3318
unsigned long flags;
3319
3320
spin_lock_irqsave(&s->spin_lock, flags);
3321
3322
events = async->events;
3323
async->events = 0;
3324
if (!__comedi_is_subdevice_running(s)) {
3325
spin_unlock_irqrestore(&s->spin_lock, flags);
3326
return;
3327
}
3328
3329
if (events & COMEDI_CB_CANCEL_MASK)
3330
__comedi_clear_subdevice_runflags(s, COMEDI_SRF_RUNNING);
3331
3332
/*
3333
* Remember if an error event has occurred, so an error can be
3334
* returned the next time the user does a read() or write().
3335
*/
3336
if (events & COMEDI_CB_ERROR_MASK)
3337
__comedi_set_subdevice_runflags(s, COMEDI_SRF_ERROR);
3338
3339
if (async->cb_mask & events) {
3340
wake_up_interruptible(&async->wait_head);
3341
si_code = async->cmd.flags & CMDF_WRITE ? POLL_OUT : POLL_IN;
3342
}
3343
3344
spin_unlock_irqrestore(&s->spin_lock, flags);
3345
3346
if (si_code)
3347
kill_fasync(&dev->async_queue, SIGIO, si_code);
3348
}
3349
EXPORT_SYMBOL_GPL(comedi_event);
3350
3351
/* Note: the ->mutex is pre-locked on successful return */
3352
struct comedi_device *comedi_alloc_board_minor(struct device *hardware_device)
3353
{
3354
struct comedi_device *dev;
3355
struct device *csdev;
3356
unsigned int i;
3357
3358
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
3359
if (!dev)
3360
return ERR_PTR(-ENOMEM);
3361
comedi_device_init(dev);
3362
comedi_set_hw_dev(dev, hardware_device);
3363
mutex_lock(&dev->mutex);
3364
mutex_lock(&comedi_board_minor_table_lock);
3365
for (i = hardware_device ? comedi_num_legacy_minors : 0;
3366
i < COMEDI_NUM_BOARD_MINORS; ++i) {
3367
if (!comedi_board_minor_table[i]) {
3368
comedi_board_minor_table[i] = dev;
3369
break;
3370
}
3371
}
3372
mutex_unlock(&comedi_board_minor_table_lock);
3373
if (i == COMEDI_NUM_BOARD_MINORS) {
3374
mutex_unlock(&dev->mutex);
3375
comedi_device_cleanup(dev);
3376
comedi_dev_put(dev);
3377
dev_err(hardware_device,
3378
"ran out of minor numbers for board device files\n");
3379
return ERR_PTR(-EBUSY);
3380
}
3381
dev->minor = i;
3382
csdev = device_create(&comedi_class, hardware_device,
3383
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i", i);
3384
if (!IS_ERR(csdev))
3385
dev->class_dev = get_device(csdev);
3386
3387
/* Note: dev->mutex needs to be unlocked by the caller. */
3388
return dev;
3389
}
3390
3391
void comedi_release_hardware_device(struct device *hardware_device)
3392
{
3393
int minor;
3394
struct comedi_device *dev;
3395
3396
for (minor = comedi_num_legacy_minors; minor < COMEDI_NUM_BOARD_MINORS;
3397
minor++) {
3398
mutex_lock(&comedi_board_minor_table_lock);
3399
dev = comedi_board_minor_table[minor];
3400
if (dev && dev->hw_dev == hardware_device) {
3401
comedi_board_minor_table[minor] = NULL;
3402
mutex_unlock(&comedi_board_minor_table_lock);
3403
comedi_free_board_dev(dev);
3404
break;
3405
}
3406
mutex_unlock(&comedi_board_minor_table_lock);
3407
}
3408
}
3409
3410
int comedi_alloc_subdevice_minor(struct comedi_subdevice *s)
3411
{
3412
struct comedi_device *dev = s->device;
3413
struct device *csdev;
3414
unsigned int i;
3415
3416
mutex_lock(&comedi_subdevice_minor_table_lock);
3417
for (i = 0; i < COMEDI_NUM_SUBDEVICE_MINORS; ++i) {
3418
if (!comedi_subdevice_minor_table[i]) {
3419
comedi_subdevice_minor_table[i] = s;
3420
break;
3421
}
3422
}
3423
mutex_unlock(&comedi_subdevice_minor_table_lock);
3424
if (i == COMEDI_NUM_SUBDEVICE_MINORS) {
3425
dev_err(dev->class_dev,
3426
"ran out of minor numbers for subdevice files\n");
3427
return -EBUSY;
3428
}
3429
i += COMEDI_NUM_BOARD_MINORS;
3430
s->minor = i;
3431
csdev = device_create(&comedi_class, dev->class_dev,
3432
MKDEV(COMEDI_MAJOR, i), NULL, "comedi%i_subd%i",
3433
dev->minor, s->index);
3434
if (!IS_ERR(csdev))
3435
s->class_dev = csdev;
3436
3437
return 0;
3438
}
3439
3440
void comedi_free_subdevice_minor(struct comedi_subdevice *s)
3441
{
3442
unsigned int i;
3443
3444
if (!s)
3445
return;
3446
if (s->minor < COMEDI_NUM_BOARD_MINORS ||
3447
s->minor >= COMEDI_NUM_MINORS)
3448
return;
3449
3450
i = s->minor - COMEDI_NUM_BOARD_MINORS;
3451
mutex_lock(&comedi_subdevice_minor_table_lock);
3452
if (s == comedi_subdevice_minor_table[i])
3453
comedi_subdevice_minor_table[i] = NULL;
3454
mutex_unlock(&comedi_subdevice_minor_table_lock);
3455
if (s->class_dev) {
3456
device_destroy(&comedi_class, MKDEV(COMEDI_MAJOR, s->minor));
3457
s->class_dev = NULL;
3458
}
3459
}
3460
3461
static void comedi_cleanup_board_minors(void)
3462
{
3463
struct comedi_device *dev;
3464
unsigned int i;
3465
3466
for (i = 0; i < COMEDI_NUM_BOARD_MINORS; i++) {
3467
dev = comedi_clear_board_minor(i);
3468
comedi_free_board_dev(dev);
3469
}
3470
}
3471
3472
static int __init comedi_init(void)
3473
{
3474
int i;
3475
int retval;
3476
3477
pr_info("version " COMEDI_RELEASE " - http://www.comedi.org\n");
3478
3479
if (comedi_num_legacy_minors > COMEDI_NUM_BOARD_MINORS) {
3480
pr_err("invalid value for module parameter \"comedi_num_legacy_minors\". Valid values are 0 through %i.\n",
3481
COMEDI_NUM_BOARD_MINORS);
3482
return -EINVAL;
3483
}
3484
3485
retval = register_chrdev_region(MKDEV(COMEDI_MAJOR, 0),
3486
COMEDI_NUM_MINORS, "comedi");
3487
if (retval)
3488
return retval;
3489
3490
cdev_init(&comedi_cdev, &comedi_fops);
3491
comedi_cdev.owner = THIS_MODULE;
3492
3493
retval = kobject_set_name(&comedi_cdev.kobj, "comedi");
3494
if (retval)
3495
goto out_unregister_chrdev_region;
3496
3497
retval = cdev_add(&comedi_cdev, MKDEV(COMEDI_MAJOR, 0),
3498
COMEDI_NUM_MINORS);
3499
if (retval)
3500
goto out_unregister_chrdev_region;
3501
3502
retval = class_register(&comedi_class);
3503
if (retval) {
3504
pr_err("failed to create class\n");
3505
goto out_cdev_del;
3506
}
3507
3508
/* create devices files for legacy/manual use */
3509
for (i = 0; i < comedi_num_legacy_minors; i++) {
3510
struct comedi_device *dev;
3511
3512
dev = comedi_alloc_board_minor(NULL);
3513
if (IS_ERR(dev)) {
3514
retval = PTR_ERR(dev);
3515
goto out_cleanup_board_minors;
3516
}
3517
/* comedi_alloc_board_minor() locked the mutex */
3518
lockdep_assert_held(&dev->mutex);
3519
mutex_unlock(&dev->mutex);
3520
}
3521
3522
/* XXX requires /proc interface */
3523
comedi_proc_init();
3524
3525
return 0;
3526
3527
out_cleanup_board_minors:
3528
comedi_cleanup_board_minors();
3529
class_unregister(&comedi_class);
3530
out_cdev_del:
3531
cdev_del(&comedi_cdev);
3532
out_unregister_chrdev_region:
3533
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
3534
return retval;
3535
}
3536
module_init(comedi_init);
3537
3538
static void __exit comedi_cleanup(void)
3539
{
3540
comedi_cleanup_board_minors();
3541
class_unregister(&comedi_class);
3542
cdev_del(&comedi_cdev);
3543
unregister_chrdev_region(MKDEV(COMEDI_MAJOR, 0), COMEDI_NUM_MINORS);
3544
3545
comedi_proc_cleanup();
3546
}
3547
module_exit(comedi_cleanup);
3548
3549
MODULE_AUTHOR("https://www.comedi.org");
3550
MODULE_DESCRIPTION("Comedi core module");
3551
MODULE_LICENSE("GPL");
3552
3553