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.
|
|
|
|
*
|
2007-01-07 14:46:14 +01:00
|
|
|
* $Id: ci.h 1.23 2007/01/07 14:38:00 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"
|
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
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
#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
|
|
|
|
|
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;
|
|
|
|
class cCamSlot;
|
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:
|
|
|
|
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'.
|
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.
|
|
|
|
virtual bool Ready(void);
|
|
|
|
///< Returns 'true' if all present CAMs in this adapter are ready.
|
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;
|
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;
|
2003-01-06 14:44:27 +01:00
|
|
|
private:
|
|
|
|
cMutex mutex;
|
2007-01-07 14:46:14 +01:00
|
|
|
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;
|
2005-11-26 13:39:47 +01:00
|
|
|
int source;
|
|
|
|
int transponder;
|
|
|
|
cList<cCiCaProgramData> caProgramList;
|
2007-01-07 14:46:14 +01:00
|
|
|
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);
|
2003-01-06 14:44:27 +01:00
|
|
|
public:
|
2007-01-07 14:46:14 +01:00
|
|
|
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.
|
2005-08-21 08:56:49 +02:00
|
|
|
bool Ready(void);
|
2007-01-07 14:46:14 +01:00
|
|
|
///< 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);
|
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().
|
2007-01-07 14:46:14 +01:00
|
|
|
bool EnterMenu(void);
|
|
|
|
///< Requests the CAM in this slot to start its menu.
|
2003-01-06 14:44:27 +01:00
|
|
|
cCiMenu *GetMenu(void);
|
2005-12-03 11:59:05 +01:00
|
|
|
///< Gets a pending menu, or NULL if there is no menu.
|
2003-01-06 14:44:27 +01:00
|
|
|
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);
|
|
|
|
///< 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
|
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.
|
2005-11-26 13:39:47 +01:00
|
|
|
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.
|
|
|
|
void SetPid(int Pid, bool Active);
|
|
|
|
///< 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.
|
2007-01-07 14:46:14 +01:00
|
|
|
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.
|
2005-11-26 13:39:47 +01:00
|
|
|
void StartDecrypting(void);
|
|
|
|
///< Triggers sending all currently active CA_PMT entries to the CAM,
|
|
|
|
///< so that it will start decrypting.
|
2007-01-07 14:46:14 +01:00
|
|
|
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.
|
2003-01-06 14:44:27 +01:00
|
|
|
};
|
|
|
|
|
2007-01-07 14:46:14 +01:00
|
|
|
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;
|
|
|
|
|
2003-01-06 14:44:27 +01:00
|
|
|
#endif //__CI_H
|