diff options
Diffstat (limited to 'ci.h')
| -rw-r--r-- | ci.h | 247 | 
1 files changed, 164 insertions, 83 deletions
| @@ -4,7 +4,7 @@   * See the main source file 'vdr.c' for copyright information and   * how to reach the author.   * - * $Id: ci.h 1.22 2006/08/12 09:43:31 kls Exp $ + * $Id: ci.h 1.23 2007/01/07 14:38:00 kls Exp $   */  #ifndef __CI_H @@ -12,13 +12,18 @@  #include <stdint.h>  #include <stdio.h> +#include "channels.h"  #include "thread.h"  #include "tools.h" +#define MAX_CAM_SLOTS_PER_ADAPTER     8 // maximum possible value is 255 +#define MAX_CONNECTIONS_PER_CAM_SLOT  8 // maximum possible value is 254 +#define CAM_READ_TIMEOUT  50 // ms +  class cCiMMI;  class cCiMenu { -  friend class cCiHandler; +  friend class cCamSlot;    friend class cCiMMI;  private:    enum { MAX_CIMENU_ENTRIES = 64 }; ///< XXX is there a specified maximum? @@ -40,14 +45,14 @@ public:    const char *Entry(int n) { return n < numEntries ? entries[n] : NULL; }    int NumEntries(void) { return numEntries; }    bool Selectable(void) { return selectable; } -  bool Select(int Index); -  bool Cancel(void); -  bool Abort(void); +  void Select(int Index); +  void Cancel(void); +  void Abort(void);    bool HasUpdate(void);    };  class cCiEnquiry { -  friend class cCiHandler; +  friend class cCamSlot;    friend class cCiMMI;  private:    cCiMMI *mmi; @@ -61,103 +66,140 @@ public:    const char *Text(void) { return text; }    bool Blind(void) { return blind; }    int ExpectedLength(void) { return expectedLength; } -  bool Reply(const char *s); -  bool Cancel(void); -  bool Abort(void); +  void Reply(const char *s); +  void Cancel(void); +  void Abort(void);    }; -#define MAX_CI_SESSION  16 //XXX -#define MAX_CI_SLOT     16 +class cDevice; +class cCamSlot; -class cCiCaPidData : public cListObject { -public: -  bool active; -  int pid; -  int streamType; -  cCiCaPidData(int Pid, int StreamType) -  { -    active = false; -    pid = Pid; -    streamType = StreamType; -  } -  }; +enum eModuleStatus { msNone, msReset, msPresent, msReady }; -class cCiCaProgramData : public cListObject { +class cCiAdapter : public cThread { +  friend class cCamSlot; +private: +  cDevice *assignedDevice; +  cCamSlot *camSlots[MAX_CAM_SLOTS_PER_ADAPTER]; +  void AddCamSlot(cCamSlot *CamSlot); +       ///< Adds the given CamSlot to this CI adapter. +protected: +  virtual void Action(void); +       ///< Handles the attached CAM slots in a separate thread. +       ///< The derived class must call the Start() function to +       ///< actually start CAM handling. +  virtual int Read(uint8_t *Buffer, int MaxLength) = 0; +       ///< Reads one chunk of data into the given Buffer, up to MaxLength bytes. +       ///< If no data is available immediately, wait for up to CAM_READ_TIMEOUT. +       ///< Returns the number of bytes read (in case of an error it will also +       ///< return 0). +  virtual void Write(const uint8_t *Buffer, int Length) = 0; +       ///< Writes Length bytes of the given Buffer. +  virtual bool Reset(int Slot) = 0; +       ///< Resets the CAM in the given Slot. +       ///< Returns true if the operation was successful. +  virtual eModuleStatus ModuleStatus(int Slot) = 0; +       ///< Returns the status of the CAM in the given Slot. +  virtual bool Assign(cDevice *Device, bool Query = false) = 0; +       ///< Assigns this adapter to the given Device, if this is possible. +       ///< If Query is 'true', the adapter only checks whether it can be +       ///< assigned to the Device, but doesn't actually assign itself to it. +       ///< Returns true if the adapter can be assigned to the Device. +       ///< If Device is NULL, the adapter will be unassigned from any +       ///< device it was previously assigned to. The value of Query +       ///< is ignored in that case, and this function always returns +       ///< 'true'.  public: -  int programNumber; -  cList<cCiCaPidData> pidList; -  cCiCaProgramData(int ProgramNumber) -  { -    programNumber = ProgramNumber; -  } +  cCiAdapter(void); +  virtual ~cCiAdapter(); +       ///< The derived class must call Cancel(3) in its destructor. +  virtual bool Ready(void); +       ///< Returns 'true' if all present CAMs in this adapter are ready.    }; -class cCiSession; -class cCiTransportLayer; +class cTPDU;  class cCiTransportConnection; +class cCiSession; +class cCiCaProgramData; -class cCiHandler { +class cCamSlot : public cListObject { +  friend class cCiAdapter; +  friend class cCiTransportConnection;  private:    cMutex mutex; -  int fd; -  int numSlots; -  bool newCaSupport; -  bool hasUserIO; -  bool moduleReady[MAX_CI_SLOT]; -  cCiSession *sessions[MAX_CI_SESSION]; -  cCiTransportLayer *tpl; -  cCiTransportConnection *tc; +  cCondVar processed; +  cCiAdapter *ciAdapter; +  int slotIndex; +  int slotNumber; +  cCiTransportConnection *tc[MAX_CONNECTIONS_PER_CAM_SLOT + 1];  // connection numbering starts with 1 +  eModuleStatus lastModuleStatus; +  time_t resetTime; +  cTimeMs moduleCheckTimer; +  bool resendPmt;    int source;    int transponder;    cList<cCiCaProgramData> caProgramList; -  uint32_t ResourceIdToInt(const uint8_t *Data); -  bool Send(uint8_t Tag, uint16_t SessionId, uint32_t ResourceId = 0, int Status = -1); -  const unsigned short *GetCaSystemIds(int Slot); -  cCiSession *GetSessionBySessionId(uint16_t SessionId); -  cCiSession *GetSessionByResourceId(uint32_t ResourceId, int Slot); -  cCiSession *CreateSession(uint32_t ResourceId); -  bool OpenSession(int Length, const uint8_t *Data); -  bool CloseSession(uint16_t SessionId); -  int CloseAllSessions(int Slot); -  cCiHandler(int Fd, int NumSlots); -  void SendCaPmt(void); +  const int *GetCaSystemIds(void); +  void SendCaPmt(uint8_t CmdId); +  void NewConnection(void); +  void DeleteAllConnections(void); +  void Process(cTPDU *TPDU = NULL); +  void Write(cTPDU *TPDU); +  cCiSession *GetSessionByResourceId(uint32_t ResourceId);  public: -  ~cCiHandler(); -  static cCiHandler *CreateCiHandler(const char *FileName); -       ///< Creates a new cCiHandler for the given CA device. -  int NumSlots(void) { return numSlots; } -       ///< Returns the number of CAM slots provided by this CA device. -  int NumCams(void); -       ///< Returns the number of actual CAMs inserted into this CA device. +  cCamSlot(cCiAdapter *CiAdapter); +       ///< 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! +  virtual ~cCamSlot(); +  bool Assign(cDevice *Device, bool Query = false); +       ///< Assigns this CAM slot to the given Device, if this is possible. +       ///< If Query is 'true', the CI adapter of this slot only checks whether +       ///< it can be assigned to the Device, but doesn't actually assign itself to it. +       ///< Returns true if this slot can be assigned to the Device. +       ///< If Device is NULL, the slot will be unassigned from any +       ///< device it was previously assigned to. The value of Query +       ///< is ignored in that case, and this function always returns +       ///< 'true'. +  cDevice *Device(void); +       ///< Returns the device this CAM slot is currently assigned to. +  int SlotIndex(void) { return slotIndex; } +       ///< Returns the index of this CAM slot within its CI adapter. +       ///< The first slot has an index of 0. +  int SlotNumber(void) { return slotNumber; } +       ///< Returns the number of this CAM slot within the whole system. +       ///< The first slot has the number 1. +  bool Reset(void); +       ///< Resets the CAM in this slot. +       ///< Returns true if the operation was successful. +  eModuleStatus ModuleStatus(void); +       ///< Returns the status of the CAM in this slot. +  const char *GetCamName(void); +       ///< Returns the name of the CAM in this slot, or NULL if there is +       ///< no ready CAM in this slot.    bool Ready(void); -       ///< Returns true if all CAMs in this CA device are ready. -  bool Process(int Slot = -1); -       ///< Processes the given Slot. If Slot is -1, all slots are processed. -       ///< Returns false in case of an error. -  bool HasUserIO(void) { return hasUserIO; } +       ///< Returns 'true' if the CAM in this slot is ready to decrypt. +  bool HasMMI(void); +       ///< Returns 'true' if the CAM in this slot has an active MMI. +  bool HasUserIO(void);         ///< Returns true if there is a pending user interaction, which shall         ///< be retrieved via GetMenu() or GetEnquiry(). -  bool EnterMenu(int Slot); -       ///< Requests the CAM in the given Slot to start its menu. +  bool EnterMenu(void); +       ///< Requests the CAM in this slot to start its menu.    cCiMenu *GetMenu(void);         ///< Gets a pending menu, or NULL if there is no menu.    cCiEnquiry *GetEnquiry(void);         ///< Gets a pending enquiry, or NULL if there is no enquiry. -  const char *GetCamName(int Slot); -       ///< Returns the name of the CAM in the given Slot, or NULL if there -       ///< is no CAM in that slot. -  bool ProvidesCa(const unsigned short *CaSystemIds); //XXX Slot??? -       ///< Returns true if any of the CAMs can provide one of the given +  int Priority(void); +       ///< Returns the priority if the device this slot is currently assigned +       ///< to, or -1 if it is not assigned to any device. +  bool ProvidesCa(const int *CaSystemIds); +       ///< Returns true if the CAM in this slot provides one of the given         ///< CaSystemIds. This doesn't necessarily mean that it will be         ///< possible to actually decrypt such a programme, since CAMs         ///< usually advertise several CA system ids, while the actual         ///< decryption is controlled by the smart card inserted into         ///< the CAM. -  void SetSource(int Source, int Transponder); -       ///< Sets the Source and Transponder of the device this cCiHandler is -       ///< currently tuned to. If Source or Transponder are different than -       ///< what was given in a previous call to SetSource(), any previously -       ///< added PIDs will be cleared.    void AddPid(int ProgramNumber, int Pid, int StreamType);         ///< Adds the given PID information to the list of PIDs. A later call         ///< to SetPid() will (de)activate one of these entries. @@ -165,16 +207,55 @@ public:         ///< Sets the given Pid (which has previously been added through a         ///< call to AddPid()) to Active. A later call to StartDecrypting() will         ///< send the full list of currently active CA_PMT entries to the CAM. -  bool CanDecrypt(int ProgramNumber); -       ///< XXX -       ///< Returns true if there is a CAM in this CA device that is able -       ///< to decrypt the programme with the given ProgramNumber. The PIDs -       ///< for this ProgramNumber must have been set through previous calls -       ///< to SetPid(). +  void AddChannel(const cChannel *Channel); +       ///< Adds all PIDs if the given Channel to the current list of PIDs. +       ///< 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. +  bool CanDecrypt(const cChannel *Channel); +       ///< 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 +       ///< CAMs don't reply to queries at all), we always return true if the +       ///< CAM is currently not decrypting anything. If there is already a +       ///< channel being decrypted, a call to CanDecrypt() checks whether the +       ///< CAM can also decrypt the given channel. Only CAMs that have replied +       ///< to the inital 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.    void StartDecrypting(void);         ///< Triggers sending all currently active CA_PMT entries to the CAM,         ///< so that it will start decrypting. -  bool Reset(int Slot); +  void StopDecrypting(void); +       ///< Clears the list of CA_PMT entries and tells the CAM to stop decrypting. +  bool IsDecrypting(void); +       ///< Returns true if the CAM in this slot is currently used for decrypting.    }; +class cCamSlots : public cList<cCamSlot> {}; + +extern cCamSlots CamSlots; + +class cChannelCamRelation; + +class cChannelCamRelations : public cList<cChannelCamRelation> { +private: +  cMutex mutex; +  cChannelCamRelation *GetEntry(tChannelID ChannelID); +  cChannelCamRelation *AddEntry(tChannelID ChannelID); +  time_t lastCleanup; +  void Cleanup(void); +public: +  cChannelCamRelations(void); +  void Reset(int CamSlotNumber); +  bool CamChecked(tChannelID ChannelID, int CamSlotNumber); +  bool CamDecrypt(tChannelID ChannelID, int CamSlotNumber); +  void SetChecked(tChannelID ChannelID, int CamSlotNumber); +  void SetDecrypt(tChannelID ChannelID, int CamSlotNumber); +  void ClrChecked(tChannelID ChannelID, int CamSlotNumber); +  void ClrDecrypt(tChannelID ChannelID, int CamSlotNumber); +  }; + +extern cChannelCamRelations ChannelCamRelations; +  #endif //__CI_H | 
