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;
373 if (tmp) // ignore already assigned cislots...
377 // eDebug("usecount now %d", ci_it->use_count);
379 data_source ci_source=CI_A;
380 switch(ci_it->getSlotID())
382 case 0: ci_source = CI_A; break;
383 case 1: ci_source = CI_B; break;
384 case 2: ci_source = CI_C; break;
385 case 3: ci_source = CI_D; break;
387 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
394 eUsePtr<iDVBChannel> channel;
395 if (!pmthandler->getChannel(channel))
397 ePtr<iDVBFrontend> frontend;
398 if (!channel->getFrontend(frontend))
400 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
401 tunernum = fe->getID();
404 ASSERT(tunernum != -1);
405 data_source tuner_source = TUNER_A;
408 case 0: tuner_source = TUNER_A; break;
409 case 1: tuner_source = TUNER_B; break;
410 case 2: tuner_source = TUNER_C; break;
411 case 3: tuner_source = TUNER_D; break;
413 eDebug("try to get source for tuner %d!!\n", tunernum);
416 ci_it->current_tuner = tunernum;
417 setInputSource(tunernum, ci_source);
418 ci_it->setSource(tuner_source);
422 ci_it->current_tuner = it->cislot->current_tuner;
423 ci_it->linked_next = it->cislot;
424 ci_it->setSource(ci_it->linked_next->current_source);
425 ci_it->linked_next->setSource(ci_source);
435 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
437 // check if this pmthandler is already registered
438 PMTHandlerList::iterator it = m_pmt_handlers.begin();
439 while (it != m_pmt_handlers.end())
441 if ( *it++ == pmthandler )
445 eServiceReferenceDVB ref;
446 pmthandler->getServiceReference(ref);
447 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
449 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
450 recheckPMTHandlers();
453 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
455 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
456 if (it != m_pmt_handlers.end())
458 eDVBCISlot *slot = it->cislot;
459 eDVBServicePMTHandler *pmthandler = it->pmthandler;
460 m_pmt_handlers.erase(it);
462 eServiceReferenceDVB service_to_remove;
463 pmthandler->getServiceReference(service_to_remove);
465 bool sameServiceExist=false;
466 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
470 eServiceReferenceDVB ref;
471 i->pmthandler->getServiceReference(ref);
472 if ( ref == service_to_remove )
474 sameServiceExist=true;
482 if (!sameServiceExist)
484 if (slot->getNumOfServices() > 1)
486 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
487 service_to_remove.toString().c_str());
488 std::vector<uint16_t> caids;
489 caids.push_back(0xFFFF);
490 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
492 slot->removeService(service_to_remove.getServiceID().get());
495 eDVBCISlot *next = slot->linked_next;
496 if (!--slot->use_count)
498 if (slot->linked_next)
499 slot->linked_next->setSource(slot->current_source);
501 setInputSource(slot->current_tuner, slot->current_source);
503 if (it->cislot == slot) // remove the base slot
504 it->cislot = slot->linked_next;
507 if (slot->linked_next)
509 eDVBCISlot *tmp = it->cislot;
510 while(tmp->linked_next != slot)
511 tmp = tmp->linked_next;
513 tmp->linked_next = slot->linked_next;
518 // eDebug("use_count is now %d", slot->use_count);
522 // check if another service is waiting for the CI
523 recheckPMTHandlers();
526 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
528 eDebug("[eDVBCIInterfaces] gotPMT");
529 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
530 if (it != m_pmt_handlers.end() && it->cislot)
532 eDVBCISlot *tmp = it->cislot;
535 tmp->sendCAPMT(pmthandler);
536 tmp = tmp->linked_next;
541 int eDVBCIInterfaces::getMMIState(int slotid)
545 if( (slot = getSlot(slotid)) == 0 )
548 return slot->getMMIState();
551 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
553 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
554 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
557 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
560 if((input = fopen(buf, "wb")) == NULL) {
561 eDebug("cannot open %s", buf);
566 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
571 fprintf(input, "CI0");
574 fprintf(input, "CI1");
577 fprintf(input, "CI2");
580 fprintf(input, "CI3");
595 eDebug("setInputSource for input %d failed!!!\n", (int)source);
600 #else // force DM7025
602 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
605 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
608 if((input = fopen(buf, "wb")) == NULL) {
609 eDebug("cannot open %s", buf);
616 fprintf(input, "CI");
625 eDebug("setInputSource for input %d failed!!!\n", (int)source);
631 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
635 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
637 eDVBCISlot *slot = getSlot(slotid);
641 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
642 PyErr_SetString(PyExc_StandardError, tmp);
645 ePyObject tuple = PyTuple_New(3);
646 int caids = slot->possible_caids.size();
647 int services = slot->possible_services.size();
648 int providers = slot->possible_providers.size();
649 ePyObject caid_list = PyList_New(caids);
650 ePyObject service_list = PyList_New(services);
651 ePyObject provider_list = PyList_New(providers);
652 std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
656 PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
659 std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
663 PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
666 std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
670 PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
673 PyTuple_SET_ITEM(tuple, 0, service_list);
674 PyTuple_SET_ITEM(tuple, 1, provider_list);
675 PyTuple_SET_ITEM(tuple, 2, caid_list);
679 const char *PyObject_TypeStr(PyObject *o)
681 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
684 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
686 eDVBCISlot *slot = getSlot(slotid);
690 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
691 PyErr_SetString(PyExc_StandardError, tmp);
694 if (!PyTuple_Check(obj))
697 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
698 PyErr_SetString(PyExc_StandardError, tmp);
701 if (PyTuple_Size(obj) != 3)
703 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
704 "first argument should be a pythonlist with possible services\n"
705 "second argument should be a pythonlist with possible providers\n"
706 "third argument should be a pythonlist with possible caids";
707 PyErr_SetString(PyExc_StandardError, errstr);
710 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
711 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
712 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
713 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
716 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
717 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
718 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
719 "third argument(%s) should be a pythonlist with possible caids (ints)",
720 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
721 PyErr_SetString(PyExc_StandardError, errstr);
724 slot->possible_caids.clear();
725 slot->possible_services.clear();
726 slot->possible_providers.clear();
727 int size = PyList_Size(service_list);
731 ePyObject refstr = PyList_GET_ITEM(service_list, size);
732 if (!PyString_Check(refstr))
735 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
736 PyErr_SetString(PyExc_StandardError, buf);
739 char *tmpstr = PyString_AS_STRING(refstr);
740 eServiceReference ref(tmpstr);
742 slot->possible_services.insert(ref);
744 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
746 size = PyList_Size(provider_list);
750 ePyObject str = PyList_GET_ITEM(provider_list, size);
751 if (!PyString_Check(str))
754 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
755 PyErr_SetString(PyExc_StandardError, buf);
758 char *tmpstr = PyString_AS_STRING(str);
760 slot->possible_providers.insert(tmpstr);
762 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
764 size = PyList_Size(caid_list);
768 ePyObject caid = PyList_GET_ITEM(caid_list, size);
769 if (!PyInt_Check(caid))
772 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
773 PyErr_SetString(PyExc_StandardError, buf);
776 int tmpcaid = PyInt_AsLong(caid);
777 if (tmpcaid > 0 && tmpcaid < 0x10000)
778 slot->possible_caids.insert(tmpcaid);
780 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
785 int eDVBCISlot::send(const unsigned char *data, size_t len)
789 //eDebugNoNewLine("< ");
791 // eDebugNoNewLine("%02x ",data[i]);
794 if (sendqueue.empty())
795 res = ::write(fd, data, len);
797 if (res < 0 || (unsigned int)res != len)
799 unsigned char *d = new unsigned char[len];
800 memcpy(d, data, len);
801 sendqueue.push( queueData(d, len) );
802 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
808 void eDVBCISlot::data(int what)
810 if(what == eSocketNotifier::Priority) {
811 if(state != stateRemoved) {
812 state = stateRemoved;
813 eDebug("ci removed");
814 while(sendqueue.size())
816 delete [] sendqueue.top().data;
819 eDVBCIInterfaces::getInstance()->ciRemoved(this);
820 eDVBCISession::deleteSessions(this);
821 notifier->setRequested(eSocketNotifier::Read);
822 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
827 if (state == stateInvalid)
830 if(state != stateInserted) {
831 eDebug("ci inserted");
832 state = stateInserted;
833 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
834 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
835 /* enable PRI to detect removal or errors */
838 if (what & eSocketNotifier::Read) {
841 r = ::read(fd, data, 4096);
844 // eDebugNoNewLine("> ");
846 // eDebugNoNewLine("%02x ",data[i]);
848 eDVBCISession::receiveData(this, data, r);
849 eDVBCISession::pollAll();
853 else if (what & eSocketNotifier::Write) {
854 if (!sendqueue.empty()) {
855 const queueData &qe = sendqueue.top();
856 int res = ::write(fd, qe.data, qe.len);
857 if (res >= 0 && (unsigned int)res == qe.len)
864 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
868 DEFINE_REF(eDVBCISlot);
870 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
874 application_manager = 0;
882 sprintf(filename, "/dev/ci%d", nr);
884 fd = ::open(filename, O_RDWR | O_NONBLOCK);
886 eDebug("eDVBCISlot has fd %d", fd);
887 state = stateInvalid;
891 notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
892 CONNECT(notifier->activated, eDVBCISlot::data);
900 eDVBCISlot::~eDVBCISlot()
904 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
906 application_manager=session;
909 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
911 mmi_session = session;
914 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
916 ca_manager = session;
919 int eDVBCISlot::getSlotID()
924 int eDVBCISlot::reset()
926 eDebug("edvbcislot: reset requested");
928 if (state == stateInvalid)
930 unsigned char buf[256];
932 while(::read(fd, buf, 256)>0);
933 state = stateResetted;
936 while(sendqueue.size())
938 delete [] sendqueue.top().data;
947 int eDVBCISlot::startMMI()
949 eDebug("edvbcislot: startMMI()");
951 if(application_manager)
952 application_manager->startMMI();
957 int eDVBCISlot::stopMMI()
959 eDebug("edvbcislot: stopMMI()");
962 mmi_session->stopMMI();
967 int eDVBCISlot::answerText(int answer)
969 eDebug("edvbcislot: answerText(%d)", answer);
972 mmi_session->answerText(answer);
977 int eDVBCISlot::getMMIState()
985 int eDVBCISlot::answerEnq(char *value)
987 eDebug("edvbcislot: answerENQ(%s)", value);
990 mmi_session->answerEnq(value);
995 int eDVBCISlot::cancelEnq()
997 eDebug("edvbcislot: cancelENQ");
1000 mmi_session->cancelEnq();
1005 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1009 eDebug("no ca_manager (no CI plugged?)");
1012 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1013 ePtr<eTable<ProgramMapSection> > ptr;
1014 if (pmthandler->getPMT(ptr))
1018 eDVBTableSpec table_spec;
1019 ptr->getSpec(table_spec);
1020 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1022 eServiceReferenceDVB ref;
1023 pmthandler->getServiceReference(ref);
1024 uint16_t program_number = ref.getServiceID().get();
1025 std::map<uint16_t, uint8_t>::iterator it =
1026 running_services.find(program_number);
1028 if ( it != running_services.end() &&
1029 (pmt_version == it->second) &&
1030 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1032 eDebug("[eDVBCISlot] dont send self capmt version twice");
1036 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1037 if ( i == ptr->getSections().end() )
1041 unsigned char raw_data[2048];
1043 // eDebug("send %s capmt for service %04x",
1044 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1047 CaProgramMapSection capmt(*i++,
1048 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1049 while( i != ptr->getSections().end() )
1051 // eDebug("append");
1054 capmt.writeToBuffer(raw_data);
1056 // begin calc capmt length
1059 if ( raw_data[3] & 0x80 )
1062 int lenbytes = raw_data[3] & ~0x80;
1064 wp = (wp << 8) | raw_data[4 + i++];
1067 hlen = 4 + lenbytes;
1075 // end calc capmt length
1076 // eDebug("ca_manager %p dump capmt:", ca_manager);
1077 // for(int i=0;i<wp;i++)
1078 // eDebugNoNewLine("%02x ", raw_data[i]);
1081 if (caids.size() == 1 && caids[0] == 0xFFFF)
1083 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1084 raw_data[hlen+3] &= ~0x3E;
1085 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1086 // eDebug(" new version is %02x", raw_data[hlen+3]);
1089 //dont need tag and lenfield
1090 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1091 running_services[program_number] = pmt_version;
1097 void eDVBCISlot::removeService(uint16_t program_number)
1099 if (program_number == 0xFFFF)
1100 running_services.clear(); // remove all
1102 running_services.erase(program_number); // remove single service
1105 int eDVBCISlot::setSource(data_source source)
1107 current_source = source;
1110 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1111 FILE *ci = fopen(buf, "wb");
1139 eDebug("setSource %d failed!!!\n", (int)source);
1143 #else // force DM7025
1144 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1145 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1146 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1148 eDebug("cannot open /proc/stb/tsmux/input2");
1151 if (source != TUNER_A && source != TUNER_B)
1152 eDebug("setSource %d failed!!!\n", (int)source);
1154 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1157 eDebug("eDVBCISlot->setSource(%d)", (int)source);
1161 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");