\r
#define LIST_ONLY 0x03 /* CA application should clear the list when an 'ONLY' CAPMT object is received, and start working with the object */\r
\r
+static char *socketPath="/var/emu/chroot%d/tmp/camd.socket";\r
+\r
+// -- cCCcamCard ---------------------------------------------------------------\r
+\r
+class cCCcamCard : public cMutex {\r
+private:\r
+ int ccam_fd;\r
+ int cardnum, pid, pmtlen;\r
+ bool newcw;\r
+ cTimeMs timecw;\r
+ unsigned char *capmt, cw[16];\r
+ const char *path;\r
+ cCondVar cwwait;\r
+public:\r
+ cCCcamCard(void);\r
+ ~cCCcamCard();\r
+ void Setup(int num, const char *Path);\r
+ bool Connect(void);\r
+ void Disconnect(void);\r
+ bool Connected(void) { return ccam_fd>=0; }\r
+ void WriteCaPmt(void);\r
+ void NewCaPmt(int p, const unsigned char *pmt, int len);\r
+ int Pid(void) { return pid; }\r
+ bool GetCw(unsigned char *Cw, int timeout);\r
+ void NewCw(const unsigned char *Cw);\r
+ };\r
+\r
+cCCcamCard::cCCcamCard(void)\r
+{\r
+ cardnum=-1; path=0;\r
+ ccam_fd=-1; capmt=0; newcw=false; pid=-1;\r
+}\r
+\r
+cCCcamCard::~cCCcamCard()\r
+{\r
+ Disconnect();\r
+ free(capmt);\r
+}\r
+\r
+void cCCcamCard::Setup(int num, const char *Path)\r
+{\r
+ cardnum=num; path=Path;\r
+}\r
+\r
+void cCCcamCard::Disconnect(void)\r
+{\r
+ cMutexLock lock(this);\r
+ close(ccam_fd);\r
+ ccam_fd=-1; newcw=false;\r
+}\r
+\r
+bool cCCcamCard::Connect(void)\r
+{\r
+ cMutexLock lock(this);\r
+ Disconnect();\r
+ ccam_fd=socket(AF_LOCAL,SOCK_STREAM,0);\r
+ if(!ccam_fd) {\r
+ PRINTF(L_CC_CCCAM,"%d: socket failed: %s",cardnum,strerror(errno));\r
+ return false;\r
+ }\r
+ sockaddr_un serv_addr_un;\r
+ memset(&serv_addr_un,0,sizeof(serv_addr_un));\r
+ serv_addr_un.sun_family=AF_LOCAL;\r
+ snprintf(serv_addr_un.sun_path,sizeof(serv_addr_un.sun_path),path,cardnum);\r
+ if(connect(ccam_fd,(const sockaddr*)&serv_addr_un,sizeof(serv_addr_un))!=0) {\r
+ PRINTF(L_CC_CCCAM,"%d: connect failed: %s",cardnum,strerror(errno));\r
+ Disconnect();\r
+ return false;\r
+ }\r
+ PRINTF(L_CC_CCCAM,"%d: opened camd socket",cardnum);\r
+ return true;\r
+}\r
+\r
+void cCCcamCard::WriteCaPmt(void)\r
+{\r
+ cMutexLock lock(this);\r
+ if(capmt) {\r
+ for(int retry=2; retry>0; retry--) {\r
+ if(!Connected() && !Connect()) break;\r
+ int r=write(ccam_fd,capmt,pmtlen);\r
+ if(r==pmtlen) {\r
+ newcw=false;\r
+ break;\r
+ }\r
+ PRINTF(L_CC_CCCAM,"%d: write failed: %s",cardnum,strerror(errno));\r
+ Disconnect();\r
+ }\r
+ }\r
+}\r
+\r
+void cCCcamCard::NewCaPmt(int p, const unsigned char *pmt, int len)\r
+{\r
+ cMutexLock lock(this);\r
+ free(capmt); pid=0; newcw=false;\r
+ capmt=MALLOC(unsigned char,len);\r
+ if(capmt) {\r
+ memcpy(capmt,pmt,len);\r
+ pmtlen=len;\r
+ capmt[6]=LIST_ONLY;\r
+ pid=p;\r
+ WriteCaPmt();\r
+ }\r
+}\r
+\r
+void cCCcamCard::NewCw(const unsigned char *Cw)\r
+{\r
+ cMutexLock lock(this);\r
+ if(memcmp(cw,Cw,sizeof(cw))) {\r
+ memcpy(cw,Cw,sizeof(cw));\r
+ newcw=true;\r
+ timecw.Set();\r
+ cwwait.Broadcast();\r
+ }\r
+}\r
+\r
+bool cCCcamCard::GetCw(unsigned char *Cw, int timeout)\r
+{\r
+ cMutexLock lock(this);\r
+ if(newcw && timecw.Elapsed()>3000)\r
+ newcw=false; // too old\r
+ if(!newcw)\r
+ cwwait.TimedWait(*this,timeout);\r
+ if(newcw) {\r
+ memcpy(Cw,cw,sizeof(cw));\r
+ newcw=false;\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
// -- cCardClientCCcam ---------------------------------------------------------\r
\r
class cCardClientCCcam : public cCardClient , private cThread {\r
private:\r
cNetSocket so;\r
- //\r
+ cCCcamCard card[4];\r
int pmtversion;\r
- unsigned char sacapmt[4][2048];\r
- unsigned char savedcw[4][16];\r
- int pids[4];\r
- int newcw[4];\r
- uint64_t timecw[4];\r
- int ccam_fd[4];\r
- int lastcard;\r
- int lastpid;\r
int failedcw;\r
- //\r
- void Writecapmt(int j);\r
protected:\r
- virtual bool lLogin(int cardnum);\r
+ virtual bool Login(void);\r
virtual void Action(void);\r
public:\r
cCardClientCCcam(const char *Name);\r
,so(DEFAULT_CONNECT_TIMEOUT,2,3600,true)\r
{\r
pmtversion=0;\r
- ccam_fd[0]=-1; ccam_fd[1]=-1; ccam_fd[2]=-1; ccam_fd[3]=-1;\r
+ for(int i=0; i<4; i++) card[i].Setup(i,socketPath);\r
}\r
\r
bool cCardClientCCcam::Init(const char *config)\r
{\r
cMutexLock lock(this);\r
int num=0;\r
- signal(SIGPIPE,SIG_IGN);\r
if(!ParseStdConfig(config,&num)) return false;\r
return true;\r
}\r
return false;\r
}\r
\r
-bool cCardClientCCcam::lLogin(int cardnum)\r
+bool cCardClientCCcam::Login(void)\r
{\r
- sockaddr_un serv_addr_un;\r
- char camdsock[256];\r
- int res;\r
-\r
- close(ccam_fd[cardnum]);\r
- sprintf(camdsock,"/var/emu/chroot%d/tmp/camd.socket",cardnum);\r
- printf(" socket = %s\n",camdsock);\r
- ccam_fd[cardnum]=socket(AF_LOCAL, SOCK_STREAM, 0);\r
- bzero(&serv_addr_un, sizeof(serv_addr_un));\r
- serv_addr_un.sun_family = AF_LOCAL;\r
- strcpy(serv_addr_un.sun_path, camdsock);\r
- res=connect(ccam_fd[cardnum], (const sockaddr*)&serv_addr_un, sizeof(serv_addr_un));\r
- if (res !=0) {\r
- PRINTF(L_CC_CCCAM,"Couldnt open camd.socket..... errno = %d Aggg",errno);\r
- close(ccam_fd[cardnum]);\r
- ccam_fd[cardnum] = -1;\r
- }\r
- PRINTF(L_CC_CCCAM,"Opened camd.socket..... ccamd_fd = %d ",ccam_fd[cardnum]);\r
-\r
if(!so.Connected()) {\r
so.Disconnect();\r
if(!so.Bind("127.0.0.1",port)) return false;\r
// cMutexLock lock(this);\r
//newcw[cardnum] =0;\r
unsigned char capmt[2048];\r
- PRINTF(L_CC_CCCAM,"Processing ECM.... for card %d",cardnum);\r
const int caid=ecm->caId;\r
const int pid =ecm->ecm_pid;\r
int lenpos=10;\r
capmt[lenpos+1]=(len & 0xff);\r
capmt[4]=((wp-6)>>8) & 0xff;\r
capmt[5]=(wp-6) & 0xff;\r
- if (newcw[cardnum]) {\r
- if ((cTimeMs::Now() - timecw[cardnum]) > 3000)\r
- // just too old lets bin em...\r
- newcw[cardnum] = 0;\r
- }\r
- if ((pid != pids[cardnum]) || (ccam_fd[cardnum] == -1)) { // channel change\r
+\r
+ cCCcamCard *c=&card[cardnum];\r
+\r
+ int timeout=700;\r
+ if(pid!=c->Pid() || !c->Connected()) { // channel change\r
PRINTF(L_CC_CCCAM,"sending capmts ");\r
- pids[cardnum] = pid;\r
- newcw[cardnum] =0;\r
- memcpy(sacapmt[cardnum],capmt,2048);\r
- lLogin(cardnum);\r
- Writecapmt(cardnum);\r
- usleep(300000);\r
+ c->NewCaPmt(pid,capmt,wp);\r
+ timeout=3000;\r
}\r
- lastcard = cardnum;\r
- lastpid = pid;\r
- failedcw=0;\r
- int u=0;\r
- while ((newcw[cardnum] == 0) && (u++<700))\r
- usleep(1000); // give the card a chance to decode it...\r
- if (newcw[cardnum] == 0) {\r
+ if(!c->GetCw(cw,timeout)) {\r
// somethings up, so we will send capmt again.\r
- pids[cardnum] = pid;\r
- // memcpy(capmt,sacapmt[cardnum],2048);\r
- Writecapmt(cardnum);\r
- }\r
- u=0;\r
- while ((newcw[cardnum] == 0) && (u++<1000))\r
- usleep(1000);\r
- if (newcw[cardnum] == 0) {\r
- PRINTF(L_CC_CCCAM,"FAILED ECM FOR CARD %d !!!!!!!!!!!!!!!!!!",cardnum);\r
- sacapmt[cardnum][9]=pmtversion; //reserved - version - current/next\r
- pmtversion++;\r
- pmtversion%=32;\r
- failedcw++;\r
- if (failedcw == 10) {\r
- // CCcam is having problems lets mark it for a restart....\r
- FILE *i = fopen("/tmp/killCCcam","w+");\r
- fclose(i);\r
+ c->WriteCaPmt();\r
+ timeout=1000;\r
+ if(!c->GetCw(cw,timeout)) {\r
+ PRINTF(L_CC_CCCAM,"%d: FAILED ECM !",cardnum);\r
+ c->Disconnect();\r
+ failedcw++;\r
+ if(failedcw>=10) {\r
+ // CCcam is having problems lets mark it for a restart....\r
+ FILE *f=fopen("/tmp/killCCcam","w+");\r
+ fclose(f);\r
+ failedcw=0;\r
+ }\r
+ return false;\r
}\r
- return false;\r
}\r
- memcpy(cw,savedcw[cardnum],16);\r
- newcw[cardnum] =0;\r
- PRINTF(L_CC_CCCAM," GOT CW FOR CARD %d !!!!!!!!!!!!!!!!!!",cardnum);\r
- sacapmt[cardnum][9]=pmtversion; //reserved - version - current/next\r
- pmtversion++;\r
- pmtversion%=32;\r
+ PRINTF(L_CC_CCCAM,"%d: GOT CW !",cardnum);\r
failedcw=0;\r
- Writecapmt(cardnum);\r
return true;\r
}\r
\r
-void cCardClientCCcam::Writecapmt(int n)\r
-{\r
- int len;\r
- int list_management ;\r
- list_management = LIST_ONLY;\r
- sacapmt[n][6] = list_management;\r
- len = sacapmt[n][4] << 8;\r
- len |= sacapmt[n][5];\r
- len += 6;\r
- int retry = 1;\r
- while (retry) {\r
- PRINTF(L_CC_CCCAM,"Writing capmt for card %d %d =================================================",n, sacapmt[n][6]);\r
- if (ccam_fd[n]==-1)\r
- lLogin(n);\r
- if (ccam_fd[n]==-1)\r
- return ;\r
-\r
- int r = write(ccam_fd[n], &sacapmt[n],len );\r
- if (r != len) {\r
- PRINTF(L_CC_CCCAM,"CCcam probably has crashed or been killed...");\r
- close(ccam_fd[n]);\r
- ccam_fd[n]=-1;\r
- retry++;\r
- if (retry > 2)\r
- retry =0;\r
- }\r
- else\r
- retry =0;\r
- }\r
-}\r
-\r
void cCardClientCCcam::Action()\r
{\r
unsigned char cw[18];\r
cw[2],cw[3],cw[4],cw[5],cw[6],cw[7],cw[8],cw[9],\r
cw[10],cw[11],cw[12],cw[13],cw[14],cw[15],cw[16],cw[17]);\r
\r
- if (cw[1] == 0x0f) {\r
- int n = cw[0];\r
- if (memcmp(savedcw[n],cw+2,16)) {\r
- if (newcw[n] == 1) {\r
- close(ccam_fd[n]);\r
- ccam_fd[n]=-1;\r
- }\r
- memcpy(savedcw[n],cw+2,16);\r
- newcw[n] =1;\r
- timecw[n]= cTimeMs::Now();\r
- PRINTF(L_CC_CCCAM,"SAVING KEYS USING PID FROM CCCAM %d !!!!!!!!!!!", n);\r
- }\r
- }\r
+ if(cw[1]==0x0f && cw[0]<4)\r
+ card[cw[0]].NewCw(cw+2);\r
}\r
}\r
}\r