diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 66aae300..1ae39e7d 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -83,6 +83,8 @@ Dave Chapman Hans-Peter Raschke for his support in adapting VDR to DVB-C for adding the 'statdvb2vdr' tool (see Tools/statdvb2vdr) + for reporting that the CA descriptors need to be sent to the CAM in the 'program' + or 'ES level' sections to make SkyCrypt CAMs work Peter Hofmann for his support in adapting VDR to DVB-C diff --git a/HISTORY b/HISTORY index 43fa1b4d..fbf27cf9 100644 --- a/HISTORY +++ b/HISTORY @@ -2508,3 +2508,6 @@ Video Disk Recorder Revision History Miguel Sequeira de Justo Teixeira for reporting this one). - Added 'StreamType' setting to CAM communication, which is important for Aston/SECA CAMs (thanks to Antonino Sergi). +- Now the CA descriptors are sent to the CAM in the 'program' or 'ES level' + sections, depending on where they are found in the PMT (thanks to Hans-Peter + Raschke for reporting this one). This should make SkyCrypt CAMs work. diff --git a/ci.c b/ci.c index d4477d55..a6f60562 100644 --- a/ci.c +++ b/ci.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.c 1.19 2003/12/23 10:19:56 kls Exp $ + * $Id: ci.c 1.20 2003/12/24 10:23:24 kls Exp $ */ /* XXX TODO @@ -22,6 +22,7 @@ XXX*/ #include #include #include +#include "pat.h" #include "tools.h" /* these might come in handy in case you want to use this code without VDR's other files: @@ -1266,8 +1267,9 @@ bool cCiEnquiry::Cancel(void) #define CPCI_QUERY 0x03 #define CPCI_NOT_SELECTED 0x04 -cCiCaPmt::cCiCaPmt(int ProgramNumber) +cCiCaPmt::cCiCaPmt(int Source, int Transponder, int ProgramNumber, const unsigned short *CaSystemIds) { + caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag); length = 0; capmt[length++] = CPLM_ONLY; capmt[length++] = (ProgramNumber >> 8) & 0xFF; @@ -1276,20 +1278,31 @@ cCiCaPmt::cCiCaPmt(int ProgramNumber) esInfoLengthPos = length; capmt[length++] = 0x00; // program_info_length H (at program level) capmt[length++] = 0x00; // program_info_length L + if (!streamFlag) + AddCaDescriptors(caDescriptorsLength, caDescriptors); +} + +bool cCiCaPmt::Valid(void) +{ + return caDescriptorsLength > 0; } void cCiCaPmt::AddPid(int Pid, uint8_t StreamType) { - //XXX buffer overflow check??? - capmt[length++] = StreamType; - capmt[length++] = (Pid >> 8) & 0xFF; - capmt[length++] = Pid & 0xFF; - esInfoLengthPos = length; - capmt[length++] = 0x00; // ES_info_length H (at ES level) - capmt[length++] = 0x00; // ES_info_length L + if (Pid) { + //XXX buffer overflow check??? + capmt[length++] = StreamType; + capmt[length++] = (Pid >> 8) & 0xFF; + capmt[length++] = Pid & 0xFF; + esInfoLengthPos = length; + capmt[length++] = 0x00; // ES_info_length H (at ES level) + capmt[length++] = 0x00; // ES_info_length L + if (streamFlag) + AddCaDescriptors(caDescriptorsLength, caDescriptors); + } } -void cCiCaPmt::AddCaDescriptor(int Length, uint8_t *Data) +void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data) { if (esInfoLengthPos) { if (length + Length < int(sizeof(capmt))) { diff --git a/ci.h b/ci.h index e83deea0..673bad21 100644 --- a/ci.h +++ b/ci.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: ci.h 1.10 2003/12/23 10:20:59 kls Exp $ + * $Id: ci.h 1.11 2003/12/24 10:05:46 kls Exp $ */ #ifndef __CI_H @@ -66,10 +66,14 @@ private: int length; int esInfoLengthPos; uint8_t capmt[2048]; ///< XXX is there a specified maximum? + int caDescriptorsLength; + uint8_t caDescriptors[2048]; + bool streamFlag; + void AddCaDescriptors(int Length, const uint8_t *Data); public: - cCiCaPmt(int ProgramNumber); + cCiCaPmt(int Source, int Transponder, int ProgramNumber, const unsigned short *CaSystemIds); + bool Valid(void); void AddPid(int Pid, uint8_t StreamType); - void AddCaDescriptor(int Length, uint8_t *Data); }; #define MAX_CI_SESSION 16 //XXX diff --git a/dvbdevice.c b/dvbdevice.c index 25c5fd96..76c3340b 100644 --- a/dvbdevice.c +++ b/dvbdevice.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: dvbdevice.c 1.74 2003/12/23 10:23:16 kls Exp $ + * $Id: dvbdevice.c 1.75 2003/12/24 09:57:29 kls Exp $ */ #include "dvbdevice.h" @@ -273,19 +273,12 @@ void cDvbTuner::Action(void) if (ciHandler->Process() && useCa) { if (tunerStatus != tsCam) {//XXX TODO update in case the CA descriptors have changed for (int Slot = 0; Slot < ciHandler->NumSlots(); Slot++) { - uchar buffer[2048]; - int length = GetCaDescriptors(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot), sizeof(buffer), buffer); - if (length > 0) { - cCiCaPmt CaPmt(channel.Sid()); - CaPmt.AddCaDescriptor(length, buffer); - if (channel.Vpid()) - CaPmt.AddPid(channel.Vpid(), 2); - if (channel.Apid1()) - CaPmt.AddPid(channel.Apid1(), 4); - if (channel.Apid2()) - CaPmt.AddPid(channel.Apid2(), 4); - if (channel.Dpid1()) - CaPmt.AddPid(channel.Dpid1(), 0); + cCiCaPmt CaPmt(channel.Source(), channel.Frequency(), channel.Sid(), ciHandler->GetCaSystemIds(Slot)); + if (CaPmt.Valid()) { + CaPmt.AddPid(channel.Vpid(), 2); + CaPmt.AddPid(channel.Apid1(), 4); + CaPmt.AddPid(channel.Apid2(), 4); + CaPmt.AddPid(channel.Dpid1(), 0); if (ciHandler->SetCaPmt(CaPmt, Slot)) { tunerStatus = tsCam; startTime = 0; diff --git a/pat.c b/pat.c index 3809a7cf..07980147 100644 --- a/pat.c +++ b/pat.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.c 1.1 2003/12/21 15:28:28 kls Exp $ + * $Id: pat.c 1.2 2003/12/24 10:23:33 kls Exp $ */ #include "pat.h" @@ -25,16 +25,17 @@ private: int caSystem; int providerId; int caPid; + bool stream; int length; uchar *data; public: - cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, int Length, const uchar *Data); + cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, bool Stream, int Length, const uchar *Data); virtual ~cCaDescriptor(); int Length(void) const { return length; } const uchar *Data(void) const { return data; } }; -cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, int Length, const uchar *Data) +cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaSystem, int ProviderId, int CaPid, bool Stream, int Length, const uchar *Data) { source = Source; transponder = Transponder; @@ -42,6 +43,7 @@ cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaS caSystem = CaSystem; providerId = ProviderId; caPid = CaPid; + stream = Stream; length = Length + 6; data = MALLOC(uchar, length); data[0] = SI::CaDescriptorTag; @@ -56,7 +58,7 @@ cCaDescriptor::cCaDescriptor(int Source, int Transponder, int ServiceId, int CaS #ifdef DEBUG_CA_DESCRIPTORS char buffer[1024]; char *q = buffer; - q += sprintf(q, "CAM: %04X %5d %5d %04X %6X %04X -", source, transponder, serviceId, caSystem, providerId, caPid); + q += sprintf(q, "CAM: %04X %5d %5d %04X %6X %04X %d -", source, transponder, serviceId, caSystem, providerId, caPid, stream); for (int i = 0; i < length; i++) q += sprintf(q, " %02X", data[i]); dsyslog(buffer); @@ -74,11 +76,11 @@ class cCaDescriptors : public cList { private: cMutex mutex; public: - void NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d); - int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data); + void NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d, bool Stream); + int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); }; -void cCaDescriptors::NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d) +void cCaDescriptors::NewCaDescriptor(int Source, int Transponder, int ServiceId, SI::CaDescriptor *d, bool Stream) { // The code for determining the ProviderID was taken from 'libdtv' // written by Rolf Hakenes . @@ -108,23 +110,27 @@ void cCaDescriptors::NewCaDescriptor(int Source, int Transponder, int ServiceId, if (ca->source == Source && ca->transponder == Transponder && ca->serviceId == ServiceId && ca->caSystem == d->getCaType() && ca->providerId == ProviderID && ca->caPid == d->getCaPid()) return; } - Add(new cCaDescriptor(Source, Transponder, ServiceId, d->getCaType(), ProviderID, d->getCaPid(), Length, Data)); + Add(new cCaDescriptor(Source, Transponder, ServiceId, d->getCaType(), ProviderID, d->getCaPid(), Stream, Length, Data)); //XXX update??? } -int cCaDescriptors::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data) +int cCaDescriptors::GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag) { if (!CaSystemIds || !*CaSystemIds) return 0; if (BufSize > 0 && Data) { cMutexLock MutexLock(&mutex); int length = 0; + int IsStream = -1; for (cCaDescriptor *d = First(); d; d = Next(d)) { if (d->source == Source && d->transponder == Transponder && d->serviceId == ServiceId) { const unsigned short *caids = CaSystemIds; do { if (d->caSystem == *caids) { if (length + d->Length() <= BufSize) { + if (IsStream >= 0 && IsStream != d->stream) + dsyslog("CAM: different stream flag in CA descriptors"); + IsStream = d->stream; memcpy(Data + length, d->Data(), d->Length()); length += d->Length(); } @@ -134,6 +140,7 @@ int cCaDescriptors::GetCaDescriptors(int Source, int Transponder, int ServiceId, } while (*++caids); } } + StreamFlag = IsStream == 1; return length; } return -1; @@ -141,9 +148,9 @@ int cCaDescriptors::GetCaDescriptors(int Source, int Transponder, int ServiceId, cCaDescriptors CaDescriptors; -int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data) +int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag) { - return CaDescriptors.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data); + return CaDescriptors.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag); } // --- cPatFilter ------------------------------------------------------------ @@ -202,7 +209,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length SI::CaDescriptor *d; // Scan the common loop: for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) { - CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d); + CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d, false); delete d; } // Scan the stream-specific loop: @@ -210,9 +217,9 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length for (SI::Loop::Iterator it; pmt.streamLoop.hasNext(it); ) { stream = pmt.streamLoop.getNext(it); for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) { - CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d); + CaDescriptors.NewCaDescriptor(Source(), Transponder(), pmt.getServiceId(), d, true); delete d; - } + } } lastPmtScan = 0; // this triggers the next scan } diff --git a/pat.h b/pat.h index aae7369c..df30c104 100644 --- a/pat.h +++ b/pat.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: pat.h 1.1 2003/12/21 14:56:03 kls Exp $ + * $Id: pat.h 1.2 2003/12/24 10:08:22 kls Exp $ */ #ifndef __PAT_H @@ -25,12 +25,14 @@ public: virtual void SetStatus(bool On); }; -int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data); +int GetCaDescriptors(int Source, int Transponder, int ServiceId, const unsigned short *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag); ///< Gets all CA descriptors for a given channel. ///< Copies all available CA descriptors for the given Source, Transponder and ServiceId ///< 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 ///< available), or -1 if BufSize was too small to hold all CA descriptors. + ///< The return value in StreamFlag tells whether these CA descriptors are to be used + ///< for the individual streams. #endif //__PAT_H