Commit 556a0442 authored by Chris Rankin's avatar Chris Rankin Committed by Mauro Carvalho Chehab

[media] dvb_frontend: regression fix: userspace ABI broken for xine

The commit e399ce77 has broken the DVB ABI for xine:

The problem is that xine is expecting every event after a successful
FE_SET_FRONTEND ioctl to have a non-zero frequency parameter, regardless
of whether the tuning process has LOCKed yet. What used to happen is
that the events inherited the initial tuning parameters from the
FE_SET_FRONTEND call. However, the fepriv->parameters_out struct is now
not initialised until the status contains the FE_HAS_LOCK bit.

You might argue that this behaviour is intentional, except that if an
application other than xine uses the DVB adapter and manages to set the
parameters_out.frequency field to something other than zero, then xine
no longer has any problems until either the adapter is replugged or the
kernel modules reloaded. This can only mean that the
fepriv->parameters_out struct still contains the (stale) tuning
information from the previous application.
Signed-off-by: default avatarChris Rankin <rankincj@yahoo.com>
Cc: stable@kernel.org # for kernel version 3.3
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 7483d45f
...@@ -143,6 +143,8 @@ struct dvb_frontend_private { ...@@ -143,6 +143,8 @@ struct dvb_frontend_private {
static void dvb_frontend_wakeup(struct dvb_frontend *fe); static void dvb_frontend_wakeup(struct dvb_frontend *fe);
static int dtv_get_frontend(struct dvb_frontend *fe, static int dtv_get_frontend(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p_out); struct dvb_frontend_parameters *p_out);
static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
struct dvb_frontend_parameters *p);
static bool has_get_frontend(struct dvb_frontend *fe) static bool has_get_frontend(struct dvb_frontend *fe)
{ {
...@@ -697,6 +699,7 @@ static int dvb_frontend_thread(void *data) ...@@ -697,6 +699,7 @@ static int dvb_frontend_thread(void *data)
fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
fepriv->delay = HZ / 2; fepriv->delay = HZ / 2;
} }
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
fe->ops.read_status(fe, &s); fe->ops.read_status(fe, &s);
if (s != fepriv->status) { if (s != fepriv->status) {
dvb_frontend_add_event(fe, s); /* update event list */ dvb_frontend_add_event(fe, s); /* update event list */
...@@ -1832,6 +1835,13 @@ static int dtv_set_frontend(struct dvb_frontend *fe) ...@@ -1832,6 +1835,13 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
if (dvb_frontend_check_parameters(fe) < 0) if (dvb_frontend_check_parameters(fe) < 0)
return -EINVAL; return -EINVAL;
/*
* Initialize output parameters to match the values given by
* the user. FE_SET_FRONTEND triggers an initial frontend event
* with status = 0, which copies output parameters to userspace.
*/
dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
/* /*
* Be sure that the bandwidth will be filled for all * Be sure that the bandwidth will be filled for all
* non-satellite systems, as tuners need to know what * non-satellite systems, as tuners need to know what
......
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