diff --git a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c index a793bfec..1a8adf95 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_frontend.c +++ b/src/input/mpegts/linuxdvb/linuxdvb_frontend.c @@ -414,6 +414,18 @@ linuxdvb_frontend_default_tables } } +static inline int +ioctl_check( linuxdvb_frontend_t *lfe, int bit ) +{ + return !(lfe->lfe_ioctls & (1 << bit)); +} + +static inline void +ioctl_bad( linuxdvb_frontend_t *lfe, int bit ) +{ + lfe->lfe_ioctls |= 1 << bit; +} + static void linuxdvb_frontend_monitor ( void *aux ) { @@ -554,10 +566,10 @@ linuxdvb_frontend_monitor ( void *aux ) dtv_prop.num = 6; dtv_prop.props = fe_properties; - if(!ioctl(lfe->lfe_fe_fd, FE_GET_PROPERTY, &dtv_prop)) { + if(ioctl_check(lfe, 0) && !ioctl(lfe->lfe_fe_fd, FE_GET_PROPERTY, &dtv_prop)) { /* Signal strength */ gotprop = 0; - if(fe_properties[0].u.st.len > 0) { + if(ioctl_check(lfe, 1) && fe_properties[0].u.st.len > 0) { if(fe_properties[0].u.st.stat[0].scale == FE_SCALE_RELATIVE) { mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.signal = fe_properties[0].u.st.stat[0].uvalue; @@ -569,18 +581,20 @@ linuxdvb_frontend_monitor ( void *aux ) gotprop = 1; } else { + ioctl_bad(lfe, 1); mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unhandled signal scale: %d", fe_properties[0].u.st.stat[0].scale); } } - if(!gotprop) { + if(!gotprop && ioctl_check(lfe, 2)) { /* try old API */ if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) { mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.signal = u16; } else { + ioctl_bad(lfe, 2); mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value."); } @@ -588,39 +602,44 @@ linuxdvb_frontend_monitor ( void *aux ) /* ERROR_BIT_COUNT */ gotprop = 0; - if(fe_properties[1].u.st.len > 0) { + if(ioctl_check(lfe, 3) && fe_properties[1].u.st.len > 0) { if(fe_properties[1].u.st.stat[0].scale == FE_SCALE_COUNTER) { mmi->mmi_stats.ec_bit = fe_properties[1].u.st.stat[0].uvalue; gotprop = 1; } - else + else { + ioctl_bad(lfe, 3); tvhlog(LOG_WARNING, "linuxdvb", "Unhandled ERROR_BIT_COUNT scale: %d", fe_properties[1].u.st.stat[0].scale); + } } /* TOTAL_BIT_COUNT */ if(gotprop && (fe_properties[2].u.st.len > 0)) { gotprop = 0; - if(fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) { + if(ioctl_check(lfe, 4) && fe_properties[2].u.st.stat[0].scale == FE_SCALE_COUNTER) { mmi->mmi_stats.tc_bit = fe_properties[2].u.st.stat[0].uvalue; gotprop = 1; } else { + ioctl_bad(lfe, 4); mmi->mmi_stats.ec_bit = 0; /* both values or none */ tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BIT_COUNT scale: %d", fe_properties[2].u.st.stat[0].scale); } } - if(!gotprop) { + if(!gotprop && ioctl_check(lfe, 5)) { /* try old API */ if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32)) mmi->mmi_stats.ber = u32; - else + else { + ioctl_bad(lfe, 5); tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value."); + } } /* SNR */ gotprop = 0; - if(fe_properties[3].u.st.len > 0) { + if(ioctl_check(lfe, 6) && fe_properties[3].u.st.len > 0) { if(fe_properties[3].u.st.stat[0].scale == FE_SCALE_RELATIVE) { mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.snr = fe_properties[3].u.st.stat[0].uvalue; @@ -632,18 +651,20 @@ linuxdvb_frontend_monitor ( void *aux ) gotprop = 1; } else { + ioctl_bad(lfe, 6); mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unhandled SNR scale: %d", fe_properties[3].u.st.stat[0].scale); } } - if(!gotprop) { + if(!gotprop && ioctl_check(lfe, 7)) { /* try old API */ if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) { mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.snr = u16; } else { + ioctl_bad(lfe, 7); mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value."); } @@ -651,66 +672,78 @@ linuxdvb_frontend_monitor ( void *aux ) /* ERROR_BLOCK_COUNT == Uncorrected blocks (UNC) */ gotprop = 0; - if(fe_properties[4].u.st.len > 0) { + if(ioctl_check(lfe, 8) && fe_properties[4].u.st.len > 0) { if(fe_properties[4].u.st.stat[0].scale == FE_SCALE_COUNTER) { mmi->mmi_stats.unc = mmi->mmi_stats.ec_block = fe_properties[4].u.st.stat[0].uvalue; gotprop = 1; } - else + else { + ioctl_bad(lfe, 8); tvhlog(LOG_WARNING, "linuxdvb", "Unhandled ERROR_BLOCK_COUNT scale: %d", fe_properties[4].u.st.stat[0].scale); + } } /* TOTAL_BLOCK_COUNT */ if(gotprop && (fe_properties[5].u.st.len > 0)) { gotprop = 0; - if(fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) { + if(ioctl_check(lfe, 9) && fe_properties[5].u.st.stat[0].scale == FE_SCALE_COUNTER) { mmi->mmi_stats.tc_block = fe_properties[5].u.st.stat[0].uvalue; gotprop = 1; } else { + ioctl_bad(lfe, 9); mmi->mmi_stats.ec_block = mmi->mmi_stats.unc = 0; /* both values or none */ tvhlog(LOG_WARNING, "linuxdvb", "Unhandled TOTAL_BLOCK_COUNT scale: %d", fe_properties[5].u.st.stat[0].scale); } } - if(!gotprop) { + if(!gotprop && ioctl_check(lfe, 10)) { /* try old API */ if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) { mmi->mmi_stats.unc = u32; gotprop = 1; } - else + else { + ioctl_bad(lfe, 10); tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide UNC value."); + } } /* Older API */ } else #endif { - if (!ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) { + ioctl_bad(lfe, 0); + if (ioctl_check(lfe, 1) && !ioctl(lfe->lfe_fe_fd, FE_READ_SIGNAL_STRENGTH, &u16)) { mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.signal = u16; } else { + ioctl_bad(lfe, 1); mmi->mmi_stats.signal_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide signal strength value."); } - if (!ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32)) + if (ioctl_check(lfe, 2) && !ioctl(lfe->lfe_fe_fd, FE_READ_BER, &u32)) mmi->mmi_stats.ber = u32; - else + else { + ioctl_bad(lfe, 2); tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide BER value."); - if (!ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) { + } + if (ioctl_check(lfe, 3) && !ioctl(lfe->lfe_fe_fd, FE_READ_SNR, &u16)) { mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_RELATIVE; mmi->mmi_stats.snr = u16; } else { + ioctl_bad(lfe, 3); mmi->mmi_stats.snr_scale = INPUT_STREAM_STATS_SCALE_UNKNOWN; tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide SNR value."); } - if (!ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) + if (ioctl_check(lfe, 4) && !ioctl(lfe->lfe_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &u32)) mmi->mmi_stats.unc = u32; - else + else { + ioctl_bad(lfe, 4); tvhlog(LOG_WARNING, "linuxdvb", "Unable to provide UNC value."); + } } /* Send message */ @@ -1041,6 +1074,7 @@ linuxdvb_frontend_tune0 } lfe->lfe_locked = 0; lfe->lfe_status = 0; + lfe->lfe_ioctls = 0; /* * copy the universal parameters to the Linux kernel structure diff --git a/src/input/mpegts/linuxdvb/linuxdvb_private.h b/src/input/mpegts/linuxdvb/linuxdvb_private.h index 4c0002aa..a5e89da6 100644 --- a/src/input/mpegts/linuxdvb/linuxdvb_private.h +++ b/src/input/mpegts/linuxdvb/linuxdvb_private.h @@ -100,6 +100,7 @@ struct linuxdvb_frontend */ int lfe_locked; int lfe_status; + int lfe_ioctls; time_t lfe_monitor; gtimer_t lfe_monitor_timer;