]> www.vanbest.org Git - sasc-ng.git/commitdiff
cardclient: add CCcam client (see README.CCcam)
authorrd250lc <unknown>
Mon, 9 Jun 2008 03:50:25 +0000 (11:50 +0800)
committerrd250lc <unknown>
Mon, 9 Jun 2008 03:50:25 +0000 (11:50 +0800)
README.CCcam [new file with mode: 0644]
systems/cardclient/aroureos.c
systems/cardclient/camd.c
systems/cardclient/cc.c
systems/cardclient/cc.h
systems/cardclient/cc.mk
systems/cardclient/cccam.c [new file with mode: 0644]
systems/cardclient/gbox.c
systems/cardclient/newcamd.c
systems/cardclient/radegast.c

diff --git a/README.CCcam b/README.CCcam
new file mode 100644 (file)
index 0000000..0cd686a
--- /dev/null
@@ -0,0 +1,175 @@
+[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.
index d34544deacf0324563d0dcdd24636a8f0237935a..ad08173228ecf5f580a6cdd5e5621b17196faa2c 100644 (file)
@@ -36,7 +36,7 @@ protected:
 public:
   cCardClientAroureos(const char *Name);
   virtual bool Init(const char *config);
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum);
   virtual bool ProcessEMM(int caSys, const unsigned char *source);
   };
 
@@ -102,7 +102,7 @@ bool cCardClientAroureos::ProcessEMM(int caSys, const unsigned char *source)
   return false;
 }
 
-bool cCardClientAroureos::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
+bool cCardClientAroureos::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum)
 {
   cMutexLock lock(this);
   so.Flush();
index 7d5c09623a41ea5aa6c81c30c57a83079b3bd775..5334a6d24f6be86b3f759b5522b7c9106d6af3dc 100644 (file)
@@ -56,7 +56,7 @@ protected:
 public:
   cCardClientCommon(const char *Name, bool ConReply, bool LogReply, bool DoAES, int MinMsgLen);
   virtual bool Init(const char *config);
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum);
   virtual bool ProcessEMM(int caSys, const unsigned char *source);
   };
 
@@ -194,7 +194,7 @@ bool cCardClientCommon::ProcessEMM(int caSys, const unsigned char *source)
   return false;
 }
 
-bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
+bool cCardClientCommon::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum)
 {
   Lock();
   bool res=false;
@@ -435,7 +435,7 @@ protected:
 public:
   cCardClientCamd35(const char *Name);
   virtual bool Init(const char *config);
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw);
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum);
   virtual bool ProcessEMM(int caSys, const unsigned char *data);
   };
 
@@ -662,7 +662,7 @@ bool cCardClientCamd35::ProcessEMM(int caSys, const unsigned char *data)
   return false;
 }
 
-bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
+bool cCardClientCamd35::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)
 {
   bool res=false;
   const int length=SCT_LEN(data);
index feb9816d940e31b38366524880e346a7bfd92798..6ea9d486cfb7d2d08a164a23db6bbd954736d757 100644 (file)
 static const struct LogModule lm_cc = {
   (LMOD_ENABLE|L_CC_ALL)&LOPT_MASK,
   (LMOD_ENABLE|L_CC_CORE|L_CC_LOGIN|L_CC_ECM|L_CC_EMM|L_CC_CAMD|L_CC_CAMD35|
-   L_CC_RDGD|L_CC_NEWCAMD|L_CC_GBOX)&LOPT_MASK,
+   L_CC_RDGD|L_CC_NEWCAMD|L_CC_GBOX|L_CC_CCCAM)&LOPT_MASK,
   "cardclient",
   { "core","login","ecm","emm","camd","camd35","camd35extra","radegast",
-    "newcamd","gbox" }
+    "newcamd","gbox","cccam" }
   };
 ADD_MODULE(L_CC,lm_cc)
 
@@ -197,7 +197,7 @@ bool cSystemCardClient::ProcessECM(const cEcmInfo *ecm, unsigned char *data)
     if(cc) {
       cTimeMs start;
       int id=cc->msECM.Get(data,SCT_LEN(data),cw);
-      if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw))) {
+      if(id==0 || (id>0 && cc->ProcessECM(ecm,data,cw,CardNum()))) {
         int dur=start.Elapsed();
         if(dur>2000) {
           char bb[32];
index 2cc117a9d197d942a17925efded8469854560a1f..e93d1801fb5f376f5e4d7d9a80eea77788eee4a9 100644 (file)
@@ -36,8 +36,9 @@
 #define L_CC_RDGD     LCLASS(L_CC,0x100)
 #define L_CC_NEWCAMD  LCLASS(L_CC,0x200)
 #define L_CC_GBOX     LCLASS(L_CC,0x400)
+#define L_CC_CCCAM    LCLASS(L_CC,0x800)
 
-#define L_CC_ALL      LALL(L_CC_GBOX)
+#define L_CC_ALL      LALL(L_CC_CCCAM)
 
 // ----------------------------------------------------------------
 
@@ -69,7 +70,7 @@ public:
   cCardClient(const char *Name);
   virtual bool Init(const char *config)=0;
   virtual bool CanHandle(unsigned short SysId);
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)=0;
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)=0;
   virtual bool ProcessEMM(int caSys, const unsigned char *data) { return false; }
   const char *Name(void) { return name; }
   };
index e2200603b54da1a1d2b553bbfd9648a0a908a2e2..468828ac992780f709385b7260f5134259f88c46 100644 (file)
@@ -2,5 +2,5 @@
 # Cardclient
 #
 TARGET = cardclient
-OBJS   = cc.o camd.o radegast.o aroureos.o newcamd.o gbox.o
+OBJS   = cc.o camd.o radegast.o aroureos.o newcamd.o gbox.o cccam.o
 LIBS   = -lcrypto -lcrypt
diff --git a/systems/cardclient/cccam.c b/systems/cardclient/cccam.c
new file mode 100644 (file)
index 0000000..e229e6a
--- /dev/null
@@ -0,0 +1,656 @@
+/*\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
index fa7c88a08f9340af47a002be636b655d8ddd4159..81d08c598b05eb38d74cc6c943841eb49ea84c8a 100644 (file)
@@ -43,7 +43,7 @@ protected:
 public: 
   cCardClientGbox(const char *Name); 
   virtual bool Init(const char *CfgDir); 
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw); 
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum);
   }; 
  
 static cCardClientLinkReg<cCardClientGbox> __ncd("gbox");
@@ -81,7 +81,7 @@ int cCardClientGbox::GetMsg(int cmd, unsigned char *buff, int len)
   return n;
 }
 
-bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw
+bool cCardClientGbox::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)
 {
   cMutexLock lock(this);
   if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
index cf5d6c703345bb95f947cc62987312677aa833d6..a53e861d03fba902057da53a3c1556f8edc818ec 100644 (file)
@@ -193,7 +193,7 @@ public:
   // 
   virtual bool Init(const char *CfgDir);
   virtual bool CanHandle(unsigned short SysId);  
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw);
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *Cw, int cardnum);
   virtual bool ProcessEMM(int caSys, const unsigned char *data);
   };
 
@@ -469,7 +469,7 @@ bool cCardClientNewCamd::Login(void)
   return true;
 }
 
-bool cCardClientNewCamd::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw)
+bool cCardClientNewCamd::ProcessECM(const cEcmInfo *ecm, const unsigned char *data, unsigned char *cw, int cardnum)
 {
   cMutexLock lock(this);
   if((!so.Connected() && !Login()) || !CanHandle(ecm->caId)) return false;
index e497df047978cfc45d141e97499c212634ee038d..01f1e05f646de7919beb4fb897fd57b72907c642 100644 (file)
@@ -53,7 +53,7 @@ public:
   cCardClientRadegast(const char *Name);
   virtual bool Init(const char *config);
   virtual bool CanHandle(unsigned short SysId);  
-  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw);
+  virtual bool ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum);
   virtual bool ProcessEMM(int caSys, const unsigned char *data);
   };
 
@@ -218,7 +218,7 @@ bool cCardClientRadegast::Login(void)
   return true; 
 }
 
-bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw)
+bool cCardClientRadegast::ProcessECM(const cEcmInfo *ecm, const unsigned char *source, unsigned char *cw, int cardnum)
 {
   cMutexLock lock(this);
   so.Flush();