linux/drivers/media/dvb-core/dvbdev.c
<<
>>
Prefs
   1/*
   2 * dvbdev.c
   3 *
   4 * Copyright (C) 2000 Ralph  Metzler <ralph@convergence.de>
   5 *                  & Marcus Metzler <marcus@convergence.de>
   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
  37static DEFINE_MUTEX(dvbdev_mutex);
  38static int dvbdev_debug;
  39
  40module_param(dvbdev_debug, int, 0644);
  41MODULE_PARM_DESC(dvbdev_debug, "Turn on/off device debugging (default:off).");
  42
  43#define dprintk if (dvbdev_debug) printk
  44
  45static LIST_HEAD(dvb_adapter_list);
  46static DEFINE_MUTEX(dvbdev_register_lock);
  47
  48static 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
  62static struct class *dvb_class;
  63
  64static struct dvb_device *dvb_minors[MAX_DVB_MINORS];
  65static DECLARE_RWSEM(minor_rwsem);
  66
  67static 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 *new_fops;
  78
  79                new_fops = fops_get(dvbdev->fops);
  80                if (!new_fops)
  81                        goto fail;
  82                file->private_data = dvbdev;
  83                replace_fops(file, new_fops);
  84                if (file->f_op->open)
  85                        err = file->f_op->open(inode,file);
  86                up_read(&minor_rwsem);
  87                mutex_unlock(&dvbdev_mutex);
  88                return err;
  89        }
  90fail:
  91        up_read(&minor_rwsem);
  92        mutex_unlock(&dvbdev_mutex);
  93        return -ENODEV;
  94}
  95
  96
  97static const struct file_operations dvb_device_fops =
  98{
  99        .owner =        THIS_MODULE,
 100        .open =         dvb_device_open,
 101        .llseek =       noop_llseek,
 102};
 103
 104static struct cdev dvb_device_cdev;
 105
 106int dvb_generic_open(struct inode *inode, struct file *file)
 107{
 108        struct dvb_device *dvbdev = file->private_data;
 109
 110        if (!dvbdev)
 111                return -ENODEV;
 112
 113        if (!dvbdev->users)
 114                return -EBUSY;
 115
 116        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 117                if (!dvbdev->readers)
 118                        return -EBUSY;
 119                dvbdev->readers--;
 120        } else {
 121                if (!dvbdev->writers)
 122                        return -EBUSY;
 123                dvbdev->writers--;
 124        }
 125
 126        dvbdev->users--;
 127        return 0;
 128}
 129EXPORT_SYMBOL(dvb_generic_open);
 130
 131
 132int dvb_generic_release(struct inode *inode, struct file *file)
 133{
 134        struct dvb_device *dvbdev = file->private_data;
 135
 136        if (!dvbdev)
 137                return -ENODEV;
 138
 139        if ((file->f_flags & O_ACCMODE) == O_RDONLY) {
 140                dvbdev->readers++;
 141        } else {
 142                dvbdev->writers++;
 143        }
 144
 145        dvbdev->users++;
 146        return 0;
 147}
 148EXPORT_SYMBOL(dvb_generic_release);
 149
 150
 151long dvb_generic_ioctl(struct file *file,
 152                       unsigned int cmd, unsigned long arg)
 153{
 154        struct dvb_device *dvbdev = file->private_data;
 155
 156        if (!dvbdev)
 157                return -ENODEV;
 158
 159        if (!dvbdev->kernel_ioctl)
 160                return -EINVAL;
 161
 162        return dvb_usercopy(file, cmd, arg, dvbdev->kernel_ioctl);
 163}
 164EXPORT_SYMBOL(dvb_generic_ioctl);
 165
 166
 167static int dvbdev_get_free_id (struct dvb_adapter *adap, int type)
 168{
 169        u32 id = 0;
 170
 171        while (id < DVB_MAX_IDS) {
 172                struct dvb_device *dev;
 173                list_for_each_entry(dev, &adap->device_list, list_head)
 174                        if (dev->type == type && dev->id == id)
 175                                goto skip;
 176                return id;
 177skip:
 178                id++;
 179        }
 180        return -ENFILE;
 181}
 182
 183static void dvb_register_media_device(struct dvb_device *dvbdev,
 184                                      int type, int minor)
 185{
 186#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 187        int ret = 0, npads;
 188
 189        if (!dvbdev->adapter->mdev)
 190                return;
 191
 192        dvbdev->entity = kzalloc(sizeof(*dvbdev->entity), GFP_KERNEL);
 193        if (!dvbdev->entity)
 194                return;
 195
 196        dvbdev->entity->info.dev.major = DVB_MAJOR;
 197        dvbdev->entity->info.dev.minor = minor;
 198        dvbdev->entity->name = dvbdev->name;
 199
 200        switch (type) {
 201        case DVB_DEVICE_CA:
 202        case DVB_DEVICE_DEMUX:
 203        case DVB_DEVICE_FRONTEND:
 204                npads = 2;
 205                break;
 206        case DVB_DEVICE_NET:
 207                npads = 0;
 208                break;
 209        default:
 210                npads = 1;
 211        }
 212
 213        if (npads) {
 214                dvbdev->pads = kcalloc(npads, sizeof(*dvbdev->pads),
 215                                       GFP_KERNEL);
 216                if (!dvbdev->pads) {
 217                        kfree(dvbdev->entity);
 218                        return;
 219                }
 220        }
 221
 222        switch (type) {
 223        case DVB_DEVICE_FRONTEND:
 224                dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_FE;
 225                dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 226                dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 227                break;
 228        case DVB_DEVICE_DEMUX:
 229                dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DEMUX;
 230                dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 231                dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 232                break;
 233        case DVB_DEVICE_DVR:
 234                dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_DVR;
 235                dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 236                break;
 237        case DVB_DEVICE_CA:
 238                dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_CA;
 239                dvbdev->pads[0].flags = MEDIA_PAD_FL_SINK;
 240                dvbdev->pads[1].flags = MEDIA_PAD_FL_SOURCE;
 241                break;
 242        case DVB_DEVICE_NET:
 243                dvbdev->entity->type = MEDIA_ENT_T_DEVNODE_DVB_NET;
 244                break;
 245        default:
 246                kfree(dvbdev->entity);
 247                dvbdev->entity = NULL;
 248                return;
 249        }
 250
 251        if (npads)
 252                ret = media_entity_init(dvbdev->entity, npads, dvbdev->pads, 0);
 253        if (!ret)
 254                ret = media_device_register_entity(dvbdev->adapter->mdev,
 255                                                   dvbdev->entity);
 256        if (ret < 0) {
 257                printk(KERN_ERR
 258                        "%s: media_device_register_entity failed for %s\n",
 259                        __func__, dvbdev->entity->name);
 260                kfree(dvbdev->pads);
 261                kfree(dvbdev->entity);
 262                dvbdev->entity = NULL;
 263                return;
 264        }
 265
 266        printk(KERN_DEBUG "%s: media device '%s' registered.\n",
 267                __func__, dvbdev->entity->name);
 268#endif
 269}
 270
 271int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev,
 272                        const struct dvb_device *template, void *priv, int type)
 273{
 274        struct dvb_device *dvbdev;
 275        struct file_operations *dvbdevfops;
 276        struct device *clsdev;
 277        int minor;
 278        int id;
 279
 280        mutex_lock(&dvbdev_register_lock);
 281
 282        if ((id = dvbdev_get_free_id (adap, type)) < 0){
 283                mutex_unlock(&dvbdev_register_lock);
 284                *pdvbdev = NULL;
 285                printk(KERN_ERR "%s: couldn't find free device id\n", __func__);
 286                return -ENFILE;
 287        }
 288
 289        *pdvbdev = dvbdev = kmalloc(sizeof(struct dvb_device), GFP_KERNEL);
 290
 291        if (!dvbdev){
 292                mutex_unlock(&dvbdev_register_lock);
 293                return -ENOMEM;
 294        }
 295
 296        dvbdevfops = kzalloc(sizeof(struct file_operations), GFP_KERNEL);
 297
 298        if (!dvbdevfops){
 299                kfree (dvbdev);
 300                mutex_unlock(&dvbdev_register_lock);
 301                return -ENOMEM;
 302        }
 303
 304        memcpy(dvbdev, template, sizeof(struct dvb_device));
 305        dvbdev->type = type;
 306        dvbdev->id = id;
 307        dvbdev->adapter = adap;
 308        dvbdev->priv = priv;
 309        dvbdev->fops = dvbdevfops;
 310        init_waitqueue_head (&dvbdev->wait_queue);
 311
 312        memcpy(dvbdevfops, template->fops, sizeof(struct file_operations));
 313        dvbdevfops->owner = adap->module;
 314
 315        list_add_tail (&dvbdev->list_head, &adap->device_list);
 316
 317        down_write(&minor_rwsem);
 318#ifdef CONFIG_DVB_DYNAMIC_MINORS
 319        for (minor = 0; minor < MAX_DVB_MINORS; minor++)
 320                if (dvb_minors[minor] == NULL)
 321                        break;
 322
 323        if (minor == MAX_DVB_MINORS) {
 324                kfree(dvbdevfops);
 325                kfree(dvbdev);
 326                up_write(&minor_rwsem);
 327                mutex_unlock(&dvbdev_register_lock);
 328                return -EINVAL;
 329        }
 330#else
 331        minor = nums2minor(adap->num, type, id);
 332#endif
 333
 334        dvbdev->minor = minor;
 335        dvb_minors[minor] = dvbdev;
 336        up_write(&minor_rwsem);
 337
 338        mutex_unlock(&dvbdev_register_lock);
 339
 340        clsdev = device_create(dvb_class, adap->device,
 341                               MKDEV(DVB_MAJOR, minor),
 342                               dvbdev, "dvb%d.%s%d", adap->num, dnames[type], id);
 343        if (IS_ERR(clsdev)) {
 344                printk(KERN_ERR "%s: failed to create device dvb%d.%s%d (%ld)\n",
 345                       __func__, adap->num, dnames[type], id, PTR_ERR(clsdev));
 346                return PTR_ERR(clsdev);
 347        }
 348        dprintk(KERN_DEBUG "DVB: register adapter%d/%s%d @ minor: %i (0x%02x)\n",
 349                adap->num, dnames[type], id, minor, minor);
 350
 351        dvb_register_media_device(dvbdev, type, minor);
 352
 353        return 0;
 354}
 355EXPORT_SYMBOL(dvb_register_device);
 356
 357
 358void dvb_unregister_device(struct dvb_device *dvbdev)
 359{
 360        if (!dvbdev)
 361                return;
 362
 363        down_write(&minor_rwsem);
 364        dvb_minors[dvbdev->minor] = NULL;
 365        up_write(&minor_rwsem);
 366
 367        device_destroy(dvb_class, MKDEV(DVB_MAJOR, dvbdev->minor));
 368
 369#if defined(CONFIG_MEDIA_CONTROLLER_DVB)
 370        if (dvbdev->entity) {
 371                media_device_unregister_entity(dvbdev->entity);
 372                kfree(dvbdev->entity);
 373                kfree(dvbdev->pads);
 374        }
 375#endif
 376
 377        list_del (&dvbdev->list_head);
 378        kfree (dvbdev->fops);
 379        kfree (dvbdev);
 380}
 381EXPORT_SYMBOL(dvb_unregister_device);
 382
 383
 384#ifdef CONFIG_MEDIA_CONTROLLER_DVB
 385void dvb_create_media_graph(struct dvb_adapter *adap)
 386{
 387        struct media_device *mdev = adap->mdev;
 388        struct media_entity *entity, *tuner = NULL, *fe = NULL;
 389        struct media_entity *demux = NULL, *dvr = NULL, *ca = NULL;
 390
 391        if (!mdev)
 392                return;
 393
 394        media_device_for_each_entity(entity, mdev) {
 395                switch (entity->type) {
 396                case MEDIA_ENT_T_V4L2_SUBDEV_TUNER:
 397                        tuner = entity;
 398                        break;
 399                case MEDIA_ENT_T_DEVNODE_DVB_FE:
 400                        fe = entity;
 401                        break;
 402                case MEDIA_ENT_T_DEVNODE_DVB_DEMUX:
 403                        demux = entity;
 404                        break;
 405                case MEDIA_ENT_T_DEVNODE_DVB_DVR:
 406                        dvr = entity;
 407                        break;
 408                case MEDIA_ENT_T_DEVNODE_DVB_CA:
 409                        ca = entity;
 410                        break;
 411                }
 412        }
 413
 414        if (tuner && fe)
 415                media_entity_create_link(tuner, 0, fe, 0, 0);
 416
 417        if (fe && demux)
 418                media_entity_create_link(fe, 1, demux, 0, MEDIA_LNK_FL_ENABLED);
 419
 420        if (demux && dvr)
 421                media_entity_create_link(demux, 1, dvr, 0, MEDIA_LNK_FL_ENABLED);
 422
 423        if (demux && ca)
 424                media_entity_create_link(demux, 1, ca, 0, MEDIA_LNK_FL_ENABLED);
 425}
 426EXPORT_SYMBOL_GPL(dvb_create_media_graph);
 427#endif
 428
 429static int dvbdev_check_free_adapter_num(int num)
 430{
 431        struct list_head *entry;
 432        list_for_each(entry, &dvb_adapter_list) {
 433                struct dvb_adapter *adap;
 434                adap = list_entry(entry, struct dvb_adapter, list_head);
 435                if (adap->num == num)
 436                        return 0;
 437        }
 438        return 1;
 439}
 440
 441static int dvbdev_get_free_adapter_num (void)
 442{
 443        int num = 0;
 444
 445        while (num < DVB_MAX_ADAPTERS) {
 446                if (dvbdev_check_free_adapter_num(num))
 447                        return num;
 448                num++;
 449        }
 450
 451        return -ENFILE;
 452}
 453
 454
 455int dvb_register_adapter(struct dvb_adapter *adap, const char *name,
 456                         struct module *module, struct device *device,
 457                         short *adapter_nums)
 458{
 459        int i, num;
 460
 461        mutex_lock(&dvbdev_register_lock);
 462
 463        for (i = 0; i < DVB_MAX_ADAPTERS; ++i) {
 464                num = adapter_nums[i];
 465                if (num >= 0  &&  num < DVB_MAX_ADAPTERS) {
 466                /* use the one the driver asked for */
 467                        if (dvbdev_check_free_adapter_num(num))
 468                                break;
 469                } else {
 470                        num = dvbdev_get_free_adapter_num();
 471                        break;
 472                }
 473                num = -1;
 474        }
 475
 476        if (num < 0) {
 477                mutex_unlock(&dvbdev_register_lock);
 478                return -ENFILE;
 479        }
 480
 481        memset (adap, 0, sizeof(struct dvb_adapter));
 482        INIT_LIST_HEAD (&adap->device_list);
 483
 484        printk(KERN_INFO "DVB: registering new adapter (%s)\n", name);
 485
 486        adap->num = num;
 487        adap->name = name;
 488        adap->module = module;
 489        adap->device = device;
 490        adap->mfe_shared = 0;
 491        adap->mfe_dvbdev = NULL;
 492        mutex_init (&adap->mfe_lock);
 493
 494        list_add_tail (&adap->list_head, &dvb_adapter_list);
 495
 496        mutex_unlock(&dvbdev_register_lock);
 497
 498        return num;
 499}
 500EXPORT_SYMBOL(dvb_register_adapter);
 501
 502
 503int dvb_unregister_adapter(struct dvb_adapter *adap)
 504{
 505        mutex_lock(&dvbdev_register_lock);
 506        list_del (&adap->list_head);
 507        mutex_unlock(&dvbdev_register_lock);
 508        return 0;
 509}
 510EXPORT_SYMBOL(dvb_unregister_adapter);
 511
 512/* if the miracle happens and "generic_usercopy()" is included into
 513   the kernel, then this can vanish. please don't make the mistake and
 514   define this as video_usercopy(). this will introduce a dependecy
 515   to the v4l "videodev.o" module, which is unnecessary for some
 516   cards (ie. the budget dvb-cards don't need the v4l module...) */
 517int dvb_usercopy(struct file *file,
 518                     unsigned int cmd, unsigned long arg,
 519                     int (*func)(struct file *file,
 520                     unsigned int cmd, void *arg))
 521{
 522        char    sbuf[128];
 523        void    *mbuf = NULL;
 524        void    *parg = NULL;
 525        int     err  = -EINVAL;
 526
 527        /*  Copy arguments into temp kernel buffer  */
 528        switch (_IOC_DIR(cmd)) {
 529        case _IOC_NONE:
 530                /*
 531                 * For this command, the pointer is actually an integer
 532                 * argument.
 533                 */
 534                parg = (void *) arg;
 535                break;
 536        case _IOC_READ: /* some v4l ioctls are marked wrong ... */
 537        case _IOC_WRITE:
 538        case (_IOC_WRITE | _IOC_READ):
 539                if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
 540                        parg = sbuf;
 541                } else {
 542                        /* too big to allocate from stack */
 543                        mbuf = kmalloc(_IOC_SIZE(cmd),GFP_KERNEL);
 544                        if (NULL == mbuf)
 545                                return -ENOMEM;
 546                        parg = mbuf;
 547                }
 548
 549                err = -EFAULT;
 550                if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
 551                        goto out;
 552                break;
 553        }
 554
 555        /* call driver */
 556        if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
 557                err = -ENOTTY;
 558
 559        if (err < 0)
 560                goto out;
 561
 562        /*  Copy results into user buffer  */
 563        switch (_IOC_DIR(cmd))
 564        {
 565        case _IOC_READ:
 566        case (_IOC_WRITE | _IOC_READ):
 567                if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
 568                        err = -EFAULT;
 569                break;
 570        }
 571
 572out:
 573        kfree(mbuf);
 574        return err;
 575}
 576
 577static int dvb_uevent(struct device *dev, struct kobj_uevent_env *env)
 578{
 579        struct dvb_device *dvbdev = dev_get_drvdata(dev);
 580
 581        add_uevent_var(env, "DVB_ADAPTER_NUM=%d", dvbdev->adapter->num);
 582        add_uevent_var(env, "DVB_DEVICE_TYPE=%s", dnames[dvbdev->type]);
 583        add_uevent_var(env, "DVB_DEVICE_NUM=%d", dvbdev->id);
 584        return 0;
 585}
 586
 587static char *dvb_devnode(struct device *dev, umode_t *mode)
 588{
 589        struct dvb_device *dvbdev = dev_get_drvdata(dev);
 590
 591        return kasprintf(GFP_KERNEL, "dvb/adapter%d/%s%d",
 592                dvbdev->adapter->num, dnames[dvbdev->type], dvbdev->id);
 593}
 594
 595
 596static int __init init_dvbdev(void)
 597{
 598        int retval;
 599        dev_t dev = MKDEV(DVB_MAJOR, 0);
 600
 601        if ((retval = register_chrdev_region(dev, MAX_DVB_MINORS, "DVB")) != 0) {
 602                printk(KERN_ERR "dvb-core: unable to get major %d\n", DVB_MAJOR);
 603                return retval;
 604        }
 605
 606        cdev_init(&dvb_device_cdev, &dvb_device_fops);
 607        if ((retval = cdev_add(&dvb_device_cdev, dev, MAX_DVB_MINORS)) != 0) {
 608                printk(KERN_ERR "dvb-core: unable register character device\n");
 609                goto error;
 610        }
 611
 612        dvb_class = class_create(THIS_MODULE, "dvb");
 613        if (IS_ERR(dvb_class)) {
 614                retval = PTR_ERR(dvb_class);
 615                goto error;
 616        }
 617        dvb_class->dev_uevent = dvb_uevent;
 618        dvb_class->devnode = dvb_devnode;
 619        return 0;
 620
 621error:
 622        cdev_del(&dvb_device_cdev);
 623        unregister_chrdev_region(dev, MAX_DVB_MINORS);
 624        return retval;
 625}
 626
 627
 628static void __exit exit_dvbdev(void)
 629{
 630        class_destroy(dvb_class);
 631        cdev_del(&dvb_device_cdev);
 632        unregister_chrdev_region(MKDEV(DVB_MAJOR, 0), MAX_DVB_MINORS);
 633}
 634
 635subsys_initcall(init_dvbdev);
 636module_exit(exit_dvbdev);
 637
 638MODULE_DESCRIPTION("DVB Core Driver");
 639MODULE_AUTHOR("Marcus Metzler, Ralph Metzler, Holger Waechtler");
 640MODULE_LICENSE("GPL");
 641