#define ECM_DATA_TIME 6000 // time to wait for ECM data updates
#define MAX_ECM_IDLE 300000 // delay before an idle handler can be removed
#define MAX_ECM_HOLD 15000 // delay before an idle handler stops processing
-#define CAID_TIME 300000 // time between caid scans
#define ECMCACHE_FILE "ecm.cache"
return HasPidCaDescr();
}
-// -- cEcmSys ------------------------------------------------------------------
+// -- cEcmPri ------------------------------------------------------------------
class cEcmPri : public cSimpleItem {
public:
// -- cScCiAdapter -------------------------------------------------------------
+#define CAID_TIME 300000 // time between caid scans
+#define TRIGGER_TIME 10000 // min. time between caid scan trigger
+
#define TDPU_SIZE_INDICATOR 0x80
struct TPDU {
cRingBufferLinear *rb;
cScCamSlot *slots[MAX_CI_SLOTS];
//
- cTimeMs caidTimer;
+ cTimeMs caidTimer, triggerTimer;
int version[MAX_CI_SLOTS];
caid_t caids[MAX_CI_SLOTS][MAX_CI_SLOT_CAIDS+1];
int tcid;
+ bool rebuildcaids;
//
cTimeMs readTimer, writeTimer;
//
void CamAddPrg(cPrg *prg);
bool CamSoftCSA(void);
int GetCaids(int slot, unsigned short *Caids, int max);
+ void CaidsChanged(void);
};
// -- cScCamSlot ---------------------------------------------------------------
cScCiAdapter::cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam)
{
device=Device; cardIndex=CardIndex; cam=Cam;
- tcid=0;
+ tcid=0; rebuildcaids=false;
memset(version,0,sizeof(version));
memset(slots,0,sizeof(slots));
SetDescription("SC-CI adapter on device %d",cardIndex);
return version[slot];
}
+void cScCiAdapter::CaidsChanged(void)
+{
+ rebuildcaids=true;
+}
+
void cScCiAdapter::BuildCaids(bool force)
{
- if(caidTimer.TimedOut() || force) {
+ if(caidTimer.TimedOut() || force || (rebuildcaids && triggerTimer.TimedOut())) {
PRINTF(L_CORE_CAIDS,"%d: building caid lists",cardIndex);
cChannelList list(cardIndex);
Channels.Lock(false);
ciMutex.Unlock();
caidTimer.Set(CAID_TIME);
+ triggerTimer.Set(TRIGGER_TIME);
+ rebuildcaids=false;
}
}
return softcsa && (!fullts || !live);
}
+void cScDvbDevice::CaidsChanged(void)
+{
+#if APIVERSNUM >= 10500
+ if(ciadapter) ciadapter->CaidsChanged();
+ PRINTF(L_CORE_CAIDS,"caid list rebuild triggered");
+#endif
+}
+
bool cScDvbDevice::SetCaDescr(ca_descr_t *ca_descr, bool initial)
{
if(!softcsa || (fullts && ca_descr->index==0)) {
return true;
}
+void cScDvbDevice::CaidsChanged(void)
+{}
+
bool cScDvbDevice::SoftCSA(bool live)
{
return softcsa && !live;
void DumpAV7110(void);
cCam *Cam(void) { return cam; }
bool SoftCSA(bool live);
+ void CaidsChanged(void);
};
#endif // ___CAM_H
return dev && dev->Cam() && dev->Cam()->TriggerHook(id);
}
+void cSoftCAM::CaidsChanged(void)
+{
+ for(int n=cDevice::NumDevices(); --n>=0;) {
+ cScDvbDevice *dev=dynamic_cast<cScDvbDevice *>(cDevice::GetDevice(n));
+ if(dev) dev->CaidsChanged();
+ }
+}
+
// --- cScHousekeeper ----------------------------------------------------------
class cScHousekeeper : public cThread {
static void SetLogStatus(int CardNum, const cEcmInfo *ecm, bool on);
static void AddHook(int CardNum, cLogHook *hook);
static bool TriggerHook(int CardNum, int id);
+ static void CaidsChanged(void);
};
#endif // ___SC_H
#include <vdr/thread.h>
#include "smartcard.h"
+#include "sc.h"
#include "misc.h"
#include "log-core.h"
return l;
}
+void cSmartCard::CaidsChanged(void)
+{
+ cSoftCAM::CaidsChanged();
+}
+
// -- cSmartCardLink -----------------------------------------------------------
cSmartCardLink::cSmartCardLink(const char *Name, int Id)
bool Status(void);
void NewCardConfig(const struct CardConfig *Cfg);
int CheckSctLen(const unsigned char *data, int off);
+ void CaidsChanged(void);
public:
cSmartCard(const struct CardConfig *Cfg, const struct StatusMsg *Msg);
virtual ~cSmartCard() {};
{
if(len>=13 && buff[0]==0 && !CheckNull(buff,len) && memcmp(buff,lastEmmReq,13)) {
emmProcessing=false;
- CAID=buff[1]*256+buff[2];
+ int c=buff[1]*256+buff[2];
+ if(c!=CAID) CaidsChanged();
+ CAID=c;
ResetIdSet();
switch(CAID>>8) {
case 0x17:
if(caid==0xFFFF) break;
if(caid) CAIDs[numCAIDs++]=caid;
}
+ CaidsChanged();
LBSTART(L_CC_LOGIN);
LBPUT("%s: CAIDs ",name);
for(int i=0; i<numCAIDs && CAIDs[i]; i++) LBPUT("%04X ",CAIDs[i]);
if(!emmAllowed) PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
emmProcessing=true;
+ CaidsChanged();
}
}
#include "system.h"
#include "cc.h"
+#include "sc.h"
#include "network.h"
#include "misc.h"
#include "opts.h"
return immediate;
}
+void cCardClient::CaidsChanged(void)
+{
+ cSoftCAM::CaidsChanged();
+}
+
bool cCardClient::ParseStdConfig(const char *config, int *num)
{
int n, emm=0;
virtual int RecvMsg(cNetSocket *so, unsigned char *data, int len, int to=-1);
virtual bool Login(void) { return false; }
bool Immediate(void);
+ void CaidsChanged(void);
public:
cCardClient(const char *Name);
virtual bool Init(const char *config)=0;
public:
int GetShares(const cEcmInfo *ecm, cShares *ss);
void SetLag(int shareid, int lag);
+ bool HasCaid(int caid);
};
cShare *cShares::Find(int shareid)
Unlock();
}
+bool cShares::HasCaid(int caid)
+{
+ for(cShare *s=First(); s; s=Next(s))
+ if(s->CaID()==caid) return true;
+ return false;
+}
+
int cShares::GetShares(const cEcmInfo *ecm, cShares *ss)
{
Lock(true);
cShare *n=shares.Next(s);
if(s->ShareID()==shareid) {
PRINTF(L_CC_CCCAM2SH,"REMOVE share %08x caid: %04x",s->ShareID(),s->CaID());
+ int caid=s->CaID();
shares.Del(s);
+ if(!shares.HasCaid(caid)) CaidsChanged();
}
s=n;
}
struct AddShare *add=(struct AddShare *)hdr;
int caid=UINT16_BE(&add->caid);
int shareid=UINT32_BE(&add->shareid);
+ shares.Lock(false);
+ if(!shares.HasCaid(caid)) CaidsChanged();
+ shares.Unlock();
cShare *s=new cShare(shareid,caid,add->uphops);
LBSTARTF(L_CC_CCCAM2SH);
LBPUT("ADD share %08x hops %d maxdown %d caid %04x serial ",shareid,add->uphops,add->maxdown,caid);
if(!CmdSend(&so,MSG_CARD_DATA_REQ) || ReceiveMessage(&so,buffer,false)<=0) return false;
if(buffer[0] == MSG_CARD_DATA) {
- caId=(buffer[4]<<8)+buffer[5];
+ int c=(buffer[4]<<8)+buffer[5];
+ if(c!=caId) CaidsChanged();
+ caId=c;
LBSTARTF(L_CC_LOGIN);
char str[32], str2[32];
LBPUT("%s: CaID=%04x admin=%d srvUA=%s",name,caId,buffer[3]==1,HexStr(str,&buffer[6],8));
else PRINTF(L_CC_RDGD,"no server hello, assuming old mode");
if(emmProcessing && !emmAllowed)
PRINTF(L_CC_EMM,"%s: EMM disabled from config",name);
- return true;
+ CaidsChanged();
+ return true;
}
bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum)
for(int i=0; i<l; i+=buff[i+1]+2) {
switch(buff[i]) {
case 0x20: cardVer=buff[i+2]; break;
- case 0x28: sysId=(buff[i+2]<<8)+buff[i+3]; break;
+ case 0x28: {
+ int s=(buff[i+2]<<8)+buff[i+3];
+ if(s!=sysId) CaidsChanged();
+ sysId=s;
+ break;
+ }
case 0x2f: currency=(buff[i+2]<<8)+buff[i+3]; break;
}
}
{
static const unsigned char cwexp[] = { 0x01,0x00,0x01 };
BN_bin2bn(cwexp,sizeof(cwexp),exp);
- ucpkValid=false;
+ caid=0; ucpkValid=false;
}
int cSmartCardCryptoworks::GetLen(void)
return false;
}
memcpy(Caid,&buff[2],2);
- caid=buff[2]*256+buff[3];
+ int c=buff[2]*256+buff[3];
+ if(c!=caid) CaidsChanged();
+ caid=c;
if(ReadRecord(buff,0x80)<7) {
PRINTF(L_SC_ERROR,"reading record 2f01/80 failed");
return false;
cSmartCardIrdeto::cSmartCardIrdeto(void)
:cSmartCard(&cardCfg,msgs)
-{}
+{
+ ACS=0; caId=0; numProv=0;
+}
bool cSmartCardIrdeto::Init(void)
{
return false;
}
ACS=buff[8]*256+buff[9];
- caId=buff[13]*256+buff[14];
+ int c=buff[13]*256+buff[14];
+ if(c!=caId) CaidsChanged();
+ caId=c;
memcpy(coco,&buff[21],3); coco[3]=0;
PRINTF(L_SC_INIT,"ACS Version %04x, CAID %04x, CoCo %s",ACS,caId,coco);
snprintf(idStr,sizeof(idStr),"%s (ACS %x)",SC_NAME,ACS);
cSmartCardVideoGuard2::cSmartCardVideoGuard2(void)
:cSmartCard(&cardCfg,msgs)
{
- cmdList=0;
+ cmdList=0; CAID=0;
}
cSmartCardVideoGuard2::~cSmartCardVideoGuard2(void)
return false;
}
- CAID=WORD(buff,0x1D,0xFFFF);
+ unsigned int c=WORD(buff,0x1D,0xFFFF);
+ if(c!=CAID) CaidsChanged();
+ CAID=c;
memcpy(&cardID,&buff[8],4);
memcpy(&groupID,&buff[8],4); groupID[3]=0;
SetCard(new cCardNDS(cardID));