Skip to content

Instantly share code, notes, and snippets.

@athoik
Last active April 25, 2017 20:11
Show Gist options
  • Save athoik/10c54f1856169637d973f62829c85e1d to your computer and use it in GitHub Desktop.
Save athoik/10c54f1856169637d973f62829c85e1d to your computer and use it in GitHub Desktop.
A small utility to test vtuner ATSC capability
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <linux/dvb/frontend.h>
#define VTUNER_GET_MESSAGE 1
#define VTUNER_SET_RESPONSE 2
#define VTUNER_SET_NAME 3
#define VTUNER_SET_TYPE 4
#define VTUNER_SET_HAS_OUTPUTS 5
#define VTUNER_SET_FE_INFO 6
#define VTUNER_SET_NUM_MODES 7
#define VTUNER_SET_MODES 8
#define VTUNER_SET_DELSYS 32
#define VTUNER_SET_ADAPTER 33
int setup_vtuner_dvb_s2(int fd)
{
struct dvb_frontend_info fe_info;
char fe_type[8];
unsigned char delsys[8];
strcpy(fe_info.name, "DVB-S2 VTUNER");
fe_info.type = FE_QPSK;
fe_info.frequency_min = 950000;
fe_info.frequency_max = 2150000;
fe_info.frequency_stepsize = 250;
fe_info.frequency_tolerance = 29500;
fe_info.symbol_rate_min = 1000000;
fe_info.symbol_rate_max = 45000000;
fe_info.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QPSK |
FE_CAN_2G_MODULATION | FE_CAN_MULTISTREAM;
strcpy(fe_type, "DVB-S2");
ioctl(fd, VTUNER_SET_NAME, fe_info.name);
ioctl(fd, VTUNER_SET_TYPE, fe_type);
ioctl(fd, VTUNER_SET_FE_INFO, &fe_info);
/* set delsys */
delsys[0] = SYS_DVBS2;
delsys[1] = SYS_DVBS;
delsys[2] = SYS_UNDEFINED;
ioctl(fd, VTUNER_SET_DELSYS, delsys);
/* has_outputs */
ioctl(fd, VTUNER_SET_HAS_OUTPUTS, "no");
return 0;
}
int setup_vtuner_dvb_c(int fd)
{
struct dvb_frontend_info fe_info;
char fe_type[8];
unsigned char delsys[8];
strcpy(fe_info.name, "DVB-C VTUNER");
fe_info.type = FE_QAM;
fe_info.frequency_min = 51000000;
fe_info.frequency_max = 858000000;
fe_info.frequency_stepsize = 62500;
fe_info.caps = FE_CAN_QAM_16 | FE_CAN_QAM_32 | FE_CAN_QAM_64 |
FE_CAN_QAM_128 | FE_CAN_QAM_256 |
FE_CAN_FEC_AUTO | FE_CAN_INVERSION_AUTO;
strcpy(fe_type, "DVB-C");
ioctl(fd, VTUNER_SET_NAME, fe_info.name);
ioctl(fd, VTUNER_SET_TYPE, fe_type);
ioctl(fd, VTUNER_SET_FE_INFO, &fe_info);
/* set delsys */
delsys[0] = SYS_DVBC_ANNEX_A;
delsys[1] = SYS_DVBC_ANNEX_C;
delsys[2] = SYS_DVBT2;
delsys[3] = SYS_DVBT;
delsys[4] = SYS_UNDEFINED;
ioctl(fd, VTUNER_SET_DELSYS, delsys);
/* has_outputs */
ioctl(fd, VTUNER_SET_HAS_OUTPUTS, "no");
return 0;
}
int setup_vtuner_dvb_t2(int fd)
{
struct dvb_frontend_info fe_info;
char fe_type[8];
unsigned char delsys[8];
strcpy(fe_info.name, "DVB-T2 VTUNER");
fe_info.type = FE_OFDM;
fe_info.frequency_min = 0;
fe_info.frequency_max = 863250000;
fe_info.frequency_stepsize = 62500;
fe_info.frequency_tolerance = 0;
fe_info.notifier_delay = 0;
fe_info.caps = FE_CAN_INVERSION_AUTO |
FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QPSK |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER |
FE_CAN_2G_MODULATION | FE_CAN_MULTISTREAM;
strcpy(fe_type, "DVB-T2");
ioctl(fd, VTUNER_SET_NAME, fe_info.name);
ioctl(fd, VTUNER_SET_TYPE, fe_type);
ioctl(fd, VTUNER_SET_FE_INFO, &fe_info);
/* set delsys */
delsys[0] = SYS_DVBT2;
delsys[1] = SYS_DVBT;
delsys[2] = SYS_DVBC_ANNEX_A;
delsys[3] = SYS_DVBC_ANNEX_C;
delsys[4] = SYS_UNDEFINED;
ioctl(fd, VTUNER_SET_DELSYS, delsys);
/* has_outputs */
ioctl(fd, VTUNER_SET_HAS_OUTPUTS, "no");
return 0;
}
int setup_vtuner_atsc(int fd)
{
struct dvb_frontend_info fe_info;
char fe_type[8];
unsigned char delsys[8];
strcpy(fe_info.name, "ATSC VTUNER");
fe_info.type = FE_ATSC;
fe_info.frequency_min = 54000000;
fe_info.frequency_max = 806000000;
fe_info.frequency_stepsize = 62500;
fe_info.frequency_tolerance = 0;
fe_info.notifier_delay = 0;
fe_info.caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
FE_CAN_8VSB | FE_CAN_QAM_64 | FE_CAN_QAM_256 |
FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO |
FE_CAN_HIERARCHY_AUTO | FE_CAN_RECOVER;
strcpy(fe_type, "ATSC");
ioctl(fd, VTUNER_SET_NAME, fe_info.name);
printf("VTUNER_SET_NAME: %d %m\n", errno);
ioctl(fd, VTUNER_SET_TYPE, fe_type);
printf("VTUNER_SET_TYPE: %d %m\n", errno);
ioctl(fd, VTUNER_SET_FE_INFO, &fe_info);
printf("VTUNER_SET_FE_INFO: %d %m\n", errno);
/* set delsys */
delsys[0] = SYS_ATSC;
delsys[1] = SYS_DVBC_ANNEX_B;
delsys[2] = SYS_UNDEFINED;
ioctl(fd, VTUNER_SET_DELSYS, delsys);
/* has_outputs */
ioctl(fd, VTUNER_SET_HAS_OUTPUTS, "no");
return 0;
}
const char *get_delivery_system(fe_delivery_system_t system)
{
switch (system) {
case SYS_UNDEFINED:
return "UNDEFINED";
case SYS_DVBC_ANNEX_A:
return "DVB-C ANNEX A";
case SYS_DVBC_ANNEX_B:
return "DVB-C ANNEX B";
case SYS_DVBC_ANNEX_C:
return "DVB-C ANNEX C";
case SYS_DVBT:
return "DVB-T";
case SYS_DSS:
return "DSS";
case SYS_DVBS:
return "DVB-S";
case SYS_DVBS2:
return "DVB-S2";
case SYS_DVBH:
return "DVB-H";
case SYS_ISDBT:
return "ISDBT";
case SYS_ISDBS:
return "ISDBS";
case SYS_ISDBC:
return "ISDBC";
case SYS_ATSC:
return "ATSC";
case SYS_ATSCMH:
return "ATSCMH";
case SYS_DTMB:
return "DTMB";
case SYS_CMMB:
return "CMMB";
case SYS_DAB:
return "DAB";
case SYS_DVBT2:
return "DVB-T2";
case SYS_TURBO:
return "TURBO";
default:
return "UNKNOWN";
}
}
int read_delsys(int fd)
{
struct dtv_property prop[1];
struct dtv_properties props;
int i;
prop[0].cmd = DTV_ENUM_DELSYS;
memset(prop[0].u.buffer.data, 0, sizeof(prop[0].u.buffer.data));
prop[0].u.buffer.len = 0;
props.props = prop;
props.num = 1;
if (ioctl(fd, FE_GET_PROPERTY, &props) < 0) {
fprintf(stderr, "DTV_ENUM_DELSYS failed: %m\n");
return -1;
}
fprintf(stdout, "Supported delivery system%s: \n",
(prop[0].u.buffer.len > 1) ? "s" : "");
for (i = 0; i < prop[0].u.buffer.len; i++)
fprintf(stdout, " [%s]\n", get_delivery_system(prop[0].u.buffer.data[i]));
return 0;
}
int newfrontend()
{
int nr = 0;
char filename[64];
while(1)
{
sprintf(filename, "/dev/dvb/adapter0/frontend%d", nr);
if(access(filename, R_OK) < 0) break;
nr++;
}
errno = 0;
return nr;
}
int main(int argc, char **argv)
{
int vtuner_fd;
int fe_fd;
char filename[64];
char vtuner_type;
if (argc == 2) {
vtuner_type = argv[1][0];
}
else {
fprintf(stderr, "usage %s a/t/c/s\n", argv[0]);
fprintf(stderr, " a = atsc\n t = dvb-t2\n c = dvb-c\n s = dvb-s2\n");
return EXIT_FAILURE;
}
sprintf(filename, "/dev/dvb/adapter0/frontend%d", newfrontend());
vtuner_fd = open("/dev/misc/vtuner0", O_RDWR);
if (vtuner_fd == -1) {
fprintf(stderr, "Can't open vtuner\n");
return EXIT_FAILURE;
}
if (vtuner_type == 's') {
fprintf(stderr, "Setting DVB-S vtuner\n");
setup_vtuner_dvb_s2(vtuner_fd);
}
else if (vtuner_type == 'c') {
fprintf(stderr, "Setting DVB-C vtuner\n");
setup_vtuner_dvb_c(vtuner_fd);
}
else if (vtuner_type == 't') {
fprintf(stderr, "Setting DVB-T vtuner\n");
setup_vtuner_dvb_t2(vtuner_fd);
}
else if (vtuner_type == 'a') {
fprintf(stderr, "Setting ATSC vtuner\n");
setup_vtuner_atsc(vtuner_fd);
}
else {
fprintf(stderr, "Not a valid vtuner type");
}
fprintf(stdout, "Displaying nim_sockets:\n");
system("cat /proc/bus/nim_sockets");
fprintf(stdout, "\n");
fprintf(stdout, "Check device/nim_sockets and press any key...\n");
getchar();
fe_fd = open(filename, O_RDWR);
if (fe_fd == -1) {
fprintf(stderr, "Can't open frontend %s\n", filename);
return EXIT_FAILURE;
}
read_delsys(fe_fd);
fprintf(stdout, "About to close frontend. Press any key...\n");
getchar();
close(fe_fd);
fprintf(stdout, "About to close vtuner. Press any key...\n");
getchar();
close(vtuner_fd);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment