diff options
author | Martin Kaiser <wireshark@kaiser.cx> | 2012-09-10 21:09:34 +0000 |
---|---|---|
committer | Martin Kaiser <wireshark@kaiser.cx> | 2012-09-10 21:09:34 +0000 |
commit | 4e2268aaa47d682cddd691ffe528196ac0232755 (patch) | |
tree | 4d22010bdcdbed1dbea2f784e53035e137f02cb7 /epan/dissectors/packet-mpeg-descriptor.c | |
parent | 1f34b3204094d13a81cf6c33dd3f3b6808a60639 (diff) |
function to dissect a sequence of mpeg/dvb descriptors
(such descriptor loops are part of all psi and si tables)
take into account that a private data specifier descriptor may set the
context for interpretation of subsequent descriptors in the loop
as a first example, add the private descriptors defined by CI+ LLP
svn path=/trunk/; revision=44856
Diffstat (limited to 'epan/dissectors/packet-mpeg-descriptor.c')
-rw-r--r-- | epan/dissectors/packet-mpeg-descriptor.c | 212 |
1 files changed, 211 insertions, 1 deletions
diff --git a/epan/dissectors/packet-mpeg-descriptor.c b/epan/dissectors/packet-mpeg-descriptor.c index 991721ae63..78c9e7316f 100644 --- a/epan/dissectors/packet-mpeg-descriptor.c +++ b/epan/dissectors/packet-mpeg-descriptor.c @@ -1912,6 +1912,17 @@ proto_mpeg_descriptor_dissect_terrestrial_delivery(tvbuff_t *tvb, guint offset, /* 0x5F Private Data Specifier */ static int hf_mpeg_descr_private_data_specifier_id = -1; +#define PRIVATE_DATA_SPECIFIER_RESERVED 0x00000000 +#define PRIVATE_DATA_SPECIFIER_CIPLUS_LLP 0x00000040 + +static const value_string mpeg_descr_data_specifier_id_vals[] = { + { PRIVATE_DATA_SPECIFIER_RESERVED, "reserved" }, + { PRIVATE_DATA_SPECIFIER_CIPLUS_LLP, "CI+ LLP" }, + /* See dvbservices.com for complete and current list */ + + { 0, NULL } +}; + static void proto_mpeg_descriptor_dissect_private_data_specifier(tvbuff_t *tvb, guint offset, proto_tree *tree) { @@ -2399,6 +2410,97 @@ proto_mpeg_descriptor_dissect_rcs_content(tvbuff_t *tvb, guint offset, guint8 le } } +/* Private descriptors + these functions replace proto_mpeg_descriptor_dissect(), they get to see the whole descriptor */ + +/* 0xCB CI+ Content Label Descriptor */ +static int hf_mpeg_descr_ciplus_cl_cb_min = -1; +static int hf_mpeg_descr_ciplus_cl_cb_max = -1; +static int hf_mpeg_descr_ciplus_cl_lang = -1; +static int hf_mpeg_descr_ciplus_cl_label = -1; + +/* 0xCC CI+ Service Descriptor */ +static int hf_mpeg_descr_ciplus_svc_id = -1; +static int hf_mpeg_descr_ciplus_svc_type = -1; +static int hf_mpeg_descr_ciplus_svc_visible = -1; +static int hf_mpeg_descr_ciplus_svc_selectable = -1; +static int hf_mpeg_descr_ciplus_svc_lcn = -1; +static int hf_mpeg_descr_ciplus_svc_prov_name = -1; +static int hf_mpeg_descr_ciplus_svc_name = -1; + +static const value_string mpeg_descriptor_ciplus_tag_vals[] = { + /* From CI+ 1.3.1 */ + { 0xCB, "CI+ Content Label Descriptor" }, + { 0xCC, "CI+ Service Descriptor" }, + { 0x00, NULL} +}; + +static guint +proto_mpeg_descriptor_dissect_private_ciplus(tvbuff_t *tvb, guint offset, proto_tree *tree) +{ + guint offset_start; + guint8 tag, len; + const gchar *tag_str; + proto_item *di; + proto_tree *descriptor_tree; + guint8 str_len_byte; + + offset_start=offset; + + tag = tvb_get_guint8(tvb, offset); + tag_str = match_strval(tag, mpeg_descriptor_ciplus_tag_vals); + if (!tag_str) + return 0; + + di = proto_tree_add_text(tree, tvb, offset_start, -1, "CI+ private descriptor Tag=0x%02x", tag); + descriptor_tree = proto_item_add_subtree(di, ett_mpeg_descriptor); + + proto_tree_add_uint_format(descriptor_tree, hf_mpeg_descriptor_tag, tvb, offset, 1, tag, "Descriptor Tag: %s (0x%x)", tag_str, tag); + offset++; + + len = tvb_get_guint8(tvb, offset); + proto_tree_add_item(descriptor_tree, hf_mpeg_descriptor_length, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + if (tag==0xCB) { + proto_tree_add_item(tree, hf_mpeg_descr_ciplus_cl_cb_min, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(tree, hf_mpeg_descr_ciplus_cl_cb_max, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(tree, hf_mpeg_descr_ciplus_cl_lang, tvb, offset, 3, ENC_BIG_ENDIAN); + offset += 3; + + proto_tree_add_item(tree, hf_mpeg_descr_ciplus_cl_label, tvb, offset, len-offset, ENC_BIG_ENDIAN); + offset += len-offset; + } + else if (tag==0xCC) { + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_id, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_type, tvb, offset, 1, ENC_BIG_ENDIAN); + offset++; + + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_visible, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_selectable, tvb, offset, 2, ENC_BIG_ENDIAN); + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_lcn, tvb, offset, 2, ENC_BIG_ENDIAN); + offset += 2; + + str_len_byte = tvb_get_guint8(tvb, offset); + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_prov_name, tvb, offset, 1, ENC_ASCII|ENC_NA); + offset += 1+str_len_byte; + + str_len_byte = tvb_get_guint8(tvb, offset); + proto_tree_add_item(descriptor_tree, hf_mpeg_descr_ciplus_svc_name, tvb, offset, 1, ENC_ASCII|ENC_NA); + offset += 1+str_len_byte; + } + + proto_item_set_len(di, offset-offset_start); + return offset-offset_start; +} + + /* Common dissector */ guint @@ -2557,6 +2659,57 @@ proto_mpeg_descriptor_dissect(tvbuff_t *tvb, guint offset, proto_tree *tree) } +/* dissect a descriptor loop consisting of one or more descriptors + take into account the contexts defined a private data specifier descriptors */ +guint +proto_mpeg_descriptor_loop_dissect(tvbuff_t *tvb, guint offset, guint loop_len, proto_tree *tree) +{ + /* we use the reserved value to indicate that no private context is active */ + guint32 private_data_specifier = PRIVATE_DATA_SPECIFIER_RESERVED; + guint offset_start; + guint desc_len; + guint8 tag; + + offset_start = offset; + + while (offset-offset_start < loop_len) { + /* don't increment offset in our pre-checks */ + tag = tvb_get_guint8(tvb, offset); + if (tag==0x5F) { + /* we have a private data specifier descriptor: get the private data specifier */ + /* offset+1 is length byte, offset+2 is start of payload */ + private_data_specifier = tvb_get_ntohl(tvb, offset+2); + } + + /* the default descriptor function takes precedence + however, if it does not know the current descriptor, we search for a context-specific subfunction + this subfunction gets to see the entire descriptor, including tag and len */ + if (match_strval(tag, mpeg_descriptor_tag_vals)) { + desc_len = proto_mpeg_descriptor_dissect(tvb, offset, tree); + } + else { + switch (private_data_specifier) { + case PRIVATE_DATA_SPECIFIER_CIPLUS_LLP: + desc_len = proto_mpeg_descriptor_dissect_private_ciplus(tvb, offset, tree); + break; + default: + desc_len = 0; + break; + } + if (desc_len==0) { + /* either there was no subfunction or it could not handle the descriptor + fall back to the default (which will dissect it as unknown) */ + desc_len = proto_mpeg_descriptor_dissect(tvb, offset, tree); + } + } + + offset += desc_len; + } + + return offset-offset_start; +} + + void proto_register_mpeg_descriptor(void) { @@ -3502,7 +3655,7 @@ proto_register_mpeg_descriptor(void) /* 0x5F Private Data Specifier */ { &hf_mpeg_descr_private_data_specifier_id, { "Private Data Specifier", "mpeg_descr.private_data_specifier.id", - FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL + FT_UINT32, BASE_HEX, VALS(mpeg_descr_data_specifier_id_vals), 0, NULL, HFILL } }, /* 0x64 Data Broadcast Descriptor */ @@ -3825,6 +3978,63 @@ proto_register_mpeg_descriptor(void) { &hf_mpeg_descr_rcs_content_table_id, { "Table ID", "mpeg_descr.rcs_content.tid", FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } }, + + /* 0xCB CI+ Content Label Descriptor */ + { &hf_mpeg_descr_ciplus_cl_cb_min, { + "Content byte minimum value", "mpeg_descr.ciplus_content_label.content_byte_min", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_cl_cb_max, { + "Content byte maximum value", "mpeg_descr.ciplus_content_label.content_byte_max", + FT_UINT8, BASE_HEX, NULL, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_cl_lang, { + "ISO 639 language code", "mpeg_descr.ciplus_content_label.lang_code", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_cl_label, { + "Content label", "mpeg_descr.ciplus_content_label.label", + FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL + } }, + + /* 0xCC CI+ Service Descriptor */ + { &hf_mpeg_descr_ciplus_svc_id, { + "Service ID", "mpeg_descr.ciplus_svc.id", + FT_UINT16, BASE_HEX, NULL, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_type, { + "Service type", "mpeg_descr.ciplus_svc.type", + FT_UINT8, BASE_HEX | BASE_EXT_STRING, &mpeg_descr_service_type_vals_ext, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_visible, { + "Visible Service Flag", "mpeg_descr.ciplus_svc.visible", + FT_UINT16, BASE_HEX, NULL, 0x8000, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_selectable, { + "Selectable Service Flag", "mpeg_descr.ciplus_svc.selectable", + FT_UINT16, BASE_HEX, NULL, 0x4000, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_lcn, { + "Logical Channel Number", "mpeg_descr.ciplus_svc.lcn", + FT_UINT16, BASE_HEX, NULL, 0x3FFF, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_prov_name, { + "Service Provider Name", "mpeg_descr.ciplus_svc.provider_name", + FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL + } }, + + { &hf_mpeg_descr_ciplus_svc_name, { + "Service Name", "mpeg_descr.ciplus_svc.name", + FT_UINT_STRING, BASE_NONE, NULL, 0, NULL, HFILL } } }; |