Now only those Ca descriptors are sent to a CAM that are actually understood by that CAM

This commit is contained in:
Klaus Schmidinger 2003-04-18 12:48:49 +02:00
parent b57eae00d3
commit 78d85cee06
6 changed files with 81 additions and 58 deletions

View File

@ -2039,3 +2039,5 @@ Video Disk Recorder Revision History
- Using masks in EIT filtering to reduce the number of filters (thanks to Andreas - Using masks in EIT filtering to reduce the number of filters (thanks to Andreas
Schultz). Schultz).
- Fixed handling Ca descriptors (thanks to Stefan Huelswitt). - Fixed handling Ca descriptors (thanks to Stefan Huelswitt).
- Now only those Ca descriptors are sent to a CAM that are actually understood
by that CAM.

43
ci.c
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ci.c 1.9 2003/03/23 15:18:40 kls Exp $ * $Id: ci.c 1.10 2003/04/18 12:48:49 kls Exp $
*/ */
/* XXX TODO /* XXX TODO
@ -769,7 +769,7 @@ public:
cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc) cCiApplicationInformation::cCiApplicationInformation(int SessionId, cCiTransportConnection *Tc)
:cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc) :cCiSession(SessionId, RI_APPLICATION_INFORMATION, Tc)
{ {
dbgprotocol("New Aplication Information (session id %d)\n", SessionId); dbgprotocol("New Application Information (session id %d)\n", SessionId);
state = 0; state = 0;
creationTime = time(NULL); creationTime = time(NULL);
menuString = NULL; menuString = NULL;
@ -827,12 +827,17 @@ bool cCiApplicationInformation::EnterMenu(void)
// --- cCiConditionalAccessSupport ------------------------------------------- // --- cCiConditionalAccessSupport -------------------------------------------
#define MAXCASYSTEMIDS 16
class cCiConditionalAccessSupport : public cCiSession { class cCiConditionalAccessSupport : public cCiSession {
private: private:
int state; int state;
int numCaSystemIds;
unsigned short caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
public: public:
cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc); cCiConditionalAccessSupport(int SessionId, cCiTransportConnection *Tc);
virtual bool Process(int Length = 0, const uint8_t *Data = NULL); virtual bool Process(int Length = 0, const uint8_t *Data = NULL);
const unsigned short *GetCaSystemIds(void) { return caSystemIds; }
bool SendPMT(cCiCaPmt &CaPmt); bool SendPMT(cCiCaPmt &CaPmt);
}; };
@ -841,6 +846,7 @@ cCiConditionalAccessSupport::cCiConditionalAccessSupport(int SessionId, cCiTrans
{ {
dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId); dbgprotocol("New Conditional Access Support (session id %d)\n", SessionId);
state = 0; state = 0;
caSystemIds[numCaSystemIds = 0] = 0;
} }
bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data) bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data)
@ -853,9 +859,16 @@ bool cCiConditionalAccessSupport::Process(int Length, const uint8_t *Data)
int l = 0; int l = 0;
const uint8_t *d = GetData(Data, l); const uint8_t *d = GetData(Data, l);
while (l > 1) { while (l > 1) {
dbgprotocol(" %04X", ((unsigned int)(*d) << 8) | *(d + 1)); unsigned short id = ((unsigned short)(*d) << 8) | *(d + 1);
dbgprotocol(" %04X", id);
d += 2; d += 2;
l -= 2; l -= 2;
if (numCaSystemIds < MAXCASYSTEMIDS) {
caSystemIds[numCaSystemIds++] = id;
caSystemIds[numCaSystemIds] = 0;
}
else
esyslog("ERROR: too many CA system IDs!");
} }
dbgprotocol("\n"); dbgprotocol("\n");
} }
@ -1274,6 +1287,7 @@ cCiHandler::cCiHandler(int Fd, int NumSlots)
{ {
numSlots = NumSlots; numSlots = NumSlots;
enabled = true; enabled = true;
newCaSupport = false;
for (int i = 0; i < MAX_CI_SESSION; i++) for (int i = 0; i < MAX_CI_SESSION; i++)
sessions[i] = NULL; sessions[i] = NULL;
tpl = new cCiTransportLayer(Fd, numSlots); tpl = new cCiTransportLayer(Fd, numSlots);
@ -1358,7 +1372,8 @@ cCiSession *cCiHandler::CreateSession(int ResourceId)
switch (ResourceId) { switch (ResourceId) {
case RI_RESOURCE_MANAGER: return sessions[i] = new cCiResourceManager(i + 1, tc); case RI_RESOURCE_MANAGER: return sessions[i] = new cCiResourceManager(i + 1, tc);
case RI_APPLICATION_INFORMATION: return sessions[i] = new cCiApplicationInformation(i + 1, tc); case RI_APPLICATION_INFORMATION: return sessions[i] = new cCiApplicationInformation(i + 1, tc);
case RI_CONDITIONAL_ACCESS_SUPPORT: return sessions[i] = new cCiConditionalAccessSupport(i + 1, tc); case RI_CONDITIONAL_ACCESS_SUPPORT: newCaSupport = true;
return sessions[i] = new cCiConditionalAccessSupport(i + 1, tc);
case RI_HOST_CONTROL: break; //XXX case RI_HOST_CONTROL: break; //XXX
case RI_DATE_TIME: return sessions[i] = new cCiDateTime(i + 1, tc); case RI_DATE_TIME: return sessions[i] = new cCiDateTime(i + 1, tc);
case RI_MMI: return sessions[i] = new cCiMMI(i + 1, tc); case RI_MMI: return sessions[i] = new cCiMMI(i + 1, tc);
@ -1470,6 +1485,8 @@ bool cCiHandler::Process(void)
if (sessions[i]) if (sessions[i])
sessions[i]->Process(); sessions[i]->Process();
} }
if (newCaSupport)
newCaSupport = result = false; // triggers new SetCaPmt at caller!
return result; return result;
} }
@ -1502,16 +1519,18 @@ cCiEnquiry *cCiHandler::GetEnquiry(void)
return NULL; return NULL;
} }
bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt) const unsigned short *cCiHandler::GetCaSystemIds(int Slot)
{ {
cMutexLock MutexLock(&mutex); cMutexLock MutexLock(&mutex);
bool result = false; cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
for (int Slot = 0; Slot < numSlots; Slot++) { return cas ? cas->GetCaSystemIds() : NULL;
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot); }
if (cas)
result |= cas->SendPMT(CaPmt); bool cCiHandler::SetCaPmt(cCiCaPmt &CaPmt, int Slot)
} {
return result; cMutexLock MutexLock(&mutex);
cCiConditionalAccessSupport *cas = (cCiConditionalAccessSupport *)GetSessionByResourceId(RI_CONDITIONAL_ACCESS_SUPPORT, Slot);
return cas && cas->SendPMT(CaPmt);
} }
bool cCiHandler::Reset(int Slot) bool cCiHandler::Reset(int Slot)

7
ci.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: ci.h 1.4 2003/03/23 15:18:40 kls Exp $ * $Id: ci.h 1.5 2003/04/18 12:41:48 kls Exp $
*/ */
#ifndef __CI_H #ifndef __CI_H
@ -81,6 +81,7 @@ private:
cMutex mutex; cMutex mutex;
int numSlots; int numSlots;
bool enabled; bool enabled;
bool newCaSupport;
cCiSession *sessions[MAX_CI_SESSION]; cCiSession *sessions[MAX_CI_SESSION];
cCiTransportLayer *tpl; cCiTransportLayer *tpl;
cCiTransportConnection *tc; cCiTransportConnection *tc;
@ -96,12 +97,14 @@ private:
public: public:
~cCiHandler(); ~cCiHandler();
static cCiHandler *CreateCiHandler(const char *FileName); static cCiHandler *CreateCiHandler(const char *FileName);
int NumSlots(void) { return numSlots; }
void SetEnabled(bool Enabled) { enabled = Enabled; } void SetEnabled(bool Enabled) { enabled = Enabled; }
bool Process(void); bool Process(void);
bool EnterMenu(int Slot); bool EnterMenu(int Slot);
cCiMenu *GetMenu(void); cCiMenu *GetMenu(void);
cCiEnquiry *GetEnquiry(void); cCiEnquiry *GetEnquiry(void);
bool SetCaPmt(cCiCaPmt &CaPmt); const unsigned short *GetCaSystemIds(int Slot);
bool SetCaPmt(cCiCaPmt &CaPmt, int Slot);
bool Reset(int Slot); bool Reset(int Slot);
}; };

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and * See the main source file 'vdr.c' for copyright information and
* how to reach the author. * how to reach the author.
* *
* $Id: dvbdevice.c 1.51 2003/04/12 15:06:11 kls Exp $ * $Id: dvbdevice.c 1.52 2003/04/18 11:35:08 kls Exp $
*/ */
#include "dvbdevice.h" #include "dvbdevice.h"
@ -264,27 +264,29 @@ void cDvbTuner::Action(void)
} }
} }
if (tunerStatus >= tsLocked) { if (tunerStatus >= tsLocked) {
if (ciHandler && channel.Ca()) { if (ciHandler && channel.Ca() > CACONFBASE) {
if (ciHandler->Process()) { if (ciHandler->Process()) {
if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed
uchar buffer[2048]; for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) {
int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), sizeof(buffer), buffer); uchar buffer[2048];
if (length > 0) { int length = cSIProcessor::GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer);
cCiCaPmt CaPmt(channel.Sid()); if (length > 0) {
CaPmt.AddCaDescriptor(length, buffer); cCiCaPmt CaPmt(channel.Sid());
if (channel.Vpid()) CaPmt.AddCaDescriptor(length, buffer);
CaPmt.AddPid(channel.Vpid()); if (channel.Vpid())
if (channel.Apid1()) CaPmt.AddPid(channel.Vpid());
CaPmt.AddPid(channel.Apid1()); if (channel.Apid1())
if (channel.Apid2()) CaPmt.AddPid(channel.Apid1());
CaPmt.AddPid(channel.Apid2()); if (channel.Apid2())
if (channel.Dpid1()) CaPmt.AddPid(channel.Apid2());
CaPmt.AddPid(channel.Dpid1()); if (channel.Dpid1())
if (ciHandler->SetCaPmt(CaPmt)) { CaPmt.AddPid(channel.Dpid1());
tunerStatus = tsCam; if (ciHandler->SetCaPmt(CaPmt, Slot)) {
startTime = 0; tunerStatus = tsCam;
} startTime = 0;
} }
}
}
} }
} }
else else

38
eit.c
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.c 1.70 2003/04/18 11:29:11 kls Exp $ * $Id: eit.c 1.71 2003/04/18 11:30:42 kls Exp $
***************************************************************************/ ***************************************************************************/
#include "eit.h" #include "eit.h"
@ -1059,12 +1059,8 @@ public:
const cCaDescriptor *cCaDescriptors::Get(int Source, int Transponder, int ServiceId, int CaSystem) const cCaDescriptor *cCaDescriptors::Get(int Source, int Transponder, int ServiceId, int CaSystem)
{ {
for (cCaDescriptor *ca = First(); ca; ca = Next(ca)) { for (cCaDescriptor *ca = First(); ca; ca = Next(ca)) {
if (ca->source == Source && ca->transponder == Transponder && ca->serviceId == ServiceId) { if (ca->source == Source && ca->transponder == Transponder && ca->serviceId == ServiceId && ca->caSystem == CaSystem)
if (CaSystem == -1 || ca->caSystem == CaSystem) return ca;
return ca;
if (CaSystem < 0)
CaSystem++;
}
} }
return NULL; return NULL;
} }
@ -1452,24 +1448,24 @@ void cSIProcessor::NewCaDescriptor(struct Descriptor *d, int ProgramID)
} }
} }
int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data) int cSIProcessor::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data)
{ {
if (!CaSystemIds || !*CaSystemIds)
return 0;
if (BufSize > 0 && Data) { if (BufSize > 0 && Data) {
cMutexLock MutexLock(&caDescriptorsMutex); cMutexLock MutexLock(&caDescriptorsMutex);
int length = 0; int length = 0;
for (int i = -1; ; i--) { do {
const cCaDescriptor *d = caDescriptors->Get(Source, Transponder, ServiceId, i); const cCaDescriptor *d = caDescriptors->Get(Source, Transponder, ServiceId, *CaSystemIds);
if (d) { if (d) {
if (length + d->Length() <= BufSize) { if (length + d->Length() <= BufSize) {
memcpy(Data + length, d->Data(), d->Length()); memcpy(Data + length, d->Data(), d->Length());
length += d->Length(); length += d->Length();
} }
else else
return -1; return -1;
} }
else } while (*++CaSystemIds);
break;
}
return length; return length;
} }
return -1; return -1;

7
eit.h
View File

@ -16,7 +16,7 @@
* the Free Software Foundation; either version 2 of the License, or * * the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. * * (at your option) any later version. *
* * * *
* $Id: eit.h 1.26 2003/04/13 14:01:24 kls Exp $ * $Id: eit.h 1.27 2003/04/18 11:30:42 kls Exp $
***************************************************************************/ ***************************************************************************/
#ifndef __EIT_H #ifndef __EIT_H
@ -168,10 +168,11 @@ public:
// Caller must provide a cMutexLock which has to survive the entire // Caller must provide a cMutexLock which has to survive the entire
// time the returned cSchedules is accessed. Once the cSchedules is no // time the returned cSchedules is accessed. Once the cSchedules is no
// longer used, the cMutexLock must be destroyed. // longer used, the cMutexLock must be destroyed.
static int GetCaDescriptors(int Source, int Transponder, int ServiceId, int BufSize, uchar *Data); static int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data);
///< Gets all CA descriptors for a given channel. ///< Gets all CA descriptors for a given channel.
///< Copies all available CA descriptors for the given Source, Transponder and ServiceId ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId
///< into the provided buffer at Data (at most BufSize bytes). ///< into the provided buffer at Data (at most BufSize bytes). Only those CA descriptors
///< are copied that match one of the given CA system IDs.
///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are ///< \return Returns the number of bytes copied into Data (0 if no CA descriptors are
///< available), or -1 if BufSize was too small to hold all CA descriptors. ///< available), or -1 if BufSize was too small to hold all CA descriptors.
static bool Read(FILE *f = NULL); static bool Read(FILE *f = NULL);