From a0c759a9878d806c470c4a849723e5448e722ab7 Mon Sep 17 00:00:00 2001 From: Christophe Massiot Date: Sun, 20 Mar 2011 18:34:30 +0000 Subject: [PATCH] * dvb/si.h: Add handling of service list, linkage and private data specifier descriptors, as well as EICTA's LCN and HD_SIMULCAST_LCN. * dvb/si_print.h: Store the last private data specifier and use it to call the private print functions. --- dvb/si.h | 225 ++++++++++++++++++++++++++++++++++++++++++++++++- dvb/si_print.h | 38 +++++++++ 2 files changed, 262 insertions(+), 1 deletion(-) diff --git a/dvb/si.h b/dvb/si.h index 237729a..331c2a2 100644 --- a/dvb/si.h +++ b/dvb/si.h @@ -358,6 +358,58 @@ static inline void desc40_print(const uint8_t *p_desc, free(psz_network_name); } +/***************************************************************************** + * Descriptor 0x41: Service list descriptor + *****************************************************************************/ +#define DESC41_HEADER_SIZE DESC_HEADER_SIZE +#define DESC41_SERVICE_SIZE 3 + +static inline uint8_t *desc41_get_service(uint8_t *p_desc, uint8_t n) +{ + uint8_t *p_desc_n = p_desc + DESC41_HEADER_SIZE + n * DESC41_SERVICE_SIZE; + if (p_desc_n + DESC41_SERVICE_SIZE - p_desc + > desc_get_length(p_desc) + DESC41_HEADER_SIZE) + return NULL; + return p_desc_n; +} + +static inline uint16_t desc41n_get_sid(const uint8_t *p_desc_n) +{ + return (p_desc_n[0] << 8) | p_desc_n[1]; +} + +static inline uint8_t desc41n_get_type(const uint8_t *p_desc_n) +{ + return p_desc_n[2]; +} + +static inline bool desc41_validate(const uint8_t *p_desc) +{ + return !(desc_get_length(p_desc) % DESC41_SERVICE_SIZE); +} + +static inline void desc41_print(uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + uint8_t j = 0; + uint8_t *p_desc_n; + + while ((p_desc_n = desc41_get_service(p_desc, j)) != NULL) { + j++; + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + desc41n_get_sid(p_desc_n), desc41n_get_type(p_desc_n)); + break; + default: + pf_print(opaque, + " - desc 41 service_list sid=%hu type=%hhu", + desc41n_get_sid(p_desc_n), desc41n_get_type(p_desc_n)); + } + } +} + /***************************************************************************** * Descriptor 0x43: Satellite delivery system descriptor *****************************************************************************/ @@ -736,6 +788,54 @@ static inline void desc48_print(const uint8_t *p_desc, free(psz_service); } +/***************************************************************************** + * Descriptor 0x4a: Linkage descriptor (partially implemented) + *****************************************************************************/ +#define DESC4A_HEADER_SIZE (DESC_HEADER_SIZE + 7) + +static inline uint16_t desc4a_get_tsid(const uint8_t *p_desc) +{ + return (p_desc[2] << 8) | p_desc[3]; +} + +static inline uint16_t desc4a_get_onid(const uint8_t *p_desc) +{ + return (p_desc[4] << 8) | p_desc[5]; +} + +static inline uint16_t desc4a_get_sid(const uint8_t *p_desc) +{ + return (p_desc[6] << 8) | p_desc[7]; +} + +static inline uint8_t desc4a_get_linkage(const uint8_t *p_desc) +{ + return p_desc[8]; +} + +static inline bool desc4a_validate(const uint8_t *p_desc) +{ + return desc_get_length(p_desc) >= DESC4A_HEADER_SIZE - DESC_HEADER_SIZE; +} + +static inline void desc4a_print(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "", + desc4a_get_tsid(p_desc), desc4a_get_onid(p_desc), + desc4a_get_sid(p_desc), desc4a_get_linkage(p_desc)); + break; + default: + pf_print(opaque, + " - desc 4a linkage tsid=%hu onid=%hu sid=%hu linkage=%hhu", + desc4a_get_tsid(p_desc), desc4a_get_onid(p_desc), + desc4a_get_sid(p_desc), desc4a_get_linkage(p_desc)); + } +} + /***************************************************************************** * Descriptor 0x56: Teletext descriptor *****************************************************************************/ @@ -1003,10 +1103,45 @@ static inline void desc5a_print(const uint8_t *p_desc, f_print pf_print, } } +/***************************************************************************** + * Descriptor 0x5f: Private data specifier descriptor + *****************************************************************************/ +#define DESC5F_HEADER_SIZE (DESC_HEADER_SIZE + 4) + +static inline void desc5f_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x5f); +} + +static inline uint32_t desc5f_get_specifier(const uint8_t *p_desc) +{ + return (p_desc[2] << 24) | (p_desc[3] << 16) | + (p_desc[4] << 8) | p_desc[5]; +} + +static inline bool desc5f_validate(const uint8_t *p_desc) +{ + return desc_get_length(p_desc) >= DESC5F_HEADER_SIZE - DESC_HEADER_SIZE; +} + +static inline void desc5f_print(const uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, "", + desc5f_get_specifier(p_desc)); + break; + default: + pf_print(opaque, " - desc 5f private data specifier=%u", + desc5f_get_specifier(p_desc)); + } +} + /***************************************************************************** * Descriptor 0x6a: AC-3 descriptor *****************************************************************************/ -#define DESC6A_HEADER_SIZE 3 +#define DESC6A_HEADER_SIZE (DESC_HEADER_SIZE + 1) static inline void desc6a_init(uint8_t *p_desc) { @@ -1035,6 +1170,94 @@ static inline void desc6a_print(const uint8_t *p_desc, f_print pf_print, } } +/***************************************************************************** + * Descriptor 0x83: Logical channel descriptor (IEC/CENELEC 62 216) + * Only valid if a private data specifier descriptor 28 is present before. + *****************************************************************************/ +#define DESC83P28_HEADER_SIZE DESC_HEADER_SIZE +#define DESC83P28_SERVICE_SIZE 4 + +static inline void desc83p28_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x83); +} + +static inline uint8_t *desc83p28_get_service(uint8_t *p_desc, uint8_t n) +{ + uint8_t *p_desc_n = p_desc + DESC83P28_HEADER_SIZE + + n * DESC83P28_SERVICE_SIZE; + if (p_desc_n + DESC83P28_SERVICE_SIZE - p_desc + > desc_get_length(p_desc) + DESC83P28_HEADER_SIZE) + return NULL; + return p_desc_n; +} + +static inline uint16_t desc83p28n_get_sid(const uint8_t *p_desc_n) +{ + return (p_desc_n[0] << 8) | p_desc_n[1]; +} + +static inline bool desc83p28n_get_visible(const uint8_t *p_desc_n) +{ + return !!(p_desc_n[2] & 0x80); +} + +static inline uint16_t desc83p28n_get_lcn(const uint8_t *p_desc_n) +{ + return ((p_desc_n[2] & 0x3) << 8) | p_desc_n[3]; +} + +static inline bool desc83p28_validate(const uint8_t *p_desc) +{ + return !(desc_get_length(p_desc) % DESC83P28_SERVICE_SIZE); +} + +static inline void desc83p28_print(uint8_t *p_desc, f_print pf_print, + void *opaque, print_type_t i_print_type) +{ + uint8_t j = 0; + uint8_t *p_desc_n; + + while ((p_desc_n = desc83p28_get_service(p_desc, j)) != NULL) { + j++; + switch (i_print_type) { + case PRINT_XML: + pf_print(opaque, + "<%s sid=\"%hu\" visible=\"%d\" lcn=\"%hu\" />", + desc_get_tag(p_desc) == 0x88 ? "HD_SIMULCAST_LCN_DESC" : "LCN_DESC", + desc83p28n_get_sid(p_desc_n), + desc83p28n_get_visible(p_desc_n) ? 1 : 0, + desc83p28n_get_lcn(p_desc_n)); + break; + default: + pf_print(opaque, + " - desc %hhu lcn sid=%hu%s lcn=%hu", desc_get_tag(p_desc), + desc83p28n_get_sid(p_desc_n), + desc83p28n_get_visible(p_desc_n) ? " visible" : "", + desc83p28n_get_lcn(p_desc_n)); + } + } +} + +/***************************************************************************** + * Descriptor 0x88: HD simulcast logical channel descriptor (IEC/CENELEC 62 216) + * Only valid if a private data specifier descriptor 28 is present before. + *****************************************************************************/ +#define DESC88P28_HEADER_SIZE DESC83P28_HEADER_SIZE +#define DESC88P28_SERVICE_SIZE DESC83P28_SERVICE_SIZE + +static inline void desc88p28_init(uint8_t *p_desc) +{ + desc_set_tag(p_desc, 0x88); +} + +#define desc88p28_get_service desc83p28_get_service +#define desc88p28_get_sid desc83p28_get_sid +#define desc88p28_get_visible desc83p28_get_visible +#define desc88p28_get_lcn desc83p28_get_lcn +#define desc88p28_validate desc83p28_validate +#define desc88p28_print desc83p28_print + /***************************************************************************** * Network Information Table *****************************************************************************/ diff --git a/dvb/si_print.h b/dvb/si_print.h index 66161d4..f0b02d9 100644 --- a/dvb/si_print.h +++ b/dvb/si_print.h @@ -39,6 +39,7 @@ static inline void descs_print(uint8_t *p_descs, { uint16_t j = 0; uint8_t *p_desc; + uint32_t i_private_data_specifier = 0; while ((p_desc = descs_get_desc(p_descs, j)) != NULL) { uint8_t i_tag = desc_get_tag(p_desc); @@ -46,6 +47,29 @@ static inline void descs_print(uint8_t *p_descs, desc_print_begin(p_desc, pf_print, print_opaque, i_print_type); + if (i_private_data_specifier == 0x28) { + /* EICTA */ + switch (i_tag) { +#define CASE_DESC(id) \ + case 0x##id: \ + if (desc##id##p28_validate(p_desc)) \ + desc##id##p28_print(p_desc, pf_print, print_opaque, \ + i_print_type); \ + else \ + desc_print_error(p_desc, pf_print, print_opaque, \ + i_print_type); \ + goto print_end; + + CASE_DESC(83) + CASE_DESC(88) + +#undef CASE_DESC + + default: + break; + } + } + switch (i_tag) { #define CASE_DESC(id) \ case 0x##id: \ @@ -71,20 +95,34 @@ static inline void descs_print(uint8_t *p_descs, CASE_DESC(09) CASE_DESC(0a) CASE_DESC_ICONV(40) + CASE_DESC(41) CASE_DESC(43) CASE_DESC(44) CASE_DESC(46) CASE_DESC_ICONV(48) + CASE_DESC(4a) CASE_DESC(56) CASE_DESC(59) CASE_DESC(5a) CASE_DESC(6a) +#undef CASE_DESC +#undef CASE_DESC_ICONV + + case 0x5f: + if (desc5f_validate(p_desc)) { + desc5f_print(p_desc, pf_print, print_opaque, i_print_type); + i_private_data_specifier = desc5f_get_specifier(p_desc); + } else + desc_print_error(p_desc, pf_print, print_opaque, i_print_type); + break; + default: desc_print(p_desc, pf_print, print_opaque, i_print_type); break; } +print_end: desc_print_end(p_desc, pf_print, print_opaque, i_print_type); } }