Commit e7fee0f3 authored by Steven Toth's avatar Steven Toth Committed by Mauro Carvalho Chehab

V4L/DVB (8996): S2API: typedefs replaced, _SEQ_'s removed, fixed 16 command arrays replaced

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: default avatarSteven Toth <stoth@linuxtv.org>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 56f0680a
...@@ -756,29 +756,14 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe, ...@@ -756,29 +756,14 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe,
} }
struct dtv_cmds_h dtv_cmds[] = { struct dtv_cmds_h dtv_cmds[] = {
[DTV_SEQ_UNDEFINED] = { [DTV_TUNE] = {
.name = "DTV_SEQ_UNDEFINED", .name = "DTV_TUNE",
.cmd = DTV_SEQ_UNDEFINED, .cmd = DTV_TUNE,
.set = 1, .set = 1,
}, },
[DTV_SEQ_START] = { [DTV_CLEAR] = {
.name = "DTV_SEQ_START", .name = "DTV_CLEAR",
.cmd = DTV_SEQ_START, .cmd = DTV_CLEAR,
.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,
.set = 1, .set = 1,
}, },
...@@ -974,7 +959,7 @@ struct dtv_cmds_h dtv_cmds[] = { ...@@ -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; int i;
...@@ -1044,6 +1029,7 @@ int dtv_property_cache_submit(struct dvb_frontend *fe) ...@@ -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 */ /* For legacy delivery systems we don't need the delivery_system to be specified */
if(is_legacy_delivery_system(c->delivery_system)) { if(is_legacy_delivery_system(c->delivery_system)) {
printk("%s() legacy, modulation = %d\n", __FUNCTION__, c->modulation);
switch(c->modulation) { switch(c->modulation) {
case QPSK: case QPSK:
printk("%s() Preparing QPSK req\n", __FUNCTION__); printk("%s() Preparing QPSK req\n", __FUNCTION__);
...@@ -1161,7 +1147,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, ...@@ -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, static int dvb_frontend_ioctl_properties(struct inode *inode, struct file *file,
unsigned int cmd, void *parg); 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) struct inode *inode, struct file *file)
{ {
int r = 0; int r = 0;
...@@ -1170,23 +1156,22 @@ int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp, ...@@ -1170,23 +1156,22 @@ int dtv_property_process(struct dvb_frontend *fe, dtv_property_t *tvp,
dtv_property_dump(tvp); dtv_property_dump(tvp);
switch(tvp->cmd) { switch(tvp->cmd) {
case DTV_SEQ_START: case DTV_CLEAR:
case DTV_SEQ_TERMINATE:
/* Reset a cache of data specific to the frontend here. This does /* Reset a cache of data specific to the frontend here. This does
* not effect hardware. * not effect hardware.
*/ */
printk("%s() Flushing property cache\n", __FUNCTION__); printk("%s() Flushing property cache\n", __FUNCTION__);
memset(&fe->dtv_property_cache, 0, sizeof(struct dtv_frontend_properties)); 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; fe->dtv_property_cache.delivery_system = SYS_UNDEFINED;
break; break;
case DTV_SEQ_COMPLETE: case DTV_TUNE:
/* interpret the cache of data, build either a traditional frontend /* interpret the cache of data, build either a traditional frontend
* tunerequest and submit it to a subset of the ioctl handler, * tunerequest and submit it to a subset of the ioctl handler,
* or, call a new undefined method on the frontend to deal with * or, call a new undefined method on the frontend to deal with
* all new tune requests. * 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__); printk("%s() Finalised property cache\n", __FUNCTION__);
r |= dtv_property_cache_submit(fe); r |= dtv_property_cache_submit(fe);
r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, 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, ...@@ -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_device *dvbdev = file->private_data;
struct dvb_frontend *fe = dvbdev->priv; struct dvb_frontend *fe = dvbdev->priv;
int err = -EOPNOTSUPP; int err = -EOPNOTSUPP;
dtv_property_t *tvp;
struct dtv_properties *tvps = NULL;
struct dtv_property *tvp = NULL;
int i;
dprintk("%s\n", __func__); dprintk("%s\n", __func__);
if(cmd == FE_SET_PROPERTY) { if(cmd == FE_SET_PROPERTY) {
printk("%s() FE_SET_PROPERTY\n", __FUNCTION__); 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 */ printk("%s() properties.num = %d\n", __FUNCTION__, tvps->num);
tvp = parg; printk("%s() properties.props = %p\n", __FUNCTION__, tvps->props);
while(tvp->cmd != DTV_SEQ_UNDEFINED) {
dtv_property_process(fe, tvp, inode, file); /* Put an arbitrary limit on the number of messages that can
if( (tvp->cmd == DTV_SEQ_TERMINATE) || (tvp->cmd == DTV_SEQ_COMPLETE) ) * be sent at once */
break; if (tvps->num > DTV_IOCTL_MAX_MSGS)
tvp++; 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__); printk("%s() Property cache is full, tuning\n", __FUNCTION__);
} }
err = 0; err = 0;
} }
out:
kfree(tvp);
return err; return err;
} }
...@@ -1545,7 +1548,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, ...@@ -1545,7 +1548,7 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file,
case FE_SET_FRONTEND: { case FE_SET_FRONTEND: {
struct dvb_frontend_tune_settings fetunesettings; 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) { if (dvb_frontend_check_parameters(fe, &fepriv->parameters) < 0) {
err = -EINVAL; err = -EINVAL;
break; break;
......
...@@ -170,8 +170,8 @@ struct dvb_frontend_ops { ...@@ -170,8 +170,8 @@ struct dvb_frontend_ops {
struct dvb_tuner_ops tuner_ops; struct dvb_tuner_ops tuner_ops;
struct analog_demod_ops analog_ops; struct analog_demod_ops analog_ops;
int (*set_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, dtv_property_t* tvp); int (*get_property)(struct dvb_frontend* fe, struct dtv_property* tvp);
int (*set_params)(struct dvb_frontend* fe); int (*set_params)(struct dvb_frontend* fe);
}; };
......
...@@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe) ...@@ -796,7 +796,7 @@ static int cx24116_initfe(struct dvb_frontend* fe)
return cx24116_diseqc_init(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__); dprintk("%s(..)\n", __func__);
return 0; return 0;
......
...@@ -251,11 +251,8 @@ struct dvb_frontend_event { ...@@ -251,11 +251,8 @@ struct dvb_frontend_event {
* binary compatability. * binary compatability.
*/ */
typedef enum dtv_cmd_types { typedef enum dtv_cmd_types {
DTV_SEQ_UNDEFINED, DTV_TUNE,
DTV_SEQ_START, DTV_CLEAR,
DTV_SEQ_CONTINUE,
DTV_SEQ_COMPLETE,
DTV_SEQ_TERMINATE,
DTV_SET_FREQUENCY, DTV_SET_FREQUENCY,
DTV_SET_MODULATION, DTV_SET_MODULATION,
...@@ -348,22 +345,32 @@ struct dtv_cmds_h { ...@@ -348,22 +345,32 @@ struct dtv_cmds_h {
__u32 reserved:30; /* Align */ __u32 reserved:30; /* Align */
}; };
typedef struct { struct dtv_property {
__u32 cmd; __u32 cmd;
__u32 reserved[3];
union { union {
__s32 valuemin;
__s32 valuemax;
__u32 data; __u32 data;
struct { struct {
__u8 data[32]; __u8 data[32];
__u32 len; __u32 len;
__u32 reserved1[3];
void *reserved2;
} buffer; } buffer;
} u; } u;
} dtv_property_t; } __attribute__ ((packed));
/* No more than 16 properties during any given ioctl */ /* 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_SET_PROPERTY _IOW('o', 82, struct dtv_properties)
#define FE_GET_PROPERTY _IOR('o', 83, dtv_properties_t) #define FE_GET_PROPERTY _IOR('o', 83, struct dtv_properties)
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment