2003-01-06 14:44:27 +01:00
|
|
|
/*
|
|
|
|
* ci.h: Common Interface
|
|
|
|
*
|
|
|
|
* See the main source file 'vdr.c' for copyright information and
|
|
|
|
* how to reach the author.
|
|
|
|
*
|
2017-05-18 09:05:46 +02:00
|
|
|
* $Id: ci.h 4.9 2017/05/18 09:05:46 kls Exp $
|
2003-01-06 14:44:27 +01:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef __CI_H
|
|
|
|
#define __CI_H
|
|
|
|
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdio.h>
|
2007-01-07 14:46:14 +01:00
|
|
|
#include "channels.h"
|
2017-03-18 16:33:59 +01:00
|
|
|
#include "ringbuffer.h"
|
2003-01-06 14:44:27 +01:00
|
|
|
#include "thread.h"
|
2005-11-26 13:39:47 +01:00
|
|
|
#include "tools.h"
|
2003-01-06 14:44:27 +01:00
|
|
|
|
2017-01-23 12:01:48 +01:00
|
|
|
#define MAX_CAM_SLOTS_PER_ADAPTER 16 // maximum possible value is 255 (same value as MAXDEVICES!)
|
2007-01-07 14:46:14 +01:00
|
|
|
#define MAX_CONNECTIONS_PER_CAM_SLOT 8 // maximum possible value is 254
|
|
|
|
#define CAM_READ_TIMEOUT 50 // ms
|
|
|
|
|
2017-05-18 09:05:46 +02:00
|
|
|
class cCiTransportConnection;
|
|
|
|
class cCamSlot;
|
|
|
|
|
|
|
|
// VDR's Common Interface functions implement only the features that are absolutely
|
|
|
|
// necessary to control a CAM. If a plugin wants to implement additional functionality
|
|
|
|
// (i.e. "resources"), it can do so by deriving from cCiResourceHandler, cCiSession
|
|
|
|
// and (if necessary) from cCiApplicationInformation.
|
|
|
|
|
|
|
|
class cCiSession {
|
|
|
|
private:
|
|
|
|
uint16_t sessionId;
|
|
|
|
uint32_t resourceId;
|
|
|
|
cCiTransportConnection *tc;
|
|
|
|
protected:
|
|
|
|
void SetTsPostProcessor(void);
|
|
|
|
///< If this cCiSession implements the TsPostProcess() function, it shall call
|
|
|
|
///< SetTsPostProcessor() to register itself as the TS post processor.
|
|
|
|
void SetResourceId(uint32_t Id);
|
|
|
|
///< If this is a class that has been derived from an existing cCiSession class,
|
|
|
|
///< but implements a different resource id, it shall call SetResourceId() with
|
|
|
|
///< that Id.
|
|
|
|
int GetTag(int &Length, const uint8_t **Data);
|
|
|
|
const uint8_t *GetData(const uint8_t *Data, int &Length);
|
|
|
|
void SendData(int Tag, int Length = 0, const uint8_t *Data = NULL);
|
|
|
|
cCiTransportConnection *Tc(void) { return tc; }
|
|
|
|
public:
|
|
|
|
cCiSession(uint16_t SessionId, uint32_t ResourceId, cCiTransportConnection *Tc);
|
|
|
|
virtual ~cCiSession();
|
|
|
|
uint16_t SessionId(void) { return sessionId; }
|
|
|
|
uint32_t ResourceId(void) { return resourceId; }
|
|
|
|
cCamSlot *CamSlot(void);
|
|
|
|
virtual bool HasUserIO(void) { return false; }
|
|
|
|
virtual void Process(int Length = 0, const uint8_t *Data = NULL);
|
|
|
|
virtual bool TsPostProcess(uint8_t *TsPacket) { return false; }
|
|
|
|
///< If this cCiSession needs to do additional processing on TS packets (after
|
|
|
|
///< the CAM has done the decryption), it shall implement TsPostProcess() and
|
|
|
|
///< do whatever operations are necessary on the given TsPacket. This function
|
|
|
|
///< is called once for each TS packet, and any and all operations must be
|
|
|
|
///< finished upon return.
|
|
|
|
///< A derived cCiSession that implements this function must call
|
|
|
|
///< SetTsPostProcessor() to make it actually get called.
|
|
|
|
///< Returns true if the TsPacket was in any way modified.
|
|
|
|
};
|
|
|
|
|
|
|
|
class cCiApplicationInformation : public cCiSession {
|
|
|
|
protected:
|
|
|
|
int state;
|
|
|
|
uint8_t applicationType;
|
|
|
|
uint16_t applicationManufacturer;
|
|
|
|
uint16_t manufacturerCode;
|
|
|
|
char *menuString;
|
|
|
|
public:
|
|
|
|
cCiApplicationInformation(uint16_t SessionId, cCiTransportConnection *Tc);
|
|
|
|
virtual ~cCiApplicationInformation();
|
|
|
|
virtual void Process(int Length = 0, const uint8_t *Data = NULL);
|
|
|
|
bool EnterMenu(void);
|
|
|
|
const char *GetMenuString(void) { return menuString; }
|
|
|
|
};
|
|
|
|
|
|
|
|
class cCiResourceHandler : public cListObject {
|
|
|
|
public:
|
|
|
|
cCiResourceHandler(void);
|
|
|
|
///< Creates a new resource handler, through which the available resources
|
|
|
|
///< can be provides. A resource handler shall be allocated on the heap and
|
|
|
|
///< registered with the global CiResourceHandlers, as in
|
|
|
|
///< CiResourceHandlers.Register(new cMyResourceHandler);
|
|
|
|
///< It will be automatically deleted at the end of the program.
|
|
|
|
virtual ~cCiResourceHandler();
|
|
|
|
virtual const uint32_t *ResourceIds(void) const = 0;
|
|
|
|
///< Returns a pointer to an array of resource identifiers, where the
|
|
|
|
///< last value is zero.
|
|
|
|
virtual cCiSession *GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc) = 0;
|
|
|
|
///< Returns a new cCiSession, according to the given ResourceId.
|
|
|
|
};
|
|
|
|
|
|
|
|
class cCiResourceHandlers : public cList<cCiResourceHandler> {
|
|
|
|
private:
|
|
|
|
cVector<uint32_t> resourceIds;
|
|
|
|
public:
|
|
|
|
cCiResourceHandlers(void);
|
|
|
|
///< Creates the default list of resourceIds.
|
|
|
|
void Register(cCiResourceHandler *ResourceHandler);
|
|
|
|
///< Adds the given ResourceHandler to the list of resource handlers and
|
|
|
|
///< appends its ResourceIds to the global resourceIds.
|
|
|
|
///< A plugin that implements additional CAM capabilities must call
|
|
|
|
///< this function to register its resources.
|
|
|
|
const uint32_t *Ids(void) { return &resourceIds[0]; }
|
|
|
|
int NumIds(void) { return resourceIds.Size(); }
|
|
|
|
cCiSession *GetNewCiSession(uint32_t ResourceId, uint16_t SessionId, cCiTransportConnection *Tc);
|
|
|
|
};
|
|
|
|
|
|
|
|
extern cCiResourceHandlers CiResourceHandlers;
|
|
|
|
|
2003-01-06 14:44:27 +01:00
|
|
|
class cCiMMI;
|
|
|
|
|
|
|
|
class cCiMenu {
|
2007-01-07 14:46:14 +01:00
|
|
|
friend class cCamSlot;
|
2003-01-06 14:44:27 +01:00
|
|
|
friend class cCiMMI;
|
|
|
|
private:
|
|
|
|
enum { MAX_CIMENU_ENTRIES = 64 }; ///< XXX is there a specified maximum?
|
|
|
|
cCiMMI *mmi;
|
2005-10-30 13:21:23 +01:00
|
|
|
cMutex *mutex;
|
2003-01-06 14:44:27 +01:00
|
|
|
bool selectable;
|
|
|
|
char *titleText;
|
|
|
|
char *subTitleText;
|
|
|
|
char *bottomText;
|
|
|
|
char *entries[MAX_CIMENU_ENTRIES];
|
|
|
|
int numEntries;
|
|
|
|
bool AddEntry(char *s);
|
|
|
|
cCiMenu(cCiMMI *MMI, bool Selectable);
|
|
|
|
public:
|
|
|
|
~cCiMenu();
|
|
|
|
const char *TitleText(void) { return titleText; }
|
|
|
|
const char *SubTitleText(void) { return subTitleText; }
|
|
|
|
const char *BottomText(void) { return bottomText; }
|
|
|
|
const char *Entry(int n) { return n < numEntries ? entries[n] : NULL; }
|
|
|
|
int NumEntries(void) { return numEntries; }
|
|
|
|
bool Selectable(void) { return selectable; }
|
2007-01-07 14:46:14 +01:00
|
|
|
void Select(int Index);
|
|
|
|
void Cancel(void);
|
|
|
|
void Abort(void);
|
2005-10-02 12:59:53 +02:00
|
|
|
bool HasUpdate(void);
|
2003-01-06 14:44:27 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
class cCiEnquiry {
|
2007-01-07 14:46:14 +01:00
|
|
|
friend class cCamSlot;
|
2003-01-06 14:44:27 +01:00
|
|
|
friend class cCiMMI;
|
|
|
|
private:
|
|
|
|
cCiMMI *mmi;
|
2005-10-30 13:21:23 +01:00
|
|
|
cMutex *mutex;
|
2003-01-06 14:44:27 +01:00
|
|
|
char *text;
|
|
|
|
bool blind;
|
|
|
|
int expectedLength;
|
|
|
|
cCiEnquiry(cCiMMI *MMI);
|
|
|
|
public:
|
|
|
|
~cCiEnquiry();
|
|
|
|
const char *Text(void) { return text; }
|
|
|
|
bool Blind(void) { return blind; }
|
|
|
|
int ExpectedLength(void) { return expectedLength; }
|
2007-01-07 14:46:14 +01:00
|
|
|
void Reply(const char *s);
|
|
|
|
void Cancel(void);
|
|
|
|
void Abort(void);
|
2003-01-06 14:44:27 +01:00
|
|
|
};
|
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
class cDevice;
|
2005-11-26 13:39:47 +01:00
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
enum eModuleStatus { msNone, msReset, msPresent, msReady };
|
2003-01-06 14:44:27 +01:00
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
class cCiAdapter : public cThread {
|
|
|
|
friend class cCamSlot;
|
|
|
|
private:
|
|
|
|
cCamSlot *camSlots[MAX_CAM_SLOTS_PER_ADAPTER];
|
|
|
|
void AddCamSlot(cCamSlot *CamSlot);
|
|
|
|
///< Adds the given CamSlot to this CI adapter.
|
|
|
|
protected:
|
2015-01-15 09:28:37 +01:00
|
|
|
cCamSlot *ItCamSlot(int &Iter);
|
|
|
|
///< Iterates over all added CAM slots of this adapter. Iter has to be
|
|
|
|
///< initialized to 0 and is required to store the iteration state.
|
|
|
|
///< Returns NULL if no further CAM slot is found.
|
2007-01-07 14:46:14 +01:00
|
|
|
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.
|
2014-01-14 12:21:17 +01:00
|
|
|
virtual int Read(uint8_t *Buffer, int MaxLength) { return 0; }
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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).
|
2014-01-14 12:21:17 +01:00
|
|
|
virtual void Write(const uint8_t *Buffer, int Length) {}
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Writes Length bytes of the given Buffer.
|
2014-01-14 12:21:17 +01:00
|
|
|
virtual bool Reset(int Slot) { return false; }
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Resets the CAM in the given Slot.
|
|
|
|
///< Returns true if the operation was successful.
|
2014-01-14 12:21:17 +01:00
|
|
|
virtual eModuleStatus ModuleStatus(int Slot) { return msNone; }
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns the status of the CAM in the given Slot.
|
2014-01-14 12:21:17 +01:00
|
|
|
virtual bool Assign(cDevice *Device, bool Query = false) { return false; }
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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'.
|
2005-11-26 13:39:47 +01:00
|
|
|
public:
|
2007-01-07 14:46:14 +01:00
|
|
|
cCiAdapter(void);
|
|
|
|
virtual ~cCiAdapter();
|
|
|
|
///< The derived class must call Cancel(3) in its destructor.
|
2005-11-26 13:39:47 +01:00
|
|
|
};
|
2003-01-06 14:44:27 +01:00
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
class cTPDU;
|
2003-01-06 14:44:27 +01:00
|
|
|
class cCiTransportConnection;
|
2007-01-07 14:46:14 +01:00
|
|
|
class cCiSession;
|
|
|
|
class cCiCaProgramData;
|
2014-04-06 10:56:50 +02:00
|
|
|
class cCaPidReceiver;
|
2015-01-30 13:38:44 +01:00
|
|
|
class cCaActivationReceiver;
|
2017-03-18 16:33:59 +01:00
|
|
|
class cMtdHandler;
|
|
|
|
class cMtdMapper;
|
|
|
|
class cMtdCamSlot;
|
|
|
|
class cCiCaPmt;
|
|
|
|
|
|
|
|
struct cCiCaPmtList {
|
|
|
|
cVector<cCiCaPmt *> caPmts;
|
|
|
|
~cCiCaPmtList();
|
|
|
|
cCiCaPmt *Add(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
|
|
|
|
void Del(cCiCaPmt *CaPmt);
|
|
|
|
};
|
2003-01-06 14:44:27 +01:00
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
class cCamSlot : public cListObject {
|
|
|
|
friend class cCiAdapter;
|
|
|
|
friend class cCiTransportConnection;
|
2017-03-18 16:33:59 +01:00
|
|
|
friend class cCiConditionalAccessSupport;
|
|
|
|
friend class cMtdCamSlot;
|
2003-01-06 14:44:27 +01:00
|
|
|
private:
|
|
|
|
cMutex mutex;
|
2007-01-07 14:46:14 +01:00
|
|
|
cCondVar processed;
|
|
|
|
cCiAdapter *ciAdapter;
|
2017-01-23 12:01:48 +01:00
|
|
|
cCamSlot *masterSlot;
|
2015-01-15 09:28:37 +01:00
|
|
|
cDevice *assignedDevice;
|
2014-04-06 10:56:50 +02:00
|
|
|
cCaPidReceiver *caPidReceiver;
|
2015-01-30 13:38:44 +01:00
|
|
|
cCaActivationReceiver *caActivationReceiver;
|
2007-01-07 14:46:14 +01:00
|
|
|
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;
|
2005-11-26 13:39:47 +01:00
|
|
|
int source;
|
|
|
|
int transponder;
|
|
|
|
cList<cCiCaProgramData> caProgramList;
|
2017-03-18 16:33:59 +01:00
|
|
|
bool mtdAvailable;
|
|
|
|
cMtdHandler *mtdHandler;
|
2007-01-07 14:46:14 +01:00
|
|
|
void NewConnection(void);
|
|
|
|
void DeleteAllConnections(void);
|
|
|
|
void Process(cTPDU *TPDU = NULL);
|
|
|
|
void Write(cTPDU *TPDU);
|
|
|
|
cCiSession *GetSessionByResourceId(uint32_t ResourceId);
|
2017-03-18 16:33:59 +01:00
|
|
|
void MtdActivate(bool On);
|
|
|
|
///< Activates (On == true) or deactivates (On == false) MTD.
|
|
|
|
protected:
|
|
|
|
virtual const int *GetCaSystemIds(void);
|
|
|
|
virtual void SendCaPmt(uint8_t CmdId);
|
|
|
|
virtual bool RepliesToQuery(void);
|
|
|
|
///< Returns true if the CAM in this slot replies to queries and thus
|
|
|
|
///< supports MCD ("Multi Channel Decryption").
|
|
|
|
void BuildCaPmts(uint8_t CmdId, cCiCaPmtList &CaPmtList, cMtdMapper *MtdMapper = NULL);
|
|
|
|
///< Generates all CA_PMTs with the given CmdId and stores them in the given CaPmtList.
|
|
|
|
///< If MtdMapper is given, all SIDs and PIDs will be mapped accordingly.
|
|
|
|
void SendCaPmts(cCiCaPmtList &CaPmtList);
|
|
|
|
///< Sends the given list of CA_PMTs to the CAM.
|
|
|
|
void MtdEnable(void);
|
|
|
|
///< Enables MTD support for this CAM. Note that actual MTD operation also
|
|
|
|
///< requires a CAM that supports MCD ("Multi Channel Decryption").
|
|
|
|
int MtdPutData(uchar *Data, int Count);
|
|
|
|
///< Sends at most Count bytes of the given Data to the individual MTD CAM slots
|
2017-03-19 10:48:52 +01:00
|
|
|
///< that are using this CAM. Data must point to the beginning of a TS packet.
|
2017-03-18 16:33:59 +01:00
|
|
|
///< Returns the number of bytes actually processed.
|
|
|
|
public:
|
|
|
|
bool McdAvailable(void) { return RepliesToQuery(); }
|
|
|
|
///< Returns true if this CAM supports MCD ("Multi Channel Decyption").
|
|
|
|
bool MtdAvailable(void) { return mtdAvailable; }
|
|
|
|
///< Returns true if this CAM supports MTD ("Multi Transponder Decryption").
|
|
|
|
bool MtdActive(void) { return mtdHandler != NULL; }
|
|
|
|
///< Returns true if MTD is currently active.
|
2003-01-06 14:44:27 +01:00
|
|
|
public:
|
2017-01-23 12:01:48 +01:00
|
|
|
cCamSlot(cCiAdapter *CiAdapter, bool WantsTsData = false, cCamSlot *MasterSlot = NULL);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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!
|
2014-01-20 12:14:30 +01:00
|
|
|
///< If WantsTsData is true, the device this CAM slot is assigned to will
|
|
|
|
///< call the Decrypt() function of this CAM slot, presenting it the complete
|
|
|
|
///< TS data stream of the encrypted programme, including the CA pids.
|
2017-01-23 12:01:48 +01:00
|
|
|
///< If this CAM slot is basically the same as an other one, MasterSlot can
|
|
|
|
///< be given to indicate this. This can be used for instance for CAM slots
|
|
|
|
///< that can do MTD ("Multi Transponder Decryption"), where the first cCamSlot
|
|
|
|
///< is created without giving a MasterSlot, and all others are given the first
|
|
|
|
///< one as their MasterSlot. This can speed up the search for a suitable CAM
|
|
|
|
///< when tuning to an encrypted channel, and it also makes the Setup/CAM menu
|
|
|
|
///< clearer because only the master CAM slots will be shown there.
|
2007-01-07 14:46:14 +01:00
|
|
|
virtual ~cCamSlot();
|
2017-01-23 12:01:48 +01:00
|
|
|
bool IsMasterSlot(void) { return !masterSlot; }
|
|
|
|
///< Returns true if this CAM slot itself is a master slot (which means that
|
|
|
|
///< it doesn't have pointer to another CAM slot that's its master).
|
|
|
|
cCamSlot *MasterSlot(void) { return masterSlot ? masterSlot : this; }
|
|
|
|
///< Returns this CAM slot's master slot, or a pointer to itself if it is a
|
|
|
|
///< master slot.
|
2017-03-18 16:33:59 +01:00
|
|
|
cCamSlot *MtdSpawn(void);
|
|
|
|
///< If this CAM slot can do MTD ("Multi Transponder Decryption"),
|
|
|
|
///< a call to this function returns a cMtdCamSlot with this CAM slot
|
|
|
|
///< as its master. Otherwise a pointer to this object is returned, which
|
|
|
|
///< means that MTD is not supported.
|
|
|
|
void TriggerResendPmt(void) { resendPmt = true; }
|
|
|
|
///< Tells this CAM slot to resend the list of CA_PMTs to the CAM.
|
2017-01-23 12:01:48 +01:00
|
|
|
virtual bool Assign(cDevice *Device, bool Query = false);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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'.
|
2017-01-23 12:01:48 +01:00
|
|
|
///< If a derived class reimplements this function, it can return 'false'
|
|
|
|
///< if this CAM can't be assigned to the given Device. If the CAM can be
|
|
|
|
///< assigned to the Device, or if Device is NULL, it must call the base
|
|
|
|
///< class function.
|
2015-01-15 09:28:37 +01:00
|
|
|
cDevice *Device(void) { return assignedDevice; }
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns the device this CAM slot is currently assigned to.
|
2017-03-18 16:33:59 +01:00
|
|
|
bool Devices(cVector<int> &CardIndexes);
|
|
|
|
///< Adds the card indexes of any devices that currently use this CAM to
|
|
|
|
///< the given CardIndexes. This can be more than one in case of MTD.
|
|
|
|
///< Returns true if the array is not empty.
|
2014-01-20 12:14:30 +01:00
|
|
|
bool WantsTsData(void) const { return caPidReceiver != NULL; }
|
|
|
|
///< Returns true if this CAM slot wants to receive the TS data through
|
|
|
|
///< its Decrypt() function.
|
2007-01-07 14:46:14 +01:00
|
|
|
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.
|
2017-01-23 12:01:48 +01:00
|
|
|
int MasterSlotNumber(void) { return masterSlot ? masterSlot->SlotNumber() : slotNumber; }
|
|
|
|
///< Returns the number of this CAM's master slot within the whole system.
|
|
|
|
///< The first slot has the number 1.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool Reset(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Resets the CAM in this slot.
|
|
|
|
///< Returns true if the operation was successful.
|
2015-01-30 13:38:44 +01:00
|
|
|
virtual bool CanActivate(void);
|
|
|
|
///< Returns true if there is a CAM in this slot that can be put into
|
|
|
|
///< activation mode.
|
|
|
|
virtual void StartActivation(void);
|
|
|
|
///< Puts the CAM in this slot into a mode where an inserted smart card
|
|
|
|
///< can be activated. The default action is to make IsActivating() return
|
|
|
|
///< true, which causes the device this CAM slot is attached to to never
|
|
|
|
///< automatically detach any receivers with negative priority if the
|
|
|
|
///< PIDs they want to receive are not decrypted by the CAM.
|
|
|
|
///< StartActivation() must be called *after* the CAM slot has been assigned
|
|
|
|
///< to a device. The CAM slot will stay in activation mode until the CAM
|
|
|
|
///< begins to decrypt, a call to CancelActivation() is made, or the device
|
|
|
|
///< is needed for a recording.
|
|
|
|
virtual void CancelActivation(void);
|
|
|
|
///< Cancels a previously started activation (if any).
|
|
|
|
virtual bool IsActivating(void);
|
|
|
|
///< Returns true if this CAM slot is currently activating a smart card.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual eModuleStatus ModuleStatus(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns the status of the CAM in this slot.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual const char *GetCamName(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns the name of the CAM in this slot, or NULL if there is
|
|
|
|
///< no ready CAM in this slot.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool Ready(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns 'true' if the CAM in this slot is ready to decrypt.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool HasMMI(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns 'true' if the CAM in this slot has an active MMI.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool HasUserIO(void);
|
2005-12-03 11:59:05 +01:00
|
|
|
///< Returns true if there is a pending user interaction, which shall
|
|
|
|
///< be retrieved via GetMenu() or GetEnquiry().
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool EnterMenu(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Requests the CAM in this slot to start its menu.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual cCiMenu *GetMenu(void);
|
2005-12-03 11:59:05 +01:00
|
|
|
///< Gets a pending menu, or NULL if there is no menu.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual cCiEnquiry *GetEnquiry(void);
|
2005-12-03 11:59:05 +01:00
|
|
|
///< Gets a pending enquiry, or NULL if there is no enquiry.
|
2007-01-07 14:46:14 +01:00
|
|
|
int Priority(void);
|
2015-01-31 14:36:41 +01:00
|
|
|
///< Returns the priority of the device this slot is currently assigned
|
2012-03-02 10:19:00 +01:00
|
|
|
///< to, or IDLEPRIORITY if it is not assigned to any device.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool ProvidesCa(const int *CaSystemIds);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns true if the CAM in this slot provides one of the given
|
2005-12-03 11:59:05 +01:00
|
|
|
///< 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.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual void AddPid(int ProgramNumber, int Pid, int StreamType);
|
2005-11-26 13:39:47 +01:00
|
|
|
///< Adds the given PID information to the list of PIDs. A later call
|
|
|
|
///< to SetPid() will (de)activate one of these entries.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual void SetPid(int Pid, bool Active);
|
2005-11-26 13:39:47 +01:00
|
|
|
///< Sets the given Pid (which has previously been added through a
|
2005-12-03 11:59:05 +01:00
|
|
|
///< call to AddPid()) to Active. A later call to StartDecrypting() will
|
|
|
|
///< send the full list of currently active CA_PMT entries to the CAM.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual void AddChannel(const cChannel *Channel);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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.
|
2017-03-23 14:34:53 +01:00
|
|
|
virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper = NULL);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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
|
2011-12-04 13:40:52 +01:00
|
|
|
///< to the initial QUERY will perform this check at all. CAMs that never
|
2007-01-07 14:46:14 +01:00
|
|
|
///< replied to the initial QUERY are assumed not to be able to handle
|
|
|
|
///< more than one channel at a time.
|
2017-03-23 14:34:53 +01:00
|
|
|
///< If MtdMapper is given, all SIDs and PIDs will be mapped accordingly.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual void StartDecrypting(void);
|
2017-03-23 14:34:53 +01:00
|
|
|
///< Sends all CA_PMT entries to the CAM that have been modified since the
|
|
|
|
///< last call to this function. This includes CA_PMTs that have been
|
|
|
|
///< added or activated, as well as ones that have been deactivated.
|
|
|
|
///< StartDecrypting() will be called whenever a PID is activated or
|
|
|
|
///< deactivated.
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual void StopDecrypting(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
|
2017-03-23 14:34:53 +01:00
|
|
|
///< Note that this function is only called when there are no more PIDs for
|
|
|
|
///< the CAM to decrypt. There is no symmetry between StartDecrypting() and
|
|
|
|
///< StopDecrypting().
|
2013-12-28 13:29:54 +01:00
|
|
|
virtual bool IsDecrypting(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< Returns true if the CAM in this slot is currently used for decrypting.
|
2014-01-02 10:47:08 +01:00
|
|
|
virtual uchar *Decrypt(uchar *Data, int &Count);
|
2013-12-28 13:29:54 +01:00
|
|
|
///< 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
|
2014-01-02 10:47:08 +01:00
|
|
|
///< of Count bytes of TS data. The first byte in Data is guaranteed
|
2017-04-15 09:39:55 +02:00
|
|
|
///< to be a TS_SYNC_BYTE, and Count is at least TS_SIZE.
|
|
|
|
///< Note that Decrypt() may be called with Data == NULL! This is necessary
|
|
|
|
///< to allow CAMs that copy the incoming data into a separate buffer to
|
|
|
|
///< return previously received and decrypted TS packets. If Data is NULL,
|
|
|
|
///< Count is 0 and must not be modified, and the return value shall point to the
|
|
|
|
///< next available decrypted TS packet (if any).
|
2014-01-02 10:47:08 +01:00
|
|
|
///< 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
|
2014-01-31 09:21:47 +01:00
|
|
|
///< wants, but it must decrypt at least the very first TS packet (if at all
|
|
|
|
///< possible - if, for whatever reasons, it can't decrypt the very first
|
|
|
|
///< packet, it must return it regardless). 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.
|
2014-01-02 10:47:08 +01:00
|
|
|
///< 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
|
2017-03-18 16:33:59 +01:00
|
|
|
///< call to Decrypt(). See mtd.h for further requirements if this CAM can
|
|
|
|
///< do MTD ("Multi Transponder Decryption").
|
2014-01-01 12:37:22 +01:00
|
|
|
///< A derived class that implements this function will also need
|
2014-01-20 12:14:30 +01:00
|
|
|
///< to set the WantsTsData parameter in the call to the base class
|
|
|
|
///< constructor to true in order to receive the TS data.
|
2017-05-18 09:05:46 +02:00
|
|
|
virtual bool TsPostProcess(uchar *Data);
|
|
|
|
///< If there is a cCiSession that needs to do additional processing on TS packets
|
|
|
|
///< (after the CAM has done the decryption), this function will call its
|
|
|
|
///< TsPostProcess() function to have it do whatever operations are necessary on
|
|
|
|
///< the given TsPacket.
|
|
|
|
///< Returns true if the TsPacket was in any way modified.
|
2017-05-01 09:32:32 +02:00
|
|
|
virtual bool Inject(uchar *Data, int Count);
|
|
|
|
///< Sends all Count bytes of the given Data to the CAM, and returns true
|
|
|
|
///< if this was possible. If the data can't be sent to the CAM completely,
|
|
|
|
///< nothing shall be sent and the return value shall be false.
|
|
|
|
///< No decrypted packet is returned by this function.
|
2017-05-01 16:26:34 +02:00
|
|
|
///< Data is guaranteed to point to one or more complete TS packets.
|
2017-05-01 09:32:32 +02:00
|
|
|
virtual void InjectEit(int Sid);
|
|
|
|
///< Injects a generated EIT with a "present event" for the given Sid into
|
|
|
|
///< the TS data stream sent to the CAM. This only applies to CAM slots that
|
|
|
|
///< have WantsTsData set to true in their constructor.
|
|
|
|
///< The default implementation sends an EIT with the minimum event
|
|
|
|
///< necessary to disable the CAMs parental rating prompt.
|
2003-01-06 14:44:27 +01:00
|
|
|
};
|
|
|
|
|
2014-01-16 11:57:54 +01:00
|
|
|
class cCamSlots : public cList<cCamSlot> {
|
|
|
|
public:
|
2017-01-23 12:01:48 +01:00
|
|
|
int NumReadyMasterSlots(void);
|
|
|
|
///< Returns the number of master CAM slots in the system that are ready
|
|
|
|
///< to decrypt.
|
2014-01-16 11:57:54 +01:00
|
|
|
bool WaitForAllCamSlotsReady(int Timeout = 0);
|
|
|
|
///< Waits until all CAM slots have become ready, or the given Timeout
|
|
|
|
///< (seconds) has expired. While waiting, the Ready() function of each
|
|
|
|
///< CAM slot is called in turn, until they all return true.
|
|
|
|
///< Returns true if all CAM slots have become ready within the given
|
|
|
|
///< timeout.
|
|
|
|
};
|
2007-01-07 14:46:14 +01:00
|
|
|
|
|
|
|
extern cCamSlots CamSlots;
|
|
|
|
|
|
|
|
class cChannelCamRelation;
|
|
|
|
|
|
|
|
class cChannelCamRelations : public cList<cChannelCamRelation> {
|
|
|
|
private:
|
|
|
|
cMutex mutex;
|
2017-01-09 13:42:41 +01:00
|
|
|
cString fileName;
|
2007-01-07 14:46:14 +01:00
|
|
|
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);
|
2017-01-09 13:42:41 +01:00
|
|
|
void Load(const char *FileName);
|
|
|
|
void Save(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
extern cChannelCamRelations ChannelCamRelations;
|
|
|
|
|
2003-01-06 14:44:27 +01:00
|
|
|
#endif //__CI_H
|