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
229 if(slot->current_tuner == 99)
230 slot->setSource(PVR_NONE);
232 setInputSource(slot->current_tuner, slot->current_source);
234 slot->removeVtunerPid();
236 slot->linked_next = 0;
239 slot->user_mapped=false;
240 slot->removeService(0xFFFF);
241 recheckPMTHandlers();
245 static bool canDescrambleMultipleServices(int slotid)
248 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
250 ePythonConfigQuery::getConfigValue(configStr, str);
251 eDebugCI("canDescrambleMultipleServices %s", str.c_str());
254 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
255 if (appname.find("AlphaCrypt") != std::string::npos)
258 else if (str == "yes")
263 void eDVBCIInterfaces::recheckPMTHandlers()
265 eDebugCI("recheckPMTHAndlers()");
266 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
267 it != m_pmt_handlers.end(); ++it)
270 ePtr<eDVBService> service;
271 eServiceReferenceDVB ref;
272 eDVBCISlot *tmp = it->cislot;
273 eDVBServicePMTHandler *pmthandler = it->pmthandler;
274 eDVBServicePMTHandler::program p;
275 bool plugged_cis_exist = false;
277 pmthandler->getServiceReference(ref);
278 pmthandler->getService(service);
280 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
281 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
282 if (ci_it->plugged && ci_it->getCAManager())
284 eDebug("Slot %d plugged", ci_it->getSlotID());
285 ci_it->plugged = false;
286 plugged_cis_exist = true;
289 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
290 if (!plugged_cis_exist)
294 if (!tmp->running_services.empty())
296 tmp=tmp->linked_next;
298 if (tmp) // we dont like to change tsmux for running services
300 eDebugCI("already assigned and running CI!\n");
301 tmp->addVtunerPid(pmthandler);
306 if (!pmthandler->getProgramInfo(p))
309 std::set<eDVBServicePMTHandler::program::capid_pair> set(p.caids.begin(), p.caids.end());
310 for (std::set<eDVBServicePMTHandler::program::capid_pair>::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt)
311 caids.push_front(x->caid);
313 service->m_ca = caids;
317 caids = service->m_ca;
320 continue; // unscrambled service
322 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
324 eDebugCI("check Slot %d", ci_it->getSlotID());
326 bool user_mapped=true;
327 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
332 if (!ci_it->possible_services.empty())
335 serviceSet::iterator it = ci_it->possible_services.find(ref);
336 if (it != ci_it->possible_services.end())
338 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
343 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
346 it = ci_it->possible_services.find(ref);
347 if (it != ci_it->possible_services.end())
349 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
350 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
356 if (!useThis && !ci_it->possible_providers.empty())
358 eDVBNamespace ns = ref.getDVBNamespace();
360 if (!service) // subservice?
362 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
363 eDVBDB::getInstance()->getService(parent_ref, service);
367 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
368 if (it != ci_it->possible_providers.end())
370 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
375 if (!useThis && !ci_it->possible_caids.empty())
378 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
380 caidSet::iterator it = ci_it->possible_caids.find(*ca);
381 if (it != ci_it->possible_caids.end())
383 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
389 if (!useThis && !mask)
391 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
392 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
394 std::vector<uint16_t>::const_iterator z =
395 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
396 if ( z != ci_caids.end() && *z == *ca )
398 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
401 ci_it->addVtunerPid(pmthandler);
410 // check if this CI is already assigned to this pmthandler
411 eDVBCISlot *tmp = it->cislot;
416 tmp=tmp->linked_next;
418 if (tmp) // ignore already assigned cislots...
420 eDebugCI("already assigned!");
423 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
424 if (ci_it->use_count) // check if this CI can descramble more than one service
428 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
429 while (!found && tmp != m_pmt_handlers.end())
432 eDVBCISlot *tmp_cislot = tmp->cislot;
433 while (!found && tmp_cislot)
436 eServiceReferenceDVB ref2;
437 tmp->pmthandler->getServiceReference(ref2);
438 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
440 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
441 eDVBChannelID s1, s2;
444 eDebugCI("different services!");
445 ref.getChannelID(s1);
446 ref2.getChannelID(s2);
448 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
452 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
456 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
457 tmpci=tmpci->linked_next;
461 tmp_cislot=tmp_cislot->linked_next;
470 if (ci_it->user_mapped) // we dont like to link user mapped CIs
472 eDebugCI("user mapped CI already in use... dont link!");
477 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
479 data_source ci_source=CI_A;
480 switch(ci_it->getSlotID())
482 case 0: ci_source = CI_A; break;
483 case 1: ci_source = CI_B; break;
484 case 2: ci_source = CI_C; break;
485 case 3: ci_source = CI_D; break;
487 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
494 eUsePtr<iDVBChannel> channel;
495 if (!pmthandler->getChannel(channel))
497 ePtr<iDVBFrontend> frontend;
498 if (!channel->getFrontend(frontend))
500 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
501 tunernum = fe->getSlotID();
503 else // no frontend, PVR
506 ASSERT(tunernum != -1);
507 data_source tuner_source = TUNER_A;
511 tuner_source = (data_source)tunernum;
513 case 99: tuner_source = PVR;
516 eDebug("try to get source for tuner %d!!\n", tunernum);
519 ci_it->current_tuner = tunernum;
521 setInputSource(tunernum, ci_source);
522 ci_it->setSource(tuner_source);
526 ci_it->current_tuner = it->cislot->current_tuner;
527 ci_it->linked_next = it->cislot;
528 ci_it->setSource(ci_it->linked_next->current_source);
529 ci_it->linked_next->setSource(ci_source);
532 eDebugCI("assigned!");
536 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
538 eDebugCI("user mapped CI assigned... dont link CIs!");
546 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
548 // check if this pmthandler is already registered
549 PMTHandlerList::iterator it = m_pmt_handlers.begin();
550 while (it != m_pmt_handlers.end())
552 if ( *it++ == pmthandler )
556 eServiceReferenceDVB ref;
557 pmthandler->getServiceReference(ref);
558 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
560 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
561 recheckPMTHandlers();
564 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
566 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
567 if (it != m_pmt_handlers.end())
569 eDVBCISlot *slot = it->cislot;
570 eDVBCISlot *base_slot = slot;
571 eDVBServicePMTHandler *pmthandler = it->pmthandler;
572 m_pmt_handlers.erase(it);
574 eServiceReferenceDVB service_to_remove;
575 pmthandler->getServiceReference(service_to_remove);
577 bool sameServiceExist=false;
578 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
582 eServiceReferenceDVB ref;
583 i->pmthandler->getServiceReference(ref);
584 if ( ref == service_to_remove )
586 sameServiceExist=true;
594 eDVBCISlot *next = slot->linked_next;
595 if (!sameServiceExist)
597 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
598 service_to_remove.toString().c_str());
599 std::vector<uint16_t> caids;
600 caids.push_back(0xFFFF);
601 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
602 slot->removeService(service_to_remove.getServiceID().get());
605 if (!--slot->use_count)
607 if (slot->linked_next)
608 slot->linked_next->setSource(slot->current_source);
611 if(slot->current_tuner == 99)
612 slot->setSource(PVR_NONE);
614 setInputSource(slot->current_tuner, slot->current_source);
616 slot->removeVtunerPid();
619 if (base_slot != slot)
621 eDVBCISlot *tmp = it->cislot;
622 while(tmp->linked_next != slot)
623 tmp = tmp->linked_next;
625 if (slot->linked_next)
626 tmp->linked_next = slot->linked_next;
628 tmp->linked_next = 0;
630 else // removed old base slot.. update ptr
631 base_slot = slot->linked_next;
632 slot->linked_next = 0;
633 slot->user_mapped = false;
635 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
638 // check if another service is waiting for the CI
639 recheckPMTHandlers();
643 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
645 eDebug("[eDVBCIInterfaces] gotPMT");
646 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
647 if (it != m_pmt_handlers.end() && it->cislot)
649 eDVBCISlot *tmp = it->cislot;
652 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
653 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
654 tmp->sendCAPMT(pmthandler);
655 tmp = tmp->linked_next;
661 bool eDVBCIInterfaces::isCiConnected(eDVBServicePMTHandler *pmthandler)
664 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
665 if (it != m_pmt_handlers.end() && it->cislot)
673 int eDVBCIInterfaces::getMMIState(int slotid)
677 if( (slot = getSlot(slotid)) == 0 )
680 return slot->getMMIState();
683 static const char *g_tuner_source[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "CI0", "CI1", "CI2", "CI3"};
685 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
687 eDebugCI("[eDVBCIInterfaces] setInputSource(%d, %d)", tuner_no, (int)source);
688 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
691 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
694 if((input = fopen(buf, "wb")) == NULL) {
695 eDebug("cannot open %s", buf);
701 case TUNER_A ... CI_D:
702 fprintf(input, g_tuner_source[(int)source]);
705 eDebug("setInputSource for input %d failed!!!\n", (int)source);
714 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
717 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
720 if((input = fopen(buf, "wb")) == NULL) {
721 eDebug("cannot open %s", buf);
728 fprintf(input, "CI");
737 eDebug("setInputSource for input %d failed!!!\n", (int)source);
743 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
747 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
749 eDVBCISlot *slot = getSlot(slotid);
753 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
754 PyErr_SetString(PyExc_StandardError, tmp);
757 ePyObject tuple = PyTuple_New(3);
758 int caids = slot->possible_caids.size();
759 int services = slot->possible_services.size();
760 int providers = slot->possible_providers.size();
761 ePyObject caid_list = PyList_New(caids);
762 ePyObject service_list = PyList_New(services);
763 ePyObject provider_list = PyList_New(providers);
764 caidSet::iterator caid_it(slot->possible_caids.begin());
768 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
771 serviceSet::iterator ref_it(slot->possible_services.begin());
775 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
778 providerSet::iterator provider_it(slot->possible_providers.begin());
781 ePyObject tuple = PyTuple_New(2);
782 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
783 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
785 PyList_SET_ITEM(provider_list, providers, tuple);
788 PyTuple_SET_ITEM(tuple, 0, service_list);
789 PyTuple_SET_ITEM(tuple, 1, provider_list);
790 PyTuple_SET_ITEM(tuple, 2, caid_list);
794 const char *PyObject_TypeStr(PyObject *o)
796 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
799 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
801 eDVBCISlot *slot = getSlot(slotid);
805 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
806 PyErr_SetString(PyExc_StandardError, tmp);
809 if (!PyTuple_Check(obj))
812 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
813 PyErr_SetString(PyExc_StandardError, tmp);
816 if (PyTuple_Size(obj) != 3)
818 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
819 "first argument should be a pythonlist with possible services\n"
820 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
821 "third argument should be a pythonlist with possible caids";
822 PyErr_SetString(PyExc_StandardError, errstr);
825 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
826 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
827 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
828 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
831 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
832 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
833 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
834 "third argument(%s) should be a pythonlist with possible caids (ints)",
835 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
836 PyErr_SetString(PyExc_StandardError, errstr);
839 slot->possible_caids.clear();
840 slot->possible_services.clear();
841 slot->possible_providers.clear();
842 int size = PyList_Size(service_list);
846 ePyObject refstr = PyList_GET_ITEM(service_list, size);
847 if (!PyString_Check(refstr))
850 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
851 PyErr_SetString(PyExc_StandardError, buf);
854 char *tmpstr = PyString_AS_STRING(refstr);
855 eServiceReference ref(tmpstr);
857 slot->possible_services.insert(ref);
859 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
861 size = PyList_Size(provider_list);
865 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
866 if (!PyTuple_Check(tuple))
869 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
870 PyErr_SetString(PyExc_StandardError, buf);
873 if (PyTuple_Size(tuple) != 2)
876 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %zd instead of 2 entries!!", PyTuple_Size(tuple));
877 PyErr_SetString(PyExc_StandardError, buf);
880 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
883 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
884 PyErr_SetString(PyExc_StandardError, buf);
887 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
890 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
891 PyErr_SetString(PyExc_StandardError, buf);
894 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
895 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
897 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
899 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
901 size = PyList_Size(caid_list);
905 ePyObject caid = PyList_GET_ITEM(caid_list, size);
906 if (!PyLong_Check(caid))
909 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
910 PyErr_SetString(PyExc_StandardError, buf);
913 int tmpcaid = PyLong_AsLong(caid);
914 if (tmpcaid > 0 && tmpcaid < 0x10000)
915 slot->possible_caids.insert(tmpcaid);
917 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
922 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
924 eDVBCISlot *slot = getSlot(slotid);
928 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
929 PyErr_SetString(PyExc_StandardError, tmp);
934 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
935 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
936 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
939 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
940 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
947 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
949 eDVBCISlot *slot = getSlot(slotid);
951 return slot->setClockRate(rate);
955 int eDVBCISlot::send(const unsigned char *data, size_t len)
959 //eDebugNoNewLine("< ");
961 // eDebugNoNewLine("%02x ",data[i]);
964 if (sendqueue.empty())
965 res = ::write(fd, data, len);
967 if (res < 0 || (unsigned int)res != len)
969 unsigned char *d = new unsigned char[len];
970 memcpy(d, data, len);
971 sendqueue.push( queueData(d, len) );
972 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
978 void eDVBCISlot::data(int what)
980 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
981 if(what == eSocketNotifier::Priority) {
982 if(state != stateRemoved) {
983 state = stateRemoved;
984 while(sendqueue.size())
986 delete [] sendqueue.top().data;
989 eDVBCISession::deleteSessions(this);
990 eDVBCIInterfaces::getInstance()->ciRemoved(this);
991 notifier->setRequested(eSocketNotifier::Read);
992 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
997 if (state == stateInvalid)
1000 if(state != stateInserted) {
1001 eDebug("ci inserted in slot %d", getSlotID());
1002 state = stateInserted;
1003 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
1004 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1005 /* enable PRI to detect removal or errors */
1008 if (what & eSocketNotifier::Read) {
1011 r = ::read(fd, data, 4096);
1014 // eDebugNoNewLine("> ");
1016 // eDebugNoNewLine("%02x ",data[i]);
1018 eDVBCISession::receiveData(this, data, r);
1019 eDVBCISession::pollAll();
1023 else if (what & eSocketNotifier::Write) {
1024 if (!sendqueue.empty()) {
1025 const queueData &qe = sendqueue.top();
1026 int res = ::write(fd, qe.data, qe.len);
1027 if (res >= 0 && (unsigned int)res == qe.len)
1034 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1038 DEFINE_REF(eDVBCISlot);
1040 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1044 application_manager = 0;
1049 user_mapped = false;
1054 sprintf(filename, "/dev/ci%d", nr);
1056 // possible_caids.insert(0x1702);
1057 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1058 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1060 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1062 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1063 state = stateInvalid;
1067 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1068 CONNECT(notifier->activated, eDVBCISlot::data);
1075 eDVBCISlot::~eDVBCISlot()
1077 eDVBCISession::deleteSessions(this);
1080 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1082 application_manager=session;
1085 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1087 mmi_session = session;
1090 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1092 ca_manager = session;
1095 int eDVBCISlot::getSlotID()
1100 int eDVBCISlot::reset()
1102 eDebug("CI Slot %d: reset requested", getSlotID());
1104 if (state == stateInvalid)
1106 unsigned char buf[256];
1108 while(::read(fd, buf, 256)>0);
1109 state = stateResetted;
1112 while(sendqueue.size())
1114 delete [] sendqueue.top().data;
1123 int eDVBCISlot::startMMI()
1125 eDebug("CI Slot %d: startMMI()", getSlotID());
1127 if(application_manager)
1128 application_manager->startMMI();
1133 int eDVBCISlot::stopMMI()
1135 eDebug("CI Slot %d: stopMMI()", getSlotID());
1138 mmi_session->stopMMI();
1143 int eDVBCISlot::answerText(int answer)
1145 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1148 mmi_session->answerText(answer);
1153 int eDVBCISlot::getMMIState()
1161 int eDVBCISlot::answerEnq(char *value)
1163 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1166 mmi_session->answerEnq(value);
1171 int eDVBCISlot::cancelEnq()
1173 eDebug("CI Slot %d: cancelENQ", getSlotID());
1176 mmi_session->cancelEnq();
1181 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1185 eDebug("no ca_manager (no CI plugged?)");
1188 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1189 ePtr<eTable<ProgramMapSection> > ptr;
1190 if (pmthandler->getPMT(ptr))
1194 eDVBTableSpec table_spec;
1195 ptr->getSpec(table_spec);
1196 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1198 eServiceReferenceDVB ref;
1199 pmthandler->getServiceReference(ref);
1200 uint16_t program_number = ref.getServiceID().get();
1201 std::map<uint16_t, uint8_t>::iterator it =
1202 running_services.find(program_number);
1203 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1205 if ( it != running_services.end() &&
1206 (pmt_version == it->second) &&
1209 eDebug("[eDVBCISlot] dont send self capmt version twice");
1213 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1214 if ( i == ptr->getSections().end() )
1218 unsigned char raw_data[2048];
1220 // eDebug("send %s capmt for service %04x to slot %d",
1221 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1222 // program_number, slotid);
1224 CaProgramMapSection capmt(*i++,
1225 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1226 while( i != ptr->getSections().end() )
1228 // eDebug("append");
1231 capmt.writeToBuffer(raw_data);
1233 // begin calc capmt length
1236 if ( raw_data[3] & 0x80 )
1239 int lenbytes = raw_data[3] & ~0x80;
1241 wp = (wp << 8) | raw_data[4 + i++];
1244 hlen = 4 + lenbytes;
1252 // end calc capmt length
1256 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1257 if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
1258 raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1259 raw_data[hlen+3] &= ~0x3E;
1260 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1261 // eDebug(" new version is %02x", raw_data[hlen+3]);
1264 // eDebug("ca_manager %p dump capmt:", ca_manager);
1265 // for(int i=0;i<wp;i++)
1266 // eDebugNoNewLine("%02x ", raw_data[i]);
1269 //dont need tag and lenfield
1270 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1271 running_services[program_number] = pmt_version;
1277 void eDVBCISlot::removeService(uint16_t program_number)
1279 if (program_number == 0xFFFF)
1280 running_services.clear(); // remove all
1282 running_services.erase(program_number); // remove single service
1285 int eDVBCISlot::setSource(data_source source)
1287 current_source = source;
1288 eDebugCI("[eDVBCISlot] setSource %d", (int)source);
1289 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1292 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1293 FILE *ci = fopen(buf, "wb");
1296 case TUNER_A ... CI_D:
1297 fprintf(ci, g_tuner_source[(int)source]);
1303 fprintf(ci, "PVR_NONE");
1306 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1313 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1314 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1315 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1317 eDebug("cannot open /proc/stb/tsmux/input2");
1320 if (source != TUNER_A && source != TUNER_B)
1321 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1323 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1326 eDebugCI("[eDVBCISlot] CI Slot %d setSource(%d)", getSlotID(), (int)source);
1330 int eDVBCISlot::setClockRate(int rate)
1333 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1334 FILE *ci = fopen(buf, "wb");
1338 fprintf(ci, "high");
1340 fprintf(ci, "normal");
1347 void eDVBCISlot::addVtunerPid(eDVBServicePMTHandler *pmthandler)
1349 ePtr<iDVBDemux> demux;
1350 eDVBServicePMTHandler::program p;
1353 if (!pmthandler->getDataDemux(demux))
1356 if (!pmthandler->getProgramInfo(p))
1358 for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(p.caids.begin());
1359 i != p.caids.end(); ++i)
1362 for (eSmartPtrList<eDVBECMParser>::iterator it(m_ecms.begin()); it != m_ecms.end(); ++it)
1364 if(it->getPid() == i->capid)
1371 if (i->capid >= 0 && !ignore)
1373 ePtr<eDVBECMParser> ecm;
1374 eDebug("PES Start CAPID = %d Caid = %d", i->capid, i->caid);
1375 ecm = new eDVBECMParser(demux);
1376 m_ecms.push_back(ecm);
1377 ecm->start(i->capid);
1385 void eDVBCISlot::removeVtunerPid(void)
1387 eDebugCI("eDVBCISlot::removeVtunerPid...");
1388 for (eSmartPtrList<eDVBECMParser>::iterator it(m_ecms.begin()); it != m_ecms.end(); ++it)
1395 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");