X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/aed917161dda79ec6a53e20dbf0ee00a1affc4c0..37b38cb05fc6bc4993f852a78bdba93c7627cf5b:/lib/dvb/pmt.cpp diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index c0447b47..842d6979 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -1,3 +1,4 @@ +#include // access to python config #include #include #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -14,7 +16,6 @@ #include #include #include -#include // access to python config eDVBServicePMTHandler::eDVBServicePMTHandler() :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF) @@ -524,8 +525,15 @@ void eDVBServicePMTHandler::SDTScanEvent(int event) eDebug("no channel list"); else { - m_dvb_scan->insertInto(db, true); - eDebug("sdt update done!"); + eDVBChannelID chid; + m_reference.getChannelID(chid); + if (chid == m_dvb_scan->getCurrentChannelID()) + { + m_dvb_scan->insertInto(db, true); + eDebug("sdt update done!"); + } + else + eDebug("ignore sdt update data.... incorrect transponder tuned!!!"); } break; } @@ -605,7 +613,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, if (ref.path.empty()) { - delete m_dvb_scan; + m_dvb_scan = 0; m_dvb_scan = new eDVBScan(m_channel, true, false); m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection); } @@ -631,7 +639,6 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, void eDVBServicePMTHandler::free() { m_dvb_scan = 0; - delete m_dvb_scan; if (m_ca_servicePtr) { @@ -671,10 +678,10 @@ ChannelMap eDVBCAService::exist_channels; ePtr eDVBCAService::m_chanAddedConn; eDVBCAService::eDVBCAService() - :m_sn(0), m_prev_build_hash(0), m_sendstate(0), m_retryTimer(eApp) + :m_buffer(512), m_prev_build_hash(0), m_sendstate(0), m_retryTimer(eTimer::create(eApp)) { memset(m_used_demux, 0xFF, sizeof(m_used_demux)); - CONNECT(m_retryTimer.timeout, eDVBCAService::sendCAPMT); + CONNECT(m_retryTimer->timeout, eDVBCAService::sendCAPMT); Connect(); } @@ -682,7 +689,6 @@ eDVBCAService::~eDVBCAService() { eDebug("[eDVBCAService] free service %s", m_service.toString().c_str()); ::close(m_sock); - delete m_sn; } // begin static methods @@ -859,27 +865,105 @@ channel_data *eDVBCAService::getChannelData(eDVBChannelID &chid) } // end static methods +#define CA_REPLY_DEBUG +#define MAX_LENGTH_BYTES 4 +#define MIN_LENGTH_BYTES 1 + void eDVBCAService::socketCB(int what) { - if (what & eSocketNotifier::Read) - /*eDebug("[eDVBCAService] data to read\n")*/; - if (what & eSocketNotifier::Priority) - /*eDebug("[eDVBCAService] priority data to read\n")*/; + if (what & (eSocketNotifier::Read | eSocketNotifier::Priority)) + { + char msgbuffer[4096]; + ssize_t length = read(m_sock, msgbuffer, sizeof(msgbuffer)); + if (length == -1) + { + if (errno != EAGAIN && errno != EINTR && errno != EBUSY) + { + eDebug("[eSocketMMIHandler] read (%m)"); + what |= eSocketNotifier::Error; + } + } else if (length == 0) + { + what |= eSocketNotifier::Hungup; + } else + { + int len = length; + unsigned char *data = (unsigned char*)msgbuffer; + int clear = 1; + // If a new message starts, then the previous message + // should already have been processed. Otherwise the + // previous message was incomplete and should therefore + // be deleted. + if ((len >= 1) && ((data[0] & 0xFF) != 0x9f)) + clear = 0; + if ((len >= 2) && ((data[1] & 0x80) != 0x80)) + clear = 0; + if ((len >= 3) && ((data[2] & 0x80) != 0x00)) + clear = 0; + if (clear) + { + m_buffer.clear(); +#ifdef CA_REPLY_DEBUG + eDebug("clear buffer"); +#endif + } +#ifdef CA_REPLY_DEBUG + eDebug("Put to buffer:"); + for (int i=0; i < len; ++i) + eDebugNoNewLine("%02x ", data[i]); + eDebug("\n--------"); +#endif + m_buffer.write( data, len ); + + while ( m_buffer.size() >= (3 + MIN_LENGTH_BYTES) ) + { + unsigned char tmp[3+MAX_LENGTH_BYTES]; + m_buffer.peek(tmp, 3+MIN_LENGTH_BYTES); + if (((tmp[0] & 0xFF) != 0x9f) || ((tmp[1] & 0x80) != 0x80) || ((tmp[2] & 0x80) != 0x00)) + { + m_buffer.skip(1); +#ifdef CA_REPLY_DEBUG + eDebug("skip %02x", tmp[0]); +#endif + continue; + } + if (tmp[3] & 0x80) + { + int peekLength = (tmp[3] & 0x7f) + 4; + if (m_buffer.size() < peekLength) + continue; + m_buffer.peek(tmp, peekLength); + } + int size=0; + int LengthBytes=eDVBCISession::parseLengthField(tmp+3, size); + int messageLength = 3+LengthBytes+size; + if ( m_buffer.size() >= messageLength ) + { + unsigned char dest[messageLength]; + m_buffer.read(dest, messageLength); +#ifdef CA_REPLY_DEBUG + eDebug("dump ca reply:"); + for (int i=0; i < messageLength; ++i) + eDebugNoNewLine("%02x ", dest[i]); + eDebug("\n--------"); +#endif +// /*emit*/ mmi_progress(0, dest, (const void*)(dest+3+LengthBytes), messageLength-3-LengthBytes); + } + } + } + } if (what & eSocketNotifier::Hungup) { - /*eDebug("[eDVBCAService] connection closed\n")*/; + /*eDebug("[eDVBCAService] connection closed")*/; m_sendstate=1; sendCAPMT(); } if (what & eSocketNotifier::Error) - /*eDebug("[eDVBCAService] connection error\n")*/; + eDebug("[eDVBCAService] connection error"); } void eDVBCAService::Connect() { - if (m_sn) { - delete m_sn; - m_sn=0; - } + m_sn=0; memset(&m_servaddr, 0, sizeof(struct sockaddr_un)); m_servaddr.sun_family = AF_UNIX; strcpy(m_servaddr.sun_path, "/tmp/camd.socket"); @@ -892,7 +976,7 @@ void eDVBCAService::Connect() int val=1; fcntl(m_sock, F_SETFL, O_NONBLOCK); setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, &val, 4); - m_sn = new eSocketNotifier(eApp, m_sock, + m_sn = eSocketNotifier::create(eApp, m_sock, eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Error|eSocketNotifier::Hungup); CONNECT(m_sn->activated, eDVBCAService::socketCB); @@ -1044,11 +1128,11 @@ void eDVBCAService::sendCAPMT() { case 0xFFFFFFFF: ++m_sendstate; - m_retryTimer.start(0,true); + m_retryTimer->start(0,true); // eDebug("[eDVBCAService] send failed .. immediate retry"); break; default: - m_retryTimer.start(5000,true); + m_retryTimer->start(5000,true); // eDebug("[eDVBCAService] send failed .. retry in 5 sec"); break; }