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>
21 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
23 eDVBCIInterfaces::eDVBCIInterfaces()
29 eDebug("scanning for common interfaces..");
35 sprintf(filename, "/dev/ci%d", num_ci);
37 if (stat(filename, &s))
40 ePtr<eDVBCISlot> cislot;
42 cislot = new eDVBCISlot(eApp, num_ci);
43 m_slots.push_back(cislot);
48 for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
49 it->setSource(TUNER_A);
51 if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
53 setInputSource(0, TUNER_A);
54 setInputSource(1, TUNER_B);
55 setInputSource(2, TUNER_C);
56 setInputSource(3, TUNER_D);
60 setInputSource(0, TUNER_A);
61 setInputSource(1, TUNER_B);
64 eDebug("done, found %d common interface slots", num_ci);
67 eDVBCIInterfaces::~eDVBCIInterfaces()
71 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
76 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
78 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
79 if(i->getSlotID() == slotid)
82 eDebug("FIXME: request for unknown slot");
87 int eDVBCIInterfaces::getSlotState(int slotid)
91 if( (slot = getSlot(slotid)) == 0 )
92 return eDVBCISlot::stateInvalid;
94 return slot->getState();
97 int eDVBCIInterfaces::reset(int slotid)
101 if( (slot = getSlot(slotid)) == 0 )
104 eDVBCISession::deleteSessions(slot);
107 return slot->reset();
110 int eDVBCIInterfaces::initialize(int slotid)
114 if( (slot = getSlot(slotid)) == 0 )
117 slot->removeService();
119 return sendCAPMT(slotid);
122 int eDVBCIInterfaces::sendCAPMT(int slotid)
126 if( (slot = getSlot(slotid)) == 0 )
129 PMTHandlerList::iterator it = m_pmt_handlers.begin();
130 while (it != m_pmt_handlers.end())
132 eDVBCISlot *tmp = it->cislot;
133 while (tmp && tmp != slot)
134 tmp = tmp->linked_next;
137 tmp->sendCAPMT(it->pmthandler); // send capmt
146 int eDVBCIInterfaces::startMMI(int slotid)
150 if( (slot = getSlot(slotid)) == 0 )
153 return slot->startMMI();
156 int eDVBCIInterfaces::stopMMI(int slotid)
160 if( (slot = getSlot(slotid)) == 0 )
163 return slot->stopMMI();
166 int eDVBCIInterfaces::answerText(int slotid, int answer)
170 if( (slot = getSlot(slotid)) == 0 )
173 return slot->answerText(answer);
176 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
180 if( (slot = getSlot(slotid)) == 0 )
183 return slot->answerEnq(value);
186 int eDVBCIInterfaces::cancelEnq(int slotid)
190 if( (slot = getSlot(slotid)) == 0 )
193 return slot->cancelEnq();
196 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
198 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
199 it != m_pmt_handlers.end(); ++it)
201 eServiceReferenceDVB ref;
202 it->pmthandler->getServiceReference(ref);
203 slot->removeService(ref.getServiceID().get());
204 if (slot->use_count && !--slot->use_count)
206 if (slot->linked_next)
207 slot->linked_next->setSource(slot->current_source);
208 else // last CI in chain
209 setInputSource(slot->current_tuner, slot->current_source);
211 if (it->cislot == slot) // remove the base slot
212 it->cislot = slot->linked_next;
215 eDVBCISlot *tmp = it->cislot;
216 while(tmp->linked_next != slot)
217 tmp = tmp->linked_next;
219 if (slot->linked_next)
220 tmp->linked_next = slot->linked_next;
222 tmp->linked_next = 0;
229 static bool canDescrambleMultipleServices(int slotid)
232 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
234 ePythonConfigQuery::getConfigValue(configStr, str);
237 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
238 if (appname.find("AlphaCrypt") != std::string::npos)
241 else if (str == "yes")
246 void eDVBCIInterfaces::recheckPMTHandlers()
248 // eDebug("recheckPMTHAndlers()");
249 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
250 it != m_pmt_handlers.end(); ++it)
253 ePtr<eDVBService> service;
254 eServiceReferenceDVB ref;
255 eDVBServicePMTHandler *pmthandler = it->pmthandler;
256 eDVBServicePMTHandler::program p;
258 pmthandler->getServiceReference(ref);
259 pmthandler->getService(service);
260 if (!pmthandler->getProgramInfo(p))
263 for (std::set<uint16_t>::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
264 caids.push_front(*x);
266 service->m_ca = caids;
270 caids = service->m_ca;
273 continue; // unscrambled service
275 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
278 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
282 if (!ci_it->possible_services.empty())
285 std::set<eServiceReference>::iterator it = ci_it->possible_services.find(ref);
286 if (it != ci_it->possible_services.end())
288 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
292 if (!useThis && !ci_it->possible_providers.empty())
296 if (!service) // subservice?
298 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
299 eDVBDB::getInstance()->getService(parent_ref, service);
304 std::set<std::string>::iterator it = ci_it->possible_providers.find(service->m_provider_name);
305 if (it != ci_it->possible_providers.end())
307 eDebug("'%s' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ci_it->getSlotID());
312 if (!useThis && !ci_it->possible_caids.empty())
314 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
316 std::set<uint16_t>::iterator it = ci_it->possible_caids.find(*ca);
317 if (it != ci_it->possible_caids.end())
319 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
325 if (!useThis && !mask)
327 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
328 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
330 std::vector<uint16_t>::const_iterator z =
331 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
332 if ( z != ci_caids.end() && *z == *ca )
334 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
344 if (ci_it->use_count) // check if this CI can descramble more than one service
347 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
348 while (tmp != m_pmt_handlers.end())
350 if ( tmp->cislot == ci_it && it != tmp )
352 eServiceReferenceDVB ref2;
353 tmp->pmthandler->getServiceReference(ref2);
354 eDVBChannelID s1, s2;
357 ref.getChannelID(s1);
358 ref2.getChannelID(s2);
360 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
371 // check if this CI is already assigned to this pmthandler
372 eDVBCISlot *tmp = it->cislot;
377 tmp=tmp->linked_next;
380 if (tmp) // ignore already assigned cislots...
384 // eDebug("usecount now %d", ci_it->use_count);
386 data_source ci_source=CI_A;
387 switch(ci_it->getSlotID())
389 case 0: ci_source = CI_A; break;
390 case 1: ci_source = CI_B; break;
391 case 2: ci_source = CI_C; break;
392 case 3: ci_source = CI_D; break;
394 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
401 eUsePtr<iDVBChannel> channel;
402 if (!pmthandler->getChannel(channel))
404 ePtr<iDVBFrontend> frontend;
405 if (!channel->getFrontend(frontend))
407 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
408 tunernum = fe->getSlotID();
411 ASSERT(tunernum != -1);
412 data_source tuner_source = TUNER_A;
415 case 0: tuner_source = TUNER_A; break;
416 case 1: tuner_source = TUNER_B; break;
417 case 2: tuner_source = TUNER_C; break;
418 case 3: tuner_source = TUNER_D; break;
420 eDebug("try to get source for tuner %d!!\n", tunernum);
423 ci_it->current_tuner = tunernum;
424 setInputSource(tunernum, ci_source);
425 ci_it->setSource(tuner_source);
429 ci_it->current_tuner = it->cislot->current_tuner;
430 ci_it->linked_next = it->cislot;
431 ci_it->setSource(ci_it->linked_next->current_source);
432 ci_it->linked_next->setSource(ci_source);
442 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
444 // check if this pmthandler is already registered
445 PMTHandlerList::iterator it = m_pmt_handlers.begin();
446 while (it != m_pmt_handlers.end())
448 if ( *it++ == pmthandler )
452 eServiceReferenceDVB ref;
453 pmthandler->getServiceReference(ref);
454 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
456 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
457 recheckPMTHandlers();
460 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
462 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
463 if (it != m_pmt_handlers.end())
465 eDVBCISlot *slot = it->cislot;
466 eDVBServicePMTHandler *pmthandler = it->pmthandler;
467 m_pmt_handlers.erase(it);
469 eServiceReferenceDVB service_to_remove;
470 pmthandler->getServiceReference(service_to_remove);
472 bool sameServiceExist=false;
473 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
477 eServiceReferenceDVB ref;
478 i->pmthandler->getServiceReference(ref);
479 if ( ref == service_to_remove )
481 sameServiceExist=true;
489 if (!sameServiceExist)
491 if (slot->getNumOfServices() > 1)
493 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
494 service_to_remove.toString().c_str());
495 std::vector<uint16_t> caids;
496 caids.push_back(0xFFFF);
497 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
499 slot->removeService(service_to_remove.getServiceID().get());
502 eDVBCISlot *next = slot->linked_next;
503 if (!--slot->use_count)
505 if (slot->linked_next)
506 slot->linked_next->setSource(slot->current_source);
508 setInputSource(slot->current_tuner, slot->current_source);
510 if (it->cislot == slot) // remove the base slot
511 it->cislot = slot->linked_next;
514 eDVBCISlot *tmp = it->cislot;
515 while(tmp->linked_next != slot)
516 tmp = tmp->linked_next;
518 if (slot->linked_next)
519 tmp->linked_next = slot->linked_next;
521 tmp->linked_next = 0;
525 // eDebug("use_count is now %d", slot->use_count);
528 // check if another service is waiting for the CI
529 recheckPMTHandlers();
533 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
535 eDebug("[eDVBCIInterfaces] gotPMT");
536 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
537 if (it != m_pmt_handlers.end() && it->cislot)
539 eDVBCISlot *tmp = it->cislot;
542 tmp->sendCAPMT(pmthandler);
543 tmp = tmp->linked_next;
548 int eDVBCIInterfaces::getMMIState(int slotid)
552 if( (slot = getSlot(slotid)) == 0 )
555 return slot->getMMIState();
558 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
560 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
561 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
562 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
565 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
568 if((input = fopen(buf, "wb")) == NULL) {
569 eDebug("cannot open %s", buf);
574 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
579 fprintf(input, "CI0");
582 fprintf(input, "CI1");
585 fprintf(input, "CI2");
588 fprintf(input, "CI3");
603 eDebug("setInputSource for input %d failed!!!\n", (int)source);
612 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
615 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
618 if((input = fopen(buf, "wb")) == NULL) {
619 eDebug("cannot open %s", buf);
626 fprintf(input, "CI");
635 eDebug("setInputSource for input %d failed!!!\n", (int)source);
641 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
645 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
647 eDVBCISlot *slot = getSlot(slotid);
651 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
652 PyErr_SetString(PyExc_StandardError, tmp);
655 ePyObject tuple = PyTuple_New(3);
656 int caids = slot->possible_caids.size();
657 int services = slot->possible_services.size();
658 int providers = slot->possible_providers.size();
659 ePyObject caid_list = PyList_New(caids);
660 ePyObject service_list = PyList_New(services);
661 ePyObject provider_list = PyList_New(providers);
662 std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
666 PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
669 std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
673 PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
676 std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
680 PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
683 PyTuple_SET_ITEM(tuple, 0, service_list);
684 PyTuple_SET_ITEM(tuple, 1, provider_list);
685 PyTuple_SET_ITEM(tuple, 2, caid_list);
689 const char *PyObject_TypeStr(PyObject *o)
691 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
694 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
696 eDVBCISlot *slot = getSlot(slotid);
700 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
701 PyErr_SetString(PyExc_StandardError, tmp);
704 if (!PyTuple_Check(obj))
707 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
708 PyErr_SetString(PyExc_StandardError, tmp);
711 if (PyTuple_Size(obj) != 3)
713 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
714 "first argument should be a pythonlist with possible services\n"
715 "second argument should be a pythonlist with possible providers\n"
716 "third argument should be a pythonlist with possible caids";
717 PyErr_SetString(PyExc_StandardError, errstr);
720 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
721 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
722 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
723 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
726 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
727 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
728 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
729 "third argument(%s) should be a pythonlist with possible caids (ints)",
730 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
731 PyErr_SetString(PyExc_StandardError, errstr);
734 slot->possible_caids.clear();
735 slot->possible_services.clear();
736 slot->possible_providers.clear();
737 int size = PyList_Size(service_list);
741 ePyObject refstr = PyList_GET_ITEM(service_list, size);
742 if (!PyString_Check(refstr))
745 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
746 PyErr_SetString(PyExc_StandardError, buf);
749 char *tmpstr = PyString_AS_STRING(refstr);
750 eServiceReference ref(tmpstr);
752 slot->possible_services.insert(ref);
754 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
756 size = PyList_Size(provider_list);
760 ePyObject str = PyList_GET_ITEM(provider_list, size);
761 if (!PyString_Check(str))
764 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
765 PyErr_SetString(PyExc_StandardError, buf);
768 char *tmpstr = PyString_AS_STRING(str);
770 slot->possible_providers.insert(tmpstr);
772 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
774 size = PyList_Size(caid_list);
778 ePyObject caid = PyList_GET_ITEM(caid_list, size);
779 if (!PyInt_Check(caid))
782 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
783 PyErr_SetString(PyExc_StandardError, buf);
786 int tmpcaid = PyInt_AsLong(caid);
787 if (tmpcaid > 0 && tmpcaid < 0x10000)
788 slot->possible_caids.insert(tmpcaid);
790 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
795 int eDVBCISlot::send(const unsigned char *data, size_t len)
799 //eDebugNoNewLine("< ");
801 // eDebugNoNewLine("%02x ",data[i]);
804 if (sendqueue.empty())
805 res = ::write(fd, data, len);
807 if (res < 0 || (unsigned int)res != len)
809 unsigned char *d = new unsigned char[len];
810 memcpy(d, data, len);
811 sendqueue.push( queueData(d, len) );
812 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
818 void eDVBCISlot::data(int what)
820 if(what == eSocketNotifier::Priority) {
821 if(state != stateRemoved) {
822 state = stateRemoved;
823 eDebug("ci removed");
824 while(sendqueue.size())
826 delete [] sendqueue.top().data;
829 eDVBCIInterfaces::getInstance()->ciRemoved(this);
830 eDVBCISession::deleteSessions(this);
831 notifier->setRequested(eSocketNotifier::Read);
832 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
837 if (state == stateInvalid)
840 if(state != stateInserted) {
841 eDebug("ci inserted");
842 state = stateInserted;
843 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
844 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
845 /* enable PRI to detect removal or errors */
848 if (what & eSocketNotifier::Read) {
851 r = ::read(fd, data, 4096);
854 // eDebugNoNewLine("> ");
856 // eDebugNoNewLine("%02x ",data[i]);
858 eDVBCISession::receiveData(this, data, r);
859 eDVBCISession::pollAll();
863 else if (what & eSocketNotifier::Write) {
864 if (!sendqueue.empty()) {
865 const queueData &qe = sendqueue.top();
866 int res = ::write(fd, qe.data, qe.len);
867 if (res >= 0 && (unsigned int)res == qe.len)
874 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
878 DEFINE_REF(eDVBCISlot);
880 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
884 application_manager = 0;
892 sprintf(filename, "/dev/ci%d", nr);
894 fd = ::open(filename, O_RDWR | O_NONBLOCK);
896 eDebug("eDVBCISlot has fd %d", fd);
897 state = stateInvalid;
901 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
902 CONNECT(notifier->activated, eDVBCISlot::data);
909 eDVBCISlot::~eDVBCISlot()
913 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
915 application_manager=session;
918 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
920 mmi_session = session;
923 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
925 ca_manager = session;
928 int eDVBCISlot::getSlotID()
933 int eDVBCISlot::reset()
935 eDebug("edvbcislot: reset requested");
937 if (state == stateInvalid)
939 unsigned char buf[256];
941 while(::read(fd, buf, 256)>0);
942 state = stateResetted;
945 while(sendqueue.size())
947 delete [] sendqueue.top().data;
956 int eDVBCISlot::startMMI()
958 eDebug("edvbcislot: startMMI()");
960 if(application_manager)
961 application_manager->startMMI();
966 int eDVBCISlot::stopMMI()
968 eDebug("edvbcislot: stopMMI()");
971 mmi_session->stopMMI();
976 int eDVBCISlot::answerText(int answer)
978 eDebug("edvbcislot: answerText(%d)", answer);
981 mmi_session->answerText(answer);
986 int eDVBCISlot::getMMIState()
994 int eDVBCISlot::answerEnq(char *value)
996 eDebug("edvbcislot: answerENQ(%s)", value);
999 mmi_session->answerEnq(value);
1004 int eDVBCISlot::cancelEnq()
1006 eDebug("edvbcislot: cancelENQ");
1009 mmi_session->cancelEnq();
1014 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1018 eDebug("no ca_manager (no CI plugged?)");
1021 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1022 ePtr<eTable<ProgramMapSection> > ptr;
1023 if (pmthandler->getPMT(ptr))
1027 eDVBTableSpec table_spec;
1028 ptr->getSpec(table_spec);
1029 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1031 eServiceReferenceDVB ref;
1032 pmthandler->getServiceReference(ref);
1033 uint16_t program_number = ref.getServiceID().get();
1034 std::map<uint16_t, uint8_t>::iterator it =
1035 running_services.find(program_number);
1037 if ( it != running_services.end() &&
1038 (pmt_version == it->second) &&
1039 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1041 eDebug("[eDVBCISlot] dont send self capmt version twice");
1045 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1046 if ( i == ptr->getSections().end() )
1050 unsigned char raw_data[2048];
1052 // eDebug("send %s capmt for service %04x to slot %d",
1053 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1054 // program_number, slotid);
1056 CaProgramMapSection capmt(*i++,
1057 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1058 while( i != ptr->getSections().end() )
1060 // eDebug("append");
1063 capmt.writeToBuffer(raw_data);
1065 // begin calc capmt length
1068 if ( raw_data[3] & 0x80 )
1071 int lenbytes = raw_data[3] & ~0x80;
1073 wp = (wp << 8) | raw_data[4 + i++];
1076 hlen = 4 + lenbytes;
1084 // end calc capmt length
1085 // eDebug("ca_manager %p dump capmt:", ca_manager);
1086 // for(int i=0;i<wp;i++)
1087 // eDebugNoNewLine("%02x ", raw_data[i]);
1090 if (caids.size() == 1 && caids[0] == 0xFFFF)
1092 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1093 raw_data[hlen+3] &= ~0x3E;
1094 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1095 // eDebug(" new version is %02x", raw_data[hlen+3]);
1098 //dont need tag and lenfield
1099 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1100 running_services[program_number] = pmt_version;
1106 void eDVBCISlot::removeService(uint16_t program_number)
1108 if (program_number == 0xFFFF)
1109 running_services.clear(); // remove all
1111 running_services.erase(program_number); // remove single service
1114 int eDVBCISlot::setSource(data_source source)
1116 current_source = source;
1117 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1120 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1121 FILE *ci = fopen(buf, "wb");
1149 eDebug("setSource %d failed!!!\n", (int)source);
1156 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1157 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1158 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1160 eDebug("cannot open /proc/stb/tsmux/input2");
1163 if (source != TUNER_A && source != TUNER_B)
1164 eDebug("setSource %d failed!!!\n", (int)source);
1166 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1169 eDebug("eDVBCISlot->setSource(%d)", (int)source);
1173 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");