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 if (it->cislot == slot) // remove the base slot
208 it->cislot = slot->linked_next;
211 eDVBCISlot *prevSlot = it->cislot, *hSlot = it->cislot->linked_next;
215 prevSlot->linked_next = slot->linked_next;
219 hSlot = hSlot->linked_next;
223 if (slot->linked_next)
224 slot->linked_next->setSource(slot->current_source);
225 else // last CI in chain
226 setInputSource(slot->current_tuner, slot->current_source);
227 slot->linked_next = 0;
230 slot->user_mapped=false;
231 slot->removeService(0xFFFF);
232 recheckPMTHandlers();
235 static bool canDescrambleMultipleServices(int slotid)
238 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
240 ePythonConfigQuery::getConfigValue(configStr, str);
243 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
244 if (appname.find("AlphaCrypt") != std::string::npos)
247 else if (str == "yes")
252 void eDVBCIInterfaces::recheckPMTHandlers()
254 eDebugCI("recheckPMTHAndlers()");
255 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
256 it != m_pmt_handlers.end(); ++it)
259 ePtr<eDVBService> service;
260 eServiceReferenceDVB ref;
261 eDVBCISlot *tmp = it->cislot;
262 eDVBServicePMTHandler *pmthandler = it->pmthandler;
263 eDVBServicePMTHandler::program p;
264 bool plugged_cis_exist = false;
266 pmthandler->getServiceReference(ref);
267 pmthandler->getService(service);
269 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
270 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
271 if (ci_it->plugged && ci_it->getCAManager())
273 eDebug("Slot %d plugged", ci_it->getSlotID());
274 ci_it->plugged = false;
275 plugged_cis_exist = true;
278 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
279 if (!plugged_cis_exist)
283 if (!tmp->running_services.empty())
285 tmp=tmp->linked_next;
287 if (tmp) // we dont like to change tsmux for running services
289 eDebugCI("already assigned and running CI!\n");
294 if (!pmthandler->getProgramInfo(p))
297 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
298 caids.push_front(*x);
300 service->m_ca = caids;
304 caids = service->m_ca;
307 continue; // unscrambled service
309 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
311 eDebugCI("check Slot %d", ci_it->getSlotID());
313 bool user_mapped=true;
314 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
319 if (!ci_it->possible_services.empty())
322 serviceSet::iterator it = ci_it->possible_services.find(ref);
323 if (it != ci_it->possible_services.end())
325 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
330 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
333 it = ci_it->possible_services.find(ref);
334 if (it != ci_it->possible_services.end())
336 eDebug("parent '%s' of '%s' is in service list of slot %d... so use it",
337 parent_ref.toString().c_str(), ref.toString().c_str(), ci_it->getSlotID());
343 if (!useThis && !ci_it->possible_providers.empty())
345 eDVBNamespace ns = ref.getDVBNamespace();
347 if (!service) // subservice?
349 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
350 eDVBDB::getInstance()->getService(parent_ref, service);
354 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
355 if (it != ci_it->possible_providers.end())
357 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
362 if (!useThis && !ci_it->possible_caids.empty())
365 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
367 caidSet::iterator it = ci_it->possible_caids.find(*ca);
368 if (it != ci_it->possible_caids.end())
370 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
376 if (!useThis && !mask)
378 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
379 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
381 std::vector<uint16_t>::const_iterator z =
382 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
383 if ( z != ci_caids.end() && *z == *ca )
385 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
396 // check if this CI is already assigned to this pmthandler
397 eDVBCISlot *tmp = it->cislot;
402 tmp=tmp->linked_next;
404 if (tmp) // ignore already assigned cislots...
406 eDebugCI("already assigned!");
409 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
410 if (ci_it->use_count) // check if this CI can descramble more than one service
414 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
415 while (!found && tmp != m_pmt_handlers.end())
418 eDVBCISlot *tmp_cislot = tmp->cislot;
419 while (!found && tmp_cislot)
422 eServiceReferenceDVB ref2;
423 tmp->pmthandler->getServiceReference(ref2);
424 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
426 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
427 eDVBChannelID s1, s2;
430 eDebugCI("different services!");
431 ref.getChannelID(s1);
432 ref2.getChannelID(s2);
434 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
438 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
442 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
443 tmpci=tmpci->linked_next;
447 tmp_cislot=tmp_cislot->linked_next;
456 if (ci_it->user_mapped) // we dont like to link user mapped CIs
458 eDebugCI("user mapped CI already in use... dont link!");
463 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
465 data_source ci_source=CI_A;
466 switch(ci_it->getSlotID())
468 case 0: ci_source = CI_A; break;
469 case 1: ci_source = CI_B; break;
470 case 2: ci_source = CI_C; break;
471 case 3: ci_source = CI_D; break;
473 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
480 eUsePtr<iDVBChannel> channel;
481 if (!pmthandler->getChannel(channel))
483 ePtr<iDVBFrontend> frontend;
484 if (!channel->getFrontend(frontend))
486 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
487 tunernum = fe->getSlotID();
490 ASSERT(tunernum != -1);
491 data_source tuner_source = TUNER_A;
494 case 0: tuner_source = TUNER_A; break;
495 case 1: tuner_source = TUNER_B; break;
496 case 2: tuner_source = TUNER_C; break;
497 case 3: tuner_source = TUNER_D; break;
499 eDebug("try to get source for tuner %d!!\n", tunernum);
502 ci_it->current_tuner = tunernum;
503 setInputSource(tunernum, ci_source);
504 ci_it->setSource(tuner_source);
508 ci_it->current_tuner = it->cislot->current_tuner;
509 ci_it->linked_next = it->cislot;
510 ci_it->setSource(ci_it->linked_next->current_source);
511 ci_it->linked_next->setSource(ci_source);
514 eDebugCI("assigned!");
518 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
520 eDebugCI("user mapped CI assigned... dont link CIs!");
528 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
530 // check if this pmthandler is already registered
531 PMTHandlerList::iterator it = m_pmt_handlers.begin();
532 while (it != m_pmt_handlers.end())
534 if ( *it++ == pmthandler )
538 eServiceReferenceDVB ref;
539 pmthandler->getServiceReference(ref);
540 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
542 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
543 recheckPMTHandlers();
546 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
548 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
549 if (it != m_pmt_handlers.end())
551 eDVBCISlot *slot = it->cislot;
552 eDVBServicePMTHandler *pmthandler = it->pmthandler;
553 m_pmt_handlers.erase(it);
555 eServiceReferenceDVB service_to_remove;
556 pmthandler->getServiceReference(service_to_remove);
558 bool sameServiceExist=false;
559 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
563 eServiceReferenceDVB ref;
564 i->pmthandler->getServiceReference(ref);
565 if ( ref == service_to_remove )
567 sameServiceExist=true;
575 if (!sameServiceExist)
577 if (slot->getNumOfServices() > 1)
579 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
580 service_to_remove.toString().c_str());
581 std::vector<uint16_t> caids;
582 caids.push_back(0xFFFF);
583 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
585 slot->removeService(service_to_remove.getServiceID().get());
588 eDVBCISlot *next = slot->linked_next;
589 if (!--slot->use_count)
591 if (slot->linked_next)
592 slot->linked_next->setSource(slot->current_source);
594 setInputSource(slot->current_tuner, slot->current_source);
596 if (it->cislot == slot) // remove the base slot
597 it->cislot = slot->linked_next;
600 eDVBCISlot *tmp = it->cislot;
601 while(tmp->linked_next != slot)
602 tmp = tmp->linked_next;
604 if (slot->linked_next)
605 tmp->linked_next = slot->linked_next;
607 tmp->linked_next = 0;
609 slot->linked_next = 0;
610 slot->user_mapped = false;
612 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
615 // check if another service is waiting for the CI
616 recheckPMTHandlers();
620 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
622 eDebug("[eDVBCIInterfaces] gotPMT");
623 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
624 if (it != m_pmt_handlers.end() && it->cislot)
626 eDVBCISlot *tmp = it->cislot;
629 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
630 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
631 tmp->sendCAPMT(pmthandler);
632 tmp = tmp->linked_next;
637 int eDVBCIInterfaces::getMMIState(int slotid)
641 if( (slot = getSlot(slotid)) == 0 )
644 return slot->getMMIState();
647 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
649 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
650 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
651 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
654 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
657 if((input = fopen(buf, "wb")) == NULL) {
658 eDebug("cannot open %s", buf);
663 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
668 fprintf(input, "CI0");
671 fprintf(input, "CI1");
674 fprintf(input, "CI2");
677 fprintf(input, "CI3");
692 eDebug("setInputSource for input %d failed!!!\n", (int)source);
701 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
704 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
707 if((input = fopen(buf, "wb")) == NULL) {
708 eDebug("cannot open %s", buf);
715 fprintf(input, "CI");
724 eDebug("setInputSource for input %d failed!!!\n", (int)source);
730 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
734 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
736 eDVBCISlot *slot = getSlot(slotid);
740 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
741 PyErr_SetString(PyExc_StandardError, tmp);
744 ePyObject tuple = PyTuple_New(3);
745 int caids = slot->possible_caids.size();
746 int services = slot->possible_services.size();
747 int providers = slot->possible_providers.size();
748 ePyObject caid_list = PyList_New(caids);
749 ePyObject service_list = PyList_New(services);
750 ePyObject provider_list = PyList_New(providers);
751 caidSet::iterator caid_it(slot->possible_caids.begin());
755 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
758 serviceSet::iterator ref_it(slot->possible_services.begin());
762 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
765 providerSet::iterator provider_it(slot->possible_providers.begin());
768 ePyObject tuple = PyTuple_New(2);
769 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
770 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
772 PyList_SET_ITEM(provider_list, providers, tuple);
775 PyTuple_SET_ITEM(tuple, 0, service_list);
776 PyTuple_SET_ITEM(tuple, 1, provider_list);
777 PyTuple_SET_ITEM(tuple, 2, caid_list);
781 const char *PyObject_TypeStr(PyObject *o)
783 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
786 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
788 eDVBCISlot *slot = getSlot(slotid);
792 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
793 PyErr_SetString(PyExc_StandardError, tmp);
796 if (!PyTuple_Check(obj))
799 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
800 PyErr_SetString(PyExc_StandardError, tmp);
803 if (PyTuple_Size(obj) != 3)
805 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
806 "first argument should be a pythonlist with possible services\n"
807 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
808 "third argument should be a pythonlist with possible caids";
809 PyErr_SetString(PyExc_StandardError, errstr);
812 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
813 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
814 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
815 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
818 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
819 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
820 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
821 "third argument(%s) should be a pythonlist with possible caids (ints)",
822 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
823 PyErr_SetString(PyExc_StandardError, errstr);
826 slot->possible_caids.clear();
827 slot->possible_services.clear();
828 slot->possible_providers.clear();
829 int size = PyList_Size(service_list);
833 ePyObject refstr = PyList_GET_ITEM(service_list, size);
834 if (!PyString_Check(refstr))
837 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
838 PyErr_SetString(PyExc_StandardError, buf);
841 char *tmpstr = PyString_AS_STRING(refstr);
842 eServiceReference ref(tmpstr);
844 slot->possible_services.insert(ref);
846 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
848 size = PyList_Size(provider_list);
852 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
853 if (!PyTuple_Check(tuple))
856 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
857 PyErr_SetString(PyExc_StandardError, buf);
860 if (PyTuple_Size(tuple) != 2)
863 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
864 PyErr_SetString(PyExc_StandardError, buf);
867 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
870 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
871 PyErr_SetString(PyExc_StandardError, buf);
874 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
877 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
878 PyErr_SetString(PyExc_StandardError, buf);
881 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
882 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
884 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
886 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
888 size = PyList_Size(caid_list);
892 ePyObject caid = PyList_GET_ITEM(caid_list, size);
893 if (!PyLong_Check(caid))
896 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
897 PyErr_SetString(PyExc_StandardError, buf);
900 int tmpcaid = PyLong_AsLong(caid);
901 if (tmpcaid > 0 && tmpcaid < 0x10000)
902 slot->possible_caids.insert(tmpcaid);
904 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
909 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
911 eDVBCISlot *slot = getSlot(slotid);
915 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
916 PyErr_SetString(PyExc_StandardError, tmp);
921 eDVBCICAManagerSession *ca_manager = slot->getCAManager();
922 const std::vector<uint16_t> *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0;
923 ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0);
926 for (std::vector<uint16_t>::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it)
927 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
934 int eDVBCIInterfaces::setCIClockRate(int slotid, int rate)
936 eDVBCISlot *slot = getSlot(slotid);
938 return slot->setClockRate(rate);
942 int eDVBCISlot::send(const unsigned char *data, size_t len)
946 //eDebugNoNewLine("< ");
948 // eDebugNoNewLine("%02x ",data[i]);
951 if (sendqueue.empty())
952 res = ::write(fd, data, len);
954 if (res < 0 || (unsigned int)res != len)
956 unsigned char *d = new unsigned char[len];
957 memcpy(d, data, len);
958 sendqueue.push( queueData(d, len) );
959 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
965 void eDVBCISlot::data(int what)
967 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
968 if(what == eSocketNotifier::Priority) {
969 if(state != stateRemoved) {
970 state = stateRemoved;
971 while(sendqueue.size())
973 delete [] sendqueue.top().data;
976 eDVBCISession::deleteSessions(this);
977 eDVBCIInterfaces::getInstance()->ciRemoved(this);
978 notifier->setRequested(eSocketNotifier::Read);
979 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
984 if (state == stateInvalid)
987 if(state != stateInserted) {
988 eDebug("ci inserted in slot %d", getSlotID());
989 state = stateInserted;
990 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
991 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
992 /* enable PRI to detect removal or errors */
995 if (what & eSocketNotifier::Read) {
998 r = ::read(fd, data, 4096);
1001 // eDebugNoNewLine("> ");
1003 // eDebugNoNewLine("%02x ",data[i]);
1005 eDVBCISession::receiveData(this, data, r);
1006 eDVBCISession::pollAll();
1010 else if (what & eSocketNotifier::Write) {
1011 if (!sendqueue.empty()) {
1012 const queueData &qe = sendqueue.top();
1013 int res = ::write(fd, qe.data, qe.len);
1014 if (res >= 0 && (unsigned int)res == qe.len)
1021 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1025 DEFINE_REF(eDVBCISlot);
1027 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1031 application_manager = 0;
1036 user_mapped = false;
1041 sprintf(filename, "/dev/ci%d", nr);
1043 // possible_caids.insert(0x1702);
1044 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1045 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1047 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1049 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1050 state = stateInvalid;
1054 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1055 CONNECT(notifier->activated, eDVBCISlot::data);
1062 eDVBCISlot::~eDVBCISlot()
1064 eDVBCISession::deleteSessions(this);
1067 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1069 application_manager=session;
1072 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1074 mmi_session = session;
1077 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1079 ca_manager = session;
1082 int eDVBCISlot::getSlotID()
1087 int eDVBCISlot::reset()
1089 eDebug("CI Slot %d: reset requested", getSlotID());
1091 if (state == stateInvalid)
1093 unsigned char buf[256];
1095 while(::read(fd, buf, 256)>0);
1096 state = stateResetted;
1099 while(sendqueue.size())
1101 delete [] sendqueue.top().data;
1110 int eDVBCISlot::startMMI()
1112 eDebug("CI Slot %d: startMMI()", getSlotID());
1114 if(application_manager)
1115 application_manager->startMMI();
1120 int eDVBCISlot::stopMMI()
1122 eDebug("CI Slot %d: stopMMI()", getSlotID());
1125 mmi_session->stopMMI();
1130 int eDVBCISlot::answerText(int answer)
1132 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1135 mmi_session->answerText(answer);
1140 int eDVBCISlot::getMMIState()
1148 int eDVBCISlot::answerEnq(char *value)
1150 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1153 mmi_session->answerEnq(value);
1158 int eDVBCISlot::cancelEnq()
1160 eDebug("CI Slot %d: cancelENQ", getSlotID());
1163 mmi_session->cancelEnq();
1168 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1172 eDebug("no ca_manager (no CI plugged?)");
1175 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1176 ePtr<eTable<ProgramMapSection> > ptr;
1177 if (pmthandler->getPMT(ptr))
1181 eDVBTableSpec table_spec;
1182 ptr->getSpec(table_spec);
1183 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1185 eServiceReferenceDVB ref;
1186 pmthandler->getServiceReference(ref);
1187 uint16_t program_number = ref.getServiceID().get();
1188 std::map<uint16_t, uint8_t>::iterator it =
1189 running_services.find(program_number);
1191 if ( it != running_services.end() &&
1192 (pmt_version == it->second) &&
1193 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1195 eDebug("[eDVBCISlot] dont send self capmt version twice");
1199 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1200 if ( i == ptr->getSections().end() )
1204 unsigned char raw_data[2048];
1206 // eDebug("send %s capmt for service %04x to slot %d",
1207 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1208 // program_number, slotid);
1210 CaProgramMapSection capmt(*i++,
1211 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1212 while( i != ptr->getSections().end() )
1214 // eDebug("append");
1217 capmt.writeToBuffer(raw_data);
1219 // begin calc capmt length
1222 if ( raw_data[3] & 0x80 )
1225 int lenbytes = raw_data[3] & ~0x80;
1227 wp = (wp << 8) | raw_data[4 + i++];
1230 hlen = 4 + lenbytes;
1238 // end calc capmt length
1239 // eDebug("ca_manager %p dump capmt:", ca_manager);
1240 // for(int i=0;i<wp;i++)
1241 // eDebugNoNewLine("%02x ", raw_data[i]);
1244 if (caids.size() == 1 && caids[0] == 0xFFFF)
1246 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1247 raw_data[hlen+3] &= ~0x3E;
1248 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1249 // eDebug(" new version is %02x", raw_data[hlen+3]);
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");
1303 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1310 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1311 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1312 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1314 eDebug("cannot open /proc/stb/tsmux/input2");
1317 if (source != TUNER_A && source != TUNER_B)
1318 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1320 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1323 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1327 int eDVBCISlot::setClockRate(int rate)
1330 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid);
1331 FILE *ci = fopen(buf, "wb");
1335 fprintf(ci, "high");
1337 fprintf(ci, "normal");
1344 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");