From 0a5a7893a5d396503628a3e7997ae550ff2597ac Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sun, 2 Apr 2017 10:08:49 +0200 Subject: [PATCH] Detecting whether a particular CAM actually decrypts a given channel is now done separately for each receiver --- HISTORY | 2 ++ device.c | 82 ++++++++++++++++++++++++++---------------------------- device.h | 4 +-- receiver.c | 5 +++- receiver.h | 5 +++- 5 files changed, 50 insertions(+), 48 deletions(-) diff --git a/HISTORY b/HISTORY index dd2fd0fc..0350a500 100644 --- a/HISTORY +++ b/HISTORY @@ -8938,3 +8938,5 @@ Video Disk Recorder Revision History The members of cEvent have been slightly rearranged to minimize the memory requirements on both 32 and 64 bit systems. - The file 'cam.data' is no longer written if it is read-only. +- Detecting whether a particular CAM actually decrypts a given channel is now + done separately for each receiver. diff --git a/device.c b/device.c index 247e8c56..1c7f2225 100644 --- a/device.c +++ b/device.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.c 4.11 2017/03/27 14:02:54 kls Exp $ + * $Id: device.c 4.12 2017/04/02 10:08:49 kls Exp $ */ #include "device.h" @@ -89,8 +89,6 @@ cDevice::cDevice(void) nitFilter = NULL; camSlot = NULL; - startScrambleDetection = 0; - scramblingTimeout = 0; occupiedTimeout = 0; @@ -253,7 +251,7 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView if (CamSlot->ModuleStatus() == msReady) { if (CamSlot->ProvidesCa(Channel->Caids())) { if (!ChannelCamRelations.CamChecked(Channel->GetChannelID(), CamSlot->MasterSlotNumber())) { - SlotPriority[CamSlot->Index()] = CamSlot->Priority(); + SlotPriority[CamSlot->Index()] = CamSlot->MtdActive() ? IDLEPRIORITY : CamSlot->Priority(); // we don't need to take the priority into account here for MTD CAM slots, because they can be used with several devices in parallel NumUsableSlots++; } } @@ -1652,50 +1650,47 @@ bool cDevice::Receiving(bool Dummy) const void cDevice::Action(void) { - time_t LastScrambledPacket = 0; if (Running() && OpenDvr()) { while (Running()) { // Read data from the DVR device: uchar *b = NULL; if (GetTSPacket(b)) { if (b) { - int Pid = TsPid(b); - // Check whether the TS packets are scrambled: - bool DetachReceivers = false; - bool DescramblingOk = false; - int CamSlotNumber = 0; - cCamSlot *cs = NULL; - if (startScrambleDetection) { - cs = CamSlot(); - CamSlotNumber = cs ? cs->MasterSlotNumber() : 0; - if (CamSlotNumber) { - if (LastScrambledPacket < startScrambleDetection) - LastScrambledPacket = startScrambleDetection; - time_t Now = time(NULL); - if (TsIsScrambled(b)) { - LastScrambledPacket = Now; - if (Now - startScrambleDetection > scramblingTimeout) - DetachReceivers = true; - } - if (Now - LastScrambledPacket > TS_SCRAMBLING_TIME_OK) - DescramblingOk = true; - } - } // Distribute the packet to all attached receivers: Lock(); + int Pid = TsPid(b); + bool IsScrambled = TsIsScrambled(b); for (int i = 0; i < MAXRECEIVERS; i++) { - if (receiver[i] && receiver[i]->WantsPid(Pid)) { - if (DetachReceivers && cs && (!cs->IsActivating() || receiver[i]->Priority() >= LIVEPRIORITY)) { - dsyslog("CAM %d: won't decrypt channel %s, detaching receiver", CamSlotNumber, *receiver[i]->ChannelID().ToString()); - ChannelCamRelations.SetChecked(receiver[i]->ChannelID(), CamSlotNumber); - Detach(receiver[i]); - } - else - receiver[i]->Receive(b, TS_SIZE); - if (DescramblingOk && receiver[i]->ChannelID().Valid()) { - dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *receiver[i]->ChannelID().ToString()); - ChannelCamRelations.SetDecrypt(receiver[i]->ChannelID(), CamSlotNumber); - startScrambleDetection = 0; + cReceiver *Receiver = receiver[i]; + if (Receiver && Receiver->WantsPid(Pid)) { + Receiver->Receive(b, TS_SIZE); + // Check whether the TS packet is scrambled: + if (Receiver->startScrambleDetection) { + if (cCamSlot *cs = CamSlot()) { + int CamSlotNumber = cs->MasterSlotNumber(); + if (Receiver->lastScrambledPacket < Receiver->startScrambleDetection) + Receiver->lastScrambledPacket = Receiver->startScrambleDetection; + time_t Now = time(NULL); + if (IsScrambled) { + Receiver->lastScrambledPacket = Now; + if (Now - Receiver->startScrambleDetection > Receiver->scramblingTimeout) { + if (!cs->IsActivating() || Receiver->Priority() >= LIVEPRIORITY) { + if (Receiver->ChannelID().Valid()) { + dsyslog("CAM %d: won't decrypt channel %s, detaching receiver", CamSlotNumber, *Receiver->ChannelID().ToString()); + ChannelCamRelations.SetChecked(Receiver->ChannelID(), CamSlotNumber); + } + Detach(Receiver); + } + } + } + else if (Now - Receiver->lastScrambledPacket > TS_SCRAMBLING_TIME_OK) { + if (Receiver->ChannelID().Valid()) { + dsyslog("CAM %d: decrypts channel %s", CamSlotNumber, *Receiver->ChannelID().ToString()); + ChannelCamRelations.SetDecrypt(Receiver->ChannelID(), CamSlotNumber); + } + Receiver->startScrambleDetection = 0; + } + } } } } @@ -1756,12 +1751,13 @@ bool cDevice::AttachReceiver(cReceiver *Receiver) if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver camSlot->StartDecrypting(); if (CamSlots.NumReadyMasterSlots() > 1) { // don't try different CAMs if there is only one - startScrambleDetection = time(NULL); - scramblingTimeout = TS_SCRAMBLING_TIMEOUT; + Receiver->startScrambleDetection = time(NULL); + Receiver->scramblingTimeout = TS_SCRAMBLING_TIMEOUT; bool KnownToDecrypt = ChannelCamRelations.CamDecrypt(Receiver->ChannelID(), camSlot->MasterSlotNumber()); if (KnownToDecrypt) - scramblingTimeout *= 10; // give it time to receive ECM/EMM - dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->SlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), scramblingTimeout); + Receiver->scramblingTimeout *= 10; // give it time to receive ECM/EMM + if (Receiver->ChannelID().Valid()) + dsyslog("CAM %d: %sknown to decrypt channel %s (scramblingTimeout = %ds)", camSlot->MasterSlotNumber(), KnownToDecrypt ? "" : "not ", *Receiver->ChannelID().ToString(), Receiver->scramblingTimeout); } } Start(); diff --git a/device.h b/device.h index 581c187a..7e3592b1 100644 --- a/device.h +++ b/device.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: device.h 4.4 2017/02/21 13:23:24 kls Exp $ + * $Id: device.h 4.5 2017/04/02 10:08:49 kls Exp $ */ #ifndef __DEVICE_H @@ -426,8 +426,6 @@ public: // Common Interface facilities: private: - time_t startScrambleDetection; - int scramblingTimeout; cCamSlot *camSlot; public: virtual bool HasCi(void); diff --git a/receiver.c b/receiver.c index dd61fd65..ef3a5cd1 100644 --- a/receiver.c +++ b/receiver.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: receiver.c 4.2 2017/02/21 10:59:27 kls Exp $ + * $Id: receiver.c 4.3 2017/04/02 10:08:49 kls Exp $ */ #include "receiver.h" @@ -16,6 +16,9 @@ cReceiver::cReceiver(const cChannel *Channel, int Priority) device = NULL; SetPriority(Priority); numPids = 0; + lastScrambledPacket = 0; + startScrambleDetection = 0; + scramblingTimeout = 0; SetPids(Channel); } diff --git a/receiver.h b/receiver.h index 09da8cda..0ba8cb44 100644 --- a/receiver.h +++ b/receiver.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: receiver.h 4.1 2015/09/05 11:42:47 kls Exp $ + * $Id: receiver.h 4.2 2017/04/02 10:08:49 kls Exp $ */ #ifndef __RECEIVER_H @@ -22,6 +22,9 @@ private: int priority; int pids[MAXRECEIVEPIDS]; int numPids; + time_t lastScrambledPacket; + time_t startScrambleDetection; + int scramblingTimeout; bool WantsPid(int Pid); protected: cDevice *Device(void) { return device; }