--- /dev/null
+[COMMENT]
+** Please note that this was written for sasc-ng. Some things may be different
+** for vdr-sc. Corrections to this doc are welcome.
+** Suggestion: start reading at 4)
+[/COMMENT]
+
+CCcam and sasc0-ng HOWTO..
+
+Draft manual...
+
+Dont try and do this unless you feel are very compentant at compiling, sasc-ng and chroot...
+Please read the forums, dont PM me unless its constuctive or your contributing.
+
+Instructions...
+
+1) Download from svn sasc-ng, I used svn version 182, but it will probably work on later and earlier versions.
+
+2) Apply the patch
+
+ patch -p0 < CCcam-sasc-ng0.3.diff
+
+Note the patch makes a small change to vdr-sc so I can get the card number.
+
+3) Follow the sasc-ng instructions to complete the installation.
+
+4) Your cardclient.cfg file needs an entry like this...
+
+cccam:127.0.0.1:9000:0/0123/F000
+
+(note that CCcam interface will offer to serve any ECMs)
+
+5) Now it gets tricky, read some docs on the internet about chroot.
+
+I did this on Ubuntu 7.10 so it might not work on other distros...
+
+install dchroot,
+
+ apt-get install dchroot
+
+now create this directory structure
+
+/var/emu/
+/var/emu/chroot0
+/var/emu/chroot1
+/var/emu/chroot2
+/var/emu/chroot3
+
+copy the cpchroot.sh script into /var/emu
+
+cd /var/emu/chroot0
+
+then run the script to setup the chroot.
+
+sh ../cpchroot.sh
+
+This copies all the files you need from you main disk into the ringfenced chroot0.
+
+Next we need to bind some directories...
+
+mount --bind /dev /var/emu/chroot0/dev
+mount --bind /lib /var/emu/chroot0/lib
+mount --bind /bin /var/emu/chroot0/bin
+mount --bind /usr /var/emu/chroot0/usr
+
+
+You can check this is working by running
+
+chroot .
+
+This should put you in a sub world with all facilities you expect in a linux box, be aware that /dev /lib /bin and /usr are all linked to your main dir so any changes will occur in your main world. Importantly /var isnt so thats where all your CCcam files go.
+
+^D to exit the chroot.
+
+If it doesnt then it should moan about some library thats missing which you need to copy from /lib or /usr/lib into the same
+place inside the chroot.
+
+6) Install CCcam into /var/emu/chroot0/var/emu, with the run.sh script and the ca.c file.
+7) compile ca.c
+ cd /var/emu/chroot0/var/emu
+ gcc -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o ca.so ca.c -ldl
+
+(ignore the warnings)
+8) In yout boot up which method you use to do this you should have a line for insmod dvbloopback (assuming you have followed a guide for installing sasc-ng)
+
+With these line add this line.
+
+mount --bind /dev /var/emu/chroot0/dev
+cd /var/emu
+rm tmp/.CCcam.nodeid
+chroot chroot0 /var/emu/run.sh
+This gives access to the dvb devices in the sub chroot world.
+
+
+
+Example from my system
+
+mount --bind /dev /var/emu/chroot0/dev
+mount --bind /dev /var/emu/chroot1/dev
+mount --bind /dev /var/emu/chroot2/dev
+mount --bind /dev /var/emu/chroot3/dev
+rm /var/emu/chroot0/var/log/*
+rm /var/emu/chroot1/var/log/*
+rm /var/emu/chroot2/var/log/*
+rm /var/emu/chroot3/var/log/*
+rm /var/log/mythbackend.log
+chroot /var/emu/chroot0 /var/emu/run.sh &
+chroot /var/emu/chroot1 /var/emu/run.sh &
+chroot /var/emu/chroot2 /var/emu/run.sh &
+chroot /var/emu/chroot3 /var/emu/run.sh &
+cd /var/emu/sasc-ng/dvbloopback/module
+insmod dvbloopback.ko num_adapters=4
+cd /var/emu/sasc-ng
+sleep 5
+./sasc-ng -j 0:4 -j 1:5 -j 2:6 -j 3:7 > /var/log/sasclog.log&
+
+(if your using the myth patch to kill errant CCcams you will need these lines also)
+cd /var/emu
+sh ./cckill.sh &
+
+8) For multiple cards repeat steps 5 6 and 7 for /var/emu/chroot1,2,3. More than 4 cards wont work.
+
+9) Configuring your CCcam.cfgs which will live in /var/emu/chroot0,1,2,3/var/etc
+ The first card you set up to connect to your shares and your local cards.
+ The other cards you need to change the server port number from 12000 and configure it to share with the first...
+NOTE (PAY ATTENTION) its real important that if you connect all these instances to a central server that you make sure of these two things.
+ a) make sure that each instance doesnt use the same /tmp/.CCcam.nodeid
+ b) make sure that each instance has a different SERVER LISTEN PORT and logs in using DIFFERENT creditentials. (Your friends will get upset with you if you use the same C: line), So just to be CLEAR DO NOT HAVE MULTIPLE INSTANCES ON THE SAME C: LINE. (sorry about shouting)
+ e.g. just an example of daisy chaining the CCcams.
+
+ chroot0/var/etc/CCcam.cfg
+ F: card1 mythtomyth 3 1 1
+ F: card2 mythtomyth 3 1 1
+ F: card3 mythtomyth 3 1 1
+ C: myfriend.no-ip.info 12000 mates matespass
+ SERIAL READER : /dev/ttyUSB1 smartreader+
+ chroot1/var/etc/CCcam.cfg
+ C: 192.168.1.42 12000 card1 mythtomyth
+ SERVER LISTEN PORT : 12001
+ WEBINFO LISTEN PORT : 16001
+ chroot2/var/etc/CCcam.cfg
+ C: 192.168.1.42 12000 card2 mythtomyth
+ SERVER LISTEN PORT : 12002
+ WEBINFO LISTEN PORT : 16002
+ chroot3/var/etc/CCcam.cfg
+ C: 192.168.1.42 12000 card3 mythtomyth
+ SERVER LISTEN PORT : 12003
+ WEBINFO LISTEN PORT : 16003
+
+
+10) As the intructions for sasc-ng say load the dvbloopback driver and run up sasc-ng.
+
+Watching the logs on sasc-ng you should see something like this.
+Mar 15 14:22:30.140 CAM(cardclient.cccam): Processing ECM....
+Mar 15 14:22:30.149 CAM(cardclient.cccam): Got: CC0f XXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXX
+Mar 15 14:22:30.149 CAM(cardclient.cccam): SAVING KEYS USING PID FROM CCCAM 2 !!!!!!!!!!!
+Mar 15 14:22:30.150 CAM(cardclient.cccam): KEYS FOR CARD 2 !!!!!!!!!!!!!!!!!!
+Called cSascDvbDevice::SetCaDescr
+Mar 15 14:22:30.150 CSA: Got command(6): O idx: 1 pid: 0 key: XXXX...XX
+
+CC = the card number 00,01,02,03 etc.
+
+11) Notes....
+
+ This hack is a little more complex than the ordinary, and you need to know your stuff to make it work.
+ Rules, dont PM me for help, try the forum.
+ Bugs with fixes PM me, bugs without post on the forum.
+
+12) TODO.
+ Work out how to get EMMs working, you will need to share with a source of EMMs if you want to keep your
+ card upto date.
+ All work on the mythtv CCcam/sasc/gbox code has ceased and will not be supported.
+ All work with gbox has ceased.
+ Make this howto better, all contributions are greatfully received.
+
+I have this working with a 4 card setup, running stock unpatched trunk myth.
--- /dev/null
+/*\r
+ * Softcam plugin to VDR (C++)\r
+ *\r
+ * This code is free software; you can redistribute it and/or\r
+ * modify it under the terms of the GNU General Public License\r
+ * as published by the Free Software Foundation; either version 2\r
+ * of the License, or (at your option) any later version.\r
+ *\r
+ * This code is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program; if not, write to the Free Software\r
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
+ * Or, point your browser to http://www.gnu.org/copyleft/gpl.html\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <stdint.h>\r
+#include <unistd.h>\r
+#include <errno.h>\r
+#include <sys/types.h>\r
+#include <sys/socket.h>\r
+#include <sys/time.h>\r
+#include <sys/un.h>\r
+#include <stdlib.h>\r
+#include <errno.h>\r
+#include <string.h>\r
+#include <sys/un.h>\r
+#include <fcntl.h>\r
+#include <netinet/in.h>\r
+#include <unistd.h>\r
+#include <arpa/inet.h>\r
+#include <signal.h>\r
+#include <pthread.h>\r
+\r
+#include <vdr/pat.h>\r
+\r
+#include "cc.h"\r
+#include "network.h"\r
+#include "parse.h"\r
+\r
+// START (C) 2002 by Andreas Oberritter <obi@tuxbox.org>\r
+\r
+#define MAX_PIDS 4\r
+\r
+typedef struct descrambleservice_t\r
+{\r
+ unsigned char valid;\r
+ unsigned char started;\r
+ unsigned short status;\r
+ unsigned short onID;\r
+ unsigned short sID;\r
+ unsigned short Unkwn;\r
+ unsigned short caID;\r
+ unsigned short ecmPID;\r
+ unsigned char numpids;\r
+ unsigned short pid[MAX_PIDS];\r
+\r
+} descrambleservice_s;\r
+\r
+typedef struct ca_descriptor_s\r
+{\r
+ unsigned char descriptor_tag : 8;\r
+ unsigned char descriptor_length : 8;\r
+ unsigned short ca_system_id : 16;\r
+ unsigned char reserved : 3;\r
+ unsigned short ca_pid : 13;\r
+ unsigned char * private_data_byte;\r
+} __attribute__ ((packed)) ca_descriptor;\r
+\r
+typedef struct ca_pmt_program_info_s\r
+{\r
+ unsigned char ca_pmt_cmd_id : 8;\r
+ ca_descriptor * descriptor;\r
+} __attribute__ ((packed)) ca_pmt_program_info;\r
+\r
+typedef struct ca_pmt_es_info_s\r
+{\r
+ unsigned char stream_type : 8;\r
+ unsigned char reserved : 3;\r
+ unsigned short elementary_pid : 13;\r
+ unsigned char reserved2 : 4;\r
+ unsigned short es_info_length : 12;\r
+ ca_pmt_program_info * program_info;\r
+} __attribute__ ((packed)) ca_pmt_es_info;\r
+\r
+typedef struct ca_pmt_s\r
+{\r
+ unsigned char ca_pmt_list_management : 8;\r
+ unsigned short program_number : 16;\r
+ unsigned char reserved1 : 2;\r
+ unsigned char version_number : 5;\r
+ unsigned char current_next_indicator : 1;\r
+ unsigned char reserved2 : 4;\r
+ unsigned short program_info_length : 12;\r
+ ca_pmt_program_info * program_info;\r
+ ca_pmt_es_info * es_info;\r
+} __attribute__ ((packed)) ca_pmt;\r
+// END (C) 2002 by Andreas Oberritter <obi@tuxbox.org>\r
+\r
+#define LIST_MORE 0x00 /* CA application should append a 'MORE' CAPMT object the list, and start receiving the next object */\r
+#define LIST_FIRST 0x01 /* CA application should clear the list when a 'FIRST' CAPMT object is received, and start receiving the next object */\r
+#define LIST_LAST 0x02 /* CA application should append a 'LAST' CAPMT object to the list, and start working with the list */\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
+#define LIST_ADD 0x04 /* CA application should append an 'ADD' CAPMT object to the current list, and start working with the updated list */\r
+#define LIST_UPDATE 0x05 /* CA application should replace an entry in the list with an 'UPDATE' CAPMT object, and start working with the updated list */\r
+/* ca_pmt_cmd_id's: */\r
+#define CMD_OK_DESCRAMBLING 0x01 /* CA application should start descrambling the service in this CAPMT object, as soon as the list of CAPMT objects is complete */\r
+\r
+int parse_ca_pmt ( unsigned char * buffer, unsigned int length);\r
+\r
+// -- cCCcamClient -----------------------------------------------------------\r
+\r
+class cCardClientCCcam : public cCardClient , private cThread {\r
+private:\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 cwccam_fd;\r
+ int lastcard;\r
+ int lastpid;\r
+ int failedcw;\r
+ //\r
+ void Writecapmt(int j);\r
+ int CCSelect(int sd, bool forRead, int s);\r
+ bool GetCCamCw(unsigned char *cw, int s);\r
+ int startportlistener();\r
+protected:\r
+ virtual bool lLogin(int cardnum);\r
+ virtual void Action(void);\r
+public:\r
+ cCardClientCCcam(const char *Name);\r
+ virtual bool Init(const char *CfgDir);\r
+ virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum);\r
+ bool CanHandle(unsigned short SysId)\r
+{\r
+if ((SysId & 0xf000) != 0x5000)\r
+ return true;\r
+else\r
+ return false;\r
+}\r
+\r
+};\r
+\r
+static cCardClientLinkReg<cCardClientCCcam> __ncd("CCcam");\r
+\r
+cCardClientCCcam::cCardClientCCcam(const char *Name)\r
+:cCardClient(Name)\r
+{\r
+ cwccam_fd=-1;\r
+ pmtversion=0;\r
+ ccam_fd[0] = -1;\r
+ ccam_fd[1] = -1;\r
+ ccam_fd[2] = -1;\r
+ ccam_fd[3] = -1;\r
+}\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
+\r
+\r
+bool cCardClientCCcam::lLogin(int cardnum)\r
+{\r
+ int rc;\r
+ int so =0;\r
+ sockaddr_un serv_addr_un;\r
+ char camdsock[256];\r
+ int res;\r
+\r
+ struct sockaddr_in servAddr;\r
+ fflush(NULL);\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
+ {\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
+ if (cwccam_fd!=-1) return 1;\r
+ PRINTF(L_CC_CCCAM,"logging in");\r
+ so=socket(AF_INET, SOCK_DGRAM, 0);\r
+ if(so<0)\r
+ {\r
+ close(so);\r
+ return false;\r
+ }\r
+ bzero(&servAddr, sizeof(servAddr));\r
+ servAddr.sin_family = AF_INET;\r
+ servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");\r
+ servAddr.sin_port = htons(port);\r
+ rc = bind (so, (struct sockaddr *) &servAddr,sizeof(servAddr));\r
+ if(rc<0)\r
+ {\r
+ close(so);\r
+ PRINTF(L_CC_CCCAM,"not logged in");\r
+ return false;\r
+ }\r
+ cwccam_fd =so;\r
+ PRINTF(L_CC_CCCAM,"logged in");\r
+ startportlistener();\r
+\r
+ return true;\r
+}\r
+\r
+\r
+bool cCardClientCCcam::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)\r
+{\r
+\r
+ // if(((ccam_fd ==0) && !Login()) || !CanHandle(ecm->caId)) return false;\r
+ //so.Flush();\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
+ int len=19;\r
+ int wp=31;\r
+ int casys[2];\r
+ casys[0]=caid;\r
+ casys[1]=0;\r
+\r
+ //PRINTF(L_CC_CCCAM,"Card num beign used... - %d, pid %d progid %d provid %d caid %d",cardnum, pid,ecm->prgId, ecm->provId, ecm->caId );\r
+ memcpy(capmt,"\x9f\x80\x32\x82\x00\x00", 6);\r
+\r
+ capmt[6]=0x01;\r
+ //prg-nr\r
+ capmt[7]=(unsigned char)((ecm->prgId>>8) & 0xff);\r
+ //prg-nr\r
+ capmt[8]=(unsigned char)(ecm->prgId & 0xff);\r
+\r
+ capmt[9]=pmtversion; //reserved - version - current/next\r
+ pmtversion++;\r
+ pmtversion%=32;\r
+ //0x00; reserved - prg-info len\r
+ capmt[10]=(unsigned char)((ecm->prgId>>8) & 0xff);\r
+ //0x00; prg-info len\r
+ capmt[11]=(unsigned char)(ecm->prgId & 0xff);\r
+ // this is ASN.1 this is NOT the way you do BER...\r
+ capmt[12]=0x01; //CMD_OK_DESCRAMBLING; ca pmt command id\r
+ capmt[13]=0x81; // private descr.. dvbnamespace\r
+ capmt[14]=0x08;\r
+ {\r
+ int dvb_namespace = cardnum<<8;\r
+ capmt[15]=dvb_namespace>>24;\r
+ capmt[16]=(dvb_namespace>>16)&0xFF;\r
+ capmt[17]=(dvb_namespace>>8)&0xFF;\r
+ capmt[18]=dvb_namespace&0xFF;\r
+ }\r
+ capmt[19]=ecm->transponder>>8;\r
+ capmt[20]=ecm->transponder&0xFF;\r
+ capmt[21]=ecm->provId>>8;\r
+ capmt[22]=ecm->provId&0xFF;\r
+\r
+ capmt[23]=0x82; // demuxer kram..\r
+ capmt[24]=0x02;\r
+ capmt[25]= 1<<cardnum ;\r
+ capmt[26]= cardnum ;\r
+ capmt[27]=0x84; // pmt pid\r
+ capmt[28]=0x02;\r
+ capmt[29]=pid>>8;\r
+ capmt[30]=pid&0xFF;\r
+ bool streamflag = 1;\r
+ int n=GetCaDescriptors(ecm->source,ecm->transponder,ecm->prgId,casys,sizeof(capmt)-31,&capmt[31],streamflag);\r
+ len+=n;\r
+ wp+=n;\r
+ capmt[wp++] = 0x01;\r
+ capmt[wp++] = 0x0f;\r
+ // cccam uses this one as PID to program ca0..\r
+ capmt[wp++] = cardnum&0xFF;\r
+ capmt[wp++] = 0x00; //es_length\r
+ capmt[wp++] = 0x06; //es ca_pmt_cmd_id\r
+\r
+ capmt[lenpos]=((len & 0xf00)>>8);\r
+ capmt[lenpos+1]=(len & 0xff);\r
+ capmt[4]=((wp-6)>>8) & 0xff;\r
+ capmt[5]=(wp-6) & 0xff;\r
+ if (newcw[cardnum])\r
+ {\r
+ cTimeMs k;\r
+ if ((k.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))\r
+ { // 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
+ }\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
+ {\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
+ {\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
+ {\r
+ // CCcam is having problems lets mark it for a restart....\r
+ FILE *i = fopen("/tmp/killCCcam","w+");\r
+ fclose(i);\r
+\r
+\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
+ failedcw=0;\r
+ Writecapmt(cardnum);\r
+ return true;\r
+}\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
+ {\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
+ {\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
+\r
+int cCardClientCCcam::startportlistener()\r
+{\r
+ PRINTF(L_CC_CCCAM,"starting UDP listener");\r
+ SetDescription("CCcamd listener...");\r
+ Start();\r
+\r
+ return 1;\r
+}\r
+\r
+\r
+void cCardClientCCcam::Action()\r
+{\r
+ unsigned char cw[18];\r
+ while (1)\r
+ {\r
+ if (GetCCamCw(cw,0))\r
+ {\r
+ int pid;\r
+ cTimeMs k;\r
+ pid = cw[0] + (cw[1]<<8);\r
+ PRINTF(L_CC_CCCAM," Got: %02hhx%02hhx %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx %02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",\r
+ cw[0], cw[1], cw[2], cw[3],\r
+ cw[4], cw[5], cw[6], cw[7],\r
+ cw[8], cw[9], cw[10], cw[11],\r
+ cw[12], cw[13], cw[14], cw[15], cw[16], cw[17]);\r
+\r
+ if (cw[1] == 0x0f)\r
+ {\r
+ int n = cw[0];\r
+ if (memcmp(savedcw[n],cw+2,16))\r
+ {\r
+ if (newcw[n] == 1)\r
+ {\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]= k.Now();\r
+ PRINTF(L_CC_CCCAM,"SAVING KEYS USING PID FROM CCCAM %d !!!!!!!!!!!", n);\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+\r
+bool cCardClientCCcam::GetCCamCw(unsigned char *cw, int s)\r
+{\r
+ unsigned char msg[18];\r
+ int n;\r
+ struct sockaddr cliAddr;\r
+ socklen_t cliLen;\r
+ cliLen = sizeof(cliAddr);\r
+ if (CCSelect(cwccam_fd, true,100))\r
+ n = ::recvfrom(cwccam_fd, msg, 18, 0, (struct sockaddr *) &cliAddr, &cliLen);\r
+ else\r
+ return false;\r
+ if(n<0)\r
+ return false;\r
+ memcpy(cw, msg, 18);\r
+ return(true);\r
+}\r
+\r
+\r
+int cCardClientCCcam::CCSelect(int sd, bool forRead, int s)\r
+{\r
+ if(sd>=0)\r
+ {\r
+ fd_set fds;\r
+ FD_ZERO(&fds); FD_SET(sd,&fds);\r
+ struct timeval tv;\r
+ tv.tv_sec=4; tv.tv_usec=000;\r
+ int r=::select(sd+1,forRead ? &fds:0,forRead ? 0:&fds,0,&tv);\r
+ if(r>0) return 1;\r
+ else if(r<0)\r
+ {\r
+ return 0;\r
+ }\r
+ else\r
+ {\r
+ return 0;\r
+ }\r
+ }\r
+ return 0;\r
+}\r
+\r
+\r
+int caid_count =1 ;\r
+int parse_ca_pmt ( unsigned char * buffer, unsigned int length)\r
+{\r
+ unsigned short i, j;\r
+ ca_pmt * pmt;\r
+ descrambleservice_s service;\r
+\r
+ memset(&service, 0, sizeof(descrambleservice_s));\r
+\r
+ pmt = (ca_pmt *) malloc(sizeof(ca_pmt));\r
+\r
+ pmt->ca_pmt_list_management = buffer[0];\r
+ pmt->program_number = (buffer[1] << 8) | buffer[2];\r
+ pmt->program_info_length = ((buffer[4] & 0x0F) << 8) | buffer[5];\r
+\r
+ printf("ca_pmt_list_management: %02x\n", pmt->ca_pmt_list_management);\r
+ printf("prugram number: %04x\n", pmt->program_number);\r
+ printf("program_info_length: %04x\n", pmt->program_info_length);\r
+ switch (pmt->ca_pmt_list_management)\r
+ {\r
+ case 0x01: /* first */\r
+ printf("first\n");\r
+ break;\r
+ case 0x03: /* only */\r
+ printf("only\n");\r
+ break;\r
+\r
+ default:\r
+ printf("unknown\n");\r
+ break;\r
+ }\r
+\r
+ if (pmt->program_info_length != 0)\r
+ {\r
+ pmt->program_info = (ca_pmt_program_info *) malloc(sizeof(ca_pmt_program_info));\r
+ pmt->program_info->ca_pmt_cmd_id = buffer[6];\r
+ printf("ca_pmt_id: %04x\n", pmt->program_info->ca_pmt_cmd_id);\r
+ pmt->program_info->descriptor = (ca_descriptor *) malloc(sizeof(ca_descriptor));\r
+\r
+ for (i = 0; i < pmt->program_info_length - 1; i += pmt->program_info->descriptor->descriptor_length + 2)\r
+ {\r
+ pmt->program_info->descriptor->descriptor_length = buffer[i + 8];\r
+ pmt->program_info->descriptor->ca_system_id = (buffer[i + 9] << 8) | buffer[i + 10];\r
+ pmt->program_info->descriptor->ca_pid = ((buffer[i + 11] & 0x1F) << 8)| buffer[i + 12];\r
+ printf("ca_descriptor_length %d\n",pmt->program_info->descriptor->descriptor_length);\r
+ printf("ca_system_id: %04x\n", pmt->program_info->descriptor->ca_system_id);\r
+ printf("ca_pid: %04x\n", pmt->program_info->descriptor->ca_pid);\r
+\r
+ }\r
+\r
+ free(pmt->program_info->descriptor);\r
+ free(pmt->program_info);\r
+ }\r
+\r
+ pmt->es_info = (ca_pmt_es_info *) malloc(sizeof(ca_pmt_es_info));\r
+\r
+ for (i = pmt->program_info_length + 6; i < length; i += pmt->es_info->es_info_length + 5)\r
+ {\r
+ if (service.numpids == MAX_PIDS)\r
+ {\r
+ break;\r
+ }\r
+\r
+ pmt->es_info->stream_type = buffer[i];\r
+ pmt->es_info->elementary_pid = ((buffer[i + 1] & 0x1F) << 8) | buffer[i + 2];\r
+ pmt->es_info->es_info_length = ((buffer[i + 3] & 0x0F) << 8) | buffer[i + 4];\r
+\r
+ printf("stream_type: %02x\n", pmt->es_info->stream_type);\r
+ printf("elementary_pid: %04x\n", pmt->es_info->elementary_pid);\r
+ printf("es_info_length: %04x\n", pmt->es_info->es_info_length);\r
+\r
+ service.pid[service.numpids++] = pmt->es_info->elementary_pid;\r
+\r
+ if (pmt->es_info->es_info_length != 0)\r
+ {\r
+ pmt->es_info->program_info = (ca_pmt_program_info *) malloc(sizeof(ca_pmt_program_info));\r
+\r
+ pmt->es_info->program_info->ca_pmt_cmd_id = buffer[i + 5];\r
+ pmt->es_info->program_info->descriptor = (ca_descriptor *)malloc(sizeof(ca_descriptor));\r
+\r
+ for (j = 0; j < pmt->es_info->es_info_length - 1; j += pmt->es_info->program_info->descriptor->descriptor_length + 2)\r
+ {\r
+ pmt->es_info->program_info->descriptor->descriptor_length = buffer[i + j + 7];\r
+ pmt->es_info->program_info->descriptor->ca_system_id = (buffer[i + j + 8] << 8) | buffer[i + j + 9];\r
+ pmt->es_info->program_info->descriptor->ca_pid = ((buffer[i + j + 10] & 0x1F) << 8) | buffer[i + j + 11];\r
+\r
+ printf("ca_system_id: %04x\n", pmt->es_info->program_info->descriptor->ca_system_id);\r
+ printf("ca_pid: %04x\n", pmt->es_info->program_info->descriptor->ca_pid);\r
+\r
+ if (service.caID != 0)\r
+ {\r
+ break;\r
+ }\r
+ }\r
+\r
+ free(pmt->es_info->program_info->descriptor);\r
+ free(pmt->es_info->program_info);\r
+ }\r
+ }\r
+\r
+ service.sID = pmt->program_number;\r
+\r
+ free(pmt->es_info);\r
+ free(pmt);\r
+\r
+ if ((service.numpids != 0) && (service.caID != 0))\r
+ {\r
+ service.onID = 0x0085;\r
+\r
+ service.Unkwn = 0x0104;\r
+\r
+ return 0; // return adddescrambleservicestruct(&service);\r
+ }\r
+ else\r
+ {\r
+ return -1;\r
+ }\r
+}\r
+\r
+\r
+unsigned int parse_length_field (unsigned char * buffer)\r
+{\r
+ unsigned char size_indicator = (buffer[0] >> 7) & 0x01;\r
+ unsigned int length_value = 0;\r
+\r
+ if (size_indicator == 0)\r
+ {\r
+ length_value = buffer[0] & 0x7F;\r
+ }\r
+\r
+ else if (size_indicator == 1)\r
+ {\r
+ unsigned char length_field_size = buffer[0] & 0x7F;\r
+ unsigned int i;\r
+\r
+ for (i = 0; i < length_field_size; i++)\r
+ {\r
+ length_value = (length_value << 8) | buffer[i + 1];\r
+ }\r
+ }\r
+\r
+ return length_value;\r
+}\r
+\r
+\r
+unsigned char get_length_field_size (unsigned int length)\r
+{\r
+ if (length < 0x80)\r
+ {\r
+ return 0x01;\r
+ }\r
+\r
+ if (length < 0x100)\r
+ {\r
+ return 0x02;\r
+ }\r
+\r
+ if (length < 0x10000)\r
+ {\r
+ return 0x03;\r
+ }\r
+\r
+ if (length < 0x1000000)\r
+ {\r
+ return 0x04;\r
+ }\r
+\r
+ else\r
+ {\r
+ return 0x05;\r
+ }\r
+}\r