4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6 #include <lib/base/ebase.h>
8 #include <lib/base/eerror.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/pmt.h>
12 #include <lib/dvb_ci/dvbci.h>
13 #include <lib/dvb_ci/dvbci_session.h>
14 #include <lib/dvb_ci/dvbci_camgr.h>
15 #include <lib/dvb_ci/dvbci_ui.h>
16 #include <lib/dvb_ci/dvbci_appmgr.h>
17 #include <lib/dvb_ci/dvbci_mmi.h>
19 #include <dvbsi++/ca_program_map_section.h>
24 #define eDebugCI(x...) eDebug(x)
26 #define eDebugCI(x...)
29 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
31 eDVBCIInterfaces::eDVBCIInterfaces()
37 eDebug("scanning for common interfaces..");
43 sprintf(filename, "/dev/ci%d", num_ci);
45 if (stat(filename, &s))
48 ePtr<eDVBCISlot> cislot;
50 cislot = new eDVBCISlot(eApp, num_ci);
51 m_slots.push_back(cislot);
56 for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
57 it->setSource(TUNER_A);
59 if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
61 setInputSource(0, TUNER_A);
62 setInputSource(1, TUNER_B);
63 setInputSource(2, TUNER_C);
64 setInputSource(3, TUNER_D);
68 setInputSource(0, TUNER_A);
69 setInputSource(1, TUNER_B);
72 eDebug("done, found %d common interface slots", num_ci);
75 eDVBCIInterfaces::~eDVBCIInterfaces()
79 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
84 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
86 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
87 if(i->getSlotID() == slotid)
90 eDebug("FIXME: request for unknown slot");
95 int eDVBCIInterfaces::getSlotState(int slotid)
99 if( (slot = getSlot(slotid)) == 0 )
100 return eDVBCISlot::stateInvalid;
102 return slot->getState();
105 int eDVBCIInterfaces::reset(int slotid)
109 if( (slot = getSlot(slotid)) == 0 )
112 return slot->reset();
115 int eDVBCIInterfaces::initialize(int slotid)
119 if( (slot = getSlot(slotid)) == 0 )
122 slot->removeService();
124 return sendCAPMT(slotid);
127 int eDVBCIInterfaces::sendCAPMT(int slotid)
131 if( (slot = getSlot(slotid)) == 0 )
134 PMTHandlerList::iterator it = m_pmt_handlers.begin();
135 while (it != m_pmt_handlers.end())
137 eDVBCISlot *tmp = it->cislot;
138 while (tmp && tmp != slot)
139 tmp = tmp->linked_next;
142 tmp->sendCAPMT(it->pmthandler); // send capmt
151 int eDVBCIInterfaces::startMMI(int slotid)
155 if( (slot = getSlot(slotid)) == 0 )
158 return slot->startMMI();
161 int eDVBCIInterfaces::stopMMI(int slotid)
165 if( (slot = getSlot(slotid)) == 0 )
168 return slot->stopMMI();
171 int eDVBCIInterfaces::answerText(int slotid, int answer)
175 if( (slot = getSlot(slotid)) == 0 )
178 return slot->answerText(answer);
181 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
185 if( (slot = getSlot(slotid)) == 0 )
188 return slot->answerEnq(value);
191 int eDVBCIInterfaces::cancelEnq(int slotid)
195 if( (slot = getSlot(slotid)) == 0 )
198 return slot->cancelEnq();
201 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
205 eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
206 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
207 it != m_pmt_handlers.end(); ++it)
209 if (it->cislot == slot) // remove the base slot
210 it->cislot = slot->linked_next;
213 eDVBCISlot *prevSlot = it->cislot, *hSlot = it->cislot->linked_next;
217 prevSlot->linked_next = slot->linked_next;
221 hSlot = hSlot->linked_next;
225 if (slot->linked_next)
226 slot->linked_next->setSource(slot->current_source);
227 else // last CI in chain
229 if(slot->current_tuner == 99)
230 slot->setSource(PVR_NONE);
232 setInputSource(slot->current_tuner, slot->current_source);
234 slot->removeVtunerPid();
236 slot->linked_next = 0;
239 slot->user_mapped=false;
240 slot->removeService(0xFFFF);
241 recheckPMTHandlers();
245 static bool canDescrambleMultipleServices(int slotid)
248 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
250 ePythonConfigQuery::getConfigValue(configStr, str);
251 eDebugCI("canDescrambleMultipleServices %s", str.c_str());
254 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
255 if (appname.find("AlphaCrypt") != std::string::npos)
258 else if (str == "yes")
263 void eDVBCIInterfaces::recheckPMTHandlers()
265 eDebugCI("recheckPMTHAndlers()");
266 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
267 it != m_pmt_handlers.end(); ++it)
270 ePtr<eDVBService> service;
271 eServiceReferenceDVB ref;
272 eDVBCISlot *tmp = it->cislot;
273 eDVBServicePMTHandler *pmthandler = it->pmthandler;
274 eDVBServicePMTHandler::program p;
275 bool plugged_cis_exist = false;
277 pmthandler->getServiceReference(ref);
278 pmthandler->getService(service);
280 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
281 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
282 if (ci_it->plugged && ci_it->getCAManager())
284 eDebug("Slot %d plugged", ci_it->getSlotID());
285 ci_it->plugged = false;
286 plugged_cis_exist = true;
289 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
290 if (!plugged_cis_exist)
294 if (!tmp->running_services.empty())
296 tmp=tmp->linked_next;
298 if (tmp) // we dont like to change tsmux for running services
300 eDebugCI("already assigned and running CI!\n");
305 if (!pmthandler->getProgramInfo(p))
308 std::set<eDVBServicePMTHandler::program::capid_pair> set(p.caids.begin(), p.caids.end());
309 for (std::set<eDVBServicePMTHandler::program::capid_pair>::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt)
310 caids.push_front(x->caid);
312 service->m_ca = caids;
316 caids = service->m_ca;
319 continue; // unscrambled service
321 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
323 eDebugCI("check Slot %d", ci_it->getSlotID());
325 bool user_mapped=true;
326 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
331 if (!ci_it->possible_services.empty())
334 serviceSet::iterator it = ci_it->possible_services.find(ref);
335 if (it != ci_it->possible_services.end())
337 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
342 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
345 it = ci_it->possible_services.find(ref);
346 if (it != ci_it->possible_services.end())
348 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
349 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
355 if (!useThis && !ci_it->possible_providers.empty())
357 eDVBNamespace ns = ref.getDVBNamespace();
359 if (!service) // subservice?
361 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
362 eDVBDB::getInstance()->getService(parent_ref, service);
366 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
367 if (it != ci_it->possible_providers.end())
369 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
374 if (!useThis && !ci_it->possible_caids.empty())
377 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
379 caidSet::iterator it = ci_it->possible_caids.find(*ca);
380 if (it != ci_it->possible_caids.end())
382 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
388 if (!useThis && !mask)
390 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
391 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
393 std::vector<uint16_t>::const_iterator z =
394 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
395 if ( z != ci_caids.end() && *z == *ca )
397 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
400 ci_it->addVtunerPid(pmthandler);
409 // check if this CI is already assigned to this pmthandler
410 eDVBCISlot *tmp = it->cislot;
415 tmp=tmp->linked_next;
417 if (tmp) // ignore already assigned cislots...
419 eDebugCI("already assigned!");
422 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
423 if (ci_it->use_count) // check if this CI can descramble more than one service
427 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
428 while (!found && tmp != m_pmt_handlers.end())
431 eDVBCISlot *tmp_cislot = tmp->cislot;
432 while (!found && tmp_cislot)
435 eServiceReferenceDVB ref2;
436 tmp->pmthandler->getServiceReference(ref2);
437 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
439 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
440 eDVBChannelID s1, s2;
443 eDebugCI("different services!");
444 ref.getChannelID(s1);
445 ref2.getChannelID(s2);
447 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
451 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
455 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
456 tmpci=tmpci->linked_next;
460 tmp_cislot=tmp_cislot->linked_next;
469 if (ci_it->user_mapped) // we dont like to link user mapped CIs
471 eDebugCI("user mapped CI already in use... dont link!");
476 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
478 data_source ci_source=CI_A;
479 switch(ci_it->getSlotID())
481 case 0: ci_source = CI_A; break;
482 case 1: ci_source = CI_B; break;
483 case 2: ci_source = CI_C; break;
484 case 3: ci_source = CI_D; break;
486 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
493 eUsePtr<iDVBChannel> channel;
494 if (!pmthandler->getChannel(channel))
496 ePtr<iDVBFrontend> frontend;
497 if (!channel->getFrontend(frontend))
499 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
500 tunernum = fe->getSlotID();
502 else // no frontend, PVR
505 ASSERT(tunernum != -1);
506 data_source tuner_source = TUNER_A;
510 tuner_source = (data_source)tunernum;
512 case 99: tuner_source = PVR;
515 eDebug("try to get source for tuner %d!!\n", tunernum);
518 ci_it->current_tuner = tunernum;
520 setInputSource(tunernum, ci_source);
521 ci_it->setSource(tuner_source);
525 ci_it->current_tuner = it->cislot->current_tuner;
526 ci_it->linked_next = it->cislot;
527 ci_it->setSource(ci_it->linked_next->current_source);
528 ci_it->linked_next->setSource(ci_source);
531 eDebugCI("assigned!");
535 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
537 eDebugCI("user mapped CI assigned... dont link CIs!");
545 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
547 // check if this pmthandler is already registered
548 PMTHandlerList::iterator it = m_pmt_handlers.begin();
549 while (it != m_pmt_handlers.end())
551 if ( *it++ == pmthandler )
555 eServiceReferenceDVB ref;
556 pmthandler->getServiceReference(ref);
557 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
559 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
560 recheckPMTHandlers();
563 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
565 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
566 if (it != m_pmt_handlers.end())
568 eDVBCISlot *slot = it->cislot;
569 eDVBCISlot *base_slot = slot;
570 eDVBServicePMTHandler *pmthandler = it->pmthandler;
571 m_pmt_handlers.erase(it);
573 eServiceReferenceDVB service_to_remove;
574 pmthandler->getServiceReference(service_to_remove);
576 bool sameServiceExist=false;
577 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
581 eServiceReferenceDVB ref;
582 i->pmthandler->getServiceReference(ref);
583 if ( ref == service_to_remove )
585 sameServiceExist=true;
593 eDVBCISlot *next = slot->linked_next;
594 if (!sameServiceExist)
596 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
597 service_to_remove.toString().c_str());
598 std::vector<uint16_t> caids;
599 caids.push_back(0xFFFF);
600 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
601 slot->removeService(service_to_remove.getServiceID().get());
604 if (!--slot->use_count)
606 if (slot->linked_next)
607 slot->linked_next->setSource(slot->current_source);
610 if(slot->current_tuner == 99)
611 slot->setSource(PVR_NONE);
613 setInputSource(slot->current_tuner, slot->current_source);
615 slot->removeVtunerPid();
618 if (base_slot != slot)
620 eDVBCISlot *tmp = it->cislot;
621 while(tmp->linked_next != slot)
622 tmp = tmp->linked_next;
624 if (slot->linked_next)
625 tmp->linked_next = slot->linked_next;
627 tmp->linked_next = 0;
629 else // removed old base slot.. update ptr
630 base_slot = slot->linked_next;
631 slot->linked_next = 0;
632 slot->user_mapped = false;
634 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
637 // check if another service is waiting for the CI
638 recheckPMTHandlers();
642 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
644 eDebug("[eDVBCIInterfaces] gotPMT");
645 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
646 if (it != m_pmt_handlers.end() && it->cislot)
648 eDVBCISlot *tmp = it->cislot;
651 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
652 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
653 tmp->sendCAPMT(pmthandler);
654 tmp = tmp->linked_next;
660 bool eDVBCIInterfaces::isCiConnected(eDVBServicePMTHandler *pmthandler)
663 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
664 if (it != m_pmt_handlers.end() && it->cislot)
672 int eDVBCIInterfaces::getMMIState(int slotid)
676 if( (slot = getSlot(slotid)) == 0 )
679 return slot->getMMIState();
682 static const char *g_tuner_source[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "CI0", "CI1", "CI2", "CI3"};
684 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
686 eDebugCI("[eDVBCIInterfaces] setInputSource(%d, %d)", tuner_no, (int)source);
687 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
690 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
693 if((input = fopen(buf, "wb")) == NULL) {
694 eDebug("cannot open %s", buf);
700 case TUNER_A ... CI_D:
701 fprintf(input, g_tuner_source[(int)source]);
704 eDebug("setInputSource for input %d failed!!!\n", (int)source);
713 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
716 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
719 if((input = fopen(buf, "wb")) == NULL) {
720 eDebug("cannot open %s", buf);
727 fprintf(input, "CI");
736 eDebug("setInputSource for input %d failed!!!\n", (int)source);
742 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
746 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
748 eDVBCISlot *slot = getSlot(slotid);
752 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
753 PyErr_SetString(PyExc_StandardError, tmp);
756 ePyObject tuple = PyTuple_New(3);
757 int caids = slot->possible_caids.size();
758 int services = slot->possible_services.size();
759 int providers = slot->possible_providers.size();
760 ePyObject caid_list = PyList_New(caids);
761 ePyObject service_list = PyList_New(services);
762 ePyObject provider_list = PyList_New(providers);
763 caidSet::iterator caid_it(slot->possible_caids.begin());
767 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
770 serviceSet::iterator ref_it(slot->possible_services.begin());
774 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
777 providerSet::iterator provider_it(slot->possible_providers.begin());
780 ePyObject tuple = PyTuple_New(2);
781 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
782 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
784 PyList_SET_ITEM(provider_list, providers, tuple);
787 PyTuple_SET_ITEM(tuple, 0, service_list);
788 PyTuple_SET_ITEM(tuple, 1, provider_list);
789 PyTuple_SET_ITEM(tuple, 2, caid_list);
793 const char *PyObject_TypeStr(PyObject *o)
795 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
798 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
800 eDVBCISlot *slot = getSlot(slotid);
804 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
805 PyErr_SetString(PyExc_StandardError, tmp);
808 if (!PyTuple_Check(obj))
811 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
812 PyErr_SetString(PyExc_StandardError, tmp);
815 if (PyTuple_Size(obj) != 3)
817 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
818 "first argument should be a pythonlist with possible services\n"
819 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
820 "third argument should be a pythonlist with possible caids";
821 PyErr_SetString(PyExc_StandardError, errstr);
824 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
825 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
826 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
827 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
830 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
831 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
832 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
833 "third argument(%s) should be a pythonlist with possible caids (ints)",
834 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
835 PyErr_SetString(PyExc_StandardError, errstr);
838 slot->possible_caids.clear();
839 slot->possible_services.clear();
840 slot->possible_providers.clear();
841 int size = PyList_Size(service_list);
845 ePyObject refstr = PyList_GET_ITEM(service_list, size);
846 if (!PyString_Check(refstr))
849 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
850 PyErr_SetString(PyExc_StandardError, buf);
853 char *tmpstr = PyString_AS_STRING(refstr);
854 eServiceReference ref(tmpstr);
856 slot->possible_services.insert(ref);
858 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
860 size = PyList_Size(provider_list);
864 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
865 if (!PyTuple_Check(tuple))
868 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
869 PyErr_SetString(PyExc_StandardError, buf);
872 if (PyTuple_Size(tuple) != 2)
875 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %zd instead of 2 entries!!", PyTuple_Size(tuple));
876 PyErr_SetString(PyExc_StandardError, buf);
879 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
882 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
883 PyErr_SetString(PyExc_StandardError, buf);
886 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
889 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
890 PyErr_SetString(PyExc_StandardError, buf);
893 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
894 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
896 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
898 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
900 size = PyList_Size(caid_list);
904 ePyObject caid = PyList_GET_ITEM(caid_list, size);
905 if (!PyLong_Check(caid))
908 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
909 PyErr_SetString(PyExc_StandardError, buf);
912 int tmpcaid = PyLong_AsLong(caid);
913 if (tmpcaid > 0 && tmpcaid < 0x10000)
914 slot->possible_caids.insert(tmpcaid);
916 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
921 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
923 eDVBCISlot *slot = getSlot(slotid);
927 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
928 PyErr_SetString(PyExc_StandardError, tmp);
933 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
934 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
935 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
938 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
939 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
946 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
948 eDVBCISlot *slot = getSlot(slotid);
950 return slot->setClockRate(rate);
954 int eDVBCISlot::send(const unsigned char *data, size_t len)
958 //eDebugNoNewLine("< ");
960 // eDebugNoNewLine("%02x ",data[i]);
963 if (sendqueue.empty())
964 res = ::write(fd, data, len);
966 if (res < 0 || (unsigned int)res != len)
968 unsigned char *d = new unsigned char[len];
969 memcpy(d, data, len);
970 sendqueue.push( queueData(d, len) );
971 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
977 void eDVBCISlot::data(int what)
979 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
980 if(what == eSocketNotifier::Priority) {
981 if(state != stateRemoved) {
982 state = stateRemoved;
983 while(sendqueue.size())
985 delete [] sendqueue.top().data;
988 eDVBCISession::deleteSessions(this);
989 eDVBCIInterfaces::getInstance()->ciRemoved(this);
990 notifier->setRequested(eSocketNotifier::Read);
991 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
996 if (state == stateInvalid)
999 if(state != stateInserted) {
1000 eDebug("ci inserted in slot %d", getSlotID());
1001 state = stateInserted;
1002 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
1003 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1004 /* enable PRI to detect removal or errors */
1007 if (what & eSocketNotifier::Read) {
1010 r = ::read(fd, data, 4096);
1013 // eDebugNoNewLine("> ");
1015 // eDebugNoNewLine("%02x ",data[i]);
1017 eDVBCISession::receiveData(this, data, r);
1018 eDVBCISession::pollAll();
1022 else if (what & eSocketNotifier::Write) {
1023 if (!sendqueue.empty()) {
1024 const queueData &qe = sendqueue.top();
1025 int res = ::write(fd, qe.data, qe.len);
1026 if (res >= 0 && (unsigned int)res == qe.len)
1033 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1037 DEFINE_REF(eDVBCISlot);
1039 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1043 application_manager = 0;
1048 user_mapped = false;
1053 sprintf(filename, "/dev/ci%d", nr);
1055 // possible_caids.insert(0x1702);
1056 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1057 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1059 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1061 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1062 state = stateInvalid;
1066 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1067 CONNECT(notifier->activated, eDVBCISlot::data);
1073 for(int i = 0; i < NUM_OF_ECM ; i++)
1081 eDVBCISlot::~eDVBCISlot()
1083 eDVBCISession::deleteSessions(this);
1086 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1088 application_manager=session;
1091 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1093 mmi_session = session;
1096 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1098 ca_manager = session;
1101 int eDVBCISlot::getSlotID()
1106 int eDVBCISlot::reset()
1108 eDebug("CI Slot %d: reset requested", getSlotID());
1110 if (state == stateInvalid)
1112 unsigned char buf[256];
1114 while(::read(fd, buf, 256)>0);
1115 state = stateResetted;
1118 while(sendqueue.size())
1120 delete [] sendqueue.top().data;
1129 int eDVBCISlot::startMMI()
1131 eDebug("CI Slot %d: startMMI()", getSlotID());
1133 if(application_manager)
1134 application_manager->startMMI();
1139 int eDVBCISlot::stopMMI()
1141 eDebug("CI Slot %d: stopMMI()", getSlotID());
1144 mmi_session->stopMMI();
1149 int eDVBCISlot::answerText(int answer)
1151 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1154 mmi_session->answerText(answer);
1159 int eDVBCISlot::getMMIState()
1167 int eDVBCISlot::answerEnq(char *value)
1169 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1172 mmi_session->answerEnq(value);
1177 int eDVBCISlot::cancelEnq()
1179 eDebug("CI Slot %d: cancelENQ", getSlotID());
1182 mmi_session->cancelEnq();
1187 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1191 eDebug("no ca_manager (no CI plugged?)");
1194 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1195 ePtr<eTable<ProgramMapSection> > ptr;
1196 if (pmthandler->getPMT(ptr))
1200 eDVBTableSpec table_spec;
1201 ptr->getSpec(table_spec);
1202 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1204 eServiceReferenceDVB ref;
1205 pmthandler->getServiceReference(ref);
1206 uint16_t program_number = ref.getServiceID().get();
1207 std::map<uint16_t, uint8_t>::iterator it =
1208 running_services.find(program_number);
1209 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1211 if ( it != running_services.end() &&
1212 (pmt_version == it->second) &&
1215 eDebug("[eDVBCISlot] dont send self capmt version twice");
1219 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1220 if ( i == ptr->getSections().end() )
1224 unsigned char raw_data[2048];
1226 // eDebug("send %s capmt for service %04x to slot %d",
1227 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1228 // program_number, slotid);
1230 CaProgramMapSection capmt(*i++,
1231 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1232 while( i != ptr->getSections().end() )
1234 // eDebug("append");
1237 capmt.writeToBuffer(raw_data);
1239 // begin calc capmt length
1242 if ( raw_data[3] & 0x80 )
1245 int lenbytes = raw_data[3] & ~0x80;
1247 wp = (wp << 8) | raw_data[4 + i++];
1250 hlen = 4 + lenbytes;
1258 // end calc capmt length
1262 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1263 if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
1264 raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1265 raw_data[hlen+3] &= ~0x3E;
1266 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1267 // eDebug(" new version is %02x", raw_data[hlen+3]);
1270 // eDebug("ca_manager %p dump capmt:", ca_manager);
1271 // for(int i=0;i<wp;i++)
1272 // eDebugNoNewLine("%02x ", raw_data[i]);
1275 //dont need tag and lenfield
1276 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1277 running_services[program_number] = pmt_version;
1283 void eDVBCISlot::removeService(uint16_t program_number)
1285 if (program_number == 0xFFFF)
1286 running_services.clear(); // remove all
1288 running_services.erase(program_number); // remove single service
1291 int eDVBCISlot::setSource(data_source source)
1293 current_source = source;
1294 eDebugCI("[eDVBCISlot] setSource %d", (int)source);
1295 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1298 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1299 FILE *ci = fopen(buf, "wb");
1302 case TUNER_A ... CI_D:
1303 fprintf(ci, g_tuner_source[(int)source]);
1309 fprintf(ci, "PVR_NONE");
1312 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1319 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1320 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1321 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1323 eDebug("cannot open /proc/stb/tsmux/input2");
1326 if (source != TUNER_A && source != TUNER_B)
1327 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1329 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1332 eDebugCI("[eDVBCISlot] CI Slot %d setSource(%d)", getSlotID(), (int)source);
1336 int eDVBCISlot::setClockRate(int rate)
1339 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1340 FILE *ci = fopen(buf, "wb");
1344 fprintf(ci, "high");
1346 fprintf(ci, "normal");
1353 void eDVBCISlot::addVtunerPid(eDVBServicePMTHandler *pmthandler)
1355 ePtr<iDVBDemux> demux;
1356 eDVBServicePMTHandler::program p;
1358 if (!pmthandler->getDataDemux(demux) && !ecm_num)
1361 if (!pmthandler->getProgramInfo(p))
1363 for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(p.caids.begin());
1364 i != p.caids.end(); ++i)
1368 eDebug("PES Start ECM PID = %d Caid = %d ecm_num=%d", i->capid, i->caid, ecm_num);
1369 m_ecm[ecm_num] = new eDVBECMParser(demux);
1370 m_ecm[ecm_num++]->start(i->capid);
1378 void eDVBCISlot::removeVtunerPid(void)
1380 for(int i = 0; i < ecm_num ; i++)
1391 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");