fix
[enigma2.git] / lib / dvb_ci / dvbci.cpp
index efd6925ce6f789d104961355343b9ec31fa1d6b6..e7d9b27b9bad06a20cca79bad02b10513d2be08d 100644 (file)
@@ -76,6 +76,16 @@ int eDVBCIInterfaces::reset(int slotid)
        return slot->reset();
 }
 
+int eDVBCIInterfaces::enableTS(int slotid, int enable)
+{
+       eDVBCISlot *slot;
+
+       if( (slot = getSlot(slotid)) == 0 )
+               return -1;
+       
+       return slot->enableTS(enable);
+}
+
 int eDVBCIInterfaces::initialize(int slotid)
 {
        eDVBCISlot *slot;
@@ -116,14 +126,24 @@ int eDVBCIInterfaces::answerText(int slotid, int answer)
        return slot->answerText(answer);
 }
 
-int eDVBCIInterfaces::answerEnq(int slotid, int answer, char *value)
+int eDVBCIInterfaces::answerEnq(int slotid, char *value)
 {
        eDVBCISlot *slot;
 
        if( (slot = getSlot(slotid)) == 0 )
                return -1;
        
-       return slot->answerEnq(answer, value);
+       return slot->answerEnq(value);
+}
+
+int eDVBCIInterfaces::cancelEnq(int slotid)
+{
+       eDVBCISlot *slot;
+
+       if( (slot = getSlot(slotid)) == 0 )
+               return -1;
+       
+       return slot->cancelEnq();
 }
 
 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
@@ -133,45 +153,70 @@ void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
        eServiceReferenceDVB service;
        pmthandler->getService(service);
 
-       PMTHandlerSet::iterator it = m_pmt_handlers.begin();
-       while (it != m_pmt_handlers.end())
+       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)
        {
-               eServiceReferenceDVB ref;
-               it->pmthandler->getService(ref);
-               if ( service == ref && it->usedby )
-                       new_handler.usedby = it->usedby;
-               break;
+               if (ci_it->use_count)
+                       continue;
+               ci_it->use_count=1;
+               new_handler.cislot = ci_it;
+               new_handler.cislot->resetPrevSentCAPMTVersion();
        }
-       m_pmt_handlers.insert(new_handler);
+
+       if (ci_it == m_slots.end())
+       {
+               PMTHandlerList::iterator it = m_pmt_handlers.begin();
+               while (it != m_pmt_handlers.end())
+               {
+                       eServiceReferenceDVB ref;
+                       it->pmthandler->getService(ref);
+                       if ( service == ref && it->cislot )
+                       {
+                               new_handler.cislot = it->cislot;
+                               ++new_handler.cislot->use_count;
+                               break;
+                       }
+                       ++it;
+               }
+       }
+
+       m_pmt_handlers.push_back(new_handler);
 }
 
 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
 {
-       PMTHandlerSet::iterator it=m_pmt_handlers.find(pmthandler);
+       PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
        if (it != m_pmt_handlers.end())
        {
-               eDVBCISlot *slot = it->usedby;
+               eDVBCISlot *slot = it->cislot;
                eDVBServicePMTHandler *pmthandler = it->pmthandler;
                m_pmt_handlers.erase(it);
-               if (slot)
+               if (slot && !--slot->use_count)
                {
-                       eServiceReferenceDVB removed_service;
-                       pmthandler->getService(removed_service);
-                       PMTHandlerSet::iterator it=m_pmt_handlers.begin();
+#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;
-                               it->pmthandler->getService(ref);
-                               if (ref == removed_service)
+                               if ( !it->cislot )
+                               {
+                                       it->cislot = slot;
+                                       ++slot->use_count;
+                                       slot->resetPrevSentCAPMTVersion();
+                                       slot->sendCAPMT(it->pmthandler);
                                        break;
+                               }
                                ++it;
                        }
-                       if ( it == m_pmt_handlers.end() && slot->getPrevSentCAPMTVersion() != 0xFF  )
-                       {
-                               std::vector<uint16_t> caids;
-                               caids.push_back(0xFFFF);
-                               slot->sendCAPMT(pmthandler, caids);
-                       }
                }
        }
 }
@@ -179,25 +224,10 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
 {
        eDebug("[eDVBCIInterfaces] gotPMT");
-       PMTHandlerSet::iterator it=m_pmt_handlers.find(pmthandler);
+       PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
        eServiceReferenceDVB service;
-       if ( it != m_pmt_handlers.end() )
-       {
-               eDebug("[eDVBCIInterfaces] usedby %p", it->usedby);
-               if (!it->usedby)
-               {
-                       // HACK this assigns ALL RUNNING SERVICES to the first free CI !!!
-                       for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
-                       {
-                               eDVBCISlot **usedby = &it->usedby;
-                               *usedby = ci_it;
-                               (*usedby)->resetPrevSentCAPMTVersion();
-                               break;
-                       }
-               }
-               if (it->usedby)
-                       it->usedby->sendCAPMT(pmthandler);
-       }
+       if ( it != m_pmt_handlers.end() && it->cislot)
+               it->cislot->sendCAPMT(pmthandler);
 }
 
 int eDVBCIInterfaces::getMMIState(int slotid)
@@ -233,6 +263,7 @@ void eDVBCISlot::data(int what)
        if(what == eSocketNotifier::Priority) {
                if(state != stateRemoved) {
                        state = stateRemoved;
+                       enableTS(0);
                        printf("ci removed\n");
                        notifier->setRequested(eSocketNotifier::Read);
                        //HACK
@@ -283,6 +314,7 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
        application_manager = 0;
        mmi_session = 0;
        ca_manager = 0;
+       use_count = 0;
        
        slotid = nr;
 
@@ -306,6 +338,7 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
 
 eDVBCISlot::~eDVBCISlot()
 {
+       enableTS(0);
 }
 
 int eDVBCISlot::getSlotID()
@@ -317,6 +350,8 @@ int eDVBCISlot::reset()
 {
        printf("edvbcislot: reset requested\n");
 
+       enableTS(0);
+
        ioctl(fd, 0);
 
        return 0;
@@ -366,9 +401,19 @@ int eDVBCISlot::getMMIState()
        return 0;
 }
 
-int eDVBCISlot::answerEnq(int answer, char *value)
+int eDVBCISlot::answerEnq(char *value)
 {
-       printf("edvbcislot: answerMMI(%d,%s)\n", answer, value);
+       printf("edvbcislot: answerENQ(%s)\n", value);
+       return 0;
+}
+
+int eDVBCISlot::cancelEnq()
+{
+       printf("edvbcislot: cancelENQ\n");
+
+       if(mmi_session)
+               mmi_session->cancelEnq();
+
        return 0;
 }
 
@@ -410,7 +455,7 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
                                int i=0;
                                int lenbytes = raw_data[3] & ~0x80;
                                while(i < lenbytes)
-                                       wp |= (raw_data[4+i] << (8 * i++));
+                                       wp = (wp << 8) | raw_data[4 + i++];
                                wp+=4;
                                wp+=lenbytes;
                                hlen = 4 + lenbytes;
@@ -441,4 +486,22 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
        
 }
 
+int eDVBCISlot::enableTS(int enable)
+{
+       printf("eDVBCISlot::enableTS(%d)\n", enable);
+
+       FILE *f;
+       if((f = fopen("/proc/stb/tsmux/input0", "wb")) == NULL) {
+               printf("cannot open /proc/stb/audio/j1_mute\n");
+               return 0;
+       }
+
+       fprintf(f, "%s", enable?"CI":"A");
+
+       fclose(f);
+
+       return 0;
+}
+
+
 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");