From 62c97dac0713c3f7b80e38492d40dcaebbe49053 Mon Sep 17 00:00:00 2001 From: leslie Date: Wed, 10 Jun 2009 06:29:17 +0800 Subject: [PATCH] contrib: add CCcam ca.so pre-load library --- Makefile | 11 +- README.CCcam | 6 ++ contrib/Makefile | 27 +++++ contrib/cccam_ca.c | 261 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 302 insertions(+), 3 deletions(-) create mode 100644 contrib/Makefile create mode 100644 contrib/cccam_ca.c diff --git a/Makefile b/Makefile index 656e422..b2340f6 100644 --- 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 diff --git a/README.CCcam b/README.CCcam index 743b948..ee5c5d4 100644 --- a/README.CCcam +++ b/README.CCcam @@ -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 index 0000000..7184e47 --- /dev/null +++ b/contrib/Makefile @@ -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 index 0000000..4ce850d --- /dev/null +++ b/contrib/cccam_ca.c @@ -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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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>>>>>>> close cafd[%d] (%d)", i, cafdc[i]); + if(--cafdc[i]) return 0; + cafd[i] = -1; + } // if + } // for + return (*func) (fd); +} // close + +#endif + -- 2.39.5