aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>2005-11-22 20:03:07 +0000
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>2005-11-22 20:03:07 +0000
commitc326dee2e7ce346cffecd196d971dd91ef1454f5 (patch)
tree8e39dacf813ba3dc8ca8043bc18b33ce7148d26b
parent68b9c0b37d880a7c98e63b6cda04cd4457a29f47 (diff)
downloadenigma2-c326dee2e7ce346cffecd196d971dd91ef1454f5.tar.gz
enigma2-c326dee2e7ce346cffecd196d971dd91ef1454f5.zip
work on ci support
please update the libdvbsi++ to CVSDATE >= 20051119
-rw-r--r--lib/dvb/pmt.cpp24
-rw-r--r--lib/dvb/pmt.h7
-rw-r--r--lib/dvb_ci/dvbci.cpp145
-rw-r--r--lib/dvb_ci/dvbci.h33
-rw-r--r--lib/dvb_ci/dvbci_camgr.cpp2
-rw-r--r--lib/dvb_ci/dvbci_camgr.h5
6 files changed, 205 insertions, 11 deletions
diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp
index c886c39a..e77c097d 100644
--- a/lib/dvb/pmt.cpp
+++ b/lib/dvb/pmt.cpp
@@ -3,6 +3,7 @@
#include <lib/dvb/specs.h>
#include <lib/dvb/dvb.h>
#include <lib/dvb/metaparser.h>
+#include <lib/dvb_ci/dvbci.h>
#include <dvbsi++/ca_program_map_section.h>
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<iDVBChannel> &channel)
+{
+ channel = m_channel;
+ if (channel)
+ return 0;
+ else
+ return -1;
+}
+
int eDVBServicePMTHandler::getDemux(ePtr<iDVBDemux> &demux)
{
demux = m_demux;
diff --git a/lib/dvb/pmt.h b/lib/dvb/pmt.h
index bf83a70a..a23abf1e 100644
--- a/lib/dvb/pmt.h
+++ b/lib/dvb/pmt.h
@@ -108,8 +108,11 @@ public:
int getProgramInfo(struct program &program);
int getDemux(ePtr<iDVBDemux> &demux);
int getPVRChannel(ePtr<iDVBPVRChannel> &pvr_channel);
-
- int tune(eServiceReferenceDVB &ref);
+ int getService(eServiceReferenceDVB &service) { service = m_reference; return 0; }
+ int getPMT(ePtr<eTable<ProgramMapSection> > &ptr) { return m_PMT.getCurrent(ptr); }
+ int getChannel(eUsePtr<iDVBChannel> &channel);
+
+ int tune(eServiceReferenceDVB &ref);
};
#endif
diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp
index 18e66620..82d3349d 100644
--- a/lib/dvb_ci/dvbci.cpp
+++ b/lib/dvb_ci/dvbci.cpp
@@ -6,13 +6,16 @@
#include <lib/base/ebase.h>
#include <lib/base/eerror.h>
+#include <lib/dvb/pmt.h>
#include <lib/dvb_ci/dvbci.h>
#include <lib/dvb_ci/dvbci_session.h>
-
+#include <lib/dvb_ci/dvbci_camgr.h>
#include <lib/dvb_ci/dvbci_ui.h>
#include <lib/dvb_ci/dvbci_appmgr.h>
#include <lib/dvb_ci/dvbci_mmi.h>
+#include <dvbsi++/ca_program_map_section.h>
+
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<uint16_t> 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<eDVBCISlot>::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<uint16_t> &ids)
+{
+ const std::vector<uint16_t> &caids = ids.empty() && ca_manager ? ca_manager->getCAIDs() : ids;
+ ePtr<eTable<ProgramMapSection> > 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<ProgramMapSection*>::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<wp;i++)
+ eDebugNoNewLine("%02x ", raw_data[i]);
+ eDebug("");
+#endif
+ if (ca_manager)
+ {
+ // TODO SEND buffer to CI ( add session number, add tag )
+ prev_sent_capmt_version = pmt_version;
+ }
+ }
+ }
+
+}
+
eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");
diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h
index 224ecde8..1df87eaa 100644
--- a/lib/dvb_ci/dvbci.h
+++ b/lib/dvb_ci/dvbci.h
@@ -3,10 +3,13 @@
#include <lib/base/ebase.h>
+#include <set>
+
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<uint16_t> &caids=std::vector<uint16_t>());
+ 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<CIPmtHandler> PMTHandlerSet;
+
class eDVBCIInterfaces
{
DECLARE_REF(eDVBCIInterfaces);
@@ -46,10 +71,16 @@ DECLARE_REF(eDVBCIInterfaces);
private:
eSmartPtrList<eDVBCISlot> 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 2ad1f1e3..d700b0a1 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<len; i+=2)
{
printf("%04x ", (((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1]));
- caids.insert((((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1]));
+ caids.push_back((((const unsigned char*)data)[i]<<8)|(((const unsigned char*)data)[i+1]));
}
printf("\n");
break;
diff --git a/lib/dvb_ci/dvbci_camgr.h b/lib/dvb_ci/dvbci_camgr.h
index 7a278539..c09997c2 100644
--- a/lib/dvb_ci/dvbci_camgr.h
+++ b/lib/dvb_ci/dvbci_camgr.h
@@ -1,7 +1,7 @@
#ifndef __dvbci_dvbci_camgr_h
#define __dvbci_dvbci_camgr_h
-#include <set>
+#include <vector>
#include <lib/dvb_ci/dvbci_session.h>
@@ -10,10 +10,11 @@ class eDVBCICAManagerSession: public eDVBCISession
enum {
stateFinal=statePrivate,
};
- std::set<int> caids;
+ std::vector<uint16_t> caids;
int receivedAPDU(const unsigned char *tag, const void *data, int len);
int doAction();
public:
+ const std::vector<uint16_t> &getCAIDs() const { return caids; }
};
#endif