V4L/DVB (8996): S2API: typedefs replaced, _SEQ_'s removed, fixed 16 command arrays...
Steven Toth [Thu, 11 Sep 2008 13:23:01 +0000 (10:23 -0300)]
After discussion the following changes were made:
1. Removed the typedefs in frontend.h, use structures.
2. In the frontend.h, remove the 16 command limit on the API and
   switch to a flexible variable length API. For practical reasons
   a #define limits this to 64, this should be discussed.
3. Changed dvb-core ioctl handing to deal with variable sequences
   of commands.

tune-v0.0.3.c is required to use this API, it contains the interface changes.

Signed-off-by: Steven Toth <stoth@linuxtv.org>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>

drivers/media/dvb/dvb-core/dvb_frontend.c
drivers/media/dvb/dvb-core/dvb_frontend.h
drivers/media/dvb/frontends/cx24116.c
include/linux/dvb/frontend.h

index 9c47615..763da96 100644 (file)
@@ -756,29 +756,14 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
 }
 
 struct dtv_cmds_h dtv_cmds[] = {
-       [DTV_SEQ_UNDEFINED] = {
-               .name   = "DTV_SEQ_UNDEFINED",
-               .cmd    = DTV_SEQ_UNDEFINED,
+       [DTV_TUNE] = {
+               .name   = "DTV_TUNE",
+               .cmd    = DTV_TUNE,
                .set    = 1,
        },
-       [DTV_SEQ_START] = {
-               .name   = "DTV_SEQ_START",
-               .cmd    = DTV_SEQ_START,
-               .set    = 1,
-       },
-       [DTV_SEQ_CONTINUE] = {
-               .name   = "DTV_SEQ_CONTINUE",
-               .cmd    = DTV_SEQ_CONTINUE,
-               .set    = 1,
-       },
-       [DTV_SEQ_COMPLETE] = {
-               .name   = "DTV_SEQ_COMPLETE",
-               .cmd    = DTV_SEQ_COMPLETE,
-               .set    = 1,
-       },
-       [DTV_SEQ_TERMINATE] = {
-               .name   = "DTV_SEQ_TERMINATE",
-               .cmd    = DTV_SEQ_TERMINATE,
+       [DTV_CLEAR] = {
+               .name   = "DTV_CLEAR",
+               .cmd    = DTV_CLEAR,
                .set    = 1,
        },
 
@@ -974,7 +959,7 @@ struct dtv_cmds_h dtv_cmds[] = {
        },
 };
 
-void dtv_property_dump(dtv_property_t *tvp)
+void dtv_property_dump(struct dtv_property *tvp)
 {
        int i;
 
@@ -1044,6 +1029,7 @@ int dtv_property_cache_submit(struct dvb_frontend *fe)
 
        /* For legacy delivery systems we don't need the delivery_system to be specified */
        if(is_legacy_delivery_system(c->delivery_system)) {
+               printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation);
                switch(c->modulation) {
                case QPSK:
                        printk("%s() Preparing QPSK req\n", __FUNCTION__);
@@ -1161,7 +1147,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
 static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
                        unsigned int cmd, void *parg);
 
-int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp,
+int dtv_property_process(struct dvb_frontend *fe, struct dtv_property *tvp,
        struct inode *inode, struct file *file)
 {
        int r = 0;
@@ -1170,23 +1156,22 @@ int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp,
        dtv_property_dump(tvp);
 
        switch(tvp->cmd) {
-       case DTV_SEQ_START:
-       case DTV_SEQ_TERMINATE:
+       case DTV_CLEAR:
                /* Reset a cache of data specific to the frontend here. This does
                 * not effect hardware.
                 */
                printk("%s() Flushing property cache\n", __FUNCTION__);
                memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties));
-               fe->dtv_property_cache.state = DTV_SEQ_START;
+               fe->dtv_property_cache.state = tvp->cmd;
                fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
                break;
-       case DTV_SEQ_COMPLETE:
+       case DTV_TUNE:
                /* interpret the cache of data, build either a traditional frontend
                 * tunerequest and submit it to a subset of the ioctl handler,
                 * or, call a new undefined method on the frontend to deal with
                 * all new tune requests.
                 */
-               fe->dtv_property_cache.state = DTV_SEQ_COMPLETE;
+               fe->dtv_property_cache.state = tvp->cmd;
                printk("%s() Finalised property cache\n", __FUNCTION__);
                r |= dtv_property_cache_submit(fe);
                r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND,
@@ -1344,30 +1329,48 @@ static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
        struct dvb_device *dvbdev = file->private_data;
        struct dvb_frontend *fe = dvbdev->priv;
        int err = -EOPNOTSUPP;
-       dtv_property_t *tvp;
+
+       struct dtv_properties *tvps = NULL;
+       struct dtv_property *tvp = NULL;
+       int i;
 
        dprintk("%s\n", __func__);
 
        if(cmd == FE_SET_PROPERTY) {
                printk("%s() FE_SET_PROPERTY\n", __FUNCTION__);
 
-               /* TODO: basic property validation here */
+               tvps = (struct dtv_properties __user *)parg;
 
-               /* TODO: ioctl userdata out of range check here */
-               tvp = parg;
-               while(tvp->cmd != DTV_SEQ_UNDEFINED) {
-                       dtv_property_process(fe, tvp, inode, file);
-                       if( (tvp->cmd == DTV_SEQ_TERMINATE) || (tvp->cmd == DTV_SEQ_COMPLETE) )
-                               break;
-                       tvp++;
+               printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
+               printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
+
+               /* Put an arbitrary limit on the number of messages that can
+                * be sent at once */
+               if (tvps->num > DTV_IOCTL_MAX_MSGS)
+                       return -EINVAL;
+
+               tvp = (struct dtv_property *) kmalloc(tvps->num *
+                       sizeof(struct dtv_property), GFP_KERNEL);
+               if (!tvp) {
+                       err = -ENOMEM;
+                       goto out;
                }
 
-               if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) {
+               if (copy_from_user(tvp, tvps->props, tvps->num * sizeof(struct dtv_property))) {
+                       err = -EFAULT;
+                       goto out;
+               }
+
+               for (i = 0; i < tvps->num; i++)
+                       dtv_property_process(fe, tvp + i, inode, file);
+
+               if(fe->dtv_property_cache.state == DTV_TUNE) {
                        printk("%s() Property cache is full, tuning\n", __FUNCTION__);
                }
                err = 0;
        }
-
+out:
+       kfree(tvp);
        return err;
 }
 
@@ -1545,7 +1548,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
        case FE_SET_FRONTEND: {
                struct dvb_frontend_tune_settings fetunesettings;
 
-               if(fe->dtv_property_cache.state == DTV_SEQ_COMPLETE) {
+               if(fe->dtv_property_cache.state == DTV_TUNE) {
                        if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
                                err = -EINVAL;
                                break;
index f376f28..85d3020 100644 (file)
@@ -170,8 +170,8 @@ struct dvb_frontend_ops {
        struct dvb_tuner_ops tuner_ops;
        struct analog_demod_ops analog_ops;
 
-       int (*set_property)(struct dvb_frontend* fe, dtv_property_t* tvp);
-       int (*get_property)(struct dvb_frontend* fe, dtv_property_t* tvp);
+       int (*set_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
+       int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
        int (*set_params)(struct dvb_frontend* fe);
 };
 
index f150fa2..9f93930 100644 (file)
@@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe)
        return cx24116_diseqc_init(fe);
 }
 
-static int cx24116_set_property(struct dvb_frontend *fe, dtv_property_t* tvp)
+static int cx24116_set_property(struct dvb_frontend *fe, struct dtv_property* tvp)
 {
        dprintk("%s(..)\n", __func__);
        return 0;
index aeace74..f667bf3 100644 (file)
@@ -251,11 +251,8 @@ struct dvb_frontend_event {
  * binary compatability.
  */
 typedef enum dtv_cmd_types {
-       DTV_SEQ_UNDEFINED,
-       DTV_SEQ_START,
-       DTV_SEQ_CONTINUE,
-       DTV_SEQ_COMPLETE,
-       DTV_SEQ_TERMINATE,
+       DTV_TUNE,
+       DTV_CLEAR,
 
        DTV_SET_FREQUENCY,
        DTV_SET_MODULATION,
@@ -348,22 +345,32 @@ struct dtv_cmds_h {
        __u32   reserved:30;    /* Align */
 };
 
-typedef struct {
+struct dtv_property {
        __u32 cmd;
+       __u32 reserved[3];
        union {
+               __s32 valuemin;
+               __s32 valuemax;
                __u32 data;
                struct {
                        __u8 data[32];
                        __u32 len;
+                       __u32 reserved1[3];
+                       void *reserved2;
                } buffer;
        } u;
-} dtv_property_t;
+} __attribute__ ((packed));
 
 /* No more than 16 properties during any given ioctl */
-typedef dtv_property_t dtv_properties_t[16];
+struct dtv_properties {
+       __u32 num;
+       struct dtv_property *props;
+};
+
+#define DTV_IOCTL_MAX_MSGS 64
 
-#define FE_SET_PROPERTY                   _IOW('o', 82, dtv_properties_t)
-#define FE_GET_PROPERTY                   _IOR('o', 83, dtv_properties_t)
+#define FE_SET_PROPERTY                   _IOW('o', 82, struct dtv_properties)
+#define FE_GET_PROPERTY                   _IOR('o', 83, struct dtv_properties)
 
 
 /**