From: Andreas Monzner Date: Tue, 22 Nov 2005 20:03:07 +0000 (+0000) Subject: work on ci support X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=c326dee2e7ce346cffecd196d971dd91ef1454f5 work on ci support please update the libdvbsi++ to CVSDATE >= 20051119 --- diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index c886c39..e77c097 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include eDVBServicePMTHandler::eDVBServicePMTHandler(int record) @@ -12,6 +13,7 @@ eDVBServicePMTHandler::eDVBServicePMTHandler(int record) eDVBResourceManager::getInstance(m_resourceManager); CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready); CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready); + eDVBCIInterfaces::getInstance()->addPMTHandler(this); eDebug("new PMT handler record: %d", m_record); } @@ -27,6 +29,7 @@ eDVBServicePMTHandler::~eDVBServicePMTHandler() m_PMT.getCurrent(ptr); eDVBCAService::unregister_service(m_reference, demux_num, ptr); } + eDVBCIInterfaces::getInstance()->removePMTHandler(this); } void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) @@ -69,11 +72,15 @@ void eDVBServicePMTHandler::PMTready(int error) else { serviceEvent(eventNewProgramInfo); - if (!m_pvr_channel && !m_ca_servicePtr) // don't send campmt to camd.socket for playbacked services + if (!m_pvr_channel) { - uint8_t demux_num; - m_demux->getCADemuxID(demux_num); - eDVBCAService::register_service(m_reference, demux_num, m_ca_servicePtr); + eDVBCIInterfaces::getInstance()->gotPMT(this); + if(!m_ca_servicePtr) // don't send campmt to camd.socket for playbacked services + { + uint8_t demux_num; + m_demux->getCADemuxID(demux_num); + eDVBCAService::register_service(m_reference, demux_num, m_ca_servicePtr); + } } if (m_ca_servicePtr) { @@ -200,6 +207,15 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) return -1; } +int eDVBServicePMTHandler::getChannel(eUsePtr &channel) +{ + channel = m_channel; + if (channel) + return 0; + else + return -1; +} + int eDVBServicePMTHandler::getDemux(ePtr &demux) { demux = m_demux; diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h index bf83a70..a23abf1 100644 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@ -108,8 +108,11 @@ public: int getProgramInfo(struct program &program); int getDemux(ePtr &demux); int getPVRChannel(ePtr &pvr_channel); - - int tune(eServiceReferenceDVB &ref); + int getService(eServiceReferenceDVB &service) { service = m_reference; return 0; } + int getPMT(ePtr > &ptr) { return m_PMT.getCurrent(ptr); } + int getChannel(eUsePtr &channel); + + int tune(eServiceReferenceDVB &ref); }; #endif diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp index 18e6662..82d3349 100644 --- a/lib/dvb_ci/dvbci.cpp +++ b/lib/dvb_ci/dvbci.cpp @@ -6,13 +6,16 @@ #include #include +#include #include #include - +#include #include #include #include +#include + eDVBCIInterfaces *eDVBCIInterfaces::instance = 0; eDVBCIInterfaces::eDVBCIInterfaces() @@ -123,6 +126,80 @@ int eDVBCIInterfaces::answerEnq(int slotid, int answer, char *value) return slot->answerEnq(answer, value); } +void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler) +{ + CIPmtHandler new_handler(pmthandler); + + eServiceReferenceDVB service; + pmthandler->getService(service); + + PMTHandlerSet::iterator it = m_pmt_handlers.begin(); + while (it != m_pmt_handlers.end()) + { + eServiceReferenceDVB ref; + it->pmthandler->getService(ref); + if ( service == ref && it->usedby ) + new_handler.usedby = it->usedby; + break; + } + m_pmt_handlers.insert(new_handler); +} + +void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) +{ + PMTHandlerSet::iterator it=m_pmt_handlers.find(pmthandler); + if (it != m_pmt_handlers.end()) + { + eDVBCISlot *slot = it->usedby; + eDVBServicePMTHandler *pmthandler = it->pmthandler; + m_pmt_handlers.erase(it); + if (slot) + { + eServiceReferenceDVB removed_service; + pmthandler->getService(removed_service); + PMTHandlerSet::iterator it=m_pmt_handlers.begin(); + while (it != m_pmt_handlers.end()) + { + eServiceReferenceDVB ref; + it->pmthandler->getService(ref); + if (ref == removed_service) + break; + ++it; + } + if ( it == m_pmt_handlers.end() && slot->getPrevSentCAPMTVersion() != 0xFF ) + { + std::vector caids; + caids.push_back(0xFFFF); + slot->sendCAPMT(pmthandler, caids); + } + } + } +} + +void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler) +{ + eDebug("[eDVBCIInterfaces] gotPMT"); + PMTHandlerSet::iterator it=m_pmt_handlers.find(pmthandler); + eServiceReferenceDVB service; + if ( it != m_pmt_handlers.end() ) + { + eDebug("[eDVBCIInterfaces] usedby %p", it->usedby); + if (!it->usedby) + { + // HACK this assigns ALL RUNNING SERVICES to the first free CI !!! + for (eSmartPtrList::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it) + { + eDVBCISlot **usedby = &it->usedby; + *usedby = ci_it; + (*usedby)->resetPrevSentCAPMTVersion(); + break; + } + } + if (it->usedby) + it->usedby->sendCAPMT(pmthandler); + } +} + int eDVBCIInterfaces::getMMIState(int slotid) { eDVBCISlot *slot; @@ -205,6 +282,7 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr) application_manager = 0; mmi_session = 0; + ca_manager = 0; slotid = nr; @@ -294,4 +372,69 @@ int eDVBCISlot::answerEnq(int answer, char *value) return 0; } +int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector &ids) +{ + const std::vector &caids = ids.empty() && ca_manager ? ca_manager->getCAIDs() : ids; + ePtr > ptr; + if (pmthandler->getPMT(ptr)) + return -1; + else + { + eDVBTableSpec table_spec; + ptr->getSpec(table_spec); + int pmt_version = table_spec.version & 0x1F; // just 5 bits + if ( pmt_version == prev_sent_capmt_version ) + { + eDebug("[eDVBCISlot] dont sent self capmt version twice"); + return -1; + } + std::vector::const_iterator i=ptr->getSections().begin(); + if ( i == ptr->getSections().end() ) + return -1; + else + { + unsigned char raw_data[2048]; + CaProgramMapSection capmt(*i++, prev_sent_capmt_version != 0xFF ? 0x05 /*update*/ : 0x03 /*only*/, 0x01, caids ); + while( i != ptr->getSections().end() ) + { + // eDebug("append"); + capmt.append(*i++); + } + capmt.writeToBuffer(raw_data); +#if 1 +// begin calc capmt length + int wp=0; + if ( raw_data[3] & 0x80 ) + { + int i=0; + int lenbytes = raw_data[3] & ~0x80; + while(i < lenbytes) + wp |= (raw_data[4+i] << (8 * i++)); + wp+=4; + wp+=lenbytes; + } + else + { + wp = raw_data[3]; + wp+=4; + } +// end calc capmt length + if (!ca_manager) + eDebug("no ca_manager !!! dump unfiltered capmt:"); + else + eDebug("ca_manager %p dump capmt:", ca_manager); + for(int i=0;i init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots"); diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h index 224ecde..1df87ea 100644 --- a/lib/dvb_ci/dvbci.h +++ b/lib/dvb_ci/dvbci.h @@ -3,10 +3,13 @@ #include +#include + class eDVBCISession; class eDVBCIApplicationManagerSession; class eDVBCICAManagerSession; class eDVBCIMMISession; +class eDVBServicePMTHandler; class eDVBCISlot: public iObject, public Object { @@ -18,7 +21,8 @@ private: eSocketNotifier *notifier; int state; - enum {stateRemoved, stateInserted}; + enum {stateRemoved, stateInserted}; + uint8_t prev_sent_capmt_version; public: eDVBCISlot(eMainloop *context, int nr); ~eDVBCISlot(); @@ -37,8 +41,29 @@ public: int answerText(int answer); int answerEnq(int answer, char *value); int getMMIState(); + int sendCAPMT(eDVBServicePMTHandler *ptr, const std::vector &caids=std::vector()); + uint8_t getPrevSentCAPMTVersion() const { return prev_sent_capmt_version; } + void resetPrevSentCAPMTVersion() { prev_sent_capmt_version = 0xFF; } +}; + +struct CIPmtHandler +{ + eDVBServicePMTHandler *pmthandler; + eDVBCISlot *usedby; + CIPmtHandler() + :pmthandler(NULL), usedby(NULL) + {} + CIPmtHandler( const CIPmtHandler &x ) + :pmthandler(x.pmthandler), usedby(x.usedby) + {} + CIPmtHandler( eDVBServicePMTHandler *ptr ) + :pmthandler(ptr), usedby(NULL) + {} + bool operator<(const CIPmtHandler &x) const { return x.pmthandler < pmthandler; } }; +typedef std::set PMTHandlerSet; + class eDVBCIInterfaces { DECLARE_REF(eDVBCIInterfaces); @@ -46,10 +71,16 @@ DECLARE_REF(eDVBCIInterfaces); private: eSmartPtrList m_slots; eDVBCISlot *getSlot(int slotid); + + PMTHandlerSet m_pmt_handlers; public: eDVBCIInterfaces(); ~eDVBCIInterfaces(); + void addPMTHandler(eDVBServicePMTHandler *pmthandler); + void removePMTHandler(eDVBServicePMTHandler *pmthandler); + void gotPMT(eDVBServicePMTHandler *pmthandler); + static eDVBCIInterfaces *getInstance(); int reset(int slot); diff --git a/lib/dvb_ci/dvbci_camgr.cpp b/lib/dvb_ci/dvbci_camgr.cpp index 2ad1f1e..d700b0a 100644 --- a/lib/dvb_ci/dvbci_camgr.cpp +++ b/lib/dvb_ci/dvbci_camgr.cpp @@ -18,7 +18,7 @@ int eDVBCICAManagerSession::receivedAPDU(const unsigned char *tag, const void *d for (int i=0; i +#include #include @@ -10,10 +10,11 @@ class eDVBCICAManagerSession: public eDVBCISession enum { stateFinal=statePrivate, }; - std::set caids; + std::vector caids; int receivedAPDU(const unsigned char *tag, const void *data, int len); int doAction(); public: + const std::vector &getCAIDs() const { return caids; } }; #endif