Author Topic: CCcam Source Code  (Read 2100 times)

0 Members and 1 Guest are viewing this topic.

Offline elcardinal74

  • Hero Member
  • *****
  • Posts: 2056
CCcam Source Code
« on: December 15, 2009, 12:59:22 PM »
Hey ich hab in nem anderen Forum nen Source Code gefunden der für CCcam sein soll!

Schaut euch das ganze mal an! Ich hoffe es ist hilfreich für einige die auf der Suche nach CCcam für andere Receiver sind!
Code: You are not allowed to view links. Register or Login
* Softcam plugin to VDR (C++)
*
* This code is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This code is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Or, point your browser to [url]http://www.gnu.org/copyleft/gpl.html[/url]
*/

#include
#include
#include
#include
#include
#include

#include

#include "cc.h"
#include "network.h"

#define LIST_ONLY 0x03 /* CA application should clear the list when an 'ONLY' CAPMT object is received, and start working with the object */

// -- cCCcamCard ---------------------------------------------------------------

class cCCcamCard : public cMutex {
private:
int ccam_fd;
int cardnum, pid, pmtlen;
bool newcw;
cTimeMs timecw;
unsigned char *capmt, cw[16];
const char *path;
cCondVar cwwait;
public:
cCCcamCard(void);
~cCCcamCard();
void Setup(int num, const char *Path);
bool Connect(void);
void Disconnect(void);
bool Connected(void) { return ccam_fd>=0; }
void WriteCaPmt(void);
void NewCaPmt(int p, const unsigned char *pmt, int len);
int Pid(void) { return pid; }
bool GetCw(unsigned char *Cw, int timeout);
void NewCw(const unsigned char *Cw);
};

cCCcamCard::cCCcamCard(void)
{
cardnum=-1; path=0;
ccam_fd=-1; capmt=0; newcw=false; pid=-1;
}

cCCcamCard::~cCCcamCard()
{
Disconnect();
free(capmt);
}

void cCCcamCard::Setup(int num, const char *Path)
{
cardnum=num; path=Path;
}

void cCCcamCard:isconnect(void)
{
cMutexLock lock(this);
close(ccam_fd);
ccam_fd=-1; newcw=false;
}

bool cCCcamCard::Connect(void)
{
cMutexLock lock(this);
Disconnect();
ccam_fd=socket(AF_LOCAL,SOCK_STRE AM,0);
if(!ccam_fd) {
PRINTF(L_CC_CCCAM,"%d: socket failed: %s",cardnum,strerror(errno));
return false;
}
sockaddr_un serv_addr_un;
memset(&serv_addr_un,0,sizeof(ser v_addr_un));
serv_addr_un.sun_family=AF_LOCAL;
snprintf(serv_addr_un.sun_path,si zeof(serv_addr_un.sun_path),path, cardnum);
if(connect(ccam_fd,(const sockaddr*)&serv_addr_un,sizeof(se rv_addr_un))!=0) {
PRINTF(L_CC_CCCAM,"%d: connect failed: %s",cardnum,strerror(errno));
Disconnect();
return false;
}
PRINTF(L_CC_CCCAM,"%d: opened camd socket",cardnum);
return true;
}

void cCCcamCard::WriteCaPmt(void)
{
cMutexLock lock(this);
if(capmt) {
for(int retry=2; retry>0; retry--) {
if(!Connected() && !Connect()) break;
int r=write(ccam_fd,capmt,pmtlen);
if(r==pmtlen) {
newcw=false;
break;
}
PRINTF(L_CC_CCCAM,"%d: write failed: %s",cardnum,strerror(errno));
Disconnect();
}
}
}

void cCCcamCard::NewCaPmt(int p, const unsigned char *pmt, int len)
{
cMutexLock lock(this);
free(capmt); pid=0; newcw=false;
capmt=MALLOC(unsigned char,len);
if(capmt) {
memcpy(capmt,pmt,len);
pmtlen=len;
capmt[6]=LIST_ONLY;
pid=p;
WriteCaPmt();
}
}

void cCCcamCard::NewCw(const unsigned char *Cw)
{
cMutexLock lock(this);
if(memcmp(cw,Cw,sizeof(cw))) {
memcpy(cw,Cw,sizeof(cw));
newcw=true;
timecw.Set();
cwwait.Broadcast();
}
}

bool cCCcamCard::GetCw(unsigned char *Cw, int timeout)
{
cMutexLock lock(this);
if(newcw && timecw.Elapsed()>3000)
newcw=false; // too old
if(!newcw)
cwwait.TimedWait(*this,timeout);
if(newcw) {
memcpy(Cw,cw,sizeof(cw));
newcw=false;
return true;
}
return false;
}

// -- cCardClientCCcam ---------------------------------------------------------

class cCardClientCCcam : public cCardClient, private cThread {
private:
cNetSocket so;
cCCcamCard card[4];
int pmtversion;
int failedcw;
char *socketpath;
protected:
virtual bool Login(void);
virtual void Action(void);
public:
cCardClientCCcam(const char *Name);
~cCardClientCCcam();
virtual bool Init(const char *CfgDir);
virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum);
};

static cCardClientLinkReg __ncd("cccam");

cCardClientCCcam::cCardClientCCca m(const char *Name)
:cCardClient(Name)
,cThread("CCcam listener")
,so(DEFAULT_CONNECT_TIMEOUT,2,360 0,true)
{
pmtversion=0; socketpath=0;
}

cCardClientCCcam::~cCardClientCCc am()
{
Cancel(3);
free(socketpath);
}

bool cCardClientCCcam::Init(const char *config)
{
cMutexLock lock(this);
int num=0;
char path[256];
if(!ParseStdConfig(config,&num)
|| sscanf(&config[num],":%255[^:]",path)!=1) return false;
PRINTF(L_CC_CORE,"%s: socket=%s",name,path);
socketpath=strdup(path);
for(int i=0; i<4; i++) card.Setup(i,socketpath);
return Immediate() ? Login() : true;
}

bool cCardClientCCcam::Login(void)
{
cMutexLock lock(this);
so.Disconnect();
if(!so.Bind(&quot;127.0.0.1&quot;,port)) return false;
PRINTF(L_CC_CCCAM,&quot;Bound to port %d, starting UDP listener&quot;,port);
Start();
return true;
}

bool cCardClientCCcam::ProcessECM(cons t cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)
{
cMutexLock lock(this);
if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;

static const unsigned char pmt&#91;] = {
0x9f,0x80,0x32,0x82,0xFF,0xFF,
0x01,
#define PRG_POS 7
0xFF,0xFF, // prg-nr
#define VERS_POS 9
0xFF, // version
#define LEN_POS 10
0xFF,0xFF, // prg-info-len
0x01, // ca pmt command
#define PRIV_POS 13
0x81,0x08,0x00,0x00,0xFF,0x00,0xF F,0xFF,0xFF,0xFF, // private descr
#define DMX_POS 23
0x82,0x02,0xFF,0xFF, // demuxer stuff
#define PID_POS 27
0x84,0x02,0xFF,0xFF // pmt pid
};
unsigned char capmt[2048];
memcpy(capmt,pmt,sizeof(pmt));
int wp=sizeof(pmt);
int len=wp-LEN_POS-2;
capmt[PRG_POS]=ecm->prgId****8;
capmt[PRG_POS+1]=ecm->prgId&0xff;
capmt[VERS_POS]=pmtversion;
pmtversion=(pmtversion+1)&0x1f;
capmt[PRIV_POS+4]=cardnum;
capmt[PRIV_POS+6]=ecm->transponder****8;
capmt[PRIV_POS+7]=ecm->transponder&0xFF;
capmt[PRIV_POS+8]=ecm->provId****8;
capmt[PRIV_POS+9]=ecm->provId&0xFF;
capmt[DMX_POS+2]=1<ecm_pid****8;
capmt[PID_POS+3]=ecm->ecm_pid&0xFF;
bool streamflag=1;
#if APIVERSNUM >= 10500
int casys[2];
#else
unsigned short casys[2];
#endif
casys[0]=ecm->caId;
casys[1]=0;
int n=GetCaDescriptors(ecm->source,ecm->transponder,ecm->prgId,casys,sizeof(capmt)-wp,&capmt[wp],streamflag);
if(n<=0) {
PRINTF(L_CC_CCCAM,&quot;no CA descriptor for caid %04x sid %d prov %04x&quot;,ecm->caId,ecm->prgId,ecm->provId);
return false;
}
len+=n; wp+=n;
capmt[wp++]=0x01;
capmt[wp++]=0x0f;
capmt[wp++]=cardnum; // cccam uses this one as PID to program ca0
capmt[wp++]=0x00; //es_length
capmt[wp++]=0x06; //es ca_pmt_cmd_id
capmt[LEN_POS]=((len&0xf00)****8);
capmt[LEN_POS+1]=(len&0xff);
capmt[4]=(wp-6)****8;
capmt[5]=(wp-6)&0xff;

cCCcamCard *c=&card[cardnum];
int timeout=700;
if(ecm->ecm_pid!=c->Pid() || !c->Connected()) { // channel change
PRINTF(L_CC_CCCAM,&quot;sending capmts &quot;);
c->NewCaPmt(ecm->ecm_pid,capmt,wp);
timeout=3000;
}
if(!c->GetCw(cw,timeout)) {
// somethings up, so we will send capmt again.
c->WriteCaPmt();
if(!c->GetCw(cw,1000)) {
PRINTF(L_CC_CCCAM,&quot;%d: FAILED ECM !&quot;,cardnum);
c->Disconnect();
failedcw++;
if(failedcw>=10) {
// CCcam is having problems lets mark it for a restart....
FILE *f=fopen(&quot;/tmp/killCCcam&quot;,&quot;w+&quot;);
fclose(f);
failedcw=0;
}
return false;
}
}
PRINTF(L_CC_CCCAM,&quot;%d: GOT CW !&quot;,cardnum);
failedcw=0;
return true;
}

void cCardClientCCcam::Action(void)
{
unsigned char cw[18];
while(Running()) {
if(so.Read(cw,sizeof(cw))==sizeof (cw)) {
LDUMP(L_CC_CCCAM,cw+2,16,&quot;got: %02x%02x&quot;,cw[0],cw[1]);
if(cw[1]==0x0f && cw[0]<4)
card[cw[0]].NewCw(cw+2);
}
}
}