From c26a0b4b65c8b579ddd8d775d544d5285f5919f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=96man?= Date: Tue, 3 May 2011 21:53:21 +0200 Subject: [PATCH] dvb: Better handling of uncorrected blocks counter Some DVB adapters return delta value from last read. Some return absolute value since adapter was created. Add some heuristics that tries to autodetect this. Ticket #393 --- src/dvb/dvb.h | 5 +++++ src/dvb/dvb_fe.c | 53 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/dvb/dvb.h b/src/dvb/dvb.h index 347fe31a82..9c14e23f2c 100644 --- a/src/dvb/dvb.h +++ b/src/dvb/dvb.h @@ -200,6 +200,11 @@ typedef struct th_dvb_adapter { int tda_allpids_dmx_fd; int tda_dump_fd; + uint32_t tda_last_fec; + + int tda_unc_is_delta; /* 1 if we believe FE_READ_UNCORRECTED_BLOCKS + * return dela values */ + } th_dvb_adapter_t; diff --git a/src/dvb/dvb_fe.c b/src/dvb/dvb_fe.c index 2382113489..9e7b789093 100644 --- a/src/dvb/dvb_fe.c +++ b/src/dvb/dvb_fe.c @@ -40,6 +40,42 @@ #include "notify.h" #include "dvr/dvr.h" +/** + * Return uncorrected block (since last read) + * + * Some adapters report delta themselfs, some return ever increasing value + * we need to deal with that ourselfs + */ +static int +dvb_fe_get_unc(th_dvb_adapter_t *tda) +{ + uint32_t fec; + int d, r; + + if(ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec)) + return 0; // read failed, just say 0 + + if(tda->tda_unc_is_delta) + return fec; + + d = (int)fec - (int)tda->tda_last_fec; + + if(d < 0) { + tda->tda_unc_is_delta = 1; + tvhlog(LOG_DEBUG, "dvb", + "%s: FE_READ_UNCORRECTED_BLOCKS returns delta updates (delta=%d)", + tda->tda_displayname, d); + return fec; + } + + r = fec - tda->tda_last_fec; + + tda->tda_last_fec = fec; + return r; +} + + + /** * Front end monitor * @@ -79,7 +115,7 @@ dvb_fe_monitor(void *aux) if(status == -1) { /* We have a lock, don't hold off */ tda->tda_fe_monitor_hold = 0; /* Reset FEC counter */ - ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec); + dvb_fe_get_unc(tda); } else { tda->tda_fe_monitor_hold--; return; @@ -89,8 +125,7 @@ dvb_fe_monitor(void *aux) if(status == -1) { /* Read FEC counter (delta) */ - if(ioctl(tda->tda_fe_fd, FE_READ_UNCORRECTED_BLOCKS, &fec)) - fec = 0; + fec = dvb_fe_get_unc(tda); tdmi->tdmi_fec_err_histogram[tdmi->tdmi_fec_err_ptr++] = fec; if(tdmi->tdmi_fec_err_ptr == TDMI_FEC_ERR_HISTOGRAM_SIZE) @@ -277,7 +312,7 @@ static int check_frontend (int fe_fd, int dvr, int human_readable) { (void)dvr; fe_status_t status; uint16_t snr, signal; - uint32_t ber, uncorrected_blocks; + uint32_t ber; int timeout = 0; do { @@ -292,15 +327,13 @@ static int check_frontend (int fe_fd, int dvr, int human_readable) { snr = -2; if (ioctl(fe_fd, FE_READ_BER, &ber) == -1) ber = -2; - if (ioctl(fe_fd, FE_READ_UNCORRECTED_BLOCKS, &uncorrected_blocks) == -1) - uncorrected_blocks = -2; if (human_readable) { - printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | unc %d | ", - status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber, uncorrected_blocks); + printf ("status %02x | signal %3u%% | snr %3u%% | ber %d | ", + status, (signal * 100) / 0xffff, (snr * 100) / 0xffff, ber); } else { - printf ("status %02x | signal %04x | snr %04x | ber %08x | unc %08x | ", - status, signal, snr, ber, uncorrected_blocks); + printf ("status %02x | signal %04x | snr %04x | ber %08x | ", + status, signal, snr, ber); } if (status & FE_HAS_LOCK) printf("FE_HAS_LOCK");