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
228 setInputSource(slot->current_tuner, slot->current_source);
229 slot->linked_next = 0;
232 slot->user_mapped=false;
233 slot->removeService(0xFFFF);
234 recheckPMTHandlers();
238 static bool canDescrambleMultipleServices(int slotid)
241 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
243 ePythonConfigQuery::getConfigValue(configStr, str);
246 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
247 if (appname.find("AlphaCrypt") != std::string::npos)
250 else if (str == "yes")
255 void eDVBCIInterfaces::recheckPMTHandlers()
257 eDebugCI("recheckPMTHAndlers()");
258 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
259 it != m_pmt_handlers.end(); ++it)
262 ePtr<eDVBService> service;
263 eServiceReferenceDVB ref;
264 eDVBCISlot *tmp = it->cislot;
265 eDVBServicePMTHandler *pmthandler = it->pmthandler;
266 eDVBServicePMTHandler::program p;
267 bool plugged_cis_exist = false;
269 pmthandler->getServiceReference(ref);
270 pmthandler->getService(service);
272 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
273 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
274 if (ci_it->plugged && ci_it->getCAManager())
276 eDebug("Slot %d plugged", ci_it->getSlotID());
277 ci_it->plugged = false;
278 plugged_cis_exist = true;
281 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
282 if (!plugged_cis_exist)
286 if (!tmp->running_services.empty())
288 tmp=tmp->linked_next;
290 if (tmp) // we dont like to change tsmux for running services
292 eDebugCI("already assigned and running CI!\n");
297 if (!pmthandler->getProgramInfo(p))
300 std::set<eDVBServicePMTHandler::program::capid_pair> set(p.caids.begin(), p.caids.end());
301 for (std::set<eDVBServicePMTHandler::program::capid_pair>::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt)
302 caids.push_front(x->caid);
304 service->m_ca = caids;
308 caids = service->m_ca;
311 continue; // unscrambled service
313 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
315 eDebugCI("check Slot %d", ci_it->getSlotID());
317 bool user_mapped=true;
318 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
323 if (!ci_it->possible_services.empty())
326 serviceSet::iterator it = ci_it->possible_services.find(ref);
327 if (it != ci_it->possible_services.end())
329 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
334 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
337 it = ci_it->possible_services.find(ref);
338 if (it != ci_it->possible_services.end())
340 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
341 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
347 if (!useThis && !ci_it->possible_providers.empty())
349 eDVBNamespace ns = ref.getDVBNamespace();
351 if (!service) // subservice?
353 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
354 eDVBDB::getInstance()->getService(parent_ref, service);
358 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
359 if (it != ci_it->possible_providers.end())
361 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
366 if (!useThis && !ci_it->possible_caids.empty())
369 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
371 caidSet::iterator it = ci_it->possible_caids.find(*ca);
372 if (it != ci_it->possible_caids.end())
374 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
380 if (!useThis && !mask)
382 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
383 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
385 std::vector<uint16_t>::const_iterator z =
386 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
387 if ( z != ci_caids.end() && *z == *ca )
389 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
400 // check if this CI is already assigned to this pmthandler
401 eDVBCISlot *tmp = it->cislot;
406 tmp=tmp->linked_next;
408 if (tmp) // ignore already assigned cislots...
410 eDebugCI("already assigned!");
413 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
414 if (ci_it->use_count) // check if this CI can descramble more than one service
418 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
419 while (!found && tmp != m_pmt_handlers.end())
422 eDVBCISlot *tmp_cislot = tmp->cislot;
423 while (!found && tmp_cislot)
426 eServiceReferenceDVB ref2;
427 tmp->pmthandler->getServiceReference(ref2);
428 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
430 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
431 eDVBChannelID s1, s2;
434 eDebugCI("different services!");
435 ref.getChannelID(s1);
436 ref2.getChannelID(s2);
438 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
442 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
446 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
447 tmpci=tmpci->linked_next;
451 tmp_cislot=tmp_cislot->linked_next;
460 if (ci_it->user_mapped) // we dont like to link user mapped CIs
462 eDebugCI("user mapped CI already in use... dont link!");
467 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
469 data_source ci_source=CI_A;
470 switch(ci_it->getSlotID())
472 case 0: ci_source = CI_A; break;
473 case 1: ci_source = CI_B; break;
474 case 2: ci_source = CI_C; break;
475 case 3: ci_source = CI_D; break;
477 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
484 eUsePtr<iDVBChannel> channel;
485 if (!pmthandler->getChannel(channel))
487 ePtr<iDVBFrontend> frontend;
488 if (!channel->getFrontend(frontend))
490 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
491 tunernum = fe->getSlotID();
494 ASSERT(tunernum != -1);
495 data_source tuner_source = TUNER_A;
498 case 0: tuner_source = TUNER_A; break;
499 case 1: tuner_source = TUNER_B; break;
500 case 2: tuner_source = TUNER_C; break;
501 case 3: tuner_source = TUNER_D; break;
503 eDebug("try to get source for tuner %d!!\n", tunernum);
506 ci_it->current_tuner = tunernum;
507 setInputSource(tunernum, ci_source);
508 ci_it->setSource(tuner_source);
512 ci_it->current_tuner = it->cislot->current_tuner;
513 ci_it->linked_next = it->cislot;
514 ci_it->setSource(ci_it->linked_next->current_source);
515 ci_it->linked_next->setSource(ci_source);
518 eDebugCI("assigned!");
522 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
524 eDebugCI("user mapped CI assigned... dont link CIs!");
532 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
534 // check if this pmthandler is already registered
535 PMTHandlerList::iterator it = m_pmt_handlers.begin();
536 while (it != m_pmt_handlers.end())
538 if ( *it++ == pmthandler )
542 eServiceReferenceDVB ref;
543 pmthandler->getServiceReference(ref);
544 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
546 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
547 recheckPMTHandlers();
550 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
552 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
553 if (it != m_pmt_handlers.end())
555 eDVBCISlot *slot = it->cislot;
556 eDVBCISlot *base_slot = slot;
557 eDVBServicePMTHandler *pmthandler = it->pmthandler;
558 m_pmt_handlers.erase(it);
560 eServiceReferenceDVB service_to_remove;
561 pmthandler->getServiceReference(service_to_remove);
563 bool sameServiceExist=false;
564 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
568 eServiceReferenceDVB ref;
569 i->pmthandler->getServiceReference(ref);
570 if ( ref == service_to_remove )
572 sameServiceExist=true;
580 eDVBCISlot *next = slot->linked_next;
581 if (!sameServiceExist)
583 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
584 service_to_remove.toString().c_str());
585 std::vector<uint16_t> caids;
586 caids.push_back(0xFFFF);
587 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
588 slot->removeService(service_to_remove.getServiceID().get());
591 if (!--slot->use_count)
593 if (slot->linked_next)
594 slot->linked_next->setSource(slot->current_source);
596 setInputSource(slot->current_tuner, slot->current_source);
598 if (base_slot != slot)
600 eDVBCISlot *tmp = it->cislot;
601 while(tmp->linked_next != slot)
602 tmp = tmp->linked_next;
604 if (slot->linked_next)
605 tmp->linked_next = slot->linked_next;
607 tmp->linked_next = 0;
609 else // removed old base slot.. update ptr
610 base_slot = slot->linked_next;
611 slot->linked_next = 0;
612 slot->user_mapped = false;
614 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
617 // check if another service is waiting for the CI
618 recheckPMTHandlers();
622 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
624 eDebug("[eDVBCIInterfaces] gotPMT");
625 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
626 if (it != m_pmt_handlers.end() && it->cislot)
628 eDVBCISlot *tmp = it->cislot;
631 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
632 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
633 tmp->sendCAPMT(pmthandler);
634 tmp = tmp->linked_next;
639 int eDVBCIInterfaces::getMMIState(int slotid)
643 if( (slot = getSlot(slotid)) == 0 )
646 return slot->getMMIState();
649 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
651 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
652 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
653 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
656 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
659 if((input = fopen(buf, "wb")) == NULL) {
660 eDebug("cannot open %s", buf);
665 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
670 fprintf(input, "CI0");
673 fprintf(input, "CI1");
676 fprintf(input, "CI2");
679 fprintf(input, "CI3");
694 eDebug("setInputSource for input %d failed!!!\n", (int)source);
703 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
706 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
709 if((input = fopen(buf, "wb")) == NULL) {
710 eDebug("cannot open %s", buf);
717 fprintf(input, "CI");
726 eDebug("setInputSource for input %d failed!!!\n", (int)source);
732 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
736 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
738 eDVBCISlot *slot = getSlot(slotid);
742 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
743 PyErr_SetString(PyExc_StandardError, tmp);
746 ePyObject tuple = PyTuple_New(3);
747 int caids = slot->possible_caids.size();
748 int services = slot->possible_services.size();
749 int providers = slot->possible_providers.size();
750 ePyObject caid_list = PyList_New(caids);
751 ePyObject service_list = PyList_New(services);
752 ePyObject provider_list = PyList_New(providers);
753 caidSet::iterator caid_it(slot->possible_caids.begin());
757 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
760 serviceSet::iterator ref_it(slot->possible_services.begin());
764 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
767 providerSet::iterator provider_it(slot->possible_providers.begin());
770 ePyObject tuple = PyTuple_New(2);
771 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
772 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
774 PyList_SET_ITEM(provider_list, providers, tuple);
777 PyTuple_SET_ITEM(tuple, 0, service_list);
778 PyTuple_SET_ITEM(tuple, 1, provider_list);
779 PyTuple_SET_ITEM(tuple, 2, caid_list);
783 const char *PyObject_TypeStr(PyObject *o)
785 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
788 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
790 eDVBCISlot *slot = getSlot(slotid);
794 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
795 PyErr_SetString(PyExc_StandardError, tmp);
798 if (!PyTuple_Check(obj))
801 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
802 PyErr_SetString(PyExc_StandardError, tmp);
805 if (PyTuple_Size(obj) != 3)
807 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
808 "first argument should be a pythonlist with possible services\n"
809 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
810 "third argument should be a pythonlist with possible caids";
811 PyErr_SetString(PyExc_StandardError, errstr);
814 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
815 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
816 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
817 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
820 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
821 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
822 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
823 "third argument(%s) should be a pythonlist with possible caids (ints)",
824 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
825 PyErr_SetString(PyExc_StandardError, errstr);
828 slot->possible_caids.clear();
829 slot->possible_services.clear();
830 slot->possible_providers.clear();
831 int size = PyList_Size(service_list);
835 ePyObject refstr = PyList_GET_ITEM(service_list, size);
836 if (!PyString_Check(refstr))
839 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
840 PyErr_SetString(PyExc_StandardError, buf);
843 char *tmpstr = PyString_AS_STRING(refstr);
844 eServiceReference ref(tmpstr);
846 slot->possible_services.insert(ref);
848 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
850 size = PyList_Size(provider_list);
854 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
855 if (!PyTuple_Check(tuple))
858 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
859 PyErr_SetString(PyExc_StandardError, buf);
862 if (PyTuple_Size(tuple) != 2)
865 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
866 PyErr_SetString(PyExc_StandardError, buf);
869 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
872 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
873 PyErr_SetString(PyExc_StandardError, buf);
876 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
879 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
880 PyErr_SetString(PyExc_StandardError, buf);
883 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
884 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
886 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
888 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
890 size = PyList_Size(caid_list);
894 ePyObject caid = PyList_GET_ITEM(caid_list, size);
895 if (!PyLong_Check(caid))
898 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
899 PyErr_SetString(PyExc_StandardError, buf);
902 int tmpcaid = PyLong_AsLong(caid);
903 if (tmpcaid > 0 && tmpcaid < 0x10000)
904 slot->possible_caids.insert(tmpcaid);
906 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
911 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
913 eDVBCISlot *slot = getSlot(slotid);
917 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
918 PyErr_SetString(PyExc_StandardError, tmp);
923 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
924 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
925 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
928 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
929 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
936 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
938 eDVBCISlot *slot = getSlot(slotid);
940 return slot->setClockRate(rate);
944 int eDVBCISlot::send(const unsigned char *data, size_t len)
948 //eDebugNoNewLine("< ");
950 // eDebugNoNewLine("%02x ",data[i]);
953 if (sendqueue.empty())
954 res = ::write(fd, data, len);
956 if (res < 0 || (unsigned int)res != len)
958 unsigned char *d = new unsigned char[len];
959 memcpy(d, data, len);
960 sendqueue.push( queueData(d, len) );
961 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
967 void eDVBCISlot::data(int what)
969 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
970 if(what == eSocketNotifier::Priority) {
971 if(state != stateRemoved) {
972 state = stateRemoved;
973 while(sendqueue.size())
975 delete [] sendqueue.top().data;
978 eDVBCISession::deleteSessions(this);
979 eDVBCIInterfaces::getInstance()->ciRemoved(this);
980 notifier->setRequested(eSocketNotifier::Read);
981 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
986 if (state == stateInvalid)
989 if(state != stateInserted) {
990 eDebug("ci inserted in slot %d", getSlotID());
991 state = stateInserted;
992 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
993 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
994 /* enable PRI to detect removal or errors */
997 if (what & eSocketNotifier::Read) {
1000 r = ::read(fd, data, 4096);
1003 // eDebugNoNewLine("> ");
1005 // eDebugNoNewLine("%02x ",data[i]);
1007 eDVBCISession::receiveData(this, data, r);
1008 eDVBCISession::pollAll();
1012 else if (what & eSocketNotifier::Write) {
1013 if (!sendqueue.empty()) {
1014 const queueData &qe = sendqueue.top();
1015 int res = ::write(fd, qe.data, qe.len);
1016 if (res >= 0 && (unsigned int)res == qe.len)
1023 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1027 DEFINE_REF(eDVBCISlot);
1029 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1033 application_manager = 0;
1038 user_mapped = false;
1043 sprintf(filename, "/dev/ci%d", nr);
1045 // possible_caids.insert(0x1702);
1046 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1047 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1049 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1051 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1052 state = stateInvalid;
1056 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1057 CONNECT(notifier->activated, eDVBCISlot::data);
1064 eDVBCISlot::~eDVBCISlot()
1066 eDVBCISession::deleteSessions(this);
1069 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1071 application_manager=session;
1074 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1076 mmi_session = session;
1079 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1081 ca_manager = session;
1084 int eDVBCISlot::getSlotID()
1089 int eDVBCISlot::reset()
1091 eDebug("CI Slot %d: reset requested", getSlotID());
1093 if (state == stateInvalid)
1095 unsigned char buf[256];
1097 while(::read(fd, buf, 256)>0);
1098 state = stateResetted;
1101 while(sendqueue.size())
1103 delete [] sendqueue.top().data;
1112 int eDVBCISlot::startMMI()
1114 eDebug("CI Slot %d: startMMI()", getSlotID());
1116 if(application_manager)
1117 application_manager->startMMI();
1122 int eDVBCISlot::stopMMI()
1124 eDebug("CI Slot %d: stopMMI()", getSlotID());
1127 mmi_session->stopMMI();
1132 int eDVBCISlot::answerText(int answer)
1134 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1137 mmi_session->answerText(answer);
1142 int eDVBCISlot::getMMIState()
1150 int eDVBCISlot::answerEnq(char *value)
1152 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1155 mmi_session->answerEnq(value);
1160 int eDVBCISlot::cancelEnq()
1162 eDebug("CI Slot %d: cancelENQ", getSlotID());
1165 mmi_session->cancelEnq();
1170 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1174 eDebug("no ca_manager (no CI plugged?)");
1177 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1178 ePtr<eTable<ProgramMapSection> > ptr;
1179 if (pmthandler->getPMT(ptr))
1183 eDVBTableSpec table_spec;
1184 ptr->getSpec(table_spec);
1185 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1187 eServiceReferenceDVB ref;
1188 pmthandler->getServiceReference(ref);
1189 uint16_t program_number = ref.getServiceID().get();
1190 std::map<uint16_t, uint8_t>::iterator it =
1191 running_services.find(program_number);
1192 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1194 if ( it != running_services.end() &&
1195 (pmt_version == it->second) &&
1198 eDebug("[eDVBCISlot] dont send self capmt version twice");
1202 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1203 if ( i == ptr->getSections().end() )
1207 unsigned char raw_data[2048];
1209 // eDebug("send %s capmt for service %04x to slot %d",
1210 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1211 // program_number, slotid);
1213 CaProgramMapSection capmt(*i++,
1214 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1215 while( i != ptr->getSections().end() )
1217 // eDebug("append");
1220 capmt.writeToBuffer(raw_data);
1222 // begin calc capmt length
1225 if ( raw_data[3] & 0x80 )
1228 int lenbytes = raw_data[3] & ~0x80;
1230 wp = (wp << 8) | raw_data[4 + i++];
1233 hlen = 4 + lenbytes;
1241 // end calc capmt length
1245 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1246 if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
1247 raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1248 raw_data[hlen+3] &= ~0x3E;
1249 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1250 // eDebug(" new version is %02x", raw_data[hlen+3]);
1253 // eDebug("ca_manager %p dump capmt:", ca_manager);
1254 // for(int i=0;i<wp;i++)
1255 // eDebugNoNewLine("%02x ", raw_data[i]);
1258 //dont need tag and lenfield
1259 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1260 running_services[program_number] = pmt_version;
1266 void eDVBCISlot::removeService(uint16_t program_number)
1268 if (program_number == 0xFFFF)
1269 running_services.clear(); // remove all
1271 running_services.erase(program_number); // remove single service
1274 int eDVBCISlot::setSource(data_source source)
1276 current_source = source;
1277 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1280 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1281 FILE *ci = fopen(buf, "wb");
1309 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1316 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1317 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1318 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1320 eDebug("cannot open /proc/stb/tsmux/input2");
1323 if (source != TUNER_A && source != TUNER_B)
1324 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1326 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1329 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1333 int eDVBCISlot::setClockRate(int rate)
1336 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1337 FILE *ci = fopen(buf, "wb");
1341 fprintf(ci, "high");
1343 fprintf(ci, "normal");
1350 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");