Skip to content

Commit

Permalink
Add: implementation for ICAM support #184
Browse files Browse the repository at this point in the history
  • Loading branch information
Barracuda09 committed Feb 14, 2023
1 parent cf6ef09 commit 9b31903
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 64 deletions.
6 changes: 5 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,16 @@ endif
# Add dvbcsa ?
ifeq "$(LIBDVBCSA)" "yes"
LDFLAGS += -ldvbcsa
# CFLAGS += -DLIBDVBCSA -DUSE_DEPRECATED_DVBAPI
# CFLAGS += -DUSE_DEPRECATED_DVBAPI
CFLAGS += -DLIBDVBCSA
SOURCES += decrypt/dvbapi/Client.cpp
SOURCES += decrypt/dvbapi/ClientProperties.cpp
SOURCES += decrypt/dvbapi/Keys.cpp
SOURCES += input/dvb/Frontend_DecryptInterface.cpp
# Need to build with ICAM support
ifeq "$(ICAM)" "yes"
CFLAGS += -DICAM
endif
endif

# Add dvbca ?
Expand Down
24 changes: 8 additions & 16 deletions src/decrypt/dvbapi/Client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,7 @@ namespace decrypt::dvbapi {
data[3] &= 0x3F;
}
} else {

///////////////////////////////////////////////////////////////////
// Need to filter this packet to OSCam
int demux = 0;
int filter = 0;
int tableID = data[5];
Expand All @@ -158,7 +157,13 @@ namespace decrypt::dvbapi {
} else {
const unsigned char *tableData = filterData.c_str();
const int sectionLength = (((tableData[6] & 0x0F) << 8) | tableData[7]) + 3; // 3 = tableID + length field

#ifdef ICAM
// Check for ICAM ECM
if ((tableID == mpegts::TableData::ECM0_ID ||
tableID == mpegts::TableData::ECM1_ID) && (tableData[7] - tableData[9])) {
frontend->setICAM(tableData[26], tableID & 0x01);
}
#endif
std::unique_ptr<unsigned char[]> clientData(new unsigned char[sectionLength + 25]);
const uint32_t request = htonl(DVBAPI_FILTER_DATA);
std::memcpy(&clientData[0], &request, 4);
Expand All @@ -176,7 +181,6 @@ namespace decrypt::dvbapi {
}
}
}
///////////////////////////////////////////////////////////////////

if (frontend->isMarkedAsActivePMT(pid)) {
sendPMT(index, id, *frontend->getSDTData(), *frontend->getPMTData(pid));
Expand Down Expand Up @@ -207,18 +211,6 @@ namespace decrypt::dvbapi {
SI_LOG_ERROR("Frontend: @#1, Stop CA Decrypt with demux index @#2 - send data to server failed", id, demux);
return false;
}
/*
const std::vector<int> demuxVector = frontend->getActiveOSCamDemuxFilters();
SI_LOG_DEBUG("Frontend: @#1, Stop CA Decrypt, number of active OSCam Demux: @#2", id, demuxVector.size());
for (const int demux : demuxVector) {
buff[7] = demux;
SI_LOG_DEBUG("Frontend: @#1, Stop CA Decrypt with demux index @#2", id, demux);
if (!_client.sendData(buff, sizeof(buff), MSG_DONTWAIT)) {
SI_LOG_ERROR("Frontend: @#1, Stop CA Decrypt with demux index @#2 - send data to server failed", id, demux);
return false;
}
}
*/
}
// Remove this PMT from the list
const auto it = _capmtMap.find(index.getID());
Expand Down
5 changes: 3 additions & 2 deletions src/decrypt/dvbapi/ClientProperties.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,12 @@ namespace decrypt::dvbapi {
}

void ClientProperties::decryptBatch() {
if (_keys.get(_parity) != nullptr) {
const auto key = _keys.get(_parity);
if (key != nullptr) {
// terminate batch buffer
setBatchData(nullptr, 0, _parity, nullptr);
// decrypt it
dvbcsa_bs_decrypt(_keys.get(_parity), _batch, 184);
dvbcsa_bs_decrypt(key, _batch, 184);

// clear scramble flags, so we can send it.
unsigned int i = 0;
Expand Down
4 changes: 4 additions & 0 deletions src/decrypt/dvbapi/ClientProperties.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ namespace decrypt::dvbapi {
_keys.set(cw, parity, index);
}

void setICAM(const unsigned char ecm, const int parity) {
_keys.setICAM(ecm, parity);
}

/// Get the active key for the requested parity
const dvbcsa_bs_key_s *getKey(int parity) const {
return _keys.get(parity);
Expand Down
80 changes: 50 additions & 30 deletions src/decrypt/dvbapi/Keys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,47 +23,67 @@

extern "C" {
#include <dvbcsa/dvbcsa.h>
#ifdef ICAM
void dvbcsa_bs_key_set_ecm(unsigned char ecm, const dvbcsa_cw_t cw, struct dvbcsa_bs_key_s *key);
#endif
}

namespace decrypt::dvbapi {

// =========================================================================
// -- Other member functions ----------------------------------------------
// =========================================================================
// =============================================================================
// -- Other member functions --------------------------------------------------
// =============================================================================

void Keys::set(const unsigned char *cw, int parity, int UNUSED(index)) {
dvbcsa_bs_key_s *k = dvbcsa_bs_key_alloc();
dvbcsa_bs_key_set(cw, k);
_key[parity].push(std::make_pair(base::TimeCounter::getTicks(), k));
//
while (_key[parity].size() > 1) {
remove(parity);
}
void Keys::set(const unsigned char *cw, int parity, int UNUSED(index)) {
dvbcsa_bs_key_s *k = dvbcsa_bs_key_alloc();
#ifdef ICAM
const unsigned char icamECM = _icam[parity].back();
dvbcsa_bs_key_set_ecm(icamECM, cw, k);
#else
dvbcsa_bs_key_set(cw, k);
#endif
_key[parity].push(std::make_tuple(base::TimeCounter::getTicks(), k));
while (_key[parity].size() > 1) {
remove(parity);
}
}

const dvbcsa_bs_key_s *Keys::get(int parity) const {
if (!_key[parity].empty()) {
const KeyPair pair = _key[parity].back();
// const long duration = base::TimeCounter::getTicks() - pair.first;
return pair.second;
} else {
return nullptr;
}
void Keys::setICAM(const unsigned char ecm, int parity) {
_icam[parity].push(ecm);
while (_icam[parity].size() > 1) {
_icam[parity].pop();
}
}

void Keys::freeKeys() {
while (!_key[0].empty()) {
remove(0);
}
while (!_key[1].empty()) {
remove(1);
}
const dvbcsa_bs_key_s * Keys::get(int parity) const {
if (!_key[parity].empty()) {
const KeyTuple tup = _key[parity].back();
// const long duration = base::TimeCounter::getTicks() - pair.first;
return std::get<1>(tup);
} else {
return nullptr;
}
}

void Keys::remove(int parity) {
const KeyPair pair = _key[parity].front();
dvbcsa_bs_key_free(pair.second);
_key[parity].pop();
void Keys::freeKeys() {
while (!_key[0].empty()) {
remove(0);
}
while (!_key[1].empty()) {
remove(1);
}
while (_icam[0].size() > 1) {
_icam[0].pop();
}
while (_icam[1].size() > 1) {
_icam[1].pop();
}
}

void Keys::remove(int parity) {
const KeyTuple tup = _key[parity].front();
dvbcsa_bs_key_free(std::get<1>(tup));
_key[parity].pop();
}

}
21 changes: 13 additions & 8 deletions src/decrypt/dvbapi/Keys.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@

#include <utility>
#include <queue>
#include <tuple>

FW_DECL_NS0(dvbcsa_bs_key_s);

Expand All @@ -34,25 +35,28 @@ namespace decrypt::dvbapi {
///
class Keys {
public:
using KeyPair = std::pair<long, dvbcsa_bs_key_s *>;
using KeyQueue = std::queue<KeyPair>;
using KeyTuple = std::tuple<long, dvbcsa_bs_key_s *>;
using KeyQueue = std::queue<KeyTuple>;
using ICAMQueue = std::queue<unsigned char>;

// =====================================================================
// -- Constructors and destructor -------------------------------------
// =====================================================================
// =========================================================================
// -- Constructors and destructor -----------------------------------------
// =========================================================================
public:

Keys() = default;

virtual ~Keys() = default;

// =====================================================================
// -- Other member functions ------------------------------------------
// =====================================================================
// =========================================================================
// -- Other member functions ----------------------------------------------
// =========================================================================
public:

void set(const unsigned char *cw, int parity, int index);

void setICAM(const unsigned char ecm, int parity);

const dvbcsa_bs_key_s *get(int parity) const;

void freeKeys();
Expand All @@ -67,6 +71,7 @@ class Keys {
private:

KeyQueue _key[2];
ICAMQueue _icam[2];
};

}
Expand Down
2 changes: 2 additions & 0 deletions src/input/dvb/Frontend.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ class Frontend :

virtual void setKey(const unsigned char *cw, int parity, int index) final;

virtual void setICAM(const unsigned char ecm, int parity) final;

virtual void startOSCamFilterData(int pid, int demux, int filter,
const unsigned char *filterData, const unsigned char *filterMask) final;

Expand Down
9 changes: 5 additions & 4 deletions src/input/dvb/FrontendDecryptInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ FW_DECL_SP_NS1(mpegts, PMT);
FW_DECL_SP_NS1(mpegts, SDT);
FW_DECL_SP_NS2(input, dvb, FrontendDecryptInterface);

namespace input {
namespace dvb {
namespace input::dvb {

/// The class @c FrontendDecryptInterface is an interface to an @c Stream for decrypting
class FrontendDecryptInterface {
Expand Down Expand Up @@ -73,6 +72,9 @@ class FrontendDecryptInterface {
///
virtual void setKey(const unsigned char *cw, int parity, int index) = 0;

///
virtual void setICAM(unsigned char ecm, int parity) = 0;

///
virtual void startOSCamFilterData(int pid, int demux, int filter,
const unsigned char *filterData, const unsigned char *filterMask) = 0;
Expand Down Expand Up @@ -113,7 +115,6 @@ class FrontendDecryptInterface {
virtual mpegts::SpSDT getSDTData() const = 0;
};

} // namespace dvb
} // namespace input
}

#endif // INPUT_DVB_FRONTENDDECRYPTINTERFACE_H_INCLUDE
4 changes: 4 additions & 0 deletions src/input/dvb/Frontend_DecryptInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ void Frontend::setKey(const unsigned char *cw, int parity, int index) {
_dvbapiData.setKey(cw, parity, index);
}

void Frontend::setICAM(const unsigned char ecm, const int parity) {
_dvbapiData.setICAM(ecm, parity);
}

void Frontend::startOSCamFilterData(const int pid, const int demux, const int filter,
const unsigned char *filterData, const unsigned char *filterMask) {
SI_LOG_INFO("Frontend: @#1, Start filter PID: @#2 demux: @#3 filter: @#4 (data @#5 @#6 @#7 mask @#8 @#9 @#10 @#11)",
Expand Down
6 changes: 3 additions & 3 deletions src/output/StreamThreadBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ void StreamThreadBase::threadEntry() {
}
}

// =========================================================================
// -- Other member functions ----------------------------------------------
// =========================================================================
// =============================================================================
// -- Other member functions --------------------------------------------------
// =============================================================================

bool StreamThreadBase::startStreaming(const int clientID) {
_clientID = clientID;
Expand Down

0 comments on commit 9b31903

Please sign in to comment.