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 eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
943 eDVBCISlot *slot = getSlot(slotid);
945 return slot->setClockRate(rate);
949 int eDVBCISlot::send(const unsigned char *data, size_t len)
953 //eDebugNoNewLine("< ");
955 // eDebugNoNewLine("%02x ",data[i]);
958 if (sendqueue.empty())
959 res = ::write(fd, data, len);
961 if (res < 0 || (unsigned int)res != len)
963 unsigned char *d = new unsigned char[len];
964 memcpy(d, data, len);
965 sendqueue.push( queueData(d, len) );
966 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
972 void eDVBCISlot::data(int what)
974 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
975 if(what == eSocketNotifier::Priority) {
976 if(state != stateRemoved) {
977 state = stateRemoved;
978 while(sendqueue.size())
980 delete [] sendqueue.top().data;
983 eDVBCISession::deleteSessions(this);
984 eDVBCIInterfaces::getInstance()->ciRemoved(this);
985 notifier->setRequested(eSocketNotifier::Read);
986 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
991 if (state == stateInvalid)
994 if(state != stateInserted) {
995 eDebug("ci inserted in slot %d", getSlotID());
996 state = stateInserted;
997 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
998 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
999 /* enable PRI to detect removal or errors */
1002 if (what & eSocketNotifier::Read) {
1005 r = ::read(fd, data, 4096);
1008 // eDebugNoNewLine("> ");
1010 // eDebugNoNewLine("%02x ",data[i]);
1012 eDVBCISession::receiveData(this, data, r);
1013 eDVBCISession::pollAll();
1017 else if (what & eSocketNotifier::Write) {
1018 if (!sendqueue.empty()) {
1019 const queueData &qe = sendqueue.top();
1020 int res = ::write(fd, qe.data, qe.len);
1021 if (res >= 0 && (unsigned int)res == qe.len)
1028 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1032 DEFINE_REF(eDVBCISlot);
1034 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1038 application_manager = 0;
1043 user_mapped = false;
1044 first_plugged = true;
1048 sprintf(filename, "/dev/ci%d", nr);
1050 // possible_caids.insert(0x1702);
1051 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1052 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1054 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1056 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1057 state = stateInvalid;
1061 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1062 CONNECT(notifier->activated, eDVBCISlot::data);
1069 eDVBCISlot::~eDVBCISlot()
1071 eDVBCISession::deleteSessions(this);
1074 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1076 application_manager=session;
1079 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1081 mmi_session = session;
1084 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1086 ca_manager = session;
1089 int eDVBCISlot::getSlotID()
1094 int eDVBCISlot::reset()
1096 eDebug("CI Slot %d: reset requested", getSlotID());
1098 if (state == stateInvalid)
1100 unsigned char buf[256];
1102 while(::read(fd, buf, 256)>0);
1103 state = stateResetted;
1106 while(sendqueue.size())
1108 delete [] sendqueue.top().data;
1117 int eDVBCISlot::startMMI()
1119 eDebug("CI Slot %d: startMMI()", getSlotID());
1121 if(application_manager)
1122 application_manager->startMMI();
1127 int eDVBCISlot::stopMMI()
1129 eDebug("CI Slot %d: stopMMI()", getSlotID());
1132 mmi_session->stopMMI();
1137 int eDVBCISlot::answerText(int answer)
1139 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1142 mmi_session->answerText(answer);
1147 int eDVBCISlot::getMMIState()
1155 int eDVBCISlot::answerEnq(char *value)
1157 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1160 mmi_session->answerEnq(value);
1165 int eDVBCISlot::cancelEnq()
1167 eDebug("CI Slot %d: cancelENQ", getSlotID());
1170 mmi_session->cancelEnq();
1175 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1179 eDebug("no ca_manager (no CI plugged?)");
1182 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1183 ePtr<eTable<ProgramMapSection> > ptr;
1184 if (pmthandler->getPMT(ptr))
1188 eDVBTableSpec table_spec;
1189 ptr->getSpec(table_spec);
1190 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1192 eServiceReferenceDVB ref;
1193 pmthandler->getServiceReference(ref);
1194 uint16_t program_number = ref.getServiceID().get();
1195 std::map<uint16_t, uint8_t>::iterator it =
1196 running_services.find(program_number);
1198 if ( it != running_services.end() &&
1199 (pmt_version == it->second) &&
1200 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1202 eDebug("[eDVBCISlot] dont send self capmt version twice");
1206 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1207 if ( i == ptr->getSections().end() )
1211 unsigned char raw_data[2048];
1213 // eDebug("send %s capmt for service %04x to slot %d",
1214 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1215 // program_number, slotid);
1217 CaProgramMapSection capmt(*i++,
1218 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1219 while( i != ptr->getSections().end() )
1221 // eDebug("append");
1224 capmt.writeToBuffer(raw_data);
1226 // begin calc capmt length
1229 if ( raw_data[3] & 0x80 )
1232 int lenbytes = raw_data[3] & ~0x80;
1234 wp = (wp << 8) | raw_data[4 + i++];
1237 hlen = 4 + lenbytes;
1245 // end calc capmt length
1246 // eDebug("ca_manager %p dump capmt:", ca_manager);
1247 // for(int i=0;i<wp;i++)
1248 // eDebugNoNewLine("%02x ", raw_data[i]);
1251 if (caids.size() == 1 && caids[0] == 0xFFFF)
1253 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1254 raw_data[hlen+3] &= ~0x3E;
1255 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1256 // eDebug(" new version is %02x", raw_data[hlen+3]);
1259 //dont need tag and lenfield
1260 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1261 running_services[program_number] = pmt_version;
1267 void eDVBCISlot::removeService(uint16_t program_number)
1269 if (program_number == 0xFFFF)
1270 running_services.clear(); // remove all
1272 running_services.erase(program_number); // remove single service
1275 int eDVBCISlot::setSource(data_source source)
1277 current_source = source;
1278 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1281 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1282 FILE *ci = fopen(buf, "wb");
1310 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1317 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1318 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1319 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1321 eDebug("cannot open /proc/stb/tsmux/input2");
1324 if (source != TUNER_A && source != TUNER_B)
1325 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1327 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1330 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1334 int eDVBCISlot::setClockRate(int rate)
1337 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1338 FILE *ci = fopen(buf, "wb");
1342 fprintf(ci, "high");
1344 fprintf(ci, "normal");
1351 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");