diff options
author | Klaus Schmidinger <vdr@tvdr.de> | 2007-01-07 14:46:14 +0100 |
---|---|---|
committer | Klaus Schmidinger <vdr@tvdr.de> | 2007-01-07 14:46:14 +0100 |
commit | 87dd5139ff6666d64e7e343bcff632b342c4c814 (patch) | |
tree | c2b8f2f437a09e1ad2f740adc574f3f1833d8fe3 /ci.h | |
parent | b4cab10eca558f6d90fa25a2a6e7fc3d90fac508 (diff) | |
download | vdr-1.5.0.tar.gz vdr-1.5.0.tar.bz2 |
CAM handling refactored; multiple recordings with one CAM; automatic CAM selection1.5.0
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 |