vdr 2.6.1
mtd.h
Go to the documentation of this file.
1/*
2 * mtd.h: Multi Transponder Decryption
3 *
4 * See the main source file 'vdr.c' for copyright information and
5 * how to reach the author.
6 *
7 * $Id: mtd.h 1.11 2020/06/16 14:33:32 kls Exp $
8 */
9
10#ifndef __MTD_H
11#define __MTD_H
12
13/*
14Multiple Transponder Decryption (MTD) is the method of sending TS packets
15from channels on different transponders to one single CAM for decryption.
16While decrypting several channels from the same transponder ("Multi Channel
17Decryption") is straightforward, because the PIDs are unique within one
18transponder, channels on different transponders might use the same PIDs
19for different streams.
20
21Here's a summary of how MTD is implemented in VDR:
22
23Identifying the relevant source code
24------------------------------------
25
26The actual code that implements the MTD handling is located in the files
27mtd.h and mtd.c. There are also a few places in ci.[hc], device.c and
28menu.c where things need to be handled differently for MTD. All functions
29and variables that have to do with MTD have the three letters "mtd" (upper-
30and/or lowercase) in their name, so that these code lines can be easily
31identified if necessary.
32
33What a plugin implementing a cCiAdapter/cCamSlot needs to do
34------------------------------------------------------------
35
36If an implementation of cCiAdapter/cCamSlot supports MTD, it needs to
37fulfill the following requirements:
38- The cCiAdapter's Assign() function needs to return true for any given
39 device.
40- The cCamSlot's constructor needs to call MtdEnable().
41- The cCamSlot's Decrypt() function shall accept the given TS packet,
42 but shall *not* return a decrypted packet. Decypted packets shall be
43 delivered through a call to MtdPutData(), one at a time.
44- The cCamSlot's Decrypt() function needs to be thread safe, because
45 it will be called from several cMtdCamSlot objects.
46
47Physical vs. virtual CAMs
48-------------------------
49
50MTD is done by having one physical CAM (accessed through a plugin's
51implementation of cCiAdapter/cCamSlot) and several "virtual" CAMs,
52implemented through cMtdCamSlot objects ("MTD CAMs"). For each device
53that requires the physical CAM, one instance of a cMtdCamSlot is created
54on the fly at runtime, and that MTD CAM is assigned to the device.
55The MTD CAM takes care of mapping the PIDs, and a cMtdHandler in the
56physical CAM object distributes the decrypted TS packets to the proper
57devices.
58
59Mapping the PIDs
60----------------
61
62The main problem with MTD is that the TS packets from different devices
63(and thus different transponders with possibly overlapping PIDs) need to
64be combined into one stream, sent to the physical CAM, and finally be sorted
65apart again and returned to the devices they came from. Both aspects are
66solved in VDR by mapping the "real" PIDs into "unique" PIDs. Real PIDs
67are in the range 0x0000-0x1FFF (13 bit). Unique PIDs use the upper 5 bit
68to indicate the number of the MTD CAM a TS packet came from, and the lower
698 bit as individual PID values. Mapping is done with a single array lookup
70and is thus very fast. The cMtdHandler class takes care of distributing
71the TS packets to the individual cMtdCamSlot objects, while mapping the
72PIDs (in both directions) is done by the cMtdMapper class.
73
74Mapping the SIDs
75----------------
76
77Besides the PIDs there are also the "service ids" (SIDs, a.k.a. "programme
78numbers" or PNRs) that need to be taken care of. SIDs only appear in the
79CA-PMTs sent to the CAM, so they only need to be mapped from real to unique
80(not the other way) and since the are only mapped when switching channels,
81mapping doesn't need to be very fast. Mapping SIDs is also done by the
82cMtdMapper class.
83
84Handling the CAT
85----------------
86
87Each transponder carries a CAT ("Conditional Access Table") with the fixed PID 1.
88The CAT contains a list of EMM PIDs, which are necessary to convey entitlement
89messages to the smart card. Since the CAM only recognizes the CAT if it has
90its fixed PID of 1, this PID cannot be mapped and has to be sent to the CAM
91as is. However, the cCaPidReceiver also needs to see the CAM in order to
92request from the device the TS packets with the EMM PIDs. Since any receivers
93only get the TS packets after they have been sent through the CAM, we need
94to send the CAT in both ways, with mapped PID but unmapped EMM PIDs for the
95cCaPidReceiver, and with unmapped PID but mapped EMM PIDs for the CAM itself.
96Since the PID 0x0001 can always be distinguished from any mapped PID (which
97always have a non-zero upper byte), the CAT can be easily channeled in both
98ways.
99
100Handling the CA-PMTs
101--------------------
102
103The CA-PMTs that are sent to the CAM contain both SIDs and PIDs, which are
104mapped in cCiCaPmt::MtdMapPids().
105*/
106
107#include "ci.h"
108#include "remux.h"
109#include "ringbuffer.h"
110
111class cMtdHandler {
112private:
114public:
124 int Put(const uchar *Data, int Count);
129 int Priority(void);
131 bool IsDecrypting(void);
133 void StartDecrypting(void);
135 void StopDecrypting(void);
139 bool IsActivating(void);
141 bool Devices(cVector<int> &DeviceNumbers);
145 void UnAssignAll(void);
147 };
148
149#define MTD_DONT_CALL(v) dsyslog("PROGRAMMING ERROR (%s,%d): DON'T CALL %s", __FILE__, __LINE__, __FUNCTION__); return v;
150
151class cMtdMapper;
152
153void MtdMapSid(uchar *p, cMtdMapper *MtdMapper);
154void MtdMapPid(uchar *p, cMtdMapper *MtdMapper);
155
156class cMtdCamSlot : public cCamSlot {
157private:
161 bool delivered;
162protected:
163 virtual const int *GetCaSystemIds(void);
164 virtual void SendCaPmt(uint8_t CmdId);
165public:
169 virtual ~cMtdCamSlot();
170 cMtdMapper *MtdMapper(void) { return mtdMapper; }
171 virtual bool RepliesToQuery(void);
172 virtual bool ProvidesCa(const int *CaSystemIds);
173 virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper = NULL);
174 virtual void StartDecrypting(void);
175 virtual void StopDecrypting(void);
176 virtual uchar *Decrypt(uchar *Data, int &Count);
177 virtual bool TsPostProcess(uchar *Data);
178 virtual void InjectEit(int Sid);
179 int PutData(const uchar *Data, int Count);
180 int PutCat(const uchar *Data, int Count);
181 // The following functions shall not be called for a cMtdCamSlot:
182 virtual cCamSlot *Spawn(void) { MTD_DONT_CALL(NULL); }
183 virtual bool Reset(void) { MTD_DONT_CALL(false); }
185 virtual const char *GetCamName(void) { MTD_DONT_CALL(NULL); }
186 virtual bool Ready(void) { MTD_DONT_CALL(false); }
187 virtual bool HasMMI(void) { MTD_DONT_CALL(false); }
188 virtual bool HasUserIO(void) { MTD_DONT_CALL(false); }
189 virtual bool EnterMenu(void) { MTD_DONT_CALL(false); }
190 virtual cCiMenu *GetMenu(void) { MTD_DONT_CALL(NULL); }
191 virtual cCiEnquiry *GetEnquiry(void) { MTD_DONT_CALL(NULL); }
192 };
193
194#endif //__MTD_H
eModuleStatus
Definition: ci.h:170
@ msNone
Definition: ci.h:170
Definition: ci.h:232
cCamSlot * MasterSlot(void)
Returns this CAM slot's master slot, or a pointer to itself if it is a master slot.
Definition: ci.h:309
Definition: ci.h:148
Definition: ci.h:119
int Index(void) const
Definition: tools.c:2104
cMtdMapper * mtdMapper
virtual cCiMenu * GetMenu(void)
Gets a pending menu, or NULL if there is no menu.
Definition: mtd.h:190
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
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 ...
virtual cCamSlot * Spawn(void)
Definition: mtd.h:182
virtual eModuleStatus ModuleStatus(void)
Returns the status of the CAM in this slot.
Definition: mtd.h:184
virtual uchar * Decrypt(uchar *Data, int &Count)
If this is a CAM slot that can be freely assigned to any device, but will not be directly inserted in...
cMtdCamSlot(cCamSlot *MasterSlot, int Index)
Creates a new "Multi Transponder Decryption" CAM slot, connected to the given physical MasterSlot,...
virtual cCiEnquiry * GetEnquiry(void)
Gets a pending enquiry, or NULL if there is no enquiry.
Definition: mtd.h:191
virtual bool HasMMI(void)
Returns 'true' if the CAM in this slot has an active MMI.
Definition: mtd.h:187
virtual bool CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper=NULL)
Returns true if there is a CAM in this slot that is able to decrypt the given Channel (or at least cl...
virtual const char * GetCamName(void)
Returns the name of the CAM in this slot, or NULL if there is no ready CAM in this slot.
Definition: mtd.h:185
virtual bool EnterMenu(void)
Requests the CAM in this slot to start its menu.
Definition: mtd.h:189
cMtdMapper * MtdMapper(void)
Definition: mtd.h:170
virtual void SendCaPmt(uint8_t CmdId)
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
virtual const int * GetCaSystemIds(void)
int PutCat(const uchar *Data, int Count)
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
virtual ~cMtdCamSlot()
virtual bool Ready(void)
Returns 'true' if the CAM in this slot is ready to decrypt.
Definition: mtd.h:186
cRingBufferLinear * mtdBuffer
virtual bool Reset(void)
Resets the CAM in this slot.
Definition: mtd.h:183
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
int PutData(const uchar *Data, int Count)
virtual bool HasUserIO(void)
Returns true if there is a pending user interaction, which shall be retrieved via GetMenu() or GetEnq...
Definition: mtd.h:188
int Put(const uchar *Data, int Count)
Puts at most Count bytes of Data into the CAM slot which's index is derived from the PID of the TS pa...
bool IsActivating(void)
Returns true if any of the active MTD CAM slots is currently activating.
void StartDecrypting(void)
Tells all active MTD CAM slots to start decrypting.
cMtdHandler(void)
Creates a new MTD handler that distributes TS data received through calls to the Put() function to th...
bool IsDecrypting(void)
Returns true if any of the active MTD CAM slots is currently decrypting.
void CancelActivation(void)
Tells all active MTD CAM slots to cancel activation.
cMtdCamSlot * GetMtdCamSlot(cCamSlot *MasterSlot)
Creates a new MTD CAM slot, or reuses an existing one that is currently unused.
void StopDecrypting(void)
Tells all active MTD CAM slots to stop decrypting.
cVector< cMtdCamSlot * > camSlots
int Priority(void)
Returns the maximum priority of any of the active MTD CAM slots.
void UnAssignAll(void)
Unassigns all MTD CAM slots from their devices.
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of the devices of any active MTD CAM slots to the given DeviceNumbers.
unsigned char uchar
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
Definition: mtd.c:241
#define MTD_DONT_CALL(v)
Definition: mtd.h:149
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
Definition: mtd.c:233