many changes for better CI handling
authorAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 20 May 2006 00:21:50 +0000 (00:21 +0000)
committerAndreas Monzner <andreas.monzner@multimedia-labs.de>
Sat, 20 May 2006 00:21:50 +0000 (00:21 +0000)
- 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

16 files changed:
lib/dvb/db.cpp
lib/dvb/epgcache.cpp
lib/dvb/idvb.h
lib/dvb/pmt.cpp
lib/dvb/pmt.h
lib/dvb/scan.cpp
lib/dvb/scan.h
lib/dvb_ci/dvbci.cpp
lib/dvb_ci/dvbci.h
lib/dvb_ci/dvbci_appmgr.cpp
lib/dvb_ci/dvbci_camgr.cpp
lib/dvb_ci/dvbci_session.h
lib/dvb_ci/dvbci_ui.cpp
lib/dvb_ci/dvbci_ui.h
lib/python/Screens/Ci.py
lib/service/servicedvb.cpp

index 9b2324a6e8c12ca445941a392141909cbaad2eee..a9f58c0f26cc6e84064904f37a7d96a6ec185f54 100644 (file)
@@ -114,21 +114,13 @@ RESULT eBouquet::setListName(const std::string &name)
 }
 
 eDVBService::eDVBService()
-       :m_flags(0)
+       :m_cache(0), m_flags(0)
 {
-       memset(m_cache, -1, sizeof(m_cache));
 }
 
 eDVBService::~eDVBService()
 {
-}
-
-bool eDVBService::cacheEmpty()
-{
-       for (int i=0; i < cacheMax; ++i)
-               if (m_cache[i] != -1)
-                       return false;
-       return true;
+       delete [] m_cache;
 }
 
 eDVBService &eDVBService::operator=(const eDVBService &s)
@@ -137,8 +129,8 @@ eDVBService &eDVBService::operator=(const eDVBService &s)
        m_service_name_sort = s.m_service_name_sort;
        m_provider_name = s.m_provider_name;
        m_flags = s.m_flags;
-//     m_ca = s.m_ca;
-       memcpy(m_cache, s.m_cache, sizeof(m_cache));
+       m_ca = s.m_ca;
+       copyCache(s.m_cache);
        return *this;
 }
 
@@ -232,15 +224,47 @@ int eDVBService::checkFilter(const eServiceReferenceDVB &ref, const eDVBChannelQ
                return res;
 }
 
+bool eDVBService::cacheEmpty()
+{
+       if (m_cache)
+               for (int i=0; i < cacheMax; ++i)
+                       if (m_cache[i] != -1)
+                               return false;
+       return true;
+}
+
+void eDVBService::initCache()
+{
+       m_cache = new int[cacheMax];
+       memset(m_cache, -1, sizeof(int) * cacheMax);
+}
+
+void eDVBService::copyCache(int *source)
+{
+       if (source)
+       {
+               if (!m_cache)
+                       m_cache = new int[cacheMax];
+               memcpy(m_cache, source, cacheMax * sizeof(int));
+       }
+       else
+       {
+               delete [] m_cache;
+               m_cache = 0;
+       }
+}
+
 int eDVBService::getCacheEntry(cacheID id)
 {
-       if (id >= cacheMax)
+       if (id >= cacheMax || !m_cache)
                return -1;
        return m_cache[id];
 }
 
 void eDVBService::setCacheEntry(cacheID id, int pid)
 {
+       if (!m_cache)
+               initCache();
        if (id < cacheMax)
                m_cache[id] = pid;
 }
@@ -426,13 +450,13 @@ void eDVBDB::reloadServicelist()
                                {
                                        int cid, val;
                                        sscanf(v.c_str(), "%02d%04x", &cid, &val);
-                                       s->m_cache[cid]=val;
-                               }/* else if (p == 'C')
+                                       s->setCacheEntry(cid,val);
+                               } else if (p == 'C')
                                {
                                        int val;
                                        sscanf(v.c_str(), "%04x", &val);
-                                       s->m_ca.insert(val);
-                               }*/
+                                       s->m_ca.push_front((uint16_t)val);
+                               }
                        }
                addService(ref, s);
        }
@@ -517,15 +541,16 @@ void eDVBDB::saveServicelist()
 
                // write cached pids
                for (int x=0; x < eDVBService::cacheMax; ++x)
-                       if (i->second->m_cache[x] != -1)
-                               fprintf(f, ",c:%02d%04x", x, i->second->m_cache[x]);
+               {
+                       int entry = i->second->getCacheEntry(x);
+                       if (entry != -1)
+                               fprintf(f, ",c:%02d%04x", x, entry);
+               }
 
-/*
                // write cached ca pids
-               for (std::set<int>::const_iterator ca(i->second->m_ca.begin());
+               for (CAID_LIST::const_iterator ca(i->second->m_ca.begin());
                        ca != i->second->m_ca.end(); ++ca)
                        fprintf(f, ",C:%04x", *ca);
-*/
 
                if (i->second->m_flags)
                        fprintf(f, ",f:%x", i->second->m_flags);
index ee61268c30520508a10e5454438ecc70ac5c30ee..b04bdd8959f746e9c2ab98bbe5b77e487ccdefcd 100644 (file)
@@ -2118,7 +2118,7 @@ void eEPGCache::PMTready(eDVBServicePMTHandler *pmthandler)
                                if (tmp==3)
                                {
                                        eServiceReferenceDVB ref;
-                                       if (!pmthandler->getService(ref))
+                                       if (!pmthandler->getServiceReference(ref))
                                        {
                                                int pid = (*es)->getPid();
                                                messages.send(Message(Message::got_private_pid, ref, pid));
index 8b86866e423a3bae8679650688b1b5f795dea3c0..8bbbaafa473c89b773f4909149fe5991fe5496b0 100644 (file)
 #include <libsig_comp.h>
 #include <connection.h>
 
+#if defined(__GNUC__) && ((__GNUC__ == 3 && __GNUC_MINOR__ >= 1) || __GNUC__ == 4 )  // check if gcc version >= 3.1
+#include <ext/slist>
+#define CAID_LIST __gnu_cxx::slist<uint16_t>
+#else
+#include <slist>
+#define CAID_LIST std::slist<uint16_t>
+#endif
+
 struct eBouquet
 {
        std::string m_bouquet_name;
@@ -220,6 +228,9 @@ class eDVBChannelQuery;
 class eDVBService: public iStaticServiceInformation
 {
        DECLARE_REF(eDVBService);
+       int *m_cache;
+       void initCache();
+       void copyCache(int *source);
 public:
        enum cacheID
        {
@@ -250,9 +261,8 @@ public:
 
        bool usePMT() const { return !(m_flags & dxNoDVB); }
 
-//     std::set<int> m_ca;
+       CAID_LIST m_ca;
 
-       int m_cache[cacheMax];
        virtual ~eDVBService();
        
        eDVBService &operator=(const eDVBService &);
index 0cdebebff807d721a87bda551c3bf03b9c920abc..4d48f86e7898c401dab01614dddd41d59581f20b 100644 (file)
@@ -85,9 +85,9 @@ void eDVBServicePMTHandler::PMTready(int error)
        {
                serviceEvent(eventNewProgramInfo);
                eEPGCache::getInstance()->PMTready(this);
-               if (!m_pvr_channel)
+               if (!m_pvr_channel) // don't send campmt to camd.socket for playbacked services
                {
-                       if(!m_ca_servicePtr)   // don't send campmt to camd.socket for playbacked services
+                       if(!m_ca_servicePtr)
                        {
                                int demuxes[2] = {0,0};
                                uint8_t tmp;
@@ -98,9 +98,10 @@ void eDVBServicePMTHandler::PMTready(int error)
                                else
                                        demuxes[1]=demuxes[0];
                                eDVBCAService::register_service(m_reference, demuxes, m_ca_servicePtr);
-                               eDVBCIInterfaces::getInstance()->addPMTHandler(this);
+                               eDVBCIInterfaces::getInstance()->recheckPMTHandlers();
                        }
-                       eDVBCIInterfaces::getInstance()->gotPMT(this);
+                       else
+                               eDVBCIInterfaces::getInstance()->gotPMT(this);
                }
                if (m_ca_servicePtr)
                {
@@ -140,70 +141,21 @@ PyObject *eDVBServicePMTHandler::getCaIds()
 {
        PyObject *ret=0;
 
-       ePtr<eTable<ProgramMapSection> > ptr;
+       program prog;
 
-       if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr))
+       if ( !getProgramInfo(prog) )
        {
-               uint16_t caids[255];
-               memset(caids, 0, sizeof(caids));
-               std::vector<ProgramMapSection*>::const_iterator i = ptr->getSections().begin();
-               for (; i != ptr->getSections().end(); ++i)
-               {
-                       const ProgramMapSection &pmt = **i;
-                       ElementaryStreamInfoConstIterator es = pmt.getEsInfo()->begin();
-                       for (; es != pmt.getEsInfo()->end(); ++es)
-                       {
-                               for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
-                                               desc != (*es)->getDescriptors()->end(); ++desc)
-                               {
-                                       switch ((*desc)->getTag())
-                                       {
-                                               case CA_DESCRIPTOR:
-                                               {
-                                                       const CaDescriptor *cadescr = (const CaDescriptor*)*desc;
-                                                       uint16_t caid = cadescr->getCaSystemId();
-                                                       int idx=0;
-                                                       while (caids[idx] && caids[idx] != caid)
-                                                               ++idx;
-                                                       caids[idx]=caid;
-                                                       break;
-                                               }
-                                       }
-                               }
-                       }
-                       for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
-                               desc != pmt.getDescriptors()->end(); ++desc)
-                       {
-                               switch ((*desc)->getTag())
-                               {
-                                       case CA_DESCRIPTOR:
-                                       {
-                                               const CaDescriptor *cadescr = (const CaDescriptor*)*desc;
-                                               uint16_t caid = cadescr->getCaSystemId();
-                                               int idx=0;
-                                               while (caids[idx] && caids[idx] != caid)
-                                                       ++idx;
-                                               caids[idx]=caid;
-                                               break;
-                                       }
-                               }
-                       }
-               }
-               int cnt=0;
-               while (caids[cnt])
-                       ++cnt;
+               int cnt=prog.caids.size();
                if (cnt)
                {
                        ret=PyList_New(cnt);
+                       std::set<uint16_t>::iterator it(prog.caids.begin());
                        while(cnt--)
-                               PyList_SET_ITEM(ret, cnt, PyInt_FromLong(caids[cnt]));
+                               PyList_SET_ITEM(ret, cnt, PyInt_FromLong(*it++));
                }
        }
 
-       if (!ret)
-               ret=PyList_New(0);
-
-       return ret;
+       return ret ? ret : PyList_New(0);
 }
 
 int eDVBServicePMTHandler::getProgramInfo(struct program &program)
@@ -213,7 +165,6 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program)
        program.videoStreams.clear();
        program.audioStreams.clear();
        program.pcrPid = -1;
-       program.isCrypted = false;
        program.pmtPid = -1;
        program.textPid = -1;
        program.audioChannel = m_service ? m_service->getCacheEntry(eDVBService::cACHANNEL) : -1;
@@ -243,7 +194,7 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program)
                        ElementaryStreamInfoConstIterator es;
                        for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
                        {
-                               int isaudio = 0, isvideo = 0, cadescriptors = 0;
+                               int isaudio = 0, isvideo = 0;
                                videoStream video;
                                audioStream audio;
                                audio.component_tag=-1;
@@ -317,9 +268,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program)
                                                                        ((StreamIdentifierDescriptor*)*desc)->getComponentTag();
                                                        break;
                                                case CA_DESCRIPTOR:
-                                                       ++cadescriptors;
+                                               {
+                                                       CaDescriptor *descr = (CaDescriptor*)(*desc);
+                                                       program.caids.insert(descr->getCaSystemId());
                                                        break;
                                                }
+                                               }
                                        }
                                        break;
                                }
@@ -346,22 +300,15 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program)
                                }
                                else
                                        continue;
-                               if ( cadescriptors > 0 )
-                                       program.isCrypted=true;
                        }
-                       if ( !program.isCrypted )
+                       for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
+                               desc != pmt.getDescriptors()->end(); ++desc)
                        {
-                               for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
-                                       desc != pmt.getDescriptors()->end(); ++desc)
+                               if ((*desc)->getTag() == CA_DESCRIPTOR)
                                {
-                                       switch ((*desc)->getTag())
-                                       {
-                                       case CA_DESCRIPTOR:
-                                               program.isCrypted=true;
-                                               break;
-                                       }
+                                       CaDescriptor *descr = (CaDescriptor*)(*desc);
+                                       program.caids.insert(descr->getCaSystemId());
                                }
-                               break;
                        }
                }
                return 0;
@@ -410,6 +357,9 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program)
                        ++cnt;
                        program.textPid = tpid;
                }
+               CAID_LIST &caids = m_service->m_ca;
+               for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it)
+                       program.caids.insert(*it);
                if ( cnt )
                        return 0;
        }
@@ -499,6 +449,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux,
                ref.getChannelID(chid);
                res = m_resourceManager->allocateChannel(chid, m_channel);
                eDebug("allocate Channel: res %d", res);
+               eDVBCIInterfaces::getInstance()->addPMTHandler(this);
        } else
        {
                eDVBMetaParser parser;
@@ -549,7 +500,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux,
                if (ref.path.empty())
                {
                        delete m_dvb_scan;
-                       m_dvb_scan = new eDVBScan(m_channel);
+                       m_dvb_scan = new eDVBScan(m_channel, false);
                        m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection);
                }
        } else
index f4e99a57b5ba5f8175b528a87ce2ee4e6c88d8e8..57176d1f363d189365c445f47faf74d0b56efddf 100644 (file)
@@ -117,11 +117,11 @@ public:
        {
                std::vector<videoStream> videoStreams;
                std::vector<audioStream> audioStreams;
-               // ca info
+               std::set<uint16_t> caids;
                int pcrPid;
                int pmtPid;
                int textPid;
-               bool isCrypted;
+               bool isCrypted() { return !caids.empty(); }
                int audioChannel;
        };
        
@@ -131,7 +131,8 @@ public:
        PyObject *getCaIds();
        
        int getPVRChannel(ePtr<iDVBPVRChannel> &pvr_channel);
-       int getService(eServiceReferenceDVB &service) { service = m_reference; return 0; }
+       int getServiceReference(eServiceReferenceDVB &service) { service = m_reference; return 0; }
+       int getService(ePtr<eDVBService> &service) { service = m_service; return 0; }
        int getPMT(ePtr<eTable<ProgramMapSection> > &ptr) { return m_PMT.getCurrent(ptr); }
        int getChannel(eUsePtr<iDVBChannel> &channel);
 
index 3bfbe5717dc56a09b7d7e16a2c548de68bb47bd2..6549e32c4f1ebc017c6bcb1c5a383e5fe2d200cc 100644 (file)
 #include <lib/base/eerror.h>
 #include <lib/base/estring.h>
 #include <errno.h>
-#include <set>
 
-#define SCAN_eDebug(x...) eDebug(x)
-#define SCAN_eDebugNoNewLine(x...) eDebugNoNewLine(x)
+static bool scan_debug;
+#define SCAN_eDebug(x...) if (scan_debug) eDebug(x)
+#define SCAN_eDebugNoNewLine(x...) if (scan_debug) eDebugNoNewLine(x)
 
 DEFINE_REF(eDVBScan);
 
-eDVBScan::eDVBScan(iDVBChannel *channel)
-       :m_channel(channel), m_ready(0), m_flags(0), m_ready_all(readySDT)
-       ,m_channel_state(iDVBChannel::state_idle)
+eDVBScan::eDVBScan(iDVBChannel *channel, bool debug)
+       :m_channel(channel), m_channel_state(iDVBChannel::state_idle)
+       ,m_ready(0), m_ready_all(readySDT), m_flags(0)
 {
+       scan_debug=debug;
        if (m_channel->getDemux(m_demux))
                SCAN_eDebug("scan: failed to allocate demux!");
        m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
@@ -100,10 +101,10 @@ RESULT eDVBScan::nextChannel()
        
        if (m_ch_toScan.empty())
        {
-//             SCAN_eDebug("no channels left to scan.");
-//             SCAN_eDebug("%d channels scanned, %d were unavailable.", 
-//                             m_ch_scanned.size(), m_ch_unavailable.size());
-//             SCAN_eDebug("%d channels in database.", m_new_channels.size());
+               SCAN_eDebug("no channels left to scan.");
+               SCAN_eDebug("%d channels scanned, %d were unavailable.", 
+                               m_ch_scanned.size(), m_ch_unavailable.size());
+               SCAN_eDebug("%d channels in database.", m_new_channels.size());
                m_event(evtFinish);
                return -ENOENT;
        }
@@ -528,7 +529,8 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
                                dvb_service->m_service_name_sort = service->second->m_service_name_sort;
                        }
                        dvb_service->m_provider_name = service->second->m_provider_name;
-
+                       if (service->second->m_ca.size())
+                               dvb_service->m_ca = service->second->m_ca;
                        if (!dontRemoveOldFlags) // do not remove new found flags when not wished
                                dvb_service->m_flags &= ~eDVBService::dxNewFound;
                }
@@ -580,7 +582,6 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription
                                SCAN_eDebug("name '%s', provider_name '%s'", service->m_service_name.c_str(), service->m_provider_name.c_str());
                                break;
                        }
-/*
                        case CA_IDENTIFIER_DESCRIPTOR:
                        {
                                CaIdentifierDescriptor &d = (CaIdentifierDescriptor&)**desc;
@@ -589,12 +590,11 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription
                                for (CaSystemIdList::const_iterator i(caids.begin()); i != caids.end(); ++i)
                                {
                                        SCAN_eDebugNoNewLine("%04x ", *i);
-                                       service->m_ca.insert(*i);
+                                       service->m_ca.push_front(*i);
                                }
                                SCAN_eDebug("");
                                break;
                        }
-*/
                        default:
                                SCAN_eDebug("descr<%x>", (*desc)->getTag());
                                break;
index 1fc55e0fb3891e99e831edb1cec21e1710f3f4a5..fe5e0686fadbbd11ccf620e6a83e2ccea65eba07 100644 (file)
@@ -65,7 +65,7 @@ private:
        
        int m_flags;
 public:
-       eDVBScan(iDVBChannel *channel);
+       eDVBScan(iDVBChannel *channel, bool debug=false);
        ~eDVBScan();
 
        enum { scanNetworkSearch = 1, scanSearchBAT = 2, scanRemoveServices = 4, scanDontRemoveFeeds=8 };
index 7d96a296f408b8f4dec66b685cfae8446824743f..1be4232eef8a59db8c62e27048cecff59e3d4d66 100644 (file)
@@ -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");
index e8f30ab6449e117706639fa0c2f4f7cf89a0c973..2ef70b0e83eab137e1609e72467670819e32dec8 100644 (file)
@@ -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();
        
index 28e0659da8ec4178f59c5987244d9d40584d7123..201b36c44205c3bde109cc6b7066bde39200eaf8 100644 (file)
@@ -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:
index e1afd17494b41a8b6348620e6c81246821296979..ef69ed4d5c286afad40ff446429f21cc7c5c56e6 100644 (file)
@@ -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;
 }
 
index cf69ca9a05697e5929847f21f094ebe43a33e8a1..ae0d340db840412207995b554fd87732137b25db 100644 (file)
@@ -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:
index 4ff047def18a31edf39157eadb31e08f76407670..ddb42fdb636ea2d0496ceceaedc77047e33772e9 100644 (file)
 #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;
index 4f23974ec215a8ef5acbbeb1d90a301dce60d51c..3db215faac4886ca032ca823ca96ec53795b09e8 100644 (file)
@@ -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);
index 01df7947f623a382c6837eb3dfa52225900e1095..a32ce3449f28c9fdd204e7e5a9c8d4f6d160ca8f 100644 (file)
@@ -124,14 +124,20 @@ class CiMmi(Screen):
                else:
                        print "give cancel action to ci"        
 
+       def keyConfigEntry(self, key):
+               try:
+                       self["entries"].handleKey(key)
+               except AttributeError:
+                       pass
+
        def keyNumberGlobal(self, number):
-               self["entries"].handleKey(config.key[str(number)])
+               self.keyConfigEntry(config.key[str(number)])
 
        def keyLeft(self):
-               self["entries"].handleKey(config.key["prevElement"])
+               self.keyConfigEntry(config.key["prevElement"])
 
        def keyRight(self):
-               self["entries"].handleKey(config.key["nextElement"])
+               self.keyConfigEntry(config.key["nextElement"])
 
        def updateList(self, list):
                List = self["entries"]
@@ -156,7 +162,6 @@ class CiMmi(Screen):
 
                List.l.setList(list)
 
-
        def showWait(self):
                self.tag = "WAIT"
                self["title"].setText("")
index 928690d0c2dd7430fb8082008858defd9f262bb4..9cfe7073055a2aecf1191e4778c436b960914a38 100644 (file)
@@ -1129,7 +1129,7 @@ int eDVBServicePlay::getInfo(int w)
                        }
                }
                return -1;
-       case sIsCrypted: return program.isCrypted;
+       case sIsCrypted: return program.isCrypted();
        case sVideoPID: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].pid;
        case sVideoType: if (program.videoStreams.empty()) return -1; return program.videoStreams[0].type;
        case sAudioPID: if (program.audioStreams.empty()) return -1; return program.audioStreams[m_current_audio_stream].pid;