int nu=0, num, vers=0;
Name[0]=0;
if(sscanf(buf,"V%d:%d:%x:%x:%63[^:]:%x/%x:%x:%x/%x:%d:%d/%d%n",
- &vers,&prgId,&source,&transponder,Name,&caId,&emmCaId,&provId,
+ &vers,&grPrgId,&source,&transponder,Name,&caId,&emmCaId,&provId,
&ecm_pid,&ecm_table,&rewriterId,&nu,&dataIdx,&num)>=13
&& vers==CACHE_VERS) {
SetName(Name);
SetRewriter();
+ prgId=grPrgId%SIDGRP_SHIFT;
const char *line=buf+num;
if(nu>0 && *line++==':') {
unsigned char *dat=AUTOMEM(nu);
sprintf(str,"0/%d:",dataIdx);
}
return cString::sprintf("V%d:%d:%x:%x:%s:%x/%x:%x:%x/%x:%d:%s",
- CACHE_VERS,prgId,source,transponder,name,
+ CACHE_VERS,grPrgId,source,transponder,name,
caId,emmCaId,provId,ecm_pid,ecm_table,rewriterId,
str);
}
dat=new cEcmData(e);
Add(dat);
Modified();
- PRINTF(L_CORE_ECM,"cache add prgId=%d source=%x transponder=%x ecm=%x/%x",e->prgId,e->source,e->transponder,e->ecm_pid,e->ecm_table);
+ PRINTF(L_CORE_ECM,"cache add prgId=%d source=%x transponder=%x ecm=%x/%x",e->grPrgId,e->source,e->transponder,e->ecm_pid,e->ecm_table);
}
else {
if(strcasecmp(e->name,dat->name)) {
if(ScSetup.EcmCache>1) return 0;
ListLock(false);
for(cEcmData *dat=First(); dat; dat=Next(dat)) {
- if(dat->prgId==sid && dat->source==Source && dat->transponder==Transponder) {
+ if(dat->grPrgId==sid && dat->source==Source && dat->transponder==Transponder) {
cEcmInfo *e=new cEcmInfo(dat);
if(e) {
PRINTF(L_CORE_ECM,"from cache: system %s (%04x) id %04x with ecm %x/%x",e->name,e->caId,e->provId,e->ecm_pid,e->ecm_table);
ListUnlock();
if(dat) {
DelItem(dat);
- PRINTF(L_CORE_ECM,"invalidated cached prgId=%d source=%x transponder=%x ecm=%x/%x",dat->prgId,dat->source,dat->transponder,dat->ecm_pid,dat->ecm_table);
+ PRINTF(L_CORE_ECM,"invalidated cached prgId=%d source=%x transponder=%x ecm=%x/%x",dat->grPrgId,dat->source,dat->transponder,dat->ecm_pid,dat->ecm_table);
}
}
source=transponder=-1; liveVpid=liveApid=0; logger=0; hookman=0;
memset(lastCW,0,sizeof(lastCW));
memset(indexMap,0,sizeof(indexMap));
+ memset(splitSid,0,sizeof(splitSid));
}
cCam::~cCam()
handler->Stop();
if(logger) logger->Down();
if(hookman) hookman->Down();
+ memset(splitSid,0,sizeof(splitSid));
}
void cCam::AddPrg(cPrg *prg)
LBPUT(" %s=%04x",TYPENAME(pid->type),pid->pid);
LBEND();
}
- if(prg->pids.Count()>0 && prg->SimplifyCaDescr()) {
- PRINTF(L_GEN_WARN,"Stream specific caDescr (aka split-ecm) cannot be handled yet (SID %d)",prg->sid);
- // take first caDescr and ignore the rest....
- cPrgPid *pid=prg->pids.First();
- prg->caDescr.Set(&pid->caDescr);
- for(; pid; pid=prg->pids.Next(pid)) pid->caDescr.Clear();
- prg->SetPidCaDescr(false);
- }
- cEcmHandler *handler=GetHandler(prg->sid,needZero,noshift);
- if(handler) {
- PRINTF(L_CORE_PIDS,"%d: found handler for SID %d (%s idle=%d idx=%d)",cardNum,prg->sid,handler->Id(),handler->IsIdle(),handler->CwIndex());
- prg->source=source;
- prg->transponder=transponder;
- handler->SetPrg(prg);
+ bool isSplit=false;
+ if(prg->pids.Count()>0 && prg->SimplifyCaDescr()) isSplit=true;
+ else {
+ for(int i=0; splitSid[i]; i++)
+ if(splitSid[i]==prg->sid) { isSplit=true; break; }
+ }
+ if(!isSplit) {
+ cEcmHandler *handler=GetHandler(prg->sid,needZero,noshift);
+ if(handler) {
+ PRINTF(L_CORE_PIDS,"%d: found handler for SID %d (%s idle=%d idx=%d)",cardNum,prg->sid,handler->Id(),handler->IsIdle(),handler->CwIndex());
+ prg->source=source;
+ prg->transponder=transponder;
+ handler->SetPrg(prg);
+ }
+ }
+ else {
+ PRINTF(L_CORE_PIDS,"%d: SID %d is handled as splitted",cardNum,prg->sid);
+ // first update the splitSid list
+ if(prg->pids.Count()==0) { // delete
+ for(int i=0; splitSid[i]; i++)
+ if(splitSid[i]==prg->sid) {
+ memmove(&splitSid[i],&splitSid[i+1],sizeof(splitSid[0])*(MAX_SPLIT_SID-i));
+ break;
+ }
+ PRINTF(L_CORE_PIDS,"%d: deleted from list",cardNum);
+ }
+ else { // add
+ bool has=false;
+ int i;
+ for(i=0; splitSid[i]; i++) if(splitSid[i]==prg->sid) has=true;
+ if(!has) {
+ if(i<MAX_SPLIT_SID) {
+ splitSid[i]=prg->sid;
+ splitSid[i+1]=0;
+ PRINTF(L_CORE_PIDS,"%d: added to list",cardNum);
+ }
+ else PRINTF(L_CORE_PIDS,"%d: split SID list overflow",cardNum);
+ }
+ }
+ LBSTART(L_CORE_PIDS);
+ LBPUT("%d: split SID list now:",cardNum);
+ for(int i=0; i<=MAX_SPLIT_SID; i++) LBPUT(" %d",splitSid[i]);
+ LBEND();
+ // prepare an empty prg head
+ cPrg work;
+ work.source=source;
+ work.transponder=transponder;
+ // loop through pids
+ int group=1;
+ cPrgPid *first;
+ while((first=prg->pids.First())) {
+ LBSTARTF(L_CORE_PIDS);
+ LBPUT("%d: group %d pids",cardNum,group);
+ prg->pids.Del(first,false);
+ work.caDescr.Set(&first->caDescr);
+ first->caDescr.Clear();
+ work.pids.Add(first);
+ LBPUT(" %04x",first->pid);
+ for(cPrgPid *pid=prg->pids.First(); pid;) {
+ cPrgPid *next=prg->pids.Next(pid);
+ if(work.caDescr==pid->caDescr) { // same group
+ prg->pids.Del(pid,false);
+ pid->caDescr.Clear();
+ work.pids.Add(pid);
+ LBPUT(" %04x",pid->pid);
+ }
+ pid=next;
+ }
+ LBEND();
+ // get a handler for the group
+ int grsid=group*SIDGRP_SHIFT+prg->sid;
+ cEcmHandler *handler=0;
+ if(group==1) {
+ // in the first group check if we have a non-split handler
+ // for the sid
+ for(handler=handlerList.First(); handler; handler=handlerList.Next(handler))
+ if(handler->Sid()==prg->sid) {
+ // let GetHandler() take care of needZero/noshift stuff
+ handler=GetHandler(prg->sid,needZero,noshift);
+ break;
+ }
+ }
+ // otherwise get the group-sid handler
+ if(!handler) handler=GetHandler(grsid,needZero,noshift);
+ if(handler) {
+ PRINTF(L_CORE_PIDS,"%d: found handler for group-SID %d (%s idle=%d idx=%d)",cardNum,grsid,handler->Id(),handler->IsIdle(),handler->CwIndex());
+ work.sid=grsid;
+ handler->SetPrg(&work);
+ }
+ // prepare for next group
+ work.pids.Clear();
+ needZero=false; // only one group can have this
+ group++;
+ }
+ // now we scan the handler list for leftover group handlers
+ for(cEcmHandler *handler=handlerList.First(); handler; handler=handlerList.Next(handler)) {
+ int sid=handler->Sid();
+ if(!handler->IsIdle() && sid>SIDGRP_SHIFT) {
+ int gr=sid/SIDGRP_SHIFT;
+ sid%=SIDGRP_SHIFT;
+ if(sid==prg->sid && gr>=group) {
+ PRINTF(L_CORE_PIDS,"%d: idle group handler %s idx=%d",cardNum,handler->Id(),handler->CwIndex());
+ work.sid=handler->Sid();
+ handler->SetPrg(&work);
+ }
+ }
+ }
}
}
--- /dev/null
+diff -u vdr-1.6.0-2-orig/ci.c vdr/ci.c
+--- vdr-1.6.0-2-orig/ci.c 2009-01-15 16:21:16.000000000 -0500
++++ vdr/ci.c 2009-08-17 05:56:38.000000000 -0400
+@@ -551,6 +551,8 @@
+
+ // --- cCiCaPmt --------------------------------------------------------------
+
++#define MAXCASYSTEMIDS 64
++
+ // Ca Pmt List Management:
+
+ #define CPLM_MORE 0x00
+@@ -574,9 +576,10 @@
+ int length;
+ int esInfoLengthPos;
+ uint8_t capmt[2048]; ///< XXX is there a specified maximum?
+- int caDescriptorsLength;
+- uint8_t caDescriptors[2048];
+- bool streamFlag;
++ int source;
++ int transponder;
++ int programNumber;
++ int caSystemIds[MAXCASYSTEMIDS + 1]; // list is zero terminated!
+ void AddCaDescriptors(int Length, const uint8_t *Data);
+ public:
+ cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds);
+@@ -589,7 +592,17 @@
+ cCiCaPmt::cCiCaPmt(uint8_t CmdId, int Source, int Transponder, int ProgramNumber, const int *CaSystemIds)
+ {
+ cmdId = CmdId;
+- caDescriptorsLength = GetCaDescriptors(Source, Transponder, ProgramNumber, CaSystemIds, sizeof(caDescriptors), caDescriptors, streamFlag);
++ source = Source;
++ transponder = Transponder;
++ programNumber = ProgramNumber;
++ int i = 0;
++ if (CaSystemIds) {
++ for (; CaSystemIds[i]; i++)
++ caSystemIds[i] = CaSystemIds[i];
++ }
++ caSystemIds[i] = 0;
++ uint8_t caDescriptors[512];
++ int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 0);
+ length = 0;
+ capmt[length++] = CPLM_ONLY;
+ capmt[length++] = (ProgramNumber >> 8) & 0xFF;
+@@ -597,8 +610,9 @@
+ capmt[length++] = 0x01; // version_number, current_next_indicator - apparently vn doesn't matter, but cni must be 1
+ esInfoLengthPos = length;
+ capmt[length++] = 0x00; // program_info_length H (at program level)
+- capmt[length++] = 0x00; // program_info_length L
+- if (!streamFlag)
++ capmt[length++] = 0x01; // program_info_length L
++ capmt[length++] = cmdId;
++ if (caDescriptorsLength>0)
+ AddCaDescriptors(caDescriptorsLength, caDescriptors);
+ }
+
+@@ -610,14 +624,17 @@
+ void cCiCaPmt::AddPid(int Pid, uint8_t StreamType)
+ {
+ if (Pid) {
++ uint8_t caDescriptors[512];
++ int caDescriptorsLength = GetCaDescriptors(source, transponder, programNumber, caSystemIds, sizeof(caDescriptors), caDescriptors, 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)
++ capmt[length++] = 0x01; // ES_info_length L
++ capmt[length++] = cmdId;
++ if (caDescriptorsLength>0)
+ AddCaDescriptors(caDescriptorsLength, caDescriptors);
+ }
+ }
+@@ -625,8 +642,7 @@
+ void cCiCaPmt::AddCaDescriptors(int Length, const uint8_t *Data)
+ {
+ if (esInfoLengthPos) {
+- if (length + Length < int(sizeof(capmt))) {
+- capmt[length++] = cmdId;
++ if (length + Length <= int(sizeof(capmt))) {
+ memcpy(capmt + length, Data, Length);
+ length += Length;
+ int l = length - esInfoLengthPos - 2;
+@@ -643,8 +659,6 @@
+
+ // --- cCiConditionalAccessSupport -------------------------------------------
+
+-#define MAXCASYSTEMIDS 64
+-
+ // CA Enable Ids:
+
+ #define CAEI_POSSIBLE 0x01
+diff -u vdr-1.6.0-2-orig/pat.c vdr/pat.c
+--- vdr-1.6.0-2-orig/pat.c 2008-02-08 08:48:30.000000000 -0500
++++ vdr/pat.c 2009-08-17 05:58:14.000000000 -0400
+@@ -21,23 +21,23 @@
+ class cCaDescriptor : public cListObject {
+ private:
+ int caSystem;
+- bool stream;
++ int esPid;
+ int length;
+ uchar *data;
+ public:
+- cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data);
++ cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data);
+ virtual ~cCaDescriptor();
+ bool operator== (const cCaDescriptor &arg) const;
+ int CaSystem(void) { return caSystem; }
+- int Stream(void) { return stream; }
++ int EsPid(void) { return esPid; }
+ int Length(void) const { return length; }
+ const uchar *Data(void) const { return data; }
+ };
+
+-cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, bool Stream, int Length, const uchar *Data)
++cCaDescriptor::cCaDescriptor(int CaSystem, int CaPid, int EsPid, int Length, const uchar *Data)
+ {
+ caSystem = CaSystem;
+- stream = Stream;
++ esPid = EsPid;
+ length = Length + 6;
+ data = MALLOC(uchar, length);
+ data[0] = SI::CaDescriptorTag;
+@@ -57,7 +57,7 @@
+
+ bool cCaDescriptor::operator== (const cCaDescriptor &arg) const
+ {
+- return length == arg.length && memcmp(data, arg.data, length) == 0;
++ return esPid == arg.esPid && length == arg.length && memcmp(data, arg.data, length) == 0;
+ }
+
+ // --- cCaDescriptors --------------------------------------------------------
+@@ -77,8 +77,8 @@
+ bool Is(int Source, int Transponder, int ServiceId);
+ bool Is(cCaDescriptors * CaDescriptors);
+ bool Empty(void) { return caDescriptors.Count() == 0; }
+- void AddCaDescriptor(SI::CaDescriptor *d, bool Stream);
+- int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++ void AddCaDescriptor(SI::CaDescriptor *d, int EsPid);
++ int GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+ const int *CaIds(void) { return caIds; }
+ };
+
+@@ -126,9 +126,9 @@
+ }
+ }
+
+-void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, bool Stream)
++void cCaDescriptors::AddCaDescriptor(SI::CaDescriptor *d, int EsPid)
+ {
+- cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), Stream, d->privateData.getLength(), d->privateData.getData());
++ cCaDescriptor *nca = new cCaDescriptor(d->getCaType(), d->getCaPid(), EsPid, d->privateData.getLength(), d->privateData.getData());
+ for (cCaDescriptor *ca = caDescriptors.First(); ca; ca = caDescriptors.Next(ca)) {
+ if (*ca == *nca) {
+ delete nca;
+@@ -141,28 +141,30 @@
+ #ifdef DEBUG_CA_DESCRIPTORS
+ char buffer[1024];
+ char *q = buffer;
+- q += sprintf(q, "CAM: %04X %5d %5d %04X %d -", source, transponder, serviceId, d->getCaType(), Stream);
++ q += sprintf(q, "CAM: %04X %5d %5d %04X %04X -", source, transponder, serviceId, d->getCaType(), EsPid);
+ for (int i = 0; i < nca->Length(); i++)
+ q += sprintf(q, " %02X", nca->Data()[i]);
+ dsyslog(buffer);
+ #endif
+ }
+
+-int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++// EsPid is to select the "type" of CaDescriptor to be returned
++// >0 - CaDescriptor for the particular esPid
++// =0 - common CaDescriptor
++// <0 - all CaDescriptors regardless of type (old default)
++
++int cCaDescriptors::GetCaDescriptors(const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+ if (!CaSystemIds || !*CaSystemIds)
+ return 0;
+ if (BufSize > 0 && Data) {
+ int length = 0;
+- int IsStream = -1;
+ for (cCaDescriptor *d = caDescriptors.First(); d; d = caDescriptors.Next(d)) {
++ if(EsPid<0 || d->EsPid()==EsPid) {
+ const int *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();
+ }
+@@ -171,7 +173,7 @@
+ }
+ } while (*++caids);
+ }
+- StreamFlag = IsStream == 1;
++ }
+ return length;
+ }
+ return -1;
+@@ -187,7 +189,7 @@
+ // Returns 0 if this is an already known descriptor,
+ // 1 if it is an all new descriptor with actual contents,
+ // and 2 if an existing descriptor was changed.
+- int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++ int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+ };
+
+ int cCaDescriptorHandler::AddCaDescriptors(cCaDescriptors *CaDescriptors)
+@@ -208,22 +210,21 @@
+ return CaDescriptors->Empty() ? 0 : 1;
+ }
+
+-int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++int cCaDescriptorHandler::GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+ cMutexLock MutexLock(&mutex);
+- StreamFlag = false;
+ for (cCaDescriptors *ca = First(); ca; ca = Next(ca)) {
+ if (ca->Is(Source, Transponder, ServiceId))
+- return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, StreamFlag);
++ return ca->GetCaDescriptors(CaSystemIds, BufSize, Data, EsPid);
+ }
+ return 0;
+ }
+
+ cCaDescriptorHandler CaDescriptorHandler;
+
+-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag)
++int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid)
+ {
+- return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, StreamFlag);
++ return CaDescriptorHandler.GetCaDescriptors(Source, Transponder, ServiceId, CaSystemIds, BufSize, Data, EsPid);
+ }
+
+ // --- cPatFilter ------------------------------------------------------------
+@@ -322,7 +323,7 @@
+ cCaDescriptors *CaDescriptors = new cCaDescriptors(Channel->Source(), Channel->Transponder(), Channel->Sid());
+ // Scan the common loop:
+ for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)pmt.commonDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
+- CaDescriptors->AddCaDescriptor(d, false);
++ CaDescriptors->AddCaDescriptor(d, 0);
+ delete d;
+ }
+ // Scan the stream-specific loop:
+@@ -340,16 +341,17 @@
+ int NumDpids = 0;
+ int NumSpids = 0;
+ for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); ) {
++ int esPid = stream.getPid();
+ switch (stream.getStreamType()) {
+ case 1: // STREAMTYPE_11172_VIDEO
+ case 2: // STREAMTYPE_13818_VIDEO
+- Vpid = stream.getPid();
++ Vpid = esPid;
+ break;
+ case 3: // STREAMTYPE_11172_AUDIO
+ case 4: // STREAMTYPE_13818_AUDIO
+ {
+ if (NumApids < MAXAPIDS) {
+- Apids[NumApids] = stream.getPid();
++ Apids[NumApids] = esPid;
+ SI::Descriptor *d;
+ for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+ switch (d->getDescriptorTag()) {
+@@ -388,11 +390,11 @@
+ for (SI::Loop::Iterator it; (d = stream.streamDescriptors.getNext(it)); ) {
+ switch (d->getDescriptorTag()) {
+ case SI::AC3DescriptorTag:
+- dpid = stream.getPid();
++ dpid = esPid;
+ break;
+ case SI::SubtitlingDescriptorTag:
+ if (NumSpids < MAXSPIDS) {
+- Spids[NumSpids] = stream.getPid();
++ Spids[NumSpids] = esPid;
+ SI::SubtitlingDescriptor *sd = (SI::SubtitlingDescriptor *)d;
+ SI::SubtitlingDescriptor::Subtitling sub;
+ char *s = SLangs[NumSpids];
+@@ -411,7 +413,7 @@
+ }
+ break;
+ case SI::TeletextDescriptorTag:
+- Tpid = stream.getPid();
++ Tpid = esPid;
+ break;
+ case SI::ISO639LanguageDescriptorTag: {
+ SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d;
+@@ -434,7 +436,7 @@
+ //default: printf("PID: %5d %5d %2d %3d %3d\n", pmt.getServiceId(), stream.getPid(), stream.getStreamType(), pmt.getVersionNumber(), Channel->Number());//XXX
+ }
+ for (SI::Loop::Iterator it; (d = (SI::CaDescriptor*)stream.streamDescriptors.getNext(it, SI::CaDescriptorTag)); ) {
+- CaDescriptors->AddCaDescriptor(d, true);
++ CaDescriptors->AddCaDescriptor(d, esPid);
+ delete d;
+ }
+ }
+diff -u vdr-1.6.0-2-orig/pat.h vdr/pat.h
+--- vdr-1.6.0-2-orig/pat.h 2007-01-05 05:42:10.000000000 -0500
++++ vdr/pat.h 2009-06-13 20:17:56.000000000 -0400
+@@ -32,7 +32,7 @@
+ void Trigger(void);
+ };
+
+-int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, bool &StreamFlag);
++int GetCaDescriptors(int Source, int Transponder, int ServiceId, const int *CaSystemIds, int BufSize, uchar *Data, int EsPid);
+ ///< 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