src/v4l.c \
src/webui/extjs_v4l.c \
-# CWC
-SRCS-${CONFIG_CWC} += src/cwc.c \
- src/capmt.c \
- src/ffdecsa/ffdecsa_interface.c \
- src/ffdecsa/ffdecsa_int.c
-
# Avahi
SRCS-$(CONFIG_AVAHI) += src/avahi.c
-# Optimised code
+# CWC
+SRCS-${CONFIG_CWC} += src/cwc.c \
+ src/capmt.c
+
+# FFdecsa
+ifneq ($(CONFIG_DVBCSA),yes)
+SRCS-${CONFIG_CWC} += src/ffdecsa/ffdecsa_interface.c \
+ src/ffdecsa/ffdecsa_int.c
SRCS-${CONFIG_MMX} += src/ffdecsa/ffdecsa_mmx.c
SRCS-${CONFIG_SSE2} += src/ffdecsa/ffdecsa_sse2.c
${BUILDDIR}/src/ffdecsa/ffdecsa_mmx.o : CFLAGS += -mmmx
${BUILDDIR}/src/ffdecsa/ffdecsa_sse2.o : CFLAGS += -msse2
+endif
# File bundles
SRCS-${CONFIG_BUNDLE} += bundle.c
"avahi:auto"
"zlib:auto"
"bundle:no"
+ "dvbcsa:no"
)
#
fi
fi
+#
+# libdvbcsa
+#
+if enabled cwc && enabled dvbcsa; then
+ (check_cc_header "dvbcsa/dvbcsa" dvbcsa_h &&\
+ check_cc_lib dvbcsa dvbcsa_l) ||\
+ die "Failed to find dvbcsa support (use --disable-dvbcsa)"
+ LDFLAGS="$LDFLAGS -ldvbcsa"
+fi
+
+
# ###########################################################################
# Write config
# ###########################################################################
#include "tcp.h"
#include "psi.h"
#include "tsdemux.h"
-#include <dvbcsa/dvbcsa.h>
#include "capmt.h"
#include "notify.h"
#include "subscriptions.h"
#include "dtable.h"
+#if ENABLE_DVBCSA
+#include <dvbcsa/dvbcsa.h>
+#else
+#include "ffdecsa/FFdecsa.h"
+#endif
+
// ca_pmt_list_management values:
#define CAPMT_LIST_MORE 0x00 // append a 'MORE' CAPMT object the list and start receiving the next object
#define CAPMT_LIST_FIRST 0x01 // clear the list when a 'FIRST' CAPMT object is received, and start receiving the next object
} ct_keystate;
/* buffers for keystructs */
+#if ENABLE_DVBCSA
struct dvbcsa_bs_key_s *ct_key_even;
struct dvbcsa_bs_key_s *ct_key_odd;
+#else
+ void *ct_keys;
+#endif
/* CSA */
int ct_cluster_size;
uint8_t *ct_tsbcluster;
+ int ct_fill;
+#if ENABLE_DVBCSA
struct dvbcsa_bs_batch_s *ct_tsbbatch_even;
struct dvbcsa_bs_batch_s *ct_tsbbatch_odd;
- int ct_fill;
int ct_fill_even;
int ct_fill_odd;
+#endif
/* current sequence number */
uint16_t ct_seq;
LIST_REMOVE(ct, ct_link);
+#if ENABLE_DVBCSA
dvbcsa_bs_key_free(ct->ct_key_odd);
dvbcsa_bs_key_free(ct->ct_key_even);
free(ct->ct_tsbbatch_odd);
free(ct->ct_tsbbatch_even);
+#else
+ free_key_struct(ct->ct_keys);
+#endif
free(ct->ct_tsbcluster);
free(ct);
}
continue;
if (memcmp(even, invalid, 8))
+#if ENABLE_DVBCSA
dvbcsa_bs_key_set(even, ct->ct_key_even);
+#else
+ set_even_control_word(ct->ct_keys, even);
+#endif
if (memcmp(odd, invalid, 8))
+#if ENABLE_DVBCSA
dvbcsa_bs_key_set(odd, ct->ct_key_odd);
+#else
+ set_odd_control_word(ct->ct_keys, odd);
+#endif
if(ct->ct_keystate != CT_RESOLVED)
tvhlog(LOG_INFO, "capmt", "Obtained key for service \"%s\"",t->s_svcname);
/**
*
*/
+#if ENABLE_DVBCSA
static int
capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
const uint8_t *tsb)
ct->ct_fill = 0;
return 0;
}
+#else
+static int
+capmt_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
+ const uint8_t *tsb)
+{
+ capmt_service_t *ct = (capmt_service_t *)td;
+ int r, i;
+ unsigned char *vec[3];
+ uint8_t *t0;
+
+ if(ct->ct_keystate == CT_FORBIDDEN)
+ return 1;
+
+ if(ct->ct_keystate != CT_RESOLVED)
+ return -1;
+
+ memcpy(ct->ct_tsbcluster + ct->ct_fill * 188, tsb, 188);
+ ct->ct_fill++;
+
+ if(ct->ct_fill != ct->ct_cluster_size)
+ return 0;
+
+ ct->ct_fill = 0;
+
+ vec[0] = ct->ct_tsbcluster;
+ vec[1] = ct->ct_tsbcluster + ct->ct_cluster_size * 188;
+ vec[2] = NULL;
+
+ while(1) {
+ t0 = vec[0];
+ r = decrypt_packets(ct->ct_keys, vec);
+ if(r == 0)
+ break;
+ for(i = 0; i < r; i++) {
+ ts_recv_packet2(t, t0);
+ t0 += 188;
+ }
+ }
+ return 0;
+}
+#endif
/**
* Check if our CAID's matches, and if so, link
/* create new capmt service */
ct = calloc(1, sizeof(capmt_service_t));
+#if ENABLE_DVBCSA
ct->ct_cluster_size = dvbcsa_bs_batch_size();
+#else
+ ct->ct_cluster_size = get_suggested_cluster_size();
+#endif
ct->ct_tsbcluster = malloc(ct->ct_cluster_size * 188);
+ ct->ct_seq = capmt->capmt_seq++;
+#if ENABLE_DVBCSA
ct->ct_tsbbatch_even = malloc((ct->ct_cluster_size + 1) *
sizeof(struct dvbcsa_bs_batch_s));
ct->ct_tsbbatch_odd = malloc((ct->ct_cluster_size + 1) *
sizeof(struct dvbcsa_bs_batch_s));
- ct->ct_seq = capmt->capmt_seq++;
+#endif
TAILQ_FOREACH(st, &t->s_components, es_link) {
caid_t *c;
}
}
+#if ENABLE_DVBCSA
ct->ct_key_even = dvbcsa_bs_key_alloc();
ct->ct_key_odd = dvbcsa_bs_key_alloc();
+#else
+ ct->ct_keys = get_key_struct();
+#endif
ct->ct_capmt = capmt;
ct->ct_service = t;
#include <netinet/in.h>
#include <arpa/inet.h>
#include <ctype.h>
+#include <openssl/des.h>
+
#include "tvheadend.h"
#include "tcp.h"
#include "psi.h"
#include "tsdemux.h"
-#include <dvbcsa/dvbcsa.h>
#include "cwc.h"
#include "notify.h"
#include "atomic.h"
#include "dtable.h"
#include "subscriptions.h"
#include "service.h"
-#include <openssl/des.h>
+
+#if ENABLE_DVBCSA
+#include <dvbcsa/dvbcsa.h>
+#else
+#include "ffdecsa/FFdecsa.h"
+#endif
/**
*
CS_IDLE
} cs_keystate;
+#if ENABLE_DVBCSA
struct dvbcsa_bs_key_s *cs_key_even;
struct dvbcsa_bs_key_s *cs_key_odd;
-
+#else
+ void *cs_keys;
+#endif
uint8_t cs_cw[16];
int cs_pending_cw_update;
*/
int cs_cluster_size;
uint8_t *cs_tsbcluster;
+ int cs_fill;
+#if ENABLE_DVBCSA
struct dvbcsa_bs_batch_s *cs_tsbbatch_even;
struct dvbcsa_bs_batch_s *cs_tsbbatch_odd;
- int cs_fill;
int cs_fill_even;
int cs_fill_odd;
+#endif
LIST_HEAD(, ecm_pid) cs_pids;
ct->cs_pending_cw_update = 0;
for(i = 0; i < 8; i++)
if(ct->cs_cw[i]) {
+#if ENABLE_DVBCSA
dvbcsa_bs_key_set(ct->cs_cw, ct->cs_key_even);
+#else
+ set_even_control_word(ct->cs_keys, ct->cs_cw);
+#endif
break;
}
for(i = 0; i < 8; i++)
if(ct->cs_cw[8 + i]) {
+#if ENABLE_DVBCSA
dvbcsa_bs_key_set(ct->cs_cw + 8, ct->cs_key_odd);
+#else
+ set_odd_control_word(ct->cs_keys, ct->cs_cw + 8);
+#endif
break;
}
}
/**
*
*/
+#if ENABLE_DVBCSA
static int
cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
const uint8_t *tsb)
return 0;
}
+#else
+static int
+cwc_descramble(th_descrambler_t *td, service_t *t, struct elementary_stream *st,
+ const uint8_t *tsb)
+{
+ cwc_service_t *ct = (cwc_service_t *)td;
+ int r;
+ unsigned char *vec[3];
+
+ if(ct->cs_keystate == CS_FORBIDDEN)
+ return 1;
+
+ if(ct->cs_keystate != CS_RESOLVED)
+ return -1;
+
+ if(ct->cs_fill == 0 && ct->cs_pending_cw_update)
+ update_keys(ct);
+
+ memcpy(ct->cs_tsbcluster + ct->cs_fill * 188, tsb, 188);
+ ct->cs_fill++;
+
+ if(ct->cs_fill != ct->cs_cluster_size)
+ return 0;
+
+ while(1) {
+
+ vec[0] = ct->cs_tsbcluster;
+ vec[1] = ct->cs_tsbcluster + ct->cs_fill * 188;
+ vec[2] = NULL;
+
+ r = decrypt_packets(ct->cs_keys, vec);
+ if(r > 0) {
+ int i;
+ const uint8_t *t0 = ct->cs_tsbcluster;
+
+ for(i = 0; i < r; i++) {
+ ts_recv_packet2(t, t0);
+ t0 += 188;
+ }
+
+ r = ct->cs_fill - r;
+ assert(r >= 0);
+
+ if(r > 0)
+ memmove(ct->cs_tsbcluster, t0, r * 188);
+ ct->cs_fill = r;
+
+ if(ct->cs_pending_cw_update && r > 0)
+ continue;
+ } else {
+ ct->cs_fill = 0;
+ }
+ break;
+ }
+ if(ct->cs_pending_cw_update)
+ update_keys(ct);
+
+ return 0;
+}
+#endif
/**
* cwc_mutex is held
LIST_REMOVE(ct, cs_link);
+#if ENABLE_DVBCSA
dvbcsa_bs_key_free(ct->cs_key_odd);
dvbcsa_bs_key_free(ct->cs_key_even);
free(ct->cs_tsbbatch_odd);
free(ct->cs_tsbbatch_even);
+#else
+ free_key_struct(ct->cs_keys);
+#endif
free(ct->cs_tsbcluster);
free(ct);
}
if(cwc_find_stream_by_caid(t, cwc->cwc_caid) == NULL)
continue;
- ct = calloc(1, sizeof(cwc_service_t));
- ct->cs_cluster_size = dvbcsa_bs_batch_size();
- ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
+ ct = calloc(1, sizeof(cwc_service_t));
+#if ENABLE_DVBCSA
+ ct->cs_cluster_size = dvbcsa_bs_batch_size();
+#else
+ ct->cs_cluster_size = get_suggested_cluster_size();
+#endif
+ ct->cs_tsbcluster = malloc(ct->cs_cluster_size * 188);
+#if ENABLE_DVBCSA
ct->cs_tsbbatch_even = malloc((ct->cs_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
- ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
- sizeof(struct dvbcsa_bs_batch_s));
-
- ct->cs_key_even = dvbcsa_bs_key_alloc();
- ct->cs_key_odd = dvbcsa_bs_key_alloc();
- ct->cs_cwc = cwc;
- ct->cs_service = t;
- ct->cs_okchannel = -3;
+ sizeof(struct dvbcsa_bs_batch_s));
+ ct->cs_tsbbatch_odd = malloc((ct->cs_cluster_size + 1) *
+ sizeof(struct dvbcsa_bs_batch_s));
+ ct->cs_key_even = dvbcsa_bs_key_alloc();
+ ct->cs_key_odd = dvbcsa_bs_key_alloc();
+#else
+ ct->cs_keys = get_key_struct();
+#endif
+ ct->cs_cwc = cwc;
+ ct->cs_service = t;
+ ct->cs_okchannel = -1;
td = &ct->cs_head;
td->td_stop = cwc_service_destroy;
htsp_init();
+#if (!ENABLE_DVBCSA)
+ ffdecsa_init();
+#endif
+
if(rawts_input != NULL)
rawts_init(rawts_input);