4 * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
5 * & Marcus Metzler <marcus@convergence.de>
6 * for convergence integrated media GmbH
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.
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.
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.
24 #include <asm/types.h>
25 #include <asm/semaphore.h>
26 #include <linux/errno.h>
27 #include <linux/string.h>
28 #include <linux/module.h>
29 #include <linux/kernel.h>
30 #include <linux/sched.h>
31 #include <linux/init.h>
32 #include <linux/slab.h>
33 #include <linux/version.h>
36 #include "dvb_functions.h"
38 static int dvbdev_debug
= 0;
39 #define dprintk if (dvbdev_debug) printk
41 static LIST_HEAD(dvb_adapter_list
);
42 static DECLARE_MUTEX(dvbdev_register_lock
);
45 static char *dnames
[] = {
46 "video", "audio", "sec", "frontend", "demux", "dvr", "ca",
52 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type)
55 struct dvb_device
* dvbdev_find_device (int minor
)
57 struct list_head
*entry
;
59 list_for_each (entry
, &dvb_adapter_list
) {
60 struct list_head
*entry0
;
61 struct dvb_adapter
*adap
;
62 adap
= list_entry (entry
, struct dvb_adapter
, list_head
);
63 list_for_each (entry0
, &adap
->device_list
) {
64 struct dvb_device
*dev
;
65 dev
= list_entry (entry0
, struct dvb_device
, list_head
);
66 if (nums2minor(adap
->num
, dev
->type
, dev
->id
) == minor
)
76 int dvb_device_open(struct inode
*inode
, struct file
*file
)
78 struct dvb_device
*dvbdev
;
80 dvbdev
= dvbdev_find_device (minor(inode
->i_rdev
));
82 if (dvbdev
&& dvbdev
->fops
) {
84 struct file_operations
*old_fops
;
86 file
->private_data
= dvbdev
;
87 old_fops
= file
->f_op
;
88 file
->f_op
= fops_get(dvbdev
->fops
);
90 err
= file
->f_op
->open(inode
,file
);
93 file
->f_op
= fops_get(old_fops
);
102 static struct file_operations dvb_device_fops
=
104 .owner
= THIS_MODULE
,
105 .open
= dvb_device_open
,
109 int dvb_generic_open(struct inode
*inode
, struct file
*file
)
111 struct dvb_device
*dvbdev
= file
->private_data
;
119 if ((file
->f_flags
& O_ACCMODE
) != O_RDONLY
) {
120 if (!dvbdev
->writers
)
130 int dvb_generic_release(struct inode
*inode
, struct file
*file
)
132 struct dvb_device
*dvbdev
= file
->private_data
;
137 if ((file
->f_flags
& O_ACCMODE
) != O_RDONLY
)
145 int dvb_generic_ioctl(struct inode
*inode
, struct file
*file
,
146 unsigned int cmd
, unsigned long arg
)
148 struct dvb_device
*dvbdev
= file
->private_data
;
153 if (!dvbdev
->kernel_ioctl
)
156 return dvb_usercopy (inode
, file
, cmd
, arg
, dvbdev
->kernel_ioctl
);
161 int dvbdev_get_free_id (struct dvb_adapter
*adap
, int type
)
165 while (id
< DVB_MAX_IDS
) {
166 struct list_head
*entry
;
167 list_for_each (entry
, &adap
->device_list
) {
168 struct dvb_device
*dev
;
169 dev
= list_entry (entry
, struct dvb_device
, list_head
);
170 if (dev
->type
== type
&& dev
->id
== id
)
181 int dvb_register_device(struct dvb_adapter
*adap
, struct dvb_device
**pdvbdev
,
182 const struct dvb_device
*template, void *priv
, int type
)
184 struct dvb_device
*dvbdev
;
187 if (down_interruptible (&dvbdev_register_lock
))
190 if ((id
= dvbdev_get_free_id (adap
, type
)) < 0) {
191 up (&dvbdev_register_lock
);
193 printk ("%s: could get find free device id...\n", __FUNCTION__
);
197 *pdvbdev
= dvbdev
= kmalloc(sizeof(struct dvb_device
), GFP_KERNEL
);
200 up(&dvbdev_register_lock
);
204 up (&dvbdev_register_lock
);
206 memcpy(dvbdev
, template, sizeof(struct dvb_device
));
209 dvbdev
->adapter
= adap
;
212 list_add_tail (&dvbdev
->list_head
, &adap
->device_list
);
214 devfs_mk_cdev(MKDEV(DVB_MAJOR
, nums2minor(adap
->num
, type
, id
)),
215 S_IFCHR
| S_IRUSR
| S_IWUSR
,
216 "dvb/adapter%d/%s%d", adap
->num
, dnames
[type
], id
);
218 dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
219 adap
->num
, dnames
[type
], id
, nums2minor(adap
->num
, type
, id
),
220 nums2minor(adap
->num
, type
, id
));
226 void dvb_unregister_device(struct dvb_device
*dvbdev
)
229 devfs_remove("dvb/adapter%d/%s%d", dvbdev
->adapter
->num
,
230 dnames
[dvbdev
->type
], dvbdev
->id
);
231 list_del(&dvbdev
->list_head
);
238 int dvbdev_get_free_adapter_num (void)
243 struct list_head
*entry
;
244 list_for_each (entry
, &dvb_adapter_list
) {
245 struct dvb_adapter
*adap
;
246 adap
= list_entry (entry
, struct dvb_adapter
, list_head
);
247 if (adap
->num
== num
)
259 int dvb_register_adapter(struct dvb_adapter
**padap
, const char *name
)
261 struct dvb_adapter
*adap
;
264 if (down_interruptible (&dvbdev_register_lock
))
267 if ((num
= dvbdev_get_free_adapter_num ()) < 0) {
268 up (&dvbdev_register_lock
);
272 if (!(*padap
= adap
= kmalloc(sizeof(struct dvb_adapter
), GFP_KERNEL
))) {
273 up(&dvbdev_register_lock
);
277 memset (adap
, 0, sizeof(struct dvb_adapter
));
278 INIT_LIST_HEAD (&adap
->device_list
);
280 printk ("DVB: registering new adapter (%s).\n", name
);
282 devfs_mk_dir("dvb/adapter%d", num
);
286 list_add_tail (&adap
->list_head
, &dvb_adapter_list
);
288 up (&dvbdev_register_lock
);
294 int dvb_unregister_adapter(struct dvb_adapter
*adap
)
296 if (down_interruptible (&dvbdev_register_lock
))
298 devfs_remove("dvb/adapter%d", adap
->num
);
299 list_del (&adap
->list_head
);
300 up (&dvbdev_register_lock
);
307 int __init
init_dvbdev(void)
311 if(register_chrdev(DVB_MAJOR
,"DVB", &dvb_device_fops
)) {
312 printk("video_dev: unable to get major %d\n", DVB_MAJOR
);
321 void __exit
exit_dvbdev(void)
323 unregister_chrdev(DVB_MAJOR
, "DVB");
327 module_init(init_dvbdev
);
328 module_exit(exit_dvbdev
);
330 MODULE_DESCRIPTION("DVB Core Driver");
331 MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
332 MODULE_LICENSE("GPL");
334 MODULE_PARM(dvbdev_debug
,"i");
335 MODULE_PARM_DESC(dvbdev_debug
, "enable verbose debug messages");