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)
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<eDVBCISlot>::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)
{
if (it != m_pmt_handlers.end())
{
eDVBCISlot *slot = it->cislot;
+ eDVBCISlot *base_slot = slot;
eDVBServicePMTHandler *pmthandler = it->pmthandler;
m_pmt_handlers.erase(it);
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<uint16_t> 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<uint16_t> 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)
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)
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;
}
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;
use_count = 0;
linked_next = 0;
user_mapped = false;
- first_plugged = true;
+ plugged = true;
slotid = nr;
uint16_t program_number = ref.getServiceID().get();
std::map<uint16_t, uint8_t>::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;
capmt.append(*i++);
}
capmt.writeToBuffer(raw_data);
-#if 1
+
// begin calc capmt length
int wp=0;
int hlen;
hlen = 4;
}
// end calc capmt length
-// eDebug("ca_manager %p dump capmt:", ca_manager);
-// for(int i=0;i<wp;i++)
-// eDebugNoNewLine("%02x ", raw_data[i]);
-// eDebug("");
-#endif
- if (caids.size() == 1 && caids[0] == 0xFFFF)
+
+ if (sendEmpty)
{
// eDebugNoNewLine("SEND EMPTY CAPMT.. old version is %02x", raw_data[hlen+3]);
+ if (sendEmpty && running_services.size() == 1) // check if this is the capmt for the last running service
+ raw_data[hlen] = 0x03; // send only instead of update... because of strange effects with alphacrypt
raw_data[hlen+3] &= ~0x3E;
raw_data[hlen+3] |= ((pmt_version+1) & 0x1F) << 1;
// eDebug(" new version is %02x", raw_data[hlen+3]);
}
+// eDebug("ca_manager %p dump capmt:", ca_manager);
+// for(int i=0;i<wp;i++)
+// eDebugNoNewLine("%02x ", raw_data[i]);
+// eDebug("");
+
//dont need tag and lenfield
ca_manager->sendCAPMT(raw_data + hlen, wp - hlen);
running_services[program_number] = pmt_version;
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<eDVBCIInterfaces> init_eDVBCIInterfaces(eAutoInitNumbers::dvb, "CI Slots");