From 0360110bfb7320f3310737b6b75da5f8cd96edb9 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 30 Sep 2016 16:13:12 +0200 Subject: Move FIG0 structures to separate file --- src/fig/FIG0.h | 319 +-------------------------------------------------------- 1 file changed, 1 insertion(+), 318 deletions(-) (limited to 'src/fig/FIG0.h') diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h index 95a8a85..25aea15 100644 --- a/src/fig/FIG0.h +++ b/src/fig/FIG0.h @@ -23,8 +23,7 @@ along with ODR-DabMux. If not, see . */ -#ifndef __FIG0_H_ -#define __FIG0_H_ +#pragma once #include #include @@ -280,321 +279,5 @@ class FIG0_19 : public IFIG std::shared_ptr,int> m_disabled_announcements; }; -#ifdef _WIN32 -# pragma pack(push) -#endif - -struct FIGtype0 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIGtype0_0 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint16_t EId; - uint8_t CIFcnt_hight:5; - uint8_t Al:1; - uint8_t Change:2; - uint8_t CIFcnt_low:8; -} PACKED; - - -struct FIGtype0_2 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIGtype0_2_Service { - uint16_t SId; - uint8_t NbServiceComp:4; - uint8_t CAId:3; - uint8_t Local_flag:1; -} PACKED; - - -struct FIGtype0_2_Service_data { - uint32_t SId; - uint8_t NbServiceComp:4; - uint8_t CAId:3; - uint8_t Local_flag:1; -} PACKED; - - -struct FIGtype0_2_audio_component { - uint8_t ASCTy:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SubChId:6; -} PACKED; - - -struct FIGtype0_2_data_component { - uint8_t DSCTy:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SubChId:6; -} PACKED; - - -struct FIGtype0_2_packet_component { - uint8_t SCId_high:6; - uint8_t TMid:2; - uint8_t CA_flag:1; - uint8_t PS:1; - uint8_t SCId_low:6; - void setSCId(uint16_t SCId) { - SCId_high = SCId >> 6; - SCId_low = SCId & 0x3f; - } -} PACKED; - - -/* Warning: When bit SCCA_flag is unset(0), the multiplexer R&S does not send - * the SCCA field. But, in the Factum ETI analyzer, if this field is not there, - * it is an error. - */ -struct FIGtype0_3 { - uint8_t SCId_high; - uint8_t SCCA_flag:1; - uint8_t rfa:3; - uint8_t SCId_low:4; - uint8_t DSCTy:6; - uint8_t rfu:1; - uint8_t DG_flag:1; - uint8_t Packet_address_high:2; - uint8_t SubChId:6; - uint8_t Packet_address_low; - uint16_t SCCA; - void setSCId(uint16_t SCId) { - SCId_high = SCId >> 4; - SCId_low = SCId & 0xf; - } - void setPacketAddress(uint16_t address) { - Packet_address_high = address >> 8; - Packet_address_low = address & 0xff; - } -} PACKED; - -struct FIGtype0_5_short { - uint8_t SubChId:6; - uint8_t rfu:1; - uint8_t LS:1; - - uint8_t language; -} PACKED; - -struct FIGtype0_8_short { - uint8_t SCIdS:4; - uint8_t rfa_1:3; - uint8_t ext:1; - uint8_t Id:6; - uint8_t MscFic:1; - uint8_t LS:1; - uint8_t rfa_2; -} PACKED; - - -struct FIGtype0_8_long { - uint8_t SCIdS:4; - uint8_t rfa_1:3; - uint8_t ext:1; - uint8_t SCId_high:4; - uint8_t rfa:3; - uint8_t LS:1; - uint8_t SCId_low; - uint8_t rfa_2; - void setSCId(uint16_t id) { - SCId_high = id >> 8; - SCId_low = id & 0xff; - } - uint16_t getSCid() { - return (SCId_high << 8) | SCId_low; - } -} PACKED; - - -struct FIGtype0_9 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint8_t ensembleLto:6; - uint8_t rfa1:1; - uint8_t ext:1; - uint8_t ensembleEcc; - uint8_t tableId; -} PACKED; - - -struct FIGtype0_10_LongForm { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; - - uint8_t MJD_high:7; - uint8_t RFU:1; - - uint8_t MJD_med; - - uint8_t Hours_high:3; - uint8_t UTC:1; - uint8_t ConfInd:1; - uint8_t LSI:1; - uint8_t MJD_low:2; - - uint8_t Minutes:6; - uint8_t Hours_low:2; - - uint8_t Milliseconds_high:2; - uint8_t Seconds:6; - - uint8_t Milliseconds_low; - - void setMJD(uint32_t date) { - MJD_high = (date >> 10) & 0x7f; - MJD_med = (date >> 2) & 0xff; - MJD_low = date & 0x03; - } - void setHours(uint16_t hours) { - Hours_high = (hours >> 2) & 0x07; - Hours_low = hours & 0x03; - } - - void setMilliseconds(uint16_t ms) { - Milliseconds_high = (ms >> 8) & 0x03; - Milliseconds_low = ms & 0xFF; - } -} PACKED; - - -struct FIGtype0_17 { - uint16_t SId; - - uint8_t rfa2_high:4; - uint8_t rfu1:2; - uint8_t rfa1:1; - uint8_t SD:1; // Static/Dynamic - - uint8_t IntCode:5; - uint8_t rfu2:1; - uint8_t rfa2_low:2; -} PACKED; - -struct FIGtype0_18 { - uint16_t SId; - uint16_t ASu; - uint8_t NumClusters:5; - uint8_t Rfa:3; - /* Followed by uint8_t Cluster IDs */ -} PACKED; - -struct FIGtype0_19 { - uint8_t ClusterId; - uint16_t ASw; - uint8_t SubChId:6; - uint8_t RegionFlag:1; // shall be zero - uint8_t NewFlag:1; - // Region and RFa not supported -} PACKED; - -struct FIGtype0_1 { - uint8_t Length:5; - uint8_t FIGtypeNumber:3; - uint8_t Extension:5; - uint8_t PD:1; - uint8_t OE:1; - uint8_t CN:1; -} PACKED; - - -struct FIG_01_SubChannel_ShortF { - uint8_t StartAdress_high:2; - uint8_t SubChId:6; - uint8_t StartAdress_low:8; - uint8_t TableIndex:6; - uint8_t TableSwitch:1; - uint8_t Short_Long_form:1; -} PACKED; - - -struct FIG_01_SubChannel_LongF { - uint8_t StartAdress_high:2; - uint8_t SubChId:6; - uint8_t StartAdress_low:8; - uint8_t Sub_ChannelSize_high:2; - uint8_t ProtectionLevel:2; - uint8_t Option:3; - uint8_t Short_Long_form:1; - uint8_t Sub_ChannelSize_low:8; -} PACKED; - - -// See EN 300 401, Clause 8.1.20 for the FIG0_13 description -struct FIG0_13_shortAppInfo { - uint16_t SId; - uint8_t No:4; - uint8_t SCIdS:4; -} PACKED; - - -struct FIG0_13_longAppInfo { - uint32_t SId; - uint8_t No:4; - uint8_t SCIdS:4; -} PACKED; - - -struct FIG0_13_app { - uint8_t typeHigh; - uint8_t length:5; - uint8_t typeLow:3; - void setType(uint16_t type) { - typeHigh = type >> 3; - typeLow = type & 0x1f; - } - uint16_t xpad; -} PACKED; - -#define FIG0_13_APPTYPE_SLIDESHOW 0x2 -#define FIG0_13_APPTYPE_WEBSITE 0x3 -#define FIG0_13_APPTYPE_TPEG 0x4 -#define FIG0_13_APPTYPE_DGPS 0x5 -#define FIG0_13_APPTYPE_TMC 0x6 -#define FIG0_13_APPTYPE_EPG 0x7 -#define FIG0_13_APPTYPE_DABJAVA 0x8 -#define FIG0_13_APPTYPE_JOURNALINE 0x441 - - -#ifdef _WIN32 -# pragma pack(pop) -#endif - } // namespace FIC -#endif // __FIG0_H_ - -- cgit v1.2.3 From f198d1a2c799c97fe1e4e92e110cc0782f6f7880 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Fri, 30 Sep 2016 17:10:43 +0200 Subject: Add some FIG0/6 structures and skeleton --- src/fig/FIG0.cpp | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/fig/FIG0.h | 28 +++++++++++++++++++++ src/fig/FIG0structs.h | 19 ++++++++++++++ 3 files changed, 116 insertions(+) (limited to 'src/fig/FIG0.h') diff --git a/src/fig/FIG0.cpp b/src/fig/FIG0.cpp index bb08fac..b560e4c 100644 --- a/src/fig/FIG0.cpp +++ b/src/fig/FIG0.cpp @@ -662,6 +662,75 @@ FillStatus FIG0_5::fill(uint8_t *buf, size_t max_size) return fs; } +//=========== FIG 0/6 =========== + +FIG0_6::FIG0_6(FIGRuntimeInformation *rti) : + m_rti(rti), + m_initialised(false) +{ +} + +FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) +{ + FillStatus fs; + ssize_t remaining = max_size; + auto ensemble = m_rti->ensemble; + + if (not m_initialised) { + linkageSetFIG0_6 = m_rti->ensemble->linkagesets.end(); + m_initialised = true; + } + + FIGtype0* fig0 = NULL; + + for (; linkageSetFIG0_6 != ensemble->linkagesets.end(); + ++linkageSetFIG0_6) { + + const int required_size = 2; + + if (fig0 == NULL) { + if (remaining < 2 + required_size) { + break; + } + fig0 = (FIGtype0*)buf; + fig0->FIGtypeNumber = 0; + fig0->Length = 1; + fig0->CN = 0; + fig0->OE = 0; + fig0->PD = 0; + fig0->Extension = 5; + + buf += 2; + remaining -= 2; + } + else if (remaining < required_size) { + break; + } + + FIGtype0_6 *fig0_6 = (FIGtype0_6*)buf; + + fig0_6->IdListFlag = 1; + fig0_6->LA = (*linkageSetFIG0_6)->active; + fig0_6->SH = (*linkageSetFIG0_6)->hard; + fig0_6->ILS = (*linkageSetFIG0_6)->international; + fig0_6->LSN = (*linkageSetFIG0_6)->lsn; + +#error "handle FIG insertion and CEI properly" + + fig0->Length += 2; + buf += 2; + remaining -= 2; + } + + if (linkageSetFIG0_6 == ensemble->linkagesets.end()) { + linkageSetFIG0_6 = ensemble->linkagesets.begin(); + fs.complete_fig_transmitted = true; + } + + fs.num_bytes_written = max_size - remaining; + return fs; +} + //=========== FIG 0/8 =========== FIG0_8::FIG0_8(FIGRuntimeInformation *rti) : diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h index 25aea15..5a8a69f 100644 --- a/src/fig/FIG0.h +++ b/src/fig/FIG0.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "fig/FIG.h" @@ -135,6 +136,33 @@ class FIG0_5 : public IFIG std::vector::iterator componentFIG0_5; }; +// FIG type 0/6 +// Service Linking +// +// This feature shall use the SIV signalling (see clause 5.2.2.1). The database +// shall be divided by use of a database key. Changes to the database shall be +// signalled using the CEI. The first service in the list of services in each +// part of the database, as divided by the database key, shall be a service +// carried in the ensemble. This service is called the key service. +// +// The database key comprises the OE and P/D flags and the S/H, ILS, and LSN +// fields. +class FIG0_6 : public IFIG +{ + public: + FIG0_6(FIGRuntimeInformation* rti); + virtual FillStatus fill(uint8_t *buf, size_t max_size); + virtual FIG_rate repetition_rate(void) { return FIG_rate::E; } + + virtual const int figtype(void) const { return 0; } + virtual const int figextension(void) const { return 6; } + + private: + FIGRuntimeInformation *m_rti; + bool m_initialised; + std::list >::iterator linkageSetFIG0_6; +}; + // FIG type 0/8 // The Extension 8 of FIG type 0 (FIG 0/8) provides information to link // together the service component description that is valid within the ensemble diff --git a/src/fig/FIG0structs.h b/src/fig/FIG0structs.h index a1e79d3..4b9b7e0 100644 --- a/src/fig/FIG0structs.h +++ b/src/fig/FIG0structs.h @@ -152,6 +152,25 @@ struct FIGtype0_5_short { uint8_t language; } PACKED; +struct FIGtype0_6 { + uint16_t IdListFlag:1; + uint16_t LA:1; // Linkage actuator + uint16_t SH:1; // 0=Soft link / 1=Hard link + uint16_t ILS:1; // 0=national / 1=international + uint16_t LSN:12; // Linkage Set Number +} PACKED; + +#define FIG0_6_IDLQ_DAB 0x0 +#define FIG0_6_IDLQ_RDS 0x1 +#define FIG0_6_IDLQ_DRM_AMSS 0x3 + +struct FIGtype0_6_header { + uint8_t rfu:1; // must be 0 + uint8_t IdLQ:2; // Identifier List Qualifier, see above defines + uint8_t rfa:1; // must be 0 + uint8_t num_ids:4; // number of Ids to follow in the list +} PACKED; + struct FIGtype0_8_short { uint8_t SCIdS:4; uint8_t rfa_1:3; -- cgit v1.2.3 From b78139a2fe6ee76bcb85b240733bf803c5430286 Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Sun, 2 Oct 2016 12:29:20 +0200 Subject: Add some WIP for FIG0/6 --- src/MuxElements.h | 2 +- src/fig/FIG0.cpp | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++---- src/fig/FIG0.h | 22 ++++++++++ 3 files changed, 136 insertions(+), 9 deletions(-) (limited to 'src/fig/FIG0.h') diff --git a/src/MuxElements.h b/src/MuxElements.h index 8285e61..2f602ba 100644 --- a/src/MuxElements.h +++ b/src/MuxElements.h @@ -452,7 +452,7 @@ class LinkageSet : public RemoteControllable { bool hard; bool international; - std::string keyservice; + std::string keyservice; // TODO replace by pointer to service private: /* Remote control */ diff --git a/src/fig/FIG0.cpp b/src/fig/FIG0.cpp index b560e4c..1e179cf 100644 --- a/src/fig/FIG0.cpp +++ b/src/fig/FIG0.cpp @@ -686,7 +686,17 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) for (; linkageSetFIG0_6 != ensemble->linkagesets.end(); ++linkageSetFIG0_6) { - const int required_size = 2; + const bool PD = false; + const bool ILS = (*linkageSetFIG0_6)->international; + + // need to add key service to num_ids + const size_t num_ids = 1 + (*linkageSetFIG0_6)->id_list.size(); + + const size_t headersize = sizeof(struct FIGtype0_6_header); + const int required_size = sizeof(struct FIGtype0_6) + + (num_ids > 0 ? + headersize + (PD == 0 ? (ILS == 0 ? 2*num_ids : 3*num_ids) : 4*num_ids) : + 0); if (fig0 == NULL) { if (remaining < 2 + required_size) { @@ -697,7 +707,7 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) fig0->Length = 1; fig0->CN = 0; fig0->OE = 0; - fig0->PD = 0; + fig0->PD = PD; fig0->Extension = 5; buf += 2; @@ -709,17 +719,112 @@ FillStatus FIG0_6::fill(uint8_t *buf, size_t max_size) FIGtype0_6 *fig0_6 = (FIGtype0_6*)buf; - fig0_6->IdListFlag = 1; + fig0_6->IdListFlag = (num_ids > 0); fig0_6->LA = (*linkageSetFIG0_6)->active; fig0_6->SH = (*linkageSetFIG0_6)->hard; - fig0_6->ILS = (*linkageSetFIG0_6)->international; + fig0_6->ILS = ILS; fig0_6->LSN = (*linkageSetFIG0_6)->lsn; -#error "handle FIG insertion and CEI properly" + fig0->Length += sizeof(struct FIGtype0_6); + buf += sizeof(struct FIGtype0_6); + remaining -= sizeof(struct FIGtype0_6); - fig0->Length += 2; - buf += 2; - remaining -= 2; + if (num_ids > 0) { + FIGtype0_6_header *header = (FIGtype0_6_header*)buf; + header->rfu = 0; + if (num_ids > 0x0F) { + etiLog.log(error, "Too large number of links for linkage set 0x%04x", + (*linkageSetFIG0_6)->lsn); + throw MuxInitException(); + } + + header->IdLQ = 0; // TODO not only DAB + header->rfa = 0; + header->num_ids = num_ids; + + fig0->Length += headersize; + buf += headersize; + remaining -= headersize; + + // TODO insert key service first + const std::string keyserviceuid =(*linkageSetFIG0_6)->keyservice; + const auto& keyservice = std::find_if( + ensemble->services.begin(), + ensemble->services.end(), + [&](const std::shared_ptr srv) { + return srv->uid == keyserviceuid; + }); + + if (keyservice == ensemble->services.end()) { + etiLog.log(error, "Invalid key service %s in linkage set 0x%04x", + keyserviceuid.c_str(), (*linkageSetFIG0_6)->lsn); + throw MuxInitException(); + } + for (const auto& l : (*linkageSetFIG0_6)->id_list) { + if (l.type != ServiceLinkType::DAB) { + etiLog.log(error, "TODO only DAB links supported. (linkage set 0x%04x)", + (*linkageSetFIG0_6)->lsn); + throw MuxInitException(); + } + } + + if (not PD and not ILS) { + buf[0] = (*keyservice)->id >> 8; + buf[1] = (*keyservice)->id & 0xFF; + fig0->Length += 2; + buf += 2; + remaining -= 2; + + for (const auto& l : (*linkageSetFIG0_6)->id_list) { + buf[0] = l.id >> 8; + buf[1] = l.id & 0xFF; + fig0->Length += 2; + buf += 2; + remaining -= 2; + } + } + if (not PD and ILS) { + buf[0] = ensemble->ecc; + buf[1] = (*keyservice)->id >> 8; + buf[2] = (*keyservice)->id & 0xFF; + fig0->Length += 3; + buf += 3; + remaining -= 3; + + for (const auto& l : (*linkageSetFIG0_6)->id_list) { + buf[0] = l.ecc; + buf[1] = l.id >> 8; + buf[2] = l.id & 0xFF; + fig0->Length += 3; + buf += 3; + remaining -= 3; + } + } + else { // PD == true + // TODO if IdLQ is 11, MSB shall be zero + buf[0] = (*keyservice)->id >> 24; + buf[1] = (*keyservice)->id >> 16; + buf[2] = (*keyservice)->id >> 8; + buf[3] = (*keyservice)->id & 0xFF; + fig0->Length += 4; + buf += 4; + remaining -= 4; + + for (const auto& l : (*linkageSetFIG0_6)->id_list) { + buf[0] = l.id >> 24; + buf[1] = l.id >> 16; + buf[2] = l.id >> 8; + buf[3] = l.id & 0xFF; + fig0->Length += 4; + buf += 4; + remaining -= 4; + } + } + } + + fig0->Length += required_size; + buf += required_size; + remaining -= required_size; } if (linkageSetFIG0_6 == ensemble->linkagesets.end()) { diff --git a/src/fig/FIG0.h b/src/fig/FIG0.h index 5a8a69f..0109219 100644 --- a/src/fig/FIG0.h +++ b/src/fig/FIG0.h @@ -29,6 +29,7 @@ #include #include #include +#include #include "fig/FIG.h" @@ -163,6 +164,27 @@ class FIG0_6 : public IFIG std::list >::iterator linkageSetFIG0_6; }; +// FIG0/6 needs a change indicator, which is a short-form FIG (i.e. without the list) +// and with C/N 1. Since this has another rate, it's implemented in another class. +// +// This is signalled once per second for a period of five seconds +// (TS 103 176 5.2.4.3). +class FIG0_6_CEI : public IFIG +{ + public: + FIG0_6_CEI(FIGRuntimeInformation* rti); + virtual FillStatus fill(uint8_t *buf, size_t max_size); + virtual FIG_rate repetition_rate(void) { return FIG_rate::B; } + + virtual const int figtype(void) const { return 0; } + virtual const int figextension(void) const { return 6; } + + private: + FIGRuntimeInformation *m_rti; + bool m_initialised; + std::list >::iterator linkageSetFIG0_6; +}; + // FIG type 0/8 // The Extension 8 of FIG type 0 (FIG 0/8) provides information to link // together the service component description that is valid within the ensemble -- cgit v1.2.3