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);
49 setInputSource(0, TUNER_A);
50 setInputSource(1, TUNER_B);
51 setInputSource(2, TUNER_C);
52 setInputSource(3, TUNER_D);
54 setInputSource(0, TUNER_A);
55 setInputSource(1, TUNER_B);
58 eDebug("done, found %d common interface slots", num_ci);
61 eDVBCIInterfaces::~eDVBCIInterfaces()
65 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
70 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
72 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
73 if(i->getSlotID() == slotid)
76 eDebug("FIXME: request for unknown slot");
81 int eDVBCIInterfaces::getSlotState(int slotid)
85 if( (slot = getSlot(slotid)) == 0 )
86 return eDVBCISlot::stateInvalid;
88 return slot->getState();
91 int eDVBCIInterfaces::reset(int slotid)
95 if( (slot = getSlot(slotid)) == 0 )
98 eDVBCISession::deleteSessions(slot);
101 return slot->reset();
104 int eDVBCIInterfaces::initialize(int slotid)
108 if( (slot = getSlot(slotid)) == 0 )
111 slot->removeService();
113 return sendCAPMT(slotid);
116 int eDVBCIInterfaces::sendCAPMT(int slotid)
120 if( (slot = getSlot(slotid)) == 0 )
123 PMTHandlerList::iterator it = m_pmt_handlers.begin();
124 while (it != m_pmt_handlers.end())
126 eDVBCISlot *tmp = it->cislot;
127 while (tmp && tmp != slot)
128 tmp = tmp->linked_next;
131 tmp->sendCAPMT(it->pmthandler); // send capmt
140 int eDVBCIInterfaces::startMMI(int slotid)
144 if( (slot = getSlot(slotid)) == 0 )
147 return slot->startMMI();
150 int eDVBCIInterfaces::stopMMI(int slotid)
154 if( (slot = getSlot(slotid)) == 0 )
157 return slot->stopMMI();
160 int eDVBCIInterfaces::answerText(int slotid, int answer)
164 if( (slot = getSlot(slotid)) == 0 )
167 return slot->answerText(answer);
170 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
174 if( (slot = getSlot(slotid)) == 0 )
177 return slot->answerEnq(value);
180 int eDVBCIInterfaces::cancelEnq(int slotid)
184 if( (slot = getSlot(slotid)) == 0 )
187 return slot->cancelEnq();
190 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
192 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
193 it != m_pmt_handlers.end(); ++it)
195 eServiceReferenceDVB ref;
196 it->pmthandler->getServiceReference(ref);
197 slot->removeService(ref.getServiceID().get());
198 if (slot->use_count && !--slot->use_count)
200 if (slot->linked_next)
201 slot->linked_next->setSource(slot->current_source);
203 setInputSource(slot->current_tuner, slot->current_source);
205 if (it->cislot == slot) // remove the base slot
206 it->cislot = slot->linked_next;
209 if (slot->linked_next)
211 eDVBCISlot *tmp = it->cislot;
212 while(tmp->linked_next != slot)
213 tmp = tmp->linked_next;
215 tmp->linked_next = slot->linked_next;
223 static bool canDescrambleMultipleServices(int slotid)
226 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
228 ePythonConfigQuery::getConfigValue(configStr, str);
231 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
232 if (appname.find("AlphaCrypt") != std::string::npos)
235 else if (str == "yes")
240 void eDVBCIInterfaces::recheckPMTHandlers()
242 // eDebug("recheckPMTHAndlers()");
243 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
244 it != m_pmt_handlers.end(); ++it)
247 ePtr<eDVBService> service;
248 eServiceReferenceDVB ref;
249 eDVBServicePMTHandler *pmthandler = it->pmthandler;
250 eDVBServicePMTHandler::program p;
252 pmthandler->getServiceReference(ref);
253 pmthandler->getService(service);
254 if (!pmthandler->getProgramInfo(p))
257 for (std::set<uint16_t>::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
258 caids.push_front(*x);
260 service->m_ca = caids;
264 caids = service->m_ca;
267 continue; // unscrambled service
269 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
272 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
276 if (!ci_it->possible_services.empty())
279 std::set<eServiceReference>::iterator it = ci_it->possible_services.find(ref);
280 if (it != ci_it->possible_services.end())
282 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
286 if (!useThis && !ci_it->possible_providers.empty())
290 if (!service) // subservice?
292 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
293 eDVBDB::getInstance()->getService(parent_ref, service);
298 std::set<std::string>::iterator it = ci_it->possible_providers.find(service->m_provider_name);
299 if (it != ci_it->possible_providers.end())
301 eDebug("'%s' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ci_it->getSlotID());
306 if (!useThis && !ci_it->possible_caids.empty())
308 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
310 std::set<uint16_t>::iterator it = ci_it->possible_caids.find(*ca);
311 if (it != ci_it->possible_caids.end())
313 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
319 if (!useThis && !mask)
321 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
322 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
324 std::vector<uint16_t>::const_iterator z =
325 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
326 if ( z != ci_caids.end() && *z == *ca )
328 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
338 if (ci_it->use_count) // check if this CI can descramble more than one service
341 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
342 while (tmp != m_pmt_handlers.end())
344 if ( tmp->cislot == ci_it && it != tmp )
346 eServiceReferenceDVB ref2;
347 tmp->pmthandler->getServiceReference(ref2);
348 eDVBChannelID s1, s2;
351 ref.getChannelID(s1);
352 ref2.getChannelID(s2);
354 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
365 // check if this CI is already assigned to this pmthandler
366 eDVBCISlot *tmp = it->cislot;
371 tmp=tmp->linked_next;
374 if (tmp) // ignore already assigned cislots...
378 // eDebug("usecount now %d", ci_it->use_count);
380 data_source ci_source=CI_A;
381 switch(ci_it->getSlotID())
383 case 0: ci_source = CI_A; break;
384 case 1: ci_source = CI_B; break;
385 case 2: ci_source = CI_C; break;
386 case 3: ci_source = CI_D; break;
388 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
395 eUsePtr<iDVBChannel> channel;
396 if (!pmthandler->getChannel(channel))
398 ePtr<iDVBFrontend> frontend;
399 if (!channel->getFrontend(frontend))
401 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
402 tunernum = fe->getID();
405 ASSERT(tunernum != -1);
406 data_source tuner_source = TUNER_A;
409 case 0: tuner_source = TUNER_A; break;
410 case 1: tuner_source = TUNER_B; break;
411 case 2: tuner_source = TUNER_C; break;
412 case 3: tuner_source = TUNER_D; break;
414 eDebug("try to get source for tuner %d!!\n", tunernum);
417 ci_it->current_tuner = tunernum;
418 setInputSource(tunernum, ci_source);
419 ci_it->setSource(tuner_source);
423 ci_it->current_tuner = it->cislot->current_tuner;
424 ci_it->linked_next = it->cislot;
425 ci_it->setSource(ci_it->linked_next->current_source);
426 ci_it->linked_next->setSource(ci_source);
436 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
438 // check if this pmthandler is already registered
439 PMTHandlerList::iterator it = m_pmt_handlers.begin();
440 while (it != m_pmt_handlers.end())
442 if ( *it++ == pmthandler )
446 eServiceReferenceDVB ref;
447 pmthandler->getServiceReference(ref);
448 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
450 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
451 recheckPMTHandlers();
454 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
456 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
457 if (it != m_pmt_handlers.end())
459 eDVBCISlot *slot = it->cislot;
460 eDVBServicePMTHandler *pmthandler = it->pmthandler;
461 m_pmt_handlers.erase(it);
463 eServiceReferenceDVB service_to_remove;
464 pmthandler->getServiceReference(service_to_remove);
466 bool sameServiceExist=false;
467 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
471 eServiceReferenceDVB ref;
472 i->pmthandler->getServiceReference(ref);
473 if ( ref == service_to_remove )
475 sameServiceExist=true;
483 if (!sameServiceExist)
485 if (slot->getNumOfServices() > 1)
487 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
488 service_to_remove.toString().c_str());
489 std::vector<uint16_t> caids;
490 caids.push_back(0xFFFF);
491 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
493 slot->removeService(service_to_remove.getServiceID().get());
496 eDVBCISlot *next = slot->linked_next;
497 if (!--slot->use_count)
499 if (slot->linked_next)
500 slot->linked_next->setSource(slot->current_source);
502 setInputSource(slot->current_tuner, slot->current_source);
504 if (it->cislot == slot) // remove the base slot
505 it->cislot = slot->linked_next;
508 if (slot->linked_next)
510 eDVBCISlot *tmp = it->cislot;
511 while(tmp->linked_next != slot)
512 tmp = tmp->linked_next;
514 tmp->linked_next = slot->linked_next;
519 // eDebug("use_count is now %d", slot->use_count);
523 // check if another service is waiting for the CI
524 recheckPMTHandlers();
527 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
529 eDebug("[eDVBCIInterfaces] gotPMT");
530 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
531 if (it != m_pmt_handlers.end() && it->cislot)
533 eDVBCISlot *tmp = it->cislot;
536 tmp->sendCAPMT(pmthandler);
537 tmp = tmp->linked_next;
542 int eDVBCIInterfaces::getMMIState(int slotid)
546 if( (slot = getSlot(slotid)) == 0 )
549 return slot->getMMIState();
552 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
554 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
555 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
558 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
561 if((input = fopen(buf, "wb")) == NULL) {
562 eDebug("cannot open %s", buf);
567 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
572 fprintf(input, "CI0");
575 fprintf(input, "CI1");
578 fprintf(input, "CI2");
581 fprintf(input, "CI3");
596 eDebug("setInputSource for input %d failed!!!\n", (int)source);
601 #else // force DM7025
603 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
606 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
609 if((input = fopen(buf, "wb")) == NULL) {
610 eDebug("cannot open %s", buf);
617 fprintf(input, "CI");
626 eDebug("setInputSource for input %d failed!!!\n", (int)source);
632 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
636 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
638 eDVBCISlot *slot = getSlot(slotid);
642 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
643 PyErr_SetString(PyExc_StandardError, tmp);
646 ePyObject tuple = PyTuple_New(3);
647 int caids = slot->possible_caids.size();
648 int services = slot->possible_services.size();
649 int providers = slot->possible_providers.size();
650 ePyObject caid_list = PyList_New(caids);
651 ePyObject service_list = PyList_New(services);
652 ePyObject provider_list = PyList_New(providers);
653 std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
657 PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
660 std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
664 PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
667 std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
671 PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
674 PyTuple_SET_ITEM(tuple, 0, service_list);
675 PyTuple_SET_ITEM(tuple, 1, provider_list);
676 PyTuple_SET_ITEM(tuple, 2, caid_list);
680 const char *PyObject_TypeStr(PyObject *o)
682 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
685 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
687 eDVBCISlot *slot = getSlot(slotid);
691 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
692 PyErr_SetString(PyExc_StandardError, tmp);
695 if (!PyTuple_Check(obj))
698 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
699 PyErr_SetString(PyExc_StandardError, tmp);
702 if (PyTuple_Size(obj) != 3)
704 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
705 "first argument should be a pythonlist with possible services\n"
706 "second argument should be a pythonlist with possible providers\n"
707 "third argument should be a pythonlist with possible caids";
708 PyErr_SetString(PyExc_StandardError, errstr);
711 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
712 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
713 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
714 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
717 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
718 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
719 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
720 "third argument(%s) should be a pythonlist with possible caids (ints)",
721 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
722 PyErr_SetString(PyExc_StandardError, errstr);
725 slot->possible_caids.clear();
726 slot->possible_services.clear();
727 slot->possible_providers.clear();
728 int size = PyList_Size(service_list);
732 ePyObject refstr = PyList_GET_ITEM(service_list, size);
733 if (!PyString_Check(refstr))
736 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
737 PyErr_SetString(PyExc_StandardError, buf);
740 char *tmpstr = PyString_AS_STRING(refstr);
741 eServiceReference ref(tmpstr);
743 slot->possible_services.insert(ref);
745 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
747 size = PyList_Size(provider_list);
751 ePyObject str = PyList_GET_ITEM(provider_list, size);
752 if (!PyString_Check(str))
755 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
756 PyErr_SetString(PyExc_StandardError, buf);
759 char *tmpstr = PyString_AS_STRING(str);
761 slot->possible_providers.insert(tmpstr);
763 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
765 size = PyList_Size(caid_list);
769 ePyObject caid = PyList_GET_ITEM(caid_list, size);
770 if (!PyInt_Check(caid))
773 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
774 PyErr_SetString(PyExc_StandardError, buf);
777 int tmpcaid = PyInt_AsLong(caid);
778 if (tmpcaid > 0 && tmpcaid < 0x10000)
779 slot->possible_caids.insert(tmpcaid);
781 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
786 int eDVBCISlot::send(const unsigned char *data, size_t len)
790 //eDebugNoNewLine("< ");
792 // eDebugNoNewLine("%02x ",data[i]);
795 if (sendqueue.empty())
796 res = ::write(fd, data, len);
798 if (res < 0 || (unsigned int)res != len)
800 unsigned char *d = new unsigned char[len];
801 memcpy(d, data, len);
802 sendqueue.push( queueData(d, len) );
803 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
809 void eDVBCISlot::data(int what)
811 if(what == eSocketNotifier::Priority) {
812 if(state != stateRemoved) {
813 state = stateRemoved;
814 eDebug("ci removed");
815 while(sendqueue.size())
817 delete [] sendqueue.top().data;
820 eDVBCIInterfaces::getInstance()->ciRemoved(this);
821 eDVBCISession::deleteSessions(this);
822 notifier->setRequested(eSocketNotifier::Read);
823 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
828 if (state == stateInvalid)
831 if(state != stateInserted) {
832 eDebug("ci inserted");
833 state = stateInserted;
834 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
835 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
836 /* enable PRI to detect removal or errors */
839 if (what & eSocketNotifier::Read) {
842 r = ::read(fd, data, 4096);
845 // eDebugNoNewLine("> ");
847 // eDebugNoNewLine("%02x ",data[i]);
849 eDVBCISession::receiveData(this, data, r);
850 eDVBCISession::pollAll();
854 else if (what & eSocketNotifier::Write) {
855 if (!sendqueue.empty()) {
856 const queueData &qe = sendqueue.top();
857 int res = ::write(fd, qe.data, qe.len);
858 if (res >= 0 && (unsigned int)res == qe.len)
865 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
869 DEFINE_REF(eDVBCISlot);
871 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
875 application_manager = 0;
883 sprintf(filename, "/dev/ci%d", nr);
885 fd = ::open(filename, O_RDWR | O_NONBLOCK);
887 eDebug("eDVBCISlot has fd %d", fd);
888 state = stateInvalid;
892 notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
893 CONNECT(notifier->activated, eDVBCISlot::data);
901 eDVBCISlot::~eDVBCISlot()
905 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
907 application_manager=session;
910 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
912 mmi_session = session;
915 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
917 ca_manager = session;
920 int eDVBCISlot::getSlotID()
925 int eDVBCISlot::reset()
927 eDebug("edvbcislot: reset requested");
929 if (state == stateInvalid)
931 unsigned char buf[256];
933 while(::read(fd, buf, 256)>0);
934 state = stateResetted;
937 while(sendqueue.size())
939 delete [] sendqueue.top().data;
948 int eDVBCISlot::startMMI()
950 eDebug("edvbcislot: startMMI()");
952 if(application_manager)
953 application_manager->startMMI();
958 int eDVBCISlot::stopMMI()
960 eDebug("edvbcislot: stopMMI()");
963 mmi_session->stopMMI();
968 int eDVBCISlot::answerText(int answer)
970 eDebug("edvbcislot: answerText(%d)", answer);
973 mmi_session->answerText(answer);
978 int eDVBCISlot::getMMIState()
986 int eDVBCISlot::answerEnq(char *value)
988 eDebug("edvbcislot: answerENQ(%s)", value);
991 mmi_session->answerEnq(value);
996 int eDVBCISlot::cancelEnq()
998 eDebug("edvbcislot: cancelENQ");
1001 mmi_session->cancelEnq();
1006 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1010 eDebug("no ca_manager (no CI plugged?)");
1013 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1014 ePtr<eTable<ProgramMapSection> > ptr;
1015 if (pmthandler->getPMT(ptr))
1019 eDVBTableSpec table_spec;
1020 ptr->getSpec(table_spec);
1021 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1023 eServiceReferenceDVB ref;
1024 pmthandler->getServiceReference(ref);
1025 uint16_t program_number = ref.getServiceID().get();
1026 std::map<uint16_t, uint8_t>::iterator it =
1027 running_services.find(program_number);
1029 if ( it != running_services.end() &&
1030 (pmt_version == it->second) &&
1031 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1033 eDebug("[eDVBCISlot] dont send self capmt version twice");
1037 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1038 if ( i == ptr->getSections().end() )
1042 unsigned char raw_data[2048];
1044 // eDebug("send %s capmt for service %04x to slot %d",
1045 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1046 // program_number, slotid);
1048 CaProgramMapSection capmt(*i++,
1049 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1050 while( i != ptr->getSections().end() )
1052 // eDebug("append");
1055 capmt.writeToBuffer(raw_data);
1057 // begin calc capmt length
1060 if ( raw_data[3] & 0x80 )
1063 int lenbytes = raw_data[3] & ~0x80;
1065 wp = (wp << 8) | raw_data[4 + i++];
1068 hlen = 4 + lenbytes;
1076 // end calc capmt length
1077 // eDebug("ca_manager %p dump capmt:", ca_manager);
1078 // for(int i=0;i<wp;i++)
1079 // eDebugNoNewLine("%02x ", raw_data[i]);
1082 if (caids.size() == 1 && caids[0] == 0xFFFF)
1084 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1085 raw_data[hlen+3] &= ~0x3E;
1086 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1087 // eDebug(" new version is %02x", raw_data[hlen+3]);
1090 //dont need tag and lenfield
1091 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1092 running_services[program_number] = pmt_version;
1098 void eDVBCISlot::removeService(uint16_t program_number)
1100 if (program_number == 0xFFFF)
1101 running_services.clear(); // remove all
1103 running_services.erase(program_number); // remove single service
1106 int eDVBCISlot::setSource(data_source source)
1108 current_source = source;
1111 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1112 FILE *ci = fopen(buf, "wb");
1140 eDebug("setSource %d failed!!!\n", (int)source);
1144 #else // force DM7025
1145 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1146 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1147 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1149 eDebug("cannot open /proc/stb/tsmux/input2");
1152 if (source != TUNER_A && source != TUNER_B)
1153 eDebug("setSource %d failed!!!\n", (int)source);
1155 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1158 eDebug("eDVBCISlot->setSource(%d)", (int)source);
1162 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");