From: Mauro Carvalho Chehab Date: Sat, 19 Jan 2013 09:25:13 +0000 (-0200) Subject: dvb-fe: Add a flag to indicate if DVBv5 stats is in use X-Git-Tag: v4l-utils-0.9.4~89 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c82c2671ac6c9e6b8eeac139cb899984c9482335;p=platform%2Fupstream%2Fv4l-utils.git dvb-fe: Add a flag to indicate if DVBv5 stats is in use Instead of trying every time to see if DVBv5 stats are available, if version is equal or upper than 5.10, a call to FE_GET_PROPERTY will fail only if a more permanent error happened (EFAULT, ENOMEM, and similar errors). A successful call to FE_GET_PROPERTY that returns all stat props with len=0 means that the frontend doesn't implement any DVBv5 stats. So, if it fails once, it can be assumed that there's no DVBv5 stats implemented for that frontend. As a bonus, the logic now knows exactly if a measure came from DVBv3 or from DVBv5 API. Signed-off-by: Mauro Carvalho Chehab --- diff --git a/lib/include/dvb-fe.h b/lib/include/dvb-fe.h index 27b9aed..a588d8e 100644 --- a/lib/include/dvb-fe.h +++ b/lib/include/dvb-fe.h @@ -70,6 +70,7 @@ struct dvb_v5_fe_parms { unsigned verbose; struct dvb_frontend_info info; uint32_t version; + int has_v5_stats; fe_delivery_system_t current_sys; int num_systems; fe_delivery_system_t systems[MAX_DELIVERY_SYSTEMS]; diff --git a/lib/libdvbv5/dvb-fe.c b/lib/libdvbv5/dvb-fe.c index ec35922..07b40df 100644 --- a/lib/libdvbv5/dvb-fe.c +++ b/lib/libdvbv5/dvb-fe.c @@ -113,6 +113,11 @@ struct dvb_v5_fe_parms *dvb_fe_open2(int adapter, int frontend, unsigned verbose if (parms->version < 0x500) use_legacy_call = 1; + if (parms->version >= 0x50a) + parms->has_v5_stats = 1; + else + parms->has_v5_stats = 0; + if (use_legacy_call || parms->version < 0x505) { parms->legacy_fe = 1; switch(parms->info.type) { @@ -666,11 +671,54 @@ ret: return 0; } +static struct dtv_stats *dvb_fe_store_stats(struct dvb_v5_fe_parms *parms, + unsigned cmd, + enum fecap_scale_params scale, + unsigned layer, + uint32_t value) +{ + int i; + for (i = 0; i < DTV_NUM_STATS_PROPS; i++) { + if (parms->stats.prop[i].cmd != cmd) + continue; + parms->stats.prop[i].u.st.stat[layer].scale = scale; + parms->stats.prop[i].u.st.stat[layer].uvalue = value; + if (parms->stats.prop[i].u.st.len < layer + 1) + parms->stats.prop[i].u.st.len = layer + 1; + return &parms->stats.prop[i].u.st.stat[layer]; + } + dvb_logerr("%s not found on store", dvb_cmd_name(cmd)); + + return NULL; +} + +static struct dtv_stats *dvb_fe_retrieve_v5_BER(struct dvb_v5_fe_parms *parms, + unsigned cmd, unsigned layer) +{ + struct dtv_stats *st_bec, *st_bc; + uint64_t ber64; + + st_bec = dvb_fe_retrieve_stats_layer(parms, DTV_STAT_POST_BIT_ERROR_COUNT, layer); + if (!st_bec) + return NULL; + + st_bc = dvb_fe_retrieve_stats_layer(parms, DTV_STAT_POST_TOTAL_BIT_COUNT, layer); + if (!st_bc || !st_bc->uvalue) + return NULL; + + ber64 = (1E9 * st_bec->uvalue) / st_bc->uvalue; + + return dvb_fe_store_stats(parms, DTV_BER, FE_SCALE_COUNTER, layer, ber64); +} + struct dtv_stats *dvb_fe_retrieve_stats_layer(struct dvb_v5_fe_parms *parms, unsigned cmd, unsigned layer) { int i; + if (cmd == DTV_BER && parms->has_v5_stats) + return dvb_fe_retrieve_v5_BER(parms, cmd, layer); + for (i = 0; i < DTV_NUM_STATS_PROPS; i++) { if (parms->stats.prop[i].cmd != cmd) continue; @@ -711,27 +759,6 @@ int dvb_fe_retrieve_stats(struct dvb_v5_fe_parms *parms, return 0; } -static int dvb_fe_store_stats(struct dvb_v5_fe_parms *parms, - unsigned cmd, - enum fecap_scale_params scale, - unsigned layer, - uint32_t value) -{ - int i; - for (i = 0; i < DTV_NUM_STATS_PROPS; i++) { - if (parms->stats.prop[i].cmd != cmd) - continue; - parms->stats.prop[i].u.st.stat[layer].scale = scale; - parms->stats.prop[i].u.st.stat[layer].uvalue = value; - if (parms->stats.prop[i].u.st.len < layer + 1) - parms->stats.prop[i].u.st.len = layer + 1; - return 0; - } - dvb_logerr("%s not found on store", dvb_cmd_name(cmd)); - - return EINVAL; -} - int dvb_fe_get_stats(struct dvb_v5_fe_parms *parms) { fe_status_t status = 0; @@ -746,49 +773,31 @@ int dvb_fe_get_stats(struct dvb_v5_fe_parms *parms) } dvb_fe_store_stats(parms, DTV_STATUS, FE_SCALE_RELATIVE, 0, status); - if (parms->version >= 0x50a) { + if (parms->has_v5_stats) { struct dtv_properties props; - struct dtv_stats *st_bec, *st_bc; props.num = 6; props.props = parms->stats.prop; /* Do a DVBv5.10 stats call */ if (ioctl(parms->fd, FE_GET_PROPERTY, &props) == -1) - goto dvbv3_fallback; + return errno; - /* If no stats i returned, fallback to the legacy API */ + /* + * All props with len=0 mean that this device doesn't have any + * dvbv5 stats. Try the legacy stats instead. + */ for (i = 0; i < props.num; i++) if (parms->stats.prop[i].u.st.len) break; if (i == props.num) goto dvbv3_fallback; - - /* Calculate and store BER */ - for (i = 0; i < 4; i++) { - uint64_t ber64; - - st_bec = dvb_fe_retrieve_stats_layer(parms, DTV_STAT_POST_BIT_ERROR_COUNT, i); - if (!st_bec) - goto no_ber; - - st_bc = dvb_fe_retrieve_stats_layer(parms, DTV_STAT_POST_TOTAL_BIT_COUNT, i); - if (!st_bc || !st_bc->uvalue) - goto no_ber; - - ber64 = (1E9 * st_bec->uvalue) / st_bc->uvalue; - - dvb_fe_store_stats(parms, DTV_BER, FE_SCALE_COUNTER, i, ber64); - continue; -no_ber: - dvb_fe_store_stats(parms, DTV_BER, FE_SCALE_NOT_AVAILABLE, i, 0); - } - - return 0; } dvbv3_fallback: - /* DVB v3 stats*/ + /* DVB v3 stats */ + parms->has_v5_stats = 0; + if (ioctl(parms->fd, FE_READ_BER, &ber) == -1) scale = FE_SCALE_NOT_AVAILABLE; else