Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/media/dvb/dvb-core/dvbdev.c
15112 views
1
/*
2
* dvbdev.c
3
*
4
* Copyright (C) 2000 Ralph Metzler <[email protected]>
5
* & Marcus Metzler <[email protected]>
6
* for convergence integrated media GmbH
7
*
8
* This program is free software; you can redistribute it and/or
9
* modify it under the terms of the GNU Lesser General Public License
10
* as published by the Free Software Foundation; either version 2.1
11
* of the License, or (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU Lesser General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
*
22
*/
23
24
#include <linux/types.h>
25
#include <linux/errno.h>
26
#include <linux/string.h>
27
#include <linux/module.h>
28
#include <linux/kernel.h>
29
#include <linux/init.h>
30
#include <linux/slab.h>
31
#include <linux/device.h>
32
#include <linux/fs.h>
33
#include <linux/cdev.h>
34
#include <linux/mutex.h>
35
#include "dvbdev.h"
36
37
static DEFINE_MUTEX(dvbdev_mutex);
38
static int dvbdev_debug;
39
40
module_param(dvbdev_debug, int, 0644);
41
MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
42
43
#define dprintk if (dvbdev_debug) printk
44
45
static LIST_HEAD(dvb_adapter_list);
46
static DEFINE_MUTEX(dvbdev_register_lock);
47
48
static const char * const dnames[] = {
49
"video", "audio", "sec", "frontend", "demux", "dvr", "ca",
50
"net", "osd"
51
};
52
53
#ifdef CONFIG_DVB_DYNAMIC_MINORS
54
#define MAX_DVB_MINORS 256
55
#define DVB_MAX_IDS MAX_DVB_MINORS
56
#else
57
#define DVB_MAX_IDS 4
58
#define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
59
#define MAX_DVB_MINORS (DVB_MAX_ADAPTERS*64)
60
#endif
61
62
static struct class *dvb_class;
63
64
static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
65
static DECLARE_RWSEM(minor_rwsem);
66
67
static int dvb_device_open(struct inode *inode, struct file *file)
68
{
69
struct dvb_device *dvbdev;
70
71
mutex_lock(&dvbdev_mutex);
72
down_read(&minor_rwsem);
73
dvbdev = dvb_minors[iminor(inode)];
74
75
if (dvbdev && dvbdev->fops) {
76
int err = 0;
77
const struct file_operations *old_fops;
78
79
file->private_data = dvbdev;
80
old_fops = file->f_op;
81
file->f_op = fops_get(dvbdev->fops);
82
if (file->f_op == NULL) {
83
file->f_op = old_fops;
84
goto fail;
85
}
86
if(file->f_op->open)
87
err = file->f_op->open(inode,file);
88
if (err) {
89
fops_put(file->f_op);
90
file->f_op = fops_get(old_fops);
91
}
92
fops_put(old_fops);
93
up_read(&minor_rwsem);
94
mutex_unlock(&dvbdev_mutex);
95
return err;
96
}
97
fail:
98
up_read(&minor_rwsem);
99
mutex_unlock(&dvbdev_mutex);
100
return -ENODEV;
101
}
102
103
104
static const struct file_operations dvb_device_fops =
105
{
106
.owner = THIS_MODULE,
107
.open = dvb_device_open,
108
.llseek = noop_llseek,
109
};
110
111
static struct cdev dvb_device_cdev;
112
113
int dvb_generic_open(struct inode *inode, struct file *file)
114
{
115
struct dvb_device *dvbdev = file->private_data;
116
117
if (!dvbdev)
118
return -ENODEV;
119
120
if (!dvbdev->users)
121
return -EBUSY;
122
123
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
124
if (!dvbdev->readers)
125
return -EBUSY;
126
dvbdev->readers--;
127
} else {
128
if (!dvbdev->writers)
129
return -EBUSY;
130
dvbdev->writers--;
131
}
132
133
dvbdev->users--;
134
return 0;
135
}
136
EXPORT_SYMBOL(dvb_generic_open);
137
138
139
int dvb_generic_release(struct inode *inode, struct file *file)
140
{
141
struct dvb_device *dvbdev = file->private_data;
142
143
if (!dvbdev)
144
return -ENODEV;
145
146
if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
147
dvbdev->readers++;
148
} else {
149
dvbdev->writers++;
150
}
151
152
dvbdev->users++;
153
return 0;
154
}
155
EXPORT_SYMBOL(dvb_generic_release);
156
157
158
long dvb_generic_ioctl(struct file *file,
159
unsigned int cmd, unsigned long arg)
160
{
161
struct dvb_device *dvbdev = file->private_data;
162
163
if (!dvbdev)
164
return -ENODEV;
165
166
if (!dvbdev->kernel_ioctl)
167
return -EINVAL;
168
169
return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
170
}
171
EXPORT_SYMBOL(dvb_generic_ioctl);
172
173
174
static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
175
{
176
u32 id = 0;
177
178
while (id < DVB_MAX_IDS) {
179
struct dvb_device *dev;
180
list_for_each_entry(dev, &adap->device_list, list_head)
181
if (dev->type == type && dev->id == id)
182
goto skip;
183
return id;
184
skip:
185
id++;
186
}
187
return -ENFILE;
188
}
189
190
191
int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
192
const struct dvb_device *template, void *priv, int type)
193
{
194
struct dvb_device *dvbdev;
195
struct file_operations *dvbdevfops;
196
struct device *clsdev;
197
int minor;
198
int id;
199
200
mutex_lock(&dvbdev_register_lock);
201
202
if ((id = dvbdev_get_free_id (adap, type)) < 0){
203
mutex_unlock(&dvbdev_register_lock);
204
*pdvbdev = NULL;
205
printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
206
return -ENFILE;
207
}
208
209
*pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
210
211
if (!dvbdev){
212
mutex_unlock(&dvbdev_register_lock);
213
return -ENOMEM;
214
}
215
216
dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
217
218
if (!dvbdevfops){
219
kfree (dvbdev);
220
mutex_unlock(&dvbdev_register_lock);
221
return -ENOMEM;
222
}
223
224
memcpy(dvbdev, template, sizeof(struct dvb_device));
225
dvbdev->type = type;
226
dvbdev->id = id;
227
dvbdev->adapter = adap;
228
dvbdev->priv = priv;
229
dvbdev->fops = dvbdevfops;
230
init_waitqueue_head (&dvbdev->wait_queue);
231
232
memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
233
dvbdevfops->owner = adap->module;
234
235
list_add_tail (&dvbdev->list_head, &adap->device_list);
236
237
down_write(&minor_rwsem);
238
#ifdef CONFIG_DVB_DYNAMIC_MINORS
239
for (minor = 0; minor < MAX_DVB_MINORS; minor++)
240
if (dvb_minors[minor] == NULL)
241
break;
242
243
if (minor == MAX_DVB_MINORS) {
244
kfree(dvbdevfops);
245
kfree(dvbdev);
246
mutex_unlock(&dvbdev_register_lock);
247
return -EINVAL;
248
}
249
#else
250
minor = nums2minor(adap->num, type, id);
251
#endif
252
253
dvbdev->minor = minor;
254
dvb_minors[minor] = dvbdev;
255
up_write(&minor_rwsem);
256
257
mutex_unlock(&dvbdev_register_lock);
258
259
clsdev = device_create(dvb_class, adap->device,
260
MKDEV(DVB_MAJOR, minor),
261
dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
262
if (IS_ERR(clsdev)) {
263
printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
264
__func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
265
return PTR_ERR(clsdev);
266
}
267
268
dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
269
adap->num, dnames[type], id, minor, minor);
270
271
return 0;
272
}
273
EXPORT_SYMBOL(dvb_register_device);
274
275
276
void dvb_unregister_device(struct dvb_device *dvbdev)
277
{
278
if (!dvbdev)
279
return;
280
281
down_write(&minor_rwsem);
282
dvb_minors[dvbdev->minor] = NULL;
283
up_write(&minor_rwsem);
284
285
device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
286
287
list_del (&dvbdev->list_head);
288
kfree (dvbdev->fops);
289
kfree (dvbdev);
290
}
291
EXPORT_SYMBOL(dvb_unregister_device);
292
293
static int dvbdev_check_free_adapter_num(int num)
294
{
295
struct list_head *entry;
296
list_for_each(entry, &dvb_adapter_list) {
297
struct dvb_adapter *adap;
298
adap = list_entry(entry, struct dvb_adapter, list_head);
299
if (adap->num == num)
300
return 0;
301
}
302
return 1;
303
}
304
305
static int dvbdev_get_free_adapter_num (void)
306
{
307
int num = 0;
308
309
while (num < DVB_MAX_ADAPTERS) {
310
if (dvbdev_check_free_adapter_num(num))
311
return num;
312
num++;
313
}
314
315
return -ENFILE;
316
}
317
318
319
int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
320
struct module *module, struct device *device,
321
short *adapter_nums)
322
{
323
int i, num;
324
325
mutex_lock(&dvbdev_register_lock);
326
327
for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
328
num = adapter_nums[i];
329
if (num >= 0 && num < DVB_MAX_ADAPTERS) {
330
/* use the one the driver asked for */
331
if (dvbdev_check_free_adapter_num(num))
332
break;
333
} else {
334
num = dvbdev_get_free_adapter_num();
335
break;
336
}
337
num = -1;
338
}
339
340
if (num < 0) {
341
mutex_unlock(&dvbdev_register_lock);
342
return -ENFILE;
343
}
344
345
memset (adap, 0, sizeof(struct dvb_adapter));
346
INIT_LIST_HEAD (&adap->device_list);
347
348
printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
349
350
adap->num = num;
351
adap->name = name;
352
adap->module = module;
353
adap->device = device;
354
adap->mfe_shared = 0;
355
adap->mfe_dvbdev = NULL;
356
mutex_init (&adap->mfe_lock);
357
358
list_add_tail (&adap->list_head, &dvb_adapter_list);
359
360
mutex_unlock(&dvbdev_register_lock);
361
362
return num;
363
}
364
EXPORT_SYMBOL(dvb_register_adapter);
365
366
367
int dvb_unregister_adapter(struct dvb_adapter *adap)
368
{
369
mutex_lock(&dvbdev_register_lock);
370
list_del (&adap->list_head);
371
mutex_unlock(&dvbdev_register_lock);
372
return 0;
373
}
374
EXPORT_SYMBOL(dvb_unregister_adapter);
375
376
/* if the miracle happens and "generic_usercopy()" is included into
377
the kernel, then this can vanish. please don't make the mistake and
378
define this as video_usercopy(). this will introduce a dependecy
379
to the v4l "videodev.o" module, which is unnecessary for some
380
cards (ie. the budget dvb-cards don't need the v4l module...) */
381
int dvb_usercopy(struct file *file,
382
unsigned int cmd, unsigned long arg,
383
int (*func)(struct file *file,
384
unsigned int cmd, void *arg))
385
{
386
char sbuf[128];
387
void *mbuf = NULL;
388
void *parg = NULL;
389
int err = -EINVAL;
390
391
/* Copy arguments into temp kernel buffer */
392
switch (_IOC_DIR(cmd)) {
393
case _IOC_NONE:
394
/*
395
* For this command, the pointer is actually an integer
396
* argument.
397
*/
398
parg = (void *) arg;
399
break;
400
case _IOC_READ: /* some v4l ioctls are marked wrong ... */
401
case _IOC_WRITE:
402
case (_IOC_WRITE | _IOC_READ):
403
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
404
parg = sbuf;
405
} else {
406
/* too big to allocate from stack */
407
mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
408
if (NULL == mbuf)
409
return -ENOMEM;
410
parg = mbuf;
411
}
412
413
err = -EFAULT;
414
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
415
goto out;
416
break;
417
}
418
419
/* call driver */
420
mutex_lock(&dvbdev_mutex);
421
if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
422
err = -EINVAL;
423
mutex_unlock(&dvbdev_mutex);
424
425
if (err < 0)
426
goto out;
427
428
/* Copy results into user buffer */
429
switch (_IOC_DIR(cmd))
430
{
431
case _IOC_READ:
432
case (_IOC_WRITE | _IOC_READ):
433
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
434
err = -EFAULT;
435
break;
436
}
437
438
out:
439
kfree(mbuf);
440
return err;
441
}
442
443
static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
444
{
445
struct dvb_device *dvbdev = dev_get_drvdata(dev);
446
447
add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
448
add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
449
add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
450
return 0;
451
}
452
453
static char *dvb_devnode(struct device *dev, mode_t *mode)
454
{
455
struct dvb_device *dvbdev = dev_get_drvdata(dev);
456
457
return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
458
dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
459
}
460
461
462
static int __init init_dvbdev(void)
463
{
464
int retval;
465
dev_t dev = MKDEV(DVB_MAJOR, 0);
466
467
if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
468
printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
469
return retval;
470
}
471
472
cdev_init(&dvb_device_cdev, &dvb_device_fops);
473
if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
474
printk(KERN_ERR "dvb-core: unable register character device\n");
475
goto error;
476
}
477
478
dvb_class = class_create(THIS_MODULE, "dvb");
479
if (IS_ERR(dvb_class)) {
480
retval = PTR_ERR(dvb_class);
481
goto error;
482
}
483
dvb_class->dev_uevent = dvb_uevent;
484
dvb_class->devnode = dvb_devnode;
485
return 0;
486
487
error:
488
cdev_del(&dvb_device_cdev);
489
unregister_chrdev_region(dev, MAX_DVB_MINORS);
490
return retval;
491
}
492
493
494
static void __exit exit_dvbdev(void)
495
{
496
class_destroy(dvb_class);
497
cdev_del(&dvb_device_cdev);
498
unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
499
}
500
501
subsys_initcall(init_dvbdev);
502
module_exit(exit_dvbdev);
503
504
MODULE_DESCRIPTION("DVB Core Driver");
505
MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
506
MODULE_LICENSE("GPL");
507
508