]> www.vanbest.org Git - sasc-ng.git/commitdiff
contrib: add CCcam ca.so pre-load library
authorleslie <unknown>
Tue, 9 Jun 2009 22:29:17 +0000 (06:29 +0800)
committerleslie <unknown>
Tue, 9 Jun 2009 22:29:17 +0000 (06:29 +0800)
Makefile
README.CCcam
contrib/Makefile [new file with mode: 0644]
contrib/cccam_ca.c [new file with mode: 0644]

index 656e422c04330276c8a4b47eb5882aa0621b930a..b2340f6638c22fdee6cedeedc01662b30e98dac7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -152,18 +152,19 @@ export CXXFLAGS
 ### Targets:
 
 ifdef STATIC
-BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).a systems
+BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).a
 SHAREDDEFINES += -DSTATICBUILD
 else
-BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) systems systems-pre
+BUILDTARGETS = $(LIBDIR)/libvdr-$(PLUGIN).so.$(APIVERSION) systems-pre
 endif
+BUILDTARGETS += systems contrib
 
 ifneq ($(strip $(HASLOCALE)),)
 BUILDTARGETS += i18n
 endif
 
 all: $(BUILDTARGETS)
-.PHONY: i18n systems systems-pre clean clean-core clean-systems clean-pre dist srcdist
+.PHONY: i18n systems systems-pre contrib clean clean-core clean-systems clean-pre dist srcdist
 
 # Dependencies:
 
@@ -224,11 +225,15 @@ systems:
 systems-pre:
        @for i in `ls -A -I ".*" $(PREDIR) | grep -- '-$(SCAPIVERS).so.$(APIVERSION)$$'`; do cp -p "$(PREDIR)/$$i" "$(LIBDIR)"; done
 
+contrib:
+       @$(MAKE) -C contrib all
+
 clean-systems:
        @for i in `ls -A -I ".*" $(SYSDIR)`; do $(MAKE) -f ../../Makefile.system -C "$(SYSDIR)/$$i" clean; done
 
 clean-core:
        @$(MAKE) -C testing clean
+       @$(MAKE) -C contrib clean
        @if test -d $(FFDECSADIR); then $(MAKE) -C $(FFDECSADIR) clean; fi
        @-rm -f $(LIBDIR)/libsc-*-$(SCAPIVERS).so.$(APIVERSION)
        @-rm -f $(LIBDIR)/libvdr-$(PLUGIN).a $(LIBDIR)/libsc-*.a
index 743b94809f1ccefc56fc74d6361ea5435e8162a5..ee5c5d494c38a332ca47d5ba366d8dfb919843f6 100644 (file)
@@ -79,6 +79,12 @@ place inside the chroot.
 7) compile ca.c
        cd /var/emu/chroot0/var/emu
        gcc -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o ca.so ca.c -ldl
+[COMMENT]
+** With vdr-sc the file has been renamed to cccam_ca.c and cccam_ca.so.
+** You will find the compiled cccam_ca.so in the contrib directory
+** after making the plugin
+** Probably you need to adjust you startup script to the new name.
+[/COMMENT]
 
 (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)
diff --git a/contrib/Makefile b/contrib/Makefile
new file mode 100644 (file)
index 0000000..7184e47
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# Softcam plugin to VDR
+#
+# 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 http://www.gnu.org/copyleft/gpl.html
+
+all: cccam_ca.so
+.PHONY: clean
+
+
+cccam_ca.so: cccam_ca.c
+       gcc -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o $@ $< -ldl
+
+clean:
+       @-rm cccam_ca.so
diff --git a/contrib/cccam_ca.c b/contrib/cccam_ca.c
new file mode 100644 (file)
index 0000000..4ce850d
--- /dev/null
@@ -0,0 +1,261 @@
+/* Compile as follows:
+ * gcc -O -fbuiltin -fomit-frame-pointer -fPIC -shared -o ca.so ca.c -ldl
+ *
+ * run cccam with:
+ * LD_PRELOAD=./ca.so ./xxx.i386
+ *
+ * Will then send CWs to vdr-sc cardclient cccam
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+//#define DEBUG
+
+#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
+
+#include <dlfcn.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <linux/dvb/ca.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend.h>
+#include <linux/ioctl.h>
+#include <stdio.h>
+#include <time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/un.h>
+#include <syslog.h>
+#include <errno.h>
+
+#if defined(RTLD_NEXT)
+#define REAL_LIBC RTLD_NEXT
+#else
+#define REAL_LIBC ((void *) -1L)
+#endif
+
+#define PORT 9000
+#define MAX_CA  4
+
+static int cafd[MAX_CA]  = {-1,-1,-1,-1};
+static int cafdc[MAX_CA] = {0,0,0,0};
+
+#define MAX_INDEX 64
+#define KEY_SIZE  8
+#define INFO_SIZE (2+KEY_SIZE+KEY_SIZE)
+#define EVEN_OFF  (2)
+#define ODD_OFF   (2+KEY_SIZE)
+
+static unsigned char ca_info[MAX_CA][MAX_INDEX][INFO_SIZE];
+
+#define CA_BASE                "/dev/dvb/adapter0/ca"
+#define DEMUX_BASE     "/dev/dvb/adapter0/demux"
+#define DEMUX_MAP      "/dev/dvb/adapter%d/demux0"
+#define CPUINFO_BASE   "/proc/cpuinfo"
+#define CPUINFO_MAP    "/tmp/cpuinfo"
+
+//#define DBG(x...) {syslog(LOG_INFO, x);}
+#define DBG(x...)
+#define INF(x...) {syslog(LOG_INFO, x);}
+#define ERR(x...) {syslog(LOG_ERR, x);}
+
+int proginfo=0;
+#define PROGINFO() {if(!proginfo){syslog(LOG_INFO,"ca.so for cccam V1.09");proginfo=1;}}
+
+int sendcw(int fd, unsigned char *buff) {
+  DBG(">>>>>>>> sendcw %02x%02x %02x%02x%02x%02x%02x%02x%02x%02x %02x%02x%02x%02x%02x%02x%02x%02x", buff[0], buff[1], buff[2], buff[3], buff[4], buff[5], buff[6], buff[7], buff[8], buff[9], buff[10], buff[11], buff[12], buff[13], buff[14], buff[15], buff[16], buff[17], buff[18]);
+  if ( send(fd,buff, 18, 0) == -1 ) { 
+       ERR("ca.so: Send cw failed %d", errno);
+    return 0;
+  } // if
+  return 1;
+} // sendcw
+
+static int cactl (int fd, int cai, int request, void *argp) {
+  ca_descr_t *ca = (ca_descr_t *)argp;
+  ca_pid_t  *cpd = (ca_pid_t  *)argp;
+  switch (request) {
+    case CA_SET_DESCR:
+      DBG(">>>>>>>> cactl CA_SET_DESCR fd %d cai %d req %d par %d idx %d %02x%02x%02x%02x%02x%02x%02x%02x", fd, cai, request, ca->parity, ca->index, ca->cw[0], ca->cw[1], ca->cw[2], ca->cw[3], ca->cw[4], ca->cw[5], ca->cw[6], ca->cw[7]);
+      if(ca->parity==0)
+        memcpy(&ca_info[cai][ca->index][EVEN_OFF],ca->cw,KEY_SIZE); // even key
+      else if(ca->parity==1)
+        memcpy(&ca_info[cai][ca->index][ODD_OFF],ca->cw,KEY_SIZE); // odd key
+      else
+        ERR("ca.so: Invalid parity %d in CA_SET_DESCR for ca id %d", ca->parity, cai);
+      sendcw(fd, ca_info[cai][ca->index]);
+      break;
+    case CA_SET_PID:
+      DBG(">>>>>>>> cactl CA_SET_PID fd %d cai %d req %d (%d %04x)", fd, cai, request, cpd->index, cpd->pid);
+      if (cpd->index >=0 && cpd->index < MAX_INDEX) { 
+        ca_info[cai][cpd->index][0] = (cpd->pid >> 0) & 0xff;
+                               ca_info[cai][cpd->index][1] = (cpd->pid >> 8) & 0xff;
+      } else if (cpd->index == -1) {
+        memset(&ca_info[cai], 0, sizeof(ca_info));
+      } else
+        ERR("ca.so: Invalid index %d in CA_SET_PID (%d) for ca id %d", cpd->index, MAX_INDEX, cai);
+      return 1;
+    case CA_RESET:
+      DBG(">>>>>>>> cactl CA_RESET cai %d", cai);
+      break;
+    case CA_GET_CAP:
+      DBG(">>>>>>>> cactl CA_GET_CAP cai %d", cai);
+      break;
+    case CA_GET_SLOT_INFO:
+      DBG(">>>>>>>> cactl CA_GET_SLOT_INFO cai %d", cai);
+      break;
+    default:
+      DBG(">>>>>>>> cactl unhandled req %d cai %d", request, cai);
+      //errno = EINVAL;
+      //return -1;
+  } // switch
+  return 0;
+} // cactl
+
+/* 
+    CPU Model
+    Brcm4380 V4.2  // DM8000
+    Brcm7401 V0.0  // DM800
+    MIPS 4KEc V4.8 // DM7025
+*/
+
+static const char *cpuinfo_file = "\
+system type             : ATI XILLEON HDTV SUPERTOLL\n\
+processor               : 0\n\
+cpu model               : Brcm4380 V4.2\n\
+BogoMIPS                : 297.98\n\
+wait instruction        : yes\n\
+microsecond timers      : yes\n\
+tlb_entries             : 16\n\
+extra interrupt vector  : yes\n\
+hardware watchpoint     : yes\n\
+VCED exceptions         : not available\n\
+VCEI exceptions         : not available\n\
+";
+
+int write_cpuinfo (void) {
+  static FILE* (*func) (const char *, const char *) = NULL;
+  func = (FILE* (*) (const char *, const char *)) dlsym (REAL_LIBC, "fopen");
+  FILE* file = func(CPUINFO_MAP, "w");
+  
+  
+  if(file == NULL) {
+     printf("error \"%s\" opening file\n", strerror(errno));
+     return -1;
+  }
+  int ret = fwrite(cpuinfo_file, strlen(cpuinfo_file), 1, file);
+  fclose(file);
+  return 0;
+}
+
+FILE *fopen(const char *path, const char *mode){
+  static FILE* (*func) (const char *, const char *) = NULL;
+  write_cpuinfo();
+  if (!func) func = (FILE* (*) (const char *, const char *)) dlsym (REAL_LIBC, "fopen");
+  if (!strcmp(path, CPUINFO_BASE)) {
+    INF("ca.so fopen %s mapped to %s", path, CPUINFO_MAP);
+    return (*func) (CPUINFO_MAP, mode);
+  } // if
+  DBG(">>>>>>>> fopen %s", path);
+  return (*func) (path, mode);
+} // fopen
+                                                 
+int open (const char *pathname, int flags, ...) {
+  static int (*func) (const char *, int, mode_t) = NULL;
+  if (!func) func = (int (*) (const char *, int, mode_t)) dlsym (REAL_LIBC, "open");
+  PROGINFO();
+  
+  va_list args;
+  mode_t mode;
+
+  va_start (args, flags);
+  mode = va_arg (args, mode_t);
+  va_end (args);
+
+  if(strstr(pathname, CA_BASE)) {
+    int cai=pathname[strlen(CA_BASE)]-'0';
+    if((cai >= 0) && (cai < MAX_CA)) {
+      DBG(">>>>>>>> open cafd[%d] flags %d %s (%d)", cai, flags, pathname, cafdc[cai]);
+      if(cafd[cai]==-1) {
+        cafd[cai] = socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
+        if(cafd[cai]==-1) {
+          ERR("Failed to open socket (%d)", errno);
+        } else {
+          struct sockaddr_in saddr;
+          fcntl(cafd[cai],F_SETFL,O_NONBLOCK);
+          bzero(&saddr,sizeof(saddr));
+          saddr.sin_family = AF_INET;
+          saddr.sin_port = htons(PORT);
+          saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
+          int r = connect(cafd[cai], (struct sockaddr *) &saddr, sizeof(saddr));
+          if (r<0) {
+            ERR("Failed to connect socket (%d)", errno);
+            close(cafd[cai]);
+            cafd[cai]=-1;
+          } // if
+        } // if
+      } // if
+      if(cafd[cai]!=-1) 
+        cafdc[cai]++;
+      else 
+        cafdc[cai] = 0;
+      return (cafd[cai]);
+    } // if      
+  } else if (strstr(pathname, DEMUX_BASE)) {
+    int cai=pathname[strlen(DEMUX_BASE)]-'0';
+    if((cai >= 0) && (cai < MAX_CA)) {
+      char dest[256];
+      sprintf(dest, DEMUX_MAP, cai);
+      DBG(">>>>>>>> open %s mapped to %s", pathname, dest);
+      return (*func) (dest, flags, mode);
+    } // if
+  } // if
+  DBG(">>>>>>>> open %s", pathname);
+  return (*func) (pathname, flags, mode);
+} // open
+
+int ioctl (int fd, int request, void *a) {
+  static int (*func) (int, int, void *) = NULL;
+  if (!func) func = (int (*) (int, int, void *)) dlsym (REAL_LIBC, "ioctl");
+  int i;
+  for(i=0;i<MAX_CA;i++)
+    if (fd == cafd[i])
+      return cactl (fd, i, request, a);
+  return (*func) (fd, request, a); 
+} // ioctl
+
+int close (int fd) {
+  static int (*func) (int) = NULL;
+  if (!func) func = (int (*) (int)) dlsym (REAL_LIBC, "close");
+  int i;
+  for(i=0;i<MAX_CA;i++) {
+    if (fd == cafd[i]) {
+      DBG(">>>>>>>> close cafd[%d] (%d)", i, cafdc[i]);
+      if(--cafdc[i]) return 0;
+      cafd[i] = -1;
+    } // if
+  } // for
+  return (*func) (fd);
+} // close
+
+#endif
+