Skip to content

Instantly share code, notes, and snippets.

@athoik
Created February 8, 2017 13:19
Show Gist options
  • Save athoik/5f755cabed0cfccea008d36e9f166e7b to your computer and use it in GitHub Desktop.
Save athoik/5f755cabed0cfccea008d36e9f166e7b to your computer and use it in GitHub Desktop.
Simple Utility to query DVB API 5 statistics (with some code borrowed from other utilities)
#include <linux/dvb/version.h>
#include <linux/dvb/frontend.h>
#include <iostream>
#include <sstream>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
using namespace std;
const char* getScale(int scale)
{
if(scale == FE_SCALE_NOT_AVAILABLE)
return "FE_SCALE_NOT_AVAILABLE";
else if(scale == FE_SCALE_RELATIVE)
return "FE_SCALE_RELATIVE";
else if(scale == FE_SCALE_DECIBEL)
return "FE_SCALE_DECIBEL";
else if(scale == FE_SCALE_COUNTER)
return "FE_SCALE_COUNTER";
else
return "ERROR??";
}
const char* getCMD(int cmd)
{
if(cmd == DTV_STAT_CNR)
return "DTV_STAT_CNR";
else if(cmd == DTV_STAT_SIGNAL_STRENGTH)
return "DTV_STAT_SIGNAL_STRENGTH";
else if(cmd == DTV_STAT_ERROR_BLOCK_COUNT)
return "DTV_STAT_ERROR_BLOCK_COUNT";
else if(cmd == DTV_STAT_PRE_ERROR_BIT_COUNT)
return "DTV_STAT_PRE_ERROR_BIT_COUNT";
else if(cmd == DTV_STAT_PRE_TOTAL_BIT_COUNT)
return "DTV_STAT_PRE_TOTAL_BIT_COUNT";
else if(cmd == DTV_STAT_POST_ERROR_BIT_COUNT)
return "DTV_STAT_POST_ERROR_BIT_COUNT";
else if(cmd == DTV_STAT_POST_TOTAL_BIT_COUNT)
return "DTV_STAT_POST_TOTAL_BIT_COUNT";
else if(cmd == DTV_STAT_ERROR_BLOCK_COUNT)
return "DTV_STAT_ERROR_BLOCK_COUNT";
else if(cmd == DTV_STAT_TOTAL_BLOCK_COUNT)
return "DTV_STAT_TOTAL_BLOCK_COUNT";
#if defined DTV_STATUS
else if(cmd == DTV_STATUS)
return "DTV_STATUS";
else if(cmd == DTV_BER)
return "DTV_BER";
else if(cmd == DTV_PER)
return "DTV_PER";
else if(cmd == DTV_QUALITY)
return "DTV_QUALITY";
else if(cmd == DTV_PRE_BER)
return "DTV_PRE_BER";
#endif
else
return "ERROR?";
}
void getCNR(int fd)
{
dtv_property prop[13];
/**prop[0].cmd = DTV_STAT_CNR;
prop[1].cmd = DTV_STAT_SIGNAL_STRENGTH;
prop[2].cmd = DTV_STAT_ERROR_BLOCK_COUNT;**/
/*
* Prepare the status struct - DVBv5.10 parameters should
* come first, as they'll be read together.
*/
prop[0].cmd = DTV_STAT_SIGNAL_STRENGTH;
prop[1].cmd = DTV_STAT_CNR;
prop[2].cmd = DTV_STAT_PRE_ERROR_BIT_COUNT;
prop[3].cmd = DTV_STAT_PRE_TOTAL_BIT_COUNT;
prop[4].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
prop[5].cmd = DTV_STAT_POST_TOTAL_BIT_COUNT;
prop[6].cmd = DTV_STAT_ERROR_BLOCK_COUNT;
prop[7].cmd = DTV_STAT_TOTAL_BLOCK_COUNT;
#if defined DTV_STATUS
/* Now, status and the calculated stats */
prop[8].cmd = DTV_STATUS;
prop[9].cmd = DTV_BER;
prop[10].cmd = DTV_PER;
prop[11].cmd = DTV_QUALITY;
prop[12].cmd = DTV_PRE_BER;
#endif
dtv_properties props;
props.props = prop;
#if defined DTV_STATUS
props.num = 13;
#else
props.num = 8;
#endif
if (::ioctl(fd, FE_GET_PROPERTY, &props) < 0)
{
cout << "error: ioctl failed on " << fd << endl;
::close(fd);
::exit(4);
}
for(unsigned int i=0; i<props.num; i++)
{
//if(!prop[i].u.st.len) prop[i].u.st.len = 1; //HACK for missing length
for(unsigned int j=0; j<prop[i].u.st.len; j++)
{
cout << getCMD(prop[i].cmd) <<
" S: " << prop[i].u.st.stat[j].svalue <<
" U: " << unsigned(prop[i].u.st.stat[j].uvalue) <<
" L: " << unsigned(prop[i].u.st.len) <<
" Scale: " << getScale(prop[i].u.st.stat[j].scale) << endl;
}
}
/**
cout << "DTV_STAT_CNR SValue: " << prop[0].u.st.stat[0].svalue << " UValue:"
<< prop[0].u.st.stat[0].uvalue << " Scale: " << getScale(prop[0].u.st.stat[0].scale) << endl;
cout << "DTV_STAT_SIGNAL_STRENGTH SValue: " << prop[1].u.st.stat[0].svalue << " UValue:"
<< prop[1].u.st.stat[0].uvalue << " Scale: " << getScale(prop[1].u.st.stat[0].scale) << endl;
cout << "DTV_STAT_ERROR_BLOCK_COUNT SValue: " << prop[2].u.st.stat[0].svalue << " UValue:"
<< prop[2].u.st.stat[0].uvalue << " Scale: " << getScale(prop[2].u.st.stat[0].scale) << endl;
**/
}
int check_frontend (int frontend_fd)
{
fe_status_t status;
unsigned int ber;
unsigned int ber_scale;
float snr;
unsigned int snr_scale;
float lvl;
unsigned int lvl_scale;
if (ioctl(frontend_fd, FE_READ_STATUS, &status) == -1) {
perror("FE_READ_STATUS failed");
}
struct dtv_property p[3];
p[0].cmd = DTV_STAT_SIGNAL_STRENGTH;
p[1].cmd = DTV_STAT_CNR;
p[2].cmd = DTV_STAT_POST_ERROR_BIT_COUNT;
struct dtv_properties p_status;
p_status.num = 3;
p_status.props = p;
if (ioctl(frontend_fd, FE_GET_PROPERTY, &p_status) == -1) {
perror("FE_GET_PROPERTY failed");
return -1;
}
lvl_scale = p_status.props[0].u.st.stat[0].scale;
if (lvl_scale == FE_SCALE_DECIBEL) {
lvl = p_status.props[0].u.st.stat[0].svalue * 0.0001;
} else {
int lvl;
if (ioctl(frontend_fd, FE_READ_SIGNAL_STRENGTH, &lvl) == -1) {
lvl = 0;
} else {
lvl = (lvl * 100) / 0xffff;
if (lvl < 0) {
lvl = 0;
}
}
}
snr_scale = p_status.props[1].u.st.stat[0].scale;
if (snr_scale == FE_SCALE_DECIBEL) {
snr = p_status.props[1].u.st.stat[0].svalue * .0001;
} else {
unsigned int snr = 0;
if (ioctl(frontend_fd, FE_READ_SNR, &snr) == -1) {
snr = 0;
}
}
ber_scale = p_status.props[2].u.st.stat[0].scale;
if (ber_scale == FE_SCALE_COUNTER) {
ber = p_status.props[2].u.st.stat[0].uvalue;
} else {
ber = 0;
if (ioctl(frontend_fd, FE_READ_BER, &ber) == -1) {
ber = 0;
}
}
printf ("status %s | signal %2.1f dBm | snr %2.1f dB | ber %u | ",
(status & FE_HAS_LOCK) ? "Locked" : "Unlocked", lvl, snr, ber);
if (status & FE_HAS_LOCK) {
printf("FE_HAS_LOCK \n");
} else printf("\n");
return 0;
}
int main(int argc, char *argv[])
{
int fd = -1;
if(argc != 2)
{
cout << "usage: " << argv[0] << " <frontend>" << endl;
cout << "example: " << argv[0] << " /dev/dvb/adapter0/frontend0" << endl;
return 1;
}
if(::access(argv[1], F_OK) < 0)
{
cout << "error: " << argv[1] << " does not exist!" << endl;
return 2;
}
fd = ::open(argv[1], O_RDONLY); //O_RDONLY O_RDWR
if(fd < 0)
{
cout << "error: " << argv[1] << " failed to open!" << endl;
return 3;
}
while(true)
{
getCNR(fd);
//check_frontend(fd);
usleep(5000000);
}
::close(fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment