diff options
author | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-10-06 18:00:00 +0200 |
---|---|---|
committer | Klaus Schmidinger <kls (at) cadsoft (dot) de> | 2002-10-06 18:00:00 +0200 |
commit | 313e33539cd22fd571fc9a0f9f841173e9faebc4 (patch) | |
tree | 29b3031574b45c44e21bcfea6128fbbcd4f959da /dvbdevice.c | |
parent | d08073815d6d9132f7fb5cd9f82877967dc6b0e4 (diff) | |
download | vdr-patch-lnbsharing-313e33539cd22fd571fc9a0f9f841173e9faebc4.tar.gz vdr-patch-lnbsharing-313e33539cd22fd571fc9a0f9f841173e9faebc4.tar.bz2 |
Version 1.1.12vdr-1.1.12
- Fixed a missing Flush() call in the remote control learning procedure (thanks
to Oliver Endriss).
- Modified channel handling to cover all parameters necessary for DVB-C and DVB-T
(see man vdr(5) for the meaning of the additional parameters stored in the field
previously named 'polarisation'). Thanks to Uwe Scheffler and Andy Carter for testing.
If you have a system with different kinds of DVB cards, like DVB-T and DVB-C,
for instance, there is no more need to distinguish the channels through the
'Ca' parameter in order to assign them to the various DVB cards. This is now
taken care of by the "source" parameter. So a channel marked as "terrestrial",
for example, will only be received on DVB-T cards.
Note that the cChannel class has been moved into a separate file (channels.[ch]),
and that all data members have been made private and are now only accessible
through member functions. You may have to change any plugin code that accesses
cChannel data accordingly.
- The new configuration file 'sources.conf' contains the various signal sources
(satellites, cable and terrestrial) which are used in 'channels.conf' and
'diseqc.conf' (thanks to Reinhard Walter Buchner for adding some satellites to
'sources.conf' and Oliver Endriss and Lauri Tischler for testing and debugging).
- The 'diseqc' parameter in the channel definitions has been redefined to hold the
"source" of the given channel (which can be either a satellite, cable or terrestrial).
For compatibility with channels.conf files from older versions, numeric values in
this parameter will be tolerated, but they have no meaning. If you want to use
DiSEqC you will need to replace these old values with the proper source identifiers
defined in the new configuration file 'sources.conf'. See how this is done in the
'channels.conf' file that comes with the VDR package.
- The new configuration file 'diseqc.conf' can be used to set up the individual
diseqc configuration (see man vdr(5) for a description of the file format).
- The "Edit channel" menu has a new entry "Source:" in which the source of this
channel can be selected (either a satellite, cable or terrestrial). The set of
parameters at the end of this menu will change according to the type of source.
- The "Use DiSEqC" parameter in the "Setup/LNB" menu has been moved to the beginning
of the list and disables the rest of the parameters when set to "yes", since these
are now only meaningful if DiSEqC is _not_ used.
- Removed some unnecessary #includes from eit.c and changed cMenuRecordings::Del()
to cMenuRecordings::Delete() to avoid warnings in gcc-3.2 (thanks to Andreas
Schultz for pointing this out).
- Improved skipping channels that are (currently) not available (thanks to Stefan
Huelswitt).
- Updated channels.conf.terr and channels.conf.cable (thanks to Uwe Scheffler).
- Fixed a bug when pressing the "Blue" button in the main menu without having
displayed it (thanks to Oliver Endriss for reporting this one).
Diffstat (limited to 'dvbdevice.c')
-rw-r--r-- | dvbdevice.c | 282 |
1 files changed, 181 insertions, 101 deletions
diff --git a/dvbdevice.c b/dvbdevice.c index f337e35..eeaa7b0 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.21 2002/09/29 13:53:26 kls Exp $ + * $Id: dvbdevice.c 1.22 2002/10/06 09:07:45 kls Exp $ */ #include "dvbdevice.h" @@ -31,6 +31,8 @@ extern "C" { #endif #include <sys/ioctl.h> #include <sys/mman.h> +#include "channels.h" +#include "diseqc.h" #include "dvbosd.h" #include "player.h" #include "receiver.h" @@ -124,7 +126,9 @@ cDvbDevice::cDvbDevice(int n) else esyslog("ERROR: can't open DVB device %d", n); - frequency = 0; + source = -1; + frequency = -1; + diseqcCommands = NULL; } cDvbDevice::~cDvbDevice() @@ -344,18 +348,33 @@ bool cDvbDevice::SetPid(cPidHandle *Handle, int Type, bool On) return true; } +bool cDvbDevice::IsTunedTo(const cChannel *Channel) const +{ + return source == Channel->Source() && frequency == Channel->Frequency(); +} + +bool cDvbDevice::ProvidesSource(int Source) const +{ + int type = Source & cSource::st_Mask; + return type == cSource::stNone + || type == cSource::stCable && frontendType == FE_QAM + || type == cSource::stSat && frontendType == FE_QPSK + || type == cSource::stTerr && frontendType == FE_OFDM; + return true; +} + bool cDvbDevice::ProvidesChannel(const cChannel *Channel, int Priority, bool *NeedsDetachReceivers) const { bool result = false; bool hasPriority = Priority < 0 || Priority > this->Priority(); bool needsDetachReceivers = true; - if (ProvidesCa(Channel->ca)) { + if (ProvidesSource(Channel->Source()) && ProvidesCa(Channel->Ca())) { if (Receiving()) { - if (frequency == Channel->frequency) { + if (IsTunedTo(Channel)) { needsDetachReceivers = false; - if (!HasPid(Channel->vpid)) { - if (Channel->ca > CACONFBASE) { + if (!HasPid(Channel->Vpid())) { + if (Channel->Ca() > CACONFBASE) { needsDetachReceivers = true; result = hasPriority; } @@ -394,24 +413,24 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) LiveView = true; #endif - bool DoTune = frequency != Channel->frequency; // TODO will be changed when DiSEqC handling is revised + bool DoTune = !IsTunedTo(Channel); bool TurnOffLivePIDs = HasDecoder() && (DoTune - || Channel->ca > CACONFBASE && pidHandles[ptVideo].pid != Channel->vpid // CA channels can only be decrypted in "live" mode + || Channel->Ca() > CACONFBASE && pidHandles[ptVideo].pid != Channel->Vpid() // CA channels can only be decrypted in "live" mode || IsPrimaryDevice() && (LiveView // for a new live view the old PIDs need to be turned off - || pidHandles[ptVideo].pid == Channel->vpid // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER + || pidHandles[ptVideo].pid == Channel->Vpid() // for recording the PIDs must be shifted from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER ) ); bool StartTransferMode = IsPrimaryDevice() && !DoTune - && (LiveView && HasPid(Channel->vpid) && pidHandles[ptVideo].pid != Channel->vpid // the PID is already set as DMX_PES_OTHER - || !LiveView && pidHandles[ptVideo].pid == Channel->vpid // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER + && (LiveView && HasPid(Channel->Vpid()) && pidHandles[ptVideo].pid != Channel->Vpid() // the PID is already set as DMX_PES_OTHER + || !LiveView && pidHandles[ptVideo].pid == Channel->Vpid() // a recording is going to shift the PIDs from DMX_PES_AUDIO/VIDEO to DMX_PES_OTHER ); bool TurnOnLivePIDs = HasDecoder() && !StartTransferMode - && (Channel->ca > CACONFBASE // CA channels can only be decrypted in "live" mode + && (Channel->Ca() > CACONFBASE // CA channels can only be decrypted in "live" mode || LiveView ); @@ -452,67 +471,127 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) switch (frontendType) { case FE_QPSK: { // DVB-S - // Frequency offsets: - - unsigned int freq = Channel->frequency; - int tone = SEC_TONE_OFF; + unsigned int frequency = Channel->Frequency(); - if (freq < (unsigned int)Setup.LnbSLOF) { - freq -= Setup.LnbFrequLo; - tone = SEC_TONE_OFF; + if (Setup.DiSEqC) { + cDiseqc *diseqc = Diseqcs.Get(Channel->Source(), Channel->Frequency(), Channel->Polarization()); + if (diseqc) { + if (diseqc->Commands() && (!diseqcCommands || strcmp(diseqcCommands, diseqc->Commands()) != 0)) { +#ifndef NEWSTRUCT + int SecTone = SEC_TONE_OFF; + int SecVolt = SEC_VOLTAGE_13; +#endif + cDiseqc::eDiseqcActions da; + for (bool Start = true; (da = diseqc->Execute(Start)) != cDiseqc::daNone; Start = false) { + switch (da) { +#ifdef NEWSTRUCT + case cDiseqc::daNone: break; + case cDiseqc::daToneOff: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); break; + case cDiseqc::daToneOn: CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_ON)); break; + case cDiseqc::daVoltage13: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_13)); break; + case cDiseqc::daVoltage18: CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, SEC_VOLTAGE_18)); break; + case cDiseqc::daMiniA: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_A)); break; + case cDiseqc::daMiniB: CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, SEC_MINI_B)); break; + case cDiseqc::daCodes: { + int n = 0; + uchar *codes = diseqc->Codes(n); + if (codes) { + struct dvb_diseqc_master_cmd cmd; + memcpy(cmd.msg, codes, min(n, int(sizeof(cmd.msg)))); + cmd.msg_len = n; + CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); + } + } + break; +#else + // This may not work very good with the old driver. + // Let's try to emulate the NEWSTRUCT driver's behaviour as good as possible... + case cDiseqc::daNone: break; + case cDiseqc::daToneOff: CHECK(ioctl(fd_sec, SEC_SET_TONE, SecTone = SEC_TONE_OFF)); break; + case cDiseqc::daToneOn: CHECK(ioctl(fd_sec, SEC_SET_TONE, SecTone = SEC_TONE_ON)); break; + case cDiseqc::daVoltage13: CHECK(ioctl(fd_sec, SEC_SET_VOLTAGE, SecVolt = SEC_VOLTAGE_13)); break; + case cDiseqc::daVoltage18: CHECK(ioctl(fd_sec, SEC_SET_VOLTAGE, SecVolt = SEC_VOLTAGE_18)); break; + case cDiseqc::daMiniA: + case cDiseqc::daMiniB: { + secCmdSequence scmds; + memset(&scmds, 0, sizeof(scmds)); + scmds.voltage = SecVolt; + scmds.miniCommand = (da == cDiseqc::daMiniA) ? SEC_MINI_A : SEC_MINI_B; + scmds.continuousTone = SecTone; + CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); + } + break; + case cDiseqc::daCodes: { + int n = 0; + uchar *codes = diseqc->Codes(n); + if (codes && n >= 3 && codes[0] == 0xE0) { + secCommand scmd; + memset(&scmd, 0, sizeof(scmd)); + scmd.type = SEC_CMDTYPE_DISEQC; + scmd.u.diseqc.addr = codes[1]; + scmd.u.diseqc.cmd = codes[2]; + scmd.u.diseqc.numParams = n - 3; + memcpy(scmd.u.diseqc.params, &codes[3], min(n - 3, int(sizeof(scmd.u.diseqc.params)))); + + secCmdSequence scmds; + memset(&scmds, 0, sizeof(scmds)); + scmds.voltage = SecVolt; + scmds.miniCommand = SEC_MINI_NONE; + scmds.continuousTone = SecTone; + scmds.numCommands = 1; + scmds.commands = &scmd; + + CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); + } + } + break; +#endif + } + } + diseqcCommands = diseqc->Commands(); + } + frequency -= diseqc->Lof(); + } + else { + esyslog("ERROR: no DiSEqC parameters found for channel %d", Channel->Number()); + return false; + } } else { - freq -= Setup.LnbFrequHi; - tone = SEC_TONE_ON; - } - + int tone = SEC_TONE_OFF; + + if (frequency < (unsigned int)Setup.LnbSLOF) { + frequency -= Setup.LnbFrequLo; + tone = SEC_TONE_OFF; + } + else { + frequency -= Setup.LnbFrequHi; + tone = SEC_TONE_ON; + } + int volt = (Channel->Polarization() == 'v' || Channel->Polarization() == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18; #ifdef NEWSTRUCT - Frontend.frequency = freq * 1000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.qpsk.symbol_rate = Channel->srate * 1000UL; - Frontend.u.qpsk.fec_inner = FEC_AUTO; + CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt)); + CHECK(ioctl(fd_frontend, FE_SET_TONE, tone)); #else - Frontend.Frequency = freq * 1000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.qpsk.SymbolRate = Channel->srate * 1000UL; - Frontend.u.qpsk.FEC_inner = FEC_AUTO; + secCmdSequence scmds; + memset(&scmds, 0, sizeof(scmds)); + scmds.voltage = volt; + scmds.miniCommand = SEC_MINI_NONE; + scmds.continuousTone = tone; + CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); #endif - - int volt = (Channel->polarization == 'v' || Channel->polarization == 'V') ? SEC_VOLTAGE_13 : SEC_VOLTAGE_18; - - // DiSEqC: + } #ifdef NEWSTRUCT - struct dvb_diseqc_master_cmd cmd = { {0xE0, 0x10, 0x38, 0xF0, 0x00, 0x00}, 4}; - cmd.msg[3] = 0xF0 | (((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0)); - - if (Setup.DiSEqC) - CHECK(ioctl(fd_frontend, FE_SET_TONE, SEC_TONE_OFF)); - CHECK(ioctl(fd_frontend, FE_SET_VOLTAGE, volt)); - if (Setup.DiSEqC) { - usleep(15 * 1000); - CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd)); - usleep(15 * 1000); - CHECK(ioctl(fd_frontend, FE_DISEQC_SEND_BURST, (Channel->diseqc / 4) % 2 ? SEC_MINI_B : SEC_MINI_A)); - usleep(15 * 1000); - } - CHECK(ioctl(fd_frontend, FE_SET_TONE, tone)); + Frontend.frequency = frequency * 1000UL; + Frontend.inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.qpsk.symbol_rate = Channel->Srate() * 1000UL; + Frontend.u.qpsk.fec_inner = CodeRate(Channel->CoderateH()); #else - secCommand scmd; - scmd.type = 0; - scmd.u.diseqc.addr = 0x10; - scmd.u.diseqc.cmd = 0x38; - scmd.u.diseqc.numParams = 1; - scmd.u.diseqc.params[0] = 0xF0 | ((Channel->diseqc * 4) & 0x0F) | (tone == SEC_TONE_ON ? 1 : 0) | (volt == SEC_VOLTAGE_18 ? 2 : 0); - - secCmdSequence scmds; - scmds.voltage = volt; - scmds.miniCommand = SEC_MINI_NONE; - scmds.continuousTone = tone; - scmds.numCommands = Setup.DiSEqC ? 1 : 0; - scmds.commands = &scmd; - - CHECK(ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds)); + Frontend.Frequency = frequency * 1000UL; + Frontend.Inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.qpsk.SymbolRate = Channel->Srate() * 1000UL; + Frontend.u.qpsk.FEC_inner = CodeRate(Channel->CoderateH()); #endif } break; @@ -521,17 +600,17 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) // Frequency and symbol rate: #ifdef NEWSTRUCT - Frontend.frequency = Channel->frequency * 1000000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.qam.symbol_rate = Channel->srate * 1000UL; - Frontend.u.qam.fec_inner = FEC_AUTO; - Frontend.u.qam.modulation = QAM_64; + Frontend.frequency = Channel->Frequency() * 1000000UL; + Frontend.inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.qam.symbol_rate = Channel->Srate() * 1000UL; + Frontend.u.qam.fec_inner = CodeRate(Channel->CoderateH()); + Frontend.u.qam.modulation = Modulation(Channel->Modulation()); #else - Frontend.Frequency = Channel->frequency * 1000000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.qam.SymbolRate = Channel->srate * 1000UL; - Frontend.u.qam.FEC_inner = FEC_AUTO; - Frontend.u.qam.QAM = QAM_64; + Frontend.Frequency = Channel->Frequency() * 1000000UL; + Frontend.Inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.qam.SymbolRate = Channel->Srate() * 1000UL; + Frontend.u.qam.FEC_inner = CodeRate(Channel->CoderateH()); + Frontend.u.qam.QAM = Modulation(Channel->Modulation()); #endif } break; @@ -540,25 +619,25 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) // Frequency and OFDM paramaters: #ifdef NEWSTRUCT - Frontend.frequency = Channel->frequency * 1000UL; - Frontend.inversion = INVERSION_AUTO; - Frontend.u.ofdm.bandwidth=BANDWIDTH_8_MHZ; - Frontend.u.ofdm.code_rate_HP = FEC_2_3; - Frontend.u.ofdm.code_rate_LP = FEC_1_2; - Frontend.u.ofdm.constellation = QAM_64; - Frontend.u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; - Frontend.u.ofdm.guard_interval = GUARD_INTERVAL_1_32; - Frontend.u.ofdm.hierarchy_information = HIERARCHY_NONE; + Frontend.frequency = Channel->Frequency() * 1000UL; + Frontend.inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.ofdm.bandwidth = BandWidth(Channel->Bandwidth()); + Frontend.u.ofdm.code_rate_HP = CodeRate(Channel->CoderateH()); + Frontend.u.ofdm.code_rate_LP = CodeRate(Channel->CoderateL()); + Frontend.u.ofdm.constellation = Modulation(Channel->Modulation()); + Frontend.u.ofdm.transmission_mode = TransmitMode(Channel->Transmission()); + Frontend.u.ofdm.guard_interval = GuardInterval(Channel->Guard()); + Frontend.u.ofdm.hierarchy_information = Hierarchy(Channel->Hierarchy()); #else - Frontend.Frequency = Channel->frequency * 1000UL; - Frontend.Inversion = INVERSION_AUTO; - Frontend.u.ofdm.bandWidth=BANDWIDTH_8_MHZ; - Frontend.u.ofdm.HP_CodeRate=FEC_2_3; - Frontend.u.ofdm.LP_CodeRate=FEC_1_2; - Frontend.u.ofdm.Constellation=QAM_64; - Frontend.u.ofdm.TransmissionMode=TRANSMISSION_MODE_2K; - Frontend.u.ofdm.guardInterval=GUARD_INTERVAL_1_32; - Frontend.u.ofdm.HierarchyInformation=HIERARCHY_NONE; + Frontend.Frequency = Channel->Frequency() * 1000UL; + Frontend.Inversion = SpectralInversion(Channel->Inversion()); + Frontend.u.ofdm.bandWidth = BandWidth(Channel->Bandwidth()); + Frontend.u.ofdm.HP_CodeRate = CodeRate(Channel->CoderateH()); + Frontend.u.ofdm.LP_CodeRate = CodeRate(Channel->CoderateL()); + Frontend.u.ofdm.Constellation = Modulation(Channel->Modulation()); + Frontend.u.ofdm.TransmissionMode = TransmitMode(Channel->Transmission()); + Frontend.u.ofdm.guardInterval = GuardInterval(Channel->Guard()); + Frontend.u.ofdm.HierarchyInformation = Hierarchy(Channel->Hierarchy()); #endif } break; @@ -592,7 +671,7 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) usleep(10 * 1000); } if (!(status & FE_HAS_LOCK)) { - esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->number, CardIndex() + 1); + esyslog("ERROR: channel %d not locked on DVB card %d!", Channel->Number(), CardIndex() + 1); if (LiveView && IsPrimaryDevice()) cThread::RaisePanic(); return false; @@ -602,43 +681,44 @@ bool cDvbDevice::SetChannelDevice(const cChannel *Channel, bool LiveView) FrontendEvent event; if (ioctl(fd_frontend, FE_GET_EVENT, &event) >= 0) { if (event.type != FE_COMPLETION_EV) { - esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->number, CardIndex() + 1); + esyslog("ERROR: channel %d not sync'ed on DVB card %d!", Channel->Number(), CardIndex() + 1); if (LiveView && IsPrimaryDevice()) cThread::RaisePanic(); return false; } } else - esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->number, CardIndex() + 1); + esyslog("ERROR in frontend get event (channel %d, card %d): %m", Channel->Number(), CardIndex() + 1); } else esyslog("ERROR: timeout while tuning on DVB card %d", CardIndex() + 1); #endif - frequency = Channel->frequency; + source = Channel->Source(); + frequency = Channel->Frequency(); } // PID settings: if (TurnOnLivePIDs) { - if (!(AddPid(Channel->apid1, ptAudio) && AddPid(Channel->vpid, ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached) - esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->number, CardIndex() + 1); + if (!(AddPid(Channel->Apid1(), ptAudio) && AddPid(Channel->Vpid(), ptVideo))) {//XXX+ dolby dpid1!!! (if audio plugins are attached) + esyslog("ERROR: failed to set PIDs for channel %d on device %d", Channel->Number(), CardIndex() + 1); return false; } if (IsPrimaryDevice()) - AddPid(Channel->tpid, ptTeletext); + AddPid(Channel->Tpid(), ptTeletext); CHECK(ioctl(fd_audio, AUDIO_SET_AV_SYNC, true)); CHECK(ioctl(fd_audio, AUDIO_SET_MUTE, false)); CHECK(ioctl(fd_video, VIDEO_SET_BLANK, false)); } else if (StartTransferMode) - cControl::Launch(new cTransferControl(this, Channel->vpid, Channel->apid1, 0, 0, 0)); + cControl::Launch(new cTransferControl(this, Channel->Vpid(), Channel->Apid1(), 0, 0, 0)); // Start setting system time: if (siProcessor) - siProcessor->SetCurrentTransponder(Channel->frequency); + siProcessor->SetCurrentTransponder(Channel->Frequency()); return true; } |