From a84defe86f2331d42c06abeba17fd4aebe359d94 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Thu, 2 Jan 2014 10:47:08 +0100 Subject: [PATCH] Added support for buffered CAM decryption --- ci.c | 6 ++++-- ci.h | 34 ++++++++++++++++++++++++---------- device.c | 8 +++++++- device.h | 9 ++++++++- dvbdevice.c | 8 +++++--- 5 files changed, 48 insertions(+), 17 deletions(-) diff --git a/ci.c b/ci.c index 2d9735e5..e2881fed 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 3.3 2014/01/01 12:33:27 kls Exp $ + * $Id: ci.c 3.4 2014/01/02 10:31:12 kls Exp $ */ #include "ci.h" @@ -2014,8 +2014,10 @@ bool cCamSlot::IsDecrypting(void) return false; } -void cCamSlot::Decrypt(uchar *Data, int Count) +uchar *cCamSlot::Decrypt(uchar *Data, int &Count) { + Count = TS_SIZE; + return Data; } // --- cChannelCamRelation --------------------------------------------------- diff --git a/ci.h b/ci.h index 1d6f5d1f..11237121 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 3.2 2014/01/01 12:13:04 kls Exp $ + * $Id: ci.h 3.3 2014/01/02 10:14:39 kls Exp $ */ #ifndef __CI_H @@ -235,19 +235,33 @@ public: ///< Clears the list of CA_PMT entries and tells the CAM to stop decrypting. virtual bool IsDecrypting(void); ///< Returns true if the CAM in this slot is currently used for decrypting. - virtual void Decrypt(uchar *Data, int Count); + virtual uchar *Decrypt(uchar *Data, int &Count); ///< If this is a CAM slot that can be freely assigned to any device, ///< but will not be directly inserted into the full TS data stream ///< in hardware, it can implement this function to be given access ///< to the data in the device's TS buffer. Data points to a buffer - ///< of Count bytes of TS packets. The first byte in Data is guaranteed - ///< to be a TS_SYNC_BYTE. This function may decrypt as many TS packets - ///< in Data as it wants, but it must decrypt at least the very first - ///< TS packet. Only this very first TS packet will be further processed - ///< after the call to this function. The next call will be done with - ///< Data pointing to the TS packet immediately following the previous - ///< one. However, it can not be assumed that a call to Decrypt() with - ///< a Data pointer of P will be followed by a call with P + TS_SIZE. + ///< of Count bytes of TS data. The first byte in Data is guaranteed + ///< to be a TS_SYNC_BYTE. + ///< There are three possible ways a CAM can handle decryption: + ///< 1. If the full TS data is physically routed through the CAM in hardware, + ///< there is no need to reimplement this function. + ///< The default implementation simply sets Count to TS_SIZE and returns Data. + ///< 2. If the CAM works directly on Data and decrypts the TS "in place" it + ///< shall decrypt at least the very first TS packet in Data, set Count to + ///< TS_SIZE and return Data. It may decrypt as many TS packets in Data as it + ///< wants, but it must decrypt at least the very first TS packet. Only this + ///< very first TS packet will be further processed after the call to this + ///< function. The next call will be done with Data pointing to the TS packet + ///< immediately following the previous one. + ///< 3. If the CAM needs to copy the data into a buffer of its own, and/or send + ///< the data to some file handle for processing and later retrieval, it shall + ///< set Count to the number of bytes it has read from Data and return a pointer + ///< to the next available decrypted TS packet (which will *not* be in the + ///< memory area pointed to by Data, but rather in some buffer that is under + ///< the CAM's control). If no decrypted TS packet is currently available, NULL + ///< shall be returned. If no data from Data can currently be processed, Count + ///< shall be set to 0 and the same Data pointer will be offered in the next + ///< call to Decrypt(). ///< A derived class that implements this function will also need ///< to set the ReceiveCaPids parameter in the call to the base class ///< constructor to true in order to receive the CA pid data. diff --git a/device.c b/device.c index 4db3ddd7..84caf4e1 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 3.6 2014/01/01 11:51:17 kls Exp $ + * $Id: device.c 3.7 2014/01/02 10:31:58 kls Exp $ */ #include "device.h" @@ -1791,3 +1791,9 @@ uchar *cTSBuffer::Get(int *Available) } return NULL; } + +void cTSBuffer::Skip(int Count) +{ + ringBuffer->Del(Count); + delivered = false; +} diff --git a/device.h b/device.h index 1cbd6cc9..368d5cfa 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 3.7 2013/12/28 12:59:13 kls Exp $ + * $Id: device.h 3.8 2014/01/02 10:47:08 kls Exp $ */ #ifndef __DEVICE_H @@ -837,6 +837,13 @@ public: ///< there are at least TS_SIZE bytes in the buffer. Otherwise NULL will be ///< returned and the value in Available (if given) is undefined. ///< Each call to Get() returns a pointer to the next TS packet in the buffer. + void Skip(int Count); + ///< If after a call to Get() more or less than TS_SIZE of the available data + ///< has been processed, a call to Skip() with the number of processed bytes + ///< will disable the automatic incrementing of the data pointer as described + ///< in Get() and skip the given number of bytes instead. Count may be 0 if the + ///< caller wants the previous TS packet to be delivered again in the next call + ///< to Get(). }; #endif //__DEVICE_H diff --git a/dvbdevice.c b/dvbdevice.c index 481489b3..62f29dac 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 3.7 2014/01/01 14:14:32 kls Exp $ + * $Id: dvbdevice.c 3.8 2014/01/02 10:30:15 kls Exp $ */ #include "dvbdevice.h" @@ -1673,8 +1673,10 @@ bool cDvbDevice::GetTSPacket(uchar *&Data) if (tsBuffer) { int Available; Data = tsBuffer->Get(&Available); - if (Data && CamSlot()) - CamSlot()->Decrypt(Data, Available); + if (Data && CamSlot()) { + Data = CamSlot()->Decrypt(Data, Available); + tsBuffer->Skip(Available); + } return true; } return false;