From: Andreas Monzner Date: Sat, 2 Jul 2005 09:27:18 +0000 (+0000) Subject: add missing files, add ability to specify table_id mask and table_id ext mask X-Git-Tag: 2.6.0~5816 X-Git-Url: https://git.cweiske.de/enigma2.git/commitdiff_plain/a8310a1a7345577916560e789cdb8c1712e620a9?hp=a33ff213255db7f59090f70235ec06c502e2a2ce add missing files, add ability to specify table_id mask and table_id ext mask --- diff --git a/lib/dvb/dvbtime.cpp b/lib/dvb/dvbtime.cpp new file mode 100644 index 00000000..84a1ef4b --- /dev/null +++ b/lib/dvb/dvbtime.cpp @@ -0,0 +1,407 @@ +#include +#include + +#include +#include +#include +#include +#include + +// defines for DM7000 / DM7020 +#define FP_IOCTL_SET_RTC 0x101 +#define FP_IOCTL_GET_RTC 0x102 + +static time_t prev_time; + +void setRTC(time_t time) +{ + int fd = open("/dev/dbox/fp0", O_RDWR); + if ( fd >= 0 ) + { + if ( ::ioctl(fd, FP_IOCTL_SET_RTC, (void*)&time ) < 0 ) + eDebug("FP_IOCTL_SET_RTC failed(%m)"); + else + prev_time = time; + close(fd); + } +} + +time_t getRTC() +{ + time_t rtc_time=0; + int fd = open("/dev/dbox/fp0", O_RDWR); + if ( fd >= 0 ) + { + if ( ::ioctl(fd, FP_IOCTL_GET_RTC, (void*)&rtc_time ) < 0 ) + eDebug("FP_IOCTL_GET_RTC failed(%m)"); + close(fd); + } + return rtc_time != prev_time ? rtc_time : 0; +} + +int fromBCD(int bcd) +{ + if ((bcd&0xF0)>=0xA0) + return -1; + if ((bcd&0xF)>=0xA) + return -1; + return ((bcd&0xF0)>>4)*10+(bcd&0xF); +} + +time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5) +{ + tm t; + t.tm_sec=fromBCD(t5); + t.tm_min=fromBCD(t4); + t.tm_hour=fromBCD(t3); + int mjd=(t1<<8)|t2; + int k; + + t.tm_year = (int) ((mjd - 15078.2) / 365.25); + t.tm_mon = (int) ((mjd - 14956.1 - (int)(t.tm_year * 365.25)) / 30.6001); + t.tm_mday = (int) (mjd - 14956 - (int)(t.tm_year * 365.25) - (int)(t.tm_mon * 30.6001)); + k = (t.tm_mon == 14 || t.tm_mon == 15) ? 1 : 0; + t.tm_year = t.tm_year + k; + t.tm_mon = t.tm_mon - 1 - k * 12; + t.tm_mon--; + + t.tm_isdst = 0; + t.tm_gmtoff = 0; + + return timegm(&t); +} + +TDT::TDT(eDVBChannel *chan) + :chan(chan) +{ + CONNECT(tableReady, TDT::ready); + CONNECT(m_interval_timer.timeout, TDT::start); + if (chan) + chan->getDemux(demux); +} + +void TDT::ready(int error) +{ + eDVBLocalTimeHandler::getInstance()->updateTime(error, chan); +} + +int TDT::createTable(int nr, const __u8 *data, unsigned int max) +{ + if ( data && data[0] == 0x70 || data[0] == 0x73 ) + { + int length = ((data[1] & 0x0F) << 8) | data[2]; + if ( length >= 8 ) + { + time_t tptime = parseDVBtime(data[3], data[4], data[5], data[6], data[7]); + eDVBLocalTimeHandler::getInstance()->updateTime(tptime, chan); + error=0; + return 1; + } + } + return 0; +} + +void TDT::start() +{ + if ( chan ) + { + eDVBTableSpec spec; + spec.pid = TimeAndDateTable::PID; + spec.tid = TimeAndDateTable::TID; + spec.tid_mask = 0xFC; + spec.timeout = TimeAndDateTable::TIMEOUT; + spec.flags= eDVBTableSpec::tfAnyVersion | + eDVBTableSpec::tfHaveTID | + eDVBTableSpec::tfHaveTIDMask | + eDVBTableSpec::tfCheckCRC | + eDVBTableSpec::tfHaveTimeout; + if ( demux ) + eGTable::start( demux, spec ); + } +} + +void TDT::startTimer( int interval ) +{ + m_interval_timer.start(interval, true); +} + +eDVBLocalTimeHandler *eDVBLocalTimeHandler::instance; +DEFINE_REF(eDVBLocalTimeHandler); + +eDVBLocalTimeHandler::eDVBLocalTimeHandler() + :m_time_ready(false), m_time_difference(0) +{ + if ( !instance ) + instance=this; + ePtr res_mgr; + eDVBResourceManager::getInstance(res_mgr); + if (!res_mgr) + eDebug("[eDVBLocalTimerHandler] no resource manager !!!!!!!"); + else + { + res_mgr->connectChannelAdded(slot(*this,&eDVBLocalTimeHandler::DVBChannelAdded), m_chanAddedConn); + res_mgr->connectChannelRemoved(slot(*this,&eDVBLocalTimeHandler::DVBChannelRemoved), m_chanRemovedConn); + res_mgr->connectChannelRunning(slot(*this,&eDVBLocalTimeHandler::DVBChannelRunning), m_chanRunningConn); + } +} + +eDVBLocalTimeHandler::~eDVBLocalTimeHandler() +{ + instance=0; + for (std::map::iterator it=m_active_tables.begin(); it != m_active_tables.end(); ++it) + delete it->second; +} + +void eDVBLocalTimeHandler::readTimeOffsetData( const char* filename ) +{ + m_timeOffsetMap.clear(); + FILE *f=fopen(filename, "r"); + if (!f) + return; + char line[256]; + fgets(line, 256, f); + while (true) + { + if (!fgets( line, 256, f )) + break; + if (strstr(line, "Transponder UTC Time Offsets\n")) + continue; + int dvbnamespace,tsid,onid,offs; + if ( sscanf( line, "%08x,%04x,%04x:%d\n",&dvbnamespace,&tsid,&onid,&offs ) == 4 ) + m_timeOffsetMap[eDVBChannelID(dvbnamespace,tsid,onid)]=offs; + } + fclose(f); +} + +void eDVBLocalTimeHandler::writeTimeOffsetData( const char* filename ) +{ + FILE *f=fopen(filename, "w+"); + if ( f ) + { + fprintf(f, "Transponder UTC Time Offsets\n"); + for ( std::map::iterator it ( m_timeOffsetMap.begin() ); it != m_timeOffsetMap.end(); ++it ) + fprintf(f, "%08x,%04x,%04x:%d\n", + it->first.dvbnamespace.get(), + it->first.transport_stream_id.get(), it->first.original_network_id.get(), it->second ); + fclose(f); + } +} + +void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan ) +{ + bool restart_tdt = false; + if (!tp_time ) + restart_tdt = true; + else if (tp_time == -1) + { + restart_tdt = true; + /*if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 || + ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7000 + && eSystemInfo::getInstance()->hasStandbyWakeupTimer() ) ) TODO !!!!!!! */ + { + eDebug("[eDVBLocalTimerHandler] no transponder tuned... or no TDT/TOT avail .. try to use RTC :)"); + time_t rtc_time = getRTC(); + if ( rtc_time ) // RTC Ready? + { + tm now = *localtime(&rtc_time); + eDebug("[eDVBLocalTimerHandler] RTC time is %02d:%02d:%02d", + now.tm_hour, + now.tm_min, + now.tm_sec); + time_t linuxTime=time(0); + time_t nowTime=linuxTime+m_time_difference; + now = *localtime(&nowTime); + eDebug("[eDVBLocalTimerHandler] Receiver time is %02d:%02d:%02d", + now.tm_hour, + now.tm_min, + now.tm_sec); + m_time_difference = rtc_time - linuxTime; + eDebug("[eDVBLocalTimerHandler] RTC to Receiver time difference is %d seconds", nowTime - rtc_time ); + if ( abs(m_time_difference) > 59 ) + { + eDebug("[eDVBLocalTimerHandler] set Linux Time to RTC Time"); + timeval tnow; + gettimeofday(&tnow,0); + tnow.tv_sec=rtc_time; + settimeofday(&tnow,0); + for (ePtrList::iterator it(eMainloop::existing_loops) + ;it != eMainloop::existing_loops.end(); ++it) + it->setTimerOffset(m_time_difference); + m_time_difference=0; + } + else if ( !m_time_difference ) + eDebug("[eDVBLocalTimerHandler] no change needed"); + else + eDebug("[eDVBLocalTimerHandler] set to RTC time"); + /*emit*/ m_timeUpdated(); + } + else + eDebug("[eDVBLocalTimerHandler] shit RTC not ready :("); + } + } + else + { + std::map< eDVBChannelID, int >::iterator it( m_timeOffsetMap.find( chan->getChannelID() ) ); + + // current linux time + time_t linuxTime = time(0); + + // current enigma time + time_t nowTime=linuxTime+m_time_difference; + + // difference between current enigma time and transponder time + int enigma_diff = tp_time-nowTime; + + int new_diff=0; + + if ( m_time_ready ) // ref time ready? + { + // difference between reference time (current enigma time) + // and the transponder time + eDebug("[eDVBLocalTimerHandler] diff is %d", enigma_diff); + if ( abs(enigma_diff) < 120 ) + { + eDebug("[eDVBLocalTimerHandler] diff < 120 .. use Transponder Time"); + m_timeOffsetMap[chan->getChannelID()] = 0; + new_diff = enigma_diff; + } + else if ( it != m_timeOffsetMap.end() ) // correction saved? + { + eDebug("[eDVBLocalTimerHandler] we have correction %d", it->second); + time_t CorrectedTpTime = tp_time+it->second; + int ddiff = CorrectedTpTime-nowTime; + eDebug("[eDVBLocalTimerHandler] diff after add correction is %d", ddiff); + if ( abs(it->second) < 300 ) // stored correction < 5 min + { + eDebug("[eDVBLocalTimerHandler] use stored correction(<5 min)"); + new_diff = ddiff; + } + else if ( /*eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 && TODO !!!*/ + getRTC() ) + { + time_t rtc=getRTC(); + m_timeOffsetMap[chan->getChannelID()] = rtc-tp_time; + new_diff = rtc-nowTime; // set enigma time to rtc + eDebug("[eDVBLocalTimerHandler] update stored correction to %d (calced against RTC time)", rtc-tp_time ); + } + else if ( abs(ddiff) <= 120 ) + { +// with stored correction calced time difference is lower 2 min +// this don't help when a transponder have a clock running to slow or to fast +// then its better to have a DM7020 with always running RTC + eDebug("[eDVBLocalTimerHandler] use stored correction(corr < 2 min)"); + new_diff = ddiff; + } + else // big change in calced correction.. hold current time and update correction + { + eDebug("[eDVBLocalTimerHandler] update stored correction to %d", -enigma_diff); + m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; + } + } + else + { + eDebug("[eDVBLocalTimerHandler] no correction found... store calced correction(%d)",-enigma_diff); + m_timeOffsetMap[chan->getChannelID()] = -enigma_diff; + } + } + else // no time setted yet + { + if ( it != m_timeOffsetMap.end() ) + { + enigma_diff += it->second; + eDebug("[eDVBLocalTimerHandler] we have correction (%d)... use", it->second ); + } + else + eDebug("[eDVBLocalTimerHandler] dont have correction.. set Transponder Diff"); + new_diff=enigma_diff; + m_time_ready=true; + } + + time_t t = nowTime+new_diff; + m_last_tp_time_difference=tp_time-t; + + if (!new_diff) + { + eDebug("[eDVBLocalTimerHandler] not changed"); + return; + } + + tm now = *localtime(&t); + eDebug("[eDVBLocalTimerHandler] time update to %02d:%02d:%02d", + now.tm_hour, + now.tm_min, + now.tm_sec); + + m_time_difference = t - linuxTime; // calc our new linux_time -> enigma_time correction + eDebug("[eDVBLocalTimerHandler] m_time_difference is %d", m_time_difference ); + +// if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 ) TODO !! + setRTC(t); + + if ( abs(m_time_difference) > 59 ) + { + eDebug("[eDVBLocalTimerHandler] set Linux Time"); + timeval tnow; + gettimeofday(&tnow,0); + tnow.tv_sec=t; + settimeofday(&tnow,0); + for (ePtrList::iterator it(eMainloop::existing_loops) + ;it != eMainloop::existing_loops.end(); ++it) + it->setTimerOffset(m_time_difference); + m_time_difference=0; + } + + /*emit*/ m_timeUpdated(); + } + + if ( restart_tdt ) + { + std::map::iterator it = + m_active_tables.find(chan); + if ( it != m_active_tables.end() ) + { + delete it->second; + it->second = new TDT(chan); + it->second->startTimer(60*60*1000); // restart TDT for this transponder in 60min + } + } + +} + +void eDVBLocalTimeHandler::DVBChannelAdded(eDVBChannel *chan) +{ + eDebug("[eDVBLocalTimerHandler] add channel %p", chan); + if ( chan ) + { + std::map::iterator it = + m_active_tables.find(chan); + if ( it != m_active_tables.end() ) + { + delete it->second; + it->second = new TDT(chan); + } + else + m_active_tables[chan] = new TDT(chan); + } +} + +void eDVBLocalTimeHandler::DVBChannelRemoved(eDVBChannel *chan) +{ + eDebug("[eDVBLocalTimerHandler] remove channel %p", chan); + std::map::iterator it = + m_active_tables.find(chan); + if ( it != m_active_tables.end() ) + { + delete it->second; + m_active_tables.erase(it); + } +} + +void eDVBLocalTimeHandler::DVBChannelRunning(iDVBChannel *chan) +{ + eDebug("[eDVBLocalTimerHandler] start channel %p", chan); + std::map::iterator it = + m_active_tables.find(chan); + if ( it != m_active_tables.end() ) + it->second->start(); +} diff --git a/lib/dvb/dvbtime.h b/lib/dvb/dvbtime.h new file mode 100644 index 00000000..a1746b5e --- /dev/null +++ b/lib/dvb/dvbtime.h @@ -0,0 +1,53 @@ +#ifndef __LIB_DVB_DVBTIME_H_ +#define __LIB_DVB_DVBTIME_H_ + +#include +#include +#include + +class eDVBChannel; + +time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5); + +class TDT: public eGTable +{ + eDVBChannel *chan; + ePtr demux; + eTimer m_interval_timer; + int createTable(int nr, const __u8 *data, unsigned int max); + void ready(int); +public: + TDT(eDVBChannel *chan); + void start(); + void startTimer(int interval); +}; + +class eDVBLocalTimeHandler: public Object +{ + friend class TDT; + DECLARE_REF(eDVBLocalTimeHandler) + std::map m_active_tables; + std::map m_timeOffsetMap; + ePtr m_chanAddedConn; + ePtr m_chanRemovedConn; + ePtr m_chanRunningConn; + bool m_time_ready; + int m_time_difference; + int m_last_tp_time_difference; + void DVBChannelAdded(eDVBChannel*); + void DVBChannelRemoved(eDVBChannel*); + void DVBChannelRunning(iDVBChannel*); + void readTimeOffsetData(const char*); + void writeTimeOffsetData(const char*); + void updateTime(time_t tp_time, eDVBChannel*); + static eDVBLocalTimeHandler *instance; +public: + PSignal0 m_timeUpdated; + eDVBLocalTimeHandler(); + ~eDVBLocalTimeHandler(); + bool ready() { return m_time_ready; } + int difference() { return m_time_difference; } + static eDVBLocalTimeHandler *getInstance() { return instance; } +}; + +#endif // __LIB_DVB_DVBTIME_H_ diff --git a/lib/dvb/esection.cpp b/lib/dvb/esection.cpp index a80168b5..78db9015 100644 --- a/lib/dvb/esection.cpp +++ b/lib/dvb/esection.cpp @@ -57,15 +57,26 @@ RESULT eGTable::start(iDVBSectionReader *reader, const eDVBTableSpec &table) if (m_table.flags & eDVBTableSpec::tfHaveTID) { mask.data[0] = m_table.tid; - mask.mask[0] = mask.pid == 0x14 ? 0xFC : 0xFF; + if (m_table.flags & eDVBTableSpec::tfHaveTIDMask) + mask.mask[0] = m_table.tid_mask; + else + mask.mask[0] = 0xFF; } - + if (m_table.flags & eDVBTableSpec::tfHaveTIDExt) { mask.data[1] = m_table.tidext >> 8; mask.data[2] = m_table.tidext; - mask.mask[1] = 0xFF; - mask.mask[2] = 0xFF; + if (m_table.flags & eDVBTableSpec::tfHaveTIDExtMask) + { + mask.mask[1] = m_table.tidext_mask >> 8; + mask.mask[2] = m_table.tidext_mask; + } + else + { + mask.mask[1] = 0xFF; + mask.mask[2] = 0xFF; + } } if (!(m_table.flags & eDVBTableSpec::tfAnyVersion)) diff --git a/lib/dvb/idemux.h b/lib/dvb/idemux.h index 9267d005..e48c5d9a 100644 --- a/lib/dvb/idemux.h +++ b/lib/dvb/idemux.h @@ -21,7 +21,7 @@ struct eDVBSectionFilterMask struct eDVBTableSpec { - int pid, tid, tidext; + int pid, tid, tidext, tid_mask, tidext_mask; int version; int timeout; /* timeout in ms */ enum @@ -38,6 +38,8 @@ struct eDVBTableSpec tfHaveTIDExt=16, tfCheckCRC=32, tfHaveTimeout=64, + tfHaveTIDMask=128, + tfHaveTIDExtMask=256 }; int flags; }; diff --git a/lib/dvb/isection.h b/lib/dvb/isection.h index 1ed53699..5a0c5cf4 100644 --- a/lib/dvb/isection.h +++ b/lib/dvb/isection.h @@ -21,7 +21,7 @@ struct eDVBSectionFilterMask struct eDVBTableSpec { - int pid, tid, tidext; + int pid, tid, tidext, tid_mask, tidext_mask; int version; int timeout; /* timeout in ms */ enum @@ -38,6 +38,8 @@ struct eDVBTableSpec tfHaveTIDExt=16, tfCheckCRC=32, tfHaveTimeout=64, + tfHaveTIDMask=128, + tfHaveTIDExtMask=256 }; int flags; };