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)
203 eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
204 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
205 it != m_pmt_handlers.end(); ++it)
207 eServiceReferenceDVB ref;
208 it->pmthandler->getServiceReference(ref);
209 eDebugCI("check %s cislot %p %d\n", ref.toString().c_str(), it->cislot, it->cislot?it->cislot->getSlotID() : -1);
210 slot->removeService(ref.getServiceID().get());
211 if (slot->use_count && !--slot->use_count)
213 if (slot->linked_next)
214 slot->linked_next->setSource(slot->current_source);
215 else // last CI in chain
216 setInputSource(slot->current_tuner, slot->current_source);
218 if (it->cislot == slot) // remove the base slot
220 it->cislot = slot->linked_next;
221 eDebugCI("base removed.. so slot is now %p", it->cislot);
225 eDebugCI("not base removed.. %d", it->cislot->getSlotID());
226 eDVBCISlot *tmp = it->cislot;
227 while(tmp->linked_next != slot)
228 tmp = tmp->linked_next;
230 if (slot->linked_next)
231 tmp->linked_next = slot->linked_next;
233 tmp->linked_next = 0;
236 slot->user_mapped=false;
239 recheckPMTHandlers();
242 static bool canDescrambleMultipleServices(int slotid)
245 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
247 ePythonConfigQuery::getConfigValue(configStr, str);
250 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
251 if (appname.find("AlphaCrypt") != std::string::npos)
254 else if (str == "yes")
259 void eDVBCIInterfaces::recheckPMTHandlers()
261 eDebugCI("recheckPMTHAndlers()");
262 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
263 it != m_pmt_handlers.end(); ++it)
266 ePtr<eDVBService> service;
267 eServiceReferenceDVB ref;
268 eDVBCISlot *tmp = it->cislot;
269 eDVBServicePMTHandler *pmthandler = it->pmthandler;
270 eDVBServicePMTHandler::program p;
271 bool first_plugged_cis_exist = false;
273 pmthandler->getServiceReference(ref);
274 pmthandler->getService(service);
276 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
277 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
278 if (ci_it->first_plugged && ci_it->getCAManager())
280 eDebug("Slot %d first plugged", ci_it->getSlotID());
281 ci_it->first_plugged = false;
282 first_plugged_cis_exist = true;
285 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
286 if (!first_plugged_cis_exist)
290 if (!tmp->running_services.empty())
292 tmp=tmp->linked_next;
294 if (tmp) // we dont like to change tsmux for running services
296 eDebugCI("already assigned and running CI!\n");
301 if (!pmthandler->getProgramInfo(p))
304 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
305 caids.push_front(*x);
307 service->m_ca = caids;
311 caids = service->m_ca;
314 continue; // unscrambled service
316 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
318 eDebugCI("check Slot %d", ci_it->getSlotID());
320 bool user_mapped=true;
321 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
326 if (!ci_it->possible_services.empty())
329 serviceSet::iterator it = ci_it->possible_services.find(ref);
330 if (it != ci_it->possible_services.end())
332 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
337 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
340 it = ci_it->possible_services.find(ref);
341 if (it != ci_it->possible_services.end())
343 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
344 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
350 if (!useThis && !ci_it->possible_providers.empty())
352 eDVBNamespace ns = ref.getDVBNamespace();
354 if (!service) // subservice?
356 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
357 eDVBDB::getInstance()->getService(parent_ref, service);
361 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
362 if (it != ci_it->possible_providers.end())
364 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
369 if (!useThis && !ci_it->possible_caids.empty())
372 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
374 caidSet::iterator it = ci_it->possible_caids.find(*ca);
375 if (it != ci_it->possible_caids.end())
377 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
383 if (!useThis && !mask)
385 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
386 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
388 std::vector<uint16_t>::const_iterator z =
389 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
390 if ( z != ci_caids.end() && *z == *ca )
392 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
403 // check if this CI is already assigned to this pmthandler
404 eDVBCISlot *tmp = it->cislot;
409 tmp=tmp->linked_next;
411 if (tmp) // ignore already assigned cislots...
413 eDebugCI("already assigned!");
416 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
417 if (ci_it->use_count) // check if this CI can descramble more than one service
421 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
422 while (!found && tmp != m_pmt_handlers.end())
425 eDVBCISlot *tmp_cislot = tmp->cislot;
426 while (!found && tmp_cislot)
429 eServiceReferenceDVB ref2;
430 tmp->pmthandler->getServiceReference(ref2);
431 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
433 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
434 eDVBChannelID s1, s2;
437 eDebugCI("different services!");
438 ref.getChannelID(s1);
439 ref2.getChannelID(s2);
441 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
445 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
449 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
450 tmpci=tmpci->linked_next;
454 tmp_cislot=tmp_cislot->linked_next;
463 if (ci_it->user_mapped) // we dont like to link user mapped CIs
465 eDebugCI("user mapped CI already in use... dont link!");
470 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
472 data_source ci_source=CI_A;
473 switch(ci_it->getSlotID())
475 case 0: ci_source = CI_A; break;
476 case 1: ci_source = CI_B; break;
477 case 2: ci_source = CI_C; break;
478 case 3: ci_source = CI_D; break;
480 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
487 eUsePtr<iDVBChannel> channel;
488 if (!pmthandler->getChannel(channel))
490 ePtr<iDVBFrontend> frontend;
491 if (!channel->getFrontend(frontend))
493 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
494 tunernum = fe->getSlotID();
497 ASSERT(tunernum != -1);
498 data_source tuner_source = TUNER_A;
501 case 0: tuner_source = TUNER_A; break;
502 case 1: tuner_source = TUNER_B; break;
503 case 2: tuner_source = TUNER_C; break;
504 case 3: tuner_source = TUNER_D; break;
506 eDebug("try to get source for tuner %d!!\n", tunernum);
509 ci_it->current_tuner = tunernum;
510 setInputSource(tunernum, ci_source);
511 ci_it->setSource(tuner_source);
515 ci_it->current_tuner = it->cislot->current_tuner;
516 ci_it->linked_next = it->cislot;
517 ci_it->setSource(ci_it->linked_next->current_source);
518 ci_it->linked_next->setSource(ci_source);
521 eDebugCI("assigned!");
525 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
527 eDebugCI("user mapped CI assigned... dont link CIs!");
535 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
537 // check if this pmthandler is already registered
538 PMTHandlerList::iterator it = m_pmt_handlers.begin();
539 while (it != m_pmt_handlers.end())
541 if ( *it++ == pmthandler )
545 eServiceReferenceDVB ref;
546 pmthandler->getServiceReference(ref);
547 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
549 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
550 recheckPMTHandlers();
553 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
555 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
556 if (it != m_pmt_handlers.end())
558 eDVBCISlot *slot = it->cislot;
559 eDVBServicePMTHandler *pmthandler = it->pmthandler;
560 m_pmt_handlers.erase(it);
562 eServiceReferenceDVB service_to_remove;
563 pmthandler->getServiceReference(service_to_remove);
565 bool sameServiceExist=false;
566 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
570 eServiceReferenceDVB ref;
571 i->pmthandler->getServiceReference(ref);
572 if ( ref == service_to_remove )
574 sameServiceExist=true;
582 if (!sameServiceExist)
584 if (slot->getNumOfServices() > 1)
586 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
587 service_to_remove.toString().c_str());
588 std::vector<uint16_t> caids;
589 caids.push_back(0xFFFF);
590 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
592 slot->removeService(service_to_remove.getServiceID().get());
595 eDVBCISlot *next = slot->linked_next;
596 if (!--slot->use_count)
598 if (slot->linked_next)
599 slot->linked_next->setSource(slot->current_source);
601 setInputSource(slot->current_tuner, slot->current_source);
603 if (it->cislot == slot) // remove the base slot
604 it->cislot = slot->linked_next;
607 eDVBCISlot *tmp = it->cislot;
608 while(tmp->linked_next != slot)
609 tmp = tmp->linked_next;
611 if (slot->linked_next)
612 tmp->linked_next = slot->linked_next;
614 tmp->linked_next = 0;
616 slot->linked_next = 0;
617 slot->user_mapped = false;
619 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
622 // check if another service is waiting for the CI
623 recheckPMTHandlers();
627 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
629 eDebug("[eDVBCIInterfaces] gotPMT");
630 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
631 if (it != m_pmt_handlers.end() && it->cislot)
633 eDVBCISlot *tmp = it->cislot;
636 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
637 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
638 tmp->sendCAPMT(pmthandler);
639 tmp = tmp->linked_next;
644 int eDVBCIInterfaces::getMMIState(int slotid)
648 if( (slot = getSlot(slotid)) == 0 )
651 return slot->getMMIState();
654 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
656 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
657 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
658 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
661 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
664 if((input = fopen(buf, "wb")) == NULL) {
665 eDebug("cannot open %s", buf);
670 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
675 fprintf(input, "CI0");
678 fprintf(input, "CI1");
681 fprintf(input, "CI2");
684 fprintf(input, "CI3");
699 eDebug("setInputSource for input %d failed!!!\n", (int)source);
708 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
711 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
714 if((input = fopen(buf, "wb")) == NULL) {
715 eDebug("cannot open %s", buf);
722 fprintf(input, "CI");
731 eDebug("setInputSource for input %d failed!!!\n", (int)source);
737 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
741 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
743 eDVBCISlot *slot = getSlot(slotid);
747 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
748 PyErr_SetString(PyExc_StandardError, tmp);
751 ePyObject tuple = PyTuple_New(3);
752 int caids = slot->possible_caids.size();
753 int services = slot->possible_services.size();
754 int providers = slot->possible_providers.size();
755 ePyObject caid_list = PyList_New(caids);
756 ePyObject service_list = PyList_New(services);
757 ePyObject provider_list = PyList_New(providers);
758 caidSet::iterator caid_it(slot->possible_caids.begin());
762 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
765 serviceSet::iterator ref_it(slot->possible_services.begin());
769 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
772 providerSet::iterator provider_it(slot->possible_providers.begin());
775 ePyObject tuple = PyTuple_New(2);
776 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
777 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
779 PyList_SET_ITEM(provider_list, providers, tuple);
782 PyTuple_SET_ITEM(tuple, 0, service_list);
783 PyTuple_SET_ITEM(tuple, 1, provider_list);
784 PyTuple_SET_ITEM(tuple, 2, caid_list);
788 const char *PyObject_TypeStr(PyObject *o)
790 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
793 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
795 eDVBCISlot *slot = getSlot(slotid);
799 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
800 PyErr_SetString(PyExc_StandardError, tmp);
803 if (!PyTuple_Check(obj))
806 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
807 PyErr_SetString(PyExc_StandardError, tmp);
810 if (PyTuple_Size(obj) != 3)
812 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
813 "first argument should be a pythonlist with possible services\n"
814 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
815 "third argument should be a pythonlist with possible caids";
816 PyErr_SetString(PyExc_StandardError, errstr);
819 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
820 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
821 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
822 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
825 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
826 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
827 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
828 "third argument(%s) should be a pythonlist with possible caids (ints)",
829 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
830 PyErr_SetString(PyExc_StandardError, errstr);
833 slot->possible_caids.clear();
834 slot->possible_services.clear();
835 slot->possible_providers.clear();
836 int size = PyList_Size(service_list);
840 ePyObject refstr = PyList_GET_ITEM(service_list, size);
841 if (!PyString_Check(refstr))
844 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
845 PyErr_SetString(PyExc_StandardError, buf);
848 char *tmpstr = PyString_AS_STRING(refstr);
849 eServiceReference ref(tmpstr);
851 slot->possible_services.insert(ref);
853 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
855 size = PyList_Size(provider_list);
859 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
860 if (!PyTuple_Check(tuple))
863 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
864 PyErr_SetString(PyExc_StandardError, buf);
867 if (PyTuple_Size(tuple) != 2)
870 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
871 PyErr_SetString(PyExc_StandardError, buf);
874 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
877 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
878 PyErr_SetString(PyExc_StandardError, buf);
881 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
884 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
885 PyErr_SetString(PyExc_StandardError, buf);
888 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
889 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
891 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
893 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
895 size = PyList_Size(caid_list);
899 ePyObject caid = PyList_GET_ITEM(caid_list, size);
900 if (!PyLong_Check(caid))
903 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
904 PyErr_SetString(PyExc_StandardError, buf);
907 int tmpcaid = PyLong_AsLong(caid);
908 if (tmpcaid > 0 && tmpcaid < 0x10000)
909 slot->possible_caids.insert(tmpcaid);
911 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
916 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
918 eDVBCISlot *slot = getSlot(slotid);
922 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
923 PyErr_SetString(PyExc_StandardError, tmp);
928 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
929 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
930 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
933 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
934 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
941 int eDVBCISlot::send(const unsigned char *data, size_t len)
945 //eDebugNoNewLine("< ");
947 // eDebugNoNewLine("%02x ",data[i]);
950 if (sendqueue.empty())
951 res = ::write(fd, data, len);
953 if (res < 0 || (unsigned int)res != len)
955 unsigned char *d = new unsigned char[len];
956 memcpy(d, data, len);
957 sendqueue.push( queueData(d, len) );
958 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
964 void eDVBCISlot::data(int what)
966 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
967 if(what == eSocketNotifier::Priority) {
968 if(state != stateRemoved) {
969 state = stateRemoved;
970 while(sendqueue.size())
972 delete [] sendqueue.top().data;
975 eDVBCISession::deleteSessions(this);
976 eDVBCIInterfaces::getInstance()->ciRemoved(this);
977 notifier->setRequested(eSocketNotifier::Read);
978 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
983 if (state == stateInvalid)
986 if(state != stateInserted) {
987 eDebug("ci inserted in slot %d", getSlotID());
988 state = stateInserted;
989 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
990 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
991 /* enable PRI to detect removal or errors */
994 if (what & eSocketNotifier::Read) {
997 r = ::read(fd, data, 4096);
1000 // eDebugNoNewLine("> ");
1002 // eDebugNoNewLine("%02x ",data[i]);
1004 eDVBCISession::receiveData(this, data, r);
1005 eDVBCISession::pollAll();
1009 else if (what & eSocketNotifier::Write) {
1010 if (!sendqueue.empty()) {
1011 const queueData &qe = sendqueue.top();
1012 int res = ::write(fd, qe.data, qe.len);
1013 if (res >= 0 && (unsigned int)res == qe.len)
1020 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1024 DEFINE_REF(eDVBCISlot);
1026 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1030 application_manager = 0;
1035 user_mapped = false;
1036 first_plugged = true;
1040 sprintf(filename, "/dev/ci%d", nr);
1042 // possible_caids.insert(0x1702);
1043 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1044 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1046 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1048 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1049 state = stateInvalid;
1053 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1054 CONNECT(notifier->activated, eDVBCISlot::data);
1061 eDVBCISlot::~eDVBCISlot()
1063 eDVBCISession::deleteSessions(this);
1066 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1068 application_manager=session;
1071 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1073 mmi_session = session;
1076 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1078 ca_manager = session;
1081 int eDVBCISlot::getSlotID()
1086 int eDVBCISlot::reset()
1088 eDebug("CI Slot %d: reset requested", getSlotID());
1090 if (state == stateInvalid)
1092 unsigned char buf[256];
1094 while(::read(fd, buf, 256)>0);
1095 state = stateResetted;
1098 while(sendqueue.size())
1100 delete [] sendqueue.top().data;
1109 int eDVBCISlot::startMMI()
1111 eDebug("CI Slot %d: startMMI()", getSlotID());
1113 if(application_manager)
1114 application_manager->startMMI();
1119 int eDVBCISlot::stopMMI()
1121 eDebug("CI Slot %d: stopMMI()", getSlotID());
1124 mmi_session->stopMMI();
1129 int eDVBCISlot::answerText(int answer)
1131 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1134 mmi_session->answerText(answer);
1139 int eDVBCISlot::getMMIState()
1147 int eDVBCISlot::answerEnq(char *value)
1149 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1152 mmi_session->answerEnq(value);
1157 int eDVBCISlot::cancelEnq()
1159 eDebug("CI Slot %d: cancelENQ", getSlotID());
1162 mmi_session->cancelEnq();
1167 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1171 eDebug("no ca_manager (no CI plugged?)");
1174 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1175 ePtr<eTable<ProgramMapSection> > ptr;
1176 if (pmthandler->getPMT(ptr))
1180 eDVBTableSpec table_spec;
1181 ptr->getSpec(table_spec);
1182 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1184 eServiceReferenceDVB ref;
1185 pmthandler->getServiceReference(ref);
1186 uint16_t program_number = ref.getServiceID().get();
1187 std::map<uint16_t, uint8_t>::iterator it =
1188 running_services.find(program_number);
1190 if ( it != running_services.end() &&
1191 (pmt_version == it->second) &&
1192 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1194 eDebug("[eDVBCISlot] dont send self capmt version twice");
1198 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1199 if ( i == ptr->getSections().end() )
1203 unsigned char raw_data[2048];
1205 // eDebug("send %s capmt for service %04x to slot %d",
1206 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1207 // program_number, slotid);
1209 CaProgramMapSection capmt(*i++,
1210 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1211 while( i != ptr->getSections().end() )
1213 // eDebug("append");
1216 capmt.writeToBuffer(raw_data);
1218 // begin calc capmt length
1221 if ( raw_data[3] & 0x80 )
1224 int lenbytes = raw_data[3] & ~0x80;
1226 wp = (wp << 8) | raw_data[4 + i++];
1229 hlen = 4 + lenbytes;
1237 // end calc capmt length
1238 // eDebug("ca_manager %p dump capmt:", ca_manager);
1239 // for(int i=0;i<wp;i++)
1240 // eDebugNoNewLine("%02x ", raw_data[i]);
1243 if (caids.size() == 1 && caids[0] == 0xFFFF)
1245 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1246 raw_data[hlen+3] &= ~0x3E;
1247 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1248 // eDebug(" new version is %02x", raw_data[hlen+3]);
1251 //dont need tag and lenfield
1252 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1253 running_services[program_number] = pmt_version;
1259 void eDVBCISlot::removeService(uint16_t program_number)
1261 if (program_number == 0xFFFF)
1262 running_services.clear(); // remove all
1264 running_services.erase(program_number); // remove single service
1267 int eDVBCISlot::setSource(data_source source)
1269 current_source = source;
1270 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1273 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1274 FILE *ci = fopen(buf, "wb");
1302 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1309 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1310 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1311 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1313 eDebug("cannot open /proc/stb/tsmux/input2");
1316 if (source != TUNER_A && source != TUNER_B)
1317 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1319 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1322 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1326 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");