Merge branch 'enable_experimental_unicable_support' into experimental
[enigma2.git] / lib / dvb_ci / dvbci.cpp
index 800a40d2b98fa8ac93c5edf262ffc30ea7512689..883fb5a47fd8373b2ce6b7589e34ca91588c837d 100644 (file)
 
 #include <dvbsi++/ca_program_map_section.h>
 
 
 #include <dvbsi++/ca_program_map_section.h>
 
+//#define CIDEBUG 1
+
+#ifdef CIDEBUG
+       #define eDebugCI(x...) eDebug(x)
+#else
+       #define eDebugCI(x...)
+#endif
+
 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
 
 eDVBCIInterfaces::eDVBCIInterfaces()
 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
 
 eDVBCIInterfaces::eDVBCIInterfaces()
@@ -45,15 +53,21 @@ eDVBCIInterfaces::eDVBCIInterfaces()
                ++num_ci;
        }
 
                ++num_ci;
        }
 
-#if defined(DM8000)
-       setInputSource(0, TUNER_A);
-       setInputSource(1, TUNER_B);
-       setInputSource(2, TUNER_C);
-       setInputSource(3, TUNER_D);
-#else // force DM7025
-       setInputSource(0, TUNER_A);
-       setInputSource(1, TUNER_B);
-#endif
+       for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
+               it->setSource(TUNER_A);
+
+       if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
+       {
+               setInputSource(0, TUNER_A);
+               setInputSource(1, TUNER_B);
+               setInputSource(2, TUNER_C);
+               setInputSource(3, TUNER_D);
+       }
+       else
+       {
+               setInputSource(0, TUNER_A);
+               setInputSource(1, TUNER_B);
+       }
 
        eDebug("done, found %d common interface slots", num_ci);
 }
 
        eDebug("done, found %d common interface slots", num_ci);
 }
@@ -95,9 +109,6 @@ int eDVBCIInterfaces::reset(int slotid)
        if( (slot = getSlot(slotid)) == 0 )
                return -1;
 
        if( (slot = getSlot(slotid)) == 0 )
                return -1;
 
-       eDVBCISession::deleteSessions(slot);
-       ciRemoved(slot);
-
        return slot->reset();
 }
 
        return slot->reset();
 }
 
@@ -189,34 +200,38 @@ int eDVBCIInterfaces::cancelEnq(int slotid)
 
 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
 {
 
 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
 {
-       for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
-               it != m_pmt_handlers.end(); ++it)
+       if (slot->use_count)
        {
        {
-               eServiceReferenceDVB ref;
-               it->pmthandler->getServiceReference(ref);
-               slot->removeService(ref.getServiceID().get());
-               if (slot->use_count && !--slot->use_count)
+               eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
+               for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
+                       it != m_pmt_handlers.end(); ++it)
                {
                {
-                       if (slot->linked_next)
-                               slot->linked_next->setSource(slot->current_source);
-                       else
-                               setInputSource(slot->current_tuner, slot->current_source);
-
                        if (it->cislot == slot) // remove the base slot
                                it->cislot = slot->linked_next;
                        if (it->cislot == slot) // remove the base slot
                                it->cislot = slot->linked_next;
-                       else
+                       else if (it->cislot)
                        {
                        {
-                               if (slot->linked_next)
+                               eDVBCISlot *prevSlot = it->cislot, *hSlot = it->cislot->linked_next;
+                               while (hSlot)
                                {
                                {
-                                       eDVBCISlot *tmp = it->cislot;
-                                       while(tmp->linked_next != slot)
-                                               tmp = tmp->linked_next;
-                                       ASSERT(tmp);
-                                       tmp->linked_next = slot->linked_next;
+                                       if (hSlot == slot) {
+                                               prevSlot->linked_next = slot->linked_next;
+                                               break;
+                                       }
+                                       prevSlot = hSlot;
+                                       hSlot = hSlot->linked_next;
                                }
                        }
                                }
                        }
-                       slot->linked_next=0;
                }
                }
+               if (slot->linked_next)
+                       slot->linked_next->setSource(slot->current_source);
+               else // last CI in chain
+                       setInputSource(slot->current_tuner, slot->current_source);
+               slot->linked_next = 0;
+               slot->use_count=0;
+               slot->plugged=true;
+               slot->user_mapped=false;
+               slot->removeService(0xFFFF);
+               recheckPMTHandlers();
        }
 }
 
        }
 }
 
@@ -239,22 +254,50 @@ static bool canDescrambleMultipleServices(int slotid)
 
 void eDVBCIInterfaces::recheckPMTHandlers()
 {
 
 void eDVBCIInterfaces::recheckPMTHandlers()
 {
-//     eDebug("recheckPMTHAndlers()");
+       eDebugCI("recheckPMTHAndlers()");
        for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
                it != m_pmt_handlers.end(); ++it)
        {
                CAID_LIST caids;
                ePtr<eDVBService> service;
                eServiceReferenceDVB ref;
        for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
                it != m_pmt_handlers.end(); ++it)
        {
                CAID_LIST caids;
                ePtr<eDVBService> service;
                eServiceReferenceDVB ref;
+               eDVBCISlot *tmp = it->cislot;
                eDVBServicePMTHandler *pmthandler = it->pmthandler;
                eDVBServicePMTHandler::program p;
                eDVBServicePMTHandler *pmthandler = it->pmthandler;
                eDVBServicePMTHandler::program p;
+               bool plugged_cis_exist = false;
 
                pmthandler->getServiceReference(ref);
                pmthandler->getService(service);
 
                pmthandler->getServiceReference(ref);
                pmthandler->getService(service);
+
+               eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
+               for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
+                       if (ci_it->plugged && ci_it->getCAManager())
+                       {
+                               eDebug("Slot %d plugged", ci_it->getSlotID());
+                               ci_it->plugged = false;
+                               plugged_cis_exist = true;
+                       }
+
+               // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
+               if (!plugged_cis_exist)
+               {
+                       while(tmp)
+                       {
+                               if (!tmp->running_services.empty())
+                                       break;
+                               tmp=tmp->linked_next;
+                       }
+                       if (tmp) // we dont like to change tsmux for running services
+                       {
+                               eDebugCI("already assigned and running CI!\n");
+                               continue;
+                       }
+               }
+
                if (!pmthandler->getProgramInfo(p))
                {
                        int cnt=0;
                if (!pmthandler->getProgramInfo(p))
                {
                        int cnt=0;
-                       for (std::set<uint16_t>::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
+                       for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
                                caids.push_front(*x);
                        if (service && cnt)
                                service->m_ca = caids;
                                caids.push_front(*x);
                        if (service && cnt)
                                service->m_ca = caids;
@@ -268,50 +311,67 @@ void eDVBCIInterfaces::recheckPMTHandlers()
 
                for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
                {
 
                for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
                {
+                       eDebugCI("check Slot %d", ci_it->getSlotID());
                        bool useThis=false;
                        bool useThis=false;
+                       bool user_mapped=true;
                        eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
                        eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
+
                        if (ca_manager)
                        {
                                int mask=0;
                                if (!ci_it->possible_services.empty())
                                {
                                        mask |= 1;
                        if (ca_manager)
                        {
                                int mask=0;
                                if (!ci_it->possible_services.empty())
                                {
                                        mask |= 1;
-                                       std::set<eServiceReference>::iterator it = ci_it->possible_services.find(ref);
+                                       serviceSet::iterator it = ci_it->possible_services.find(ref);
                                        if (it != ci_it->possible_services.end())
                                        {
                                                eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
                                                useThis = true;
                                        }
                                        if (it != ci_it->possible_services.end())
                                        {
                                                eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
                                                useThis = true;
                                        }
+                                       else // check parent
+                                       {
+                                               eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
+                                               if (parent_ref)
+                                               {
+                                                       it = ci_it->possible_services.find(ref);
+                                                       if (it != ci_it->possible_services.end())
+                                                       {
+                                                               eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
+                                                                       parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
+                                                               useThis = true;
+                                                       }
+                                               }
+                                       }
                                }
                                if (!useThis && !ci_it->possible_providers.empty())
                                {
                                }
                                if (!useThis && !ci_it->possible_providers.empty())
                                {
-                                       bool parent=false;
+                                       eDVBNamespace ns = ref.getDVBNamespace();
                                        mask |= 2;
                                        if (!service) // subservice?
                                        {
                                                eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
                                                eDVBDB::getInstance()->getService(parent_ref, service);
                                        mask |= 2;
                                        if (!service) // subservice?
                                        {
                                                eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
                                                eDVBDB::getInstance()->getService(parent_ref, service);
-                                               parent=true;
                                        }
                                        if (service)
                                        {
                                        }
                                        if (service)
                                        {
-                                               std::set<std::string>::iterator it = ci_it->possible_providers.find(service->m_provider_name);
+                                               providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
                                                if (it != ci_it->possible_providers.end())
                                                {
                                                if (it != ci_it->possible_providers.end())
                                                {
-                                                       eDebug("'%s' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ci_it->getSlotID());
+                                                       eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
                                                        useThis = true;
                                                }
                                        }
                                }
                                if (!useThis && !ci_it->possible_caids.empty())
                                {
                                                        useThis = true;
                                                }
                                        }
                                }
                                if (!useThis && !ci_it->possible_caids.empty())
                                {
+                                       mask |= 4;
                                        for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
                                        {
                                        for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
                                        {
-                                               std::set<uint16_t>::iterator it = ci_it->possible_caids.find(*ca);
+                                               caidSet::iterator it = ci_it->possible_caids.find(*ca);
                                                if (it != ci_it->possible_caids.end())
                                                {
                                                        eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
                                                if (it != ci_it->possible_caids.end())
                                                {
                                                        eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
-                                                       useThis=true;
+                                                       useThis = true;
                                                        break;
                                                }
                                        }
                                                        break;
                                                }
                                        }
@@ -326,7 +386,8 @@ void eDVBCIInterfaces::recheckPMTHandlers()
                                                if ( z != ci_caids.end() && *z == *ca )
                                                {
                                                        eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
                                                if ( z != ci_caids.end() && *z == *ca )
                                                {
                                                        eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
-                                                       useThis=true;
+                                                       useThis = true;
+                                                       user_mapped = false;
                                                        break;
                                                }
                                        }
                                                        break;
                                                }
                                        }
@@ -335,46 +396,74 @@ void eDVBCIInterfaces::recheckPMTHandlers()
 
                        if (useThis)
                        {
 
                        if (useThis)
                        {
+                               // check if this CI is already assigned to this pmthandler
+                               eDVBCISlot *tmp = it->cislot;
+                               while(tmp)
+                               {
+                                       if (tmp == ci_it)
+                                               break;
+                                       tmp=tmp->linked_next;
+                               }
+                               if (tmp) // ignore already assigned cislots...
+                               {
+                                       eDebugCI("already assigned!");
+                                       continue;
+                               }
+                               eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
                                if (ci_it->use_count)  // check if this CI can descramble more than one service
                                {
                                if (ci_it->use_count)  // check if this CI can descramble more than one service
                                {
+                                       bool found = false;
                                        useThis = false;
                                        PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
                                        useThis = false;
                                        PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
-                                       while (tmp != m_pmt_handlers.end())
+                                       while (!found && tmp != m_pmt_handlers.end())
                                        {
                                        {
-                                               if ( tmp->cislot == ci_it && it != tmp )
+                                               eDebugCI(".");
+                                               eDVBCISlot *tmp_cislot = tmp->cislot;
+                                               while (!found && tmp_cislot)
                                                {
                                                {
+                                                       eDebugCI("..");
                                                        eServiceReferenceDVB ref2;
                                                        tmp->pmthandler->getServiceReference(ref2);
                                                        eServiceReferenceDVB ref2;
                                                        tmp->pmthandler->getServiceReference(ref2);
-                                                       eDVBChannelID s1, s2;
-                                                       if (ref != ref2)
-                                                       {
-                                                               ref.getChannelID(s1);
-                                                               ref2.getChannelID(s2);
-                                                       }
-                                                       if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
+                                                       if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
                                                        {
                                                        {
-                                                               useThis = true;
-                                                               break;
+                                                               eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
+                                                               eDVBChannelID s1, s2;
+                                                               if (ref != ref2)
+                                                               {
+                                                                       eDebugCI("different services!");
+                                                                       ref.getChannelID(s1);
+                                                                       ref2.getChannelID(s2);
+                                                               }
+                                                               if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
+                                                               {
+                                                                       found = true;
+                                                                       eDebugCI("found!");
+                                                                       eDVBCISlot *tmpci = it->cislot = tmp->cislot;
+                                                                       while(tmpci)
+                                                                       {
+                                                                               ++tmpci->use_count;
+                                                                               eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
+                                                                               tmpci=tmpci->linked_next;
+                                                                       }
+                                                               }
                                                        }
                                                        }
+                                                       tmp_cislot=tmp_cislot->linked_next;
                                                }
                                                }
+                                               eDebugCI("...");
                                                ++tmp;
                                        }
                                }
                                                ++tmp;
                                        }
                                }
+
                                if (useThis)
                                {
                                if (useThis)
                                {
-                                       // check if this CI is already assigned to this pmthandler
-                                       eDVBCISlot *tmp = it->cislot;
-                                       while(tmp)
+                                       if (ci_it->user_mapped)  // we dont like to link user mapped CIs
                                        {
                                        {
-                                               if (tmp == ci_it)
-                                                       break;
-                                       }
-
-                                       if (tmp) // ignore already assigned cislots...
+                                               eDebugCI("user mapped CI already in use... dont link!");
                                                continue;
                                                continue;
+                                       }
 
                                        ++ci_it->use_count;
 
                                        ++ci_it->use_count;
-//                                     eDebug("usecount now %d", ci_it->use_count);
+                                       eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
 
                                        data_source ci_source=CI_A;
                                        switch(ci_it->getSlotID())
 
                                        data_source ci_source=CI_A;
                                        switch(ci_it->getSlotID())
@@ -398,7 +487,7 @@ void eDVBCIInterfaces::recheckPMTHandlers()
                                                        if (!channel->getFrontend(frontend))
                                                        {
                                                                eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
                                                        if (!channel->getFrontend(frontend))
                                                        {
                                                                eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
-                                                               tunernum = fe->getID();
+                                                               tunernum = fe->getSlotID();
                                                        }
                                                }
                                                ASSERT(tunernum != -1);
                                                        }
                                                }
                                                ASSERT(tunernum != -1);
@@ -425,8 +514,15 @@ void eDVBCIInterfaces::recheckPMTHandlers()
                                                ci_it->linked_next->setSource(ci_source);
                                        }
                                        it->cislot = ci_it;
                                                ci_it->linked_next->setSource(ci_source);
                                        }
                                        it->cislot = ci_it;
+                                       eDebugCI("assigned!");
                                        gotPMT(pmthandler);
                                }
                                        gotPMT(pmthandler);
                                }
+
+                               if (it->cislot && user_mapped) // CI assigned to this pmthandler in this run.. and user mapped? then we break here.. we dont like to link other CIs to user mapped CIs
+                               {
+                                       eDebugCI("user mapped CI assigned... dont link CIs!");
+                                       break;
+                               }
                        }
                }
        }
                        }
                }
        }
@@ -456,6 +552,7 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
        if (it != m_pmt_handlers.end())
        {
                eDVBCISlot *slot = it->cislot;
        if (it != m_pmt_handlers.end())
        {
                eDVBCISlot *slot = it->cislot;
+               eDVBCISlot *base_slot = slot;
                eDVBServicePMTHandler *pmthandler = it->pmthandler;
                m_pmt_handlers.erase(it);
 
                eDVBServicePMTHandler *pmthandler = it->pmthandler;
                m_pmt_handlers.erase(it);
 
@@ -479,20 +576,17 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
 
                while(slot)
                {
 
                while(slot)
                {
+                       eDVBCISlot *next = slot->linked_next;
                        if (!sameServiceExist)
                        {
                        if (!sameServiceExist)
                        {
-                               if (slot->getNumOfServices() > 1)
-                               {
-                                       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
-                               }
+                               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());
                        }
 
                                slot->removeService(service_to_remove.getServiceID().get());
                        }
 
-                       eDVBCISlot *next = slot->linked_next;
                        if (!--slot->use_count)
                        {
                                if (slot->linked_next)
                        if (!--slot->use_count)
                        {
                                if (slot->linked_next)
@@ -500,27 +594,28 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
                                else
                                        setInputSource(slot->current_tuner, slot->current_source);
 
                                else
                                        setInputSource(slot->current_tuner, slot->current_source);
 
-                               if (it->cislot == slot) // remove the base slot
-                                       it->cislot = slot->linked_next;
-                               else
+                               if (base_slot != slot)
                                {
                                {
+                                       eDVBCISlot *tmp = it->cislot;
+                                       while(tmp->linked_next != slot)
+                                               tmp = tmp->linked_next;
+                                       ASSERT(tmp);
                                        if (slot->linked_next)
                                        if (slot->linked_next)
-                                       {
-                                               eDVBCISlot *tmp = it->cislot;
-                                               while(tmp->linked_next != slot)
-                                                       tmp = tmp->linked_next;
-                                               ASSERT(tmp);
                                                tmp->linked_next = slot->linked_next;
                                                tmp->linked_next = slot->linked_next;
-                                       }
+                                       else
+                                               tmp->linked_next = 0;
                                }
                                }
-                               slot->linked_next=0;
+                               else // removed old base slot.. update ptr
+                                       base_slot = slot->linked_next;
+                               slot->linked_next = 0;
+                               slot->user_mapped = false;
                        }
                        }
-//                     eDebug("use_count is now %d", slot->use_count);
+                       eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
                        slot = next;
                }
                        slot = next;
                }
+               // check if another service is waiting for the CI
+               recheckPMTHandlers();
        }
        }
-       // check if another service is waiting for the CI
-       recheckPMTHandlers();
 }
 
 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
 }
 
 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
@@ -532,7 +627,9 @@ void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
                eDVBCISlot *tmp = it->cislot;
                while(tmp)
                {
                eDVBCISlot *tmp = it->cislot;
                while(tmp)
                {
-                       tmp->sendCAPMT(pmthandler);
+                       eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
+                       if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
+                               tmp->sendCAPMT(pmthandler);
                        tmp = tmp->linked_next;
                }
        }
                        tmp = tmp->linked_next;
                }
        }
@@ -544,7 +641,7 @@ int eDVBCIInterfaces::getMMIState(int slotid)
 
        if( (slot = getSlot(slotid)) == 0 )
                return -1;
 
        if( (slot = getSlot(slotid)) == 0 )
                return -1;
-       
+
        return slot->getMMIState();
 }
 
        return slot->getMMIState();
 }
 
@@ -552,82 +649,85 @@ int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
 {
 //     eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
 //     eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
 {
 //     eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
 //     eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
-#if defined(DM8000)
-       char buf[64];
-       snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
+       if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
+       {
+               char buf[64];
+               snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
 
 
-       FILE *input=0;
-       if((input = fopen(buf, "wb")) == NULL) {
-               eDebug("cannot open %s", buf);
-               return 0;
-       }
+               FILE *input=0;
+               if((input = fopen(buf, "wb")) == NULL) {
+                       eDebug("cannot open %s", buf);
+                       return 0;
+               }
 
 
-       if (input > 3)
-               eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
+               if (tuner_no > 3)
+                       eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
 
 
-       switch(source)
-       {
-               case CI_A:
-                       fprintf(input, "CI0");
-                       break;
-               case CI_B:
-                       fprintf(input, "CI1");
-                       break;
-               case CI_C:
-                       fprintf(input, "CI2");
-                       break;
-               case CI_D:
-                       fprintf(input, "CI3");
-                       break;
-               case TUNER_A:
-                       fprintf(input, "A");
-                       break;
-               case TUNER_B:
-                       fprintf(input, "B");
-                       break;
-               case TUNER_C:
-                       fprintf(input, "C");
-                       break;
-               case TUNER_D:
-                       fprintf(input, "D");
-                       break;
-               default:
-                       eDebug("setInputSource for input %d failed!!!\n", (int)source);
+               switch(source)
+               {
+                       case CI_A:
+                               fprintf(input, "CI0");
+                               break;
+                       case CI_B:
+                               fprintf(input, "CI1");
+                               break;
+                       case CI_C:
+                               fprintf(input, "CI2");
                        break;
                        break;
+                       case CI_D:
+                               fprintf(input, "CI3");
+                               break;
+                       case TUNER_A:
+                               fprintf(input, "A");
+                               break;
+                       case TUNER_B:
+                               fprintf(input, "B");
+                               break;
+                       case TUNER_C:
+                               fprintf(input, "C");
+                               break;
+                       case TUNER_D:
+                               fprintf(input, "D");
+                               break;
+                       default:
+                               eDebug("setInputSource for input %d failed!!!\n", (int)source);
+                               break;
+               }
+
+               fclose(input);
        }
        }
+       else  // DM7025
+       {
+               char buf[64];
+               snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
 
 
-       fclose(input);
-#else // force DM7025
-       char buf[64];
-       snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
+               if (tuner_no > 1)
+                       eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
 
 
-       if (tuner_no > 1)
-               eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
+               FILE *input=0;
+               if((input = fopen(buf, "wb")) == NULL) {
+                       eDebug("cannot open %s", buf);
+                       return 0;
+               }
 
 
-       FILE *input=0;
-       if((input = fopen(buf, "wb")) == NULL) {
-               eDebug("cannot open %s", buf);
-               return 0;
-       }
+               switch(source)
+               {
+                       case CI_A:
+                               fprintf(input, "CI");
+                               break;
+                       case TUNER_A:
+                               fprintf(input, "A");
+                               break;
+                       case TUNER_B:
+                               fprintf(input, "B");
+                               break;
+                       default:
+                               eDebug("setInputSource for input %d failed!!!\n", (int)source);
+                               break;
+               }
 
 
-       switch(source)
-       {
-               case CI_A:
-                       fprintf(input, "CI");
-                       break;
-               case TUNER_A:
-                       fprintf(input, "A");
-                       break;
-               case TUNER_B:
-                       fprintf(input, "B");
-                       break;
-               default:
-                       eDebug("setInputSource for input %d failed!!!\n", (int)source);
-                       break;
+               fclose(input);
        }
        }
-
-       fclose(input);
-#endif
        eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
        return 0;
 }
        eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
        return 0;
 }
@@ -649,25 +749,28 @@ PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
        ePyObject caid_list = PyList_New(caids);
        ePyObject service_list = PyList_New(services);
        ePyObject provider_list = PyList_New(providers);
        ePyObject caid_list = PyList_New(caids);
        ePyObject service_list = PyList_New(services);
        ePyObject provider_list = PyList_New(providers);
-       std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
+       caidSet::iterator caid_it(slot->possible_caids.begin());
        while(caids)
        {
                --caids;
        while(caids)
        {
                --caids;
-               PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
+               PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
                ++caid_it;
        }
                ++caid_it;
        }
-       std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
+       serviceSet::iterator ref_it(slot->possible_services.begin());
        while(services)
        {
                --services;
        while(services)
        {
                --services;
-               PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
+               PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
                ++ref_it;
        }
                ++ref_it;
        }
-       std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
+       providerSet::iterator provider_it(slot->possible_providers.begin());
        while(providers)
        {
        while(providers)
        {
+               ePyObject tuple = PyTuple_New(2);
+               PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
+               PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
                --providers;
                --providers;
-               PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
+               PyList_SET_ITEM(provider_list, providers, tuple);
                ++provider_it;
        }
        PyTuple_SET_ITEM(tuple, 0, service_list);
                ++provider_it;
        }
        PyTuple_SET_ITEM(tuple, 0, service_list);
@@ -702,7 +805,7 @@ RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject)
        {
                const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
                        "first argument should be a pythonlist with possible services\n"
        {
                const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
                        "first argument should be a pythonlist with possible services\n"
-                       "second argument should be a pythonlist with possible providers\n"
+                       "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
                        "third argument should be a pythonlist with possible caids";
                PyErr_SetString(PyExc_StandardError, errstr);
                return -1;
                        "third argument should be a pythonlist with possible caids";
                PyErr_SetString(PyExc_StandardError, errstr);
                return -1;
@@ -747,33 +850,55 @@ RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject)
        while(size)
        {
                --size;
        while(size)
        {
                --size;
-               ePyObject str = PyList_GET_ITEM(provider_list, size);
-               if (!PyString_Check(str))
+               ePyObject tuple = PyList_GET_ITEM(provider_list, size);
+               if (!PyTuple_Check(tuple))
                {
                        char buf[255];
                {
                        char buf[255];
-                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
                        PyErr_SetString(PyExc_StandardError, buf);
                        return -1;
                }
                        PyErr_SetString(PyExc_StandardError, buf);
                        return -1;
                }
-               char *tmpstr = PyString_AS_STRING(str);
+               if (PyTuple_Size(tuple) != 2)
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
+               {
+                       char buf[255];
+                       snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
+                       PyErr_SetString(PyExc_StandardError, buf);
+                       return -1;
+               }
+               char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
+               uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
                if (strlen(tmpstr))
                if (strlen(tmpstr))
-                       slot->possible_providers.insert(tmpstr);
+                       slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
                else
                else
-                       eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
+                       eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
        };
        size = PyList_Size(caid_list);
        while(size)
        {
                --size;
                ePyObject caid = PyList_GET_ITEM(caid_list, size);
        };
        size = PyList_Size(caid_list);
        while(size)
        {
                --size;
                ePyObject caid = PyList_GET_ITEM(caid_list, size);
-               if (!PyInt_Check(caid))
+               if (!PyLong_Check(caid))
                {
                        char buf[255];
                        snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
                        PyErr_SetString(PyExc_StandardError, buf);
                        return -1;
                }
                {
                        char buf[255];
                        snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
                        PyErr_SetString(PyExc_StandardError, buf);
                        return -1;
                }
-               int tmpcaid = PyInt_AsLong(caid);
+               int tmpcaid = PyLong_AsLong(caid);
                if (tmpcaid > 0 && tmpcaid < 0x10000)
                        slot->possible_caids.insert(tmpcaid);
                else
                if (tmpcaid > 0 && tmpcaid < 0x10000)
                        slot->possible_caids.insert(tmpcaid);
                else
@@ -782,6 +907,39 @@ RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject)
        return 0;
 }
 
        return 0;
 }
 
+PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
+{
+       eDVBCISlot *slot = getSlot(slotid);
+       if (!slot)
+       {
+               char tmp[255];
+               snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
+               PyErr_SetString(PyExc_StandardError, tmp);
+       }
+       else
+       {
+               int idx=0;
+               eDVBCICAManagerSession *ca_manager = slot->getCAManager();
+               const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
+               ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
+               if (ci_caids)
+               {
+                       for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
+                               PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
+               }
+               return list;
+       }
+       return 0;
+}
+
+int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
+{
+       eDVBCISlot *slot = getSlot(slotid);
+       if (slot)
+               return slot->setClockRate(rate);
+       return -1;
+}
+
 int eDVBCISlot::send(const unsigned char *data, size_t len)
 {
        int res=0;
 int eDVBCISlot::send(const unsigned char *data, size_t len)
 {
        int res=0;
@@ -807,17 +965,17 @@ int eDVBCISlot::send(const unsigned char *data, size_t len)
 
 void eDVBCISlot::data(int what)
 {
 
 void eDVBCISlot::data(int what)
 {
+       eDebugCI("CISlot %d what %d\n", getSlotID(), what);
        if(what == eSocketNotifier::Priority) {
                if(state != stateRemoved) {
                        state = stateRemoved;
        if(what == eSocketNotifier::Priority) {
                if(state != stateRemoved) {
                        state = stateRemoved;
-                       eDebug("ci removed");
                        while(sendqueue.size())
                        {
                                delete [] sendqueue.top().data;
                                sendqueue.pop();
                        }
                        while(sendqueue.size())
                        {
                                delete [] sendqueue.top().data;
                                sendqueue.pop();
                        }
-                       eDVBCIInterfaces::getInstance()->ciRemoved(this);
                        eDVBCISession::deleteSessions(this);
                        eDVBCISession::deleteSessions(this);
+                       eDVBCIInterfaces::getInstance()->ciRemoved(this);
                        notifier->setRequested(eSocketNotifier::Read);
                        eDVBCI_UI::getInstance()->setState(getSlotID(),0);
                }
                        notifier->setRequested(eSocketNotifier::Read);
                        eDVBCI_UI::getInstance()->setState(getSlotID(),0);
                }
@@ -828,7 +986,7 @@ void eDVBCISlot::data(int what)
                reset();
 
        if(state != stateInserted) {
                reset();
 
        if(state != stateInserted) {
-               eDebug("ci inserted");
+               eDebug("ci inserted in slot %d", getSlotID());
                state = stateInserted;
                eDVBCI_UI::getInstance()->setState(getSlotID(),1);
                notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
                state = stateInserted;
                eDVBCI_UI::getInstance()->setState(getSlotID(),1);
                notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
@@ -876,29 +1034,35 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
        ca_manager = 0;
        use_count = 0;
        linked_next = 0;
        ca_manager = 0;
        use_count = 0;
        linked_next = 0;
+       user_mapped = false;
+       plugged = true;
        
        slotid = nr;
 
        sprintf(filename, "/dev/ci%d", nr);
 
        
        slotid = nr;
 
        sprintf(filename, "/dev/ci%d", nr);
 
+//     possible_caids.insert(0x1702);
+//     possible_providers.insert(providerPair("PREMIERE", 0xC00000));
+//     possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
+
        fd = ::open(filename, O_RDWR | O_NONBLOCK);
 
        fd = ::open(filename, O_RDWR | O_NONBLOCK);
 
-       eDebug("eDVBCISlot has fd %d", fd);
+       eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
        state = stateInvalid;
 
        if (fd >= 0)
        {
        state = stateInvalid;
 
        if (fd >= 0)
        {
-               notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
+               notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
                CONNECT(notifier->activated, eDVBCISlot::data);
        } else
        {
                perror(filename);
        }
                CONNECT(notifier->activated, eDVBCISlot::data);
        } else
        {
                perror(filename);
        }
-       setSource(TUNER_A);
 }
 
 eDVBCISlot::~eDVBCISlot()
 {
 }
 
 eDVBCISlot::~eDVBCISlot()
 {
+       eDVBCISession::deleteSessions(this);
 }
 
 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
 }
 
 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
@@ -923,7 +1087,7 @@ int eDVBCISlot::getSlotID()
 
 int eDVBCISlot::reset()
 {
 
 int eDVBCISlot::reset()
 {
-       eDebug("edvbcislot: reset requested");
+       eDebug("CI Slot %d: reset requested", getSlotID());
 
        if (state == stateInvalid)
        {
 
        if (state == stateInvalid)
        {
@@ -946,7 +1110,7 @@ int eDVBCISlot::reset()
 
 int eDVBCISlot::startMMI()
 {
 
 int eDVBCISlot::startMMI()
 {
-       eDebug("edvbcislot: startMMI()");
+       eDebug("CI Slot %d: startMMI()", getSlotID());
        
        if(application_manager)
                application_manager->startMMI();
        
        if(application_manager)
                application_manager->startMMI();
@@ -956,7 +1120,7 @@ int eDVBCISlot::startMMI()
 
 int eDVBCISlot::stopMMI()
 {
 
 int eDVBCISlot::stopMMI()
 {
-       eDebug("edvbcislot: stopMMI()");
+       eDebug("CI Slot %d: stopMMI()", getSlotID());
 
        if(mmi_session)
                mmi_session->stopMMI();
 
        if(mmi_session)
                mmi_session->stopMMI();
@@ -966,7 +1130,7 @@ int eDVBCISlot::stopMMI()
 
 int eDVBCISlot::answerText(int answer)
 {
 
 int eDVBCISlot::answerText(int answer)
 {
-       eDebug("edvbcislot: answerText(%d)", answer);
+       eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
 
        if(mmi_session)
                mmi_session->answerText(answer);
 
        if(mmi_session)
                mmi_session->answerText(answer);
@@ -984,7 +1148,7 @@ int eDVBCISlot::getMMIState()
 
 int eDVBCISlot::answerEnq(char *value)
 {
 
 int eDVBCISlot::answerEnq(char *value)
 {
-       eDebug("edvbcislot: answerENQ(%s)", value);
+       eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
 
        if(mmi_session)
                mmi_session->answerEnq(value);
 
        if(mmi_session)
                mmi_session->answerEnq(value);
@@ -994,7 +1158,7 @@ int eDVBCISlot::answerEnq(char *value)
 
 int eDVBCISlot::cancelEnq()
 {
 
 int eDVBCISlot::cancelEnq()
 {
-       eDebug("edvbcislot: cancelENQ");
+       eDebug("CI Slot %d: cancelENQ", getSlotID());
 
        if(mmi_session)
                mmi_session->cancelEnq();
 
        if(mmi_session)
                mmi_session->cancelEnq();
@@ -1024,10 +1188,11 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
                uint16_t program_number = ref.getServiceID().get();
                std::map<uint16_t, uint8_t>::iterator it =
                        running_services.find(program_number);
                uint16_t program_number = ref.getServiceID().get();
                std::map<uint16_t, uint8_t>::iterator it =
                        running_services.find(program_number);
+               bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
 
                if ( it != running_services.end() &&
                        (pmt_version == it->second) &&
 
                if ( it != running_services.end() &&
                        (pmt_version == it->second) &&
-                       !(caids.size() == 1 && caids[0] == 0xFFFF) )
+                       !sendEmpty )
                {
                        eDebug("[eDVBCISlot] dont send self capmt version twice");
                        return -1;
                {
                        eDebug("[eDVBCISlot] dont send self capmt version twice");
                        return -1;
@@ -1040,9 +1205,9 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
                {
                        unsigned char raw_data[2048];
 
                {
                        unsigned char raw_data[2048];
 
-//                     eDebug("send %s capmt for service %04x",
+//                     eDebug("send %s capmt for service %04x to slot %d",
 //                             it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
 //                             it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
-//                             program_number);
+//                             program_number, slotid);
 
                        CaProgramMapSection capmt(*i++,
                                it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
 
                        CaProgramMapSection capmt(*i++,
                                it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
@@ -1052,7 +1217,7 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
                                capmt.append(*i++);
                        }
                        capmt.writeToBuffer(raw_data);
                                capmt.append(*i++);
                        }
                        capmt.writeToBuffer(raw_data);
-#if 1
+
 // begin calc capmt length
                        int wp=0;
                        int hlen;
 // begin calc capmt length
                        int wp=0;
                        int hlen;
@@ -1073,19 +1238,22 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<u
                                hlen = 4;
                        }
 // end calc capmt length
                                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("");
-#endif
-                       if (caids.size() == 1 && caids[0] == 0xFFFF)
+
+                       if (sendEmpty)
                        {
 //                             eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
                        {
 //                             eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
+                               if (sendEmpty && running_services.size() == 1)  // check if this is the capmt for the last running service
+                                       raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
                                raw_data[hlen+3] &= ~0x3E;
                                raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
 //                             eDebug(" new 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]);
                        }
 
+//                     eDebug("ca_manager %p dump capmt:", ca_manager);
+//                     for(int i=0;i<wp;i++)
+//                             eDebugNoNewLine("%02x ", raw_data[i]);
+//                     eDebug("");
+
                        //dont need tag and lenfield
                        ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
                        running_services[program_number] = pmt_version;
                        //dont need tag and lenfield
                        ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
                        running_services[program_number] = pmt_version;
@@ -1105,57 +1273,77 @@ void eDVBCISlot::removeService(uint16_t program_number)
 int eDVBCISlot::setSource(data_source source)
 {
        current_source = source;
 int eDVBCISlot::setSource(data_source source)
 {
        current_source = source;
-#if defined(DM8000)
+       if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
+       {
+               char buf[64];
+               snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
+               FILE *ci = fopen(buf, "wb");
+               switch(source)
+               {
+                       case CI_A:
+                               fprintf(ci, "CI0");
+                               break;
+                       case CI_B:
+                               fprintf(ci, "CI1");
+                               break;
+                       case CI_C:
+                               fprintf(ci, "CI2");
+                               break;
+                       case CI_D:
+                               fprintf(ci, "CI3");
+                               break;
+                       case TUNER_A:
+                               fprintf(ci, "A");
+                               break;
+                       case TUNER_B:
+                               fprintf(ci, "B");
+                               break;
+                       case TUNER_C:
+                               fprintf(ci, "C");
+                               break;
+                               case TUNER_D:
+                               fprintf(ci, "D");
+                               break;
+                       default:
+                               eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
+                               break;
+               }
+               fclose(ci);
+       }
+       else // DM7025
+       {
+//             eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+//             eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
+               FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
+               if(ci == NULL) {
+                       eDebug("cannot open /proc/stb/tsmux/input2");
+                       return 0;
+               }
+               if (source != TUNER_A && source != TUNER_B)
+                       eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
+               else
+                       fprintf(ci, "%s", source==TUNER_A ? "A" : "B");  // configure CI data source (TunerA, TunerB)
+               fclose(ci);
+       }
+       eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
+       return 0;
+}
+
+int eDVBCISlot::setClockRate(int rate)
+{
        char buf[64];
        char buf[64];
-       snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
+       snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
        FILE *ci = fopen(buf, "wb");
        FILE *ci = fopen(buf, "wb");
-       switch(source)
+       if (ci)
        {
        {
-               case CI_A:
-                       fprintf(ci, "CI0");
-                       break;
-               case CI_B:
-                       fprintf(ci, "CI1");
-                       break;
-               case CI_C:
-                       fprintf(ci, "CI2");
-                       break;
-               case CI_D:
-                       fprintf(ci, "CI3");
-                       break;
-               case TUNER_A:
-                       fprintf(ci, "A");
-                       break;
-               case TUNER_B:
-                       fprintf(ci, "B");
-                       break;
-               case TUNER_C:
-                       fprintf(ci, "C");
-                       break;
-               case TUNER_D:
-                       fprintf(ci, "D");
-                       break;
-               default:
-                       eDebug("setSource %d failed!!!\n", (int)source);
-                       break;
-       }
-       fclose(ci);
-#else // force DM7025
-//     eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-//     eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
-       FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
-       if(ci == NULL) {
-               eDebug("cannot open /proc/stb/tsmux/input2");
+               if (rate)
+                       fprintf(ci, "high");
+               else
+                       fprintf(ci, "normal");
+               fclose(ci);
                return 0;
        }
                return 0;
        }
-       if (source != TUNER_A && source != TUNER_B)
-               eDebug("setSource %d failed!!!\n", (int)source);
-       else
-               fprintf(ci, "%s", source==TUNER_A ? "A" : "B");  // configure CI data source (TunerA, TunerB)
-       fclose(ci);
-#endif
-       eDebug("eDVBCISlot->setSource(%d)", (int)source);
-       return 0;
+       return -1;
 }
 
 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");
 }
 
 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");