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
228 setInputSource(slot->current_tuner, slot->current_source);
229 slot->linked_next = 0;
232 slot->user_mapped=false;
233 slot->removeService(0xFFFF);
234 recheckPMTHandlers();
238 static bool canDescrambleMultipleServices(int slotid)
241 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
243 ePythonConfigQuery::getConfigValue(configStr, str);
246 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
247 if (appname.find("AlphaCrypt") != std::string::npos)
250 else if (str == "yes")
255 void eDVBCIInterfaces::recheckPMTHandlers()
257 eDebugCI("recheckPMTHAndlers()");
258 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
259 it != m_pmt_handlers.end(); ++it)
262 ePtr<eDVBService> service;
263 eServiceReferenceDVB ref;
264 eDVBCISlot *tmp = it->cislot;
265 eDVBServicePMTHandler *pmthandler = it->pmthandler;
266 eDVBServicePMTHandler::program p;
267 bool plugged_cis_exist = false;
269 pmthandler->getServiceReference(ref);
270 pmthandler->getService(service);
272 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
273 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
274 if (ci_it->plugged && ci_it->getCAManager())
276 eDebug("Slot %d plugged", ci_it->getSlotID());
277 ci_it->plugged = false;
278 plugged_cis_exist = true;
281 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
282 if (!plugged_cis_exist)
286 if (!tmp->running_services.empty())
288 tmp=tmp->linked_next;
290 if (tmp) // we dont like to change tsmux for running services
292 eDebugCI("already assigned and running CI!\n");
297 if (!pmthandler->getProgramInfo(p))
300 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
301 caids.push_front(*x);
303 service->m_ca = caids;
307 caids = service->m_ca;
310 continue; // unscrambled service
312 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
314 eDebugCI("check Slot %d", ci_it->getSlotID());
316 bool user_mapped=true;
317 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
322 if (!ci_it->possible_services.empty())
325 serviceSet::iterator it = ci_it->possible_services.find(ref);
326 if (it != ci_it->possible_services.end())
328 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
333 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
336 it = ci_it->possible_services.find(ref);
337 if (it != ci_it->possible_services.end())
339 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
340 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
346 if (!useThis && !ci_it->possible_providers.empty())
348 eDVBNamespace ns = ref.getDVBNamespace();
350 if (!service) // subservice?
352 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
353 eDVBDB::getInstance()->getService(parent_ref, service);
357 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
358 if (it != ci_it->possible_providers.end())
360 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
365 if (!useThis && !ci_it->possible_caids.empty())
368 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
370 caidSet::iterator it = ci_it->possible_caids.find(*ca);
371 if (it != ci_it->possible_caids.end())
373 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
379 if (!useThis && !mask)
381 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
382 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
384 std::vector<uint16_t>::const_iterator z =
385 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
386 if ( z != ci_caids.end() && *z == *ca )
388 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
399 // check if this CI is already assigned to this pmthandler
400 eDVBCISlot *tmp = it->cislot;
405 tmp=tmp->linked_next;
407 if (tmp) // ignore already assigned cislots...
409 eDebugCI("already assigned!");
412 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
413 if (ci_it->use_count) // check if this CI can descramble more than one service
417 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
418 while (!found && tmp != m_pmt_handlers.end())
421 eDVBCISlot *tmp_cislot = tmp->cislot;
422 while (!found && tmp_cislot)
425 eServiceReferenceDVB ref2;
426 tmp->pmthandler->getServiceReference(ref2);
427 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
429 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
430 eDVBChannelID s1, s2;
433 eDebugCI("different services!");
434 ref.getChannelID(s1);
435 ref2.getChannelID(s2);
437 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
441 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
445 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
446 tmpci=tmpci->linked_next;
450 tmp_cislot=tmp_cislot->linked_next;
459 if (ci_it->user_mapped) // we dont like to link user mapped CIs
461 eDebugCI("user mapped CI already in use... dont link!");
466 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
468 data_source ci_source=CI_A;
469 switch(ci_it->getSlotID())
471 case 0: ci_source = CI_A; break;
472 case 1: ci_source = CI_B; break;
473 case 2: ci_source = CI_C; break;
474 case 3: ci_source = CI_D; break;
476 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
483 eUsePtr<iDVBChannel> channel;
484 if (!pmthandler->getChannel(channel))
486 ePtr<iDVBFrontend> frontend;
487 if (!channel->getFrontend(frontend))
489 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
490 tunernum = fe->getSlotID();
493 ASSERT(tunernum != -1);
494 data_source tuner_source = TUNER_A;
497 case 0: tuner_source = TUNER_A; break;
498 case 1: tuner_source = TUNER_B; break;
499 case 2: tuner_source = TUNER_C; break;
500 case 3: tuner_source = TUNER_D; break;
502 eDebug("try to get source for tuner %d!!\n", tunernum);
505 ci_it->current_tuner = tunernum;
506 setInputSource(tunernum, ci_source);
507 ci_it->setSource(tuner_source);
511 ci_it->current_tuner = it->cislot->current_tuner;
512 ci_it->linked_next = it->cislot;
513 ci_it->setSource(ci_it->linked_next->current_source);
514 ci_it->linked_next->setSource(ci_source);
517 eDebugCI("assigned!");
521 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
523 eDebugCI("user mapped CI assigned... dont link CIs!");
531 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
533 // check if this pmthandler is already registered
534 PMTHandlerList::iterator it = m_pmt_handlers.begin();
535 while (it != m_pmt_handlers.end())
537 if ( *it++ == pmthandler )
541 eServiceReferenceDVB ref;
542 pmthandler->getServiceReference(ref);
543 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
545 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
546 recheckPMTHandlers();
549 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
551 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
552 if (it != m_pmt_handlers.end())
554 eDVBCISlot *slot = it->cislot;
555 eDVBServicePMTHandler *pmthandler = it->pmthandler;
556 m_pmt_handlers.erase(it);
558 eServiceReferenceDVB service_to_remove;
559 pmthandler->getServiceReference(service_to_remove);
561 bool sameServiceExist=false;
562 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
566 eServiceReferenceDVB ref;
567 i->pmthandler->getServiceReference(ref);
568 if ( ref == service_to_remove )
570 sameServiceExist=true;
578 if (!sameServiceExist)
580 // if (slot->getNumOfServices() > 1)
582 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
583 service_to_remove.toString().c_str());
584 std::vector<uint16_t> caids;
585 caids.push_back(0xFFFF);
586 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
588 slot->removeService(service_to_remove.getServiceID().get());
591 eDVBCISlot *next = slot->linked_next;
592 if (!--slot->use_count)
594 if (slot->linked_next)
595 slot->linked_next->setSource(slot->current_source);
597 setInputSource(slot->current_tuner, slot->current_source);
599 if (it->cislot == slot) // remove the base slot
600 it->cislot = slot->linked_next;
603 eDVBCISlot *tmp = it->cislot;
604 while(tmp->linked_next != slot)
605 tmp = tmp->linked_next;
607 if (slot->linked_next)
608 tmp->linked_next = slot->linked_next;
610 tmp->linked_next = 0;
612 slot->linked_next = 0;
613 slot->user_mapped = false;
615 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
618 // check if another service is waiting for the CI
619 recheckPMTHandlers();
623 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
625 eDebug("[eDVBCIInterfaces] gotPMT");
626 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
627 if (it != m_pmt_handlers.end() && it->cislot)
629 eDVBCISlot *tmp = it->cislot;
632 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
633 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
634 tmp->sendCAPMT(pmthandler);
635 tmp = tmp->linked_next;
640 int eDVBCIInterfaces::getMMIState(int slotid)
644 if( (slot = getSlot(slotid)) == 0 )
647 return slot->getMMIState();
650 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
652 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
653 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
654 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
657 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
660 if((input = fopen(buf, "wb")) == NULL) {
661 eDebug("cannot open %s", buf);
666 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
671 fprintf(input, "CI0");
674 fprintf(input, "CI1");
677 fprintf(input, "CI2");
680 fprintf(input, "CI3");
695 eDebug("setInputSource for input %d failed!!!\n", (int)source);
704 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
707 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
710 if((input = fopen(buf, "wb")) == NULL) {
711 eDebug("cannot open %s", buf);
718 fprintf(input, "CI");
727 eDebug("setInputSource for input %d failed!!!\n", (int)source);
733 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
737 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
739 eDVBCISlot *slot = getSlot(slotid);
743 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
744 PyErr_SetString(PyExc_StandardError, tmp);
747 ePyObject tuple = PyTuple_New(3);
748 int caids = slot->possible_caids.size();
749 int services = slot->possible_services.size();
750 int providers = slot->possible_providers.size();
751 ePyObject caid_list = PyList_New(caids);
752 ePyObject service_list = PyList_New(services);
753 ePyObject provider_list = PyList_New(providers);
754 caidSet::iterator caid_it(slot->possible_caids.begin());
758 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
761 serviceSet::iterator ref_it(slot->possible_services.begin());
765 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
768 providerSet::iterator provider_it(slot->possible_providers.begin());
771 ePyObject tuple = PyTuple_New(2);
772 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
773 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
775 PyList_SET_ITEM(provider_list, providers, tuple);
778 PyTuple_SET_ITEM(tuple, 0, service_list);
779 PyTuple_SET_ITEM(tuple, 1, provider_list);
780 PyTuple_SET_ITEM(tuple, 2, caid_list);
784 const char *PyObject_TypeStr(PyObject *o)
786 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
789 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
791 eDVBCISlot *slot = getSlot(slotid);
795 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
796 PyErr_SetString(PyExc_StandardError, tmp);
799 if (!PyTuple_Check(obj))
802 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
803 PyErr_SetString(PyExc_StandardError, tmp);
806 if (PyTuple_Size(obj) != 3)
808 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
809 "first argument should be a pythonlist with possible services\n"
810 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
811 "third argument should be a pythonlist with possible caids";
812 PyErr_SetString(PyExc_StandardError, errstr);
815 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
816 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
817 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
818 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
821 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
822 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
823 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
824 "third argument(%s) should be a pythonlist with possible caids (ints)",
825 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
826 PyErr_SetString(PyExc_StandardError, errstr);
829 slot->possible_caids.clear();
830 slot->possible_services.clear();
831 slot->possible_providers.clear();
832 int size = PyList_Size(service_list);
836 ePyObject refstr = PyList_GET_ITEM(service_list, size);
837 if (!PyString_Check(refstr))
840 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
841 PyErr_SetString(PyExc_StandardError, buf);
844 char *tmpstr = PyString_AS_STRING(refstr);
845 eServiceReference ref(tmpstr);
847 slot->possible_services.insert(ref);
849 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
851 size = PyList_Size(provider_list);
855 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
856 if (!PyTuple_Check(tuple))
859 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
860 PyErr_SetString(PyExc_StandardError, buf);
863 if (PyTuple_Size(tuple) != 2)
866 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
867 PyErr_SetString(PyExc_StandardError, buf);
870 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
873 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
874 PyErr_SetString(PyExc_StandardError, buf);
877 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
880 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
881 PyErr_SetString(PyExc_StandardError, buf);
884 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
885 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
887 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
889 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
891 size = PyList_Size(caid_list);
895 ePyObject caid = PyList_GET_ITEM(caid_list, size);
896 if (!PyLong_Check(caid))
899 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
900 PyErr_SetString(PyExc_StandardError, buf);
903 int tmpcaid = PyLong_AsLong(caid);
904 if (tmpcaid > 0 && tmpcaid < 0x10000)
905 slot->possible_caids.insert(tmpcaid);
907 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
912 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
914 eDVBCISlot *slot = getSlot(slotid);
918 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
919 PyErr_SetString(PyExc_StandardError, tmp);
924 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
925 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
926 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
929 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
930 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
937 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
939 eDVBCISlot *slot = getSlot(slotid);
941 return slot->setClockRate(rate);
945 int eDVBCISlot::send(const unsigned char *data, size_t len)
949 //eDebugNoNewLine("< ");
951 // eDebugNoNewLine("%02x ",data[i]);
954 if (sendqueue.empty())
955 res = ::write(fd, data, len);
957 if (res < 0 || (unsigned int)res != len)
959 unsigned char *d = new unsigned char[len];
960 memcpy(d, data, len);
961 sendqueue.push( queueData(d, len) );
962 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
968 void eDVBCISlot::data(int what)
970 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
971 if(what == eSocketNotifier::Priority) {
972 if(state != stateRemoved) {
973 state = stateRemoved;
974 while(sendqueue.size())
976 delete [] sendqueue.top().data;
979 eDVBCISession::deleteSessions(this);
980 eDVBCIInterfaces::getInstance()->ciRemoved(this);
981 notifier->setRequested(eSocketNotifier::Read);
982 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
987 if (state == stateInvalid)
990 if(state != stateInserted) {
991 eDebug("ci inserted in slot %d", getSlotID());
992 state = stateInserted;
993 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
994 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
995 /* enable PRI to detect removal or errors */
998 if (what & eSocketNotifier::Read) {
1001 r = ::read(fd, data, 4096);
1004 // eDebugNoNewLine("> ");
1006 // eDebugNoNewLine("%02x ",data[i]);
1008 eDVBCISession::receiveData(this, data, r);
1009 eDVBCISession::pollAll();
1013 else if (what & eSocketNotifier::Write) {
1014 if (!sendqueue.empty()) {
1015 const queueData &qe = sendqueue.top();
1016 int res = ::write(fd, qe.data, qe.len);
1017 if (res >= 0 && (unsigned int)res == qe.len)
1024 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1028 DEFINE_REF(eDVBCISlot);
1030 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1034 application_manager = 0;
1039 user_mapped = false;
1044 sprintf(filename, "/dev/ci%d", nr);
1046 // possible_caids.insert(0x1702);
1047 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1048 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1050 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1052 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1053 state = stateInvalid;
1057 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1058 CONNECT(notifier->activated, eDVBCISlot::data);
1065 eDVBCISlot::~eDVBCISlot()
1067 eDVBCISession::deleteSessions(this);
1070 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1072 application_manager=session;
1075 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1077 mmi_session = session;
1080 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1082 ca_manager = session;
1085 int eDVBCISlot::getSlotID()
1090 int eDVBCISlot::reset()
1092 eDebug("CI Slot %d: reset requested", getSlotID());
1094 if (state == stateInvalid)
1096 unsigned char buf[256];
1098 while(::read(fd, buf, 256)>0);
1099 state = stateResetted;
1102 while(sendqueue.size())
1104 delete [] sendqueue.top().data;
1113 int eDVBCISlot::startMMI()
1115 eDebug("CI Slot %d: startMMI()", getSlotID());
1117 if(application_manager)
1118 application_manager->startMMI();
1123 int eDVBCISlot::stopMMI()
1125 eDebug("CI Slot %d: stopMMI()", getSlotID());
1128 mmi_session->stopMMI();
1133 int eDVBCISlot::answerText(int answer)
1135 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1138 mmi_session->answerText(answer);
1143 int eDVBCISlot::getMMIState()
1151 int eDVBCISlot::answerEnq(char *value)
1153 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1156 mmi_session->answerEnq(value);
1161 int eDVBCISlot::cancelEnq()
1163 eDebug("CI Slot %d: cancelENQ", getSlotID());
1166 mmi_session->cancelEnq();
1171 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1175 eDebug("no ca_manager (no CI plugged?)");
1178 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1179 ePtr<eTable<ProgramMapSection> > ptr;
1180 if (pmthandler->getPMT(ptr))
1184 eDVBTableSpec table_spec;
1185 ptr->getSpec(table_spec);
1186 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1188 eServiceReferenceDVB ref;
1189 pmthandler->getServiceReference(ref);
1190 uint16_t program_number = ref.getServiceID().get();
1191 std::map<uint16_t, uint8_t>::iterator it =
1192 running_services.find(program_number);
1194 if ( it != running_services.end() &&
1195 (pmt_version == it->second) &&
1196 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1198 eDebug("[eDVBCISlot] dont send self capmt version twice");
1202 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1203 if ( i == ptr->getSections().end() )
1207 unsigned char raw_data[2048];
1209 // eDebug("send %s capmt for service %04x to slot %d",
1210 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1211 // program_number, slotid);
1213 CaProgramMapSection capmt(*i++,
1214 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1215 while( i != ptr->getSections().end() )
1217 // eDebug("append");
1220 capmt.writeToBuffer(raw_data);
1222 // begin calc capmt length
1225 if ( raw_data[3] & 0x80 )
1228 int lenbytes = raw_data[3] & ~0x80;
1230 wp = (wp << 8) | raw_data[4 + i++];
1233 hlen = 4 + lenbytes;
1241 // end calc capmt length
1242 // eDebug("ca_manager %p dump capmt:", ca_manager);
1243 // for(int i=0;i<wp;i++)
1244 // eDebugNoNewLine("%02x ", raw_data[i]);
1247 if (caids.size() == 1 && caids[0] == 0xFFFF)
1249 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1250 raw_data[hlen+3] &= ~0x3E;
1251 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1252 // eDebug(" new version is %02x", raw_data[hlen+3]);
1255 //dont need tag and lenfield
1256 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1257 running_services[program_number] = pmt_version;
1263 void eDVBCISlot::removeService(uint16_t program_number)
1265 if (program_number == 0xFFFF)
1266 running_services.clear(); // remove all
1268 running_services.erase(program_number); // remove single service
1271 int eDVBCISlot::setSource(data_source source)
1273 current_source = source;
1274 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1277 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1278 FILE *ci = fopen(buf, "wb");
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 eDebug("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 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");