X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/c598ff78dac60b446b42ae23f3128c518b76642a..ce98272b7475d1bcd6a8ef78b17f17715ff48589:/lib/dvb_ci/dvbci.cpp diff --git a/lib/dvb_ci/dvbci.cpp b/lib/dvb_ci/dvbci.cpp index a0166355..883fb5a4 100644 --- a/lib/dvb_ci/dvbci.cpp +++ b/lib/dvb_ci/dvbci.cpp @@ -200,43 +200,39 @@ int eDVBCIInterfaces::cancelEnq(int slotid) void eDVBCIInterfaces::ciRemoved(eDVBCISlot *slot) { - eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count); - for (PMTHandlerList::iterator it(m_pmt_handlers.begin()); - it != m_pmt_handlers.end(); ++it) + if (slot->use_count) { - eServiceReferenceDVB ref; - it->pmthandler->getServiceReference(ref); - eDebugCI("check %s cislot %p %d\n", ref.toString().c_str(), it->cislot, it->cislot?it->cislot->getSlotID() : -1); - slot->removeService(ref.getServiceID().get()); - if (slot->use_count && !--slot->use_count) + eDebug("CI Slot %d: removed... usecount %d", slot->getSlotID(), slot->use_count); + for (PMTHandlerList::iterator it(m_pmt_handlers.begin()); + it != m_pmt_handlers.end(); ++it) { - if (slot->linked_next) - slot->linked_next->setSource(slot->current_source); - else // last CI in chain - setInputSource(slot->current_tuner, slot->current_source); - if (it->cislot == slot) // remove the base slot - { it->cislot = slot->linked_next; - eDebugCI("base removed.. so slot is now %p", it->cislot); - } - else + else if (it->cislot) { - eDebugCI("not base removed.. %d", it->cislot->getSlotID()); - eDVBCISlot *tmp = it->cislot; - while(tmp->linked_next != slot) - tmp = tmp->linked_next; - ASSERT(tmp); - if (slot->linked_next) - tmp->linked_next = slot->linked_next; - else - tmp->linked_next = 0; + eDVBCISlot *prevSlot = it->cislot, *hSlot = it->cislot->linked_next; + while (hSlot) + { + if (hSlot == slot) { + prevSlot->linked_next = slot->linked_next; + break; + } + prevSlot = hSlot; + hSlot = hSlot->linked_next; + } } - slot->linked_next=0; - slot->user_mapped=false; } + if (slot->linked_next) + slot->linked_next->setSource(slot->current_source); + else // last CI in chain + setInputSource(slot->current_tuner, slot->current_source); + slot->linked_next = 0; + slot->use_count=0; + slot->plugged=true; + slot->user_mapped=false; + slot->removeService(0xFFFF); + recheckPMTHandlers(); } - recheckPMTHandlers(); } static bool canDescrambleMultipleServices(int slotid) @@ -268,22 +264,22 @@ void eDVBCIInterfaces::recheckPMTHandlers() eDVBCISlot *tmp = it->cislot; eDVBServicePMTHandler *pmthandler = it->pmthandler; eDVBServicePMTHandler::program p; - bool first_plugged_cis_exist = false; + bool plugged_cis_exist = false; pmthandler->getServiceReference(ref); pmthandler->getService(service); eDebugCI("recheck %p %s", pmthandler, ref.toString().c_str()); for (eSmartPtrList::iterator ci_it(m_slots.begin()); ci_it != m_slots.end(); ++ci_it) - if (ci_it->first_plugged && ci_it->getCAManager()) + if (ci_it->plugged && ci_it->getCAManager()) { - eDebug("Slot %d first plugged", ci_it->getSlotID()); - ci_it->first_plugged = false; - first_plugged_cis_exist = true; + eDebug("Slot %d plugged", ci_it->getSlotID()); + ci_it->plugged = false; + plugged_cis_exist = true; } // check if this pmt handler has already assigned CI(s) .. and this CI(s) are already running - if (!first_plugged_cis_exist) + if (!plugged_cis_exist) { while(tmp) { @@ -556,6 +552,7 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) if (it != m_pmt_handlers.end()) { eDVBCISlot *slot = it->cislot; + eDVBCISlot *base_slot = slot; eDVBServicePMTHandler *pmthandler = it->pmthandler; m_pmt_handlers.erase(it); @@ -579,20 +576,17 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) while(slot) { + eDVBCISlot *next = slot->linked_next; if (!sameServiceExist) { - if (slot->getNumOfServices() > 1) - { - eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt", - service_to_remove.toString().c_str()); - std::vector caids; - caids.push_back(0xFFFF); - slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service - } + eDebug("[eDVBCIInterfaces] remove last pmt handler for service %s send empty capmt", + service_to_remove.toString().c_str()); + std::vector caids; + caids.push_back(0xFFFF); + slot->sendCAPMT(pmthandler, caids); // send a capmt without caids to remove a running service slot->removeService(service_to_remove.getServiceID().get()); } - eDVBCISlot *next = slot->linked_next; if (!--slot->use_count) { if (slot->linked_next) @@ -600,9 +594,7 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) else setInputSource(slot->current_tuner, slot->current_source); - if (it->cislot == slot) // remove the base slot - it->cislot = slot->linked_next; - else + if (base_slot != slot) { eDVBCISlot *tmp = it->cislot; while(tmp->linked_next != slot) @@ -613,6 +605,8 @@ void eDVBCIInterfaces::removePMTHandler(eDVBServicePMTHandler *pmthandler) else tmp->linked_next = 0; } + else // removed old base slot.. update ptr + base_slot = slot->linked_next; slot->linked_next = 0; slot->user_mapped = false; } @@ -897,14 +891,14 @@ RESULT eDVBCIInterfaces::setDescrambleRules(int slotid, SWIG_PYOBJECT(ePyObject) { --size; ePyObject caid = PyList_GET_ITEM(caid_list, size); - if (!PyInt_Check(caid)) + if (!PyLong_Check(caid)) { char buf[255]; snprintf(buf, 255, "eDVBCIInterfaces::setDescrambleRules entry in caid list is not a long it is '%s'!!", PyObject_TypeStr(caid)); PyErr_SetString(PyExc_StandardError, buf); return -1; } - int tmpcaid = PyInt_AsLong(caid); + int tmpcaid = PyLong_AsLong(caid); if (tmpcaid > 0 && tmpcaid < 0x10000) slot->possible_caids.insert(tmpcaid); else @@ -926,15 +920,26 @@ PyObject *eDVBCIInterfaces::readCICaIds(int slotid) { int idx=0; eDVBCICAManagerSession *ca_manager = slot->getCAManager(); - const std::vector &ci_caids = ca_manager->getCAIDs(); - ePyObject list = PyList_New(ci_caids.size()); - for (std::vector::const_iterator it = ci_caids.begin(); it != ci_caids.end(); ++it) - PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it)); + const std::vector *ci_caids = ca_manager ? &ca_manager->getCAIDs() : 0; + ePyObject list = PyList_New(ci_caids ? ci_caids->size() : 0); + if (ci_caids) + { + for (std::vector::const_iterator it = ci_caids->begin(); it != ci_caids->end(); ++it) + PyList_SET_ITEM(list, idx++, PyLong_FromLong(*it)); + } return list; } return 0; } +int eDVBCIInterfaces::setCIClockRate(int slotid, int rate) +{ + eDVBCISlot *slot = getSlot(slotid); + if (slot) + return slot->setClockRate(rate); + return -1; +} + int eDVBCISlot::send(const unsigned char *data, size_t len) { int res=0; @@ -1030,7 +1035,7 @@ eDVBCISlot::eDVBCISlot(eMainloop *context, int nr) use_count = 0; linked_next = 0; user_mapped = false; - first_plugged = true; + plugged = true; slotid = nr; @@ -1183,10 +1188,11 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vector::iterator it = running_services.find(program_number); + bool sendEmpty = caids.size() == 1 && caids[0] == 0xFFFF; if ( it != running_services.end() && (pmt_version == it->second) && - !(caids.size() == 1 && caids[0] == 0xFFFF) ) + !sendEmpty ) { eDebug("[eDVBCISlot] dont send self capmt version twice"); return -1; @@ -1211,7 +1217,7 @@ int eDVBCISlot::sendCAPMT(eDVBServicePMTHandler *pmthandler, const std::vectorsendCAPMT(raw_data + hlen, wp - hlen); running_services[program_number] = pmt_version; @@ -1320,4 +1329,21 @@ int eDVBCISlot::setSource(data_source source) return 0; } +int eDVBCISlot::setClockRate(int rate) +{ + char buf[64]; + snprintf(buf, 64, "/proc/stb/tsmux/ci%d_tsclk", slotid); + FILE *ci = fopen(buf, "wb"); + if (ci) + { + if (rate) + fprintf(ci, "high"); + else + fprintf(ci, "normal"); + fclose(ci); + return 0; + } + return -1; +} + eAutoInitP0 init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");