Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+43 −40
Original line number Diff line number Diff line
@@ -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;
+2 −2
Original line number Diff line number Diff line
@@ -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);
};

+1 −1
Original line number Diff line number Diff line
@@ -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;
+17 −10
Original line number Diff line number Diff line
@@ -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)


/**