#define FP_IOCTL_SET_RTC 0x101
#define FP_IOCTL_GET_RTC 0x102
+#define TIME_UPDATE_INTERVAL (30*60*1000)
+
static time_t prev_time;
void setRTC(time_t time)
FILE *f = fopen("/proc/stb/fp/rtc", "w");
if (f)
{
- if (fprintf(f, "%u", time))
+ if (fprintf(f, "%u", (unsigned int)time))
prev_time = time;
else
eDebug("write /proc/stb/fp/rtc failed (%m)");
if (f)
{
// sanity check to detect corrupt atmel firmware
- if (fscanf(f, "%u", &rtc_time) != 1)
+ unsigned int tmp;
+ if (fscanf(f, "%u", &tmp) != 1)
eDebug("read /proc/stb/fp/rtc failed (%m)");
+ else
+ rtc_time=tmp;
fclose(f);
}
else
return rtc_time != prev_time ? rtc_time : 0;
}
-time_t parseDVBtime(__u8 t1, __u8 t2, __u8 t3, __u8 t4, __u8 t5)
+static void parseDVBdate(tm& t, int mjd)
{
- 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_isdst = 0;
t.tm_gmtoff = 0;
+}
+
+static inline void parseDVBtime_impl(tm& t, const uint8_t *data)
+{
+ parseDVBdate(t, (data[0] << 8) | data[1]);
+ t.tm_hour = fromBCD(data[2]);
+ t.tm_min = fromBCD(data[3]);
+ t.tm_sec = fromBCD(data[4]);
+}
+
+time_t parseDVBtime(uint16_t mjd, uint32_t stime_bcd)
+{
+ tm t;
+ parseDVBdate(t, mjd);
+ t.tm_hour = fromBCD(stime_bcd >> 16);
+ t.tm_min = fromBCD((stime_bcd >> 8)&0xFF);
+ t.tm_sec = fromBCD(stime_bcd & 0xFF);
+ return timegm(&t);
+}
+time_t parseDVBtime(const uint8_t *data)
+{
+ tm t;
+ parseDVBtime_impl(t, data);
+ return timegm(&t);
+}
+
+time_t parseDVBtime(const uint8_t *data, uint16_t *hash)
+{
+ tm t;
+ parseDVBtime_impl(t, data);
+ *hash = t.tm_hour * 60 + t.tm_min;
+ *hash |= t.tm_mday << 11;
return timegm(&t);
}
int TDT::createTable(unsigned int nr, const __u8 *data, unsigned int max)
{
- if ( data && data[0] == 0x70 || data[0] == 0x73 )
+ if ( data && (data[0] == 0x70 || data[0] == 0x73 ))
{
int length = ((data[1] & 0x0F) << 8) | data[2];
if ( length >= 5 )
{
- time_t tptime = parseDVBtime(data[3], data[4], data[5], data[6], data[7]);
+ time_t tptime = parseDVBtime(&data[3]);
if (tptime && tptime != -1)
eDVBLocalTimeHandler::getInstance()->updateTime(tptime, chan, update_count);
error=0;
DEFINE_REF(eDVBLocalTimeHandler);
eDVBLocalTimeHandler::eDVBLocalTimeHandler()
- :m_time_ready(false)
+ :m_use_dvb_time(false), m_updateNonTunedTimer(eTimer::create(eApp)), m_time_ready(false)
{
if ( !instance )
instance=this;
/*emit*/ m_timeUpdated();
}
}
+ CONNECT(m_updateNonTunedTimer->timeout, eDVBLocalTimeHandler::updateNonTuned);
}
eDVBLocalTimeHandler::~eDVBLocalTimeHandler()
}
}
+void eDVBLocalTimeHandler::setUseDVBTime(bool b)
+{
+ if (m_use_dvb_time != b) {
+ if (m_use_dvb_time) {
+ eDebug("[eDVBLocalTimeHandler] disable sync local time with transponder time!");
+ std::map<iDVBChannel*, channel_data>::iterator it =
+ m_knownChannels.begin();
+ for (; it != m_knownChannels.end(); ++it) {
+ if (it->second.m_prevChannelState == iDVBChannel::state_ok)
+ it->second.tdt = 0;
+ }
+ }
+ else {
+ eDebug("[eDVBLocalTimeHandler] enable sync local time with transponder time!");
+ std::map<iDVBChannel*, channel_data>::iterator it =
+ m_knownChannels.begin();
+ for (; it != m_knownChannels.end(); ++it) {
+ if (it->second.m_prevChannelState == iDVBChannel::state_ok) {
+ it->second.tdt = new TDT(it->second.channel);
+ it->second.tdt->start();
+ }
+ }
+ }
+ m_use_dvb_time = b;
+ }
+}
+
+void eDVBLocalTimeHandler::updateNonTuned()
+{
+ updateTime(-1, 0, 0);
+ m_updateNonTunedTimer->start(TIME_UPDATE_INTERVAL, true);
+}
+
void eDVBLocalTimeHandler::updateTime( time_t tp_time, eDVBChannel *chan, int update_count )
{
int time_difference;
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();
int updateCount = it->second.tdt->getUpdateCount();
it->second.tdt = 0;
it->second.tdt = new TDT(chan, updateCount);
- it->second.tdt->startTimer(60*60*1000); // restart TDT for this transponder in 60min
+ it->second.tdt->startTimer(TIME_UPDATE_INTERVAL); // restart TDT for this transponder in 30min
}
}
}
{
case iDVBChannel::state_ok:
eDebug("[eDVBLocalTimerHandler] channel %p running", chan);
- it->second.tdt = new TDT(it->second.channel);
- it->second.tdt->start();
+ m_updateNonTunedTimer->stop();
+ if (m_use_dvb_time) {
+ it->second.tdt = new TDT(it->second.channel);
+ it->second.tdt->start();
+ }
break;
case iDVBChannel::state_release:
eDebug("[eDVBLocalTimerHandler] remove channel %p", chan);
m_knownChannels.erase(it);
+ if (m_knownChannels.empty())
+ m_updateNonTunedTimer->start(TIME_UPDATE_INTERVAL, true);
break;
default: // ignore all other events
return;