diff options
| -rw-r--r-- | HISTORY | 7 | ||||
| -rw-r--r-- | ci.c | 36 | ||||
| -rw-r--r-- | ci.h | 12 | ||||
| -rw-r--r-- | device.c | 6 | ||||
| -rw-r--r-- | pat.c | 46 | ||||
| -rw-r--r-- | pat.h | 12 | ||||
| -rw-r--r-- | receiver.c | 24 | ||||
| -rw-r--r-- | receiver.h | 8 | 
8 files changed, 135 insertions, 16 deletions
| @@ -8032,7 +8032,7 @@ Video Disk Recorder Revision History    the last replayed recording (if any) by pressing Ok repeatedly in the Recordings    menu. -2013-12-29: Version 2.1.3 +2014-01-01: Version 2.1.3  - Changed the return value of cPositioner::HorizonLongitude() to 0 in case the    latitude of the antenna location is beyond +/-81 degrees. @@ -8091,7 +8091,10 @@ Video Disk Recorder Revision History    Skyttä).  - The new function cCamSlot::Decrypt() can be used by derived classes to implement a    CAM slot that can be freely assigned to any device, without being directly inserted -  into the full TS data stream in hardware. +  into the full TS data stream in hardware. A derived class that implements Decrypt() +  will also need to set the new parameter ReceiveCaPids in the call to the cCamSlot +  base class constructor to true, in order to receive the CA pid TS packets that +  contain data necessary for decrypting.  - Many member functions of cCamSlot have been made virtual to allow for easier    implementation of derived classes.  - cTSBuffer now provides the number of available bytes in its Get() function. @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: ci.c 3.2 2013/12/29 15:51:08 kls Exp $ + * $Id: ci.c 3.3 2014/01/01 12:33:27 kls Exp $   */  #include "ci.h" @@ -19,6 +19,7 @@  #include <unistd.h>  #include "device.h"  #include "pat.h" +#include "receiver.h"  #include "tools.h"  // Set these to 'true' for debug output: @@ -102,6 +103,16 @@ static char *GetString(int &Length, const uint8_t **Data)    return NULL;  } +// --- cCaPidReceiver -------------------------------------------------------- + +// A dummy receiver, just used to make the device receive the CA pids. + +class cCaPidReceiver : public cReceiver { +public: +  virtual ~cCaPidReceiver() { Detach(); } +  virtual void Receive(uchar *Data, int Length) {} +  }; +  // --- cTPDU -----------------------------------------------------------------  #define MAX_TPDU_SIZE  2048 @@ -570,7 +581,7 @@ bool cCiApplicationInformation::EnterMenu(void)  #define CPCI_QUERY            0x03  #define CPCI_NOT_SELECTED     0x04 -class cCiCaPmt : public cListObject { +class cCiCaPmt {    friend class cCiConditionalAccessSupport;  private:    uint8_t cmdId; @@ -1553,9 +1564,10 @@ cCamSlots CamSlots;  #define MODULE_CHECK_INTERVAL 500 // ms  #define MODULE_RESET_TIMEOUT    2 // s -cCamSlot::cCamSlot(cCiAdapter *CiAdapter) +cCamSlot::cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids)  {    ciAdapter = CiAdapter; +  caPidReceiver = ReceiveCaPids ? new cCaPidReceiver : NULL;    slotIndex = -1;    lastModuleStatus = msReset; // avoids initial reset log message    resetTime = 0; @@ -1572,6 +1584,7 @@ cCamSlot::cCamSlot(cCiAdapter *CiAdapter)  cCamSlot::~cCamSlot()  { +  delete caPidReceiver;    CamSlots.Del(this, false);    DeleteAllConnections();  } @@ -1802,6 +1815,10 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)       const int *CaSystemIds = cas->GetCaSystemIds();       if (CaSystemIds && *CaSystemIds) {          if (caProgramList.Count()) { +           if (caPidReceiver && caPidReceiver->NumPids()) { +              if (cDevice *d = Device()) +                 d->Detach(caPidReceiver); +              }             for (int Loop = 1; Loop <= 2; Loop++) {                 for (cCiCaProgramData *p = caProgramList.First(); p; p = caProgramList.Next(p)) {                     if (p->modified || resendPmt) { @@ -1814,6 +1831,15 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)                               }                            }                        if ((Loop == 1) != Active) { // first remove, then add +                         if (caPidReceiver) { +                            int CaPids[MAXRECEIVEPIDS + 1]; +                            if (GetCaPids(source, transponder, p->programNumber, CaSystemIds, MAXRECEIVEPIDS + 1, CaPids) > 0) { +                               if (Loop == 1) +                                  caPidReceiver->DelPids(CaPids); +                               else +                                  caPidReceiver->AddPids(CaPids); +                               } +                            }                           if (cas->RepliesToQuery())                              CaPmt.SetListManagement(Active ? CPLM_ADD : CPLM_UPDATE);                           if (Active || cas->RepliesToQuery()) @@ -1823,6 +1849,10 @@ void cCamSlot::SendCaPmt(uint8_t CmdId)                        }                     }                 } +           if (caPidReceiver && caPidReceiver->NumPids()) { +              if (cDevice *d = Device()) +                 d->AttachReceiver(caPidReceiver); +              }             resendPmt = false;             }          else { @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: ci.h 3.1 2013/12/28 13:20:08 kls Exp $ + * $Id: ci.h 3.2 2014/01/01 12:13:04 kls Exp $   */  #ifndef __CI_H @@ -121,6 +121,7 @@ class cTPDU;  class cCiTransportConnection;  class cCiSession;  class cCiCaProgramData; +class cReceiver;  class cCamSlot : public cListObject {    friend class cCiAdapter; @@ -129,6 +130,7 @@ private:    cMutex mutex;    cCondVar processed;    cCiAdapter *ciAdapter; +  cReceiver *caPidReceiver;    int slotIndex;    int slotNumber;    cCiTransportConnection *tc[MAX_CONNECTIONS_PER_CAM_SLOT + 1];  // connection numbering starts with 1 @@ -147,10 +149,13 @@ private:    void Write(cTPDU *TPDU);    cCiSession *GetSessionByResourceId(uint32_t ResourceId);  public: -  cCamSlot(cCiAdapter *CiAdapter); +  cCamSlot(cCiAdapter *CiAdapter, bool ReceiveCaPids = false);         ///< Creates a new CAM slot for the given CiAdapter.         ///< The CiAdapter will take care of deleting the CAM slot,         ///< so the caller must not delete it! +       ///< If ReceiveCaPids is true, the CAM slot will take care that the CA pids +       ///< of the selected programmes will be included in the TS data stream that +       ///< is presented to the Decrypt() function.    virtual ~cCamSlot();    bool Assign(cDevice *Device, bool Query = false);         ///< Assigns this CAM slot to the given Device, if this is possible. @@ -243,6 +248,9 @@ public:         ///< 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. +       ///< 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.    };  class cCamSlots : public cList<cCamSlot> {}; @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: device.c 3.5 2013/12/28 12:56:24 kls Exp $ + * $Id: device.c 3.6 2014/01/01 11:51:17 kls Exp $   */  #include "device.h" @@ -1666,7 +1666,7 @@ bool cDevice::AttachReceiver(cReceiver *Receiver)           Receiver->device = this;           receiver[i] = Receiver;           Unlock(); -         if (camSlot) { +         if (camSlot && Receiver->priority > MINPRIORITY) { // priority check to avoid an infinite loop with the CAM slot's caPidReceiver              camSlot->StartDecrypting();              startScrambleDetection = time(NULL);              } @@ -1697,7 +1697,7 @@ void cDevice::Detach(cReceiver *Receiver)        else if (receiver[i])           receiversLeft = true;        } -  if (camSlot) +  if (camSlot && Receiver->priority > MINPRIORITY) // priority check to avoid an infinite loop with the CAM slot's caPidReceiver       camSlot->StartDecrypting();    if (!receiversLeft)       Cancel(-1); @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: pat.c 2.19 2012/11/25 14:12:21 kls Exp $ + * $Id: pat.c 3.1 2014/01/01 12:02:39 kls Exp $   */  #include "pat.h" @@ -21,6 +21,7 @@  class cCaDescriptor : public cListObject {  private:    int caSystem; +  int caPid;    int esPid;    int length;    uchar *data; @@ -29,6 +30,7 @@ public:    virtual ~cCaDescriptor();    bool operator== (const cCaDescriptor &arg) const;    int CaSystem(void) { return caSystem; } +  int CaPid(void) { return caPid; }    int EsPid(void) { return esPid; }    int Length(void) const { return length; }    const uchar *Data(void) const { return data; } @@ -37,6 +39,7 @@ public:  cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)  {    caSystem = CaSystem; +  caPid = CaPid;    esPid = EsPid;    length = Length + 6;    data = MALLOC(uchar, length); @@ -79,6 +82,7 @@ public:    bool Empty(void) { return caDescriptors.Count() == 0; }    void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);    int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid); +  int GetCaPids(const int *CaSystemIds, int BufSize, int *Pids);    const int *CaIds(void) { return caIds; }    }; @@ -179,6 +183,30 @@ int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar    return -1;  } +int cCaDescriptors::GetCaPids(const int *CaSystemIds, int BufSize, int *Pids) +{ +  if (!CaSystemIds || !*CaSystemIds) +     return 0; +  if (BufSize > 0 && Pids) { +     int numPids = 0; +     for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) { +         const int *caids = CaSystemIds; +         do { +            if (d->CaSystem() == *caids) { +               if (numPids + 1 < BufSize) { +                  Pids[numPids++] = d->CaPid(); +                  Pids[numPids] = 0; +                  } +               else +                  return -1; +               } +            } while (*++caids); +         } +     return numPids; +     } +  return -1; +} +  // --- cCaDescriptorHandler --------------------------------------------------  class cCaDescriptorHandler : public cList<cCaDescriptors> { @@ -190,6 +218,7 @@ public:        // 1 if it is an all new descriptor with actual contents,        // and 2 if an existing descriptor was changed.    int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid); +  int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids);    };  int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors) @@ -220,6 +249,16 @@ int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int Serv    return 0;  } +int cCaDescriptorHandler::GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids) +{ +  cMutexLock MutexLock(&mutex); +  for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) { +      if (ca->Is(Source, Transponder, ServiceId)) +         return ca->GetCaPids(CaSystemIds, BufSize, Pids); +      } +  return 0; +} +  cCaDescriptorHandler CaDescriptorHandler;  int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid) @@ -227,6 +266,11 @@ int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSy    return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);  } +int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids) +{ +  return CaDescriptorHandler.GetCaPids(Source, Transponder, ServiceId, CaSystemIds, BufSize, Pids); +} +  // --- cPatFilter ------------------------------------------------------------  cPatFilter::cPatFilter(void) @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: pat.h 2.3 2013/02/16 15:20:24 kls Exp $ + * $Id: pat.h 3.1 2013/12/30 11:32:40 kls Exp $   */  #ifndef __PAT_H @@ -39,7 +39,13 @@ int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSy           ///< are copied that match one of the given CA system IDs.           ///< Returns the number of bytes copied into Data (0 if no CA descriptors are           ///< available), or -1 if BufSize was too small to hold all CA descriptors. -         ///< The return value tells whether these CA descriptors are to be used -         ///< for the individual streams. + +int GetCaPids(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, int *Pids); +         ///< Gets all CA pids for a given channel. +         ///< Copies all available CA pids from the CA descriptors for the given Source, Transponder and ServiceId +         ///< into the provided buffer at Pids (at most BufSize - 1 entries, the list will be zero-terminated). +         ///< Only the CA pids of those CA descriptors are copied that match one of the given CA system IDs. +         ///< Returns the number of pids copied into Pids (0 if no CA descriptors are +         ///< available), or -1 if BufSize was too small to hold all CA pids.  #endif //__PAT_H @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: receiver.c 2.7 2012/06/02 13:20:38 kls Exp $ + * $Id: receiver.c 3.1 2014/01/01 12:03:00 kls Exp $   */  #include "receiver.h" @@ -72,6 +72,28 @@ bool cReceiver::SetPids(const cChannel *Channel)    return true;  } +void cReceiver::DelPid(int Pid) +{ +  if (Pid) { +     for (int i = 0; i < numPids; i++) { +         if (pids[i] == Pid) { +            for ( ; i < numPids; i++) // we also copy the terminating 0! +                pids[i] = pids[i + 1]; +            numPids--; +            return; +            } +         } +     } +} + +void cReceiver::DelPids(const int *Pids) +{ +  if (Pids) { +     while (*Pids) +           DelPid(*Pids++); +     } +} +  bool cReceiver::WantsPid(int Pid)  {    if (Pid) { @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: receiver.h 2.9 2012/09/02 09:27:20 kls Exp $ + * $Id: receiver.h 3.1 2014/01/01 11:45:09 kls Exp $   */  #ifndef __RECEIVER_H @@ -64,7 +64,13 @@ public:                 ///< through ChannelID(). The ChannelID is necessary to allow the device                 ///< that will be used for this receiver to detect and store whether the                 ///< channel can be decrypted in case this is an encrypted channel. +  void DelPid(int Pid); +               ///< Deletes the given Pid from the list of PIDs of this receiver. +  void DelPids(const int *Pids); +               ///< Deletes the given zero terminated list of Pids from the list of PIDs of this +               ///< receiver.    tChannelID ChannelID(void) { return channelID; } +  int NumPids(void) const { return numPids; }    bool IsAttached(void) { return device != NULL; }                 ///< Returns true if this receiver is (still) attached to a device.                 ///< A receiver may be automatically detached from its device in | 
