Untitled
unknown
plain_text
3 years ago
33 kB
11
Indexable
diff --git a/CMakeLists.txt b/CMakeLists.txt
index dc19535..8d8fe7c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -684,7 +684,7 @@ if (CMAKE_COMPILER_IS_GNUCC)
list(GET GCC_VERSION_COMPONENTS 0 GCC_MAJOR)
list(GET GCC_VERSION_COMPONENTS 0 GCC_MINOR)
add_definitions ("-W -Wall ")
- set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O2")
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -pipe -ffunction-sections -fdata-sections -funroll-loops -fomit-frame-pointer -fno-schedule-insns")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -O2")
set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O0 -ggdb")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -O0 -ggdb")
diff --git a/Makefile b/Makefile
index 1c6c59f..dfdbc5a 100644
--- a/Makefile
+++ b/Makefile
@@ -58,7 +58,7 @@ override STD_DEFS += -D'CS_CONFDIR="$(CONF_DIR)"'
CC_WARN = -W -Wall -Wshadow -Wredundant-decls -Wstrict-prototypes -Wold-style-definition
# Compiler optimizations
-CC_OPTS = -O2 -ggdb -pipe -ffunction-sections -fdata-sections
+CC_OPTS = -O3 -ggdb -pipe -ffunction-sections -fdata-sections -funroll-loops -fomit-frame-pointer -fno-schedule-insns
CC = $(CROSS_DIR)$(CROSS)gcc
STRIP = $(CROSS_DIR)$(CROSS)strip
@@ -68,6 +68,8 @@ LDFLAGS = -Wl,--gc-sections
TARGETHELP := $(shell $(CC) --target-help 2>&1)
ifneq (,$(findstring sse2,$(TARGETHELP)))
override CFLAGS += -fexpensive-optimizations -mmmx -msse -msse2 -msse3
+else ifneq (,$(findstring neon,$(TARGETHELP)))
+override CFLAGS += -fexpensive-optimizations -mfpu=neon
else
override CFLAGS += -fexpensive-optimizations
endif
@@ -287,6 +289,7 @@ SRC-$(CONFIG_WITH_EMU) += module-emulator-director.c
SRC-$(CONFIG_WITH_EMU) += module-emulator-irdeto.c
SRC-$(CONFIG_WITH_EMU) += module-emulator-nagravision.c
SRC-$(CONFIG_WITH_EMU) += module-emulator-powervu.c
+SRC-$(CONFIG_WITH_EMU) += module-emulator-icam.c
SRC-$(CONFIG_WITH_EMU) += module-emulator-viaccess.c
SRC-$(CONFIG_WITH_EMU) += ffdecsa/ffdecsa.c
ifeq "$(CONFIG_WITH_EMU)" "y"
@@ -449,7 +452,7 @@ $(OBJDIR)/config.o: $(OBJDIR)/config.c
$(Q)$(CC) $(STD_DEFS) $(CC_OPTS) $(CC_WARN) $(CFLAGS) -c $< -o $@
$(OBJDIR)/%.o: %.c Makefile
- @$(CC) -MP -MM -MT $@ -o $(subst .o,.d,$@) $<
+ @$(CC) $(CFLAGS) -MP -MM -MT $@ -o $(subst .o,.d,$@) $<
$(SAY) "CC $<"
$(Q)$(CC) $(STD_DEFS) $(CC_OPTS) $(CC_WARN) $(CFLAGS) -c $< -o $@
diff --git a/config.h b/config.h
index 8995af7..567d1d5 100644
--- a/config.h
+++ b/config.h
@@ -3,11 +3,12 @@
#define WITH_EMU 1
#define WITH_SOFTCAM 1
+#define WITH_ARM_NEON 1
#define WEBIF 1
#define WEBIF_LIVELOG 1
#define WEBIF_JQUERY 1
//#define TOUCH 1
-//#define WITH_SSL 1
+#define WITH_SSL 1
#if defined(__linux__) || defined(__CYGWIN__)
#define HAVE_DVBAPI 1
#endif
@@ -33,7 +34,7 @@
#define MODULE_CCCAM 1
#define MODULE_CCCSHARE 1
#define MODULE_GBOX 1
-//#define MODULE_RADEGAST 1
+#define MODULE_RADEGAST 1
//#define MODULE_SERIAL 1
//#define MODULE_CONSTCW 1
//#define MODULE_PANDORA 1
diff --git a/config.sh b/config.sh
index fd5bb0f..8c3cf9a 100755
--- a/config.sh
+++ b/config.sh
@@ -1,6 +1,6 @@
#!/bin/sh
-addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI WITH_NEUTRINO READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CS_CACHEEX_AIO CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT WITH_EMU WITH_SOFTCAM"
+addons="WEBIF WEBIF_LIVELOG WEBIF_JQUERY TOUCH WITH_SSL HAVE_DVBAPI WITH_NEUTRINO READ_SDT_CHARSETS IRDETO_GUESSING CS_ANTICASC WITH_DEBUG MODULE_MONITOR WITH_LB CS_CACHEEX CS_CACHEEX_AIO CW_CYCLE_CHECK LCDSUPPORT LEDSUPPORT CLOCKFIX IPV6SUPPORT WITH_EMU WITH_SOFTCAM WITH_ARM_NEON"
protocols="MODULE_CAMD33 MODULE_CAMD35 MODULE_CAMD35_TCP MODULE_NEWCAMD MODULE_CCCAM MODULE_CCCSHARE MODULE_GBOX MODULE_RADEGAST MODULE_SCAM MODULE_SERIAL MODULE_CONSTCW MODULE_PANDORA MODULE_GHTTP"
readers="READER_NAGRA READER_NAGRA_MERLIN READER_IRDETO READER_CONAX READER_CRYPTOWORKS READER_SECA READER_VIACCESS READER_VIDEOGUARD READER_DRE READER_TONGFANG READER_BULCRYPT READER_GRIFFIN READER_DGCRYPT"
card_readers="CARDREADER_PHOENIX CARDREADER_INTERNAL CARDREADER_SC8IN1 CARDREADER_MP35 CARDREADER_SMARGO CARDREADER_DB2COM CARDREADER_STAPI CARDREADER_STAPI5 CARDREADER_STINGER CARDREADER_DRECAS"
@@ -28,6 +28,7 @@ CONFIG_WITH_LB=y
# CONFIG_IPV6SUPPORT=n
CONFIG_WITH_EMU=y
CONFIG_WITH_SOFTCAM=y
+CONFIG_WITH_ARM_NEON=y
# CONFIG_MODULE_CAMD33=n
CONFIG_MODULE_CAMD35=y
CONFIG_MODULE_CAMD35_TCP=y
@@ -475,6 +476,7 @@ menu_addons() {
IPV6SUPPORT "IPv6 support (experimental)" $(check_test "IPV6SUPPORT") \
WITH_EMU "Emulator support" $(check_test "WITH_EMU") \
WITH_SOFTCAM "Built-in SoftCam.Key" $(check_test "WITH_SOFTCAM") \
+ WITH_ARM_NEON "ARM Neon Support" $(check_test "WITH_ARM_NEON") \
2> ${tempfile}
opt=${?}
diff --git a/ffdecsa/CMakeLists.txt b/ffdecsa/CMakeLists.txt
index d5be555..a703e5a 100644
--- a/ffdecsa/CMakeLists.txt
+++ b/ffdecsa/CMakeLists.txt
@@ -5,4 +5,15 @@ file (GLOB ffdecsa_hdrs "*.h")
set (lib_name "ffdecsa")
+if (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -msse -msse2 -msse3")
+elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "(arm)|(ARM)")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon")
+ set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -mfpu=neon")
+endif (CMAKE_SYSTEM_PROCESSOR MATCHES "(x86)|(X86)|(amd64)|(AMD64)")
+
+if (CMAKE_COMPILER_IS_GNUCC)
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -O3 -pipe -ffunction-sections -fdata-sections -funroll-loops -fomit-frame-pointer -fno-schedule-insns")
+endif (CMAKE_COMPILER_IS_GNUCC)
+
add_library (${lib_name} STATIC ${ffdecsa_srcs} ${ffdecsa_hdrs})
diff --git a/ffdecsa/ffdecsa.c b/ffdecsa/ffdecsa.c
index 2c7169a..ca6d109 100644
--- a/ffdecsa/ffdecsa.c
+++ b/ffdecsa/ffdecsa.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include "ffdecsa.h"
+#include "../config.h"
#ifndef NULL
#define NULL 0
@@ -53,6 +54,7 @@
#define PARALLEL_128_2MMX 1284
#define PARALLEL_128_SSE 1285
#define PARALLEL_128_SSE2 1286
+#define PARALLEL_128_NEON 1287
//////// our choice //////////////// our choice //////////////// our choice //////////////// our choice ////////
#ifndef PARALLEL_MODE
@@ -61,13 +63,21 @@
#define PARALLEL_MODE PARALLEL_128_SSE2
#elif defined(__mips__) || defined(__mips) || defined(__MIPS__)
-#define PARALLEL_MODE PARALLEL_64_LONG
+//#define PARALLEL_MODE PARALLEL_64_LONG
+#define PARALLEL_MODE PARALLEL_32_INT
#elif defined(__sh__) || defined(__SH4__)
#define PARALLEL_MODE PARALLEL_32_INT
#define COPY_UNALIGNED_PKT
#define MEMALIGN_VAL 4
+#elif defined(__arm__)
+#ifdef WITH_ARM_NEON
+#define PARALLEL_MODE PARALLEL_128_NEON
+#else
+#define PARALLEL_MODE PARALLEL_32_INT
+#endif
+
#else
#define PARALLEL_MODE PARALLEL_32_INT
#endif
@@ -107,6 +117,8 @@
#include "parallel_128_sse.h"
#elif PARALLEL_MODE==PARALLEL_128_SSE2
#include "parallel_128_sse2.h"
+#elif PARALLEL_MODE==PARALLEL_128_NEON
+#include "parallel_128_neon.h"
#else
#error "unknown/undefined parallel mode"
#endif
@@ -278,6 +290,96 @@ static void key_schedule_block(
}
+static void key_schedule_block_ecm(
+ unsigned char *ck, // [In] ck[0]-ck[7] 8 bytes | Key.
+ unsigned char *kk, // [Out] kk[0]-kk[55] 56 bytes | Key schedule.
+ unsigned char ecm) // ecm
+{
+ static const unsigned char key_perm[0x40] = {
+ 0x12,0x24,0x09,0x07,0x2A,0x31,0x1D,0x15, 0x1C,0x36,0x3E,0x32,0x13,0x21,0x3B,0x40,
+ 0x18,0x14,0x25,0x27,0x02,0x35,0x1B,0x01, 0x22,0x04,0x0D,0x0E,0x39,0x28,0x1A,0x29,
+ 0x33,0x23,0x34,0x0C,0x16,0x30,0x1E,0x3A, 0x2D,0x1F,0x08,0x19,0x17,0x2F,0x3D,0x11,
+ 0x3C,0x05,0x38,0x2B,0x0B,0x06,0x0A,0x2C, 0x20,0x3F,0x2E,0x0F,0x03,0x26,0x10,0x37,
+ };
+
+ static const unsigned char ecm_perm[0x100] = {
+ 0x00,0x02,0x80,0x82,0x20,0x22,0xa0,0xa2, 0x04,0x06,0x84,0x86,0x24,0x26,0xa4,0xa6,
+ 0x40,0x42,0xc0,0xc2,0x60,0x62,0xe0,0xe2, 0x44,0x46,0xc4,0xc6,0x64,0x66,0xe4,0xe6,
+ 0x01,0x03,0x81,0x83,0x21,0x23,0xa1,0xa3, 0x05,0x07,0x85,0x87,0x25,0x27,0xa5,0xa7,
+ 0x41,0x43,0xc1,0xc3,0x61,0x63,0xe1,0xe3, 0x45,0x47,0xc5,0xc7,0x65,0x67,0xe5,0xe7,
+ 0x08,0x0a,0x88,0x8a,0x28,0x2a,0xa8,0xaa, 0x0c,0x0e,0x8c,0x8e,0x2c,0x2e,0xac,0xae,
+ 0x48,0x4a,0xc8,0xca,0x68,0x6a,0xe8,0xea, 0x4c,0x4e,0xcc,0xce,0x6c,0x6e,0xec,0xee,
+ 0x09,0x0b,0x89,0x8b,0x29,0x2b,0xa9,0xab, 0x0d,0x0f,0x8d,0x8f,0x2d,0x2f,0xad,0xaf,
+ 0x49,0x4b,0xc9,0xcb,0x69,0x6b,0xe9,0xeb, 0x4d,0x4f,0xcd,0xcf,0x6d,0x6f,0xed,0xef,
+ 0x10,0x12,0x90,0x92,0x30,0x32,0xb0,0xb2, 0x14,0x16,0x94,0x96,0x34,0x36,0xb4,0xb6,
+ 0x50,0x52,0xd0,0xd2,0x70,0x72,0xf0,0xf2, 0x54,0x56,0xd4,0xd6,0x74,0x76,0xf4,0xf6,
+ 0x11,0x13,0x91,0x93,0x31,0x33,0xb1,0xb3, 0x15,0x17,0x95,0x97,0x35,0x37,0xb5,0xb7,
+ 0x51,0x53,0xd1,0xd3,0x71,0x73,0xf1,0xf3, 0x55,0x57,0xd5,0xd7,0x75,0x77,0xf5,0xf7,
+ 0x18,0x1a,0x98,0x9a,0x38,0x3a,0xb8,0xba, 0x1c,0x1e,0x9c,0x9e,0x3c,0x3e,0xbc,0xbe,
+ 0x58,0x5a,0xd8,0xda,0x78,0x7a,0xf8,0xfa, 0x5c,0x5e,0xdc,0xde,0x7c,0x7e,0xfc,0xfe,
+ 0x19,0x1b,0x99,0x9b,0x39,0x3b,0xb9,0xbb, 0x1d,0x1f,0x9d,0x9f,0x3d,0x3f,0xbd,0xbf,
+ 0x59,0x5b,0xd9,0xdb,0x79,0x7b,0xf9,0xfb, 0x5d,0x5f,0xdd,0xdf,0x7d,0x7f,0xfd,0xff
+ };
+
+ int i,j,k;
+ int bit[64];
+ int newbit[64];
+ int kb[7][8];
+
+ // 56 steps
+ // 56 key bytes kk(55)..kk(0) by key schedule from ck
+
+ // kb(6,0) .. kb(6,7) = ck(0) .. ck(7)
+ if (ecm == 4)
+ {
+ kb[6][0] = ecm_perm[ck[0]];
+ kb[6][1] = ck[1];
+ kb[6][2] = ck[2];
+ kb[6][3] = ck[3];
+ kb[6][4] = ecm_perm[ck[4]];
+ kb[6][5] = ck[5];
+ kb[6][6] = ck[6];
+ kb[6][7] = ck[7];
+ }
+ else
+ {
+ kb[6][0] = ck[0];
+ kb[6][1] = ck[1];
+ kb[6][2] = ck[2];
+ kb[6][3] = ck[3];
+ kb[6][4] = ck[4];
+ kb[6][5] = ck[5];
+ kb[6][6] = ck[6];
+ kb[6][7] = ck[7];
+ }
+
+
+ // calculate kb[5] .. kb[0]
+ for(i=5; i>=0; i--){
+ // 64 bit perm on kb
+ for(j=0; j<8; j++){
+ for(k=0; k<8; k++){
+ bit[j*8+k] = (kb[i+1][j] >> (7-k)) & 1;
+ newbit[key_perm[j*8+k]-1] = bit[j*8+k];
+ }
+ }
+ for(j=0; j<8; j++){
+ kb[i][j] = 0;
+ for(k=0; k<8; k++){
+ kb[i][j] |= newbit[j*8+k] << (7-k);
+ }
+ }
+ }
+
+ // xor to give kk
+ for(i=0; i<7; i++){
+ for(j=0; j<8; j++){
+ kk[i*8+j] = kb[i][j] ^ i;
+ }
+ }
+
+}
+
//-----block utils
static inline __attribute__((always_inline)) void trasp_N_8 (unsigned char *in,unsigned char* out,int count){
@@ -395,7 +497,7 @@ static void block_decypher_group(
roff=GROUP_PARALLELISM*56;
-#define FASTTRASP1
+//#define FASTTRASP1
#ifndef FASTTRASP1
for(g=0;g<count;g++){
// Init registers
@@ -476,7 +578,7 @@ static void block_decypher_group(
#endif
}
-#define FASTTRASP2
+//#define FASTTRASP2
#ifndef FASTTRASP2
for(g=0;g<count;g++){
// Copy results
@@ -552,6 +654,34 @@ static void schedule_key(struct csa_key_t *key, const unsigned char *pk){
}
}
+static void schedule_key_ecm(struct csa_key_t *key, const unsigned char *pk, const unsigned char ecm){
+ // could be made faster, but is not run often
+ int bi,by;
+ int i,j;
+// key
+ memcpy(key->ck,pk,8);
+// precalculations for stream
+ key_schedule_stream(key->ck,key->iA,key->iB);
+ for(by=0;by<8;by++){
+ for(bi=0;bi<8;bi++){
+ key->ck_g[by][bi]=(key->ck[by]&(1<<bi))?FF1():FF0();
+ }
+ }
+ for(by=0;by<8;by++){
+ for(bi=0;bi<4;bi++){
+ key->iA_g[by][bi]=(key->iA[by]&(1<<bi))?FF1():FF0();
+ key->iB_g[by][bi]=(key->iB[by]&(1<<bi))?FF1():FF0();
+ }
+ }
+// precalculations for block
+ key_schedule_block_ecm(key->ck,key->kk,ecm);
+ for(i=0;i<56;i++){
+ for(j=0;j<BYTES_PER_BATCH;j++){
+ *(((unsigned char *)&key->kkmulti[i])+j)=key->kk[i];
+ }
+ }
+}
+
void set_control_words(void *keys, const unsigned char *ev, const unsigned char *od){
schedule_key(&((struct csa_keys_t *)keys)->even,ev);
schedule_key(&((struct csa_keys_t *)keys)->odd,od);
@@ -561,10 +691,18 @@ void set_even_control_word(void *keys, const unsigned char *pk){
schedule_key(&((struct csa_keys_t *)keys)->even,pk);
}
+void set_even_control_word_ecm(void *keys, const unsigned char *pk, const unsigned char ecm){
+ schedule_key_ecm(&((struct csa_keys_t *)keys)->even,pk,ecm);
+}
+
void set_odd_control_word(void *keys, const unsigned char *pk){
schedule_key(&((struct csa_keys_t *)keys)->odd,pk);
}
+void set_odd_control_word_ecm(void *keys, const unsigned char *pk, const unsigned char ecm){
+ schedule_key_ecm(&((struct csa_keys_t *)keys)->odd,pk,ecm);
+}
+
//-----get control words
void get_control_words(void *keys, unsigned char *even, unsigned char *odd){
diff --git a/ffdecsa/ffdecsa.h b/ffdecsa/ffdecsa.h
index 1be08e7..d37c606 100644
--- a/ffdecsa/ffdecsa.h
+++ b/ffdecsa/ffdecsa.h
@@ -47,9 +47,11 @@ void set_control_words(void *keys, const unsigned char *even, const unsigned cha
// -- set even control word, 8 bytes
void set_even_control_word(void *keys, const unsigned char *even);
+void set_even_control_word_ecm(void *keys, const unsigned char *even, const unsigned char ecm);
// -- set odd control word, 8 bytes
void set_odd_control_word(void *keys, const unsigned char *odd);
+void set_odd_control_word_ecm(void *keys, const unsigned char *odd, const unsigned char ecm);
// -- get control words, 8 bytes each
//void get_control_words(void *keys, unsigned char *even, unsigned char *odd);
diff --git a/ffdecsa/parallel_128_neon.h b/ffdecsa/parallel_128_neon.h
new file mode 100644
index 0000000..0265123
--- /dev/null
+++ b/ffdecsa/parallel_128_neon.h
@@ -0,0 +1,81 @@
+/* FFdecsa -- fast decsa algorithm
+ *
+ * Copyright (C) 2007 Dark Avenger
+ * 2003-2004 fatih89r
+ *
+ * This program 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 program 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+# include <arm_neon.h>
+
+#define MEMALIGN_VAL 16
+
+union __u128i {
+ unsigned int u[4];
+ uint64x2_t v;
+};
+
+static const union __u128i ff0 = {{0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}};
+static const union __u128i ff1 = {{0xffffffffU, 0xffffffffU, 0xffffffffU, 0xffffffffU}};
+
+typedef uint64x2_t group;
+#define GROUP_PARALLELISM 128
+#define FF0() ff0.v
+#define FF1() ff1.v
+#define FFAND(a,b) vandq_u64((a),(b))
+#define FFOR(a,b) vorrq_u64((a),(b))
+#define FFXOR(a,b) veorq_u64((a),(b))
+#define FFNOT(a) vreinterpretq_u64_u8(vmvnq_u8(vreinterpretq_u8_u64(a)))
+
+
+/* BATCH */
+
+static const union __u128i ff29 = {{0x29292929U, 0x29292929U, 0x29292929U, 0x29292929U}};
+static const union __u128i ff02 = {{0x02020202U, 0x02020202U, 0x02020202U, 0x02020202U}};
+static const union __u128i ff04 = {{0x04040404U, 0x04040404U, 0x04040404U, 0x04040404U}};
+static const union __u128i ff10 = {{0x10101010U, 0x10101010U, 0x10101010U, 0x10101010U}};
+static const union __u128i ff40 = {{0x40404040U, 0x40404040U, 0x40404040U, 0x40404040U}};
+static const union __u128i ff80 = {{0x80808080U, 0x80808080U, 0x80808080U, 0x80808080U}};
+
+typedef uint64x2_t batch;
+#define BYTES_PER_BATCH 16
+#define B_FFN_ALL_29() ff29.v
+#define B_FFN_ALL_02() ff02.v
+#define B_FFN_ALL_04() ff04.v
+#define B_FFN_ALL_10() ff10.v
+#define B_FFN_ALL_40() ff40.v
+#define B_FFN_ALL_80() ff80.v
+
+#define B_FFAND(a,b) FFAND(a,b)
+#define B_FFOR(a,b) FFOR(a,b)
+#define B_FFXOR(a,b) FFXOR(a,b)
+#define B_FFSH8L(a,n) vshlq_n_u64((a),(n))
+#define B_FFSH8R(a,n) vshrq_n_u64((a),(n))
+
+#define M_EMPTY()
+
+#undef BEST_SPAN
+#define BEST_SPAN 16
+
+#undef XOR_BEST_BY
+inline static void XOR_BEST_BY(unsigned char *d, unsigned char *s1, unsigned char *s2)
+{
+ uint64x2_t vs1 = vld1q_u64((uint64_t*)s1);
+ uint64x2_t vs2 = vld1q_u64((uint64_t*)s2);
+ vs1 = veorq_u64(vs1, vs2);
+ vst1q_u64((uint64_t*)d, vs1);
+}
+
+#include "fftable.h"
diff --git a/module-dvbapi.c b/module-dvbapi.c
index 118a1e5..81ad127 100644
--- a/module-dvbapi.c
+++ b/module-dvbapi.c
@@ -11,6 +11,7 @@
#include "module-dvbapi-coolapi.h"
#include "module-dvbapi-stapi.h"
#include "module-dvbapi-chancache.h"
+#include "module-emulator-streamserver.h"
#include "module-stat.h"
#include "oscam-chk.h"
#include "oscam-client.h"
@@ -7847,7 +7848,13 @@ void dvbapi_send_dcw(struct s_client *client, ECM_REQUEST *er)
delayer(er, delay);
#ifdef WITH_EMU
- if(!chk_ctab_ex(er->caid, &cfg.emu_stream_relay_ctab) || !cfg.emu_stream_relay_enabled)
+ bool set_dvbapi_cw = true;
+ if(chk_ctab_ex(er->caid, &cfg.emu_stream_relay_ctab) && cfg.emu_stream_relay_enabled)
+ {
+ // streamserver set cw
+ set_dvbapi_cw = !stream_write_cw(er);
+ }
+ if (set_dvbapi_cw)
#endif
switch(selected_api)
{
diff --git a/module-emulator-icam.c b/module-emulator-icam.c
new file mode 100644
index 0000000..aae20c7
--- /dev/null
+++ b/module-emulator-icam.c
@@ -0,0 +1,153 @@
+#define MODULE_LOG_PREFIX "emu"
+
+#include "globals.h"
+#include "oscam-net.h"
+#include "oscam-chk.h"
+#include "module-emulator-icam.h"
+#include "oscam-ecm.h"
+#include "oscam-client.h"
+#include "ffdecsa/ffdecsa.h"
+
+#ifdef WITH_EMU
+
+
+#ifdef MODULE_RADEGAST
+static int32_t gRadegastFd = 0;
+static uint8_t gLast_ecm_paket[EMU_STREAM_SERVER_MAX_CONNECTIONS][8];
+#endif
+
+
+bool caid_is_icam(uint16_t caid)
+{
+ if (caid == 0x098C || caid == 0x098D || caid == 0x09C4)
+ return true;
+ return false;
+}
+
+
+void icam_write_cw(ECM_REQUEST *er, int32_t connid)
+{
+ SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[connid]);
+
+ if (emu_fixed_key_data[connid].icam_csa_ks == NULL)
+ {
+ emu_fixed_key_data[connid].icam_csa_ks = get_key_struct();
+ }
+
+ bool icam = (er->ecm[2] - er->ecm[4]) == 4;
+ if (er->ecm[0] == 0x80)
+ {
+ if (icam)
+ {
+ set_even_control_word_ecm(emu_fixed_key_data[connid].icam_csa_ks, er->cw, er->ecm[0x15]);
+ }
+ else
+ {
+ set_even_control_word(emu_fixed_key_data[connid].icam_csa_ks, er->cw);
+ }
+ }
+ else if (icam)
+ {
+ set_odd_control_word_ecm(emu_fixed_key_data[connid].icam_csa_ks, er->cw + 8, er->ecm[0x15]);
+ }
+ else
+ {
+ set_odd_control_word(emu_fixed_key_data[connid].icam_csa_ks, er->cw + 8);
+ }
+
+ emu_fixed_key_data[connid].icam_csa_used = 1;
+
+ SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[connid]);
+}
+
+#ifdef MODULE_RADEGAST
+void icam_ecm(emu_stream_client_data *cdata)
+{
+ uint16_t section_length = SCT_LEN(cdata->ecm_data);
+ uint16_t packet_len;
+ static uint8_t header_len = 2;
+ static uint8_t payload_static_len = 12;
+
+ if (memcmp(gLast_ecm_paket[cdata->connid], cdata->ecm_data, 8) != 0)
+ {
+ memcpy(gLast_ecm_paket[cdata->connid], cdata->ecm_data, 8);
+
+ if (gRadegastFd <= 0)
+ icam_connect_to_radegast();
+
+ packet_len = header_len + payload_static_len + section_length;
+ uint8_t outgoing_data[packet_len];
+ outgoing_data[0] = 1;
+ outgoing_data[1] = payload_static_len + section_length;
+ outgoing_data[2] = 10; // caid
+ outgoing_data[3] = 2;
+ outgoing_data[4] = cdata->caid >> 8;
+ outgoing_data[5] = cdata->caid & 0xFF;
+ outgoing_data[6] = 9; // srvid
+ outgoing_data[7] = 4;
+ outgoing_data[8] = cdata->srvid & 0xFF;
+ outgoing_data[10] = cdata->srvid >> 8;
+ outgoing_data[12] = 3;
+ outgoing_data[13] = section_length;
+
+ memcpy(outgoing_data + header_len + payload_static_len, cdata->ecm_data, section_length);
+
+ if (!icam_send_to_radegast(outgoing_data, packet_len))
+ {
+ icam_close_radegast_connection();
+ if (icam_connect_to_radegast())
+ {
+ icam_send_to_radegast(outgoing_data, packet_len);
+ }
+ }
+ }
+}
+
+bool icam_connect_to_radegast(void)
+{
+ struct sockaddr_in cservaddr;
+
+ if (gRadegastFd == 0)
+ gRadegastFd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (gRadegastFd < 0)
+ {
+ gRadegastFd = 0;
+ return false;
+ }
+
+ int32_t flags = fcntl(gRadegastFd, F_GETFL);
+ fcntl(gRadegastFd, F_SETFL, flags | O_NONBLOCK);
+
+ bzero(&cservaddr, sizeof(cservaddr));
+ cservaddr.sin_family = AF_INET;
+ SIN_GET_ADDR(cservaddr) = cfg.rad_srvip;
+ cservaddr.sin_port = htons(cfg.rad_port);
+
+ connect(gRadegastFd,(struct sockaddr *)&cservaddr, sizeof(cservaddr));
+ return true;
+}
+
+void icam_reset(int32_t connid)
+{
+ memset(gLast_ecm_paket[connid], 0, 8);
+}
+
+void icam_close_radegast_connection(void)
+{
+ close(gRadegastFd);
+ gRadegastFd = 0;
+}
+
+bool icam_send_to_radegast(uint8_t* data, int len)
+{
+ if (send(gRadegastFd, data, len, 0) < 0)
+ {
+ cs_log("icam_send_to_radegast: Send failure");
+ return false;
+ }
+ return true;
+}
+#endif // MODULE_RADEGAST
+
+#endif // WITH_EMU
diff --git a/module-emulator-icam.h b/module-emulator-icam.h
new file mode 100644
index 0000000..3ecc782
--- /dev/null
+++ b/module-emulator-icam.h
@@ -0,0 +1,21 @@
+#ifndef MODULE_EMULATOR_ICAM_H
+#define MODULE_EMULATOR_ICAM_H
+
+#ifdef WITH_EMU
+
+#include "module-emulator-streamserver.h"
+
+bool caid_is_icam(uint16_t caid);
+void icam_write_cw(ECM_REQUEST *er, int32_t connid);
+
+#ifdef MODULE_RADEGAST
+void icam_ecm(emu_stream_client_data *cdata);
+bool icam_connect_to_radegast(void);
+void icam_close_radegast_connection(void);
+void icam_reset(int32_t connid);
+bool icam_send_to_radegast(uint8_t* data, int len);
+#endif // MODULE_RADEGAST
+
+#endif // WITH_EMU
+
+#endif // MODULE_EMULATOR_ICAM_H
diff --git a/module-emulator-streamserver.c b/module-emulator-streamserver.c
index a828a4f..e32c244 100644
--- a/module-emulator-streamserver.c
+++ b/module-emulator-streamserver.c
@@ -9,6 +9,7 @@
#include "module-emulator-osemu.h"
#include "module-emulator-streamserver.h"
#include "module-emulator-powervu.h"
+#include "module-emulator-icam.h"
#include "oscam-config.h"
#include "oscam-net.h"
#include "oscam-string.h"
@@ -378,7 +379,7 @@ static void ParsePmtData(emu_stream_client_data *cdata)
{
caid = b2i(2, data + i + 2);
- if (caid_is_powervu(caid) || caid == 0xA101) // add all supported caids here
+ if (chk_ctab_ex(caid, &cfg.emu_stream_relay_ctab) && (caid_is_powervu(caid) || caid == 0xA101 || caid_is_icam(caid))) // add all supported caids here
{
if (cdata->caid == NO_CAID_VALUE)
{
@@ -537,6 +538,12 @@ static void ParseEcmData(emu_stream_client_data *cdata)
powervu_ecm(data, dcw, NULL, cdata->srvid, cdata->caid, cdata->tsid, cdata->onid, cdata->ens, &cdata->key);
}
}
+#ifdef MODULE_RADEGAST
+ else if (caid_is_icam(cdata->caid))
+ {
+ icam_ecm(cdata);
+ }
+#endif // MODULE_RADEGAST
//else if () // All other caids
//{
//emu_process_ecm();
@@ -1230,6 +1237,84 @@ static void DescrambleTsPacketsCompel(emu_stream_client_data *data, uint8_t *str
}
}
+static void DescrambleTsPacketsICam(emu_stream_client_data *data, uint8_t *stream_buf, uint32_t bufLength, uint16_t packetSize)
+{
+ uint8_t *packetCluster[4];
+ uint8_t scrambled_packets = 0, scramblingControl;
+ uint32_t i, tsHeader;
+ int8_t odd_even = -1, odd_even_count = 1;
+
+ for (i = 0; i < bufLength; i += packetSize)
+ {
+ tsHeader = b2i(4, stream_buf + i);
+ scramblingControl = (tsHeader & 0xC0) >> 6;
+
+#ifdef MODULE_RADEGAST
+ uint16_t pid, offset, payloadStart;
+
+ pid = (tsHeader & 0x1FFF00) >> 8;
+ payloadStart = (tsHeader & 0x400000) >> 22;
+
+ if (tsHeader & 0x20)
+ {
+ offset = 4 + stream_buf[i + 4] + 1;
+ }
+ else
+ {
+ offset = 4;
+ }
+
+ if (data->ecm_pid && pid == data->ecm_pid) // Process the ECM data
+ {
+ stream_server_has_ecm[data->connid] = 1;
+ data->key.icam_csa_used = emu_fixed_key_data[data->connid].icam_csa_used;
+
+ ParseTsData(0x80, 0xFE, 3, &data->have_ecm_data, data->ecm_data, sizeof(data->ecm_data),
+ &data->ecm_data_pos, payloadStart, stream_buf + i + offset, packetSize - offset, ParseEcmData, data);
+ }
+#endif // MODULE_RADEGAST
+
+ if (scramblingControl == 0)
+ {
+ continue;
+ }
+
+ scrambled_packets++;
+ scramblingControl &= 0x1;
+
+ if (odd_even == -1)
+ {
+ odd_even = scramblingControl;
+ }
+
+ if (odd_even != scramblingControl)
+ {
+ odd_even_count++;
+ odd_even = scramblingControl;
+ }
+ }
+
+ if (scrambled_packets == 0)
+ return;
+
+ SAFE_MUTEX_LOCK(&emu_fixed_key_data_mutex[data->connid]);
+
+ if (emu_fixed_key_data[data->connid].icam_csa_used && emu_fixed_key_data[data->connid].icam_csa_ks != NULL)
+ {
+ packetCluster[0] = stream_buf;
+ packetCluster[1] = stream_buf + bufLength;
+ packetCluster[2] = NULL;
+
+ decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
+ if (odd_even_count > 1) // odd and even packets together cannot be decrypted in one step
+ {
+ decrypt_packets(emu_fixed_key_data[data->connid].icam_csa_ks, packetCluster);
+ }
+ }
+
+ SAFE_MUTEX_UNLOCK(&emu_fixed_key_data_mutex[data->connid]);
+}
+
static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *stream_path)
{
struct sockaddr_in cservaddr;
@@ -1241,15 +1326,6 @@ static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *str
return -1;
}
- struct timeval tv;
- tv.tv_sec = 2;
- tv.tv_usec = 0;
- if (setsockopt(streamfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof tv))
- {
- cs_log("ERROR: setsockopt() failed for SO_RCVTIMEO");
- return -1;
- }
-
bzero(&cservaddr, sizeof(cservaddr));
cservaddr.sin_family = AF_INET;
cs_resolve(emu_stream_source_host, &in_addr, NULL, NULL);
@@ -1284,6 +1360,8 @@ static int32_t connect_to_stream(char *http_buf, int32_t http_buf_len, char *str
return -1;
}
+ fcntl(streamfd, F_SETFL, fcntl(streamfd, F_GETFL) | O_NONBLOCK);
+
return streamfd;
}
@@ -1332,6 +1410,9 @@ static void *stream_client_handler(void *arg)
uint16_t packetCount = 0, packetSize = 0, startOffset = 0;
uint32_t remainingDataPos, remainingDataLength, tmp_pids[4];
+ struct pollfd pfd[2];
+ int ret;
+
cs_log("Stream client %i connected", conndata->connid);
if (!cs_malloc(&http_buf, 1024))
@@ -1454,35 +1535,55 @@ static void *stream_client_handler(void *arg)
cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_CSA;
cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_CSA;
}
+ else if (emu_fixed_key_data[conndata->connid].icam_csa_used)
+ {
+ cur_dvb_buffer_size = 188 * cluster_size;
+ cur_dvb_buffer_wait = 188 * (cluster_size - 3);
+ }
else
{
cur_dvb_buffer_size = EMU_DVB_BUFFER_SIZE_DES;
cur_dvb_buffer_wait = EMU_DVB_BUFFER_WAIT_DES;
}
- streamStatus = recv(streamfd, stream_buf + bytesRead, cur_dvb_buffer_size - bytesRead, MSG_WAITALL);
- if (streamStatus == 0) // socket closed
+ pfd[0].fd = streamfd;
+ pfd[0].events = POLLIN | POLLRDHUP | POLLHUP;
+ pfd[1].fd = conndata->connfd;
+ pfd[1].events = POLLRDHUP | POLLHUP;
+
+ ret = poll(pfd, 2, 2000);
+
+ if (ret < 0) // poll error
{
- cs_log("WARNING: stream client %i - stream source closed connection", conndata->connid);
+ cs_log("WARNING: stream client %i error receiving data from stream source", conndata->connid);
streamConnectErrorCount++;
cs_sleepms(100);
break;
}
-
- if (streamStatus < 0) // error
+ else if (ret == 0) // timeout
+ {
+ cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
+ streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
+ continue;
+ }
+ else
{
- if ((errno == EWOULDBLOCK) | (errno == EAGAIN))
+ if (pfd[0].revents & POLLIN) // new incoming data
{
- cs_log("WARNING: stream client %i no data from stream source", conndata->connid);
- streamDataErrorCount++; // 2 sec timeout * 15 = 30 seconds no data -> close
+ streamStatus = recv(streamfd, stream_buf + bytesRead, cur_dvb_buffer_size - bytesRead, MSG_DONTWAIT);
+ }
+ if ((pfd[0].revents & POLLHUP) || (pfd[0].revents & POLLRDHUP)) // incoming connection closed
+ {
+ cs_log("WARNING: stream client %i - stream source closed connection", conndata->connid);
+ streamConnectErrorCount++;
cs_sleepms(100);
- continue;
+ break;
+ }
+ if ((pfd[1].revents & POLLHUP) || (pfd[1].revents & POLLRDHUP)) // outgoing connection was closed -> e.g. user zapped to other channel
+ {
+ clientStatus = -1;
+ break;
}
-
- cs_log("WARNING: stream client %i error receiving data from stream source", conndata->connid);
- streamConnectErrorCount++;
- cs_sleepms(100);
- break;
}
if (streamStatus < cur_dvb_buffer_size - bytesRead) // probably just received header but no stream
@@ -1546,6 +1647,10 @@ static void *stream_client_handler(void *arg)
{
DescrambleTsPacketsCompel(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
}
+ else if (caid_is_icam(data->caid)) //ICAM
+ {
+ DescrambleTsPacketsICam(data, stream_buf + startOffset, packetCount * packetSize, packetSize);
+ }
}
else
{
@@ -1590,6 +1695,13 @@ static void *stream_client_handler(void *arg)
free_key_struct(data->key.pvu_csa_ks[i]);
}
}
+ if (data->key.icam_csa_ks)
+ {
+ free_key_struct(data->key.icam_csa_ks);
+ }
+#ifdef MODULE_RADEGAST
+ icam_reset(data->connid);
+#endif
NULLFREE(data);
stream_client_disconnect(conndata);
@@ -1805,8 +1917,35 @@ void stop_stream_server(void)
gconncount = 0;
SAFE_MUTEX_UNLOCK(&emu_stream_server_mutex);
+#ifdef MODULE_RADEGAST
+ icam_close_radegast_connection();
+#endif
+
shutdown(glistenfd, 2);
close(glistenfd);
}
+bool stream_write_cw(ECM_REQUEST *er)
+{
+ int32_t i;
+
+ if (caid_is_icam(er->caid))
+ {
+ bool cw_written = false;
+ //SAFE_MUTEX_LOCK(&emu_fixed_key_srvid_mutex);
+ for (i = 0; i < EMU_STREAM_SERVER_MAX_CONNECTIONS; i++)
+ {
+ if (emu_stream_cur_srvid[i] == er->srvid)
+ {
+ icam_write_cw(er, i);
+ cw_written = true;
+ // don't return as there might be more connections which for the same channel (recording)
+ }
+ }
+ //SAFE_MUTEX_UNLOCK(&emu_fixed_key_srvid_mutex);
+ return cw_written;
+ }
+ return true;
+}
+
#endif // WITH_EMU
diff --git a/module-emulator-streamserver.h b/module-emulator-streamserver.h
index 2b1c2ac..5b76d0d 100644
--- a/module-emulator-streamserver.h
+++ b/module-emulator-streamserver.h
@@ -18,6 +18,8 @@ typedef struct
uint32_t pvu_des_ks[8][2][32];
int8_t pvu_csa_used;
void* pvu_csa_ks[8];
+ int8_t icam_csa_used;
+ uint32_t* icam_csa_ks;
} emu_stream_client_key_data;
typedef struct
@@ -84,6 +86,7 @@ extern emu_stream_client_key_data emu_fixed_key_data[EMU_STREAM_SERVER_MAX_CONNE
extern LLIST *ll_emu_stream_delayed_keys[EMU_STREAM_SERVER_MAX_CONNECTIONS];
void *stream_key_delayer(void *arg);
+bool stream_write_cw(ECM_REQUEST *er);
#endif // WITH_EMU
diff --git a/module-radegast.c b/module-radegast.c
index b514203..5b07d2d 100644
--- a/module-radegast.c
+++ b/module-radegast.c
@@ -7,6 +7,8 @@
#include "oscam-net.h"
#include "oscam-string.h"
#include "oscam-reader.h"
+#include "module-emulator-streamserver.h"
+#include "oscam-chk.h"
static int32_t radegast_connect(void);
@@ -86,6 +88,9 @@ static void radegast_send_dcw(struct s_client *client, ECM_REQUEST *er)
mbuf[0] = 0x02; // DCW
if(er->rc < E_NOTFOUND)
{
+ if(chk_ctab_ex(er->caid, &cfg.emu_stream_relay_ctab) && cfg.emu_stream_relay_enabled)
+ stream_write_cw(er);
+
mbuf[1] = 0x12; // len (overall)
mbuf[2] = 0x05; // ACCESS
mbuf[3] = 0x10; // len
diff --git a/oscam.c b/oscam.c
index d014cd1..f948b69 100644
--- a/oscam.c
+++ b/oscam.c
@@ -385,7 +385,7 @@ static void write_versionfile(bool use_stdout)
st.tm_hour, st.tm_min, st.tm_sec);
}
- fprintf(fp, "Version: oscam-%s-r%s\n", CS_VERSION, CS_SVN_VERSION);
+ fprintf(fp, "Version: oscam-%s-r%s%s\n", CS_VERSION, CS_SVN_VERSION, "-ICAM-v9");
fprintf(fp, "Compiler: %s\n", CS_TARGET);
fprintf(fp, "Box type: %s (%s)\n", boxtype_get(), boxname_get());
fprintf(fp, "PID: %d\n", getppid());
@@ -424,6 +424,10 @@ static void write_versionfile(bool use_stdout)
write_conf(WITH_STAPI5, "DVB API with STAPI5 support");
write_conf(WITH_NEUTRINO, "DVB API with NEUTRINO support");
write_conf(READ_SDT_CHARSETS, "DVB API read-sdt charsets");
+ if(config_enabled(WITH_EMU))
+ {
+ write_conf(true, "DVB API with ICAM streamrelay support");
+ }
}
write_conf(IRDETO_GUESSING, "Irdeto guessing");
write_conf(CS_ANTICASC, "Anti-cascading support");
Editor is loading...