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 if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
50 setInputSource(0, TUNER_A);
51 setInputSource(1, TUNER_B);
52 setInputSource(2, TUNER_C);
53 setInputSource(3, TUNER_D);
57 setInputSource(0, TUNER_A);
58 setInputSource(1, TUNER_B);
61 eDebug("done, found %d common interface slots", num_ci);
64 eDVBCIInterfaces::~eDVBCIInterfaces()
68 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
73 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
75 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
76 if(i->getSlotID() == slotid)
79 eDebug("FIXME: request for unknown slot");
84 int eDVBCIInterfaces::getSlotState(int slotid)
88 if( (slot = getSlot(slotid)) == 0 )
89 return eDVBCISlot::stateInvalid;
91 return slot->getState();
94 int eDVBCIInterfaces::reset(int slotid)
98 if( (slot = getSlot(slotid)) == 0 )
101 eDVBCISession::deleteSessions(slot);
104 return slot->reset();
107 int eDVBCIInterfaces::initialize(int slotid)
111 if( (slot = getSlot(slotid)) == 0 )
114 slot->removeService();
116 return sendCAPMT(slotid);
119 int eDVBCIInterfaces::sendCAPMT(int slotid)
123 if( (slot = getSlot(slotid)) == 0 )
126 PMTHandlerList::iterator it = m_pmt_handlers.begin();
127 while (it != m_pmt_handlers.end())
129 eDVBCISlot *tmp = it->cislot;
130 while (tmp && tmp != slot)
131 tmp = tmp->linked_next;
134 tmp->sendCAPMT(it->pmthandler); // send capmt
143 int eDVBCIInterfaces::startMMI(int slotid)
147 if( (slot = getSlot(slotid)) == 0 )
150 return slot->startMMI();
153 int eDVBCIInterfaces::stopMMI(int slotid)
157 if( (slot = getSlot(slotid)) == 0 )
160 return slot->stopMMI();
163 int eDVBCIInterfaces::answerText(int slotid, int answer)
167 if( (slot = getSlot(slotid)) == 0 )
170 return slot->answerText(answer);
173 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
177 if( (slot = getSlot(slotid)) == 0 )
180 return slot->answerEnq(value);
183 int eDVBCIInterfaces::cancelEnq(int slotid)
187 if( (slot = getSlot(slotid)) == 0 )
190 return slot->cancelEnq();
193 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
195 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
196 it != m_pmt_handlers.end(); ++it)
198 eServiceReferenceDVB ref;
199 it->pmthandler->getServiceReference(ref);
200 slot->removeService(ref.getServiceID().get());
201 if (slot->use_count && !--slot->use_count)
203 if (slot->linked_next)
204 slot->linked_next->setSource(slot->current_source);
206 setInputSource(slot->current_tuner, slot->current_source);
208 if (it->cislot == slot) // remove the base slot
209 it->cislot = slot->linked_next;
212 if (slot->linked_next)
214 eDVBCISlot *tmp = it->cislot;
215 while(tmp->linked_next != slot)
216 tmp = tmp->linked_next;
218 tmp->linked_next = slot->linked_next;
226 static bool canDescrambleMultipleServices(int slotid)
229 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
231 ePythonConfigQuery::getConfigValue(configStr, str);
234 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
235 if (appname.find("AlphaCrypt") != std::string::npos)
238 else if (str == "yes")
243 void eDVBCIInterfaces::recheckPMTHandlers()
245 // eDebug("recheckPMTHAndlers()");
246 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
247 it != m_pmt_handlers.end(); ++it)
250 ePtr<eDVBService> service;
251 eServiceReferenceDVB ref;
252 eDVBServicePMTHandler *pmthandler = it->pmthandler;
253 eDVBServicePMTHandler::program p;
255 pmthandler->getServiceReference(ref);
256 pmthandler->getService(service);
257 if (!pmthandler->getProgramInfo(p))
260 for (std::set<uint16_t>::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
261 caids.push_front(*x);
263 service->m_ca = caids;
267 caids = service->m_ca;
270 continue; // unscrambled service
272 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
275 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
279 if (!ci_it->possible_services.empty())
282 std::set<eServiceReference>::iterator it = ci_it->possible_services.find(ref);
283 if (it != ci_it->possible_services.end())
285 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
289 if (!useThis && !ci_it->possible_providers.empty())
293 if (!service) // subservice?
295 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
296 eDVBDB::getInstance()->getService(parent_ref, service);
301 std::set<std::string>::iterator it = ci_it->possible_providers.find(service->m_provider_name);
302 if (it != ci_it->possible_providers.end())
304 eDebug("'%s' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ci_it->getSlotID());
309 if (!useThis && !ci_it->possible_caids.empty())
311 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
313 std::set<uint16_t>::iterator it = ci_it->possible_caids.find(*ca);
314 if (it != ci_it->possible_caids.end())
316 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
322 if (!useThis && !mask)
324 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
325 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
327 std::vector<uint16_t>::const_iterator z =
328 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
329 if ( z != ci_caids.end() && *z == *ca )
331 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
341 if (ci_it->use_count) // check if this CI can descramble more than one service
344 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
345 while (tmp != m_pmt_handlers.end())
347 if ( tmp->cislot == ci_it && it != tmp )
349 eServiceReferenceDVB ref2;
350 tmp->pmthandler->getServiceReference(ref2);
351 eDVBChannelID s1, s2;
354 ref.getChannelID(s1);
355 ref2.getChannelID(s2);
357 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(ci_it->getSlotID())))
368 // check if this CI is already assigned to this pmthandler
369 eDVBCISlot *tmp = it->cislot;
374 tmp=tmp->linked_next;
377 if (tmp) // ignore already assigned cislots...
381 // eDebug("usecount now %d", ci_it->use_count);
383 data_source ci_source=CI_A;
384 switch(ci_it->getSlotID())
386 case 0: ci_source = CI_A; break;
387 case 1: ci_source = CI_B; break;
388 case 2: ci_source = CI_C; break;
389 case 3: ci_source = CI_D; break;
391 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
398 eUsePtr<iDVBChannel> channel;
399 if (!pmthandler->getChannel(channel))
401 ePtr<iDVBFrontend> frontend;
402 if (!channel->getFrontend(frontend))
404 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
405 tunernum = fe->getID();
408 ASSERT(tunernum != -1);
409 data_source tuner_source = TUNER_A;
412 case 0: tuner_source = TUNER_A; break;
413 case 1: tuner_source = TUNER_B; break;
414 case 2: tuner_source = TUNER_C; break;
415 case 3: tuner_source = TUNER_D; break;
417 eDebug("try to get source for tuner %d!!\n", tunernum);
420 ci_it->current_tuner = tunernum;
421 setInputSource(tunernum, ci_source);
422 ci_it->setSource(tuner_source);
426 ci_it->current_tuner = it->cislot->current_tuner;
427 ci_it->linked_next = it->cislot;
428 ci_it->setSource(ci_it->linked_next->current_source);
429 ci_it->linked_next->setSource(ci_source);
439 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
441 // check if this pmthandler is already registered
442 PMTHandlerList::iterator it = m_pmt_handlers.begin();
443 while (it != m_pmt_handlers.end())
445 if ( *it++ == pmthandler )
449 eServiceReferenceDVB ref;
450 pmthandler->getServiceReference(ref);
451 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
453 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
454 recheckPMTHandlers();
457 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
459 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
460 if (it != m_pmt_handlers.end())
462 eDVBCISlot *slot = it->cislot;
463 eDVBServicePMTHandler *pmthandler = it->pmthandler;
464 m_pmt_handlers.erase(it);
466 eServiceReferenceDVB service_to_remove;
467 pmthandler->getServiceReference(service_to_remove);
469 bool sameServiceExist=false;
470 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
474 eServiceReferenceDVB ref;
475 i->pmthandler->getServiceReference(ref);
476 if ( ref == service_to_remove )
478 sameServiceExist=true;
486 if (!sameServiceExist)
488 if (slot->getNumOfServices() > 1)
490 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
491 service_to_remove.toString().c_str());
492 std::vector<uint16_t> caids;
493 caids.push_back(0xFFFF);
494 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
496 slot->removeService(service_to_remove.getServiceID().get());
499 eDVBCISlot *next = slot->linked_next;
500 if (!--slot->use_count)
502 if (slot->linked_next)
503 slot->linked_next->setSource(slot->current_source);
505 setInputSource(slot->current_tuner, slot->current_source);
507 if (it->cislot == slot) // remove the base slot
508 it->cislot = slot->linked_next;
511 if (slot->linked_next)
513 eDVBCISlot *tmp = it->cislot;
514 while(tmp->linked_next != slot)
515 tmp = tmp->linked_next;
517 tmp->linked_next = slot->linked_next;
522 // eDebug("use_count is now %d", slot->use_count);
526 // check if another service is waiting for the CI
527 recheckPMTHandlers();
530 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
532 eDebug("[eDVBCIInterfaces] gotPMT");
533 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
534 if (it != m_pmt_handlers.end() && it->cislot)
536 eDVBCISlot *tmp = it->cislot;
539 tmp->sendCAPMT(pmthandler);
540 tmp = tmp->linked_next;
545 int eDVBCIInterfaces::getMMIState(int slotid)
549 if( (slot = getSlot(slotid)) == 0 )
552 return slot->getMMIState();
555 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
557 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
558 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
559 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
562 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
565 if((input = fopen(buf, "wb")) == NULL) {
566 eDebug("cannot open %s", buf);
571 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
576 fprintf(input, "CI0");
579 fprintf(input, "CI1");
582 fprintf(input, "CI2");
585 fprintf(input, "CI3");
600 eDebug("setInputSource for input %d failed!!!\n", (int)source);
609 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
612 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
615 if((input = fopen(buf, "wb")) == NULL) {
616 eDebug("cannot open %s", buf);
623 fprintf(input, "CI");
632 eDebug("setInputSource for input %d failed!!!\n", (int)source);
638 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
642 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
644 eDVBCISlot *slot = getSlot(slotid);
648 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
649 PyErr_SetString(PyExc_StandardError, tmp);
652 ePyObject tuple = PyTuple_New(3);
653 int caids = slot->possible_caids.size();
654 int services = slot->possible_services.size();
655 int providers = slot->possible_providers.size();
656 ePyObject caid_list = PyList_New(caids);
657 ePyObject service_list = PyList_New(services);
658 ePyObject provider_list = PyList_New(providers);
659 std::set<uint16_t>::iterator caid_it(slot->possible_caids.begin());
663 PyTuple_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
666 std::set<eServiceReference>::iterator ref_it(slot->possible_services.begin());
670 PyTuple_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
673 std::set<std::string>::iterator provider_it(slot->possible_providers.begin());
677 PyTuple_SET_ITEM(provider_list, providers, PyString_FromString(provider_it->c_str()));
680 PyTuple_SET_ITEM(tuple, 0, service_list);
681 PyTuple_SET_ITEM(tuple, 1, provider_list);
682 PyTuple_SET_ITEM(tuple, 2, caid_list);
686 const char *PyObject_TypeStr(PyObject *o)
688 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
691 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
693 eDVBCISlot *slot = getSlot(slotid);
697 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
698 PyErr_SetString(PyExc_StandardError, tmp);
701 if (!PyTuple_Check(obj))
704 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
705 PyErr_SetString(PyExc_StandardError, tmp);
708 if (PyTuple_Size(obj) != 3)
710 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
711 "first argument should be a pythonlist with possible services\n"
712 "second argument should be a pythonlist with possible providers\n"
713 "third argument should be a pythonlist with possible caids";
714 PyErr_SetString(PyExc_StandardError, errstr);
717 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
718 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
719 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
720 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
723 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
724 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
725 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
726 "third argument(%s) should be a pythonlist with possible caids (ints)",
727 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
728 PyErr_SetString(PyExc_StandardError, errstr);
731 slot->possible_caids.clear();
732 slot->possible_services.clear();
733 slot->possible_providers.clear();
734 int size = PyList_Size(service_list);
738 ePyObject refstr = PyList_GET_ITEM(service_list, size);
739 if (!PyString_Check(refstr))
742 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
743 PyErr_SetString(PyExc_StandardError, buf);
746 char *tmpstr = PyString_AS_STRING(refstr);
747 eServiceReference ref(tmpstr);
749 slot->possible_services.insert(ref);
751 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
753 size = PyList_Size(provider_list);
757 ePyObject str = PyList_GET_ITEM(provider_list, size);
758 if (!PyString_Check(str))
761 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a string it is '%s'!!", PyObject_TypeStr(str));
762 PyErr_SetString(PyExc_StandardError, buf);
765 char *tmpstr = PyString_AS_STRING(str);
767 slot->possible_providers.insert(tmpstr);
769 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider name list!!");
771 size = PyList_Size(caid_list);
775 ePyObject caid = PyList_GET_ITEM(caid_list, size);
776 if (!PyInt_Check(caid))
779 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
780 PyErr_SetString(PyExc_StandardError, buf);
783 int tmpcaid = PyInt_AsLong(caid);
784 if (tmpcaid > 0 && tmpcaid < 0x10000)
785 slot->possible_caids.insert(tmpcaid);
787 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
792 int eDVBCISlot::send(const unsigned char *data, size_t len)
796 //eDebugNoNewLine("< ");
798 // eDebugNoNewLine("%02x ",data[i]);
801 if (sendqueue.empty())
802 res = ::write(fd, data, len);
804 if (res < 0 || (unsigned int)res != len)
806 unsigned char *d = new unsigned char[len];
807 memcpy(d, data, len);
808 sendqueue.push( queueData(d, len) );
809 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
815 void eDVBCISlot::data(int what)
817 if(what == eSocketNotifier::Priority) {
818 if(state != stateRemoved) {
819 state = stateRemoved;
820 eDebug("ci removed");
821 while(sendqueue.size())
823 delete [] sendqueue.top().data;
826 eDVBCIInterfaces::getInstance()->ciRemoved(this);
827 eDVBCISession::deleteSessions(this);
828 notifier->setRequested(eSocketNotifier::Read);
829 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
834 if (state == stateInvalid)
837 if(state != stateInserted) {
838 eDebug("ci inserted");
839 state = stateInserted;
840 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
841 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
842 /* enable PRI to detect removal or errors */
845 if (what & eSocketNotifier::Read) {
848 r = ::read(fd, data, 4096);
851 // eDebugNoNewLine("> ");
853 // eDebugNoNewLine("%02x ",data[i]);
855 eDVBCISession::receiveData(this, data, r);
856 eDVBCISession::pollAll();
860 else if (what & eSocketNotifier::Write) {
861 if (!sendqueue.empty()) {
862 const queueData &qe = sendqueue.top();
863 int res = ::write(fd, qe.data, qe.len);
864 if (res >= 0 && (unsigned int)res == qe.len)
871 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
875 DEFINE_REF(eDVBCISlot);
877 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
881 application_manager = 0;
889 sprintf(filename, "/dev/ci%d", nr);
891 fd = ::open(filename, O_RDWR | O_NONBLOCK);
893 eDebug("eDVBCISlot has fd %d", fd);
894 state = stateInvalid;
898 notifier = new eSocketNotifier(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
899 CONNECT(notifier->activated, eDVBCISlot::data);
907 eDVBCISlot::~eDVBCISlot()
911 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
913 application_manager=session;
916 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
918 mmi_session = session;
921 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
923 ca_manager = session;
926 int eDVBCISlot::getSlotID()
931 int eDVBCISlot::reset()
933 eDebug("edvbcislot: reset requested");
935 if (state == stateInvalid)
937 unsigned char buf[256];
939 while(::read(fd, buf, 256)>0);
940 state = stateResetted;
943 while(sendqueue.size())
945 delete [] sendqueue.top().data;
954 int eDVBCISlot::startMMI()
956 eDebug("edvbcislot: startMMI()");
958 if(application_manager)
959 application_manager->startMMI();
964 int eDVBCISlot::stopMMI()
966 eDebug("edvbcislot: stopMMI()");
969 mmi_session->stopMMI();
974 int eDVBCISlot::answerText(int answer)
976 eDebug("edvbcislot: answerText(%d)", answer);
979 mmi_session->answerText(answer);
984 int eDVBCISlot::getMMIState()
992 int eDVBCISlot::answerEnq(char *value)
994 eDebug("edvbcislot: answerENQ(%s)", value);
997 mmi_session->answerEnq(value);
1002 int eDVBCISlot::cancelEnq()
1004 eDebug("edvbcislot: cancelENQ");
1007 mmi_session->cancelEnq();
1012 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1016 eDebug("no ca_manager (no CI plugged?)");
1019 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1020 ePtr<eTable<ProgramMapSection> > ptr;
1021 if (pmthandler->getPMT(ptr))
1025 eDVBTableSpec table_spec;
1026 ptr->getSpec(table_spec);
1027 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1029 eServiceReferenceDVB ref;
1030 pmthandler->getServiceReference(ref);
1031 uint16_t program_number = ref.getServiceID().get();
1032 std::map<uint16_t, uint8_t>::iterator it =
1033 running_services.find(program_number);
1035 if ( it != running_services.end() &&
1036 (pmt_version == it->second) &&
1037 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1039 eDebug("[eDVBCISlot] dont send self capmt version twice");
1043 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1044 if ( i == ptr->getSections().end() )
1048 unsigned char raw_data[2048];
1050 // eDebug("send %s capmt for service %04x to slot %d",
1051 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1052 // program_number, slotid);
1054 CaProgramMapSection capmt(*i++,
1055 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1056 while( i != ptr->getSections().end() )
1058 // eDebug("append");
1061 capmt.writeToBuffer(raw_data);
1063 // begin calc capmt length
1066 if ( raw_data[3] & 0x80 )
1069 int lenbytes = raw_data[3] & ~0x80;
1071 wp = (wp << 8) | raw_data[4 + i++];
1074 hlen = 4 + lenbytes;
1082 // end calc capmt length
1083 // eDebug("ca_manager %p dump capmt:", ca_manager);
1084 // for(int i=0;i<wp;i++)
1085 // eDebugNoNewLine("%02x ", raw_data[i]);
1088 if (caids.size() == 1 && caids[0] == 0xFFFF)
1090 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1091 raw_data[hlen+3] &= ~0x3E;
1092 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1093 // eDebug(" new version is %02x", raw_data[hlen+3]);
1096 //dont need tag and lenfield
1097 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1098 running_services[program_number] = pmt_version;
1104 void eDVBCISlot::removeService(uint16_t program_number)
1106 if (program_number == 0xFFFF)
1107 running_services.clear(); // remove all
1109 running_services.erase(program_number); // remove single service
1112 int eDVBCISlot::setSource(data_source source)
1114 current_source = source;
1115 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1118 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1119 FILE *ci = fopen(buf, "wb");
1147 eDebug("setSource %d failed!!!\n", (int)source);
1154 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1155 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1156 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1158 eDebug("cannot open /proc/stb/tsmux/input2");
1161 if (source != TUNER_A && source != TUNER_B)
1162 eDebug("setSource %d failed!!!\n", (int)source);
1164 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1167 eDebug("eDVBCISlot->setSource(%d)", (int)source);
1171 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");