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 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
301 caids.push_front(*x);
303 service->m_ca = caids;
307 caids = service->m_ca;
310 continue; // unscrambled service
312 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
314 eDebugCI("check Slot %d", ci_it->getSlotID());
316 bool user_mapped=true;
317 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
322 if (!ci_it->possible_services.empty())
325 serviceSet::iterator it = ci_it->possible_services.find(ref);
326 if (it != ci_it->possible_services.end())
328 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
333 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
336 it = ci_it->possible_services.find(ref);
337 if (it != ci_it->possible_services.end())
339 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
340 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
346 if (!useThis && !ci_it->possible_providers.empty())
348 eDVBNamespace ns = ref.getDVBNamespace();
350 if (!service) // subservice?
352 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
353 eDVBDB::getInstance()->getService(parent_ref, service);
357 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
358 if (it != ci_it->possible_providers.end())
360 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
365 if (!useThis && !ci_it->possible_caids.empty())
368 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
370 caidSet::iterator it = ci_it->possible_caids.find(*ca);
371 if (it != ci_it->possible_caids.end())
373 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
379 if (!useThis && !mask)
381 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
382 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
384 std::vector<uint16_t>::const_iterator z =
385 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
386 if ( z != ci_caids.end() && *z == *ca )
388 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
399 // check if this CI is already assigned to this pmthandler
400 eDVBCISlot *tmp = it->cislot;
405 tmp=tmp->linked_next;
407 if (tmp) // ignore already assigned cislots...
409 eDebugCI("already assigned!");
412 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
413 if (ci_it->use_count) // check if this CI can descramble more than one service
417 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
418 while (!found && tmp != m_pmt_handlers.end())
421 eDVBCISlot *tmp_cislot = tmp->cislot;
422 while (!found && tmp_cislot)
425 eServiceReferenceDVB ref2;
426 tmp->pmthandler->getServiceReference(ref2);
427 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
429 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
430 eDVBChannelID s1, s2;
433 eDebugCI("different services!");
434 ref.getChannelID(s1);
435 ref2.getChannelID(s2);
437 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
441 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
445 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
446 tmpci=tmpci->linked_next;
450 tmp_cislot=tmp_cislot->linked_next;
459 if (ci_it->user_mapped) // we dont like to link user mapped CIs
461 eDebugCI("user mapped CI already in use... dont link!");
466 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
468 data_source ci_source=CI_A;
469 switch(ci_it->getSlotID())
471 case 0: ci_source = CI_A; break;
472 case 1: ci_source = CI_B; break;
473 case 2: ci_source = CI_C; break;
474 case 3: ci_source = CI_D; break;
476 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
483 eUsePtr<iDVBChannel> channel;
484 if (!pmthandler->getChannel(channel))
486 ePtr<iDVBFrontend> frontend;
487 if (!channel->getFrontend(frontend))
489 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
490 tunernum = fe->getSlotID();
493 ASSERT(tunernum != -1);
494 data_source tuner_source = TUNER_A;
497 case 0: tuner_source = TUNER_A; break;
498 case 1: tuner_source = TUNER_B; break;
499 case 2: tuner_source = TUNER_C; break;
500 case 3: tuner_source = TUNER_D; break;
502 eDebug("try to get source for tuner %d!!\n", tunernum);
505 ci_it->current_tuner = tunernum;
506 setInputSource(tunernum, ci_source);
507 ci_it->setSource(tuner_source);
511 ci_it->current_tuner = it->cislot->current_tuner;
512 ci_it->linked_next = it->cislot;
513 ci_it->setSource(ci_it->linked_next->current_source);
514 ci_it->linked_next->setSource(ci_source);
517 eDebugCI("assigned!");
521 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
523 eDebugCI("user mapped CI assigned... dont link CIs!");
531 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
533 // check if this pmthandler is already registered
534 PMTHandlerList::iterator it = m_pmt_handlers.begin();
535 while (it != m_pmt_handlers.end())
537 if ( *it++ == pmthandler )
541 eServiceReferenceDVB ref;
542 pmthandler->getServiceReference(ref);
543 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
545 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
546 recheckPMTHandlers();
549 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
551 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
552 if (it != m_pmt_handlers.end())
554 eDVBCISlot *slot = it->cislot;
555 eDVBCISlot *base_slot = slot;
556 eDVBServicePMTHandler *pmthandler = it->pmthandler;
557 m_pmt_handlers.erase(it);
559 eServiceReferenceDVB service_to_remove;
560 pmthandler->getServiceReference(service_to_remove);
562 bool sameServiceExist=false;
563 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
567 eServiceReferenceDVB ref;
568 i->pmthandler->getServiceReference(ref);
569 if ( ref == service_to_remove )
571 sameServiceExist=true;
579 eDVBCISlot *next = slot->linked_next;
580 if (!sameServiceExist)
582 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
583 service_to_remove.toString().c_str());
584 std::vector<uint16_t> caids;
585 caids.push_back(0xFFFF);
586 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
587 slot->removeService(service_to_remove.getServiceID().get());
590 if (!--slot->use_count)
592 if (slot->linked_next)
593 slot->linked_next->setSource(slot->current_source);
595 setInputSource(slot->current_tuner, slot->current_source);
597 if (base_slot != slot)
599 eDVBCISlot *tmp = it->cislot;
600 while(tmp->linked_next != slot)
601 tmp = tmp->linked_next;
603 if (slot->linked_next)
604 tmp->linked_next = slot->linked_next;
606 tmp->linked_next = 0;
608 else // removed old base slot.. update ptr
609 base_slot = slot->linked_next;
610 slot->linked_next = 0;
611 slot->user_mapped = false;
613 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
616 // check if another service is waiting for the CI
617 recheckPMTHandlers();
621 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
623 eDebug("[eDVBCIInterfaces] gotPMT");
624 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
625 if (it != m_pmt_handlers.end() && it->cislot)
627 eDVBCISlot *tmp = it->cislot;
630 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
631 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
632 tmp->sendCAPMT(pmthandler);
633 tmp = tmp->linked_next;
638 int eDVBCIInterfaces::getMMIState(int slotid)
642 if( (slot = getSlot(slotid)) == 0 )
645 return slot->getMMIState();
648 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
650 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
651 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
652 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
655 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
658 if((input = fopen(buf, "wb")) == NULL) {
659 eDebug("cannot open %s", buf);
664 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
669 fprintf(input, "CI0");
672 fprintf(input, "CI1");
675 fprintf(input, "CI2");
678 fprintf(input, "CI3");
693 eDebug("setInputSource for input %d failed!!!\n", (int)source);
702 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
705 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
708 if((input = fopen(buf, "wb")) == NULL) {
709 eDebug("cannot open %s", buf);
716 fprintf(input, "CI");
725 eDebug("setInputSource for input %d failed!!!\n", (int)source);
731 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
735 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
737 eDVBCISlot *slot = getSlot(slotid);
741 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
742 PyErr_SetString(PyExc_StandardError, tmp);
745 ePyObject tuple = PyTuple_New(3);
746 int caids = slot->possible_caids.size();
747 int services = slot->possible_services.size();
748 int providers = slot->possible_providers.size();
749 ePyObject caid_list = PyList_New(caids);
750 ePyObject service_list = PyList_New(services);
751 ePyObject provider_list = PyList_New(providers);
752 caidSet::iterator caid_it(slot->possible_caids.begin());
756 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
759 serviceSet::iterator ref_it(slot->possible_services.begin());
763 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
766 providerSet::iterator provider_it(slot->possible_providers.begin());
769 ePyObject tuple = PyTuple_New(2);
770 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
771 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
773 PyList_SET_ITEM(provider_list, providers, tuple);
776 PyTuple_SET_ITEM(tuple, 0, service_list);
777 PyTuple_SET_ITEM(tuple, 1, provider_list);
778 PyTuple_SET_ITEM(tuple, 2, caid_list);
782 const char *PyObject_TypeStr(PyObject *o)
784 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
787 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
789 eDVBCISlot *slot = getSlot(slotid);
793 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
794 PyErr_SetString(PyExc_StandardError, tmp);
797 if (!PyTuple_Check(obj))
800 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
801 PyErr_SetString(PyExc_StandardError, tmp);
804 if (PyTuple_Size(obj) != 3)
806 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
807 "first argument should be a pythonlist with possible services\n"
808 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
809 "third argument should be a pythonlist with possible caids";
810 PyErr_SetString(PyExc_StandardError, errstr);
813 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
814 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
815 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
816 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
819 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
820 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
821 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
822 "third argument(%s) should be a pythonlist with possible caids (ints)",
823 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
824 PyErr_SetString(PyExc_StandardError, errstr);
827 slot->possible_caids.clear();
828 slot->possible_services.clear();
829 slot->possible_providers.clear();
830 int size = PyList_Size(service_list);
834 ePyObject refstr = PyList_GET_ITEM(service_list, size);
835 if (!PyString_Check(refstr))
838 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
839 PyErr_SetString(PyExc_StandardError, buf);
842 char *tmpstr = PyString_AS_STRING(refstr);
843 eServiceReference ref(tmpstr);
845 slot->possible_services.insert(ref);
847 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
849 size = PyList_Size(provider_list);
853 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
854 if (!PyTuple_Check(tuple))
857 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
858 PyErr_SetString(PyExc_StandardError, buf);
861 if (PyTuple_Size(tuple) != 2)
864 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
865 PyErr_SetString(PyExc_StandardError, buf);
868 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
871 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
872 PyErr_SetString(PyExc_StandardError, buf);
875 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
878 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
879 PyErr_SetString(PyExc_StandardError, buf);
882 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
883 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
885 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
887 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
889 size = PyList_Size(caid_list);
893 ePyObject caid = PyList_GET_ITEM(caid_list, size);
894 if (!PyLong_Check(caid))
897 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
898 PyErr_SetString(PyExc_StandardError, buf);
901 int tmpcaid = PyLong_AsLong(caid);
902 if (tmpcaid > 0 && tmpcaid < 0x10000)
903 slot->possible_caids.insert(tmpcaid);
905 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
910 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
912 eDVBCISlot *slot = getSlot(slotid);
916 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
917 PyErr_SetString(PyExc_StandardError, tmp);
922 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
923 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
924 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
927 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
928 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
935 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
937 eDVBCISlot *slot = getSlot(slotid);
939 return slot->setClockRate(rate);
943 int eDVBCISlot::send(const unsigned char *data, size_t len)
947 //eDebugNoNewLine("< ");
949 // eDebugNoNewLine("%02x ",data[i]);
952 if (sendqueue.empty())
953 res = ::write(fd, data, len);
955 if (res < 0 || (unsigned int)res != len)
957 unsigned char *d = new unsigned char[len];
958 memcpy(d, data, len);
959 sendqueue.push( queueData(d, len) );
960 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
966 void eDVBCISlot::data(int what)
968 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
969 if(what == eSocketNotifier::Priority) {
970 if(state != stateRemoved) {
971 state = stateRemoved;
972 while(sendqueue.size())
974 delete [] sendqueue.top().data;
977 eDVBCISession::deleteSessions(this);
978 eDVBCIInterfaces::getInstance()->ciRemoved(this);
979 notifier->setRequested(eSocketNotifier::Read);
980 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
985 if (state == stateInvalid)
988 if(state != stateInserted) {
989 eDebug("ci inserted in slot %d", getSlotID());
990 state = stateInserted;
991 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
992 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
993 /* enable PRI to detect removal or errors */
996 if (what & eSocketNotifier::Read) {
999 r = ::read(fd, data, 4096);
1002 // eDebugNoNewLine("> ");
1004 // eDebugNoNewLine("%02x ",data[i]);
1006 eDVBCISession::receiveData(this, data, r);
1007 eDVBCISession::pollAll();
1011 else if (what & eSocketNotifier::Write) {
1012 if (!sendqueue.empty()) {
1013 const queueData &qe = sendqueue.top();
1014 int res = ::write(fd, qe.data, qe.len);
1015 if (res >= 0 && (unsigned int)res == qe.len)
1022 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1026 DEFINE_REF(eDVBCISlot);
1028 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1032 application_manager = 0;
1037 user_mapped = false;
1042 sprintf(filename, "/dev/ci%d", nr);
1044 // possible_caids.insert(0x1702);
1045 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1046 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1048 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1050 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1051 state = stateInvalid;
1055 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1056 CONNECT(notifier->activated, eDVBCISlot::data);
1063 eDVBCISlot::~eDVBCISlot()
1065 eDVBCISession::deleteSessions(this);
1068 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1070 application_manager=session;
1073 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1075 mmi_session = session;
1078 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1080 ca_manager = session;
1083 int eDVBCISlot::getSlotID()
1088 int eDVBCISlot::reset()
1090 eDebug("CI Slot %d: reset requested", getSlotID());
1092 if (state == stateInvalid)
1094 unsigned char buf[256];
1096 while(::read(fd, buf, 256)>0);
1097 state = stateResetted;
1100 while(sendqueue.size())
1102 delete [] sendqueue.top().data;
1111 int eDVBCISlot::startMMI()
1113 eDebug("CI Slot %d: startMMI()", getSlotID());
1115 if(application_manager)
1116 application_manager->startMMI();
1121 int eDVBCISlot::stopMMI()
1123 eDebug("CI Slot %d: stopMMI()", getSlotID());
1126 mmi_session->stopMMI();
1131 int eDVBCISlot::answerText(int answer)
1133 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1136 mmi_session->answerText(answer);
1141 int eDVBCISlot::getMMIState()
1149 int eDVBCISlot::answerEnq(char *value)
1151 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1154 mmi_session->answerEnq(value);
1159 int eDVBCISlot::cancelEnq()
1161 eDebug("CI Slot %d: cancelENQ", getSlotID());
1164 mmi_session->cancelEnq();
1169 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1173 eDebug("no ca_manager (no CI plugged?)");
1176 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1177 ePtr<eTable<ProgramMapSection> > ptr;
1178 if (pmthandler->getPMT(ptr))
1182 eDVBTableSpec table_spec;
1183 ptr->getSpec(table_spec);
1184 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1186 eServiceReferenceDVB ref;
1187 pmthandler->getServiceReference(ref);
1188 uint16_t program_number = ref.getServiceID().get();
1189 std::map<uint16_t, uint8_t>::iterator it =
1190 running_services.find(program_number);
1191 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1193 if ( it != running_services.end() &&
1194 (pmt_version == it->second) &&
1197 eDebug("[eDVBCISlot] dont send self capmt version twice");
1201 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1202 if ( i == ptr->getSections().end() )
1206 unsigned char raw_data[2048];
1208 // eDebug("send %s capmt for service %04x to slot %d",
1209 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1210 // program_number, slotid);
1212 CaProgramMapSection capmt(*i++,
1213 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1214 while( i != ptr->getSections().end() )
1216 // eDebug("append");
1219 capmt.writeToBuffer(raw_data);
1221 // begin calc capmt length
1224 if ( raw_data[3] & 0x80 )
1227 int lenbytes = raw_data[3] & ~0x80;
1229 wp = (wp << 8) | raw_data[4 + i++];
1232 hlen = 4 + lenbytes;
1240 // end calc capmt length
1244 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1245 if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
1246 raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1247 raw_data[hlen+3] &= ~0x3E;
1248 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1249 // eDebug(" new version is %02x", raw_data[hlen+3]);
1252 // eDebug("ca_manager %p dump capmt:", ca_manager);
1253 // for(int i=0;i<wp;i++)
1254 // eDebugNoNewLine("%02x ", raw_data[i]);
1257 //dont need tag and lenfield
1258 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1259 running_services[program_number] = pmt_version;
1265 void eDVBCISlot::removeService(uint16_t program_number)
1267 if (program_number == 0xFFFF)
1268 running_services.clear(); // remove all
1270 running_services.erase(program_number); // remove single service
1273 int eDVBCISlot::setSource(data_source source)
1275 current_source = source;
1276 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1279 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1280 FILE *ci = fopen(buf, "wb");
1308 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1315 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1316 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1317 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1319 eDebug("cannot open /proc/stb/tsmux/input2");
1322 if (source != TUNER_A && source != TUNER_B)
1323 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1325 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1328 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1332 int eDVBCISlot::setClockRate(int rate)
1335 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1336 FILE *ci = fopen(buf, "wb");
1340 fprintf(ci, "high");
1342 fprintf(ci, "normal");
1349 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");