static int tune_it(int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone, fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth, fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout) { int res, hi_lo, dfd; #ifdef HAVE_DVB_HEAD struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; #else FrontendParameters feparams; FrontendInfo fe_info; FrontendEvent event; struct secStatus sec_state; #endif mp_msg(MSGT_DEMUX, MSGL_V, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n", fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); memset(&feparams, 0, sizeof(feparams)); if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0)) { mp_msg(MSGT_DEMUX, MSGL_FATAL, "FE_GET_INFO FAILED\n"); return -1; } #ifdef HAVE_DVB_HEAD mp_msg(MSGT_DEMUX, MSGL_V, "Using DVB card \"%s\"\n", fe_info.name); #endif switch(fe_info.type) { case FE_OFDM: #ifdef HAVE_DVB_HEAD if (freq < 1000000) freq*=1000UL; feparams.frequency=freq; feparams.inversion=specInv; feparams.u.ofdm.bandwidth=bandwidth; feparams.u.ofdm.code_rate_HP=HP_CodeRate; feparams.u.ofdm.code_rate_LP=LP_CodeRate; feparams.u.ofdm.constellation=modulation; feparams.u.ofdm.transmission_mode=TransmissionMode; feparams.u.ofdm.guard_interval=guardInterval; feparams.u.ofdm.hierarchy_information=hier; #else if (freq < 1000000) freq*=1000UL; feparams.Frequency=freq; feparams.Inversion=specInv; feparams.u.ofdm.bandWidth=bandwidth; feparams.u.ofdm.HP_CodeRate=HP_CodeRate; feparams.u.ofdm.LP_CodeRate=LP_CodeRate; feparams.u.ofdm.Constellation=modulation; feparams.u.ofdm.TransmissionMode=TransmissionMode; feparams.u.ofdm.guardInterval=guardInterval; feparams.u.ofdm.HierarchyInformation=hier; #endif mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-T to %d Hz, bandwidth: %d\n",freq, bandwidth); break; case FE_QPSK: if (freq > 2200000) { // this must be an absolute frequency if (freq < SLOF) { #ifdef HAVE_DVB_HEAD freq = feparams.frequency=(freq-LOF1); #else freq = feparams.Frequency=(freq-LOF1); #endif hi_lo = 0; } else { #ifdef HAVE_DVB_HEAD freq = feparams.frequency=(freq-LOF2); #else freq = feparams.Frequency=(freq-LOF2); #endif hi_lo = 1; } } else { // this is an L-Band frequency #ifdef HAVE_DVB_HEAD feparams.frequency=freq; #else feparams.Frequency=freq; #endif } #ifdef HAVE_DVB_HEAD feparams.inversion=specInv; feparams.u.qpsk.symbol_rate=srate; feparams.u.qpsk.fec_inner=HP_CodeRate; dfd = fd_frontend; #else feparams.Inversion=specInv; feparams.u.qpsk.SymbolRate=srate; feparams.u.qpsk.FEC_inner=HP_CodeRate; dfd = fd_sec; #endif mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-S to Freq: %u, Pol: %c Srate: %d, 22kHz: %s, LNB: %d\n",freq,pol,srate,hi_lo ? "on" : "off", diseqc); if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0) mp_msg(MSGT_DEMUX, MSGL_V, "DISEQC SETTING SUCCEDED\n"); else { mp_msg(MSGT_DEMUX, MSGL_ERR, "DISEQC SETTING FAILED\n"); return -1; } break; case FE_QAM: mp_msg(MSGT_DEMUX, MSGL_V, "tuning DVB-C to %d, srate=%d\n",freq,srate); #ifdef HAVE_DVB_HEAD feparams.frequency=freq; feparams.inversion=specInv; feparams.u.qam.symbol_rate = srate; feparams.u.qam.fec_inner = HP_CodeRate; feparams.u.qam.modulation = modulation; #else feparams.Frequency=freq; feparams.Inversion=specInv; feparams.u.qam.SymbolRate = srate; feparams.u.qam.FEC_inner = HP_CodeRate; feparams.u.qam.QAM = modulation; #endif break; #ifdef DVB_ATSC case FE_ATSC: mp_msg(MSGT_DEMUX, MSGL_V, "tuning ATSC to %d, modulation=%d\n",freq,modulation); feparams.frequency=freq; feparams.u.vsb.modulation = modulation; break; #endif default: mp_msg(MSGT_DEMUX, MSGL_V, "Unknown FE type. Aborting\n"); return 0; } usleep(100000); #ifndef HAVE_DVB_HEAD if (fd_sec) SecGetStatus(fd_sec, &sec_state); while(1) { if(ioctl(fd_frontend, FE_GET_EVENT, &event) == -1) break; } #endif if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) { mp_msg(MSGT_DEMUX, MSGL_ERR, "ERROR tuning channel\n"); return -1; } return(check_status(fd_frontend, timeout)); }
static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone, fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth, fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout) { int hi_lo = 0, dfd; struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, pol %c, tone %i, specInv, diseqc %u, fe_modulation_t modulation,fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth\n", fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); memset(&feparams, 0, sizeof(feparams)); if ( ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0) { MP_FATAL(priv, "FE_GET_INFO FAILED\n"); return -1; } MP_VERBOSE(priv, "Using DVB card \"%s\"\n", fe_info.name); switch(fe_info.type) { case FE_OFDM: if (freq < 1000000) freq*=1000UL; feparams.frequency=freq; feparams.inversion=specInv; feparams.u.ofdm.bandwidth=bandwidth; feparams.u.ofdm.code_rate_HP=HP_CodeRate; feparams.u.ofdm.code_rate_LP=LP_CodeRate; feparams.u.ofdm.constellation=modulation; feparams.u.ofdm.transmission_mode=TransmissionMode; feparams.u.ofdm.guard_interval=guardInterval; feparams.u.ofdm.hierarchy_information=hier; MP_VERBOSE(priv, "tuning DVB-T to %d Hz, bandwidth: %d\n",freq, bandwidth); break; case FE_QPSK: if (freq > 2200000) { // this must be an absolute frequency if (freq < SLOF) { freq = feparams.frequency=(freq-LOF1); hi_lo = 0; } else { freq = feparams.frequency=(freq-LOF2); hi_lo = 1; } } else { // this is an L-Band frequency feparams.frequency=freq; } feparams.inversion=specInv; feparams.u.qpsk.symbol_rate=srate; feparams.u.qpsk.fec_inner=HP_CodeRate; dfd = fd_frontend; MP_VERBOSE(priv, "tuning DVB-S to Freq: %u, Pol: %c Srate: %d, 22kHz: %s, LNB: %d\n",freq,pol,srate,hi_lo ? "on" : "off", diseqc); if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0) MP_VERBOSE(priv, "DISEQC SETTING SUCCEDED\n"); else { MP_ERR(priv, "DISEQC SETTING FAILED\n"); return -1; } break; case FE_QAM: MP_VERBOSE(priv, "tuning DVB-C to %d, srate=%d\n",freq,srate); feparams.frequency=freq; feparams.inversion=specInv; feparams.u.qam.symbol_rate = srate; feparams.u.qam.fec_inner = HP_CodeRate; feparams.u.qam.modulation = modulation; break; #ifdef DVB_ATSC case FE_ATSC: MP_VERBOSE(priv, "tuning ATSC to %d, modulation=%d\n",freq,modulation); feparams.frequency=freq; feparams.u.vsb.modulation = modulation; break; #endif default: MP_VERBOSE(priv, "Unknown FE type. Aborting\n"); return 0; } usleep(100000); if(ioctl(fd_frontend,FE_SET_FRONTEND,&feparams) < 0) { MP_ERR(priv, "ERROR tuning channel\n"); return -1; } return check_status(priv, fd_frontend, timeout); }
int tune_it(int fd_frontend, unsigned int freq, unsigned int srate, char pol, int tone, fe_spectral_inversion_t specInv, unsigned char diseqc,fe_modulation_t modulation,fe_code_rate_t HP_CodeRate,fe_transmit_mode_t TransmissionMode,fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth, fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier) { int res, hi_lo, dfd; unsigned int base; struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; if ( (res = ioctl(fd_frontend,FE_GET_INFO, &fe_info) < 0)){ perror("FE_GET_INFO: "); return -1; } fprintf(stderr,"Using DVB card \"%s\", freq=%d\n",fe_info.name, freq); if (freq < 1000000) freq*=1000UL; switch(fe_info.type) { case FE_OFDM: feparams.frequency=freq; feparams.inversion=INVERSION_OFF; feparams.u.ofdm.bandwidth=bandwidth; feparams.u.ofdm.code_rate_HP=HP_CodeRate; feparams.u.ofdm.code_rate_LP=LP_CodeRate; feparams.u.ofdm.constellation=modulation; feparams.u.ofdm.transmission_mode=TransmissionMode; feparams.u.ofdm.guard_interval=guardInterval; feparams.u.ofdm.hierarchy_information=hier; fprintf(stderr,"tuning DVB-T (%s) to %d Hz, Bandwidth: %d\n",DVB_T_LOCATION,freq, bandwidth==BANDWIDTH_8_MHZ ? 8 : (bandwidth==BANDWIDTH_7_MHZ ? 7 : 6)); break; case FE_QPSK: pol = toupper(pol); if (freq > 2200000) { if (freq < SLOF) { feparams.frequency=(freq-LOF1); hi_lo = 0; base = LOF1; } else { feparams.frequency=(freq-LOF2); hi_lo = 1; base = LOF2; } } else { feparams.frequency=freq; base = 0; } fprintf(stderr,"tuning DVB-S to Freq: %u, Pol:%c Srate=%d, 22kHz tone=%s, LNB: %d\n",feparams.frequency,pol,srate,tone == SEC_TONE_ON ? "on" : "off", diseqc); feparams.inversion=specInv; feparams.u.qpsk.symbol_rate=srate; feparams.u.qpsk.fec_inner=FEC_AUTO; dfd = fd_frontend; if(do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0) fprintf(stderr, "DISEQC SETTING SUCCEDED\n"); else { fprintf(stderr, "DISEQC SETTING FAILED\n"); return -1; } break; case FE_QAM: fprintf(stderr,"tuning DVB-C to %d, srate=%d\n",freq,srate); feparams.frequency=freq; feparams.inversion=INVERSION_OFF; feparams.u.qam.symbol_rate = srate; feparams.u.qam.fec_inner = FEC_AUTO; feparams.u.qam.modulation = modulation; break; #ifdef DVB_ATSC case FE_ATSC: fprintf(stderr, "tuning ATSC to %d, modulation=%d\n",freq,modulation); feparams.frequency=freq; feparams.u.vsb.modulation = modulation; break; #endif default: fprintf(stderr,"Unknown FE type. Aborting\n"); exit(-1); } usleep(100000); return(check_status(fd_frontend,fe_info.type,&feparams,base)); }
bool tune_service_id(unsigned int adapter, unsigned int frontend, unsigned int timeout, uint16_t service_id, int* tuner_fd) { char fe_dev[PATH_MAX]; bool got_info; struct dvb_frontend_info fe_info; struct dvb_frontend_parameters current_params; struct dvb_frontend_parameters needed_params; char polarity; unsigned int sat_no; bool hi_lo; struct dvb_frontend_event event; // fe_status_t status; bool lock; /* need to keep the frontend device open to stop it untuning itself */ static int fe_fd = -1; static bool first_time = true; #if 0 if (*tuner_fd = -1) { fe_fd = -1; bool first_time = true; } #endif if(fe_fd < 0) { snprintf(fe_dev, sizeof(fe_dev), FE_DEVICE, adapter, frontend); /* * need O_RDWR if you want to tune, O_RDONLY is okay for getting info * if someone else is using the frontend, we can only open O_RDONLY * => we can still download data, but just not retune */ if((fe_fd = open(fe_dev, O_RDWR | O_NONBLOCK)) < 0) { error("Unable to open '%s' read/write; you will not be able to retune", fe_dev); if((fe_fd = open(fe_dev, O_RDONLY | O_NONBLOCK)) < 0) fatal("open '%s': %s", fe_dev, strerror(errno)); /* don't try to tune in */ first_time = false; } } vverbose("Getting frontend info"); do { /* maybe interrupted by a signal */ got_info = (ioctl(fe_fd, FE_GET_INFO, &fe_info) >= 0); if(!got_info && errno != EINTR) fatal("ioctl FE_GET_INFO: %s", strerror(errno)); } while(!got_info); /* see what we are currently tuned to */ if(ioctl(fe_fd, FE_GET_FRONTEND, ¤t_params) < 0) fatal("ioctl FE_GET_FRONTEND: %s", strerror(errno)); /* find the tuning params for the service */ if(!get_tune_params(fe_info.type, service_id, &needed_params, &polarity, &sat_no)) { error("service_id %u not found in channels.conf file", service_id); return false; } /* * if no-one was using the frontend when we open it * FE_GET_FRONTEND may say we are tuned to the frequency we want * but when we try to read any data, it fails * checking if we have a lock doesn't seem to work * so, always retune the first time we are called */ #if 0 if(ioctl(fe_fd, FE_READ_STATUS, &status) < 0) lock = false; else lock = status & FE_HAS_LOCK; #endif /* are we already tuned to the right frequency */ vverbose("Current frequency %u; needed %u; first_time=%d", current_params.frequency, needed_params.frequency, first_time); /* frequency resolution is up to 1 kHz */ if(first_time || abs(current_params.frequency - needed_params.frequency) >= ONE_kHz) { first_time = false; verbose("Retuning to frequency %u", needed_params.frequency); /* empty event queue */ while(ioctl(fe_fd, FE_GET_EVENT, &event) >= 0) ; /* do nothing */ /* do DISEQC (whatever that is) for DVB-S */ if(fe_info.type == FE_QPSK) { if(needed_params.frequency < SLOF) { needed_params.frequency -= LOF1; hi_lo = false; } else { needed_params.frequency -= LOF2; hi_lo = true; } if(do_diseqc(fe_fd, sat_no, polarity, hi_lo) < 0) error("DISEQC command failed for service_id %u", service_id); } /* tune in */ if(ioctl(fe_fd, FE_SET_FRONTEND, &needed_params) < 0) fatal("Unable to retune: ioctl FE_SET_FRONTEND: %s", strerror(errno)); /* wait for lock */ vverbose("Waiting for tuner to lock on"); /* TODO: use timeout value here */ struct timeval start, end; gettimeofday(&start, NULL); lock = false; while(!lock) { if(ioctl(fe_fd, FE_GET_EVENT, &event) >= 0) lock = event.status & FE_HAS_LOCK; gettimeofday(&end, NULL); if (end.tv_sec - start.tv_sec > 120) return false; } vverbose("Retuned"); } *tuner_fd = fe_fd; return true; }
static int tune_it(dvb_priv_t *priv, int fd_frontend, int fd_sec, unsigned int freq, unsigned int srate, char pol, int tone, bool is_dvb_s2, int stream_id, fe_spectral_inversion_t specInv, unsigned int diseqc, fe_modulation_t modulation, fe_code_rate_t HP_CodeRate, fe_transmit_mode_t TransmissionMode, fe_guard_interval_t guardInterval, fe_bandwidth_t bandwidth, fe_code_rate_t LP_CodeRate, fe_hierarchy_t hier, int timeout) { int hi_lo = 0, dfd; struct dvb_frontend_parameters feparams; struct dvb_frontend_info fe_info; MP_VERBOSE(priv, "TUNE_IT, fd_frontend %d, fd_sec %d\nfreq %lu, srate %lu, " "pol %c, tone %i, diseqc %u\n", fd_frontend, fd_sec, (long unsigned int)freq, (long unsigned int)srate, pol, tone, diseqc); memset(&feparams, 0, sizeof(feparams)); if (ioctl(fd_frontend, FE_GET_INFO, &fe_info) < 0) { MP_FATAL(priv, "FE_GET_INFO FAILED\n"); return -1; } MP_VERBOSE(priv, "Using DVB card \"%s\"\n", fe_info.name); { /* discard stale QPSK events */ struct dvb_frontend_event ev; while (true) { if (ioctl(fd_frontend, FE_GET_EVENT, &ev) == -1) break; } } switch (fe_info.type) { case FE_OFDM: if (freq < 1000000) freq *= 1000UL; feparams.frequency = freq; feparams.inversion = specInv; feparams.u.ofdm.bandwidth = bandwidth; feparams.u.ofdm.code_rate_HP = HP_CodeRate; feparams.u.ofdm.code_rate_LP = LP_CodeRate; feparams.u.ofdm.constellation = modulation; feparams.u.ofdm.transmission_mode = TransmissionMode; feparams.u.ofdm.guard_interval = guardInterval; feparams.u.ofdm.hierarchy_information = hier; MP_VERBOSE(priv, "tuning DVB-T to %d Hz, bandwidth: %d\n", freq, bandwidth); if (ioctl(fd_frontend, FE_SET_FRONTEND, &feparams) < 0) { MP_ERR(priv, "ERROR tuning channel\n"); return -1; } break; case FE_QPSK: // DVB-S if (freq > 2200000) { // this must be an absolute frequency if (freq < SLOF) { freq = feparams.frequency = (freq - LOF1); hi_lo = 0; } else { freq = feparams.frequency = (freq - LOF2); hi_lo = 1; } } else { // this is an L-Band frequency feparams.frequency = freq; } feparams.inversion = specInv; feparams.u.qpsk.symbol_rate = srate; feparams.u.qpsk.fec_inner = HP_CodeRate; dfd = fd_frontend; MP_VERBOSE(priv, "tuning DVB-S%sto Freq: %u, Pol: %c Srate: %d, " "22kHz: %s, LNB: %d\n", is_dvb_s2 ? "2 " : " ", freq, pol, srate, hi_lo ? "on" : "off", diseqc); if (do_diseqc(dfd, diseqc, (pol == 'V' ? 1 : 0), hi_lo) == 0) { MP_VERBOSE(priv, "DISEQC setting succeeded\n"); } else { MP_ERR(priv, "DISEQC setting failed\n"); return -1; } usleep(100000); #ifdef DVB_USE_S2API /* S2API is the DVB API new since 2.6.28. * It is needed to tune to new delivery systems, e.g. DVB-S2. * It takes a struct with a list of pairs of command + parameter. */ fe_delivery_system_t delsys = SYS_DVBS; if (is_dvb_s2) delsys = SYS_DVBS2; fe_rolloff_t rolloff = ROLLOFF_AUTO; struct dtv_property p[] = { { .cmd = DTV_DELIVERY_SYSTEM, .u.data = delsys }, { .cmd = DTV_FREQUENCY, .u.data = freq }, { .cmd = DTV_MODULATION, .u.data = modulation },