aboutsummaryrefslogtreecommitdiff
path: root/lib/dvb_ci
diff options
context:
space:
mode:
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>2006-05-20 00:21:50 +0000
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>2006-05-20 00:21:50 +0000
commit75db34c299094d2ae87941ed464e8efa79848e16 (patch)
tree4d63a8aa488112c6d58d05440ae488f7c86a911e /lib/dvb_ci
parentd0812009f069ba9aee256ba1fb8c54f2ffba671d (diff)
downloadenigma2-75db34c299094d2ae87941ed464e8efa79848e16.tar.gz
enigma2-75db34c299094d2ae87941ed464e8efa79848e16.zip
many changes for better CI handling
- the CI is now working on both tuners - the CI is no more blocked by freetv services - add multi services support (on same transponder) (yet hardcoded for Alphacrypt only) - fix bluescreen in CI MMI dialog when pressin ok/left/right
Diffstat (limited to 'lib/dvb_ci')
-rw-r--r--lib/dvb_ci/dvbci.cpp418
-rw-r--r--lib/dvb_ci/dvbci.h33
-rw-r--r--lib/dvb_ci/dvbci_appmgr.cpp7
-rw-r--r--lib/dvb_ci/dvbci_camgr.cpp7
-rw-r--r--lib/dvb_ci/dvbci_session.h10
-rw-r--r--lib/dvb_ci/dvbci_ui.cpp128
-rw-r--r--lib/dvb_ci/dvbci_ui.h18
7 files changed, 410 insertions, 211 deletions
diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp
index 7d96a296..1be4232e 100644
--- a/lib/dvb_ci/dvbci.cpp
+++ b/lib/dvb_ci/dvbci.cpp
@@ -74,6 +74,7 @@ int eDVBCIInterfaces::reset(int slotid)
return -1;
eDVBCISession::deleteSessions(slot);
+ ciRemoved(slot);
return slot->reset();
}
@@ -86,28 +87,25 @@ int eDVBCIInterfaces::enableTS(int slotid, int enable)
return -1;
int tunernum = 0;
- if (enable)
+ PMTHandlerList::iterator it = m_pmt_handlers.begin();
+ while (it != m_pmt_handlers.end())
{
- PMTHandlerList::iterator it = m_pmt_handlers.begin();
- while (it != m_pmt_handlers.end())
+ if ( it->cislot == slot )
{
- if ( it->cislot == slot )
+ eDVBServicePMTHandler *pmthandler = it->pmthandler;
+ eUsePtr<iDVBChannel> channel;
+ if (!pmthandler->getChannel(channel))
{
- eDVBServicePMTHandler *pmthandler = it->pmthandler;
- eUsePtr<iDVBChannel> channel;
- if (!pmthandler->getChannel(channel))
+ ePtr<iDVBFrontend> frontend;
+ if (!channel->getFrontend(frontend))
{
- ePtr<iDVBFrontend> frontend;
- if (!channel->getFrontend(frontend))
- {
- eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
- tunernum = fe->getID();
- }
+ eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
+ tunernum = fe->getID();
}
- break;
}
- ++it;
+ break;
}
+ ++it;
}
return slot->enableTS(enable, tunernum);
}
@@ -119,19 +117,9 @@ int eDVBCIInterfaces::initialize(int slotid)
if( (slot = getSlot(slotid)) == 0 )
return -1;
- slot->resetPrevSentCAPMTVersion();
- PMTHandlerList::iterator it = m_pmt_handlers.begin();
- while (it != m_pmt_handlers.end())
- {
- if ( it->cislot == slot )
- {
- slot->sendCAPMT(it->pmthandler); // send capmt
- break;
- }
- ++it;
- }
+ slot->removeService();
- return slot->initialize();
+ return sendCAPMT(slotid);
}
int eDVBCIInterfaces::sendCAPMT(int slotid)
@@ -141,19 +129,15 @@ int eDVBCIInterfaces::sendCAPMT(int slotid)
if( (slot = getSlot(slotid)) == 0 )
return -1;
- slot->resetPrevSentCAPMTVersion();
PMTHandlerList::iterator it = m_pmt_handlers.begin();
while (it != m_pmt_handlers.end())
{
if ( it->cislot == slot )
- {
slot->sendCAPMT(it->pmthandler); // send capmt
- return 0;
- }
++it;
}
- return -1;
+ return 0;
}
int eDVBCIInterfaces::startMMI(int slotid)
@@ -206,44 +190,147 @@ int eDVBCIInterfaces::cancelEnq(int slotid)
return slot->cancelEnq();
}
-void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
+void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
{
- CIPmtHandler new_handler(pmthandler);
-
- eServiceReferenceDVB service;
- pmthandler->getService(service);
-
- eDebug("[eDVBCIInterfaces] addPMTHandler %s", service.toString().c_str());
-
- // HACK the first service get the CI..
- eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin());
- for (; ci_it != m_slots.end(); ++ci_it)
+ for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
+ it != m_pmt_handlers.end(); ++it)
{
- if (ci_it->use_count)
- continue;
- ci_it->use_count=1;
- new_handler.cislot = ci_it;
- new_handler.cislot->resetPrevSentCAPMTVersion();
+ if (it->cislot == slot)
+ {
+ eServiceReferenceDVB ref;
+ it->pmthandler->getServiceReference(ref);
+ slot->removeService(ref.getServiceID().get());
+ if (!--slot->use_count)
+ enableTS(slot->getSlotID(), 0);
+ it->cislot=0;
+ }
}
+}
- if (ci_it == m_slots.end())
+void eDVBCIInterfaces::recheckPMTHandlers()
+{
+// eDebug("recheckPMTHAndlers()");
+ for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
+ it != m_pmt_handlers.end(); ++it)
{
- PMTHandlerList::iterator it = m_pmt_handlers.begin();
- while (it != m_pmt_handlers.end())
+ CAID_LIST caids;
+ ePtr<eDVBService> service;
+ eServiceReferenceDVB ref;
+ eDVBServicePMTHandler *pmthandler = it->pmthandler;
+ eDVBServicePMTHandler::program p;
+
+ pmthandler->getServiceReference(ref);
+ pmthandler->getService(service);
+ if (!pmthandler->getProgramInfo(p))
{
- eServiceReferenceDVB ref;
- it->pmthandler->getService(ref);
- if ( service == ref && it->cislot )
+ int cnt=0;
+ for (std::set<uint16_t>::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
+ caids.push_front(*x);
+ if (service && cnt)
+ service->m_ca = caids;
+ }
+
+ if (it->cislot)
+ continue; // already running
+
+ if (service)
+ caids = service->m_ca;
+
+ if (!caids.empty())
+ {
+ for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
{
- new_handler.cislot = it->cislot;
- ++new_handler.cislot->use_count;
- break;
+ if (ci_it->getState() == eDVBCISlot::stateInvalid)
+ ci_it->reset();
+
+ bool useThis=false;
+ eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
+ if (ca_manager)
+ {
+ const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
+ for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
+ {
+ std::vector<uint16_t>::const_iterator z =
+ std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
+ if ( z != ci_caids.end() && *z == *ca )
+ {
+ eDebug("found ci for caid %04x", *z);
+ useThis=true;
+ break;
+ }
+ }
+ }
+
+ if (useThis)
+ {
+ bool send_ca_pmt = false;
+ if (ci_it->use_count) // check if this CI can descramble more than one service
+ {
+ PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
+ while (tmp != m_pmt_handlers.end())
+ {
+ if ( tmp->cislot )
+ {
+ bool canHandleMultipleServices=false;
+ eServiceReferenceDVB ref2;
+ tmp->pmthandler->getServiceReference(ref2);
+ eDVBChannelID s1, s2;
+ if (ref != ref2)
+ {
+ ref.getChannelID(s1);
+ ref2.getChannelID(s2);
+ // FIXME .. build a "ci can handle multiple services" config entry
+ // Yes / No / Auto
+ if ( eDVBCI_UI::getInstance()->getAppName(ci_it->getSlotID()) == "AlphaCrypt" )
+ {
+ canHandleMultipleServices = true;
+ eDebug("Alphacrypt can handle multiple services");
+ }
+ }
+ if (ref == ref2 || (s1 == s2 && canHandleMultipleServices) )
+ {
+ it->cislot = tmp->cislot;
+ ++it->cislot->use_count;
+ send_ca_pmt = true;
+// eDebug("usecount now %d", it->cislot->use_count);
+ break;
+ }
+ }
+ ++tmp;
+ }
+ }
+ else
+ {
+ ci_it->use_count=1;
+ it->cislot = ci_it;
+// eDebug("usecount now %d", it->cislot->use_count);
+ enableTS(ci_it->getSlotID(), 1);
+ send_ca_pmt = true;
+ }
+ if (send_ca_pmt)
+ gotPMT(pmthandler);
+ }
}
- ++it;
}
}
+}
+
+void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
+{
+ // check if this pmthandler is already registered
+ PMTHandlerList::iterator it = m_pmt_handlers.begin();
+ while (it != m_pmt_handlers.end())
+ {
+ if ( *it++ == pmthandler )
+ return;
+ }
+
+ eServiceReferenceDVB ref;
+ pmthandler->getServiceReference(ref);
+ eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
- m_pmt_handlers.push_back(new_handler);
+ m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
+ recheckPMTHandlers();
}
void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
@@ -252,41 +339,52 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
if (it != m_pmt_handlers.end())
{
eDVBCISlot *slot = it->cislot;
-// eDVBServicePMTHandler *pmthandler = it->pmthandler;
+ eDVBServicePMTHandler *pmthandler = it->pmthandler;
m_pmt_handlers.erase(it);
- if (slot && !--slot->use_count)
+
+ eServiceReferenceDVB service_to_remove;
+ pmthandler->getServiceReference(service_to_remove);
+
+ bool sameServiceExist=false;
+ for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
{
-#if 0
- eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt");
- std::vector<uint16_t> caids;
- caids.push_back(0xFFFF);
- slot->resetPrevSentCAPMTVersion();
- slot->sendCAPMT(pmthandler, caids);
-#endif
- // check if another service is running
- it = m_pmt_handlers.begin();
- while (it != m_pmt_handlers.end())
+ eServiceReferenceDVB ref;
+ i->pmthandler->getServiceReference(ref);
+ if ( ref == service_to_remove )
{
- if ( !it->cislot )
- {
- it->cislot = slot;
- ++slot->use_count;
- slot->resetPrevSentCAPMTVersion();
- slot->sendCAPMT(it->pmthandler);
- break;
- }
- ++it;
+ sameServiceExist=true;
+ break;
}
}
+
+ if (slot && !sameServiceExist)
+ {
+ if (slot->getNumOfServices() > 1) // fixme make it dependend of "ci can handle more than one service"
+ {
+ eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
+ service_to_remove.toString().c_str());
+ std::vector<uint16_t> caids;
+ caids.push_back(0xFFFF);
+ slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
+ }
+ slot->removeService(service_to_remove.getServiceID().get());
+ }
+
+ if (slot && !--slot->use_count)
+ {
+ ASSERT(!slot->getNumOfServices());
+ enableTS(slot->getSlotID(),0);
+ }
}
+ // check if another service is waiting for the CI
+ recheckPMTHandlers();
}
void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
{
eDebug("[eDVBCIInterfaces] gotPMT");
PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
- eServiceReferenceDVB service;
- if ( it != m_pmt_handlers.end() && it->cislot)
+ if (it != m_pmt_handlers.end() && it->cislot)
it->cislot->sendCAPMT(pmthandler);
}
@@ -302,29 +400,41 @@ int eDVBCIInterfaces::getMMIState(int slotid)
int eDVBCISlot::send(const unsigned char *data, size_t len)
{
- int res;
+ int res=0;
//int i;
//printf("< ");
//for(i=0;i<len;i++)
// printf("%02x ",data[i]);
//printf("\n");
- res = ::write(fd, data, len);
-
- //printf("write() %d\n",res);
+ if (sendqueue.empty())
+ res = ::write(fd, data, len);
- notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
+ if (res < 0 || (unsigned int)res != len)
+ {
+ unsigned char *d = new unsigned char[len];
+ memcpy(d, data, len);
+ sendqueue.push( queueData(d, len) );
+ notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
+ }
return res;
}
void eDVBCISlot::data(int what)
{
+ if (state == stateInvalid)
+ return;
if(what == eSocketNotifier::Priority) {
if(state != stateRemoved) {
state = stateRemoved;
- enableTS(0);
printf("ci removed\n");
+ while(sendqueue.size())
+ {
+ delete [] sendqueue.top().data;
+ sendqueue.pop();
+ }
+ eDVBCIInterfaces::getInstance()->ciRemoved(this);
eDVBCISession::deleteSessions(this);
notifier->setRequested(eSocketNotifier::Read);
//HACK
@@ -333,36 +443,42 @@ void eDVBCISlot::data(int what)
return;
}
- __u8 data[4096];
- int r;
- r = ::read(fd, data, 4096);
-
if(state != stateInserted) {
- state = stateInserted;
eDebug("ci inserted");
-
- //HACK
+ state = stateInserted;
+// HACK
eDVBCI_UI::getInstance()->setState(0,1);
-
+ notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
/* enable PRI to detect removal or errors */
- notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Write);
}
- if(r > 0) {
- //int i;
- //printf("> ");
- //for(i=0;i<r;i++)
- // printf("%02x ",data[i]);
- //printf("\n");
- eDVBCISession::receiveData(this, data, r);
- notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority|eSocketNotifier::Write);
- return;
+ if (what & eSocketNotifier::Read) {
+ __u8 data[4096];
+ int r;
+ r = ::read(fd, data, 4096);
+ if(r > 0) {
+// int i;
+// printf("> ");
+// for(i=0;i<r;i++)
+// printf("%02x ",data[i]);
+// printf("\n");
+ eDVBCISession::receiveData(this, data, r);
+ eDVBCISession::pollAll();
+ return;
+ }
}
-
- if(what == eSocketNotifier::Write) {
- if(eDVBCISession::pollAll() == 0) {
- notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority);
+ else if (what & eSocketNotifier::Write) {
+ if (!sendqueue.empty()) {
+ const queueData &qe = sendqueue.top();
+ int res = ::write(fd, qe.data, qe.len);
+ if (res >= 0 && (unsigned int)res == qe.len)
+ {
+ delete [] qe.data;
+ sendqueue.pop();
+ }
}
+ else
+ notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
}
}
@@ -384,22 +500,22 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
fd = ::open(filename, O_RDWR | O_NONBLOCK);
eDebug("eDVBCISlot has fd %d", fd);
-
- state = stateInserted;
+ state = stateInvalid;
if (fd >= 0)
{
- notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority);
+ notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
CONNECT(notifier->activated, eDVBCISlot::data);
} else
{
perror(filename);
}
+
+ enableTS(0, 0);
}
eDVBCISlot::~eDVBCISlot()
{
- enableTS(0);
}
void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
@@ -426,16 +542,22 @@ int eDVBCISlot::reset()
{
printf("edvbcislot: reset requested\n");
- enableTS(0);
+ if (state == stateInvalid)
+ {
+ unsigned char buf[256];
+ eDebug("ci flush");
+ while(::read(fd, buf, 256)>0);
+ state = stateResetted;
+ }
- ioctl(fd, 0);
+ while(sendqueue.size())
+ {
+ delete [] sendqueue.top().data;
+ sendqueue.pop();
+ }
- return 0;
-}
+ ioctl(fd, 0);
-int eDVBCISlot::initialize()
-{
- printf("edvbcislot: initialize()\n");
return 0;
}
@@ -513,18 +635,34 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
eDVBTableSpec table_spec;
ptr->getSpec(table_spec);
int pmt_version = table_spec.version & 0x1F; // just 5 bits
- if ( pmt_version == prev_sent_capmt_version )
+
+ eServiceReferenceDVB ref;
+ pmthandler->getServiceReference(ref);
+ uint16_t program_number = ref.getServiceID().get();
+ std::map<uint16_t, uint8_t>::iterator it =
+ running_services.find(program_number);
+
+ if ( it != running_services.end() &&
+ (pmt_version == it->second) &&
+ !(caids.size() == 1 && caids[0] == 0xFFFF) )
{
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 );
+
+// eDebug("send %s capmt for service %04x",
+// it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
+// program_number);
+
+ CaProgramMapSection capmt(*i++,
+ it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
while( i != ptr->getSections().end() )
{
// eDebug("append");
@@ -552,22 +690,39 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
hlen = 4;
}
// end calc capmt length
- eDebug("ca_manager %p dump capmt:", ca_manager);
- for(int i=0;i<wp;i++)
- eDebugNoNewLine("%02x ", raw_data[i]);
- eDebug("");
+// eDebug("ca_manager %p dump capmt:", ca_manager);
+// for(int i=0;i<wp;i++)
+// eDebugNoNewLine("%02x ", raw_data[i]);
+// eDebug("");
#endif
+ if (caids.size() == 1 && caids[0] == 0xFFFF)
+ {
+// eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
+ raw_data[hlen+3] &= ~0x3E;
+ raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
+// eDebug(" new version is %02x", raw_data[hlen+3]);
+ }
+
//dont need tag and lenfield
ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
- prev_sent_capmt_version = pmt_version;
+ running_services[program_number] = pmt_version;
}
}
return 0;
}
+void eDVBCISlot::removeService(uint16_t program_number)
+{
+ if (program_number == 0xFFFF)
+ running_services.clear(); // remove all
+ else
+ running_services.erase(program_number); // remove single service
+}
+
int eDVBCISlot::enableTS(int enable, int tuner)
{
- printf("eDVBCISlot::enableTS(%d %d)\n", enable, tuner);
+// printf("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+// printf("eDVBCISlot::enableTS(%d %d)\n", enable, tuner);
FILE *input0, *input1, *ci;
if((input0 = fopen("/proc/stb/tsmux/input0", "wb")) == NULL) {
@@ -593,9 +748,4 @@ int eDVBCISlot::enableTS(int enable, int tuner)
return 0;
}
-void eDVBCISlot::resendCAPMT()
-{
- eDVBCIInterfaces::getInstance()->sendCAPMT(slotid);
-}
-
eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");
diff --git a/lib/dvb_ci/dvbci.h b/lib/dvb_ci/dvbci.h
index e8f30ab6..2ef70b0e 100644
--- a/lib/dvb_ci/dvbci.h
+++ b/lib/dvb_ci/dvbci.h
@@ -4,6 +4,7 @@
#include <lib/base/ebase.h>
#include <set>
+#include <queue>
class eDVBCISession;
class eDVBCIApplicationManagerSession;
@@ -12,6 +13,22 @@ class eDVBCIMMISession;
class eDVBServicePMTHandler;
class eDVBCISlot;
+struct queueData
+{
+ __u8 prio;
+ unsigned char *data;
+ unsigned int len;
+ queueData( unsigned char *data, unsigned int len, __u8 prio = 0 )
+ :prio(prio), data(data), len(len)
+ {
+
+ }
+ bool operator < ( const struct queueData &a ) const
+ {
+ return prio < a.prio;
+ }
+};
+
class eDVBCISlot: public iObject, public Object
{
DECLARE_REF(eDVBCISlot);
@@ -22,12 +39,13 @@ private:
eSocketNotifier *notifier;
int state;
- enum {stateRemoved, stateInserted};
- uint8_t prev_sent_capmt_version;
+ std::map<uint16_t, uint8_t> running_services;
eDVBCIApplicationManagerSession *application_manager;
eDVBCICAManagerSession *ca_manager;
eDVBCIMMISession *mmi_session;
+ std::priority_queue<queueData> sendqueue;
public:
+ enum {stateRemoved, stateInserted, stateInvalid, stateResetted};
int use_count;
eDVBCISlot(eMainloop *context, int nr);
@@ -43,19 +61,18 @@ public:
eDVBCIMMISession *getMMIManager() { return mmi_session; }
eDVBCICAManagerSession *getCAManager() { return ca_manager; }
+ int getState() { return state; }
int getSlotID();
int reset();
- int initialize();
int startMMI();
int stopMMI();
int answerText(int answer);
int answerEnq(char *value);
int cancelEnq();
int getMMIState();
- void resendCAPMT();
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; }
+ void removeService(uint16_t program_number=0xFFFF);
+ int getNumOfServices() { return running_services.size(); }
int enableTS(int enable, int tuner=0);
@@ -84,7 +101,7 @@ class eDVBCIInterfaces
DECLARE_REF(eDVBCIInterfaces);
static eDVBCIInterfaces *instance;
private:
- eSmartPtrList<eDVBCISlot> m_slots;
+ eSmartPtrList<eDVBCISlot> m_slots;
eDVBCISlot *getSlot(int slotid);
PMTHandlerList m_pmt_handlers;
@@ -94,7 +111,9 @@ public:
void addPMTHandler(eDVBServicePMTHandler *pmthandler);
void removePMTHandler(eDVBServicePMTHandler *pmthandler);
+ void recheckPMTHandlers();
void gotPMT(eDVBServicePMTHandler *pmthandler);
+ void ciRemoved(eDVBCISlot *slot);
static eDVBCIInterfaces *getInstance();
diff --git a/lib/dvb_ci/dvbci_appmgr.cpp b/lib/dvb_ci/dvbci_appmgr.cpp
index 28e0659d..201b36c4 100644
--- a/lib/dvb_ci/dvbci_appmgr.cpp
+++ b/lib/dvb_ci/dvbci_appmgr.cpp
@@ -46,9 +46,10 @@ int eDVBCIApplicationManagerSession::receivedAPDU(const unsigned char *tag,const
for (int i = 0; i < dl; ++i)
printf("%c", ((unsigned char*)data)[i+6]);
printf("\n");
-
- eDVBCI_UI::getInstance()->setState(0,2);
- eDVBCI_UI::getInstance()->setAppName(0,str);
+
+ eDVBCI_UI::getInstance()->setState(slot->getSlotID(), 2);
+
+ eDVBCI_UI::getInstance()->setAppName(slot->getSlotID(), str);
break;
}
default:
diff --git a/lib/dvb_ci/dvbci_camgr.cpp b/lib/dvb_ci/dvbci_camgr.cpp
index e1afd174..ef69ed4d 100644
--- a/lib/dvb_ci/dvbci_camgr.cpp
+++ b/lib/dvb_ci/dvbci_camgr.cpp
@@ -31,8 +31,9 @@ int eDVBCICAManagerSession::receivedAPDU(const unsigned char *tag, const void *d
printf("%04x ", (((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]));
}
+ std::sort(caids.begin(), caids.end());
printf("\n");
- slot->resendCAPMT();
+ eDVBCIInterfaces::getInstance()->recheckPMTHandlers();
break;
default:
printf("unknown APDU tag 9F 80 %02x\n", tag[2]);
@@ -64,8 +65,8 @@ int eDVBCICAManagerSession::sendCAPMT(unsigned char *data, int len)
{
const unsigned char tag[3]={0x9F, 0x80, 0x32}; // ca_pmt
- sendAPDU(tag, data, len);
-
+ sendAPDU(tag, data, len);
+
return 0;
}
diff --git a/lib/dvb_ci/dvbci_session.h b/lib/dvb_ci/dvbci_session.h
index cf69ca9a..ae0d340d 100644
--- a/lib/dvb_ci/dvbci_session.h
+++ b/lib/dvb_ci/dvbci_session.h
@@ -11,9 +11,9 @@ class eDVBCISession
{
DECLARE_REF(eDVBCISession);
static ePtr<eDVBCISession> sessions[SLMS];
- static void eDVBCISession::deleteSessions(const eDVBCISlot *slot);
- static void eDVBCISession::createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr<eDVBCISession> &ptr);
- static void eDVBCISession::sendSPDU(eDVBCISlot *slot, unsigned char tag,const void *data, int len, unsigned short session_nb, const void *apdu=0,int alen=0);
+ static void deleteSessions(const eDVBCISlot *slot);
+ static void createSession(eDVBCISlot *slot, const unsigned char *resource_identifier, unsigned char &status, ePtr<eDVBCISession> &ptr);
+ static void sendSPDU(eDVBCISlot *slot, unsigned char tag,const void *data, int len, unsigned short session_nb, const void *apdu=0,int alen=0);
static void sendOpenSessionResponse(eDVBCISlot *slot,unsigned char session_status, const unsigned char *resource_identifier,unsigned short session_nb);
void recvCreateSessionResponse(const unsigned char *data);
void recvCloseSessionRequest(const unsigned char *data);
@@ -24,8 +24,8 @@ protected:
eDVBCISlot *slot; //base only
unsigned short session_nb;
virtual int receivedAPDU(const unsigned char *tag, const void *data, int len) = 0;
- void eDVBCISession::sendAPDU(const unsigned char *tag, const void *data=0,int len=0);
- void eDVBCISession::sendSPDU(unsigned char tag, const void *data, int len,const void *apdu=0, int alen=0);
+ void sendAPDU(const unsigned char *tag, const void *data=0,int len=0);
+ void sendSPDU(unsigned char tag, const void *data, int len,const void *apdu=0, int alen=0);
virtual int doAction()=0;
void handleClose();
public:
diff --git a/lib/dvb_ci/dvbci_ui.cpp b/lib/dvb_ci/dvbci_ui.cpp
index 4ff047de..ddb42fdb 100644
--- a/lib/dvb_ci/dvbci_ui.cpp
+++ b/lib/dvb_ci/dvbci_ui.cpp
@@ -11,23 +11,28 @@
#include <lib/base/init_num.h>
#include <lib/base/eerror.h>
-eDVBCI_UI *eDVBCI_UI::instance = 0;
+eDVBCI_UI *eDVBCI_UI::instance;
eDVBCI_UI::eDVBCI_UI()
- :mmiScreen(NULL)
- ,mmiTuplePos(0)
- ,mmiScreenReady(0)
{
ASSERT(!instance);
instance = this;
- for(int i=0;i<MAX_SLOTS;i++)
- state[i] = 0; //no module
+ for(int i=0;i<MAX_SLOTS;++i)
+ {
+ slotdata[i].mmiScreen=NULL;
+ slotdata[i].mmiScreenReady=0;
+ slotdata[i].mmiTuplePos=0;
+ slotdata[i].state=0;
+ }
}
eDVBCI_UI::~eDVBCI_UI()
{
- if(mmiScreen)
- Py_DECREF(mmiScreen);
+ for(int i=0;i<MAX_SLOTS;++i)
+ {
+ if (slotdata[i].mmiScreen)
+ Py_DECREF(slotdata[i].mmiScreen);
+ }
}
eDVBCI_UI *eDVBCI_UI::getInstance()
@@ -37,31 +42,33 @@ eDVBCI_UI *eDVBCI_UI::getInstance()
int eDVBCI_UI::getState(int slot)
{
- return state[slot]; //exploit me ;)
+ if (slot < MAX_SLOTS)
+ return slotdata[slot].state;
+ return 0;
}
void eDVBCI_UI::setState(int slot, int newState)
{
- state[slot] = newState;
-
- if(newState == 2) //enable TS
- eDVBCIInterfaces::getInstance()->enableTS(slot, 1);
+ if (slot < MAX_SLOTS)
+ slotdata[slot].state = newState;
}
std::string eDVBCI_UI::getAppName(int slot)
{
- return appName;
+ if (slot < MAX_SLOTS)
+ return slotdata[slot].appName;
+ return "";
}
void eDVBCI_UI::setAppName(int slot, const char *name)
{
- //printf("set name to -%c-\n", name);
- appName = name;
+ if (slot < MAX_SLOTS)
+ slotdata[slot].appName = name;
}
void eDVBCI_UI::setInit(int slot)
{
- eDVBCIInterfaces::getInstance()->sendCAPMT(slot);
+ eDVBCIInterfaces::getInstance()->initialize(slot);
}
void eDVBCI_UI::setReset(int slot)
@@ -81,12 +88,6 @@ int eDVBCI_UI::stopMMI(int slot)
return 0;
}
-int eDVBCI_UI::initialize(int slot)
-{
- eDVBCIInterfaces::getInstance()->initialize(slot);
- return 0;
-}
-
int eDVBCI_UI::answerMenu(int slot, int answer)
{
eDVBCIInterfaces::getInstance()->answerText(slot, answer);
@@ -107,20 +108,27 @@ int eDVBCI_UI::cancelEnq(int slot)
int eDVBCI_UI::availableMMI(int slot)
{
- return mmiScreenReady;
+ if (slot < MAX_SLOTS)
+ return slotdata[slot].mmiScreenReady;
+ return false;
}
int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text)
{
- mmiScreenReady = 0;
+ if (slot >= MAX_SLOTS)
+ return 0;
- if(mmiScreen)
- Py_DECREF(mmiScreen);
- mmiScreen = PyList_New(2);
+ slot_ui_data &data = slotdata[slot];
+
+ data.mmiScreenReady = 0;
+
+ if (data.mmiScreen)
+ Py_DECREF(data.mmiScreen);
+ data.mmiScreen = PyList_New(2);
PyObject *tuple = PyTuple_New(1);
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("ENQ"));
- PyList_SET_ITEM(mmiScreen, 0, tuple);
+ PyList_SET_ITEM(data.mmiScreen, 0, tuple);
tuple = PyTuple_New(4);
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("PIN"));
@@ -128,47 +136,58 @@ int eDVBCI_UI::mmiScreenEnq(int slot, int blind, int answerLen, char *text)
PyTuple_SET_ITEM(tuple, 2, PyString_FromString(text));
PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong(blind));
- PyList_SET_ITEM(mmiScreen, 1, tuple);
+ PyList_SET_ITEM(data.mmiScreen, 1, tuple);
- mmiScreenReady = 1;
+ data.mmiScreenReady = 1;
return 0;
}
int eDVBCI_UI::mmiScreenBegin(int slot, int listmenu)
{
+ if (slot >= MAX_SLOTS)
+ return 0;
+
printf("eDVBCI_UI::mmiScreenBegin\n");
- mmiScreenReady = 0;
+ slot_ui_data &data = slotdata[slot];
- if(mmiScreen)
- Py_DECREF(mmiScreen);
- mmiScreen = PyList_New(1);
+ data.mmiScreenReady = 0;
+
+ if (data.mmiScreen)
+ Py_DECREF(data.mmiScreen);
+
+ data.mmiScreen = PyList_New(1);
PyObject *tuple = PyTuple_New(1);
- if(listmenu == 0) //menu
+ if (listmenu == 0) //menu
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("MENU"));
else //list
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("LIST"));
- PyList_SET_ITEM(mmiScreen, 0, tuple);
+ PyList_SET_ITEM(data.mmiScreen, 0, tuple);
- mmiTuplePos = 1;
+ data.mmiTuplePos = 1;
return 0;
}
int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value)
{
- eDebug("eDVBCI_UI::mmiScreenAddText(%s)",value);
+ if (slot >= MAX_SLOTS)
+ return 0;
+
+ eDebug("eDVBCI_UI::mmiScreenAddText(%s)",value ? value : "");
+
+ slot_ui_data &data = slotdata[slot];
PyObject *tuple = PyTuple_New(3);
- if(type == 0) //title
+ if (type == 0) //title
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TITLE"));
- else if(type == 1) //subtitle
+ else if (type == 1) //subtitle
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("SUBTITLE"));
- else if(type == 2) //bottom
+ else if (type == 2) //bottom
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("BOTTOM"));
else
PyTuple_SET_ITEM(tuple, 0, PyString_FromString("TEXT"));
@@ -177,12 +196,12 @@ int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value)
PyTuple_SET_ITEM(tuple, 1, PyString_FromString(value));
- if(type > 2)
+ if (type > 2)
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(type-2));
else
PyTuple_SET_ITEM(tuple, 2, PyInt_FromLong(-1));
- PyList_Append(mmiScreen, tuple);
+ PyList_Append(data.mmiScreen, tuple);
Py_DECREF(tuple);
return 0;
@@ -190,10 +209,11 @@ int eDVBCI_UI::mmiScreenAddText(int slot, int type, char *value)
int eDVBCI_UI::mmiScreenFinish(int slot)
{
- printf("eDVBCI_UI::mmiScreenFinish\n");
-
- mmiScreenReady = 1;
-
+ if (slot < MAX_SLOTS)
+ {
+ printf("eDVBCI_UI::mmiScreenFinish\n");
+ slotdata[slot].mmiScreenReady = 1;
+ }
return 0;
}
@@ -204,11 +224,15 @@ int eDVBCI_UI::getMMIState(int slot)
PyObject *eDVBCI_UI::getMMIScreen(int slot)
{
- if(mmiScreenReady)
+ if (slot < MAX_SLOTS)
{
- mmiScreenReady = 0;
- Py_INCREF(mmiScreen);
- return mmiScreen;
+ slot_ui_data &data = slotdata[slot];
+ if (data.mmiScreenReady)
+ {
+ data.mmiScreenReady = 0;
+ Py_INCREF(data.mmiScreen);
+ return data.mmiScreen;
+ }
}
Py_INCREF(Py_None);
return Py_None;
diff --git a/lib/dvb_ci/dvbci_ui.h b/lib/dvb_ci/dvbci_ui.h
index 4f23974e..3db215fa 100644
--- a/lib/dvb_ci/dvbci_ui.h
+++ b/lib/dvb_ci/dvbci_ui.h
@@ -7,16 +7,21 @@
#define _POSIX_C_SOURCE 200112L
#include <Python.h>
-#define MAX_SLOTS 2
+#define MAX_SLOTS 4
-class eDVBCI_UI
+struct slot_ui_data
{
- int state[MAX_SLOTS];
- static eDVBCI_UI *instance;
std::string appName;
+ int state;
PyObject *mmiScreen;
int mmiTuplePos;
int mmiScreenReady;
+};
+
+class eDVBCI_UI
+{
+ static eDVBCI_UI *instance;
+ slot_ui_data slotdata[MAX_SLOTS];
#ifdef SWIG
eDVBCI_UI();
~eDVBCI_UI();
@@ -27,14 +32,13 @@ public:
~eDVBCI_UI();
#endif
static eDVBCI_UI *getInstance();
-
+
int getState(int slot);
void setState(int slot, int state);
std::string getAppName(int slot);
void setAppName(int slot, const char *name);
void setInit(int slot);
void setReset(int slot);
- int initialize(int slot);
int startMMI(int slot);
int stopMMI(int slot);
int availableMMI(int slot);
@@ -44,7 +48,7 @@ public:
int answerEnq(int slot, char *val);
int cancelEnq(int slot);
- PyObject *eDVBCI_UI::getMMIScreen(int slot);
+ PyObject *getMMIScreen(int slot);
int mmiScreenEnq(int slot, int blind, int answerLen, char *text);
int mmiScreenBegin(int slot, int listmenu);