diff --git a/ci.c b/ci.c index e4f43209..a788781b 100644 --- a/ci.c +++ b/ci.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 4.7 2017/03/18 15:20:27 kls Exp $ + * $Id: ci.c 4.8 2017/03/23 14:30:56 kls Exp $ */ #include "ci.h" @@ -2205,6 +2205,8 @@ void cCamSlot::BuildCaPmts(uint8_t CmdId, cCiCaPmtList &CaPmtList, cMtdMapper *M } } } + else if (CmdId == CPCI_NOT_SELECTED) + CaPmtList.Add(CmdId, 0, 0, 0, NULL); } } @@ -2343,7 +2345,7 @@ void cCamSlot::AddChannel(const cChannel *Channel) #define QUERY_REPLY_WAIT 100 // ms to wait between checks for a reply -bool cCamSlot::CanDecrypt(const cChannel *Channel) +bool cCamSlot::CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper) { if (Channel->Ca() < CA_ENCRYPTED_MIN) return true; // channel not encrypted @@ -2361,6 +2363,8 @@ bool cCamSlot::CanDecrypt(const cChannel *Channel) CaPmt.AddPid(*Dpid, STREAM_TYPE_PRIVATE); for (const int *Spid = Channel->Spids(); *Spid; Spid++) CaPmt.AddPid(*Spid, STREAM_TYPE_PRIVATE); + if (MtdMapper) + CaPmt.MtdMapPids(MtdMapper); cas->SendPMT(&CaPmt); cTimeMs Timeout(QUERY_REPLY_TIMEOUT); do { @@ -2385,7 +2389,11 @@ void cCamSlot::StartDecrypting(void) void cCamSlot::StopDecrypting(void) { cMutexLock MutexLock(&mutex); - caProgramList.Clear(); + if (caProgramList.Count()) { + caProgramList.Clear(); + if (!dynamic_cast(this)) + SendCaPmt(CPCI_NOT_SELECTED); + } } bool cCamSlot::IsDecrypting(void) diff --git a/ci.h b/ci.h index 78d4087d..0e8253d9 100644 --- a/ci.h +++ b/ci.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.h 4.4 2017/03/19 10:48:14 kls Exp $ + * $Id: ci.h 4.5 2017/03/23 14:23:33 kls Exp $ */ #ifndef __CI_H @@ -314,7 +314,7 @@ public: ///< If the source or transponder of the channel are different than ///< what was given in a previous call to AddChannel(), any previously ///< added PIDs will be cleared. - virtual bool CanDecrypt(const cChannel *Channel); + virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper = NULL); ///< Returns true if there is a CAM in this slot that is able to decrypt ///< the given Channel (or at least claims to be able to do so). ///< Since the QUERY/REPLY mechanism for CAMs is pretty unreliable (some @@ -325,11 +325,18 @@ public: ///< to the initial QUERY will perform this check at all. CAMs that never ///< replied to the initial QUERY are assumed not to be able to handle ///< more than one channel at a time. + ///< If MtdMapper is given, all SIDs and PIDs will be mapped accordingly. virtual void StartDecrypting(void); - ///< Triggers sending all currently active CA_PMT entries to the CAM, - ///< so that it will start decrypting. + ///< Sends all CA_PMT entries to the CAM that have been modified since the + ///< last call to this function. This includes CA_PMTs that have been + ///< added or activated, as well as ones that have been deactivated. + ///< StartDecrypting() will be called whenever a PID is activated or + ///< deactivated. virtual void StopDecrypting(void); ///< Clears the list of CA_PMT entries and tells the CAM to stop decrypting. + ///< Note that this function is only called when there are no more PIDs for + ///< the CAM to decrypt. There is no symmetry between StartDecrypting() and + ///< StopDecrypting(). virtual bool IsDecrypting(void); ///< Returns true if the CAM in this slot is currently used for decrypting. virtual uchar *Decrypt(uchar *Data, int &Count); diff --git a/device.c b/device.c index b6a6ee10..6f3a155d 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.8 2017/03/18 15:45:53 kls Exp $ + * $Id: device.c 4.9 2017/03/23 14:19:59 kls Exp $ */ #include "device.h" @@ -320,8 +320,8 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView if (!NumUsableSlots) break; // no CAM necessary, so just one loop over the devices } - if (d && !Query) { - if (NeedsDetachReceivers) + if (d) { + if (!Query && NeedsDetachReceivers) d->DetachAllReceivers(); if (s) { // Some of the following statements could probably be combined, but let's keep them @@ -333,9 +333,11 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView } else { // device d has a CAM slot, but it's not the right one - d->CamSlot()->Assign(NULL); - s = s->MtdSpawn(); - s->Assign(d); + if (!Query) { + d->CamSlot()->Assign(NULL); + s = s->MtdSpawn(); + s->Assign(d); + } } } else { @@ -343,9 +345,10 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView if (s->Device() != d) { // CAM slot s is currently assigned to a different device than d if (Priority > s->Priority()) { - s->Device()->DetachAllReceivers(); - d->CamSlot()->Assign(NULL); - s->Assign(d); + if (!Query) { + d->CamSlot()->Assign(NULL); + s->Assign(d); + } } else { d = NULL; @@ -359,8 +362,10 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView else { if (s != d->CamSlot()) { // device d has a CAM slot, but it's not the right one - d->CamSlot()->Assign(NULL); - s->Assign(d); + if (!Query) { + d->CamSlot()->Assign(NULL); + s->Assign(d); + } } else { // device d already has a proper CAM slot, so nothing to do here @@ -372,16 +377,20 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView // device d has no CAM slot, ... if (s->MtdActive()) { // ... so we assign s with MTD support - s = s->MtdSpawn(); - s->Assign(d); + if (!Query) { + s = s->MtdSpawn(); + s->Assign(d); + } } else { // CAM slot s has no MTD support ... if (s->Device()) { // ... but it is assigned to a different device, so we reassign it to d if (Priority > s->Priority()) { - s->Device()->DetachAllReceivers(); - s->Assign(d); + if (!Query) { + s->Device()->DetachAllReceivers(); + s->Assign(d); + } } else { d = NULL; @@ -390,7 +399,8 @@ cDevice *cDevice::GetDevice(const cChannel *Channel, int Priority, bool LiveView } else { // ... and is not assigned to any device, so we just assign it to d - s->Assign(d); + if (!Query) + s->Assign(d); } } } diff --git a/mtd.c b/mtd.c index b3a6af96..a09f0162 100644 --- a/mtd.c +++ b/mtd.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: mtd.c 1.3 2017/03/19 14:20:22 kls Exp $ + * $Id: mtd.c 1.4 2017/03/23 14:34:53 kls Exp $ */ #include "mtd.h" @@ -262,10 +262,9 @@ bool cMtdCamSlot::ProvidesCa(const int *CaSystemIds) return MasterSlot()->ProvidesCa(CaSystemIds); } -bool cMtdCamSlot::CanDecrypt(const cChannel *Channel) +bool cMtdCamSlot::CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper) { - //TODO PID mapping? - return MasterSlot()->CanDecrypt(Channel); + return MasterSlot()->CanDecrypt(Channel, mtdMapper); } void cMtdCamSlot::StartDecrypting(void) @@ -277,15 +276,12 @@ void cMtdCamSlot::StartDecrypting(void) void cMtdCamSlot::StopDecrypting(void) { cCamSlot::StopDecrypting(); + if (!MasterSlot()->IsDecrypting()) + MasterSlot()->StopDecrypting(); mtdMapper->Clear(); clearBuffer = true; } -bool cMtdCamSlot::IsDecrypting(void) -{ - return cCamSlot::IsDecrypting(); -} - uchar *cMtdCamSlot::Decrypt(uchar *Data, int &Count) { // Send data to CAM: diff --git a/mtd.h b/mtd.h index b9cf55ae..15d29b83 100644 --- a/mtd.h +++ b/mtd.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: mtd.h 1.3 2017/03/19 13:32:48 kls Exp $ + * $Id: mtd.h 1.4 2017/03/23 12:48:22 kls Exp $ */ #ifndef __MTD_H @@ -166,10 +166,9 @@ public: cMtdMapper *MtdMapper(void) { return mtdMapper; } virtual bool RepliesToQuery(void); virtual bool ProvidesCa(const int *CaSystemIds); - virtual bool CanDecrypt(const cChannel *Channel); + virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper = NULL); virtual void StartDecrypting(void); virtual void StopDecrypting(void); - virtual bool IsDecrypting(void); virtual uchar *Decrypt(uchar *Data, int &Count); int PutData(const uchar *Data, int Count); int PutCat(const uchar *Data, int Count);