[media] dvb-frontend: split set_delivery_system()
This function is complex, and has different workflows, one for DVBv3 calls, and another one for DVBv5 calls. Break it into 3 functions, in order to make easier to understand what each block does. No functional changes so far. A few comments got improved. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
7f6301d125
commit
be431b16c6
|
@ -1509,132 +1509,12 @@ static bool is_dvbv3_delsys(u32 delsys)
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
|
static int emulate_delivery_system(struct dvb_frontend *fe,
|
||||||
|
enum dvbv3_emulation_type type,
|
||||||
|
u32 delsys, u32 desired_system)
|
||||||
{
|
{
|
||||||
int ncaps, i;
|
int i;
|
||||||
u32 delsys = SYS_UNDEFINED;
|
|
||||||
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
enum dvbv3_emulation_type type;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* It was reported that some old DVBv5 applications were
|
|
||||||
* filling delivery_system with SYS_UNDEFINED. If this happens,
|
|
||||||
* assume that the application wants to use the first supported
|
|
||||||
* delivery system.
|
|
||||||
*/
|
|
||||||
if (c->delivery_system == SYS_UNDEFINED)
|
|
||||||
c->delivery_system = fe->ops.delsys[0];
|
|
||||||
|
|
||||||
if (desired_system == SYS_UNDEFINED) {
|
|
||||||
/*
|
|
||||||
* A DVBv3 call doesn't know what's the desired system.
|
|
||||||
* Also, DVBv3 applications don't know that ops.info->type
|
|
||||||
* could be changed, and they simply dies when it doesn't
|
|
||||||
* match.
|
|
||||||
* So, don't change the current delivery system, as it
|
|
||||||
* may be trying to do the wrong thing, like setting an
|
|
||||||
* ISDB-T frontend as DVB-T. Instead, find the closest
|
|
||||||
* DVBv3 system that matches the delivery system.
|
|
||||||
*/
|
|
||||||
if (is_dvbv3_delsys(c->delivery_system)) {
|
|
||||||
dev_dbg(fe->dvb->device,
|
|
||||||
"%s: Using delivery system to %d\n",
|
|
||||||
__func__, c->delivery_system);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
type = dvbv3_type(c->delivery_system);
|
|
||||||
switch (type) {
|
|
||||||
case DVBV3_QPSK:
|
|
||||||
desired_system = SYS_DVBS;
|
|
||||||
break;
|
|
||||||
case DVBV3_QAM:
|
|
||||||
desired_system = SYS_DVBC_ANNEX_A;
|
|
||||||
break;
|
|
||||||
case DVBV3_ATSC:
|
|
||||||
desired_system = SYS_ATSC;
|
|
||||||
break;
|
|
||||||
case DVBV3_OFDM:
|
|
||||||
desired_system = SYS_DVBT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
|
|
||||||
__func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
* Get a delivery system that is compatible with DVBv3
|
|
||||||
* NOTE: in order for this to work with softwares like Kaffeine that
|
|
||||||
* uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
|
|
||||||
* DVB-S, drivers that support both should put the SYS_DVBS entry
|
|
||||||
* before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
|
|
||||||
* The real fix is that userspace applications should not use DVBv3
|
|
||||||
* and not trust on calling FE_SET_FRONTEND to switch the delivery
|
|
||||||
* system.
|
|
||||||
*/
|
|
||||||
ncaps = 0;
|
|
||||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
|
||||||
if (fe->ops.delsys[ncaps] == desired_system) {
|
|
||||||
delsys = desired_system;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ncaps++;
|
|
||||||
}
|
|
||||||
if (delsys == SYS_UNDEFINED) {
|
|
||||||
dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
|
|
||||||
__func__, desired_system);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*
|
|
||||||
* This is a DVBv5 call. So, it likely knows the supported
|
|
||||||
* delivery systems.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Check if the desired delivery system is supported */
|
|
||||||
ncaps = 0;
|
|
||||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
|
||||||
if (fe->ops.delsys[ncaps] == desired_system) {
|
|
||||||
c->delivery_system = desired_system;
|
|
||||||
dev_dbg(fe->dvb->device,
|
|
||||||
"%s: Changing delivery system to %d\n",
|
|
||||||
__func__, desired_system);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
ncaps++;
|
|
||||||
}
|
|
||||||
type = dvbv3_type(desired_system);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The delivery system is not supported. See if it can be
|
|
||||||
* emulated.
|
|
||||||
* The emulation only works if the desired system is one of the
|
|
||||||
* DVBv3 delivery systems
|
|
||||||
*/
|
|
||||||
if (!is_dvbv3_delsys(desired_system)) {
|
|
||||||
dev_dbg(fe->dvb->device,
|
|
||||||
"%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
|
|
||||||
__func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the last non-DVBv3 delivery system that has the same type
|
|
||||||
* of the desired system
|
|
||||||
*/
|
|
||||||
ncaps = 0;
|
|
||||||
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
|
||||||
if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
|
|
||||||
!is_dvbv3_delsys(fe->ops.delsys[ncaps]))
|
|
||||||
delsys = fe->ops.delsys[ncaps];
|
|
||||||
ncaps++;
|
|
||||||
}
|
|
||||||
/* There's nothing compatible with the desired delivery system */
|
|
||||||
if (delsys == SYS_UNDEFINED) {
|
|
||||||
dev_dbg(fe->dvb->device,
|
|
||||||
"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
|
|
||||||
__func__);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c->delivery_system = delsys;
|
c->delivery_system = delsys;
|
||||||
|
|
||||||
|
@ -1648,8 +1528,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
|
||||||
* delivery system is the last one at the ops.delsys[] array
|
* delivery system is the last one at the ops.delsys[] array
|
||||||
*/
|
*/
|
||||||
dev_dbg(fe->dvb->device,
|
dev_dbg(fe->dvb->device,
|
||||||
"%s: Using delivery system %d emulated as if it were a %d\n",
|
"%s: Using delivery system %d emulated as if it were a %d\n",
|
||||||
__func__, delsys, desired_system);
|
__func__, delsys, desired_system);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For now, handles ISDB-T calls. More code may be needed here for the
|
* For now, handles ISDB-T calls. More code may be needed here for the
|
||||||
|
@ -1684,6 +1564,162 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int dvbv5_set_delivery_system(struct dvb_frontend *fe,
|
||||||
|
u32 desired_system)
|
||||||
|
{
|
||||||
|
int ncaps;
|
||||||
|
u32 delsys = SYS_UNDEFINED;
|
||||||
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
|
enum dvbv3_emulation_type type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* It was reported that some old DVBv5 applications were
|
||||||
|
* filling delivery_system with SYS_UNDEFINED. If this happens,
|
||||||
|
* assume that the application wants to use the first supported
|
||||||
|
* delivery system.
|
||||||
|
*/
|
||||||
|
if (c->delivery_system == SYS_UNDEFINED)
|
||||||
|
c->delivery_system = fe->ops.delsys[0];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a DVBv5 call. So, it likely knows the supported
|
||||||
|
* delivery systems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Check if the desired delivery system is supported */
|
||||||
|
ncaps = 0;
|
||||||
|
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||||
|
if (fe->ops.delsys[ncaps] == desired_system) {
|
||||||
|
c->delivery_system = desired_system;
|
||||||
|
dev_dbg(fe->dvb->device,
|
||||||
|
"%s: Changing delivery system to %d\n",
|
||||||
|
__func__, desired_system);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ncaps++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Need to emulate a delivery system
|
||||||
|
*/
|
||||||
|
|
||||||
|
type = dvbv3_type(desired_system);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The delivery system is not supported. See if it can be
|
||||||
|
* emulated.
|
||||||
|
* The emulation only works if the desired system is one of the
|
||||||
|
* DVBv3 delivery systems
|
||||||
|
*/
|
||||||
|
if (!is_dvbv3_delsys(desired_system)) {
|
||||||
|
dev_dbg(fe->dvb->device,
|
||||||
|
"%s: can't use a DVBv3 FE_SET_FRONTEND call for this frontend\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get the last non-DVBv3 delivery system that has the same type
|
||||||
|
* of the desired system
|
||||||
|
*/
|
||||||
|
ncaps = 0;
|
||||||
|
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||||
|
if ((dvbv3_type(fe->ops.delsys[ncaps]) == type) &&
|
||||||
|
!is_dvbv3_delsys(fe->ops.delsys[ncaps]))
|
||||||
|
delsys = fe->ops.delsys[ncaps];
|
||||||
|
ncaps++;
|
||||||
|
}
|
||||||
|
/* There's nothing compatible with the desired delivery system */
|
||||||
|
if (delsys == SYS_UNDEFINED) {
|
||||||
|
dev_dbg(fe->dvb->device,
|
||||||
|
"%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return emulate_delivery_system(fe, type, delsys, desired_system);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dvbv3_set_delivery_system(struct dvb_frontend *fe)
|
||||||
|
{
|
||||||
|
int ncaps;
|
||||||
|
u32 desired_system;
|
||||||
|
u32 delsys = SYS_UNDEFINED;
|
||||||
|
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
|
||||||
|
enum dvbv3_emulation_type type;
|
||||||
|
|
||||||
|
/* If not set yet, defaults to the first supported delivery system */
|
||||||
|
if (c->delivery_system == SYS_UNDEFINED)
|
||||||
|
c->delivery_system = fe->ops.delsys[0];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A DVBv3 call doesn't know what's the desired system.
|
||||||
|
* Also, DVBv3 applications don't know that ops.info->type
|
||||||
|
* could be changed, and they simply don't tune when it doesn't
|
||||||
|
* match.
|
||||||
|
* So, don't change the current delivery system, as it
|
||||||
|
* may be trying to do the wrong thing, like setting an
|
||||||
|
* ISDB-T frontend as DVB-T. Instead, find the closest
|
||||||
|
* DVBv3 system that matches the delivery system.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trivial case: just use the current one, if it already a DVBv3
|
||||||
|
* delivery system
|
||||||
|
*/
|
||||||
|
if (is_dvbv3_delsys(c->delivery_system)) {
|
||||||
|
dev_dbg(fe->dvb->device,
|
||||||
|
"%s: Using delivery system to %d\n",
|
||||||
|
__func__, c->delivery_system);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert from DVBv3 into DVBv5 namespace */
|
||||||
|
type = dvbv3_type(c->delivery_system);
|
||||||
|
switch (type) {
|
||||||
|
case DVBV3_QPSK:
|
||||||
|
desired_system = SYS_DVBS;
|
||||||
|
break;
|
||||||
|
case DVBV3_QAM:
|
||||||
|
desired_system = SYS_DVBC_ANNEX_A;
|
||||||
|
break;
|
||||||
|
case DVBV3_ATSC:
|
||||||
|
desired_system = SYS_ATSC;
|
||||||
|
break;
|
||||||
|
case DVBV3_OFDM:
|
||||||
|
desired_system = SYS_DVBT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Get a delivery system that is compatible with DVBv3
|
||||||
|
* NOTE: in order for this to work with softwares like Kaffeine that
|
||||||
|
* uses a DVBv5 call for DVB-S2 and a DVBv3 call to go back to
|
||||||
|
* DVB-S, drivers that support both should put the SYS_DVBS entry
|
||||||
|
* before the SYS_DVBS2, otherwise it won't switch back to DVB-S.
|
||||||
|
* The real fix is that userspace applications should not use DVBv3
|
||||||
|
* and not trust on calling FE_SET_FRONTEND to switch the delivery
|
||||||
|
* system.
|
||||||
|
*/
|
||||||
|
ncaps = 0;
|
||||||
|
while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
|
||||||
|
if (fe->ops.delsys[ncaps] == desired_system) {
|
||||||
|
delsys = desired_system;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ncaps++;
|
||||||
|
}
|
||||||
|
if (delsys == SYS_UNDEFINED) {
|
||||||
|
dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
|
||||||
|
__func__, desired_system);
|
||||||
|
}
|
||||||
|
return emulate_delivery_system(fe, type, delsys, desired_system);
|
||||||
|
}
|
||||||
|
|
||||||
static int dtv_property_process_set(struct dvb_frontend *fe,
|
static int dtv_property_process_set(struct dvb_frontend *fe,
|
||||||
struct dtv_property *tvp,
|
struct dtv_property *tvp,
|
||||||
struct file *file)
|
struct file *file)
|
||||||
|
@ -1742,7 +1778,7 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
|
||||||
c->rolloff = tvp->u.data;
|
c->rolloff = tvp->u.data;
|
||||||
break;
|
break;
|
||||||
case DTV_DELIVERY_SYSTEM:
|
case DTV_DELIVERY_SYSTEM:
|
||||||
r = set_delivery_system(fe, tvp->u.data);
|
r = dvbv5_set_delivery_system(fe, tvp->u.data);
|
||||||
break;
|
break;
|
||||||
case DTV_VOLTAGE:
|
case DTV_VOLTAGE:
|
||||||
c->voltage = tvp->u.data;
|
c->voltage = tvp->u.data;
|
||||||
|
@ -2335,7 +2371,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FE_SET_FRONTEND:
|
case FE_SET_FRONTEND:
|
||||||
err = set_delivery_system(fe, SYS_UNDEFINED);
|
err = dvbv3_set_delivery_system(fe);
|
||||||
if (err)
|
if (err)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -2594,7 +2630,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
|
||||||
* first supported delivery system (ops->delsys[0])
|
* first supported delivery system (ops->delsys[0])
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
|
fe->dtv_property_cache.delivery_system = fe->ops.delsys[0];
|
||||||
dvb_frontend_clear_cache(fe);
|
dvb_frontend_clear_cache(fe);
|
||||||
|
|
||||||
mutex_unlock(&frontend_mutex);
|
mutex_unlock(&frontend_mutex);
|
||||||
|
|
Loading…
Reference in New Issue