1 #include <lib/dvb/dvbtime.h>
2 #include <lib/dvb/dvb.h>
10 // defines for DM7000 / DM7020
11 #define FP_IOCTL_SET_RTC 0x101
12 #define FP_IOCTL_GET_RTC 0x102
14 static time_t prev_time;
16 void setRTC(time_t time)
18 int fd = open("/dev/dbox/fp0", O_RDWR);
21 if ( ::ioctl(fd, FP_IOCTL_SET_RTC, (void*)&time ) < 0 )
22 eDebug("FP_IOCTL_SET_RTC failed(%m)");
32 int fd = open("/dev/dbox/fp0", O_RDWR);
35 if ( ::ioctl(fd, FP_IOCTL_GET_RTC, (void*)&rtc_time ) < 0 )
36 eDebug("FP_IOCTL_GET_RTC failed(%m)");
39 return rtc_time != prev_time ? rtc_time : 0;
48 return ((bcd&0xF0)>>4)*10+(bcd&0xF);
51 time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5)
56 t.tm_hour=fromBCD(t3);
60 t.tm_year = (int) ((mjd - 15078.2) / 365.25);
61 t.tm_mon = (int) ((mjd - 14956.1 - (int)(t.tm_year * 365.25)) / 30.6001);
62 t.tm_mday = (int) (mjd - 14956 - (int)(t.tm_year * 365.25) - (int)(t.tm_mon * 30.6001));
63 k = (t.tm_mon == 14 || t.tm_mon == 15) ? 1 : 0;
64 t.tm_year = t.tm_year + k;
65 t.tm_mon = t.tm_mon - 1 - k * 12;
74 TDT::TDT(eDVBChannel *chan)
77 CONNECT(tableReady, TDT::ready);
78 CONNECT(m_interval_timer.timeout, TDT::start);
80 chan->getDemux(demux);
83 void TDT::ready(int error)
85 eDVBLocalTimeHandler::getInstance()->updateTime(error, chan);
88 int TDT::createTable(int nr, const __u8 *data, unsigned int max)
90 if ( data && data[0] == 0x70 || data[0] == 0x73 )
92 int length = ((data[1] & 0x0F) << 8) | data[2];
95 time_t tptime = parseDVBtime(data[3], data[4], data[5], data[6], data[7]);
96 eDVBLocalTimeHandler::getInstance()->updateTime(tptime, chan);
109 spec.pid = TimeAndDateTable::PID;
110 spec.tid = TimeAndDateTable::TID;
111 spec.tid_mask = 0xFC;
112 spec.timeout = TimeAndDateTable::TIMEOUT;
113 spec.flags= eDVBTableSpec::tfAnyVersion |
114 eDVBTableSpec::tfHaveTID |
115 eDVBTableSpec::tfHaveTIDMask |
116 eDVBTableSpec::tfCheckCRC |
117 eDVBTableSpec::tfHaveTimeout;
119 eGTable::start( demux, spec );
123 void TDT::startTimer( int interval )
125 m_interval_timer.start(interval, true);
128 eDVBLocalTimeHandler *eDVBLocalTimeHandler::instance;
129 DEFINE_REF(eDVBLocalTimeHandler);
131 eDVBLocalTimeHandler::eDVBLocalTimeHandler()
132 :m_time_ready(false), m_time_difference(0)
136 ePtr<eDVBResourceManager> res_mgr;
137 eDVBResourceManager::getInstance(res_mgr);
139 eDebug("[eDVBLocalTimerHandler] no resource manager !!!!!!!");
142 res_mgr->connectChannelAdded(slot(*this,&eDVBLocalTimeHandler::DVBChannelAdded), m_chanAddedConn);
143 res_mgr->connectChannelRemoved(slot(*this,&eDVBLocalTimeHandler::DVBChannelRemoved), m_chanRemovedConn);
144 res_mgr->connectChannelRunning(slot(*this,&eDVBLocalTimeHandler::DVBChannelRunning), m_chanRunningConn);
148 eDVBLocalTimeHandler::~eDVBLocalTimeHandler()
151 for (std::map<iDVBChannel*, TDT*>::iterator it=m_active_tables.begin(); it != m_active_tables.end(); ++it)
155 void eDVBLocalTimeHandler::readTimeOffsetData( const char* filename )
157 m_timeOffsetMap.clear();
158 FILE *f=fopen(filename, "r");
165 if (!fgets( line, 256, f ))
167 if (strstr(line, "Transponder UTC Time Offsets\n"))
169 int dvbnamespace,tsid,onid,offs;
170 if ( sscanf( line, "%08x,%04x,%04x:%d\n",&dvbnamespace,&tsid,&onid,&offs ) == 4 )
171 m_timeOffsetMap[eDVBChannelID(dvbnamespace,tsid,onid)]=offs;
176 void eDVBLocalTimeHandler::writeTimeOffsetData( const char* filename )
178 FILE *f=fopen(filename, "w+");
181 fprintf(f, "Transponder UTC Time Offsets\n");
182 for ( std::map<eDVBChannelID,int>::iterator it ( m_timeOffsetMap.begin() ); it != m_timeOffsetMap.end(); ++it )
183 fprintf(f, "%08x,%04x,%04x:%d\n",
184 it->first.dvbnamespace.get(),
185 it->first.transport_stream_id.get(), it->first.original_network_id.get(), it->second );
190 void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan )
192 bool restart_tdt = false;
195 else if (tp_time == -1)
198 /*if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 ||
199 ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7000
200 && eSystemInfo::getInstance()->hasStandbyWakeupTimer() ) ) TODO !!!!!!! */
202 eDebug("[eDVBLocalTimerHandler] no transponder tuned... or no TDT/TOT avail .. try to use RTC :)");
203 time_t rtc_time = getRTC();
204 if ( rtc_time ) // RTC Ready?
206 tm now = *localtime(&rtc_time);
207 eDebug("[eDVBLocalTimerHandler] RTC time is %02d:%02d:%02d",
211 time_t linuxTime=time(0);
212 time_t nowTime=linuxTime+m_time_difference;
213 now = *localtime(&nowTime);
214 eDebug("[eDVBLocalTimerHandler] Receiver time is %02d:%02d:%02d",
218 m_time_difference = rtc_time - linuxTime;
219 eDebug("[eDVBLocalTimerHandler] RTC to Receiver time difference is %d seconds", nowTime - rtc_time );
220 if ( abs(m_time_difference) > 59 )
222 eDebug("[eDVBLocalTimerHandler] set Linux Time to RTC Time");
224 gettimeofday(&tnow,0);
225 tnow.tv_sec=rtc_time;
226 settimeofday(&tnow,0);
227 for (ePtrList<eMainloop>::iterator it(eMainloop::existing_loops)
228 ;it != eMainloop::existing_loops.end(); ++it)
229 it->setTimerOffset(m_time_difference);
232 else if ( !m_time_difference )
233 eDebug("[eDVBLocalTimerHandler] no change needed");
235 eDebug("[eDVBLocalTimerHandler] set to RTC time");
236 /*emit*/ m_timeUpdated();
239 eDebug("[eDVBLocalTimerHandler] shit RTC not ready :(");
244 std::map< eDVBChannelID, int >::iterator it( m_timeOffsetMap.find( chan->getChannelID() ) );
246 // current linux time
247 time_t linuxTime = time(0);
249 // current enigma time
250 time_t nowTime=linuxTime+m_time_difference;
252 // difference between current enigma time and transponder time
253 int enigma_diff = tp_time-nowTime;
257 if ( m_time_ready ) // ref time ready?
259 // difference between reference time (current enigma time)
260 // and the transponder time
261 eDebug("[eDVBLocalTimerHandler] diff is %d", enigma_diff);
262 if ( abs(enigma_diff) < 120 )
264 eDebug("[eDVBLocalTimerHandler] diff < 120 .. use Transponder Time");
265 m_timeOffsetMap[chan->getChannelID()] = 0;
266 new_diff = enigma_diff;
268 else if ( it != m_timeOffsetMap.end() ) // correction saved?
270 eDebug("[eDVBLocalTimerHandler] we have correction %d", it->second);
271 time_t CorrectedTpTime = tp_time+it->second;
272 int ddiff = CorrectedTpTime-nowTime;
273 eDebug("[eDVBLocalTimerHandler] diff after add correction is %d", ddiff);
274 if ( abs(it->second) < 300 ) // stored correction < 5 min
276 eDebug("[eDVBLocalTimerHandler] use stored correction(<5 min)");
279 else if ( /*eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 && TODO !!!*/
283 m_timeOffsetMap[chan->getChannelID()] = rtc-tp_time;
284 new_diff = rtc-nowTime; // set enigma time to rtc
285 eDebug("[eDVBLocalTimerHandler] update stored correction to %d (calced against RTC time)", rtc-tp_time );
287 else if ( abs(ddiff) <= 120 )
289 // with stored correction calced time difference is lower 2 min
290 // this don't help when a transponder have a clock running to slow or to fast
291 // then its better to have a DM7020 with always running RTC
292 eDebug("[eDVBLocalTimerHandler] use stored correction(corr < 2 min)");
295 else // big change in calced correction.. hold current time and update correction
297 eDebug("[eDVBLocalTimerHandler] update stored correction to %d", -enigma_diff);
298 m_timeOffsetMap[chan->getChannelID()] = -enigma_diff;
303 eDebug("[eDVBLocalTimerHandler] no correction found... store calced correction(%d)",-enigma_diff);
304 m_timeOffsetMap[chan->getChannelID()] = -enigma_diff;
307 else // no time setted yet
309 if ( it != m_timeOffsetMap.end() )
311 enigma_diff += it->second;
312 eDebug("[eDVBLocalTimerHandler] we have correction (%d)... use", it->second );
315 eDebug("[eDVBLocalTimerHandler] dont have correction.. set Transponder Diff");
316 new_diff=enigma_diff;
320 time_t t = nowTime+new_diff;
321 m_last_tp_time_difference=tp_time-t;
325 eDebug("[eDVBLocalTimerHandler] not changed");
329 tm now = *localtime(&t);
330 eDebug("[eDVBLocalTimerHandler] time update to %02d:%02d:%02d",
335 m_time_difference = t - linuxTime; // calc our new linux_time -> enigma_time correction
336 eDebug("[eDVBLocalTimerHandler] m_time_difference is %d", m_time_difference );
338 // if ( eSystemInfo::getInstance()->getHwType() == eSystemInfo::DM7020 ) TODO !!
341 if ( abs(m_time_difference) > 59 )
343 eDebug("[eDVBLocalTimerHandler] set Linux Time");
345 gettimeofday(&tnow,0);
347 settimeofday(&tnow,0);
348 for (ePtrList<eMainloop>::iterator it(eMainloop::existing_loops)
349 ;it != eMainloop::existing_loops.end(); ++it)
350 it->setTimerOffset(m_time_difference);
354 /*emit*/ m_timeUpdated();
359 std::map<iDVBChannel*, TDT*>::iterator it =
360 m_active_tables.find(chan);
361 if ( it != m_active_tables.end() )
364 it->second = new TDT(chan);
365 it->second->startTimer(60*60*1000); // restart TDT for this transponder in 60min
371 void eDVBLocalTimeHandler::DVBChannelAdded(eDVBChannel *chan)
373 eDebug("[eDVBLocalTimerHandler] add channel %p", chan);
376 std::map<iDVBChannel*, TDT*>::iterator it =
377 m_active_tables.find(chan);
378 if ( it != m_active_tables.end() )
381 it->second = new TDT(chan);
384 m_active_tables[chan] = new TDT(chan);
388 void eDVBLocalTimeHandler::DVBChannelRemoved(eDVBChannel *chan)
390 eDebug("[eDVBLocalTimerHandler] remove channel %p", chan);
391 std::map<iDVBChannel*, TDT*>::iterator it =
392 m_active_tables.find(chan);
393 if ( it != m_active_tables.end() )
396 m_active_tables.erase(it);
400 void eDVBLocalTimeHandler::DVBChannelRunning(iDVBChannel *chan)
402 eDebug("[eDVBLocalTimerHandler] start channel %p", chan);
403 std::map<iDVBChannel*, TDT*>::iterator it =
404 m_active_tables.find(chan);
405 if ( it != m_active_tables.end() )