vdr 2.6.6
mtd.c
Go to the documentation of this file.
1/*
2 * mtd.c: 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.c 1.16 2020/06/16 14:33:32 kls Exp $
8 */
9
10#include "mtd.h"
11#include "receiver.h"
12
13//#define DEBUG_MTD
14#ifdef DEBUG_MTD
15#define DBGMTD(a...) dsyslog(a)
16#else
17#define DBGMTD(a...)
18#endif
19
20//#define KEEPPIDS // for testing and debugging - USE ONLY IF YOU KNOW WHAT YOU ARE DOING!
21
22#define MAX_REAL_PIDS MAXPID // real PIDs are 13 bit (0x0000 - 0x1FFF)
23#ifdef KEEPPIDS
24#define MAX_UNIQ_PIDS MAXPID
25#define UNIQ_PID_MASK 0x1FFF
26#else
27#define MAX_UNIQ_PIDS 256 // uniq PIDs are 8 bit (0x00 - 0xFF)
28#define UNIQ_PID_MASK 0x00FF
29#define UNIQ_PID_SHIFT 8
30#endif // KEEPPIDS
31
32// --- cMtdHandler -----------------------------------------------------------
33
37
39{
40 for (int i = 0; i < camSlots.Size(); i++) {
41 dsyslog("CAM %d/%d: deleting MTD CAM slot", camSlots[i]->MasterSlot()->SlotNumber(), i + 1);
42 delete camSlots[i];
43 }
44}
45
47{
48 for (int i = 0; i < camSlots.Size(); i++) {
49 if (!camSlots[i]->Device()) {
50 dsyslog("CAM %d/%d: reusing MTD CAM slot", MasterSlot->SlotNumber(), i + 1);
51 return camSlots[i];
52 }
53 }
54 dsyslog("CAM %d/%d: creating new MTD CAM slot", MasterSlot->SlotNumber(), camSlots.Size() + 1);
55 cMtdCamSlot *s = new cMtdCamSlot(MasterSlot, camSlots.Size());
57 return s;
58}
59
60int cMtdHandler::Put(const uchar *Data, int Count)
61{
62 int Used = 0;
63 while (Count >= TS_SIZE) {
64 if (int Skipped = TS_SYNC(Data, Count))
65 return Used + Skipped;
66 int Pid = TsPid(Data);
67#ifdef KEEPPIDS
68 int Index = 0;
69#else
70 int Index = (Pid >> UNIQ_PID_SHIFT) - 1;
71#endif // KEEPPIDS
72 if (Index >= 0 && Index < camSlots.Size()) {
73 int w = camSlots[Index]->PutData(Data, TS_SIZE);
74 if (w == 0)
75 break;
76 else if (w != TS_SIZE)
77 esyslog("ERROR: incomplete MTD packet written (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
78 }
79 else if (Index >= 0) // anything with Index -1 (i.e. MTD number 0) is either garbage or an actual CAT or EIT, which need not be returned to the device
80 esyslog("ERROR: invalid MTD number (%d) in PID %d (%04X)", Index + 1, Pid, Pid);
81 Data += TS_SIZE;
82 Count -= TS_SIZE;
83 Used += TS_SIZE;
84 }
85 return Used;
86}
87
89{
90 int p = IDLEPRIORITY;
91 for (int i = 0; i < camSlots.Size(); i++)
92 p = max(p, camSlots[i]->Priority());
93 return p;
94}
95
97{
98 for (int i = 0; i < camSlots.Size(); i++) {
99 if (camSlots[i]->IsDecrypting())
100 return true;
101 }
102 return false;
103}
104
106{
107 for (int i = 0; i < camSlots.Size(); i++) {
108 if (camSlots[i]->Device()) {
109 camSlots[i]->TriggerResendPmt();
110 camSlots[i]->StartDecrypting();
111 }
112 }
113}
114
116{
117 for (int i = 0; i < camSlots.Size(); i++) {
118 if (camSlots[i]->Device())
119 camSlots[i]->StopDecrypting();
120 }
121}
122
124{
125 for (int i = 0; i < camSlots.Size(); i++)
127}
128
130{
131 for (int i = 0; i < camSlots.Size(); i++) {
132 if (camSlots[i]->IsActivating())
133 return true;
134 }
135 return false;
136}
137
139{
140 for (int i = 0; i < camSlots.Size(); i++)
141 camSlots[i]->Devices(DeviceNumbers);
142 return DeviceNumbers.Size() > 0;
143}
144
146{
147 for (int i = 0; i < camSlots.Size(); i++)
148 camSlots[i]->Assign(NULL);
149}
150
151// --- cMtdMapper ------------------------------------------------------------
152
153#define MTD_INVALID_PID 0xFFFF
154
156private:
160 uint16_t uniqPids[MAX_REAL_PIDS]; // maps a real PID to a unique PID
161 uint16_t realPids[MAX_UNIQ_PIDS]; // maps a unique PID to a real PID
163 uint16_t MakeUniqPid(uint16_t RealPid);
164public:
165 cMtdMapper(int Number, int MasterCamSlotNumber);
166 ~cMtdMapper();
167 uint16_t RealToUniqPid(uint16_t RealPid) { if (uniqPids[RealPid]) return uniqPids[RealPid]; return MakeUniqPid(RealPid); }
168 uint16_t UniqToRealPid(uint16_t UniqPid) { return realPids[UniqPid & UNIQ_PID_MASK]; }
169 uint16_t RealToUniqSid(uint16_t RealSid);
170 void Clear(void);
171 };
172
173cMtdMapper::cMtdMapper(int Number, int MasterCamSlotNumber)
174{
175 number = Number;
176 masterCamSlotNumber = MasterCamSlotNumber;
177 nextUniqPid = 0;
178 Clear();
179}
180
184
185uint16_t cMtdMapper::MakeUniqPid(uint16_t RealPid)
186{
187#ifdef KEEPPIDS
188 uniqPids[RealPid] = realPids[RealPid] = RealPid;
189 DBGMTD("CAM %d/%d: mapped PID %d (%04X) to %d (%04X)", masterCamSlotNumber, number, RealPid, RealPid, uniqPids[RealPid], uniqPids[RealPid]);
190 return uniqPids[RealPid];
191#else
192 for (int p = 0; p < MAX_UNIQ_PIDS; p++) {
193 int i = nextUniqPid + p;
194 if (i >= MAX_UNIQ_PIDS)
195 i -= MAX_UNIQ_PIDS;
196 if (realPids[i] == MTD_INVALID_PID) { // 0x0000 is a valid PID (PAT)!
197 realPids[i] = RealPid;
198 uniqPids[RealPid] = (number << UNIQ_PID_SHIFT) | i;
199 DBGMTD("CAM %d/%d: mapped PID %d (%04X) to %d (%04X)", masterCamSlotNumber, number, RealPid, RealPid, uniqPids[RealPid], uniqPids[RealPid]);
200 nextUniqPid = i + 1;
201 return uniqPids[RealPid];
202 }
203 }
204#endif // KEEPPIDS
205 esyslog("ERROR: MTD %d: mapper ran out of unique PIDs", number);
206 return 0;
207}
208
209uint16_t cMtdMapper::RealToUniqSid(uint16_t RealSid)
210{
211#ifdef KEEPPIDS
212 return RealSid;
213#endif // KEEPPIDS
214 int UniqSid = uniqSids.IndexOf(RealSid);
215 if (UniqSid < 0) {
216 UniqSid = uniqSids.Size();
217 uniqSids.Append(RealSid);
218 DBGMTD("CAM %d/%d: mapped SID %d (%04X) to %d (%04X)", masterCamSlotNumber, number, RealSid, RealSid, UniqSid | (number << UNIQ_PID_SHIFT), UniqSid | (number << UNIQ_PID_SHIFT));
219 }
220 UniqSid |= number << UNIQ_PID_SHIFT;
221 return UniqSid;
222}
223
225{
226 DBGMTD("CAM %d/%d: MTD mapper cleared", masterCamSlotNumber, number);
227 memset(uniqPids, 0, sizeof(uniqPids));
228 memset(realPids, MTD_INVALID_PID, sizeof(realPids));
229 // do not reset nextUniqPid here!
230 uniqSids.Clear();
231}
232
233void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
234{
235 uint16_t RealSid = p[0] << 8 | p[1];
236 uint16_t UniqSid = MtdMapper->RealToUniqSid(RealSid);
237 p[0] = UniqSid >> 8;
238 p[1] = UniqSid & 0xff;
239}
240
241void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
242{
243 Poke13(p, MtdMapper->RealToUniqPid(Peek13(p)));
244}
245
246// --- cMtdCamSlot -----------------------------------------------------------
247
248#define MTD_BUFFER_SIZE MEGABYTE(1)
249
250cMtdCamSlot::cMtdCamSlot(cCamSlot *MasterSlot, int Index)
251:cCamSlot(NULL, true, MasterSlot)
252{
253 mtdBuffer = new cRingBufferLinear(MTD_BUFFER_SIZE, TS_SIZE, true, "MTD buffer");
255 delivered = false;
256 ciAdapter = MasterSlot->ciAdapter; // we don't pass the CI adapter in the constructor, to prevent this one from being inserted into CamSlots
257}
258
260{
261 Assign(NULL);
262 delete mtdMapper;
263 delete mtdBuffer;
264}
265
267{
268 return MasterSlot()->GetCaSystemIds();
269}
270
271void cMtdCamSlot::SendCaPmt(uint8_t CmdId)
272{
273 cMutexLock MutexLock(&mutex);
274 cCiCaPmtList CaPmtList;
275 BuildCaPmts(CmdId, CaPmtList, mtdMapper);
276 MasterSlot()->SendCaPmts(CaPmtList);
277}
278
280{
281 return MasterSlot()->RepliesToQuery();
282}
283
284bool cMtdCamSlot::ProvidesCa(const int *CaSystemIds)
285{
286 return MasterSlot()->ProvidesCa(CaSystemIds);
287}
288
289bool cMtdCamSlot::CanDecrypt(const cChannel *Channel, cMtdMapper *MtdMapper)
290{
291 return MasterSlot()->CanDecrypt(Channel, mtdMapper);
292}
293
299
301{
303 cMutexLock MutexLock(&clearMutex);
304 mtdMapper->Clear();
305 mtdBuffer->Clear();
306 delivered = false;
307}
308
310{
311 // Send data to CAM:
312 if (Count >= TS_SIZE) {
313 Count = TS_SIZE;
314 int Pid = TsPid(Data);
315 TsSetPid(Data, mtdMapper->RealToUniqPid(Pid));
316 MasterSlot()->Decrypt(Data, Count);
317 if (Count == 0)
318 TsSetPid(Data, Pid); // must restore PID for later retry
319 }
320 else
321 Count = 0;
322 // Drop delivered data from previous call:
323 cMutexLock MutexLock(&clearMutex);
324 if (delivered) {
326 delivered = false;
327 }
328 // Receive data from buffer:
329 int c = 0;
330 uchar *d = mtdBuffer->Get(c);
331 if (d) {
332 if (int Skipped = TS_SYNC(d, c)) {
333 mtdBuffer->Del(Skipped);
334 return NULL;
335 }
336 if (c >= TS_SIZE) {
338 delivered = true;
339 }
340 else
341 d = NULL;
342 }
343 return d;
344}
345
347{
348 return MasterSlot()->TsPostProcess(Data);
349}
350
355
356int cMtdCamSlot::PutData(const uchar *Data, int Count)
357{
358 int Free = mtdBuffer->Free();
359 Free -= Free % TS_SIZE;
360 if (Free < TS_SIZE)
361 return 0;
362 if (Free < Count)
363 Count = Free;
364 return mtdBuffer->Put(Data, Count);
365}
366
367int cMtdCamSlot::PutCat(const uchar *Data, int Count)
368{
369 MasterSlot()->Decrypt(const_cast<uchar *>(Data), Count);
370 return Count;
371}
Definition ci.h:232
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
Definition ci.c:2520
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 ...
Definition ci.c:2830
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
cMutex mutex
Definition ci.h:238
friend class cMtdCamSlot
Definition ci.h:236
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...
Definition ci.c:2740
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...
Definition ci.c:2813
virtual const int * GetCaSystemIds(void)
Definition ci.c:2649
virtual bool Assign(cDevice *Device, bool Query=false)
Assigns this CAM slot to the given Device, if this is possible.
Definition ci.c:2221
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
Definition ci.c:2776
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
Definition ci.c:2820
cCiAdapter * ciAdapter
Definition ci.h:240
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
Definition ci.c:2781
void SendCaPmts(cCiCaPmtList &CaPmtList)
Sends the given list of CA_PMTs to the CAM.
Definition ci.c:2603
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.
Definition ci.c:2527
int SlotNumber(void)
Returns the number of this CAM slot within the whole system.
Definition ci.h:344
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
Definition ci.c:2664
int Index(void) const
Definition tools.c:2132
cMutex clearMutex
Definition mtd.h:158
virtual void StartDecrypting(void)
Sends all CA_PMT entries to the CAM that have been modified since the last call to this function.
Definition mtd.c:294
virtual void StopDecrypting(void)
Clears the list of CA_PMT entries and tells the CAM to stop decrypting.
Definition mtd.c:300
virtual bool TsPostProcess(uchar *Data)
If there is a cCiSession that needs to do additional processing on TS packets (after the CAM has done...
Definition mtd.c:346
virtual void SendCaPmt(uint8_t CmdId)
Definition mtd.c:271
cRingBufferLinear * mtdBuffer
Definition mtd.h:160
virtual ~cMtdCamSlot()
Definition mtd.c:259
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...
Definition mtd.c:289
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 ...
Definition mtd.c:351
virtual bool ProvidesCa(const int *CaSystemIds)
Returns true if the CAM in this slot provides one of the given CaSystemIds.
Definition mtd.c:284
bool delivered
Definition mtd.h:161
virtual bool RepliesToQuery(void)
Returns true if the CAM in this slot replies to queries and thus supports MCD ("Multi Channel Decrypt...
Definition mtd.c:279
virtual const int * GetCaSystemIds(void)
Definition mtd.c:266
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...
Definition mtd.c:309
int PutCat(const uchar *Data, int Count)
Definition mtd.c:367
cMtdMapper * mtdMapper
Definition mtd.h:159
int PutData(const uchar *Data, int Count)
Definition mtd.c:356
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...
Definition mtd.c:60
~cMtdHandler()
Definition mtd.c:38
bool IsActivating(void)
Returns true if any of the active MTD CAM slots is currently activating.
Definition mtd.c:129
cVector< cMtdCamSlot * > camSlots
Definition mtd.h:113
void StartDecrypting(void)
Tells all active MTD CAM slots to start decrypting.
Definition mtd.c:105
cMtdHandler(void)
Creates a new MTD handler that distributes TS data received through calls to the Put() function to th...
Definition mtd.c:34
bool IsDecrypting(void)
Returns true if any of the active MTD CAM slots is currently decrypting.
Definition mtd.c:96
void CancelActivation(void)
Tells all active MTD CAM slots to cancel activation.
Definition mtd.c:123
cMtdCamSlot * GetMtdCamSlot(cCamSlot *MasterSlot)
Creates a new MTD CAM slot, or reuses an existing one that is currently unused.
Definition mtd.c:46
void StopDecrypting(void)
Tells all active MTD CAM slots to stop decrypting.
Definition mtd.c:115
int Priority(void)
Returns the maximum priority of any of the active MTD CAM slots.
Definition mtd.c:88
void UnAssignAll(void)
Unassigns all MTD CAM slots from their devices.
Definition mtd.c:145
bool Devices(cVector< int > &DeviceNumbers)
Adds the numbers of the devices of any active MTD CAM slots to the given DeviceNumbers.
Definition mtd.c:138
cVector< uint16_t > uniqSids
Definition mtd.c:162
uint16_t MakeUniqPid(uint16_t RealPid)
Definition mtd.c:185
uint16_t uniqPids[MAX_REAL_PIDS]
Definition mtd.c:160
int nextUniqPid
Definition mtd.c:159
uint16_t realPids[MAX_UNIQ_PIDS]
Definition mtd.c:161
uint16_t RealToUniqPid(uint16_t RealPid)
Definition mtd.c:167
uint16_t RealToUniqSid(uint16_t RealSid)
Definition mtd.c:209
~cMtdMapper()
Definition mtd.c:181
uint16_t UniqToRealPid(uint16_t UniqPid)
Definition mtd.c:168
void Clear(void)
Definition mtd.c:224
int masterCamSlotNumber
Definition mtd.c:158
cMtdMapper(int Number, int MasterCamSlotNumber)
Definition mtd.c:173
int number
Definition mtd.c:157
void Del(int Count)
Deletes at most Count bytes from the ring buffer.
Definition ringbuffer.c:371
int Put(const uchar *Data, int Count)
Puts at most Count bytes of Data into the ring buffer.
Definition ringbuffer.c:306
virtual void Clear(void)
Immediately clears the ring buffer.
Definition ringbuffer.c:217
uchar * Get(int &Count)
Gets data from the ring buffer.
Definition ringbuffer.c:346
virtual int Free(void)
Definition ringbuffer.h:80
int Size(void) const
Definition tools.h:767
int IndexOf(const T &Data)
Definition tools.h:759
virtual void Clear(void)
Definition tools.h:818
virtual void Append(T Data)
Definition tools.h:787
#define IDLEPRIORITY
Definition config.h:47
void MtdMapPid(uchar *p, cMtdMapper *MtdMapper)
Definition mtd.c:241
#define UNIQ_PID_MASK
Definition mtd.c:28
#define MAX_UNIQ_PIDS
Definition mtd.c:27
#define UNIQ_PID_SHIFT
Definition mtd.c:29
#define MTD_INVALID_PID
Definition mtd.c:153
#define MTD_BUFFER_SIZE
Definition mtd.c:248
#define MAX_REAL_PIDS
Definition mtd.c:22
#define DBGMTD(a...)
Definition mtd.c:17
void MtdMapSid(uchar *p, cMtdMapper *MtdMapper)
Definition mtd.c:233
int TsPid(const uchar *p)
Definition remux.h:82
#define TS_SIZE
Definition remux.h:34
void TsSetPid(uchar *p, int Pid)
Definition remux.h:87
#define TS_SYNC(Data, Length)
Definition remux.h:149
uint16_t Peek13(const uchar *p)
Definition tools.h:293
unsigned char uchar
Definition tools.h:31
#define dsyslog(a...)
Definition tools.h:37
void Poke13(uchar *p, uint16_t v)
Definition tools.h:298
T max(T a, T b)
Definition tools.h:64
#define esyslog(a...)
Definition tools.h:35