⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cam.c

📁 这是一个LINUX环境的 VDR 插件源代码,可支持Irdeto, Seca, Viaccess, Nagra, Conax & Cryptoworks等CA系统的读卡、共享等操作。
💻 C
📖 第 1 页 / 共 5 页
字号:
    status=msReset;    if(resetTimer.TimedOut()) reset=false;    }  else if(caids[0]) status=msReady;  else {    status=msPresent; //msNone;    Check();    }  if(status!=lastStatus) {    static const char *stext[] = { "none","reset","present","ready" };    PRINTF(L_CORE_CI,"%d.%d: status '%s'",cardIndex,slot,stext[status]);    lastStatus=status;    }  return status;}bool cScCamSlot::Reset(bool log){  reset=true; resetTimer.Set(SLOT_RESET_TIME);  Clear();  if(log) PRINTF(L_CORE_CI,"%d.%d: reset",cardIndex,slot);  return true;}bool cScCamSlot::Check(void){  bool res=false;  bool dr=ciadapter->CamSoftCSA() || ScSetup.ConcurrentFF>0;  if(dr!=doReply && !IsDecrypting()) {    PRINTF(L_CORE_CI,"%d.%d: doReply changed, reset triggered",cardIndex,slot);    Reset(false);    doReply=dr;    }  if(checkTimer.TimedOut()) {    if(version!=ciadapter->GetCaids(slot,0,0)) {      version=ciadapter->GetCaids(slot,caids,MAX_CI_SLOT_CAIDS);      PRINTF(L_CORE_CI,"%d.%d: now using CAIDs version %d",cardIndex,slot,version);      res=true;      }    checkTimer.Set(SLOT_CAID_CHECK);    }  return res;}int cScCamSlot::GetLength(const unsigned char * &data){  int len=*data++;  if(len&0x80) {    int i;    for(i=len&~0x80, len=0; i>0; i--) len=(len<<8) + *data++;    }  return len;}void cScCamSlot::CaInfo(unsigned char *b, int tcid, int cid){  b[0]=0xa0; b[2]=tcid;  b[3]=0x90;  b[4]=0x02; b[5]=cid<<8; b[6]=cid&0xff;  b[7]=0x9f; b[8]=0x80;   b[9]=0x31; // AOT_CA_INFO  int l=0;  for(int i=0; caids[i]; i++) {    b[l+11]=caids[i]>>8;    b[l+12]=caids[i]&0xff;    l+=2;    }  b[10]=l; b[1]=l+9; b[-1]=l+11; Put(b-1,l+12);  PRINTF(L_CORE_CI,"%d.%d sending CA info",cardIndex,slot);}void cScCamSlot::Process(const unsigned char *data, int len){  const unsigned char *save=data;  data+=3;  int dlen=GetLength(data);  if(dlen>len-(data-save)) {    PRINTF(L_CORE_CI,"%d.%d TDPU length exceeds data length",cardIndex,slot);    dlen=len-(data-save);    }  int tcid=data[0];  unsigned char a[128], *b=&a[1];  if(Check()) CaInfo(b,tcid,0x01);  if(dlen<8 || data[1]!=0x90) return;  int cid=(data[3]<<8)+data[4];  int tag=(data[5]<<16)+(data[6]<<8)+data[7];  data+=8;  dlen=GetLength(data);  if(dlen>len-(data-save)) {    PRINTF(L_CORE_CI,"%d.%d tag length exceeds data length",cardIndex,slot);    dlen=len-(data-save);    }  switch(tag) {    case 0x9f8030: // AOT_CA_INFO_ENQ      CaInfo(b,tcid,cid);      break;        case 0x9f8032: // AOT_CA_PMT      if(dlen>=6) {        int ca_lm=data[0];        int ci_cmd=-1;        cPrg *prg=new cPrg((data[1]<<8)+data[2],ca_lm==5);        int ilen=(data[4]<<8)+data[5];        LBSTARTF(L_CORE_CI);        LBPUT("%d.%d CA_PMT decoding len=%x lm=%x prg=%d len=%x",cardIndex,slot,dlen,ca_lm,(data[1]<<8)+data[2],ilen);        data+=6; dlen-=6;        LBPUT("/%x",dlen);        if(ilen>0 && dlen>=ilen) {          ci_cmd=data[0];          LBPUT(" ci_cmd(G)=%02x",ci_cmd);          }        data+=ilen; dlen-=ilen;        while(dlen>=5) {          cPrgPid *pid=new cPrgPid(data[0],(data[1]<<8)+data[2]);          prg->pids.Add(pid);          ilen=(data[3]<<8)+data[4];          LBPUT(" pid=%d,%x len=%x",data[0],(data[1]<<8)+data[2],ilen);          data+=5; dlen-=5;          LBPUT("/%x",dlen);          if(ilen>0 && dlen>=ilen) {            ci_cmd=data[0];            LBPUT(" ci_cmd(S)=%x",ci_cmd);            }          data+=ilen; dlen-=ilen;          }        LBEND();        PRINTF(L_CORE_CI,"%d.%d got CA pmt ciCmd=%d caLm=%d",cardIndex,slot,ci_cmd,ca_lm);        if(doReply && (ci_cmd==0x03 || (ci_cmd==0x01 && ca_lm==0x03))) {          b[0]=0xa0; b[2]=tcid;          b[3]=0x90;          b[4]=0x02; b[5]=cid<<8; b[6]=cid&0xff;          b[7]=0x9f; b[8]=0x80; b[9]=0x33; // AOT_CA_PMT_REPLY          b[11]=prg->Prg()<<8;          b[12]=prg->Prg()&0xff;          b[13]=0x00;          b[14]=0x81; 	// CA_ENABLE          b[10]=4; b[1]=4+9; a[0]=4+11; Put(a,4+12);          PRINTF(L_CORE_CI,"%d.%d answer to query",cardIndex,slot);          }        if(prg->Prg()!=0) {          if(ci_cmd==0x04) {            PRINTF(L_CORE_CI,"%d.%d stop decrypt",cardIndex,slot);            ciadapter->CamStop();            }          if(ci_cmd==0x01 || (ci_cmd==-1 && (ca_lm==0x04 || ca_lm==0x05))) {            PRINTF(L_CORE_CI,"%d.%d set CAM decrypt (prg %d)",cardIndex,slot,prg->Prg());            ciadapter->CamAddPrg(prg);            }          }        delete prg;        }      break;    }}// -- cScCiAdapter -------------------------------------------------------------cScCiAdapter::cScCiAdapter(cDevice *Device, int CardIndex, cCam *Cam){  device=Device; cardIndex=CardIndex; cam=Cam;  tcid=0;  memset(version,0,sizeof(version));  memset(slots,0,sizeof(slots));  SetDescription("SC-CI adapter on device %d",cardIndex);  rb=new cRingBufferLinear(KILOBYTE(5),6+1,false,"SC-CI adapter read");  if(rb) {    rb->SetTimeouts(0,CAM_READ_TIMEOUT);/*    bool spare=true;    for(int i=0; i<MAX_CI_SLOTS; i++) {      if(GetCaids(i,0,0)<=0) {        if(!spare) break;        spare=false;        }      slots[i]=new cScCamSlot(this,cardIndex,i);      }*/    BuildCaids(true);    slots[0]=new cScCamSlot(this,cardIndex,0);    Start();    }  else PRINTF(L_GEN_ERROR,"failed to create ringbuffer for SC-CI adapter %d.",cardIndex);}cScCiAdapter::~cScCiAdapter(){  Cancel(3);  ciMutex.Lock();  delete rb; rb=0;  ciMutex.Unlock();}void cScCiAdapter::CamStop(void){  if(cam) cam->Stop();}void cScCiAdapter::CamAddPrg(cPrg *prg){  if(cam) cam->AddPrg(prg);}bool cScCiAdapter::CamSoftCSA(void){  return cam && cam->IsSoftCSA();}int cScCiAdapter::GetCaids(int slot, unsigned short *Caids, int max){  BuildCaids(false);  cMutexLock lock(&ciMutex);  if(Caids) {    int i;    for(i=0; i<MAX_CI_SLOT_CAIDS && i<max && caids[i]; i++) Caids[i]=caids[slot][i];    Caids[i]=0;    }  return version[slot];}void cScCiAdapter::BuildCaids(bool force){  if(caidTimer.TimedOut() || force) {    PRINTF(L_CORE_CAIDS,"%d: building caid lists",cardIndex);    cChannelList list(cardIndex);    Channels.Lock(false);    for(cChannel *channel=Channels.First(); channel; channel=Channels.Next(channel)) {      if(!channel->GroupSep() && channel->Ca()>=CA_ENCRYPTED_MIN && device->ProvidesTransponder(channel)) {        cChannelCaids *ch=new cChannelCaids(channel);        if(ch) list.Add(ch);        }      }    Channels.Unlock();    list.Unique();    list.CheckIgnore();    list.Unique();    int n=0, h;    caid_t c[MAX_CI_SLOT_CAIDS+1];    memset(c,0,sizeof(c));    do {      if((h=list.Histo())<0) break;      c[n++]=h;      LBSTART(L_CORE_CAIDS);      LBPUT("%d: added %04x caids now",cardIndex,h); for(int i=0; i<n; i++) LBPUT(" %04x",c[i]);      LBEND();      list.Purge(h);      } while(n<MAX_CI_SLOT_CAIDS && list.Count()>0);    c[n]=0;    if(n==0) PRINTF(L_CORE_CI,"no active CAIDs");    else if(list.Count()>0) PRINTF(L_GEN_ERROR,"too many CAIDs. You should ignore some CAIDs.");    ciMutex.Lock();    if((version[0]==0 && c[0]!=0) || memcmp(caids[0],c,sizeof(caids[0]))) {      memcpy(caids[0],c,sizeof(caids[0]));      version[0]++;      if(version[0]>0) {        LBSTART(L_CORE_CI);        LBPUT("card %d, slot %d (v=%2d) caids:",cardIndex,0,version[0]);        for(int i=0; caids[0][i]; i++) LBPUT(" %04x",caids[0][i]);        LBEND();        }      }    ciMutex.Unlock();    caidTimer.Set(CAID_TIME);    }}int cScCiAdapter::Read(unsigned char *Buffer, int MaxLength){  cMutexLock lock(&ciMutex);  if(cam && rb && Buffer && MaxLength>0) {    int c;    unsigned char *data=rb->Get(c);    if(data) {      int s=data[0];      if(c>=s+1) {        c=s>MaxLength ? MaxLength : s;        memcpy(Buffer,&data[1],c);        if(c<s) { data[c]=s-c; rb->Del(c); }        else rb->Del(c+1);        if(Buffer[2]!=0x80 || LOG(L_CORE_CIFULL)) {          LDUMP(L_CORE_CI,Buffer,c,"%d.%d <-",cardIndex,Buffer[0]);          readTimer.Set();          }        return c;        }      else {        LDUMP(L_GEN_DEBUG,data,c,"internal: sc-ci %d rb frame sync got=%d avail=%d -",cardIndex,c,rb->Available());        rb->Clear();        }      }    }  else cCondWait::SleepMs(CAM_READ_TIMEOUT);  if(LOG(L_CORE_CIFULL) && readTimer.Elapsed()>2000) {    PRINTF(L_CORE_CIFULL,"%d: read heartbeat",cardIndex);    readTimer.Set();    }  return 0;}#define TPDU(data,slot) do { unsigned char *_d=(data); _d[0]=(slot); _d[1]=tcid; } while(0)#define TAG(data,tag,len) do { unsigned char *_d=(data); _d[0]=(tag); _d[1]=(len); } while(0)#define SB_TAG(data,sb) do { unsigned char *_d=(data); _d[0]=0x80; _d[1]=0x02; _d[2]=tcid; _d[3]=(sb); } while(0)#define PUT_TAG(data,len) do { unsigned char *_d=(data)-1; int _l=(len); _d[0]=_l; if(rb) rb->Put(_d,_l+1); } while(0)void cScCiAdapter::Write(const unsigned char *buff, int len){  cMutexLock lock(&ciMutex);  if(cam && buff && len>=5) {    unsigned char a[128], *b=&a[1];    struct TPDU *tpdu=(struct TPDU *)buff;    int slot=tpdu->slot;    if(buff[2]!=0xA0 || buff[3]>0x01 || LOG(L_CORE_CIFULL))      LDUMP(L_CORE_CI,buff,len,"%d.%d ->",cardIndex,slot);    if(slots[slot]) {      switch(tpdu->tag) {        case 0x81: // T_RCV          {          TPDU(b,slot);          int l=2, c;          unsigned char *d=slots[slot]->Get(c);          if(d) {            int s=d[0];            if(c>=s) {              memcpy(&b[l],&d[1],s);              l+=s;              slots[slot]->Del(s+1);              }            else slots[slot]->Del(c);            }          SB_TAG(&b[l],0x00);          PUT_TAG(b,l+4);          break;          }        case 0x82: // T_CREATE_TC          tcid=tpdu->data[0];          TPDU(b,slot);          TAG(&b[2],0x83,0x01); b[4]=tcid;          SB_TAG(&b[5],0x00);          PUT_TAG(b,9);          static const unsigned char reqCAS[] = { 0xA0,0x07,0x01,0x91,0x04,0x00,0x03,0x00,0x41 };          memcpy(b,reqCAS,sizeof(reqCAS));          b[2]=tcid;          a[0]=sizeof(reqCAS);          slots[slot]->Put(a,sizeof(reqCAS)+1);          break;        case 0xA0: // T_DATA_LAST          slots[slot]->Process(buff,len);          TPDU(b,slot);          SB_TAG(&b[2],slots[slot]->Available()>0 ? 0x80:0x00);          PUT_TAG(b,6);          break;        }      }    }  else PRINTF(L_CORE_CIFULL,"%d: short write (cam=%d buff=%d len=%d)",cardIndex,cam!=0,buff!=0,len);}bool cScCiAdapter::Reset(int Slot){  cMutexLock lock(&ciMutex);  PRINTF(L_CORE_CI,"%d: reset of slot %d requested",cardIndex,Slot);  return slots[Slot] ? slots[Slot]->Reset():false;}eModuleStatus cScCiAdapter::ModuleStatus(int Slot){  cMutexLock lock(&ciMutex);  bool enable=ScSetup.CapCheck(cardIndex);  if(!enable) CamStop();  return (enable && cam && slots[Slot]) ? slots[Slot]->Status():msNone;}bool cScCiAdapter::Assign(cDevice *Device, bool Query){  return Device ? (Device==device) : true;}#endif //APIVERSNUM >= 10500// -- cDeCSA -------------------------------------------------------------------#define MAX_CSA_PIDS 8192#define MAX_CSA_IDX  16class cDeCSA : public cMutex {private:  int cs;  unsigned char **range;  unsigned char pidmap[MAX_CSA_PIDS];  void *keys[MAX_CSA_IDX];  //  bool GetKeyStruct(int idx);public:  cDeCSA(void);  ~cDeCSA();  bool Decrypt(unsigned char *data, int len, bool force);  bool SetDescr(ca_descr_t *ca_descr);  bool SetCaPid(ca_pid_t *ca_pid);  };cDeCSA::cDeCSA(void){  cs=get_suggested_cluster_size();  PRINTF(L_CORE_CSA,"clustersize=%d rangesize=%d",cs,cs*2+5);  range=MALLOC(unsigned char *,(cs*2+5));  memset(keys,0,sizeof(keys));  memset(pidmap,0,sizeof(pidmap));}cDeCSA::~cDeCSA(){  for(int i=0; i<MAX_CSA_IDX; i++)    if(keys[i]) free_key_struct(keys[i]);  free(range);}bool cDeCSA::GetKeyStruct(int idx){  if(!keys[idx]) keys[idx]=get_key_struct();  return keys[idx]!=0;}bool cDeCSA::SetDescr(ca_descr_t *ca_descr){  cMutexLock lock(this);  int idx=ca_descr->index;  if(idx<MAX_CSA_IDX && GetKeyStruct(idx)) {    if(ca_descr->parity==0) { // even key      set_even_control_word(keys[idx],ca_descr->cw);      PRINTF(L_CORE_CSA,"even key set");      }    else {                    // odd key      set_odd_control_word(keys[idx],ca_descr->cw);      PRINTF(L_CORE_CSA,"odd key set");      }    }  return true;}bool cDeCSA::SetCaPid(ca_pid_t *ca_pid){  cMutexLock lock(this);  if(ca_pid->index<MAX_CSA_IDX && ca_pid->pid<MAX_CSA_PIDS) {    pidmap[ca_pid->pid]=ca_pid->index;    PRINTF(L_CORE_CSA,"set pid %04x to index %d",ca_pid->pid,ca_pid->index);    }  return true;}bool cDeCSA::Decrypt(unsigned char *data, int len, bool force){  cMutexLock lock(this);  int r=-2, ccs=0, currIdx=-1;  bool newRange=true;  range[0]=0;  len-=(TS_SIZE-1);  for(int l=0; l<len; l+=TS_SIZE) {    if(data[l]!=TS_SYNC_BYTE) {       // let higher level cope with that      PRINTF(L_CORE_CSA,"garbage in TS buffer");      break;      }    if(data[l+3]&0xC0) {              // encrypted      int idx=pidmap[((data[l+1]<<8)+data[l+2])&(MAX_CSA_PIDS-1)];      if(currIdx<0 || idx==currIdx) { // same or no index        currIdx=idx;        if(newRange) {          r+=2; newRange=false;          range[r]=&data[l];          range[r+2]=0;          }        range[r+1]=&data[l+TS_SIZE];        if(++ccs>=cs) break;        }      else {                          // other index, create hole        PRINTF(L_CORE_CSA,"other index. current=%d idx=%d",currIdx,idx);        newRange=true;        } 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -