X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fmedia%2Fdvb%2Fdvb-core%2Fdvbdev.c;h=4032239b39d0d613d7c5a837256d1d4799a77c2a;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=686ffc229eec2caa9d1f440d8ce6f40ad7aa955d;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 686ffc229..4032239b3 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -25,29 +25,39 @@ #include #include #include +#include #include #include #include #include +#include +#include +#include #include "dvbdev.h" -#include "dvb_functions.h" -static int dvbdev_debug = 0; +static int dvbdev_debug; + +module_param(dvbdev_debug, int, 0644); +MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off)."); + #define dprintk if (dvbdev_debug) printk static LIST_HEAD(dvb_adapter_list); static DECLARE_MUTEX(dvbdev_register_lock); - -static char *dnames[] = { +static const char * const dnames[] = { "video", "audio", "sec", "frontend", "demux", "dvr", "ca", "net", "osd" }; -#define DVB_MAX_IDS 4 +#define DVB_MAX_IDS 6 #define nums2minor(num,type,id) ((num << 6) | (id << 4) | type) +#define MAX_DVB_MINORS (DVB_MAX_IDS*64) + +struct class_simple *dvb_class; +EXPORT_SYMBOL(dvb_class); static struct dvb_device* dvbdev_find_device (int minor) { @@ -102,6 +112,11 @@ static struct file_operations dvb_device_fops = }; +static struct cdev dvb_device_cdev = { + .kobj = {.name = "dvb", }, + .owner = THIS_MODULE, +}; + int dvb_generic_open(struct inode *inode, struct file *file) { struct dvb_device *dvbdev = file->private_data; @@ -125,6 +140,7 @@ int dvb_generic_open(struct inode *inode, struct file *file) dvbdev->users--; return 0; } +EXPORT_SYMBOL(dvb_generic_open); int dvb_generic_release(struct inode *inode, struct file *file) @@ -143,6 +159,7 @@ int dvb_generic_release(struct inode *inode, struct file *file) dvbdev->users++; return 0; } +EXPORT_SYMBOL(dvb_generic_release); int dvb_generic_ioctl(struct inode *inode, struct file *file, @@ -158,6 +175,7 @@ int dvb_generic_ioctl(struct inode *inode, struct file *file, return dvb_usercopy (inode, file, cmd, arg, dvbdev->kernel_ioctl); } +EXPORT_SYMBOL(dvb_generic_ioctl); static int dvbdev_get_free_id (struct dvb_adapter *adap, int type) @@ -219,12 +237,16 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, S_IFCHR | S_IRUSR | S_IWUSR, "dvb/adapter%d/%s%d", adap->num, dnames[type], id); + class_simple_device_add(dvb_class, MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), + NULL, "dvb%d.%s%d", adap->num, dnames[type], id); + dprintk("DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n", adap->num, dnames[type], id, nums2minor(adap->num, type, id), nums2minor(adap->num, type, id)); return 0; } +EXPORT_SYMBOL(dvb_register_device); void dvb_unregister_device(struct dvb_device *dvbdev) @@ -235,9 +257,13 @@ void dvb_unregister_device(struct dvb_device *dvbdev) devfs_remove("dvb/adapter%d/%s%d", dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id); + class_simple_device_remove(MKDEV(DVB_MAJOR, nums2minor(dvbdev->adapter->num, + dvbdev->type, dvbdev->id))); + list_del(&dvbdev->list_head); kfree(dvbdev); } +EXPORT_SYMBOL(dvb_unregister_device); static int dvbdev_get_free_adapter_num (void) @@ -296,37 +322,127 @@ int dvb_register_adapter(struct dvb_adapter **padap, const char *name, struct mo return num; } +EXPORT_SYMBOL(dvb_register_adapter); int dvb_unregister_adapter(struct dvb_adapter *adap) { + devfs_remove("dvb/adapter%d", adap->num); + if (down_interruptible (&dvbdev_register_lock)) return -ERESTARTSYS; - devfs_remove("dvb/adapter%d", adap->num); list_del (&adap->list_head); up (&dvbdev_register_lock); kfree (adap); return 0; } +EXPORT_SYMBOL(dvb_unregister_adapter); + +/* if the miracle happens and "generic_usercopy()" is included into + the kernel, then this can vanish. please don't make the mistake and + define this as video_usercopy(). this will introduce a dependecy + to the v4l "videodev.o" module, which is unnecessary for some + cards (ie. the budget dvb-cards don't need the v4l module...) */ +int dvb_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)) +{ + char sbuf[128]; + void *mbuf = NULL; + void *parg = NULL; + int err = -EINVAL; + + /* Copy arguments into temp kernel buffer */ + switch (_IOC_DIR(cmd)) { + case _IOC_NONE: + /* + * For this command, the pointer is actually an integer + * argument. + */ + parg = (void *) arg; + break; + case _IOC_READ: /* some v4l ioctls are marked wrong ... */ + case _IOC_WRITE: + case (_IOC_WRITE | _IOC_READ): + if (_IOC_SIZE(cmd) <= sizeof(sbuf)) { + parg = sbuf; + } else { + /* too big to allocate from stack */ + mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL); + if (NULL == mbuf) + return -ENOMEM; + parg = mbuf; + } + err = -EFAULT; + if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd))) + goto out; + break; + } + + /* call driver */ + if ((err = func(inode, file, cmd, parg)) == -ENOIOCTLCMD) + err = -EINVAL; + + if (err < 0) + goto out; + + /* Copy results into user buffer */ + switch (_IOC_DIR(cmd)) + { + case _IOC_READ: + case (_IOC_WRITE | _IOC_READ): + if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) + err = -EFAULT; + break; + } + +out: + if (mbuf) + kfree(mbuf); + + return err; +} static int __init init_dvbdev(void) { int retval; + dev_t dev = MKDEV(DVB_MAJOR, 0); + + if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) { + printk("dvb-core: unable to get major %d\n", DVB_MAJOR); + return retval; + } + + cdev_init(&dvb_device_cdev, &dvb_device_fops); + if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) { + printk("dvb-core: unable to get major %d\n", DVB_MAJOR); + goto error; + } + devfs_mk_dir("dvb"); - retval = register_chrdev(DVB_MAJOR,"DVB", &dvb_device_fops); - if (retval) - printk("video_dev: unable to get major %d\n", DVB_MAJOR); + dvb_class = class_simple_create(THIS_MODULE, "dvb"); + if (IS_ERR(dvb_class)) { + retval = PTR_ERR(dvb_class); + goto error; + } + return 0; +error: + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(dev, MAX_DVB_MINORS); return retval; } static void __exit exit_dvbdev(void) { - unregister_chrdev(DVB_MAJOR, "DVB"); devfs_remove("dvb"); + class_simple_destroy(dvb_class); + cdev_del(&dvb_device_cdev); + unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS); } module_init(init_dvbdev); @@ -336,6 +452,3 @@ MODULE_DESCRIPTION("DVB Core Driver"); MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler"); MODULE_LICENSE("GPL"); -MODULE_PARM(dvbdev_debug,"i"); -MODULE_PARM_DESC(dvbdev_debug, "enable verbose debug messages"); -