[media] dvb_frontend: regression fix: userspace ABI broken for xine
authorChris Rankin <rankincj@yahoo.com>
Fri, 6 Apr 2012 21:38:18 +0000 (18:38 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Mon, 9 Apr 2012 12:41:34 +0000 (09:41 -0300)
The commit e399ce77e6e 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: Chris Rankin <rankincj@yahoo.com>
Cc: stable@kernel.org # for kernel version 3.3
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/dvb/dvb-core/dvb_frontend.c

index 4555baa383b26ec58b987bb65fecbe8303d7c504..e721975476b04c8e510848f79b88386373a39d2f 100644 (file)
@@ -143,6 +143,8 @@ struct dvb_frontend_private {
 static void dvb_frontend_wakeup(struct dvb_frontend *fe);
 static int dtv_get_frontend(struct dvb_frontend *fe,
                            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)
 {
@@ -697,6 +699,7 @@ restart:
                                        fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN;
                                        fepriv->delay = HZ / 2;
                                }
+                               dtv_property_legacy_params_sync(fe, &fepriv->parameters_out);
                                fe->ops.read_status(fe, &s);
                                if (s != fepriv->status) {
                                        dvb_frontend_add_event(fe, s); /* update event list */
@@ -1832,6 +1835,13 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
        if (dvb_frontend_check_parameters(fe) < 0)
                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
         * non-satellite systems, as tuners need to know what