4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6 #include <lib/base/ebase.h>
8 #include <lib/base/eerror.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/pmt.h>
12 #include <lib/dvb_ci/dvbci.h>
13 #include <lib/dvb_ci/dvbci_session.h>
14 #include <lib/dvb_ci/dvbci_camgr.h>
15 #include <lib/dvb_ci/dvbci_ui.h>
16 #include <lib/dvb_ci/dvbci_appmgr.h>
17 #include <lib/dvb_ci/dvbci_mmi.h>
19 #include <dvbsi++/ca_program_map_section.h>
24 #define eDebugCI(x...) eDebug(x)
26 #define eDebugCI(x...)
29 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
31 eDVBCIInterfaces::eDVBCIInterfaces()
37 eDebug("scanning for common interfaces..");
43 sprintf(filename, "/dev/ci%d", num_ci);
45 if (stat(filename, &s))
48 ePtr<eDVBCISlot> cislot;
50 cislot = new eDVBCISlot(eApp, num_ci);
51 m_slots.push_back(cislot);
56 for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
57 it->setSource(TUNER_A);
59 if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
61 setInputSource(0, TUNER_A);
62 setInputSource(1, TUNER_B);
63 setInputSource(2, TUNER_C);
64 setInputSource(3, TUNER_D);
68 setInputSource(0, TUNER_A);
69 setInputSource(1, TUNER_B);
72 eDebug("done, found %d common interface slots", num_ci);
75 eDVBCIInterfaces::~eDVBCIInterfaces()
79 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
84 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
86 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
87 if(i->getSlotID() == slotid)
90 eDebug("FIXME: request for unknown slot");
95 int eDVBCIInterfaces::getSlotState(int slotid)
99 if( (slot = getSlot(slotid)) == 0 )
100 return eDVBCISlot::stateInvalid;
102 return slot->getState();
105 int eDVBCIInterfaces::reset(int slotid)
109 if( (slot = getSlot(slotid)) == 0 )
112 return slot->reset();
115 int eDVBCIInterfaces::initialize(int slotid)
119 if( (slot = getSlot(slotid)) == 0 )
122 slot->removeService();
124 return sendCAPMT(slotid);
127 int eDVBCIInterfaces::sendCAPMT(int slotid)
131 if( (slot = getSlot(slotid)) == 0 )
134 PMTHandlerList::iterator it = m_pmt_handlers.begin();
135 while (it != m_pmt_handlers.end())
137 eDVBCISlot *tmp = it->cislot;
138 while (tmp && tmp != slot)
139 tmp = tmp->linked_next;
142 tmp->sendCAPMT(it->pmthandler); // send capmt
151 int eDVBCIInterfaces::startMMI(int slotid)
155 if( (slot = getSlot(slotid)) == 0 )
158 return slot->startMMI();
161 int eDVBCIInterfaces::stopMMI(int slotid)
165 if( (slot = getSlot(slotid)) == 0 )
168 return slot->stopMMI();
171 int eDVBCIInterfaces::answerText(int slotid, int answer)
175 if( (slot = getSlot(slotid)) == 0 )
178 return slot->answerText(answer);
181 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
185 if( (slot = getSlot(slotid)) == 0 )
188 return slot->answerEnq(value);
191 int eDVBCIInterfaces::cancelEnq(int slotid)
195 if( (slot = getSlot(slotid)) == 0 )
198 return slot->cancelEnq();
201 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
203 eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
204 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
205 it != m_pmt_handlers.end(); ++it)
207 eServiceReferenceDVB ref;
208 it->pmthandler->getServiceReference(ref);
209 eDebugCI("check %s cislot %p %d\n", ref.toString().c_str(), it->cislot, it->cislot?it->cislot->getSlotID() : -1);
210 slot->removeService(ref.getServiceID().get());
211 if (slot->use_count && !--slot->use_count)
213 if (slot->linked_next)
214 slot->linked_next->setSource(slot->current_source);
215 else // last CI in chain
216 setInputSource(slot->current_tuner, slot->current_source);
218 if (it->cislot == slot) // remove the base slot
220 it->cislot = slot->linked_next;
221 eDebugCI("base removed.. so slot is now %p", it->cislot);
225 eDebugCI("not base removed.. %d", it->cislot->getSlotID());
226 eDVBCISlot *tmp = it->cislot;
227 while(tmp->linked_next != slot)
228 tmp = tmp->linked_next;
230 if (slot->linked_next)
231 tmp->linked_next = slot->linked_next;
233 tmp->linked_next = 0;
236 slot->user_mapped=false;
239 recheckPMTHandlers();
242 static bool canDescrambleMultipleServices(int slotid)
245 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
247 ePythonConfigQuery::getConfigValue(configStr, str);
250 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
251 if (appname.find("AlphaCrypt") != std::string::npos)
254 else if (str == "yes")
259 void eDVBCIInterfaces::recheckPMTHandlers()
261 eDebugCI("recheckPMTHAndlers()");
262 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
263 it != m_pmt_handlers.end(); ++it)
266 ePtr<eDVBService> service;
267 eServiceReferenceDVB ref;
268 eDVBCISlot *tmp = it->cislot;
269 eDVBServicePMTHandler *pmthandler = it->pmthandler;
270 eDVBServicePMTHandler::program p;
272 pmthandler->getServiceReference(ref);
273 pmthandler->getService(service);
275 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
277 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
280 if (!tmp->running_services.empty())
282 tmp=tmp->linked_next;
284 if (tmp) // we dont like to change tsmux for running services
286 eDebugCI("already assigned and running CI!\n");
290 if (!pmthandler->getProgramInfo(p))
293 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
294 caids.push_front(*x);
296 service->m_ca = caids;
300 caids = service->m_ca;
303 continue; // unscrambled service
305 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
307 eDebugCI("check Slot %d", ci_it->getSlotID());
309 bool user_mapped=true;
310 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
315 if (!ci_it->possible_services.empty())
318 serviceSet::iterator it = ci_it->possible_services.find(ref);
319 if (it != ci_it->possible_services.end())
321 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
325 if (!useThis && !ci_it->possible_providers.empty())
327 eDVBNamespace ns = ref.getDVBNamespace();
329 if (!service) // subservice?
331 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
332 eDVBDB::getInstance()->getService(parent_ref, service);
336 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
337 if (it != ci_it->possible_providers.end())
339 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
344 if (!useThis && !ci_it->possible_caids.empty())
346 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
348 caidSet::iterator it = ci_it->possible_caids.find(*ca);
349 if (it != ci_it->possible_caids.end())
351 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
357 if (!useThis && !mask)
359 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
360 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
362 std::vector<uint16_t>::const_iterator z =
363 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
364 if ( z != ci_caids.end() && *z == *ca )
366 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
377 // check if this CI is already assigned to this pmthandler
378 eDVBCISlot *tmp = it->cislot;
383 tmp=tmp->linked_next;
385 if (tmp) // ignore already assigned cislots...
387 eDebugCI("already assigned!");
390 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
391 if (ci_it->use_count) // check if this CI can descramble more than one service
395 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
396 while (!found && tmp != m_pmt_handlers.end())
399 eDVBCISlot *tmp_cislot = tmp->cislot;
400 while (!found && tmp_cislot)
403 eServiceReferenceDVB ref2;
404 tmp->pmthandler->getServiceReference(ref2);
405 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
407 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
408 eDVBChannelID s1, s2;
411 eDebugCI("different services!");
412 ref.getChannelID(s1);
413 ref2.getChannelID(s2);
415 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
419 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
423 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
424 tmpci=tmpci->linked_next;
428 tmp_cislot=tmp_cislot->linked_next;
437 if (ci_it->user_mapped) // we dont like to link user mapped CIs
439 eDebugCI("user mapped CI already in use... dont link!");
444 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
446 data_source ci_source=CI_A;
447 switch(ci_it->getSlotID())
449 case 0: ci_source = CI_A; break;
450 case 1: ci_source = CI_B; break;
451 case 2: ci_source = CI_C; break;
452 case 3: ci_source = CI_D; break;
454 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
461 eUsePtr<iDVBChannel> channel;
462 if (!pmthandler->getChannel(channel))
464 ePtr<iDVBFrontend> frontend;
465 if (!channel->getFrontend(frontend))
467 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
468 tunernum = fe->getSlotID();
471 ASSERT(tunernum != -1);
472 data_source tuner_source = TUNER_A;
475 case 0: tuner_source = TUNER_A; break;
476 case 1: tuner_source = TUNER_B; break;
477 case 2: tuner_source = TUNER_C; break;
478 case 3: tuner_source = TUNER_D; break;
480 eDebug("try to get source for tuner %d!!\n", tunernum);
483 ci_it->current_tuner = tunernum;
484 setInputSource(tunernum, ci_source);
485 ci_it->setSource(tuner_source);
489 ci_it->current_tuner = it->cislot->current_tuner;
490 ci_it->linked_next = it->cislot;
491 ci_it->setSource(ci_it->linked_next->current_source);
492 ci_it->linked_next->setSource(ci_source);
495 eDebugCI("assigned!");
499 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
501 eDebugCI("user mapped CI assigned... dont link CIs!");
509 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
511 // check if this pmthandler is already registered
512 PMTHandlerList::iterator it = m_pmt_handlers.begin();
513 while (it != m_pmt_handlers.end())
515 if ( *it++ == pmthandler )
519 eServiceReferenceDVB ref;
520 pmthandler->getServiceReference(ref);
521 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
523 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
524 recheckPMTHandlers();
527 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
529 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
530 if (it != m_pmt_handlers.end())
532 eDVBCISlot *slot = it->cislot;
533 eDVBServicePMTHandler *pmthandler = it->pmthandler;
534 m_pmt_handlers.erase(it);
536 eServiceReferenceDVB service_to_remove;
537 pmthandler->getServiceReference(service_to_remove);
539 bool sameServiceExist=false;
540 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
544 eServiceReferenceDVB ref;
545 i->pmthandler->getServiceReference(ref);
546 if ( ref == service_to_remove )
548 sameServiceExist=true;
556 if (!sameServiceExist)
558 if (slot->getNumOfServices() > 1)
560 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
561 service_to_remove.toString().c_str());
562 std::vector<uint16_t> caids;
563 caids.push_back(0xFFFF);
564 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
566 slot->removeService(service_to_remove.getServiceID().get());
569 eDVBCISlot *next = slot->linked_next;
570 if (!--slot->use_count)
572 if (slot->linked_next)
573 slot->linked_next->setSource(slot->current_source);
575 setInputSource(slot->current_tuner, slot->current_source);
577 if (it->cislot == slot) // remove the base slot
578 it->cislot = slot->linked_next;
581 eDVBCISlot *tmp = it->cislot;
582 while(tmp->linked_next != slot)
583 tmp = tmp->linked_next;
585 if (slot->linked_next)
586 tmp->linked_next = slot->linked_next;
588 tmp->linked_next = 0;
590 slot->linked_next = 0;
591 slot->user_mapped = false;
593 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
596 // check if another service is waiting for the CI
597 recheckPMTHandlers();
601 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
603 eDebug("[eDVBCIInterfaces] gotPMT");
604 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
605 if (it != m_pmt_handlers.end() && it->cislot)
607 eDVBCISlot *tmp = it->cislot;
610 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
611 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
612 tmp->sendCAPMT(pmthandler);
613 tmp = tmp->linked_next;
618 int eDVBCIInterfaces::getMMIState(int slotid)
622 if( (slot = getSlot(slotid)) == 0 )
625 return slot->getMMIState();
628 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
630 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
631 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
632 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
635 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
638 if((input = fopen(buf, "wb")) == NULL) {
639 eDebug("cannot open %s", buf);
644 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
649 fprintf(input, "CI0");
652 fprintf(input, "CI1");
655 fprintf(input, "CI2");
658 fprintf(input, "CI3");
673 eDebug("setInputSource for input %d failed!!!\n", (int)source);
682 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
685 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
688 if((input = fopen(buf, "wb")) == NULL) {
689 eDebug("cannot open %s", buf);
696 fprintf(input, "CI");
705 eDebug("setInputSource for input %d failed!!!\n", (int)source);
711 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
715 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
717 eDVBCISlot *slot = getSlot(slotid);
721 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
722 PyErr_SetString(PyExc_StandardError, tmp);
725 ePyObject tuple = PyTuple_New(3);
726 int caids = slot->possible_caids.size();
727 int services = slot->possible_services.size();
728 int providers = slot->possible_providers.size();
729 ePyObject caid_list = PyList_New(caids);
730 ePyObject service_list = PyList_New(services);
731 ePyObject provider_list = PyList_New(providers);
732 caidSet::iterator caid_it(slot->possible_caids.begin());
736 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
739 serviceSet::iterator ref_it(slot->possible_services.begin());
743 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
746 providerSet::iterator provider_it(slot->possible_providers.begin());
749 ePyObject tuple = PyTuple_New(2);
750 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
751 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
753 PyList_SET_ITEM(provider_list, providers, tuple);
756 PyTuple_SET_ITEM(tuple, 0, service_list);
757 PyTuple_SET_ITEM(tuple, 1, provider_list);
758 PyTuple_SET_ITEM(tuple, 2, caid_list);
762 const char *PyObject_TypeStr(PyObject *o)
764 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
767 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
769 eDVBCISlot *slot = getSlot(slotid);
773 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
774 PyErr_SetString(PyExc_StandardError, tmp);
777 if (!PyTuple_Check(obj))
780 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
781 PyErr_SetString(PyExc_StandardError, tmp);
784 if (PyTuple_Size(obj) != 3)
786 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
787 "first argument should be a pythonlist with possible services\n"
788 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
789 "third argument should be a pythonlist with possible caids";
790 PyErr_SetString(PyExc_StandardError, errstr);
793 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
794 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
795 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
796 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
799 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
800 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
801 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
802 "third argument(%s) should be a pythonlist with possible caids (ints)",
803 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
804 PyErr_SetString(PyExc_StandardError, errstr);
807 slot->possible_caids.clear();
808 slot->possible_services.clear();
809 slot->possible_providers.clear();
810 int size = PyList_Size(service_list);
814 ePyObject refstr = PyList_GET_ITEM(service_list, size);
815 if (!PyString_Check(refstr))
818 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
819 PyErr_SetString(PyExc_StandardError, buf);
822 char *tmpstr = PyString_AS_STRING(refstr);
823 eServiceReference ref(tmpstr);
825 slot->possible_services.insert(ref);
827 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
829 size = PyList_Size(provider_list);
833 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
834 if (!PyTuple_Check(tuple))
837 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
838 PyErr_SetString(PyExc_StandardError, buf);
841 if (PyTuple_Size(tuple) != 2)
844 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
845 PyErr_SetString(PyExc_StandardError, buf);
848 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
851 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
852 PyErr_SetString(PyExc_StandardError, buf);
855 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
858 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
859 PyErr_SetString(PyExc_StandardError, buf);
862 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
863 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
865 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
867 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
869 size = PyList_Size(caid_list);
873 ePyObject caid = PyList_GET_ITEM(caid_list, size);
874 if (!PyInt_Check(caid))
877 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
878 PyErr_SetString(PyExc_StandardError, buf);
881 int tmpcaid = PyInt_AsLong(caid);
882 if (tmpcaid > 0 && tmpcaid < 0x10000)
883 slot->possible_caids.insert(tmpcaid);
885 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
890 int eDVBCISlot::send(const unsigned char *data, size_t len)
894 //eDebugNoNewLine("< ");
896 // eDebugNoNewLine("%02x ",data[i]);
899 if (sendqueue.empty())
900 res = ::write(fd, data, len);
902 if (res < 0 || (unsigned int)res != len)
904 unsigned char *d = new unsigned char[len];
905 memcpy(d, data, len);
906 sendqueue.push( queueData(d, len) );
907 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
913 void eDVBCISlot::data(int what)
915 if(what == eSocketNotifier::Priority) {
916 if(state != stateRemoved) {
917 state = stateRemoved;
918 while(sendqueue.size())
920 delete [] sendqueue.top().data;
923 eDVBCISession::deleteSessions(this);
924 eDVBCIInterfaces::getInstance()->ciRemoved(this);
925 notifier->setRequested(eSocketNotifier::Read);
926 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
931 if (state == stateInvalid)
934 if(state != stateInserted) {
935 eDebug("ci inserted in slot %d", getSlotID());
936 state = stateInserted;
937 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
938 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
939 /* enable PRI to detect removal or errors */
942 if (what & eSocketNotifier::Read) {
945 r = ::read(fd, data, 4096);
948 // eDebugNoNewLine("> ");
950 // eDebugNoNewLine("%02x ",data[i]);
952 eDVBCISession::receiveData(this, data, r);
953 eDVBCISession::pollAll();
957 else if (what & eSocketNotifier::Write) {
958 if (!sendqueue.empty()) {
959 const queueData &qe = sendqueue.top();
960 int res = ::write(fd, qe.data, qe.len);
961 if (res >= 0 && (unsigned int)res == qe.len)
968 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
972 DEFINE_REF(eDVBCISlot);
974 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
978 application_manager = 0;
987 sprintf(filename, "/dev/ci%d", nr);
989 // possible_caids.insert(0x1702);
990 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
991 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
993 fd = ::open(filename, O_RDWR | O_NONBLOCK);
995 eDebug("CI Slot %d has fd %d", getSlotID(), fd);
996 state = stateInvalid;
1000 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1001 CONNECT(notifier->activated, eDVBCISlot::data);
1008 eDVBCISlot::~eDVBCISlot()
1012 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1014 application_manager=session;
1017 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1019 mmi_session = session;
1022 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1024 ca_manager = session;
1027 int eDVBCISlot::getSlotID()
1032 int eDVBCISlot::reset()
1034 eDebug("CI Slot %d: reset requested", getSlotID());
1036 if (state == stateInvalid)
1038 unsigned char buf[256];
1040 while(::read(fd, buf, 256)>0);
1041 state = stateResetted;
1044 while(sendqueue.size())
1046 delete [] sendqueue.top().data;
1055 int eDVBCISlot::startMMI()
1057 eDebug("CI Slot %d: startMMI()", getSlotID());
1059 if(application_manager)
1060 application_manager->startMMI();
1065 int eDVBCISlot::stopMMI()
1067 eDebug("CI Slot %d: stopMMI()", getSlotID());
1070 mmi_session->stopMMI();
1075 int eDVBCISlot::answerText(int answer)
1077 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1080 mmi_session->answerText(answer);
1085 int eDVBCISlot::getMMIState()
1093 int eDVBCISlot::answerEnq(char *value)
1095 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1098 mmi_session->answerEnq(value);
1103 int eDVBCISlot::cancelEnq()
1105 eDebug("CI Slot %d: cancelENQ", getSlotID());
1108 mmi_session->cancelEnq();
1113 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1117 eDebug("no ca_manager (no CI plugged?)");
1120 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1121 ePtr<eTable<ProgramMapSection> > ptr;
1122 if (pmthandler->getPMT(ptr))
1126 eDVBTableSpec table_spec;
1127 ptr->getSpec(table_spec);
1128 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1130 eServiceReferenceDVB ref;
1131 pmthandler->getServiceReference(ref);
1132 uint16_t program_number = ref.getServiceID().get();
1133 std::map<uint16_t, uint8_t>::iterator it =
1134 running_services.find(program_number);
1136 if ( it != running_services.end() &&
1137 (pmt_version == it->second) &&
1138 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1140 eDebug("[eDVBCISlot] dont send self capmt version twice");
1144 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1145 if ( i == ptr->getSections().end() )
1149 unsigned char raw_data[2048];
1151 // eDebug("send %s capmt for service %04x to slot %d",
1152 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1153 // program_number, slotid);
1155 CaProgramMapSection capmt(*i++,
1156 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1157 while( i != ptr->getSections().end() )
1159 // eDebug("append");
1162 capmt.writeToBuffer(raw_data);
1164 // begin calc capmt length
1167 if ( raw_data[3] & 0x80 )
1170 int lenbytes = raw_data[3] & ~0x80;
1172 wp = (wp << 8) | raw_data[4 + i++];
1175 hlen = 4 + lenbytes;
1183 // end calc capmt length
1184 // eDebug("ca_manager %p dump capmt:", ca_manager);
1185 // for(int i=0;i<wp;i++)
1186 // eDebugNoNewLine("%02x ", raw_data[i]);
1189 if (caids.size() == 1 && caids[0] == 0xFFFF)
1191 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1192 raw_data[hlen+3] &= ~0x3E;
1193 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1194 // eDebug(" new version is %02x", raw_data[hlen+3]);
1197 //dont need tag and lenfield
1198 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1199 running_services[program_number] = pmt_version;
1205 void eDVBCISlot::removeService(uint16_t program_number)
1207 if (program_number == 0xFFFF)
1208 running_services.clear(); // remove all
1210 running_services.erase(program_number); // remove single service
1213 int eDVBCISlot::setSource(data_source source)
1215 current_source = source;
1216 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1219 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1220 FILE *ci = fopen(buf, "wb");
1248 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1255 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1256 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1257 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1259 eDebug("cannot open /proc/stb/tsmux/input2");
1262 if (source != TUNER_A && source != TUNER_B)
1263 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1265 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1268 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1272 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");