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: Steven Toth <stoth@linuxtv.org> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
56f0680a28
commit
e7fee0f3aa
@@ -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[] = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
/* 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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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 {
|
|||||||
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)
|
|||||||
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 {
|
|||||||
* 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 {
|
|||||||
__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 FE_SET_PROPERTY _IOW('o', 82, dtv_properties_t)
|
#define DTV_IOCTL_MAX_MSGS 64
|
||||||
#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)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user