V4L/DVB (13103): create a standard method for dvb adapter drivers to override fronten...
authorMichael Krufky <mkrufky@kernellabs.com>
Sat, 23 May 2009 21:00:59 +0000 (18:00 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 5 Dec 2009 20:40:21 +0000 (18:40 -0200)
Signed-off-by: Michael Krufky <mkrufky@kernellabs.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvbdev.h
drivers/media/video/cx23885/cx23885-dvb.c
drivers/media/video/cx88/cx88-dvb.c
drivers/media/video/saa7134/saa7134-dvb.c
drivers/media/video/videobuf-dvb.c
include/media/videobuf-dvb.h

index 98082416aa52aec23e14ec242a6416f02ae443c3..e9ec8e9110562ead1959755d19e9a29209af695f 100644 (file)
@@ -1712,7 +1712,18 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int err = -EOPNOTSUPP;
+       int cb_err, err = -EOPNOTSUPP;
+
+       if (fe->dvb->fe_ioctl_override) {
+               cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
+                                                   DVB_FE_IOCTL_PRE);
+               if (cb_err < 0)
+                       return cb_err;
+               if (cb_err > 0)
+                       return 0;
+               /* fe_ioctl_override returning 0 allows
+                * dvb-core to continue handling the ioctl */
+       }
 
        switch (cmd) {
        case FE_GET_INFO: {
@@ -1978,6 +1989,13 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
                break;
        };
 
+       if (fe->dvb->fe_ioctl_override) {
+               cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
+                                                   DVB_FE_IOCTL_POST);
+               if (cb_err < 0)
+                       return cb_err;
+       }
+
        return err;
 }
 
index 01fc704847434fb1faa08e61c09053e053ecaff3..f7b499d4a3c0a3d3adf126a7b3e27097f70863fb 100644 (file)
@@ -54,6 +54,8 @@
        module_param_array(adapter_nr, short, NULL, 0444); \
        MODULE_PARM_DESC(adapter_nr, "DVB adapter numbers")
 
+struct dvb_frontend;
+
 struct dvb_adapter {
        int num;
        struct list_head list_head;
@@ -69,6 +71,32 @@ struct dvb_adapter {
        int mfe_shared;                 /* indicates mutually exclusive frontends */
        struct dvb_device *mfe_dvbdev;  /* frontend device in use */
        struct mutex mfe_lock;          /* access lock for thread creation */
+
+       /* Allow the adapter/bridge driver to perform an action before and/or
+        * after the core handles an ioctl:
+        *
+        * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled.
+        * DVB_FE_IOCTL_POST indicates that the ioctl has been handled.
+        *
+        * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg:
+        *
+        * return 0 to allow dvb-core to handle the ioctl.
+        * return a positive int to prevent dvb-core from handling the ioctl,
+        *      and exit without error.
+        * return a negative int to prevent dvb-core from handling the ioctl,
+        *      and return that value as an error.
+        *
+        * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg:
+        *
+        * return 0 to allow the dvb_frontend ioctl handler to exit normally.
+        * return a negative int to cause the dvb_frontend ioctl handler to
+        *      return that value as an error.
+        */
+#define DVB_FE_IOCTL_PRE 0
+#define DVB_FE_IOCTL_POST 1
+       int (*fe_ioctl_override)(struct dvb_frontend *fe,
+                                unsigned int cmd, void *parg,
+                                unsigned int stage);
 };
 
 
index 45e13ee66dc7088ea19f020567b4c1b0066fff05..0a03e02b119b85979d262d259575acf0b2b34297 100644 (file)
@@ -904,7 +904,7 @@ static int dvb_register(struct cx23885_tsport *port)
 
        /* register everything */
        ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
-               &dev->pci->dev, adapter_nr, 0);
+                                       &dev->pci->dev, adapter_nr, 0, NULL);
 
        /* init CI & MAC */
        switch (dev->board) {
index 518bcfe18bcbf9313201d551d6be5e0cfeb7402c..d9e402b25b56a800840350eb8d5138b807d3c101 100644 (file)
@@ -1174,7 +1174,7 @@ static int dvb_register(struct cx8802_dev *dev)
 
        /* register everything */
        return videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-               &dev->pci->dev, adapter_nr, mfe_shared);
+                                        &dev->pci->dev, adapter_nr, mfe_shared, NULL);
 
 frontend_detach:
        core->gate_ctrl = NULL;
index 058b56bf67177372156a787bd92c8282671b75e0..96d3668f4691ae369d6407108fc683956c1d9ecc 100644 (file)
@@ -1574,7 +1574,7 @@ static int dvb_init(struct saa7134_dev *dev)
 
        /* register everything else */
        ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-               &dev->pci->dev, adapter_nr, 0);
+                                       &dev->pci->dev, adapter_nr, 0, NULL);
 
        /* this sequence is necessary to make the tda1004x load its firmware
         * and to enter analog mode of hybrid boards
index 0e7dcba8e4ae08aa902a0a4c06213630d077bb76..a56cf0d3a6d618134d70f046059df84919f3b1d0 100644 (file)
@@ -139,7 +139,9 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
                          struct device *device,
                          char *adapter_name,
                          short *adapter_nr,
-                         int mfe_shared)
+                         int mfe_shared,
+                         int (*fe_ioctl_override)(struct dvb_frontend *,
+                                       unsigned int, void *, unsigned int))
 {
        int result;
 
@@ -154,6 +156,7 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
        }
        fe->adapter.priv = adapter_priv;
        fe->adapter.mfe_shared = mfe_shared;
+       fe->adapter.fe_ioctl_override = fe_ioctl_override;
 
        return result;
 }
@@ -253,7 +256,9 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
                          void *adapter_priv,
                          struct device *device,
                          short *adapter_nr,
-                         int mfe_shared)
+                         int mfe_shared,
+                         int (*fe_ioctl_override)(struct dvb_frontend *,
+                                       unsigned int, void *, unsigned int))
 {
        struct list_head *list, *q;
        struct videobuf_dvb_frontend *fe;
@@ -267,7 +272,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
 
        /* Bring up the adapter */
        res = videobuf_dvb_register_adapter(f, module, adapter_priv, device,
-               fe->dvb.name, adapter_nr, mfe_shared);
+               fe->dvb.name, adapter_nr, mfe_shared, fe_ioctl_override);
        if (res < 0) {
                printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
                return res;
index 6ba4f1271d237f7af4c5166040992f7ad8a96200..07cf4b9d0a656e56c28b3e6e16c4d6abc14f1b0a 100644 (file)
@@ -42,7 +42,9 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
                          void *adapter_priv,
                          struct device *device,
                          short *adapter_nr,
-                         int mfe_shared);
+                         int mfe_shared,
+                         int (*fe_ioctl_override)(struct dvb_frontend *,
+                                       unsigned int, void *, unsigned int));
 
 void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f);