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 setInputSource(slot->current_tuner, slot->current_source);
230 slot->removeVtunerPid();
232 slot->linked_next = 0;
235 slot->user_mapped=false;
236 slot->removeService(0xFFFF);
237 recheckPMTHandlers();
241 static bool canDescrambleMultipleServices(int slotid)
244 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
246 ePythonConfigQuery::getConfigValue(configStr, str);
249 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
250 if (appname.find("AlphaCrypt") != std::string::npos)
253 else if (str == "yes")
258 void eDVBCIInterfaces::recheckPMTHandlers()
260 eDebugCI("recheckPMTHAndlers()");
261 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
262 it != m_pmt_handlers.end(); ++it)
265 ePtr<eDVBService> service;
266 eServiceReferenceDVB ref;
267 eDVBCISlot *tmp = it->cislot;
268 eDVBServicePMTHandler *pmthandler = it->pmthandler;
269 eDVBServicePMTHandler::program p;
270 bool plugged_cis_exist = false;
272 pmthandler->getServiceReference(ref);
273 pmthandler->getService(service);
275 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
276 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
277 if (ci_it->plugged && ci_it->getCAManager())
279 eDebug("Slot %d plugged", ci_it->getSlotID());
280 ci_it->plugged = false;
281 plugged_cis_exist = true;
284 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
285 if (!plugged_cis_exist)
289 if (!tmp->running_services.empty())
291 tmp=tmp->linked_next;
293 if (tmp) // we dont like to change tsmux for running services
295 eDebugCI("already assigned and running CI!\n");
300 if (!pmthandler->getProgramInfo(p))
303 std::set<eDVBServicePMTHandler::program::capid_pair> set(p.caids.begin(), p.caids.end());
304 for (std::set<eDVBServicePMTHandler::program::capid_pair>::reverse_iterator x(set.rbegin()); x != set.rend(); ++x, ++cnt)
305 caids.push_front(x->caid);
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);
395 ci_it->addVtunerPid(pmthandler);
404 // check if this CI is already assigned to this pmthandler
405 eDVBCISlot *tmp = it->cislot;
410 tmp=tmp->linked_next;
412 if (tmp) // ignore already assigned cislots...
414 eDebugCI("already assigned!");
417 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
418 if (ci_it->use_count) // check if this CI can descramble more than one service
422 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
423 while (!found && tmp != m_pmt_handlers.end())
426 eDVBCISlot *tmp_cislot = tmp->cislot;
427 while (!found && tmp_cislot)
430 eServiceReferenceDVB ref2;
431 tmp->pmthandler->getServiceReference(ref2);
432 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
434 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
435 eDVBChannelID s1, s2;
438 eDebugCI("different services!");
439 ref.getChannelID(s1);
440 ref2.getChannelID(s2);
442 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
446 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
450 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
451 tmpci=tmpci->linked_next;
455 tmp_cislot=tmp_cislot->linked_next;
464 if (ci_it->user_mapped) // we dont like to link user mapped CIs
466 eDebugCI("user mapped CI already in use... dont link!");
471 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
473 data_source ci_source=CI_A;
474 switch(ci_it->getSlotID())
476 case 0: ci_source = CI_A; break;
477 case 1: ci_source = CI_B; break;
478 case 2: ci_source = CI_C; break;
479 case 3: ci_source = CI_D; break;
481 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
488 eUsePtr<iDVBChannel> channel;
489 if (!pmthandler->getChannel(channel))
491 ePtr<iDVBFrontend> frontend;
492 if (!channel->getFrontend(frontend))
494 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
495 tunernum = fe->getSlotID();
498 ASSERT(tunernum != -1);
499 data_source tuner_source = TUNER_A;
503 tuner_source = (data_source)tunernum;
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 eDVBCISlot *base_slot = slot;
560 eDVBServicePMTHandler *pmthandler = it->pmthandler;
561 m_pmt_handlers.erase(it);
563 eServiceReferenceDVB service_to_remove;
564 pmthandler->getServiceReference(service_to_remove);
566 bool sameServiceExist=false;
567 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
571 eServiceReferenceDVB ref;
572 i->pmthandler->getServiceReference(ref);
573 if ( ref == service_to_remove )
575 sameServiceExist=true;
583 eDVBCISlot *next = slot->linked_next;
584 if (!sameServiceExist)
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
591 slot->removeService(service_to_remove.getServiceID().get());
594 if (!--slot->use_count)
596 if (slot->linked_next)
597 slot->linked_next->setSource(slot->current_source);
600 setInputSource(slot->current_tuner, slot->current_source);
601 slot->removeVtunerPid();
604 if (base_slot != slot)
606 eDVBCISlot *tmp = it->cislot;
607 while(tmp->linked_next != slot)
608 tmp = tmp->linked_next;
610 if (slot->linked_next)
611 tmp->linked_next = slot->linked_next;
613 tmp->linked_next = 0;
615 else // removed old base slot.. update ptr
616 base_slot = slot->linked_next;
617 slot->linked_next = 0;
618 slot->user_mapped = false;
620 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
623 // check if another service is waiting for the CI
624 recheckPMTHandlers();
628 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
630 eDebug("[eDVBCIInterfaces] gotPMT");
631 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
632 if (it != m_pmt_handlers.end() && it->cislot)
634 eDVBCISlot *tmp = it->cislot;
637 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
638 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
639 tmp->sendCAPMT(pmthandler);
640 tmp = tmp->linked_next;
645 int eDVBCIInterfaces::getMMIState(int slotid)
649 if( (slot = getSlot(slotid)) == 0 )
652 return slot->getMMIState();
655 static const char *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"};
657 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
659 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
660 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
661 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
664 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
667 if((input = fopen(buf, "wb")) == NULL) {
668 eDebug("cannot open %s", buf);
673 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
677 case TUNER_A ... CI_D:
678 fprintf(input, tuner_source[(int)source]);
681 eDebug("setInputSource for input %d failed!!!\n", (int)source);
690 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
693 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
696 if((input = fopen(buf, "wb")) == NULL) {
697 eDebug("cannot open %s", buf);
704 fprintf(input, "CI");
713 eDebug("setInputSource for input %d failed!!!\n", (int)source);
719 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
723 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
725 eDVBCISlot *slot = getSlot(slotid);
729 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
730 PyErr_SetString(PyExc_StandardError, tmp);
733 ePyObject tuple = PyTuple_New(3);
734 int caids = slot->possible_caids.size();
735 int services = slot->possible_services.size();
736 int providers = slot->possible_providers.size();
737 ePyObject caid_list = PyList_New(caids);
738 ePyObject service_list = PyList_New(services);
739 ePyObject provider_list = PyList_New(providers);
740 caidSet::iterator caid_it(slot->possible_caids.begin());
744 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
747 serviceSet::iterator ref_it(slot->possible_services.begin());
751 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
754 providerSet::iterator provider_it(slot->possible_providers.begin());
757 ePyObject tuple = PyTuple_New(2);
758 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
759 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
761 PyList_SET_ITEM(provider_list, providers, tuple);
764 PyTuple_SET_ITEM(tuple, 0, service_list);
765 PyTuple_SET_ITEM(tuple, 1, provider_list);
766 PyTuple_SET_ITEM(tuple, 2, caid_list);
770 const char *PyObject_TypeStr(PyObject *o)
772 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
775 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
777 eDVBCISlot *slot = getSlot(slotid);
781 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
782 PyErr_SetString(PyExc_StandardError, tmp);
785 if (!PyTuple_Check(obj))
788 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
789 PyErr_SetString(PyExc_StandardError, tmp);
792 if (PyTuple_Size(obj) != 3)
794 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
795 "first argument should be a pythonlist with possible services\n"
796 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
797 "third argument should be a pythonlist with possible caids";
798 PyErr_SetString(PyExc_StandardError, errstr);
801 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
802 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
803 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
804 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
807 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
808 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
809 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
810 "third argument(%s) should be a pythonlist with possible caids (ints)",
811 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
812 PyErr_SetString(PyExc_StandardError, errstr);
815 slot->possible_caids.clear();
816 slot->possible_services.clear();
817 slot->possible_providers.clear();
818 int size = PyList_Size(service_list);
822 ePyObject refstr = PyList_GET_ITEM(service_list, size);
823 if (!PyString_Check(refstr))
826 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
827 PyErr_SetString(PyExc_StandardError, buf);
830 char *tmpstr = PyString_AS_STRING(refstr);
831 eServiceReference ref(tmpstr);
833 slot->possible_services.insert(ref);
835 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
837 size = PyList_Size(provider_list);
841 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
842 if (!PyTuple_Check(tuple))
845 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
846 PyErr_SetString(PyExc_StandardError, buf);
849 if (PyTuple_Size(tuple) != 2)
852 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %zd instead of 2 entries!!", PyTuple_Size(tuple));
853 PyErr_SetString(PyExc_StandardError, buf);
856 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
859 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
860 PyErr_SetString(PyExc_StandardError, buf);
863 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
866 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
867 PyErr_SetString(PyExc_StandardError, buf);
870 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
871 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
873 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
875 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
877 size = PyList_Size(caid_list);
881 ePyObject caid = PyList_GET_ITEM(caid_list, size);
882 if (!PyLong_Check(caid))
885 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
886 PyErr_SetString(PyExc_StandardError, buf);
889 int tmpcaid = PyLong_AsLong(caid);
890 if (tmpcaid > 0 && tmpcaid < 0x10000)
891 slot->possible_caids.insert(tmpcaid);
893 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
898 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
900 eDVBCISlot *slot = getSlot(slotid);
904 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %zd slots are available", slotid, m_slots.size());
905 PyErr_SetString(PyExc_StandardError, tmp);
910 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
911 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
912 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
915 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
916 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
923 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
925 eDVBCISlot *slot = getSlot(slotid);
927 return slot->setClockRate(rate);
931 int eDVBCISlot::send(const unsigned char *data, size_t len)
935 //eDebugNoNewLine("< ");
937 // eDebugNoNewLine("%02x ",data[i]);
940 if (sendqueue.empty())
941 res = ::write(fd, data, len);
943 if (res < 0 || (unsigned int)res != len)
945 unsigned char *d = new unsigned char[len];
946 memcpy(d, data, len);
947 sendqueue.push( queueData(d, len) );
948 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
954 void eDVBCISlot::data(int what)
956 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
957 if(what == eSocketNotifier::Priority) {
958 if(state != stateRemoved) {
959 state = stateRemoved;
960 while(sendqueue.size())
962 delete [] sendqueue.top().data;
965 eDVBCISession::deleteSessions(this);
966 eDVBCIInterfaces::getInstance()->ciRemoved(this);
967 notifier->setRequested(eSocketNotifier::Read);
968 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
973 if (state == stateInvalid)
976 if(state != stateInserted) {
977 eDebug("ci inserted in slot %d", getSlotID());
978 state = stateInserted;
979 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
980 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
981 /* enable PRI to detect removal or errors */
984 if (what & eSocketNotifier::Read) {
987 r = ::read(fd, data, 4096);
990 // eDebugNoNewLine("> ");
992 // eDebugNoNewLine("%02x ",data[i]);
994 eDVBCISession::receiveData(this, data, r);
995 eDVBCISession::pollAll();
999 else if (what & eSocketNotifier::Write) {
1000 if (!sendqueue.empty()) {
1001 const queueData &qe = sendqueue.top();
1002 int res = ::write(fd, qe.data, qe.len);
1003 if (res >= 0 && (unsigned int)res == qe.len)
1010 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1014 DEFINE_REF(eDVBCISlot);
1016 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1020 application_manager = 0;
1025 user_mapped = false;
1030 sprintf(filename, "/dev/ci%d", nr);
1032 // possible_caids.insert(0x1702);
1033 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1034 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1036 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1038 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1039 state = stateInvalid;
1043 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1044 CONNECT(notifier->activated, eDVBCISlot::data);
1050 for(int i = 0; i < NUM_OF_ECM ; i++)
1058 eDVBCISlot::~eDVBCISlot()
1060 eDVBCISession::deleteSessions(this);
1063 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1065 application_manager=session;
1068 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1070 mmi_session = session;
1073 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1075 ca_manager = session;
1078 int eDVBCISlot::getSlotID()
1083 int eDVBCISlot::reset()
1085 eDebug("CI Slot %d: reset requested", getSlotID());
1087 if (state == stateInvalid)
1089 unsigned char buf[256];
1091 while(::read(fd, buf, 256)>0);
1092 state = stateResetted;
1095 while(sendqueue.size())
1097 delete [] sendqueue.top().data;
1106 int eDVBCISlot::startMMI()
1108 eDebug("CI Slot %d: startMMI()", getSlotID());
1110 if(application_manager)
1111 application_manager->startMMI();
1116 int eDVBCISlot::stopMMI()
1118 eDebug("CI Slot %d: stopMMI()", getSlotID());
1121 mmi_session->stopMMI();
1126 int eDVBCISlot::answerText(int answer)
1128 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1131 mmi_session->answerText(answer);
1136 int eDVBCISlot::getMMIState()
1144 int eDVBCISlot::answerEnq(char *value)
1146 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1149 mmi_session->answerEnq(value);
1154 int eDVBCISlot::cancelEnq()
1156 eDebug("CI Slot %d: cancelENQ", getSlotID());
1159 mmi_session->cancelEnq();
1164 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1168 eDebug("no ca_manager (no CI plugged?)");
1171 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1172 ePtr<eTable<ProgramMapSection> > ptr;
1173 if (pmthandler->getPMT(ptr))
1177 eDVBTableSpec table_spec;
1178 ptr->getSpec(table_spec);
1179 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1181 eServiceReferenceDVB ref;
1182 pmthandler->getServiceReference(ref);
1183 uint16_t program_number = ref.getServiceID().get();
1184 std::map<uint16_t, uint8_t>::iterator it =
1185 running_services.find(program_number);
1186 bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF;
1188 if ( it != running_services.end() &&
1189 (pmt_version == it->second) &&
1192 eDebug("[eDVBCISlot] dont send self capmt version twice");
1196 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1197 if ( i == ptr->getSections().end() )
1201 unsigned char raw_data[2048];
1203 // eDebug("send %s capmt for service %04x to slot %d",
1204 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1205 // program_number, slotid);
1207 CaProgramMapSection capmt(*i++,
1208 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1209 while( i != ptr->getSections().end() )
1211 // eDebug("append");
1214 capmt.writeToBuffer(raw_data);
1216 // begin calc capmt length
1219 if ( raw_data[3] & 0x80 )
1222 int lenbytes = raw_data[3] & ~0x80;
1224 wp = (wp << 8) | raw_data[4 + i++];
1227 hlen = 4 + lenbytes;
1235 // end calc capmt length
1239 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1240 if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
1241 raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
1242 raw_data[hlen+3] &= ~0x3E;
1243 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1244 // eDebug(" new version is %02x", raw_data[hlen+3]);
1247 // eDebug("ca_manager %p dump capmt:", ca_manager);
1248 // for(int i=0;i<wp;i++)
1249 // eDebugNoNewLine("%02x ", raw_data[i]);
1252 //dont need tag and lenfield
1253 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1254 running_services[program_number] = pmt_version;
1260 void eDVBCISlot::removeService(uint16_t program_number)
1262 if (program_number == 0xFFFF)
1263 running_services.clear(); // remove all
1265 running_services.erase(program_number); // remove single service
1268 int eDVBCISlot::setSource(data_source source)
1270 current_source = source;
1271 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1274 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1275 FILE *ci = fopen(buf, "wb");
1278 case TUNER_A ... CI_D:
1279 fprintf(ci, tuner_source[(int)source]);
1282 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1289 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1290 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1291 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1293 eDebug("cannot open /proc/stb/tsmux/input2");
1296 if (source != TUNER_A && source != TUNER_B)
1297 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1299 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1302 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1306 int eDVBCISlot::setClockRate(int rate)
1309 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1310 FILE *ci = fopen(buf, "wb");
1314 fprintf(ci, "high");
1316 fprintf(ci, "normal");
1323 void eDVBCISlot::addVtunerPid(eDVBServicePMTHandler *pmthandler)
1325 ePtr<iDVBDemux> demux;
1326 eDVBServicePMTHandler::program p;
1328 if (!pmthandler->getDataDemux(demux) && !ecm_num)
1331 if (!pmthandler->getProgramInfo(p))
1333 for (std::list<eDVBServicePMTHandler::program::capid_pair>::const_iterator i(p.caids.begin());
1334 i != p.caids.end(); ++i)
1338 eDebug("PES Start ECM PID = %d Caid = %d ecm_num=%d", i->capid, i->caid, ecm_num);
1339 m_ecm[ecm_num] = new eDVBECMParser(demux);
1340 m_ecm[ecm_num++]->start(i->capid);
1348 void eDVBCISlot::removeVtunerPid(void)
1350 for(int i = 0; i < ecm_num ; i++)
1361 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");