From 26ff10ce1e76be9a6440b081f34dd239f26e6774 Mon Sep 17 00:00:00 2001 From: Rolf Ahrenberg Date: Sun, 11 Jan 2015 01:49:59 +0200 Subject: [PATCH] Added configurable CI slots. --- HISTORY | 2 ++ README | 8 +++---- common.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++++++++++- common.h | 16 +++++++++++--- config.c | 29 ++++++++++++++++++------- config.h | 3 +++ device.c | 17 +++++++++++++-- satip.c | 30 ++++++++++++++++++++++++-- setup.c | 35 ++++++++++++++++++++++++++++--- setup.h | 3 +++ 10 files changed, 183 insertions(+), 24 deletions(-) diff --git a/HISTORY b/HISTORY index f8c336e..997defe 100644 --- a/HISTORY +++ b/HISTORY @@ -99,3 +99,5 @@ VDR Plugin 'satip' Revision History - Added support for Digital Devices CI extension. 2015-01-18: Version 1.0.2 + +- Added configurable CI slots. diff --git a/README b/README index bf87e0f..a510951 100644 --- a/README +++ b/README @@ -70,11 +70,6 @@ identifier number in RID field of a channels.conf entry: FE = RID % 100 Valid range: 1 ... 99 -A channel can be assigned into a specific integrated CI slot by giving -the identifier number in RID field of a channels.conf entry: -CI# = (RID / 100) % 10 -Valid range: 1 ... 9 - Setup menu: - Operating mode = off If you want exclude all SAT>IP devices @@ -89,6 +84,9 @@ Setup menu: in some SAT>IP hardware (e.g. Digital Devices OctopusNet), set this option to "yes". +- CICAM # = If you want to assign a CA system into + a specific CI slot, set this option to + a named one. Use "---" for autoselection. - Enable EPG scanning = yes If you want exclude all SAT>IP devices from VDR's EIT background scanning, set this option to "no". diff --git a/common.c b/common.c index 4206964..02892ca 100644 --- a/common.c +++ b/common.c @@ -79,10 +79,72 @@ cString ChangeCase(const cString &strP, bool upperP) const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE] = { - /* description tag pid tid mask */ + // description tag pid tid mask {trNOOP("PAT (0x00)"), "PAT", 0x00, 0x00, 0xFF}, {trNOOP("NIT (0x40)"), "NIT", 0x10, 0x40, 0xFF}, {trNOOP("SDT (0x42)"), "SDT", 0x11, 0x42, 0xFF}, {trNOOP("EIT (0x4E/0x4F/0x5X/0x6X)"), "EIT", 0x12, 0x40, 0xC0}, {trNOOP("TDT (0x70)"), "TDT", 0x14, 0x70, 0xFF}, }; + +const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE] = +{ + // http://www.dvb.org/index.php?id=174 + // http://en.wikipedia.org/wiki/Conditional_access_system + // start end description + {0x0000, 0x0000, "---" }, // 0 + {0x0100, 0x01FF, "SECA Mediaguard (100..1FF)"}, // 1 + {0x0464, 0x0464, "EuroDec (464)" }, // 2 + {0x0500, 0x05FF, "Viaccess (500..5FF)" }, // 3 + {0x0600, 0x06FF, "Irdeto (600..6FF)" }, // 4 + {0x0700, 0x07FF, "DigiCipher 2 (700..7FF)" }, // 5 + {0x0900, 0x09FF, "NDS Videoguard (900..9FF)" }, // 6 + {0x0B00, 0x0BFF, "Conax (B00..BFF)" }, // 7 + {0x0D00, 0x0DFF, "CryptoWorks (D00..DFF)" }, // 8 + {0x0E00, 0x0EFF, "PowerVu (E00..EFF)" }, // 9 + {0x1000, 0x10FF, "RAS (1000..10FF)" }, // 10 + {0x1200, 0x12FF, "NagraVision (1200..12FF)" }, // 11 + {0x1700, 0x17FF, "VCAS (1700..17FF)" }, // 12 + {0x1800, 0x18FF, "NagraVision (1800..18FF)" }, // 13 + {0x22F0, 0x22F0, "Codicrypt (22F0)" }, // 14 + {0x2600, 0x2600, "BISS (2600)" }, // 15 + {0x2719, 0x2719, "VanyaCas (2719)" }, // 16 + {0x4347, 0x4347, "CryptOn (4347)" }, // 17 + {0x4800, 0x4800, "Accessgate (4800)" }, // 18 + {0x4900, 0x4900, "China Crypt (4900)" }, // 19 + {0x4A02, 0x4A02, "Tongfang (4A02)" }, // 20 + {0x4A10, 0x4A10, "EasyCas (4A10)" }, // 21 + {0x4A20, 0x4A20, "AlphaCrypt (4A20)" }, // 22 + {0x4A60, 0x4A60, "SkyCrypt (4A60)" }, // 23 + {0x4A61, 0x4A61, "Neotioncrypt (4A61)" }, // 24 + {0x4A62, 0x4A62, "SkyCrypt (4A62)" }, // 25 + {0x4A63, 0x4A63, "Neotion SHL (4A63)" }, // 26 + {0x4A64, 0x4A6F, "SkyCrypt (4A64)" }, // 27 + {0x4A70, 0x4A70, "DreamCrypt (4A70)" }, // 28 + {0x4A80, 0x4A80, "ThalesCrypt (4A80)" }, // 29 + {0x4AA1, 0x4AA1, "KeyFly (4AA1)" }, // 30 + {0x4ABF, 0x4ABF, "CTI-CAS (4ABF)" }, // 31 + {0x4AC1, 0x4AC1, "Latens (4AC1)" }, // 32 + {0x4AD0, 0x4AD1, "X-Crypt (4AD0)" }, // 33 + {0x4AD4, 0x4AD4, "OmniCrypt (4AD4)" }, // 34 + {0x4AE0, 0x4AE1, "Z-Crypt (4AE0)" }, // 35 + {0x4AE4, 0x4AE4, "CoreCrypt (4AE4)" }, // 36 + {0x4AE5, 0x4AE5, "PRO-Crypt (4AE5)" }, // 37 + {0x4AEA, 0x4AEA, "Cryptoguard (4AEA)" }, // 38 + {0x4AEB, 0x4AEB, "Abel Quintic (4AEB)" }, // 39 + {0x4AF0, 0x4AF0, "ABV (4AF0)" }, // 40 + {0x5500, 0x5500, "Z-Crypt (5500)" }, // 41 + {0x5501, 0x5501, "Griffin (5501)" }, // 42 + {0x5581, 0x5581, "Bulcrypt (5581)" }, // 43 + {0x7BE1, 0x7BE1, "DRE-Crypt (7BE1)" }, // 44 + {0xA101, 0xA101, "RosCrypt-M (A101)" }, // 45 + {0xEAD0, 0xEAD0, "VanyaCas (EAD0)" }, // 46 +}; + +bool checkCASystem(unsigned int cicamP, int caidP) +{ + // always skip the first row + if ((cicamP > 0) && (cicamP < ELEMENTS(ca_systems_table))) + return ((caidP >= ca_systems_table[cicamP].start) && (caidP <= ca_systems_table[cicamP].end)); + return false; +} diff --git a/common.h b/common.h index c57274e..91e750e 100644 --- a/common.h +++ b/common.h @@ -13,8 +13,6 @@ #include #include -#define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) - #define SATIP_MAX_DEVICES MAXDEVICES #define SATIP_BUFFER_SIZE KILOBYTE(1024) @@ -32,6 +30,9 @@ #define MAX_DISABLED_SOURCES_COUNT 5 #define SECTION_FILTER_TABLE_SIZE 5 +#define MAX_CICAM_COUNT 2 +#define CA_SYSTEMS_TABLE_SIZE 47 + #define SATIP_CURL_EASY_GETINFO(X, Y, Z) \ if ((res = curl_easy_getinfo((X), (Y), (Z))) != CURLE_OK) { \ error("curl_easy_getinfo(%s) [%s,%d] failed: %s (%d)", #Y, __FILE__, __LINE__, curl_easy_strerror(res), res); \ @@ -81,7 +82,7 @@ } \ } while (0) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) +#define ELEMENTS(x) (sizeof(x) / sizeof(x[0])) uint16_t ts_pid(const uint8_t *bufP); uint8_t payload(const uint8_t *bufP); @@ -100,6 +101,15 @@ struct section_filter_table_type { extern const section_filter_table_type section_filter_table[SECTION_FILTER_TABLE_SIZE]; +struct ca_systems_table_type { + int start; + int end; + const char *description; +}; + +extern const ca_systems_table_type ca_systems_table[CA_SYSTEMS_TABLE_SIZE]; +extern bool checkCASystem(unsigned int cicamP, int caidP); + extern const char VERSION[]; #endif // __SATIP_COMMON_H diff --git a/config.c b/config.c index c5c2112..91002bb 100644 --- a/config.c +++ b/config.c @@ -18,46 +18,59 @@ cSatipConfig::cSatipConfig(void) eitScanM(1), useBytesM(1) { - for (unsigned int i = 0; i < ARRAY_SIZE(disabledSourcesM); ++i) + for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i) + cicamsM[i] = 0; + for (unsigned int i = 0; i < ELEMENTS(disabledSourcesM); ++i) disabledSourcesM[i] = cSource::stNone; - for (unsigned int i = 0; i < ARRAY_SIZE(disabledFiltersM); ++i) + for (unsigned int i = 0; i < ELEMENTS(disabledFiltersM); ++i) disabledFiltersM[i] = -1; } +int cSatipConfig::GetCICAM(unsigned int indexP) const +{ + return (indexP < ELEMENTS(cicamsM)) ? cicamsM[indexP] : -1; +} + +void cSatipConfig::SetCICAM(unsigned int indexP, int cicamP) +{ + if (indexP < ELEMENTS(cicamsM)) + cicamsM[indexP] = cicamP; +} + unsigned int cSatipConfig::GetDisabledSourcesCount(void) const { unsigned int n = 0; - while ((n < ARRAY_SIZE(disabledSourcesM) && (disabledSourcesM[n] != cSource::stNone))) + while ((n < ELEMENTS(disabledSourcesM) && (disabledSourcesM[n] != cSource::stNone))) n++; return n; } int cSatipConfig::GetDisabledSources(unsigned int indexP) const { - return (indexP < ARRAY_SIZE(disabledSourcesM)) ? disabledSourcesM[indexP] : cSource::stNone; + return (indexP < ELEMENTS(disabledSourcesM)) ? disabledSourcesM[indexP] : cSource::stNone; } void cSatipConfig::SetDisabledSources(unsigned int indexP, int sourceP) { - if (indexP < ARRAY_SIZE(disabledSourcesM)) + if (indexP < ELEMENTS(disabledSourcesM)) disabledSourcesM[indexP] = sourceP; } unsigned int cSatipConfig::GetDisabledFiltersCount(void) const { unsigned int n = 0; - while ((n < ARRAY_SIZE(disabledFiltersM) && (disabledFiltersM[n] != -1))) + while ((n < ELEMENTS(disabledFiltersM) && (disabledFiltersM[n] != -1))) n++; return n; } int cSatipConfig::GetDisabledFilters(unsigned int indexP) const { - return (indexP < ARRAY_SIZE(disabledFiltersM)) ? disabledFiltersM[indexP] : -1; + return (indexP < ELEMENTS(disabledFiltersM)) ? disabledFiltersM[indexP] : -1; } void cSatipConfig::SetDisabledFilters(unsigned int indexP, int numberP) { - if (indexP < ARRAY_SIZE(disabledFiltersM)) + if (indexP < ELEMENTS(disabledFiltersM)) disabledFiltersM[indexP] = numberP; } diff --git a/config.h b/config.h index e1f9f46..0490401 100644 --- a/config.h +++ b/config.h @@ -19,6 +19,7 @@ private: unsigned int ciExtensionM; unsigned int eitScanM; unsigned int useBytesM; + int cicamsM[MAX_CICAM_COUNT]; int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT]; int disabledFiltersM[SECTION_FILTER_TABLE_SIZE]; @@ -60,6 +61,7 @@ public: unsigned int GetTraceMode(void) const { return traceModeM; } bool IsTraceMode(eTraceMode modeP) const { return (traceModeM & modeP); } unsigned int GetCIExtension(void) const { return ciExtensionM; } + int GetCICAM(unsigned int indexP) const; unsigned int GetEITScan(void) const { return eitScanM; } unsigned int GetUseBytes(void) const { return useBytesM; } unsigned int GetDisabledSourcesCount(void) const; @@ -70,6 +72,7 @@ public: void SetOperatingMode(unsigned int operatingModeP) { operatingModeM = operatingModeP; } void SetTraceMode(unsigned int modeP) { traceModeM = (modeP & eTraceModeMask); } void SetCIExtension(unsigned int onOffP) { ciExtensionM = onOffP; } + void SetCICAM(unsigned int indexP, int cicamP); void SetEITScan(unsigned int onOffP) { eitScanM = onOffP; } void SetUseBytes(unsigned int onOffP) { useBytesM = onOffP; } void SetDisabledSources(unsigned int indexP, int sourceP); diff --git a/device.c b/device.c index 32bd624..e21b2b2 100644 --- a/device.c +++ b/device.c @@ -440,8 +440,21 @@ int cSatipDevice::GetPmtPid(void) int cSatipDevice::GetCISlot(void) { - int slot = channelM.Ca() ? (channelM.Rid() / 100) % 10 : 0; - debug11("%s slot=%d name=%s [device %u]", __PRETTY_FUNCTION__, slot, channelM.Name(), deviceIndexM); + int slot = 0; + int ca = 0; + for (const int *id = channelM.Caids(); *id; ++id) { + if (checkCASystem(SatipConfig.GetCICAM(0), *id)) { + ca = *id; + slot = 1; + break; + } + else if (checkCASystem(SatipConfig.GetCICAM(1), *id)) { + ca = *id; + slot = 2; + break; + } + } + debug11("%s slot=%d ca=%X name=%s [device %u]", __PRETTY_FUNCTION__, slot, ca, channelM.Name(), deviceIndexM); return slot; } diff --git a/satip.c b/satip.c index adc102e..305d41f 100644 --- a/satip.c +++ b/satip.c @@ -35,6 +35,7 @@ private: unsigned int deviceCountM; cSatipDiscoverServers *serversM; void ParseServer(const char *paramP); + int ParseCicams(const char *valueP, int *cicamsP); int ParseSources(const char *valueP, int *sourcesP); int ParseFilters(const char *valueP, int *filtersP); public: @@ -234,6 +235,23 @@ void cPluginSatip::ParseServer(const char *paramP) } } +int cPluginSatip::ParseCicams(const char *valueP, int *cicamsP) +{ + debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP); + int n = 0; + char *s, *p = (char *)valueP; + char *r = strtok_r(p, " ", &s); + while (r) { + r = skipspace(r); + debug3("%s cicams[%d]=%s", __PRETTY_FUNCTION__, n, r); + if (n < MAX_CICAM_COUNT) { + cicamsP[n++] = atoi(r); + } + r = strtok_r(NULL, " \n", &s); + } + return n; +} + int cPluginSatip::ParseSources(const char *valueP, int *sourcesP) { debug1("%s (%s,)", __PRETTY_FUNCTION__, valueP); @@ -276,11 +294,19 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP) SatipConfig.SetOperatingMode(atoi(valueP)); else if (!strcasecmp(nameP, "EnableCIExtension")) SatipConfig.SetCIExtension(atoi(valueP)); + else if (!strcasecmp(nameP, "CICAM")) { + int Cicams[MAX_CICAM_COUNT]; + for (unsigned int i = 0; i < ELEMENTS(Cicams); ++i) + Cicams[i] = 0; + unsigned int CicamsCount = ParseCicams(valueP, Cicams); + for (unsigned int i = 0; i < CicamsCount; ++i) + SatipConfig.SetCICAM(i, Cicams[i]); + } else if (!strcasecmp(nameP, "EnableEITScan")) SatipConfig.SetEITScan(atoi(valueP)); else if (!strcasecmp(nameP, "DisabledSources")) { int DisabledSources[MAX_DISABLED_SOURCES_COUNT]; - for (unsigned int i = 0; i < ARRAY_SIZE(DisabledSources); ++i) + for (unsigned int i = 0; i < ELEMENTS(DisabledSources); ++i) DisabledSources[i] = cSource::stNone; unsigned int DisabledSourcesCount = ParseSources(valueP, DisabledSources); for (unsigned int i = 0; i < DisabledSourcesCount; ++i) @@ -288,7 +314,7 @@ bool cPluginSatip::SetupParse(const char *nameP, const char *valueP) } else if (!strcasecmp(nameP, "DisabledFilters")) { int DisabledFilters[SECTION_FILTER_TABLE_SIZE]; - for (unsigned int i = 0; i < ARRAY_SIZE(DisabledFilters); ++i) + for (unsigned int i = 0; i < ELEMENTS(DisabledFilters); ++i) DisabledFilters[i] = -1; unsigned int DisabledFiltersCount = ParseFilters(valueP, DisabledFilters); for (unsigned int i = 0; i < DisabledFiltersCount; ++i) diff --git a/setup.c b/setup.c index b83e01e..88be18a 100644 --- a/setup.c +++ b/setup.c @@ -342,6 +342,10 @@ cSatipPluginSetup::cSatipPluginSetup() operatingModeTextsM[cSatipConfig::eOperatingModeLow] = tr("low"); operatingModeTextsM[cSatipConfig::eOperatingModeNormal] = tr("normal"); operatingModeTextsM[cSatipConfig::eOperatingModeHigh] = tr("high"); + for (unsigned int i = 0; i < ELEMENTS(cicamsM); ++i) + cicamsM[i] = SatipConfig.GetCICAM(i); + for (unsigned int i = 0; i < ELEMENTS(ca_systems_table); ++i) + cicamTextsM[i] = ca_systems_table[i].description; if (numDisabledSourcesM > MAX_DISABLED_SOURCES_COUNT) numDisabledSourcesM = MAX_DISABLED_SOURCES_COUNT; for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i) @@ -371,6 +375,11 @@ void cSatipPluginSetup::Setup(void) #ifdef XCI Add(new cMenuEditBoolItem(tr("Enable CI extension"), &ciExtensionM)); helpM.Append(tr("Define whether a CI extension shall be used.\n\nThis setting enables integrated CI/CAM handling found in some SAT>IP hardware (e.g. Digital Devices OctopusNet).")); + + for (unsigned int i = 0; ciExtensionM && i < ELEMENTS(cicamsM); ++i) { + Add(new cMenuEditStraItem(*cString::sprintf(" %s #%d", "CI/CAM", i + 1), &cicamsM[i], ELEMENTS(cicamTextsM), cicamTextsM)); + helpM.Append("Define the used CI/CAM type for CI slot."); + } #endif Add(new cMenuEditBoolItem(tr("Enable EPG scanning"), &eitScanM)); helpM.Append(tr("Define whether the EPG background scanning shall be used.\n\nThis setting disables the automatic EIT scanning functionality for all SAT>IP devices.")); @@ -448,6 +457,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP) { bool hadSubMenu = HasSubMenu(); int oldOperatingMode = operatingModeM; + int oldCiExtension = ciExtensionM; int oldNumDisabledSources = numDisabledSourcesM; int oldNumDisabledFilters = numDisabledFiltersM; eOSState state = cMenuSetupPage::ProcessKey(keyP); @@ -471,7 +481,7 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP) if ((keyP == kNone) && (cSatipDiscover::GetInstance()->GetServers()->Count() != deviceCountM)) Setup(); - if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode))) { + if ((keyP != kNone) && ((numDisabledSourcesM != oldNumDisabledSources) || (numDisabledFiltersM != oldNumDisabledFilters) || (operatingModeM != oldOperatingMode) || (ciExtensionM != oldCiExtension))) { while ((numDisabledSourcesM < oldNumDisabledSources) && (oldNumDisabledSources > 0)) disabledSourcesM[--oldNumDisabledSources] = cSource::stNone; while ((numDisabledFiltersM < oldNumDisabledFilters) && (oldNumDisabledFilters > 0)) @@ -482,6 +492,22 @@ eOSState cSatipPluginSetup::ProcessKey(eKeys keyP) return state; } +void cSatipPluginSetup::StoreCicams(const char *nameP, int *cicamsP) +{ + cString buffer = ""; + int n = 0; + for (int i = 0; i < MAX_CICAM_COUNT; ++i) { + if (cicamsP[i] < 0) + break; + if (n++ > 0) + buffer = cString::sprintf("%s %d", *buffer, cicamsP[i]); + else + buffer = cString::sprintf("%d", cicamsP[i]); + } + debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer); + SetupStore(nameP, *buffer); +} + void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP) { cString buffer = ""; @@ -494,7 +520,7 @@ void cSatipPluginSetup::StoreSources(const char *nameP, int *sourcesP) else buffer = cString::sprintf("%s", *cSource::ToString(sourcesP[i])); } - debug1("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer); + debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer); SetupStore(nameP, *buffer); } @@ -510,7 +536,7 @@ void cSatipPluginSetup::StoreFilters(const char *nameP, int *valuesP) else buffer = cString::sprintf("%d", valuesP[i]); } - debug1("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer); + debug3("%s (%s, %s)", __PRETTY_FUNCTION__, nameP, *buffer); SetupStore(nameP, *buffer); } @@ -520,12 +546,15 @@ void cSatipPluginSetup::Store(void) SetupStore("OperatingMode", operatingModeM); SetupStore("EnableCIExtension", ciExtensionM); SetupStore("EnableEITScan", eitScanM); + StoreCicams("CICAM", cicamsM); StoreSources("DisabledSources", disabledSourcesM); StoreFilters("DisabledFilters", disabledFilterIndexesM); // Update global config SatipConfig.SetOperatingMode(operatingModeM); SatipConfig.SetCIExtension(ciExtensionM); SatipConfig.SetEITScan(eitScanM); + for (int i = 0; i < MAX_CICAM_COUNT; ++i) + SatipConfig.SetCICAM(i, cicamsM[i]); for (int i = 0; i < MAX_DISABLED_SOURCES_COUNT; ++i) SatipConfig.SetDisabledSources(i, disabledSourcesM[i]); for (int i = 0; i < SECTION_FILTER_TABLE_SIZE; ++i) diff --git a/setup.h b/setup.h index 8d4b986..f2489da 100644 --- a/setup.h +++ b/setup.h @@ -19,6 +19,8 @@ private: int operatingModeM; const char *operatingModeTextsM[cSatipConfig::eOperatingModeCount]; int ciExtensionM; + int cicamsM[MAX_CICAM_COUNT]; + const char *cicamTextsM[CA_SYSTEMS_TABLE_SIZE]; int eitScanM; int numDisabledSourcesM; int disabledSourcesM[MAX_DISABLED_SOURCES_COUNT]; @@ -32,6 +34,7 @@ private: eOSState ShowDeviceStatus(void); eOSState ShowInfo(void); void Setup(void); + void StoreCicams(const char *nameP, int *cicamsP); void StoreSources(const char *nameP, int *sourcesP); void StoreFilters(const char *nameP, int *valuesP);