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 (!PyInt_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 = PyInt_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);
927 ePyObject list = PyList_New(slot->possible_caids.size());
928 for (caidSet::iterator it = slot->possible_caids.begin(); it != slot->possible_caids.end(); ++it)
929 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
933 int eDVBCISlot::send(const unsigned char *data, size_t len)
937 //eDebugNoNewLine("< ");
939 // eDebugNoNewLine("%02x ",data[i]);
942 if (sendqueue.empty())
943 res = ::write(fd, data, len);
945 if (res < 0 || (unsigned int)res != len)
947 unsigned char *d = new unsigned char[len];
948 memcpy(d, data, len);
949 sendqueue.push( queueData(d, len) );
950 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
956 void eDVBCISlot::data(int what)
958 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
959 if(what == eSocketNotifier::Priority) {
960 if(state != stateRemoved) {
961 state = stateRemoved;
962 while(sendqueue.size())
964 delete [] sendqueue.top().data;
967 eDVBCISession::deleteSessions(this);
968 eDVBCIInterfaces::getInstance()->ciRemoved(this);
969 notifier->setRequested(eSocketNotifier::Read);
970 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
975 if (state == stateInvalid)
978 if(state != stateInserted) {
979 eDebug("ci inserted in slot %d", getSlotID());
980 state = stateInserted;
981 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
982 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
983 /* enable PRI to detect removal or errors */
986 if (what & eSocketNotifier::Read) {
989 r = ::read(fd, data, 4096);
992 // eDebugNoNewLine("> ");
994 // eDebugNoNewLine("%02x ",data[i]);
996 eDVBCISession::receiveData(this, data, r);
997 eDVBCISession::pollAll();
1001 else if (what & eSocketNotifier::Write) {
1002 if (!sendqueue.empty()) {
1003 const queueData &qe = sendqueue.top();
1004 int res = ::write(fd, qe.data, qe.len);
1005 if (res >= 0 && (unsigned int)res == qe.len)
1012 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1016 DEFINE_REF(eDVBCISlot);
1018 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1022 application_manager = 0;
1027 user_mapped = false;
1028 first_plugged = true;
1032 sprintf(filename, "/dev/ci%d", nr);
1034 // possible_caids.insert(0x1702);
1035 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1036 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1038 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1040 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1041 state = stateInvalid;
1045 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1046 CONNECT(notifier->activated, eDVBCISlot::data);
1053 eDVBCISlot::~eDVBCISlot()
1055 eDVBCISession::deleteSessions(this);
1058 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1060 application_manager=session;
1063 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1065 mmi_session = session;
1068 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1070 ca_manager = session;
1073 int eDVBCISlot::getSlotID()
1078 int eDVBCISlot::reset()
1080 eDebug("CI Slot %d: reset requested", getSlotID());
1082 if (state == stateInvalid)
1084 unsigned char buf[256];
1086 while(::read(fd, buf, 256)>0);
1087 state = stateResetted;
1090 while(sendqueue.size())
1092 delete [] sendqueue.top().data;
1101 int eDVBCISlot::startMMI()
1103 eDebug("CI Slot %d: startMMI()", getSlotID());
1105 if(application_manager)
1106 application_manager->startMMI();
1111 int eDVBCISlot::stopMMI()
1113 eDebug("CI Slot %d: stopMMI()", getSlotID());
1116 mmi_session->stopMMI();
1121 int eDVBCISlot::answerText(int answer)
1123 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1126 mmi_session->answerText(answer);
1131 int eDVBCISlot::getMMIState()
1139 int eDVBCISlot::answerEnq(char *value)
1141 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1144 mmi_session->answerEnq(value);
1149 int eDVBCISlot::cancelEnq()
1151 eDebug("CI Slot %d: cancelENQ", getSlotID());
1154 mmi_session->cancelEnq();
1159 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1163 eDebug("no ca_manager (no CI plugged?)");
1166 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1167 ePtr<eTable<ProgramMapSection> > ptr;
1168 if (pmthandler->getPMT(ptr))
1172 eDVBTableSpec table_spec;
1173 ptr->getSpec(table_spec);
1174 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1176 eServiceReferenceDVB ref;
1177 pmthandler->getServiceReference(ref);
1178 uint16_t program_number = ref.getServiceID().get();
1179 std::map<uint16_t, uint8_t>::iterator it =
1180 running_services.find(program_number);
1182 if ( it != running_services.end() &&
1183 (pmt_version == it->second) &&
1184 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1186 eDebug("[eDVBCISlot] dont send self capmt version twice");
1190 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1191 if ( i == ptr->getSections().end() )
1195 unsigned char raw_data[2048];
1197 // eDebug("send %s capmt for service %04x to slot %d",
1198 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1199 // program_number, slotid);
1201 CaProgramMapSection capmt(*i++,
1202 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1203 while( i != ptr->getSections().end() )
1205 // eDebug("append");
1208 capmt.writeToBuffer(raw_data);
1210 // begin calc capmt length
1213 if ( raw_data[3] & 0x80 )
1216 int lenbytes = raw_data[3] & ~0x80;
1218 wp = (wp << 8) | raw_data[4 + i++];
1221 hlen = 4 + lenbytes;
1229 // end calc capmt length
1230 // eDebug("ca_manager %p dump capmt:", ca_manager);
1231 // for(int i=0;i<wp;i++)
1232 // eDebugNoNewLine("%02x ", raw_data[i]);
1235 if (caids.size() == 1 && caids[0] == 0xFFFF)
1237 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1238 raw_data[hlen+3] &= ~0x3E;
1239 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1240 // eDebug(" new version is %02x", raw_data[hlen+3]);
1243 //dont need tag and lenfield
1244 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1245 running_services[program_number] = pmt_version;
1251 void eDVBCISlot::removeService(uint16_t program_number)
1253 if (program_number == 0xFFFF)
1254 running_services.clear(); // remove all
1256 running_services.erase(program_number); // remove single service
1259 int eDVBCISlot::setSource(data_source source)
1261 current_source = source;
1262 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1265 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1266 FILE *ci = fopen(buf, "wb");
1294 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1301 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1302 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1303 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1305 eDebug("cannot open /proc/stb/tsmux/input2");
1308 if (source != TUNER_A && source != TUNER_B)
1309 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1311 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1314 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1318 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");