4 #include <lib/base/init.h>
5 #include <lib/base/init_num.h>
6 #include <lib/base/ebase.h>
8 #include <lib/base/eerror.h>
9 #include <lib/base/nconfig.h> // access to python config
10 #include <lib/dvb/db.h>
11 #include <lib/dvb/pmt.h>
12 #include <lib/dvb_ci/dvbci.h>
13 #include <lib/dvb_ci/dvbci_session.h>
14 #include <lib/dvb_ci/dvbci_camgr.h>
15 #include <lib/dvb_ci/dvbci_ui.h>
16 #include <lib/dvb_ci/dvbci_appmgr.h>
17 #include <lib/dvb_ci/dvbci_mmi.h>
19 #include <dvbsi++/ca_program_map_section.h>
24 #define eDebugCI(x...) eDebug(x)
26 #define eDebugCI(x...)
29 eDVBCIInterfaces *eDVBCIInterfaces::instance = 0;
31 eDVBCIInterfaces::eDVBCIInterfaces()
37 eDebug("scanning for common interfaces..");
43 sprintf(filename, "/dev/ci%d", num_ci);
45 if (stat(filename, &s))
48 ePtr<eDVBCISlot> cislot;
50 cislot = new eDVBCISlot(eApp, num_ci);
51 m_slots.push_back(cislot);
56 for (eSmartPtrList<eDVBCISlot>::iterator it(m_slots.begin()); it != m_slots.end(); ++it)
57 it->setSource(TUNER_A);
59 if (num_ci > 1) // // FIXME .. we force DM8000 when more than one CI Slot is avail
61 setInputSource(0, TUNER_A);
62 setInputSource(1, TUNER_B);
63 setInputSource(2, TUNER_C);
64 setInputSource(3, TUNER_D);
68 setInputSource(0, TUNER_A);
69 setInputSource(1, TUNER_B);
72 eDebug("done, found %d common interface slots", num_ci);
75 eDVBCIInterfaces::~eDVBCIInterfaces()
79 eDVBCIInterfaces *eDVBCIInterfaces::getInstance()
84 eDVBCISlot *eDVBCIInterfaces::getSlot(int slotid)
86 for(eSmartPtrList<eDVBCISlot>::iterator i(m_slots.begin()); i != m_slots.end(); ++i)
87 if(i->getSlotID() == slotid)
90 eDebug("FIXME: request for unknown slot");
95 int eDVBCIInterfaces::getSlotState(int slotid)
99 if( (slot = getSlot(slotid)) == 0 )
100 return eDVBCISlot::stateInvalid;
102 return slot->getState();
105 int eDVBCIInterfaces::reset(int slotid)
109 if( (slot = getSlot(slotid)) == 0 )
112 return slot->reset();
115 int eDVBCIInterfaces::initialize(int slotid)
119 if( (slot = getSlot(slotid)) == 0 )
122 slot->removeService();
124 return sendCAPMT(slotid);
127 int eDVBCIInterfaces::sendCAPMT(int slotid)
131 if( (slot = getSlot(slotid)) == 0 )
134 PMTHandlerList::iterator it = m_pmt_handlers.begin();
135 while (it != m_pmt_handlers.end())
137 eDVBCISlot *tmp = it->cislot;
138 while (tmp && tmp != slot)
139 tmp = tmp->linked_next;
142 tmp->sendCAPMT(it->pmthandler); // send capmt
151 int eDVBCIInterfaces::startMMI(int slotid)
155 if( (slot = getSlot(slotid)) == 0 )
158 return slot->startMMI();
161 int eDVBCIInterfaces::stopMMI(int slotid)
165 if( (slot = getSlot(slotid)) == 0 )
168 return slot->stopMMI();
171 int eDVBCIInterfaces::answerText(int slotid, int answer)
175 if( (slot = getSlot(slotid)) == 0 )
178 return slot->answerText(answer);
181 int eDVBCIInterfaces::answerEnq(int slotid, char *value)
185 if( (slot = getSlot(slotid)) == 0 )
188 return slot->answerEnq(value);
191 int eDVBCIInterfaces::cancelEnq(int slotid)
195 if( (slot = getSlot(slotid)) == 0 )
198 return slot->cancelEnq();
201 void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot)
203 eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count);
204 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
205 it != m_pmt_handlers.end(); ++it)
207 eServiceReferenceDVB ref;
208 it->pmthandler->getServiceReference(ref);
209 eDebugCI("check %s cislot %p %d\n", ref.toString().c_str(), it->cislot, it->cislot?it->cislot->getSlotID() : -1);
210 slot->removeService(ref.getServiceID().get());
211 if (slot->use_count && !--slot->use_count)
213 if (slot->linked_next)
214 slot->linked_next->setSource(slot->current_source);
215 else // last CI in chain
216 setInputSource(slot->current_tuner, slot->current_source);
218 if (it->cislot == slot) // remove the base slot
220 it->cislot = slot->linked_next;
221 eDebugCI("base removed.. so slot is now %p", it->cislot);
225 eDebugCI("not base removed.. %d", it->cislot->getSlotID());
226 eDVBCISlot *tmp = it->cislot;
227 while(tmp->linked_next != slot)
228 tmp = tmp->linked_next;
230 if (slot->linked_next)
231 tmp->linked_next = slot->linked_next;
233 tmp->linked_next = 0;
236 slot->user_mapped=false;
239 recheckPMTHandlers();
242 static bool canDescrambleMultipleServices(int slotid)
245 snprintf(configStr, 255, "config.ci.%d.canDescrambleMultipleServices", slotid);
247 ePythonConfigQuery::getConfigValue(configStr, str);
250 std::string appname = eDVBCI_UI::getInstance()->getAppName(slotid);
251 if (appname.find("AlphaCrypt") != std::string::npos)
254 else if (str == "yes")
259 void eDVBCIInterfaces::recheckPMTHandlers()
261 eDebugCI("recheckPMTHAndlers()");
262 for (PMTHandlerList::iterator it(m_pmt_handlers.begin());
263 it != m_pmt_handlers.end(); ++it)
266 ePtr<eDVBService> service;
267 eServiceReferenceDVB ref;
268 eDVBCISlot *tmp = it->cislot;
269 eDVBServicePMTHandler *pmthandler = it->pmthandler;
270 eDVBServicePMTHandler::program p;
271 bool first_plugged_cis_exist = false;
273 pmthandler->getServiceReference(ref);
274 pmthandler->getService(service);
276 eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str());
277 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
278 if (ci_it->first_plugged && ci_it->getCAManager())
280 eDebug("Slot %d first plugged", ci_it->getSlotID());
281 ci_it->first_plugged = false;
282 first_plugged_cis_exist = true;
285 // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running
286 if (!first_plugged_cis_exist)
290 if (!tmp->running_services.empty())
292 tmp=tmp->linked_next;
294 if (tmp) // we dont like to change tsmux for running services
296 eDebugCI("already assigned and running CI!\n");
301 if (!pmthandler->getProgramInfo(p))
304 for (caidSet::reverse_iterator x(p.caids.rbegin()); x != p.caids.rend(); ++x, ++cnt)
305 caids.push_front(*x);
307 service->m_ca = caids;
311 caids = service->m_ca;
314 continue; // unscrambled service
316 for (eSmartPtrList<eDVBCISlot>::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it)
318 eDebugCI("check Slot %d", ci_it->getSlotID());
320 bool user_mapped=true;
321 eDVBCICAManagerSession *ca_manager = ci_it->getCAManager();
326 if (!ci_it->possible_services.empty())
329 serviceSet::iterator it = ci_it->possible_services.find(ref);
330 if (it != ci_it->possible_services.end())
332 eDebug("'%s' is in service list of slot %d... so use it", ref.toString().c_str(), ci_it->getSlotID());
336 if (!useThis && !ci_it->possible_providers.empty())
338 eDVBNamespace ns = ref.getDVBNamespace();
340 if (!service) // subservice?
342 eServiceReferenceDVB parent_ref = ref.getParentServiceReference();
343 eDVBDB::getInstance()->getService(parent_ref, service);
347 providerSet::iterator it = ci_it->possible_providers.find(providerPair(service->m_provider_name, ns.get()));
348 if (it != ci_it->possible_providers.end())
350 eDebug("'%s/%08x' is in provider list of slot %d... so use it", service->m_provider_name.c_str(), ns.get(), ci_it->getSlotID());
355 if (!useThis && !ci_it->possible_caids.empty())
357 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
359 caidSet::iterator it = ci_it->possible_caids.find(*ca);
360 if (it != ci_it->possible_caids.end())
362 eDebug("caid '%04x' is in caid list of slot %d... so use it", *ca, ci_it->getSlotID());
368 if (!useThis && !mask)
370 const std::vector<uint16_t> &ci_caids = ca_manager->getCAIDs();
371 for (CAID_LIST::iterator ca(caids.begin()); ca != caids.end(); ++ca)
373 std::vector<uint16_t>::const_iterator z =
374 std::lower_bound(ci_caids.begin(), ci_caids.end(), *ca);
375 if ( z != ci_caids.end() && *z == *ca )
377 eDebug("The CI in Slot %d has said it can handle caid %04x... so use it", ci_it->getSlotID(), *z);
388 // check if this CI is already assigned to this pmthandler
389 eDVBCISlot *tmp = it->cislot;
394 tmp=tmp->linked_next;
396 if (tmp) // ignore already assigned cislots...
398 eDebugCI("already assigned!");
401 eDebugCI("current slot %d usecount %d", ci_it->getSlotID(), ci_it->use_count);
402 if (ci_it->use_count) // check if this CI can descramble more than one service
406 PMTHandlerList::iterator tmp = m_pmt_handlers.begin();
407 while (!found && tmp != m_pmt_handlers.end())
410 eDVBCISlot *tmp_cislot = tmp->cislot;
411 while (!found && tmp_cislot)
414 eServiceReferenceDVB ref2;
415 tmp->pmthandler->getServiceReference(ref2);
416 if ( tmp_cislot == ci_it && it->pmthandler != tmp->pmthandler )
418 eDebugCI("check pmthandler %s for same service/tp", ref2.toString().c_str());
419 eDVBChannelID s1, s2;
422 eDebugCI("different services!");
423 ref.getChannelID(s1);
424 ref2.getChannelID(s2);
426 if (ref == ref2 || (s1 == s2 && canDescrambleMultipleServices(tmp_cislot->getSlotID())))
430 eDVBCISlot *tmpci = it->cislot = tmp->cislot;
434 eDebug("(2)CISlot %d, usecount now %d", tmpci->getSlotID(), tmpci->use_count);
435 tmpci=tmpci->linked_next;
439 tmp_cislot=tmp_cislot->linked_next;
448 if (ci_it->user_mapped) // we dont like to link user mapped CIs
450 eDebugCI("user mapped CI already in use... dont link!");
455 eDebug("(1)CISlot %d, usecount now %d", ci_it->getSlotID(), ci_it->use_count);
457 data_source ci_source=CI_A;
458 switch(ci_it->getSlotID())
460 case 0: ci_source = CI_A; break;
461 case 1: ci_source = CI_B; break;
462 case 2: ci_source = CI_C; break;
463 case 3: ci_source = CI_D; break;
465 eDebug("try to get source for CI %d!!\n", ci_it->getSlotID());
472 eUsePtr<iDVBChannel> channel;
473 if (!pmthandler->getChannel(channel))
475 ePtr<iDVBFrontend> frontend;
476 if (!channel->getFrontend(frontend))
478 eDVBFrontend *fe = (eDVBFrontend*) &(*frontend);
479 tunernum = fe->getSlotID();
482 ASSERT(tunernum != -1);
483 data_source tuner_source = TUNER_A;
486 case 0: tuner_source = TUNER_A; break;
487 case 1: tuner_source = TUNER_B; break;
488 case 2: tuner_source = TUNER_C; break;
489 case 3: tuner_source = TUNER_D; break;
491 eDebug("try to get source for tuner %d!!\n", tunernum);
494 ci_it->current_tuner = tunernum;
495 setInputSource(tunernum, ci_source);
496 ci_it->setSource(tuner_source);
500 ci_it->current_tuner = it->cislot->current_tuner;
501 ci_it->linked_next = it->cislot;
502 ci_it->setSource(ci_it->linked_next->current_source);
503 ci_it->linked_next->setSource(ci_source);
506 eDebugCI("assigned!");
510 if (it->cislot && user_mapped) // CI assigned to this pmthandler in this run.. and user mapped? then we break here.. we dont like to link other CIs to user mapped CIs
512 eDebugCI("user mapped CI assigned... dont link CIs!");
520 void eDVBCIInterfaces::addPMTHandler(eDVBServicePMTHandler *pmthandler)
522 // check if this pmthandler is already registered
523 PMTHandlerList::iterator it = m_pmt_handlers.begin();
524 while (it != m_pmt_handlers.end())
526 if ( *it++ == pmthandler )
530 eServiceReferenceDVB ref;
531 pmthandler->getServiceReference(ref);
532 eDebug("[eDVBCIInterfaces] addPMTHandler %s", ref.toString().c_str());
534 m_pmt_handlers.push_back(CIPmtHandler(pmthandler));
535 recheckPMTHandlers();
538 void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler)
540 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(),m_pmt_handlers.end(),pmthandler);
541 if (it != m_pmt_handlers.end())
543 eDVBCISlot *slot = it->cislot;
544 eDVBServicePMTHandler *pmthandler = it->pmthandler;
545 m_pmt_handlers.erase(it);
547 eServiceReferenceDVB service_to_remove;
548 pmthandler->getServiceReference(service_to_remove);
550 bool sameServiceExist=false;
551 for (PMTHandlerList::iterator i=m_pmt_handlers.begin(); i != m_pmt_handlers.end(); ++i)
555 eServiceReferenceDVB ref;
556 i->pmthandler->getServiceReference(ref);
557 if ( ref == service_to_remove )
559 sameServiceExist=true;
567 if (!sameServiceExist)
569 if (slot->getNumOfServices() > 1)
571 eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt",
572 service_to_remove.toString().c_str());
573 std::vector<uint16_t> caids;
574 caids.push_back(0xFFFF);
575 slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service
577 slot->removeService(service_to_remove.getServiceID().get());
580 eDVBCISlot *next = slot->linked_next;
581 if (!--slot->use_count)
583 if (slot->linked_next)
584 slot->linked_next->setSource(slot->current_source);
586 setInputSource(slot->current_tuner, slot->current_source);
588 if (it->cislot == slot) // remove the base slot
589 it->cislot = slot->linked_next;
592 eDVBCISlot *tmp = it->cislot;
593 while(tmp->linked_next != slot)
594 tmp = tmp->linked_next;
596 if (slot->linked_next)
597 tmp->linked_next = slot->linked_next;
599 tmp->linked_next = 0;
601 slot->linked_next = 0;
602 slot->user_mapped = false;
604 eDebug("(3) slot %d usecount is now %d", slot->getSlotID(), slot->use_count);
607 // check if another service is waiting for the CI
608 recheckPMTHandlers();
612 void eDVBCIInterfaces::gotPMT(eDVBServicePMTHandler *pmthandler)
614 eDebug("[eDVBCIInterfaces] gotPMT");
615 PMTHandlerList::iterator it=std::find(m_pmt_handlers.begin(), m_pmt_handlers.end(), pmthandler);
616 if (it != m_pmt_handlers.end() && it->cislot)
618 eDVBCISlot *tmp = it->cislot;
621 eDebugCI("check slot %d %d %d", tmp->getSlotID(), tmp->running_services.empty(), canDescrambleMultipleServices(tmp->getSlotID()));
622 if (tmp->running_services.empty() || canDescrambleMultipleServices(tmp->getSlotID()))
623 tmp->sendCAPMT(pmthandler);
624 tmp = tmp->linked_next;
629 int eDVBCIInterfaces::getMMIState(int slotid)
633 if( (slot = getSlot(slotid)) == 0 )
636 return slot->getMMIState();
639 int eDVBCIInterfaces::setInputSource(int tuner_no, data_source source)
641 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
642 // eDebug("eDVBCIInterfaces::setInputSource(%d %d)", tuner_no, (int)source);
643 if (getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
646 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
649 if((input = fopen(buf, "wb")) == NULL) {
650 eDebug("cannot open %s", buf);
655 eDebug("setInputSource(%d, %d) failed... dm8000 just have four inputs", tuner_no, (int)source);
660 fprintf(input, "CI0");
663 fprintf(input, "CI1");
666 fprintf(input, "CI2");
669 fprintf(input, "CI3");
684 eDebug("setInputSource for input %d failed!!!\n", (int)source);
693 snprintf(buf, 64, "/proc/stb/tsmux/input%d", tuner_no);
696 eDebug("setInputSource(%d, %d) failed... dm7025 just have two inputs", tuner_no, (int)source);
699 if((input = fopen(buf, "wb")) == NULL) {
700 eDebug("cannot open %s", buf);
707 fprintf(input, "CI");
716 eDebug("setInputSource for input %d failed!!!\n", (int)source);
722 eDebug("eDVBCIInterfaces->setInputSource(%d, %d)", tuner_no, (int)source);
726 PyObject *eDVBCIInterfaces::getDescrambleRules(int slotid)
728 eDVBCISlot *slot = getSlot(slotid);
732 snprintf(tmp, 255, "eDVBCIInterfaces::getDescrambleRules try to get rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
733 PyErr_SetString(PyExc_StandardError, tmp);
736 ePyObject tuple = PyTuple_New(3);
737 int caids = slot->possible_caids.size();
738 int services = slot->possible_services.size();
739 int providers = slot->possible_providers.size();
740 ePyObject caid_list = PyList_New(caids);
741 ePyObject service_list = PyList_New(services);
742 ePyObject provider_list = PyList_New(providers);
743 caidSet::iterator caid_it(slot->possible_caids.begin());
747 PyList_SET_ITEM(caid_list, caids, PyLong_FromLong(*caid_it));
750 serviceSet::iterator ref_it(slot->possible_services.begin());
754 PyList_SET_ITEM(service_list, services, PyString_FromString(ref_it->toString().c_str()));
757 providerSet::iterator provider_it(slot->possible_providers.begin());
760 ePyObject tuple = PyTuple_New(2);
761 PyTuple_SET_ITEM(tuple, 0, PyString_FromString(provider_it->first.c_str()));
762 PyTuple_SET_ITEM(tuple, 1, PyLong_FromUnsignedLong(provider_it->second));
764 PyList_SET_ITEM(provider_list, providers, tuple);
767 PyTuple_SET_ITEM(tuple, 0, service_list);
768 PyTuple_SET_ITEM(tuple, 1, provider_list);
769 PyTuple_SET_ITEM(tuple, 2, caid_list);
773 const char *PyObject_TypeStr(PyObject *o)
775 return o->ob_type && o->ob_type->tp_name ? o->ob_type->tp_name : "unknown object type";
778 RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) obj )
780 eDVBCISlot *slot = getSlot(slotid);
784 snprintf(tmp, 255, "eDVBCIInterfaces::setDescrambleRules try to set rules for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
785 PyErr_SetString(PyExc_StandardError, tmp);
788 if (!PyTuple_Check(obj))
791 snprintf(tmp, 255, "2nd argument of setDescrambleRules is not a tuple.. it is a '%s'!!", PyObject_TypeStr(obj));
792 PyErr_SetString(PyExc_StandardError, tmp);
795 if (PyTuple_Size(obj) != 3)
797 const char *errstr = "eDVBCIInterfaces::setDescrambleRules not enough entrys in argument tuple!!\n"
798 "first argument should be a pythonlist with possible services\n"
799 "second argument should be a pythonlist with possible providers/dvbnamespace tuples\n"
800 "third argument should be a pythonlist with possible caids";
801 PyErr_SetString(PyExc_StandardError, errstr);
804 ePyObject service_list = PyTuple_GET_ITEM(obj, 0);
805 ePyObject provider_list = PyTuple_GET_ITEM(obj, 1);
806 ePyObject caid_list = PyTuple_GET_ITEM(obj, 2);
807 if (!PyList_Check(service_list) || !PyList_Check(provider_list) || !PyList_Check(caid_list))
810 snprintf(errstr, 512, "eDVBCIInterfaces::setDescrambleRules incorrect data types in argument tuple!!\n"
811 "first argument(%s) should be a pythonlist with possible services (reference strings)\n"
812 "second argument(%s) should be a pythonlist with possible providers (providername strings)\n"
813 "third argument(%s) should be a pythonlist with possible caids (ints)",
814 PyObject_TypeStr(service_list), PyObject_TypeStr(provider_list), PyObject_TypeStr(caid_list));
815 PyErr_SetString(PyExc_StandardError, errstr);
818 slot->possible_caids.clear();
819 slot->possible_services.clear();
820 slot->possible_providers.clear();
821 int size = PyList_Size(service_list);
825 ePyObject refstr = PyList_GET_ITEM(service_list, size);
826 if (!PyString_Check(refstr))
829 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in service list is not a string.. it is '%s'!!", PyObject_TypeStr(refstr));
830 PyErr_SetString(PyExc_StandardError, buf);
833 char *tmpstr = PyString_AS_STRING(refstr);
834 eServiceReference ref(tmpstr);
836 slot->possible_services.insert(ref);
838 eDebug("eDVBCIInterfaces::setDescrambleRules '%s' is not a valid service reference... ignore!!", tmpstr);
840 size = PyList_Size(provider_list);
844 ePyObject tuple = PyList_GET_ITEM(provider_list, size);
845 if (!PyTuple_Check(tuple))
848 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in provider list is not a tuple it is '%s'!!", PyObject_TypeStr(tuple));
849 PyErr_SetString(PyExc_StandardError, buf);
852 if (PyTuple_Size(tuple) != 2)
855 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules provider tuple has %d instead of 2 entries!!", PyTuple_Size(tuple));
856 PyErr_SetString(PyExc_StandardError, buf);
859 if (!PyString_Check(PyTuple_GET_ITEM(tuple, 0)))
862 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 1st entry in provider tuple is not a string it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 0)));
863 PyErr_SetString(PyExc_StandardError, buf);
866 if (!PyLong_Check(PyTuple_GET_ITEM(tuple, 1)))
869 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules 2nd entry in provider tuple is not a long it is '%s'", PyObject_TypeStr(PyTuple_GET_ITEM(tuple, 1)));
870 PyErr_SetString(PyExc_StandardError, buf);
873 char *tmpstr = PyString_AS_STRING(PyTuple_GET_ITEM(tuple, 0));
874 uint32_t orbpos = PyLong_AsUnsignedLong(PyTuple_GET_ITEM(tuple, 1));
876 slot->possible_providers.insert(std::pair<std::string, uint32_t>(tmpstr, orbpos));
878 eDebug("eDVBCIInterfaces::setDescrambleRules ignore invalid entry in provider tuple (string is empty)!!");
880 size = PyList_Size(caid_list);
884 ePyObject caid = PyList_GET_ITEM(caid_list, size);
885 if (!PyInt_Check(caid))
888 snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid));
889 PyErr_SetString(PyExc_StandardError, buf);
892 int tmpcaid = PyInt_AsLong(caid);
893 if (tmpcaid > 0 && tmpcaid < 0x10000)
894 slot->possible_caids.insert(tmpcaid);
896 eDebug("eDVBCIInterfaces::setDescrambleRules %d is not a valid caid... ignore!!", tmpcaid);
901 PyObject *eDVBCIInterfaces::readCICaIds(int slotid)
903 eDVBCISlot *slot = getSlot(slotid);
907 snprintf(tmp, 255, "eDVBCIInterfaces::readCICaIds try to get CAIds for CI Slot %d... but just %d slots are available", slotid, m_slots.size());
908 PyErr_SetString(PyExc_StandardError, tmp);
912 ePyObject list = PyList_New(slot->possible_caids.size());
913 for (caidSet::iterator it = slot->possible_caids.begin(); it != slot->possible_caids.end(); ++it)
914 PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it));
918 int eDVBCISlot::send(const unsigned char *data, size_t len)
922 //eDebugNoNewLine("< ");
924 // eDebugNoNewLine("%02x ",data[i]);
927 if (sendqueue.empty())
928 res = ::write(fd, data, len);
930 if (res < 0 || (unsigned int)res != len)
932 unsigned char *d = new unsigned char[len];
933 memcpy(d, data, len);
934 sendqueue.push( queueData(d, len) );
935 notifier->setRequested(eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
941 void eDVBCISlot::data(int what)
943 eDebugCI("CISlot %d what %d\n", getSlotID(), what);
944 if(what == eSocketNotifier::Priority) {
945 if(state != stateRemoved) {
946 state = stateRemoved;
947 while(sendqueue.size())
949 delete [] sendqueue.top().data;
952 eDVBCISession::deleteSessions(this);
953 eDVBCIInterfaces::getInstance()->ciRemoved(this);
954 notifier->setRequested(eSocketNotifier::Read);
955 eDVBCI_UI::getInstance()->setState(getSlotID(),0);
960 if (state == stateInvalid)
963 if(state != stateInserted) {
964 eDebug("ci inserted in slot %d", getSlotID());
965 state = stateInserted;
966 eDVBCI_UI::getInstance()->setState(getSlotID(),1);
967 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
968 /* enable PRI to detect removal or errors */
971 if (what & eSocketNotifier::Read) {
974 r = ::read(fd, data, 4096);
977 // eDebugNoNewLine("> ");
979 // eDebugNoNewLine("%02x ",data[i]);
981 eDVBCISession::receiveData(this, data, r);
982 eDVBCISession::pollAll();
986 else if (what & eSocketNotifier::Write) {
987 if (!sendqueue.empty()) {
988 const queueData &qe = sendqueue.top();
989 int res = ::write(fd, qe.data, qe.len);
990 if (res >= 0 && (unsigned int)res == qe.len)
997 notifier->setRequested(eSocketNotifier::Read|eSocketNotifier::Priority);
1001 DEFINE_REF(eDVBCISlot);
1003 eDVBCISlot::eDVBCISlot(eMainloop *context, int nr)
1007 application_manager = 0;
1012 user_mapped = false;
1013 first_plugged = true;
1017 sprintf(filename, "/dev/ci%d", nr);
1019 // possible_caids.insert(0x1702);
1020 // possible_providers.insert(providerPair("PREMIERE", 0xC00000));
1021 // possible_services.insert(eServiceReference("1:0:1:2A:4:85:C00000:0:0:0:"));
1023 fd = ::open(filename, O_RDWR | O_NONBLOCK);
1025 eDebugCI("CI Slot %d has fd %d", getSlotID(), fd);
1026 state = stateInvalid;
1030 notifier = eSocketNotifier::create(context, fd, eSocketNotifier::Read | eSocketNotifier::Priority | eSocketNotifier::Write);
1031 CONNECT(notifier->activated, eDVBCISlot::data);
1038 eDVBCISlot::~eDVBCISlot()
1040 eDVBCISession::deleteSessions(this);
1043 void eDVBCISlot::setAppManager( eDVBCIApplicationManagerSession *session )
1045 application_manager=session;
1048 void eDVBCISlot::setMMIManager( eDVBCIMMISession *session )
1050 mmi_session = session;
1053 void eDVBCISlot::setCAManager( eDVBCICAManagerSession *session )
1055 ca_manager = session;
1058 int eDVBCISlot::getSlotID()
1063 int eDVBCISlot::reset()
1065 eDebug("CI Slot %d: reset requested", getSlotID());
1067 if (state == stateInvalid)
1069 unsigned char buf[256];
1071 while(::read(fd, buf, 256)>0);
1072 state = stateResetted;
1075 while(sendqueue.size())
1077 delete [] sendqueue.top().data;
1086 int eDVBCISlot::startMMI()
1088 eDebug("CI Slot %d: startMMI()", getSlotID());
1090 if(application_manager)
1091 application_manager->startMMI();
1096 int eDVBCISlot::stopMMI()
1098 eDebug("CI Slot %d: stopMMI()", getSlotID());
1101 mmi_session->stopMMI();
1106 int eDVBCISlot::answerText(int answer)
1108 eDebug("CI Slot %d: answerText(%d)", getSlotID(), answer);
1111 mmi_session->answerText(answer);
1116 int eDVBCISlot::getMMIState()
1124 int eDVBCISlot::answerEnq(char *value)
1126 eDebug("CI Slot %d: answerENQ(%s)", getSlotID(), value);
1129 mmi_session->answerEnq(value);
1134 int eDVBCISlot::cancelEnq()
1136 eDebug("CI Slot %d: cancelENQ", getSlotID());
1139 mmi_session->cancelEnq();
1144 int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector<uint16_t> &ids)
1148 eDebug("no ca_manager (no CI plugged?)");
1151 const std::vector<uint16_t> &caids = ids.empty() ? ca_manager->getCAIDs() : ids;
1152 ePtr<eTable<ProgramMapSection> > ptr;
1153 if (pmthandler->getPMT(ptr))
1157 eDVBTableSpec table_spec;
1158 ptr->getSpec(table_spec);
1159 int pmt_version = table_spec.version & 0x1F; // just 5 bits
1161 eServiceReferenceDVB ref;
1162 pmthandler->getServiceReference(ref);
1163 uint16_t program_number = ref.getServiceID().get();
1164 std::map<uint16_t, uint8_t>::iterator it =
1165 running_services.find(program_number);
1167 if ( it != running_services.end() &&
1168 (pmt_version == it->second) &&
1169 !(caids.size() == 1 && caids[0] == 0xFFFF) )
1171 eDebug("[eDVBCISlot] dont send self capmt version twice");
1175 std::vector<ProgramMapSection*>::const_iterator i=ptr->getSections().begin();
1176 if ( i == ptr->getSections().end() )
1180 unsigned char raw_data[2048];
1182 // eDebug("send %s capmt for service %04x to slot %d",
1183 // it != running_services.end() ? "UPDATE" : running_services.empty() ? "ONLY" : "ADD",
1184 // program_number, slotid);
1186 CaProgramMapSection capmt(*i++,
1187 it != running_services.end() ? 0x05 /*update*/ : running_services.empty() ? 0x03 /*only*/ : 0x04 /*add*/, 0x01, caids );
1188 while( i != ptr->getSections().end() )
1190 // eDebug("append");
1193 capmt.writeToBuffer(raw_data);
1195 // begin calc capmt length
1198 if ( raw_data[3] & 0x80 )
1201 int lenbytes = raw_data[3] & ~0x80;
1203 wp = (wp << 8) | raw_data[4 + i++];
1206 hlen = 4 + lenbytes;
1214 // end calc capmt length
1215 // eDebug("ca_manager %p dump capmt:", ca_manager);
1216 // for(int i=0;i<wp;i++)
1217 // eDebugNoNewLine("%02x ", raw_data[i]);
1220 if (caids.size() == 1 && caids[0] == 0xFFFF)
1222 // eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
1223 raw_data[hlen+3] &= ~0x3E;
1224 raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
1225 // eDebug(" new version is %02x", raw_data[hlen+3]);
1228 //dont need tag and lenfield
1229 ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
1230 running_services[program_number] = pmt_version;
1236 void eDVBCISlot::removeService(uint16_t program_number)
1238 if (program_number == 0xFFFF)
1239 running_services.clear(); // remove all
1241 running_services.erase(program_number); // remove single service
1244 int eDVBCISlot::setSource(data_source source)
1246 current_source = source;
1247 if (eDVBCIInterfaces::getInstance()->getNumOfSlots() > 1) // FIXME .. we force DM8000 when more than one CI Slot is avail
1250 snprintf(buf, 64, "/proc/stb/tsmux/ci%d_input", slotid);
1251 FILE *ci = fopen(buf, "wb");
1279 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1286 // eDebug("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
1287 // eDebug("eDVBCISlot::enableTS(%d %d)", enable, (int)source);
1288 FILE *ci = fopen("/proc/stb/tsmux/input2", "wb");
1290 eDebug("cannot open /proc/stb/tsmux/input2");
1293 if (source != TUNER_A && source != TUNER_B)
1294 eDebug("CI Slot %d: setSource %d failed!!!\n", getSlotID(), (int)source);
1296 fprintf(ci, "%s", source==TUNER_A ? "A" : "B"); // configure CI data source (TunerA, TunerB)
1299 eDebug("CI Slot %d setSource(%d)", getSlotID(), (int)source);
1303 eAutoInitP0<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");