summaryrefslogtreecommitdiff
path: root/ci.h
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2007-01-07 14:46:14 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2007-01-07 14:46:14 +0100
commit87dd5139ff6666d64e7e343bcff632b342c4c814 (patch)
treec2b8f2f437a09e1ad2f740adc574f3f1833d8fe3 /ci.h
parentb4cab10eca558f6d90fa25a2a6e7fc3d90fac508 (diff)
downloadvdr-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.h247
1 files changed, 164 insertions, 83 deletions
diff --git a/ci.h b/ci.h
index 45740106..678f17ba 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 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