aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authoretobi <git@e-tobi.net>2013-09-03 09:48:41 +0200
committeretobi <git@e-tobi.net>2013-09-03 09:48:41 +0200
commitab959d7b4194715870128e616b8e29d4a101e488 (patch)
tree61a746231d30817be73416a7d67763fd677a1042 /lib
parent6b350466c4902c5b137e0efaf1d189128a7f18f5 (diff)
downloadlinux-dvb-apps-upstream/1.1.1+rev1207.tar.gz
Imported Upstream version 1.1.1+rev1207upstream/1.1.1+rev1207
Diffstat (limited to '')
-rw-r--r--lib/Makefile11
-rw-r--r--lib/libdvbapi/Makefile25
-rw-r--r--lib/libdvbapi/dvbaudio.c50
-rw-r--r--lib/libdvbapi/dvbaudio.h55
-rw-r--r--lib/libdvbapi/dvbca.c159
-rw-r--r--lib/libdvbapi/dvbca.h135
-rw-r--r--lib/libdvbapi/dvbdemux.c255
-rw-r--r--lib/libdvbapi/dvbdemux.h204
-rw-r--r--lib/libdvbapi/dvbfe.c574
-rw-r--r--lib/libdvbapi/dvbfe.h333
-rw-r--r--lib/libdvbapi/dvbnet.c104
-rw-r--r--lib/libdvbapi/dvbnet.h87
-rw-r--r--lib/libdvbapi/dvbvideo.c46
-rw-r--r--lib/libdvbapi/dvbvideo.h46
-rw-r--r--lib/libdvbcfg/Makefile18
-rw-r--r--lib/libdvbcfg/dvbcfg_common.c136
-rw-r--r--lib/libdvbcfg/dvbcfg_common.h37
-rw-r--r--lib/libdvbcfg/dvbcfg_scanfile.c282
-rw-r--r--lib/libdvbcfg/dvbcfg_scanfile.h61
-rw-r--r--lib/libdvbcfg/dvbcfg_zapchannel.c384
-rw-r--r--lib/libdvbcfg/dvbcfg_zapchannel.h77
-rw-r--r--lib/libdvbcfg/zapchannel.txt72
-rw-r--r--lib/libdvben50221/Makefile49
-rw-r--r--lib/libdvben50221/asn_1.c83
-rw-r--r--lib/libdvben50221/asn_1.h41
-rw-r--r--lib/libdvben50221/en50221_app_ai.c191
-rw-r--r--lib/libdvben50221/en50221_app_ai.h136
-rw-r--r--lib/libdvben50221/en50221_app_auth.c180
-rw-r--r--lib/libdvben50221/en50221_app_auth.h123
-rw-r--r--lib/libdvben50221/en50221_app_ca.c631
-rw-r--r--lib/libdvben50221/en50221_app_ca.h264
-rw-r--r--lib/libdvben50221/en50221_app_datetime.c173
-rw-r--r--lib/libdvben50221/en50221_app_datetime.h119
-rw-r--r--lib/libdvben50221/en50221_app_dvb.c282
-rw-r--r--lib/libdvben50221/en50221_app_dvb.h176
-rw-r--r--lib/libdvben50221/en50221_app_epg.c167
-rw-r--r--lib/libdvben50221/en50221_app_epg.h138
-rw-r--r--lib/libdvben50221/en50221_app_lowspeed.c533
-rw-r--r--lib/libdvben50221/en50221_app_lowspeed.h219
-rw-r--r--lib/libdvben50221/en50221_app_mmi.c1397
-rw-r--r--lib/libdvben50221/en50221_app_mmi.h618
-rw-r--r--lib/libdvben50221/en50221_app_rm.c307
-rw-r--r--lib/libdvben50221/en50221_app_rm.h187
-rw-r--r--lib/libdvben50221/en50221_app_smartcard.c296
-rw-r--r--lib/libdvben50221/en50221_app_smartcard.h200
-rw-r--r--lib/libdvben50221/en50221_app_tags.h104
-rw-r--r--lib/libdvben50221/en50221_app_teletext.c141
-rw-r--r--lib/libdvben50221/en50221_app_teletext.h107
-rw-r--r--lib/libdvben50221/en50221_app_utils.c38
-rw-r--r--lib/libdvben50221/en50221_app_utils.h112
-rw-r--r--lib/libdvben50221/en50221_errno.h49
-rw-r--r--lib/libdvben50221/en50221_session.c1055
-rw-r--r--lib/libdvben50221/en50221_session.h232
-rw-r--r--lib/libdvben50221/en50221_stdcam.c54
-rw-r--r--lib/libdvben50221/en50221_stdcam.h102
-rw-r--r--lib/libdvben50221/en50221_stdcam_hlci.c216
-rw-r--r--lib/libdvben50221/en50221_stdcam_llci.c437
-rw-r--r--lib/libdvben50221/en50221_transport.c1296
-rw-r--r--lib/libdvben50221/en50221_transport.h234
-rw-r--r--lib/libdvbmisc/dvbmisc.h72
-rw-r--r--lib/libdvbsec/Makefile17
-rw-r--r--lib/libdvbsec/dvbsec_api.c951
-rw-r--r--lib/libdvbsec/dvbsec_api.h436
-rw-r--r--lib/libdvbsec/dvbsec_cfg.c366
-rw-r--r--lib/libdvbsec/dvbsec_cfg.h203
-rw-r--r--lib/libesg/Makefile27
-rw-r--r--lib/libesg/TODO18
-rw-r--r--lib/libesg/bootstrap/Makefile24
-rw-r--r--lib/libesg/bootstrap/access_descriptor.c115
-rw-r--r--lib/libesg/bootstrap/access_descriptor.h86
-rw-r--r--lib/libesg/bootstrap/provider_discovery_descriptor.c50
-rw-r--r--lib/libesg/bootstrap/provider_discovery_descriptor.h59
-rw-r--r--lib/libesg/encapsulation/Makefile28
-rw-r--r--lib/libesg/encapsulation/auxiliary_data.h62
-rw-r--r--lib/libesg/encapsulation/container.c206
-rw-r--r--lib/libesg/encapsulation/container.h94
-rw-r--r--lib/libesg/encapsulation/data_repository.c53
-rw-r--r--lib/libesg/encapsulation/data_repository.h59
-rw-r--r--lib/libesg/encapsulation/fragment_management_information.c118
-rw-r--r--lib/libesg/encapsulation/fragment_management_information.h96
-rw-r--r--lib/libesg/encapsulation/string_repository.c54
-rw-r--r--lib/libesg/encapsulation/string_repository.h60
-rw-r--r--lib/libesg/representation/Makefile26
-rw-r--r--lib/libesg/representation/bim_decoder_init.h40
-rw-r--r--lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h40
-rw-r--r--lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c70
-rw-r--r--lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h60
-rw-r--r--lib/libesg/representation/init_message.c112
-rw-r--r--lib/libesg/representation/init_message.h80
-rw-r--r--lib/libesg/representation/textual_decoder_init.c128
-rw-r--r--lib/libesg/representation/textual_decoder_init.h104
-rw-r--r--lib/libesg/transport/Makefile22
-rw-r--r--lib/libesg/transport/session_partition_declaration.c253
-rw-r--r--lib/libesg/transport/session_partition_declaration.h139
-rw-r--r--lib/libesg/types.c37
-rw-r--r--lib/libesg/types.h53
-rw-r--r--lib/libesg/xml/provider_discovery_descriptor.xsd22
-rw-r--r--lib/libucsi/Makefile34
-rw-r--r--lib/libucsi/atsc/Makefile55
-rw-r--r--lib/libucsi/atsc/ac3_descriptor.h112
-rw-r--r--lib/libucsi/atsc/atsc_text.c743
-rw-r--r--lib/libucsi/atsc/caption_service_descriptor.h137
-rw-r--r--lib/libucsi/atsc/component_name_descriptor.h92
-rw-r--r--lib/libucsi/atsc/content_advisory_descriptor.h235
-rw-r--r--lib/libucsi/atsc/cvct_section.c77
-rw-r--r--lib/libucsi/atsc/cvct_section.h228
-rw-r--r--lib/libucsi/atsc/dcc_arriving_request_descriptor.h107
-rw-r--r--lib/libucsi/atsc/dcc_departing_request_descriptor.h108
-rw-r--r--lib/libucsi/atsc/dccsct_section.c109
-rw-r--r--lib/libucsi/atsc/dccsct_section.h327
-rw-r--r--lib/libucsi/atsc/dcct_section.c96
-rw-r--r--lib/libucsi/atsc/dcct_section.h380
-rw-r--r--lib/libucsi/atsc/descriptor.h68
-rw-r--r--lib/libucsi/atsc/eit_section.c71
-rw-r--r--lib/libucsi/atsc/eit_section.h191
-rw-r--r--lib/libucsi/atsc/ett_section.c42
-rw-r--r--lib/libucsi/atsc/ett_section.h91
-rw-r--r--lib/libucsi/atsc/extended_channel_name_descriptor.h92
-rw-r--r--lib/libucsi/atsc/genre_descriptor.h82
-rw-r--r--lib/libucsi/atsc/mgt_section.c76
-rw-r--r--lib/libucsi/atsc/mgt_section.h215
-rw-r--r--lib/libucsi/atsc/rc_descriptor.h83
-rw-r--r--lib/libucsi/atsc/rrt_section.c108
-rw-r--r--lib/libucsi/atsc/rrt_section.h379
-rw-r--r--lib/libucsi/atsc/section.h84
-rw-r--r--lib/libucsi/atsc/service_location_descriptor.h141
-rw-r--r--lib/libucsi/atsc/stt_section.c42
-rw-r--r--lib/libucsi/atsc/stt_section.h105
-rw-r--r--lib/libucsi/atsc/stuffing_descriptor.h82
-rw-r--r--lib/libucsi/atsc/time_shifted_service_descriptor.h136
-rw-r--r--lib/libucsi/atsc/tvct_section.c81
-rw-r--r--lib/libucsi/atsc/tvct_section.h227
-rw-r--r--lib/libucsi/atsc/types.c71
-rw-r--r--lib/libucsi/atsc/types.h227
-rw-r--r--lib/libucsi/crc32.c89
-rw-r--r--lib/libucsi/crc32.h58
-rw-r--r--lib/libucsi/descriptor.h129
-rw-r--r--lib/libucsi/dvb/Makefile121
-rw-r--r--lib/libucsi/dvb/ac3_descriptor.h88
-rw-r--r--lib/libucsi/dvb/adaptation_field_data_descriptor.h62
-rw-r--r--lib/libucsi/dvb/ait_application_descriptor.h204
-rw-r--r--lib/libucsi/dvb/ait_application_icons_descriptor.h157
-rw-r--r--lib/libucsi/dvb/ait_application_name_descriptor.h145
-rw-r--r--lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h125
-rw-r--r--lib/libucsi/dvb/ancillary_data_descriptor.h67
-rw-r--r--lib/libucsi/dvb/announcement_support_descriptor.h219
-rw-r--r--lib/libucsi/dvb/application_signalling_descriptor.h124
-rw-r--r--lib/libucsi/dvb/bat_section.c77
-rw-r--r--lib/libucsi/dvb/bat_section.h211
-rw-r--r--lib/libucsi/dvb/bouquet_name_descriptor.h82
-rw-r--r--lib/libucsi/dvb/ca_identifier_descriptor.h94
-rw-r--r--lib/libucsi/dvb/cable_delivery_descriptor.h70
-rw-r--r--lib/libucsi/dvb/cell_frequency_link_descriptor.h190
-rw-r--r--lib/libucsi/dvb/cell_list_descriptor.h201
-rw-r--r--lib/libucsi/dvb/component_descriptor.h147
-rw-r--r--lib/libucsi/dvb/content_descriptor.h116
-rw-r--r--lib/libucsi/dvb/content_identifier_descriptor.h233
-rw-r--r--lib/libucsi/dvb/country_availability_descriptor.h120
-rw-r--r--lib/libucsi/dvb/data_broadcast_descriptor.h139
-rw-r--r--lib/libucsi/dvb/data_broadcast_id_descriptor.h221
-rw-r--r--lib/libucsi/dvb/default_authority_descriptor.h82
-rw-r--r--lib/libucsi/dvb/descriptor.h229
-rw-r--r--lib/libucsi/dvb/dit_section.c32
-rw-r--r--lib/libucsi/dvb/dit_section.h54
-rw-r--r--lib/libucsi/dvb/dsng_descriptor.h80
-rw-r--r--lib/libucsi/dvb/eit_section.c63
-rw-r--r--lib/libucsi/dvb/eit_section.h160
-rw-r--r--lib/libucsi/dvb/extended_event_descriptor.h232
-rw-r--r--lib/libucsi/dvb/frequency_list_descriptor.h107
-rw-r--r--lib/libucsi/dvb/int_section.c79
-rw-r--r--lib/libucsi/dvb/int_section.h245
-rw-r--r--lib/libucsi/dvb/ip_mac_platform_name_descriptor.h87
-rw-r--r--lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h87
-rw-r--r--lib/libucsi/dvb/ip_mac_stream_location_descriptor.h73
-rw-r--r--lib/libucsi/dvb/linkage_descriptor.h480
-rw-r--r--lib/libucsi/dvb/local_time_offset_descriptor.h127
-rw-r--r--lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h110
-rw-r--r--lib/libucsi/dvb/mosaic_descriptor.h324
-rw-r--r--lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h145
-rw-r--r--lib/libucsi/dvb/multilingual_component_descriptor.h149
-rw-r--r--lib/libucsi/dvb/multilingual_network_name_descriptor.h145
-rw-r--r--lib/libucsi/dvb/multilingual_service_name_descriptor.h197
-rw-r--r--lib/libucsi/dvb/network_name_descriptor.h82
-rw-r--r--lib/libucsi/dvb/nit_section.c78
-rw-r--r--lib/libucsi/dvb/nit_section.h207
-rw-r--r--lib/libucsi/dvb/nvod_reference_descriptor.h125
-rw-r--r--lib/libucsi/dvb/parental_rating_descriptor.h135
-rw-r--r--lib/libucsi/dvb/partial_transport_stream_descriptor.h68
-rw-r--r--lib/libucsi/dvb/pdc_descriptor.h64
-rw-r--r--lib/libucsi/dvb/private_data_specifier_descriptor.h63
-rw-r--r--lib/libucsi/dvb/related_content_descriptor.h56
-rw-r--r--lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h110
-rw-r--r--lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h87
-rw-r--r--lib/libucsi/dvb/rnt_rnt_scan_descriptor.h125
-rw-r--r--lib/libucsi/dvb/rst_section.c47
-rw-r--r--lib/libucsi/dvb/rst_section.h110
-rw-r--r--lib/libucsi/dvb/s2_satellite_delivery_descriptor.h116
-rw-r--r--lib/libucsi/dvb/satellite_delivery_descriptor.h73
-rw-r--r--lib/libucsi/dvb/scrambling_descriptor.h61
-rw-r--r--lib/libucsi/dvb/sdt_section.c60
-rw-r--r--lib/libucsi/dvb/sdt_section.h157
-rw-r--r--lib/libucsi/dvb/section.h107
-rw-r--r--lib/libucsi/dvb/service_availability_descriptor.h98
-rw-r--r--lib/libucsi/dvb/service_descriptor.h163
-rw-r--r--lib/libucsi/dvb/service_identifier_descriptor.h82
-rw-r--r--lib/libucsi/dvb/service_list_descriptor.h122
-rw-r--r--lib/libucsi/dvb/service_move_descriptor.h67
-rw-r--r--lib/libucsi/dvb/short_event_descriptor.h135
-rw-r--r--lib/libucsi/dvb/short_smoothing_buffer_descriptor.h87
-rw-r--r--lib/libucsi/dvb/sit_section.c69
-rw-r--r--lib/libucsi/dvb/sit_section.h173
-rw-r--r--lib/libucsi/dvb/st_section.c29
-rw-r--r--lib/libucsi/dvb/st_section.h77
-rw-r--r--lib/libucsi/dvb/stream_identifier_descriptor.h61
-rw-r--r--lib/libucsi/dvb/stuffing_descriptor.h82
-rw-r--r--lib/libucsi/dvb/subtitling_descriptor.h126
-rw-r--r--lib/libucsi/dvb/target_ip_address_descriptor.h116
-rw-r--r--lib/libucsi/dvb/target_ip_slash_descriptor.h116
-rw-r--r--lib/libucsi/dvb/target_ip_source_slash_descriptor.h118
-rw-r--r--lib/libucsi/dvb/target_ipv6_address_descriptor.h116
-rw-r--r--lib/libucsi/dvb/target_ipv6_slash_descriptor.h116
-rw-r--r--lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h118
-rw-r--r--lib/libucsi/dvb/tdt_section.c33
-rw-r--r--lib/libucsi/dvb/tdt_section.h54
-rw-r--r--lib/libucsi/dvb/telephone_descriptor.h150
-rw-r--r--lib/libucsi/dvb/teletext_descriptor.h127
-rw-r--r--lib/libucsi/dvb/terrestrial_delivery_descriptor.h77
-rw-r--r--lib/libucsi/dvb/time_shifted_event_descriptor.h65
-rw-r--r--lib/libucsi/dvb/time_shifted_service_descriptor.h63
-rw-r--r--lib/libucsi/dvb/tot_section.c50
-rw-r--r--lib/libucsi/dvb/tot_section.h97
-rw-r--r--lib/libucsi/dvb/transport_stream_descriptor.h82
-rw-r--r--lib/libucsi/dvb/tva_container_section.c33
-rw-r--r--lib/libucsi/dvb/tva_container_section.h90
-rw-r--r--lib/libucsi/dvb/tva_id_descriptor.h124
-rw-r--r--lib/libucsi/dvb/types.c270
-rw-r--r--lib/libucsi/dvb/types.h127
-rw-r--r--lib/libucsi/dvb/vbi_data_descriptor.h186
-rw-r--r--lib/libucsi/dvb/vbi_teletext_descriptor.h116
-rw-r--r--lib/libucsi/endianops.h128
-rw-r--r--lib/libucsi/mpeg/Makefile65
-rw-r--r--lib/libucsi/mpeg/audio_stream_descriptor.h65
-rw-r--r--lib/libucsi/mpeg/ca_descriptor.h91
-rw-r--r--lib/libucsi/mpeg/cat_section.c34
-rw-r--r--lib/libucsi/mpeg/cat_section.h94
-rw-r--r--lib/libucsi/mpeg/content_labelling_descriptor.h356
-rw-r--r--lib/libucsi/mpeg/copyright_descriptor.h89
-rw-r--r--lib/libucsi/mpeg/data_stream_alignment_descriptor.h73
-rw-r--r--lib/libucsi/mpeg/descriptor.h102
-rw-r--r--lib/libucsi/mpeg/external_es_id_descriptor.h63
-rw-r--r--lib/libucsi/mpeg/fmc_descriptor.h122
-rw-r--r--lib/libucsi/mpeg/fmxbuffer_size_descriptor.h83
-rw-r--r--lib/libucsi/mpeg/hierarchy_descriptor.h83
-rw-r--r--lib/libucsi/mpeg/ibp_descriptor.h65
-rw-r--r--lib/libucsi/mpeg/iod_descriptor.h87
-rw-r--r--lib/libucsi/mpeg/iso_639_language_descriptor.h124
-rw-r--r--lib/libucsi/mpeg/maximum_bitrate_descriptor.h64
-rw-r--r--lib/libucsi/mpeg/metadata_descriptor.h472
-rw-r--r--lib/libucsi/mpeg/metadata_pointer_descriptor.h360
-rw-r--r--lib/libucsi/mpeg/metadata_section.c27
-rw-r--r--lib/libucsi/mpeg/metadata_section.h122
-rw-r--r--lib/libucsi/mpeg/metadata_std_descriptor.h72
-rw-r--r--lib/libucsi/mpeg/mpeg4_audio_descriptor.h61
-rw-r--r--lib/libucsi/mpeg/mpeg4_video_descriptor.h61
-rw-r--r--lib/libucsi/mpeg/multiplex_buffer_descriptor.h65
-rw-r--r--lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h67
-rw-r--r--lib/libucsi/mpeg/muxcode_descriptor.h82
-rw-r--r--lib/libucsi/mpeg/odsmt_section.c80
-rw-r--r--lib/libucsi/mpeg/odsmt_section.h224
-rw-r--r--lib/libucsi/mpeg/pat_section.c46
-rw-r--r--lib/libucsi/mpeg/pat_section.h118
-rw-r--r--lib/libucsi/mpeg/pmt_section.c71
-rw-r--r--lib/libucsi/mpeg/pmt_section.h188
-rw-r--r--lib/libucsi/mpeg/private_data_indicator_descriptor.h63
-rw-r--r--lib/libucsi/mpeg/registration_descriptor.h91
-rw-r--r--lib/libucsi/mpeg/section.h58
-rw-r--r--lib/libucsi/mpeg/sl_descriptor.h63
-rw-r--r--lib/libucsi/mpeg/smoothing_buffer_descriptor.h66
-rw-r--r--lib/libucsi/mpeg/std_descriptor.h62
-rw-r--r--lib/libucsi/mpeg/system_clock_descriptor.h65
-rw-r--r--lib/libucsi/mpeg/target_background_grid_descriptor.h66
-rw-r--r--lib/libucsi/mpeg/tsdt_section.c34
-rw-r--r--lib/libucsi/mpeg/tsdt_section.h94
-rw-r--r--lib/libucsi/mpeg/types.h127
-rw-r--r--lib/libucsi/mpeg/video_stream_descriptor.h101
-rw-r--r--lib/libucsi/mpeg/video_window_descriptor.h64
-rw-r--r--lib/libucsi/section.h253
-rw-r--r--lib/libucsi/section_buf.c173
-rw-r--r--lib/libucsi/section_buf.h124
-rw-r--r--lib/libucsi/testrecord.txt146
-rw-r--r--lib/libucsi/transport_packet.c256
-rw-r--r--lib/libucsi/transport_packet.h195
-rw-r--r--lib/libucsi/types.h36
-rw-r--r--libdvb2/README23
294 files changed, 42375 insertions, 23 deletions
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..3389628
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,11 @@
+# Makefile for linuxtv.org dvb-apps/lib
+
+.PHONY: all clean install
+
+all clean install:
+ $(MAKE) -C libdvbapi $@
+ $(MAKE) -C libdvbcfg $@
+ $(MAKE) -C libdvben50221 $@
+ $(MAKE) -C libdvbsec $@
+ $(MAKE) -C libesg $@
+ $(MAKE) -C libucsi $@
diff --git a/lib/libdvbapi/Makefile b/lib/libdvbapi/Makefile
new file mode 100644
index 0000000..0ed96ec
--- /dev/null
+++ b/lib/libdvbapi/Makefile
@@ -0,0 +1,25 @@
+# Makefile for linuxtv.org dvb-apps/lib/libdvbapi
+
+includes = dvbaudio.h \
+ dvbca.h \
+ dvbdemux.h \
+ dvbfe.h \
+ dvbnet.h \
+ dvbvideo.h
+
+objects = dvbaudio.o \
+ dvbca.o \
+ dvbdemux.o \
+ dvbfe.o \
+ dvbnet.o \
+ dvbvideo.o
+
+lib_name = libdvbapi
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include ../../Make.rules
diff --git a/lib/libdvbapi/dvbaudio.c b/lib/libdvbapi/dvbaudio.c
new file mode 100644
index 0000000..72b4d70
--- /dev/null
+++ b/lib/libdvbapi/dvbaudio.c
@@ -0,0 +1,50 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/dvb/audio.h>
+#include <errno.h>
+#include "dvbaudio.h"
+
+int dvbaudio_open(int adapter, int audiodeviceid)
+{
+ char filename[PATH_MAX+1];
+ int fd;
+
+ sprintf(filename, "/dev/dvb/adapter%i/audio%i", adapter, audiodeviceid);
+ if ((fd = open(filename, O_RDWR)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.audio%i", adapter, audiodeviceid);
+ fd = open(filename, O_RDWR);
+ }
+
+ return fd;
+}
+
+int dvbaudio_set_bypass(int fd, int bypass)
+{
+ return ioctl(fd, AUDIO_SET_BYPASS_MODE, bypass);
+}
diff --git a/lib/libdvbapi/dvbaudio.h b/lib/libdvbapi/dvbaudio.h
new file mode 100644
index 0000000..36f6a55
--- /dev/null
+++ b/lib/libdvbapi/dvbaudio.h
@@ -0,0 +1,55 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBAUDIO_H
+#define LIBDVBAUDIO_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * Open a DVB audio device.
+ *
+ * @param adapter DVB adapter ID.
+ * @param audiodeviceid Id of audio device of that adapter to open.
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbaudio_open(int adapter, int audiodeviceid);
+
+/**
+ * Control audio bypass - i.e. output decoded audio, or the raw bitstream (e.g. AC3).
+ *
+ * @param fd Audio device opened with dvbaudio_open().
+ * @param bypass 1=> enable bypass, 0=> disable.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbaudio_set_bypass(int fd, int bypass);
+
+// FIXME: this is a stub library
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBAUDIO_H
diff --git a/lib/libdvbapi/dvbca.c b/lib/libdvbapi/dvbca.c
new file mode 100644
index 0000000..8261cd2
--- /dev/null
+++ b/lib/libdvbapi/dvbca.c
@@ -0,0 +1,159 @@
+/*
+ * libdvbca - interface onto raw CA devices
+ *
+ * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/dvb/ca.h>
+#include "dvbca.h"
+
+
+int dvbca_open(int adapter, int cadevice)
+{
+ char filename[PATH_MAX+1];
+ int fd;
+
+ sprintf(filename, "/dev/dvb/adapter%i/ca%i", adapter, cadevice);
+ if ((fd = open(filename, O_RDWR)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.ca%i", adapter, cadevice);
+ fd = open(filename, O_RDWR);
+ }
+
+ return fd;
+}
+
+int dvbca_reset(int fd, uint8_t slot)
+{
+ return ioctl(fd, CA_RESET, (1 << slot));
+}
+
+int dvbca_get_interface_type(int fd, uint8_t slot)
+{
+ ca_slot_info_t info;
+
+ info.num = slot;
+ if (ioctl(fd, CA_GET_SLOT_INFO, &info))
+ return -1;
+
+ if (info.type & CA_CI_LINK)
+ return DVBCA_INTERFACE_LINK;
+ if (info.type & CA_CI)
+ return DVBCA_INTERFACE_HLCI;
+
+ return -1;
+}
+
+int dvbca_get_cam_state(int fd, uint8_t slot)
+{
+ ca_slot_info_t info;
+
+ info.num = slot;
+ if (ioctl(fd, CA_GET_SLOT_INFO, &info))
+ return -1;
+
+ if (info.flags == 0)
+ return DVBCA_CAMSTATE_MISSING;
+ if (info.flags & CA_CI_MODULE_READY)
+ return DVBCA_CAMSTATE_READY;
+ if (info.flags & CA_CI_MODULE_PRESENT)
+ return DVBCA_CAMSTATE_INITIALISING;
+
+ return -1;
+}
+
+int dvbca_link_write(int fd, uint8_t slot, uint8_t connection_id,
+ uint8_t *data, uint16_t data_length)
+{
+ uint8_t *buf = malloc(data_length + 2);
+ if (buf == NULL)
+ return -1;
+
+ buf[0] = slot;
+ buf[1] = connection_id;
+ memcpy(buf+2, data, data_length);
+
+ int result = write(fd, buf, data_length+2);
+ free(buf);
+ return result;
+}
+
+int dvbca_link_read(int fd, uint8_t *slot, uint8_t *connection_id,
+ uint8_t *data, uint16_t data_length)
+{
+ int size;
+
+ uint8_t *buf = malloc(data_length + 2);
+ if (buf == NULL)
+ return -1;
+
+ if ((size = read(fd, buf, data_length+2)) < 2)
+ return -1;
+
+ *slot = buf[0];
+ *connection_id = buf[1];
+ memcpy(data, buf+2, size-2);
+ free(buf);
+
+ return size - 2;
+}
+
+int dvbca_hlci_write(int fd, uint8_t *data, uint16_t data_length)
+{
+ struct ca_msg msg;
+
+ if (data_length > 256) {
+ return -1;
+ }
+ memset(&msg, 0, sizeof(msg));
+ msg.length = data_length;
+
+ memcpy(msg.msg, data, data_length);
+
+ return ioctl(fd, CA_SEND_MSG, &msg);
+}
+
+int dvbca_hlci_read(int fd, uint32_t app_tag, uint8_t *data,
+ uint16_t data_length)
+{
+ struct ca_msg msg;
+
+ if (data_length > 256) {
+ data_length = 256;
+ }
+ memset(&msg, 0, sizeof(msg));
+ msg.length = data_length;
+ msg.msg[0] = app_tag >> 16;
+ msg.msg[1] = app_tag >> 8;
+ msg.msg[2] = app_tag;
+
+ int status = ioctl(fd, CA_GET_MSG, &msg);
+ if (status < 0) return status;
+
+ if (msg.length > data_length) msg.length = data_length;
+ memcpy(data, msg.msg, msg.length);
+ return msg.length;
+}
diff --git a/lib/libdvbapi/dvbca.h b/lib/libdvbapi/dvbca.h
new file mode 100644
index 0000000..c65423b
--- /dev/null
+++ b/lib/libdvbapi/dvbca.h
@@ -0,0 +1,135 @@
+/*
+ * libdvbca - interface onto raw CA devices
+ *
+ * Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBCA_H
+#define LIBDVBCA_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * The types of CA interface we support.
+ */
+#define DVBCA_INTERFACE_LINK 0
+#define DVBCA_INTERFACE_HLCI 1
+
+/**
+ * States a CAM in a slot can be in.
+ */
+#define DVBCA_CAMSTATE_MISSING 0
+#define DVBCA_CAMSTATE_INITIALISING 1
+#define DVBCA_CAMSTATE_READY 2
+
+
+/**
+ * Open a CA device. Multiple CAMs can be accessed through a CA device.
+ *
+ * @param adapter Index of the DVB adapter.
+ * @param cadevice Index of the CA device on that adapter (usually 0).
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbca_open(int adapter, int cadevice);
+
+/**
+ * Reset a CAM.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param slot Slot where the requested CAM is in.
+ * @return 0 on success, -1 on failure.
+ */
+extern int dvbca_reset(int fd, uint8_t slot);
+
+/**
+ * Get the interface type of a CAM.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param slot Slot where the requested CAM is in.
+ * @return One of the DVBCA_INTERFACE_* values, or -1 on failure.
+ */
+extern int dvbca_get_interface_type(int fd, uint8_t slot);
+
+/**
+ * Get the state of a CAM.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param slot Slot where the requested CAM is in.
+ * @return One of the DVBCA_CAMSTATE_* values, or -1 on failure.
+ */
+extern int dvbca_get_cam_state(int fd, uint8_t slot);
+
+/**
+ * Write a message to a CAM using a link-layer interface.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param slot Slot where the requested CAM is in.
+ * @param connection_id Connection ID of the message.
+ * @param data Data to write.
+ * @param data_length Number of bytes to write.
+ * @return 0 on success, or -1 on failure.
+ */
+extern int dvbca_link_write(int fd, uint8_t slot, uint8_t connection_id,
+ uint8_t *data, uint16_t data_length);
+
+/**
+ * Read a message from a CAM using a link-layer interface.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param slot Slot where the responding CAM is in.
+ * @param connection_id Destination for the connection ID the message came from.
+ * @param data Data that was read.
+ * @param data_length Max number of bytes to read.
+ * @return Number of bytes read on success, or -1 on failure.
+ */
+extern int dvbca_link_read(int fd, uint8_t *slot, uint8_t *connection_id,
+ uint8_t *data, uint16_t data_length);
+
+// FIXME how do we determine which CAM slot of a CA is meant?
+/**
+ * Write a message to a CAM using an HLCI interface.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param data Data to write.
+ * @param data_length Number of bytes to write.
+ * @return 0 on success, or -1 on failure.
+ */
+extern int dvbca_hlci_write(int fd, uint8_t *data, uint16_t data_length);
+
+// FIXME how do we determine which CAM slot of a CA is meant?
+/**
+ * Read a message from a CAM using an HLCI interface.
+ *
+ * @param fd File handle opened with dvbca_open.
+ * @param app_tag Application layer tag giving the message type to read.
+ * @param data Data that was read.
+ * @param data_length Max number of bytes to read.
+ * @return Number of bytes read on success, or -1 on failure.
+ */
+extern int dvbca_hlci_read(int fd, uint32_t app_tag, uint8_t *data,
+ uint16_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBCA_H
diff --git a/lib/libdvbapi/dvbdemux.c b/lib/libdvbapi/dvbdemux.c
new file mode 100644
index 0000000..a882af6
--- /dev/null
+++ b/lib/libdvbapi/dvbdemux.c
@@ -0,0 +1,255 @@
+/*
+ * libdvbdemux - a DVB demux library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/dvb/dmx.h>
+#include "dvbdemux.h"
+
+
+int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking)
+{
+ char filename[PATH_MAX+1];
+ int flags = O_RDWR;
+ int fd;
+
+ if (nonblocking)
+ flags |= O_NONBLOCK;
+
+ sprintf(filename, "/dev/dvb/adapter%i/demux%i", adapter, demuxdevice);
+ if ((fd = open(filename, flags)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.demux%i", adapter, demuxdevice);
+ fd = open(filename, flags);
+ }
+
+ return fd;
+}
+
+int dvbdemux_open_dvr(int adapter, int dvrdevice, int readonly, int nonblocking)
+{
+ char filename[PATH_MAX+1];
+ int flags = O_RDWR;
+ int fd;
+
+ if (readonly)
+ flags = O_RDONLY;
+ if (nonblocking)
+ flags |= O_NONBLOCK;
+
+ sprintf(filename, "/dev/dvb/adapter%i/dvr%i", adapter, dvrdevice);
+ if ((fd = open(filename, flags)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.dvr%i", adapter, dvrdevice);
+ fd = open(filename, flags);
+ }
+
+ return fd;
+}
+
+int dvbdemux_set_section_filter(int fd, int pid,
+ uint8_t filter[18], uint8_t mask[18],
+ int start, int checkcrc)
+{
+ struct dmx_sct_filter_params sctfilter;
+
+ memset(&sctfilter, 0, sizeof(sctfilter));
+ sctfilter.pid = pid;
+ memcpy(sctfilter.filter.filter, filter, 1);
+ memcpy(sctfilter.filter.filter+1, filter+3, 15);
+ memcpy(sctfilter.filter.mask, mask, 1);
+ memcpy(sctfilter.filter.mask+1, mask+3, 15);
+ memset(sctfilter.filter.mode, 0, 16);
+ if (start)
+ sctfilter.flags |= DMX_IMMEDIATE_START;
+ if (checkcrc)
+ sctfilter.flags |= DMX_CHECK_CRC;
+
+ return ioctl(fd, DMX_SET_FILTER, &sctfilter);
+}
+
+int dvbdemux_set_pes_filter(int fd, int pid,
+ int input, int output,
+ int pestype,
+ int start)
+{
+ struct dmx_pes_filter_params filter;
+
+ memset(&filter, 0, sizeof(filter));
+ filter.pid = pid;
+
+ switch(input) {
+ case DVBDEMUX_INPUT_FRONTEND:
+ filter.input = DMX_IN_FRONTEND;
+ break;
+
+ case DVBDEMUX_INPUT_DVR:
+ filter.input = DMX_IN_DVR;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch(output) {
+ case DVBDEMUX_OUTPUT_DECODER:
+ filter.output = DMX_OUT_DECODER;
+ break;
+
+ case DVBDEMUX_OUTPUT_DEMUX:
+ filter.output = DMX_OUT_TAP;
+ break;
+
+ case DVBDEMUX_OUTPUT_DVR:
+ filter.output = DMX_OUT_TS_TAP;
+ break;
+
+#ifdef DMX_OUT_TSDEMUX_TAP
+ case DVBDEMUX_OUTPUT_TS_DEMUX:
+ filter.output = DMX_OUT_TSDEMUX_TAP;
+ break;
+#endif
+
+ default:
+ return -EINVAL;
+ }
+
+ switch(pestype) {
+ case DVBDEMUX_PESTYPE_AUDIO:
+ filter.pes_type = DMX_PES_AUDIO;
+ break;
+
+ case DVBDEMUX_PESTYPE_VIDEO:
+ filter.pes_type = DMX_PES_VIDEO;
+ break;
+
+ case DVBDEMUX_PESTYPE_TELETEXT:
+ filter.pes_type = DMX_PES_TELETEXT;
+ break;
+
+ case DVBDEMUX_PESTYPE_SUBTITLE:
+ filter.pes_type = DMX_PES_SUBTITLE;
+ break;
+
+ case DVBDEMUX_PESTYPE_PCR:
+ filter.pes_type = DMX_PES_PCR;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ if (start)
+ filter.flags |= DMX_IMMEDIATE_START;
+
+ return ioctl(fd, DMX_SET_PES_FILTER, &filter);
+}
+
+int dvbdemux_set_pid_filter(int fd, int pid,
+ int input, int output,
+ int start)
+{
+ struct dmx_pes_filter_params filter;
+
+ memset(&filter, 0, sizeof(filter));
+ if (pid == -1)
+ filter.pid = 0x2000;
+ else
+ filter.pid = pid;
+
+ switch(input) {
+ case DVBDEMUX_INPUT_FRONTEND:
+ filter.input = DMX_IN_FRONTEND;
+ break;
+
+ case DVBDEMUX_INPUT_DVR:
+ filter.input = DMX_IN_DVR;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ switch(output) {
+ case DVBDEMUX_OUTPUT_DECODER:
+ filter.output = DMX_OUT_DECODER;
+ break;
+
+ case DVBDEMUX_OUTPUT_DEMUX:
+ filter.output = DMX_OUT_TAP;
+ break;
+
+ case DVBDEMUX_OUTPUT_DVR:
+ filter.output = DMX_OUT_TS_TAP;
+ break;
+
+#ifdef DMX_OUT_TSDEMUX_TAP
+ case DVBDEMUX_OUTPUT_TS_DEMUX:
+ filter.output = DMX_OUT_TSDEMUX_TAP;
+ break;
+#endif
+
+ default:
+ return -EINVAL;
+ }
+
+ filter.pes_type = DMX_PES_OTHER;
+
+ if (start)
+ filter.flags |= DMX_IMMEDIATE_START;
+
+ return ioctl(fd, DMX_SET_PES_FILTER, &filter);
+}
+
+int dvbdemux_start(int fd)
+{
+ return ioctl(fd, DMX_START);
+}
+
+int dvbdemux_stop(int fd)
+{
+ return ioctl(fd, DMX_STOP);
+}
+
+int dvbdemux_get_stc(int fd, uint64_t *stc)
+{
+ struct dmx_stc _stc;
+ int result;
+
+ memset(stc, 0, sizeof(_stc));
+ if ((result = ioctl(fd, DMX_GET_STC, &_stc)) != 0) {
+ return result;
+ }
+
+ *stc = _stc.stc / _stc.base;
+ return 0;
+}
+
+int dvbdemux_set_buffer(int fd, int bufsize)
+{
+ return ioctl(fd, DMX_SET_BUFFER_SIZE, bufsize);
+}
diff --git a/lib/libdvbapi/dvbdemux.h b/lib/libdvbapi/dvbdemux.h
new file mode 100644
index 0000000..808ee80
--- /dev/null
+++ b/lib/libdvbapi/dvbdemux.h
@@ -0,0 +1,204 @@
+/*
+ * libdvbdemux - a DVB demux library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBDEMUX_H
+#define LIBDVBDEMUX_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * Source of the data to be demuxed.
+ *
+ * FRONTEND. The data will be read from the frontend on the adapter.
+ *
+ * DVR. The data will be read from the DVR device of the adapter (of course,
+ * you need to write data TO the DVR device as well).
+ */
+#define DVBDEMUX_INPUT_FRONTEND 0
+#define DVBDEMUX_INPUT_DVR 1
+
+/**
+ * Destination of the demuxed data.
+ *
+ * DECODER. Sends the data directly to a hardware decoder (if present).
+ *
+ * DEMUX. Sends the PID stream to the current demux file descriptor. HOWEVER, the
+ * data will be the payload *only* - transport stream headers will be stripped.
+ *
+ * DVR sends the data to the DVR device. The data will be the complete transport
+ * stream packets with headers intact. Note: if multiple filters specify
+ * DVBDEMUX_OUTPUT_DVR, the individual PID streams will be re-multiplexed
+ * together.
+ */
+#define DVBDEMUX_OUTPUT_DECODER 0
+#define DVBDEMUX_OUTPUT_DEMUX 1
+#define DVBDEMUX_OUTPUT_DVR 2
+#define DVBDEMUX_OUTPUT_TS_DEMUX 3
+
+/**
+ * PES types.
+ */
+#define DVBDEMUX_PESTYPE_AUDIO 0
+#define DVBDEMUX_PESTYPE_VIDEO 1
+#define DVBDEMUX_PESTYPE_TELETEXT 2
+#define DVBDEMUX_PESTYPE_SUBTITLE 3
+#define DVBDEMUX_PESTYPE_PCR 4
+
+
+/**
+ * Open a demux device. Can be called multiple times. These let you setup a
+ * single filter per FD. It can can also be read() from if you use a section
+ * filter, or create a pes_filter or raw_filter with output DVBDEMUX_OUTPUT_DEMUX.
+ *
+ * @param adapter Index of the DVB adapter.
+ * @param demuxdevice Index of the demux device on that adapter (usually 0).
+ * @param nonblocking If 1, frontend will be opened in nonblocking mode.
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking);
+
+/**
+ * Open a DVR device. May be opened for writing or reading once.
+ * It is used to either write() transport stream data to be demuxed
+ * (if input == DVBDEMUX_INPUT_DVR), or to read() a stream of demuxed data
+ * (if output == DVBDEMUX_OUTPUT_DVR).
+ *
+ * Note, all demux filters with output set to DVBDEMUX_OUTPUT_DVR will be
+ * multiplexed together and output their data on this device.
+ *
+ * @param adapter Index of the DVB adapter.
+ * @param dvrdevice Index of the dvr device on that adapter (usually 0)
+ * @param readonly If 1, frontend will be opened in readonly mode only.
+ * @param nonblocking If 1, frontend will be opened in nonblocking mode.
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbdemux_open_dvr(int adapter, int dvrdevice, int readonly, int nonblocking);
+
+/**
+ * Set filter for the first 18 bytes of decoded SI table sections. Note that
+ * bytes 1 and 2 are _not_ filtered since they contain the length field.
+ *
+ * Conceptually, the driver computes the following for each filtered bit.
+ *
+ * (filter[X].bit[Y] & mask[X].bit[Y]) == (header[X].bit[Y] & mask[X].bit[Y])
+ *
+ * Any sections which do not match this criteria for every bit will be discarded.
+ *
+ * The SI data is always read from the frontend, and is always returned by
+ * read()ing the demux fd. FIXME: check this statement!
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @param pid PID of the stream.
+ * @param filter The filter values of the first 18 bytes of the desired sections.
+ * @param mask Bitmask indicating which bits in the filter array should be tested
+ * (if a bit is 1, it will be tested).
+ * @param start If 1, the filter will be started immediately. Otherwise you must
+ * call dvbdemux_start() manually.
+ * @param checkcrc If 1, the driver will check the CRC on the table sections.
+ * Any bad sections will be dropped.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_set_section_filter(int fd, int pid,
+ uint8_t filter[18], uint8_t mask[18],
+ int start, int checkcrc);
+
+/**
+ * Set filter for a stream of PES data. This call can only used for cards
+ * equipped with a hardware decoder.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @param pid PID of the stream.
+ * @param input One of DVBDEMUX_INPUT_*.
+ * @param output One of DVBDEMUX_OUTPUT_*.
+ * @param pestype One of DVBDEMUX_PESTYPE_* - this tells the decoder the type
+ * of data in this stream.
+ * @param start If 1, the filter will be started immediately. Otherwise you must
+ * call dvbdemux_start() manually.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_set_pes_filter(int fd, int pid,
+ int input, int output,
+ int pestype,
+ int start);
+
+/**
+ * Create a pid filter - this will extract transport stream packets for a
+ * specified PID.
+ *
+ * Note: The wildcard PID can only be used on "budget" cards.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @param pid PID to retrieve, or use -1 as a wildcard for ALL PIDs.
+ * @param input One of DVBDEMUX_INPUT_*.
+ * @param output One of DVBDEMUX_OUTPUT_*.
+ * @param start If 1, the filter will be started immediately. Otherwise you must
+ * call dvbdemux_start() manually.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_set_pid_filter(int fd, int pid,
+ int input, int output,
+ int start);
+
+/**
+ * Start a demux going.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_start(int fd);
+
+/**
+ * Stop a demux.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_stop(int fd);
+
+/**
+ * Retrieve the current STC from the demux. This call can only used for cards
+ * equipped with a hardware decoder.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @param stc Where to put the retrieved STC value (in 90kHz clock).
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_get_stc(int fd, uint64_t *stc);
+
+/**
+ * Change the internal buffer size used by the demuxer. The default buffer size
+ * is 8192 bytes. Can only be used if the demux in question is stopped.
+ *
+ * @param fd FD as opened with dvbdemux_open_demux() above.
+ * @param bufsize New buffer size to use.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbdemux_set_buffer(int fd, int bufsize);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBDEMUX_H
diff --git a/lib/libdvbapi/dvbfe.c b/lib/libdvbapi/dvbfe.c
new file mode 100644
index 0000000..98104c9
--- /dev/null
+++ b/lib/libdvbapi/dvbfe.c
@@ -0,0 +1,574 @@
+/*
+ * libdvbfe - a DVB frontend library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/dvb/frontend.h>
+#include <libdvbmisc/dvbmisc.h>
+#include "dvbfe.h"
+
+int verbose = 0;
+
+static int dvbfe_spectral_inversion_to_kapi[][2] =
+{
+ { DVBFE_INVERSION_OFF, INVERSION_OFF },
+ { DVBFE_INVERSION_ON, INVERSION_ON },
+ { DVBFE_INVERSION_AUTO, INVERSION_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_code_rate_to_kapi[][2] =
+{
+ { DVBFE_FEC_NONE, FEC_NONE },
+ { DVBFE_FEC_1_2, FEC_1_2 },
+ { DVBFE_FEC_2_3, FEC_2_3 },
+ { DVBFE_FEC_3_4, FEC_3_4 },
+ { DVBFE_FEC_4_5, FEC_4_5 },
+ { DVBFE_FEC_5_6, FEC_5_6 },
+ { DVBFE_FEC_6_7, FEC_6_7 },
+ { DVBFE_FEC_7_8, FEC_7_8 },
+ { DVBFE_FEC_8_9, FEC_8_9 },
+ { DVBFE_FEC_AUTO, FEC_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_dvbt_const_to_kapi[][2] =
+{
+ { DVBFE_DVBT_CONST_QPSK, FE_QPSK },
+ { DVBFE_DVBT_CONST_QAM_16, QAM_16 },
+ { DVBFE_DVBT_CONST_QAM_32, QAM_32 },
+ { DVBFE_DVBT_CONST_QAM_64, QAM_64 },
+ { DVBFE_DVBT_CONST_QAM_128, QAM_128 },
+ { DVBFE_DVBT_CONST_QAM_256, QAM_256 },
+ { DVBFE_DVBT_CONST_AUTO, QAM_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_dvbc_mod_to_kapi[][2] =
+{
+ { DVBFE_DVBC_MOD_QAM_16, QAM_16 },
+ { DVBFE_DVBC_MOD_QAM_32, QAM_32 },
+ { DVBFE_DVBC_MOD_QAM_64, QAM_64 },
+ { DVBFE_DVBC_MOD_QAM_128, QAM_128 },
+ { DVBFE_DVBC_MOD_QAM_256, QAM_256 },
+ { DVBFE_DVBC_MOD_AUTO, QAM_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_atsc_mod_to_kapi[][2] =
+{
+ { DVBFE_ATSC_MOD_QAM_64, QAM_64 },
+ { DVBFE_ATSC_MOD_QAM_256, QAM_256 },
+ { DVBFE_ATSC_MOD_VSB_8, VSB_8 },
+ { DVBFE_ATSC_MOD_VSB_16, VSB_16 },
+ { DVBFE_ATSC_MOD_AUTO, QAM_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_dvbt_transmit_mode_to_kapi[][2] =
+{
+ { DVBFE_DVBT_TRANSMISSION_MODE_2K, TRANSMISSION_MODE_2K },
+ { DVBFE_DVBT_TRANSMISSION_MODE_8K, TRANSMISSION_MODE_8K },
+ { DVBFE_DVBT_TRANSMISSION_MODE_AUTO, TRANSMISSION_MODE_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_dvbt_bandwidth_to_kapi[][2] =
+{
+ { DVBFE_DVBT_BANDWIDTH_8_MHZ, BANDWIDTH_8_MHZ },
+ { DVBFE_DVBT_BANDWIDTH_7_MHZ, BANDWIDTH_7_MHZ },
+ { DVBFE_DVBT_BANDWIDTH_6_MHZ, BANDWIDTH_6_MHZ },
+ { DVBFE_DVBT_BANDWIDTH_AUTO, BANDWIDTH_AUTO },
+ { -1, -1 }
+};
+
+static int dvbfe_dvbt_guard_interval_to_kapi[][2] =
+{
+ { DVBFE_DVBT_GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_32},
+ { DVBFE_DVBT_GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_16},
+ { DVBFE_DVBT_GUARD_INTERVAL_1_8, GUARD_INTERVAL_1_8},
+ { DVBFE_DVBT_GUARD_INTERVAL_1_4, GUARD_INTERVAL_1_4},
+ { DVBFE_DVBT_GUARD_INTERVAL_AUTO, GUARD_INTERVAL_AUTO},
+ { -1, -1 }
+};
+
+static int dvbfe_dvbt_hierarchy_to_kapi[][2] =
+{
+ { DVBFE_DVBT_HIERARCHY_NONE, HIERARCHY_NONE },
+ { DVBFE_DVBT_HIERARCHY_1, HIERARCHY_1 },
+ { DVBFE_DVBT_HIERARCHY_2, HIERARCHY_2 },
+ { DVBFE_DVBT_HIERARCHY_4, HIERARCHY_4 },
+ { DVBFE_DVBT_HIERARCHY_AUTO, HIERARCHY_AUTO },
+ { -1, -1 }
+};
+
+
+static int lookupval(int val, int reverse, int table[][2])
+{
+ int i =0;
+
+ while(table[i][0] != -1) {
+ if (!reverse) {
+ if (val == table[i][0]) {
+ return table[i][1];
+ }
+ } else {
+ if (val == table[i][1]) {
+ return table[i][0];
+ }
+ }
+ i++;
+ }
+
+ return -1;
+}
+
+
+struct dvbfe_handle {
+ int fd;
+ enum dvbfe_type type;
+ char *name;
+};
+
+struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly)
+{
+ char filename[PATH_MAX+1];
+ struct dvbfe_handle *fehandle;
+ int fd;
+ struct dvb_frontend_info info;
+
+ // flags
+ int flags = O_RDWR;
+ if (readonly) {
+ flags = O_RDONLY;
+ }
+
+ // open it (try normal /dev structure first)
+ sprintf(filename, "/dev/dvb/adapter%i/frontend%i", adapter, frontend);
+ if ((fd = open(filename, flags)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.frontend%i", adapter, frontend);
+ if ((fd = open(filename, flags)) < 0) {
+ return NULL;
+ }
+ }
+
+ // determine fe type
+ if (ioctl(fd, FE_GET_INFO, &info)) {
+ close(fd);
+ return NULL;
+ }
+
+ // setup structure
+ fehandle = (struct dvbfe_handle*) malloc(sizeof(struct dvbfe_handle));
+ memset(fehandle, 0, sizeof(struct dvbfe_handle));
+ fehandle->fd = fd;
+ switch(info.type) {
+ case FE_QPSK:
+ fehandle->type = DVBFE_TYPE_DVBS;
+ break;
+
+ case FE_QAM:
+ fehandle->type = DVBFE_TYPE_DVBC;
+ break;
+
+ case FE_OFDM:
+ fehandle->type = DVBFE_TYPE_DVBT;
+ break;
+
+ case FE_ATSC:
+ fehandle->type = DVBFE_TYPE_ATSC;
+ break;
+ }
+ fehandle->name = strndup(info.name, sizeof(info.name));
+
+ // done
+ return fehandle;
+}
+
+void dvbfe_close(struct dvbfe_handle *fehandle)
+{
+ close(fehandle->fd);
+ free(fehandle->name);
+ free(fehandle);
+}
+
+extern int dvbfe_get_info(struct dvbfe_handle *fehandle,
+ enum dvbfe_info_mask querymask,
+ struct dvbfe_info *result,
+ enum dvbfe_info_querytype querytype,
+ int timeout)
+{
+ int returnval = 0;
+ struct dvb_frontend_event kevent;
+ int ok = 0;
+
+ result->name = fehandle->name;
+ result->type = fehandle->type;
+
+ switch(querytype) {
+ case DVBFE_INFO_QUERYTYPE_IMMEDIATE:
+ if (querymask & DVBFE_INFO_LOCKSTATUS) {
+ if (!ioctl(fehandle->fd, FE_READ_STATUS, &kevent.status)) {
+ returnval |= DVBFE_INFO_LOCKSTATUS;
+ }
+ }
+ if (querymask & DVBFE_INFO_FEPARAMS) {
+ if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kevent.parameters)) {
+ returnval |= DVBFE_INFO_FEPARAMS;
+ }
+ }
+ break;
+
+ case DVBFE_INFO_QUERYTYPE_LOCKCHANGE:
+ {
+ struct pollfd pollfd;
+ pollfd.fd = fehandle->fd;
+ pollfd.events = POLLIN | POLLERR;
+
+ ok = 1;
+ if (poll(&pollfd, 1, timeout) < 0)
+ ok = 0;
+ if (pollfd.revents & POLLERR)
+ ok = 0;
+ if (!(pollfd.revents & POLLIN))
+ ok = 0;
+ }
+
+ if (ok &&
+ ((querymask & DVBFE_INFO_LOCKSTATUS) ||
+ (querymask & DVBFE_INFO_FEPARAMS))) {
+ if (!ioctl(fehandle->fd, FE_GET_EVENT, &kevent)) {
+ if (querymask & DVBFE_INFO_LOCKSTATUS)
+ returnval |= DVBFE_INFO_LOCKSTATUS;
+ if (querymask & DVBFE_INFO_FEPARAMS)
+ returnval |= DVBFE_INFO_FEPARAMS;
+ }
+ }
+ break;
+ }
+
+ if (returnval & DVBFE_INFO_LOCKSTATUS) {
+ result->signal = kevent.status & FE_HAS_SIGNAL ? 1 : 0;
+ result->carrier = kevent.status & FE_HAS_CARRIER ? 1 : 0;
+ result->viterbi = kevent.status & FE_HAS_VITERBI ? 1 : 0;
+ result->sync = kevent.status & FE_HAS_SYNC ? 1 : 0;
+ result->lock = kevent.status & FE_HAS_LOCK ? 1 : 0;
+ }
+
+ if (returnval & DVBFE_INFO_FEPARAMS) {
+ result->feparams.frequency = kevent.parameters.frequency;
+ result->feparams.inversion = lookupval(kevent.parameters.inversion, 1, dvbfe_spectral_inversion_to_kapi);
+ switch(fehandle->type) {
+ case FE_QPSK:
+ result->feparams.u.dvbs.symbol_rate = kevent.parameters.u.qpsk.symbol_rate;
+ result->feparams.u.dvbs.fec_inner =
+ lookupval(kevent.parameters.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi);
+ break;
+
+ case FE_QAM:
+ result->feparams.u.dvbc.symbol_rate = kevent.parameters.u.qam.symbol_rate;
+ result->feparams.u.dvbc.fec_inner =
+ lookupval(kevent.parameters.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi);
+ result->feparams.u.dvbc.modulation =
+ lookupval(kevent.parameters.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi);
+ break;
+
+ case FE_OFDM:
+ result->feparams.u.dvbt.bandwidth =
+ lookupval(kevent.parameters.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi);
+ result->feparams.u.dvbt.code_rate_HP =
+ lookupval(kevent.parameters.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi);
+ result->feparams.u.dvbt.code_rate_LP =
+ lookupval(kevent.parameters.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi);
+ result->feparams.u.dvbt.constellation =
+ lookupval(kevent.parameters.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi);
+ result->feparams.u.dvbt.transmission_mode =
+ lookupval(kevent.parameters.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi);
+ result->feparams.u.dvbt.guard_interval =
+ lookupval(kevent.parameters.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi);
+ result->feparams.u.dvbt.hierarchy_information =
+ lookupval(kevent.parameters.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi);
+ break;
+
+ case FE_ATSC:
+ result->feparams.u.atsc.modulation =
+ lookupval(kevent.parameters.u.vsb.modulation, 1, dvbfe_atsc_mod_to_kapi);
+ break;
+ }
+ }
+
+ if (querymask & DVBFE_INFO_BER) {
+ if (!ioctl(fehandle->fd, FE_READ_BER, &result->ber))
+ returnval |= DVBFE_INFO_BER;
+ }
+ if (querymask & DVBFE_INFO_SIGNAL_STRENGTH) {
+ if (!ioctl(fehandle->fd, FE_READ_SIGNAL_STRENGTH, &result->signal_strength))
+ returnval |= DVBFE_INFO_SIGNAL_STRENGTH;
+ }
+ if (querymask & DVBFE_INFO_SNR) {
+ if (!ioctl(fehandle->fd, FE_READ_SNR, &result->snr))
+ returnval |= DVBFE_INFO_SNR;
+ }
+ if (querymask & DVBFE_INFO_UNCORRECTED_BLOCKS) {
+ if (!ioctl(fehandle->fd, FE_READ_UNCORRECTED_BLOCKS, &result->ucblocks))
+ returnval |= DVBFE_INFO_UNCORRECTED_BLOCKS;
+ }
+
+ // done
+ return returnval;
+}
+
+int dvbfe_set(struct dvbfe_handle *fehandle,
+ struct dvbfe_parameters *params,
+ int timeout)
+{
+ struct dvb_frontend_parameters kparams;
+ int res;
+ struct timeval endtime;
+ fe_status_t status;
+
+ kparams.frequency = params->frequency;
+ kparams.inversion = lookupval(params->inversion, 0, dvbfe_spectral_inversion_to_kapi);
+ switch(fehandle->type) {
+ case FE_QPSK:
+ kparams.u.qpsk.symbol_rate = params->u.dvbs.symbol_rate;
+ kparams.u.qpsk.fec_inner = lookupval(params->u.dvbs.fec_inner, 0, dvbfe_code_rate_to_kapi);
+ break;
+
+ case FE_QAM:
+ kparams.u.qam.symbol_rate = params->u.dvbc.symbol_rate;
+ kparams.u.qam.fec_inner = lookupval(params->u.dvbc.fec_inner, 0, dvbfe_code_rate_to_kapi);
+ kparams.u.qam.modulation = lookupval(params->u.dvbc.modulation, 0, dvbfe_dvbc_mod_to_kapi);
+ break;
+
+ case FE_OFDM:
+ kparams.u.ofdm.bandwidth = lookupval(params->u.dvbt.bandwidth, 0, dvbfe_dvbt_bandwidth_to_kapi);
+ kparams.u.ofdm.code_rate_HP = lookupval(params->u.dvbt.code_rate_HP, 0, dvbfe_code_rate_to_kapi);
+ kparams.u.ofdm.code_rate_LP = lookupval(params->u.dvbt.code_rate_LP, 0, dvbfe_code_rate_to_kapi);
+ kparams.u.ofdm.constellation = lookupval(params->u.dvbt.constellation, 0, dvbfe_dvbt_const_to_kapi);
+ kparams.u.ofdm.transmission_mode =
+ lookupval(params->u.dvbt.transmission_mode, 0, dvbfe_dvbt_transmit_mode_to_kapi);
+ kparams.u.ofdm.guard_interval =
+ lookupval(params->u.dvbt.guard_interval, 0, dvbfe_dvbt_guard_interval_to_kapi);
+ kparams.u.ofdm.hierarchy_information =
+ lookupval(params->u.dvbt.hierarchy_information, 0, dvbfe_dvbt_hierarchy_to_kapi);
+ break;
+
+ case FE_ATSC:
+ kparams.u.vsb.modulation = lookupval(params->u.atsc.modulation, 0, dvbfe_atsc_mod_to_kapi);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ // set it and check for error
+ res = ioctl(fehandle->fd, FE_SET_FRONTEND, &kparams);
+ if (res)
+ return res;
+
+ // 0 => return immediately
+ if (timeout == 0) {
+ return 0;
+ }
+
+ /* calculate timeout */
+ if (timeout > 0) {
+ gettimeofday(&endtime, NULL);
+ timeout *= 1000;
+ endtime.tv_sec += timeout / 1000000;
+ endtime.tv_usec += timeout % 1000000;
+ }
+
+ /* wait for a lock */
+ while(1) {
+ /* has it locked? */
+ if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) {
+ if (status & FE_HAS_LOCK) {
+ break;
+ }
+ }
+
+ /* check for timeout */
+ if (timeout > 0) {
+ struct timeval curtime;
+ gettimeofday(&curtime, NULL);
+ if ((curtime.tv_sec > endtime.tv_sec) ||
+ ((curtime.tv_sec == endtime.tv_sec) && (curtime.tv_usec >= endtime.tv_usec))) {
+ break;
+ }
+ }
+
+ /* delay for a bit */
+ usleep(100000);
+ }
+
+ /* exit */
+ if (status & FE_HAS_LOCK)
+ return 0;
+ return -ETIMEDOUT;
+}
+
+int dvbfe_get_pollfd(struct dvbfe_handle *handle)
+{
+ return handle->fd;
+}
+
+int dvbfe_set_22k_tone(struct dvbfe_handle *fehandle, enum dvbfe_sec_tone_mode tone)
+{
+ int ret = 0;
+
+ switch (tone) {
+ case DVBFE_SEC_TONE_OFF:
+ ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF);
+ break;
+ case DVBFE_SEC_TONE_ON:
+ ret = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON);
+ break;
+ default:
+ print(verbose, ERROR, 1, "Invalid command !");
+ break;
+ }
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed !");
+
+ return ret;
+}
+
+int dvbfe_set_tone_data_burst(struct dvbfe_handle *fehandle, enum dvbfe_sec_mini_cmd minicmd)
+{
+ int ret = 0;
+
+ switch (minicmd) {
+ case DVBFE_SEC_MINI_A:
+ ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A);
+ break;
+ case DVBFE_SEC_MINI_B:
+ ret = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B);
+ break;
+ default:
+ print(verbose, ERROR, 1, "Invalid command");
+ break;
+ }
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
+
+ return ret;
+}
+
+int dvbfe_set_voltage(struct dvbfe_handle *fehandle, enum dvbfe_sec_voltage voltage)
+{
+ int ret = 0;
+
+ switch (voltage) {
+ case DVBFE_SEC_VOLTAGE_OFF:
+ ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF);
+ break;
+ case DVBFE_SEC_VOLTAGE_13:
+ ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13);
+ break;
+ case DVBFE_SEC_VOLTAGE_18:
+ ret = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18);
+ break;
+ default:
+ print(verbose, ERROR, 1, "Invalid command");
+ break;
+ }
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
+
+ return ret;
+}
+
+int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on)
+{
+ switch (on) {
+ case 0:
+ ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0);
+ break;
+ default:
+ ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1);
+ break;
+ }
+ return 0;
+}
+
+int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *fehandle, unsigned int cmd)
+{
+ int ret = 0;
+
+ ret = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd);
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
+
+ return ret;
+}
+
+int dvbfe_do_diseqc_command(struct dvbfe_handle *fehandle, uint8_t *data, uint8_t len)
+{
+ int ret = 0;
+ struct dvb_diseqc_master_cmd diseqc_message;
+
+ if (len > 6)
+ return -EINVAL;
+
+ diseqc_message.msg_len = len;
+ memcpy(diseqc_message.msg, data, len);
+
+ ret = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &diseqc_message);
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
+
+ return ret;
+}
+
+int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len)
+{
+ struct dvb_diseqc_slave_reply reply;
+ int result;
+
+ if (len > 4)
+ len = 4;
+
+ reply.timeout = timeout;
+ reply.msg_len = len;
+
+ if ((result = ioctl(fehandle->fd, FE_DISEQC_RECV_SLAVE_REPLY, reply)) != 0)
+ return result;
+
+ if (reply.msg_len < len)
+ len = reply.msg_len;
+ memcpy(buf, reply.msg, len);
+
+ return len;
+}
diff --git a/lib/libdvbapi/dvbfe.h b/lib/libdvbapi/dvbfe.h
new file mode 100644
index 0000000..69cb05b
--- /dev/null
+++ b/lib/libdvbapi/dvbfe.h
@@ -0,0 +1,333 @@
+/*
+ * libdvbfe - a DVB frontend library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBFE_H
+#define LIBDVBFE_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * The types of frontend we support.
+ */
+enum dvbfe_type {
+ DVBFE_TYPE_DVBS,
+ DVBFE_TYPE_DVBC,
+ DVBFE_TYPE_DVBT,
+ DVBFE_TYPE_ATSC,
+};
+
+enum dvbfe_spectral_inversion {
+ DVBFE_INVERSION_OFF,
+ DVBFE_INVERSION_ON,
+ DVBFE_INVERSION_AUTO
+};
+
+enum dvbfe_code_rate {
+ DVBFE_FEC_NONE,
+ DVBFE_FEC_1_2,
+ DVBFE_FEC_2_3,
+ DVBFE_FEC_3_4,
+ DVBFE_FEC_4_5,
+ DVBFE_FEC_5_6,
+ DVBFE_FEC_6_7,
+ DVBFE_FEC_7_8,
+ DVBFE_FEC_8_9,
+ DVBFE_FEC_AUTO
+};
+
+enum dvbfe_dvbt_const {
+ DVBFE_DVBT_CONST_QPSK,
+ DVBFE_DVBT_CONST_QAM_16,
+ DVBFE_DVBT_CONST_QAM_32,
+ DVBFE_DVBT_CONST_QAM_64,
+ DVBFE_DVBT_CONST_QAM_128,
+ DVBFE_DVBT_CONST_QAM_256,
+ DVBFE_DVBT_CONST_AUTO
+};
+
+enum dvbfe_dvbc_mod {
+ DVBFE_DVBC_MOD_QAM_16,
+ DVBFE_DVBC_MOD_QAM_32,
+ DVBFE_DVBC_MOD_QAM_64,
+ DVBFE_DVBC_MOD_QAM_128,
+ DVBFE_DVBC_MOD_QAM_256,
+ DVBFE_DVBC_MOD_AUTO,
+};
+
+enum dvbfe_atsc_mod {
+ DVBFE_ATSC_MOD_QAM_64,
+ DVBFE_ATSC_MOD_QAM_256,
+ DVBFE_ATSC_MOD_VSB_8,
+ DVBFE_ATSC_MOD_VSB_16,
+ DVBFE_ATSC_MOD_AUTO
+};
+
+enum dvbfe_dvbt_transmit_mode {
+ DVBFE_DVBT_TRANSMISSION_MODE_2K,
+ DVBFE_DVBT_TRANSMISSION_MODE_8K,
+ DVBFE_DVBT_TRANSMISSION_MODE_AUTO
+};
+
+enum dvbfe_dvbt_bandwidth {
+ DVBFE_DVBT_BANDWIDTH_8_MHZ,
+ DVBFE_DVBT_BANDWIDTH_7_MHZ,
+ DVBFE_DVBT_BANDWIDTH_6_MHZ,
+ DVBFE_DVBT_BANDWIDTH_AUTO
+};
+
+enum dvbfe_dvbt_guard_interval {
+ DVBFE_DVBT_GUARD_INTERVAL_1_32,
+ DVBFE_DVBT_GUARD_INTERVAL_1_16,
+ DVBFE_DVBT_GUARD_INTERVAL_1_8,
+ DVBFE_DVBT_GUARD_INTERVAL_1_4,
+ DVBFE_DVBT_GUARD_INTERVAL_AUTO
+};
+
+enum dvbfe_dvbt_hierarchy {
+ DVBFE_DVBT_HIERARCHY_NONE,
+ DVBFE_DVBT_HIERARCHY_1,
+ DVBFE_DVBT_HIERARCHY_2,
+ DVBFE_DVBT_HIERARCHY_4,
+ DVBFE_DVBT_HIERARCHY_AUTO
+};
+
+/**
+ * Structure used to store and communicate frontend parameters.
+ */
+struct dvbfe_parameters {
+ uint32_t frequency;
+ enum dvbfe_spectral_inversion inversion;
+ union {
+ struct {
+ uint32_t symbol_rate;
+ enum dvbfe_code_rate fec_inner;
+ } dvbs;
+
+ struct {
+ uint32_t symbol_rate;
+ enum dvbfe_code_rate fec_inner;
+ enum dvbfe_dvbc_mod modulation;
+ } dvbc;
+
+ struct {
+ enum dvbfe_dvbt_bandwidth bandwidth;
+ enum dvbfe_code_rate code_rate_HP;
+ enum dvbfe_code_rate code_rate_LP;
+ enum dvbfe_dvbt_const constellation;
+ enum dvbfe_dvbt_transmit_mode transmission_mode;
+ enum dvbfe_dvbt_guard_interval guard_interval;
+ enum dvbfe_dvbt_hierarchy hierarchy_information;
+ } dvbt;
+
+ struct {
+ enum dvbfe_atsc_mod modulation;
+ } atsc;
+ } u;
+};
+
+enum dvbfe_sec_voltage {
+ DVBFE_SEC_VOLTAGE_13,
+ DVBFE_SEC_VOLTAGE_18,
+ DVBFE_SEC_VOLTAGE_OFF
+};
+
+enum dvbfe_sec_tone_mode {
+ DVBFE_SEC_TONE_ON,
+ DVBFE_SEC_TONE_OFF
+};
+
+enum dvbfe_sec_mini_cmd {
+ DVBFE_SEC_MINI_A,
+ DVBFE_SEC_MINI_B
+};
+
+/**
+ * Mask of values used in the dvbfe_get_info() call.
+ */
+enum dvbfe_info_mask {
+ DVBFE_INFO_LOCKSTATUS = 0x01,
+ DVBFE_INFO_FEPARAMS = 0x02,
+ DVBFE_INFO_BER = 0x04,
+ DVBFE_INFO_SIGNAL_STRENGTH = 0x08,
+ DVBFE_INFO_SNR = 0x10,
+ DVBFE_INFO_UNCORRECTED_BLOCKS = 0x20,
+};
+
+/**
+ * Structure containing values used by the dvbfe_get_info() call.
+ */
+struct dvbfe_info {
+ enum dvbfe_type type; /* always retrieved */
+ const char *name; /* always retrieved */
+ unsigned int signal : 1; /* } DVBFE_INFO_LOCKSTATUS */
+ unsigned int carrier : 1; /* } */
+ unsigned int viterbi : 1; /* } */
+ unsigned int sync : 1; /* } */
+ unsigned int lock : 1; /* } */
+ struct dvbfe_parameters feparams; /* DVBFE_INFO_FEPARAMS */
+ uint32_t ber; /* DVBFE_INFO_BER */
+ uint16_t signal_strength; /* DVBFE_INFO_SIGNAL_STRENGTH */
+ uint16_t snr; /* DVBFE_INFO_SNR */
+ uint32_t ucblocks; /* DVBFE_INFO_UNCORRECTED_BLOCKS */
+};
+
+/**
+ * Possible types of query used in dvbfe_get_info.
+ *
+ * DVBFE_INFO_QUERYTYPE_IMMEDIATE - interrogate frontend for most up to date values.
+ * DVBFE_INFO_QUERYTYPE_LOCKCHANGE - return details from queued lock status
+ * change events, or wait for one to occur
+ * if none are queued.
+ */
+enum dvbfe_info_querytype {
+ DVBFE_INFO_QUERYTYPE_IMMEDIATE,
+ DVBFE_INFO_QUERYTYPE_LOCKCHANGE,
+};
+
+
+/**
+ * Frontend handle datatype.
+ */
+struct dvbfe_handle;
+
+/**
+ * Open a DVB frontend.
+ *
+ * @param adapter DVB adapter ID.
+ * @param frontend Frontend ID of that adapter to open.
+ * @param readonly If 1, frontend will be opened in readonly mode only.
+ * @return A handle on success, or NULL on failure.
+ */
+extern struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly);
+
+/**
+ * Close a DVB frontend.
+ *
+ * @param fehandle Handle opened with dvbfe_open().
+ */
+extern void dvbfe_close(struct dvbfe_handle *handle);
+
+/**
+ * Set the frontend tuning parameters.
+ *
+ * Note: this function provides only the basic tuning operation; you might want to
+ * investigate dvbfe_set_sec() in sec.h for a unified device tuning operation.
+ *
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param params Params to set.
+ * @param timeout <0 => wait forever for lock. 0=>return immediately, >0=>
+ * number of milliseconds to wait for a lock.
+ * @return 0 on locked (or if timeout==0 and everything else worked), or
+ * nonzero on failure (including no lock).
+ */
+extern int dvbfe_set(struct dvbfe_handle *fehandle,
+ struct dvbfe_parameters *params,
+ int timeout);
+
+/**
+ * Retrieve information about the frontend.
+ *
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param querymask ORed bitmask of desired DVBFE_INFO_* values.
+ * @param result Where to put the retrieved results.
+ * @param querytype Type of query requested.
+ * @param timeout Timeout in ms to use if querytype==lockchange (0=>no timeout, <0=> wait forever).
+ * @return ORed bitmask of DVBFE_INFO_* indicating which values were read successfully.
+ */
+extern int dvbfe_get_info(struct dvbfe_handle *fehandle,
+ enum dvbfe_info_mask querymask,
+ struct dvbfe_info *result,
+ enum dvbfe_info_querytype querytype,
+ int timeout);
+
+/**
+ * Get a file descriptor for polling for lock status changes.
+ *
+ * @param fehandle Handle opened with dvbfe_open().
+ * @return FD for polling.
+ */
+extern int dvbfe_get_pollfd(struct dvbfe_handle *handle);
+
+/**
+ * Tone/Data Burst control
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param tone, SEC_TONE_ON/SEC_TONE_OFF
+ */
+extern int dvbfe_set_22k_tone(struct dvbfe_handle *handle, enum dvbfe_sec_tone_mode tone);
+
+/**
+ * 22khz Tone control
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param adapter, minicmd, SEC_MINI_A/SEC_MINI_B
+ */
+extern int dvbfe_set_tone_data_burst(struct dvbfe_handle *handle, enum dvbfe_sec_mini_cmd minicmd);
+
+/**
+ * Voltage control
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param polarization, SEC_VOLTAGE_13/SEC_VOLTAGE_18/SEC_VOLTAGE_OFF
+ */
+extern int dvbfe_set_voltage(struct dvbfe_handle *handle, enum dvbfe_sec_voltage voltage);
+
+/**
+ * High LNB voltage control (increases voltage by 1v to compensate for long cables)
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param on 1 to enable, 0 to disable.
+ */
+extern int dvbfe_set_high_lnb_voltage(struct dvbfe_handle *fehandle, int on);
+
+/**
+ * Send a legacy Dish Networks command
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param cmd, the command to send
+ */
+extern int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *handle, unsigned int cmd);
+
+/**
+ * Send a DiSEqC Command
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param data, a pointer to am array containing the data to be sent.
+ * @param len Length of data in bytes, max 6 bytes.
+ */
+extern int dvbfe_do_diseqc_command(struct dvbfe_handle *handle, uint8_t *data, uint8_t len);
+
+/**
+ * Read a DISEQC response from the frontend.
+ *
+ * @param fehandle Handle opened with dvbfe_open().
+ * @param timeout Timeout for DISEQC response.
+ * @param buf Buffer to store response in.
+ * @param len Number of bytes in buffer.
+ * @return >= 0 on success (number of received bytes), <0 on failure.
+ */
+extern int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBFE_H
diff --git a/lib/libdvbapi/dvbnet.c b/lib/libdvbapi/dvbnet.c
new file mode 100644
index 0000000..f0f08f9
--- /dev/null
+++ b/lib/libdvbapi/dvbnet.c
@@ -0,0 +1,104 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/dvb/net.h>
+#include <errno.h>
+#include "dvbnet.h"
+
+int dvbnet_open(int adapter, int netdeviceid)
+{
+ char filename[PATH_MAX+1];
+ int fd;
+
+ sprintf(filename, "/dev/dvb/adapter%i/net%i", adapter, netdeviceid);
+ if ((fd = open(filename, O_RDWR)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.net%i", adapter, netdeviceid);
+ fd = open(filename, O_RDWR);
+ }
+
+ return fd;
+}
+
+int dvbnet_add_interface(int fd, uint16_t pid, enum dvbnet_encap encapsulation)
+{
+ struct dvb_net_if params;
+ int status;
+
+ memset(&params, 0, sizeof(params));
+ params.pid = pid;
+
+ switch(encapsulation) {
+ case DVBNET_ENCAP_MPE:
+ params.feedtype = DVB_NET_FEEDTYPE_MPE;
+ break;
+
+ case DVBNET_ENCAP_ULE:
+ params.feedtype = DVB_NET_FEEDTYPE_ULE;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ status = ioctl(fd, NET_ADD_IF, &params);
+ if (status < 0)
+ return status;
+ return params.if_num;
+}
+
+int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation)
+{
+ struct dvb_net_if info;
+ int res;
+
+ memset(&info, 0, sizeof(struct dvb_net_if));
+ info.if_num = ifnum;
+
+ if ((res = ioctl(fd, NET_GET_IF, &info)) < 0)
+ return res;
+
+ *pid = info.pid;
+ switch(info.feedtype) {
+ case DVB_NET_FEEDTYPE_MPE:
+ *encapsulation = DVBNET_ENCAP_MPE;
+ break;
+
+ case DVB_NET_FEEDTYPE_ULE:
+ *encapsulation = DVBNET_ENCAP_ULE;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int dvbnet_remove_interface(int fd, int ifnum)
+{
+ return ioctl(fd, NET_REMOVE_IF, ifnum);
+}
diff --git a/lib/libdvbapi/dvbnet.h b/lib/libdvbapi/dvbnet.h
new file mode 100644
index 0000000..287919f
--- /dev/null
+++ b/lib/libdvbapi/dvbnet.h
@@ -0,0 +1,87 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBNET_H
+#define LIBDVBNET_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * Possible encapsulations of data.
+ */
+enum dvbnet_encap {
+ DVBNET_ENCAP_MPE,
+ DVBNET_ENCAP_ULE,
+};
+
+/**
+ * The maximum allowed number of dvb network devices per adapter netdevice.
+ */
+#define DVBNET_MAX_INTERFACES 10
+
+/**
+ * Open a DVB net interface.
+ *
+ * @param adapter DVB adapter ID.
+ * @param netdeviceid Network control interface of that adapter to open.
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbnet_open(int adapter, int netdeviceid);
+
+/**
+ * Create a new DVBNET interface.
+ *
+ * @param fd FD opened with libdvbnet_open().
+ * @param pid PID of the stream containing the network data.
+ * @param encapsulation Encapsulation type of the stream (one of DVBNET_ENCAP_*).
+ * @return Index of new interface on success, < 0 on failure.
+ */
+extern int dvbnet_add_interface(int fd, uint16_t pid, enum dvbnet_encap encapsulation);
+
+/**
+ * Get details of a DVBNET interface.
+ *
+ * @param fd FD opened with libdvbnet_open().
+ * @param ifnum Index of interface to retrieve.
+ * @param pid The PID of the interface.
+ * @param encapsulation The encapsulation of the interface (DVBNET_ENCAP_*).
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation);
+
+/**
+ * Remove a DVBNET interface.
+ *
+ * @param fd FD opened with libdvbnet_open().
+ * @param ifnum Index of interface to remove.
+ * @return 0 on success, nonzero on failure.
+ */
+extern int dvbnet_remove_interface(int fd, int ifnum);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBNET_H
diff --git a/lib/libdvbapi/dvbvideo.c b/lib/libdvbapi/dvbvideo.c
new file mode 100644
index 0000000..f1ffbe8
--- /dev/null
+++ b/lib/libdvbapi/dvbvideo.c
@@ -0,0 +1,46 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/dvb/video.h>
+#include <errno.h>
+#include "dvbvideo.h"
+
+int dvbvideo_open(int adapter, int videodeviceid)
+{
+ char filename[PATH_MAX+1];
+ int fd;
+
+ sprintf(filename, "/dev/dvb/adapter%i/video%i", adapter, videodeviceid);
+ if ((fd = open(filename, O_RDWR)) < 0) {
+ // if that failed, try a flat /dev structure
+ sprintf(filename, "/dev/dvb%i.video%i", adapter, videodeviceid);
+ fd = open(filename, O_RDWR);
+ }
+
+ return fd;
+}
diff --git a/lib/libdvbapi/dvbvideo.h b/lib/libdvbapi/dvbvideo.h
new file mode 100644
index 0000000..cc49914
--- /dev/null
+++ b/lib/libdvbapi/dvbvideo.h
@@ -0,0 +1,46 @@
+/*
+ * libdvbnet - a DVB network support library
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef LIBDVBVIDEO_H
+#define LIBDVBVIDEO_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * Open a DVB video device.
+ *
+ * @param adapter DVB adapter ID.
+ * @param videodeviceid Id of video device of that adapter to open.
+ * @return A unix file descriptor on success, or -1 on failure.
+ */
+extern int dvbvideo_open(int adapter, int videodeviceid);
+
+// FIXME: this is a stub library
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // LIBDVBVIDEO_H
diff --git a/lib/libdvbcfg/Makefile b/lib/libdvbcfg/Makefile
new file mode 100644
index 0000000..5e5e365
--- /dev/null
+++ b/lib/libdvbcfg/Makefile
@@ -0,0 +1,18 @@
+# Makefile for linuxtv.org dvb-apps/lib/libdvbcfg
+
+includes = dvbcfg_zapchannel.h \
+ dvbcfg_scanfile.h
+
+objects = dvbcfg_zapchannel.o \
+ dvbcfg_scanfile.o \
+ dvbcfg_common.o
+
+lib_name = libdvbcfg
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include ../../Make.rules
diff --git a/lib/libdvbcfg/dvbcfg_common.c b/lib/libdvbcfg/dvbcfg_common.c
new file mode 100644
index 0000000..1609e51
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_common.c
@@ -0,0 +1,136 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * common functions
+ *
+ * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include "dvbcfg_common.h"
+
+int dvbcfg_parse_int(char **text, char *tokens)
+{
+ char *start = *text;
+ char *stop = *text;
+ int value;
+
+ while (*stop != '\0') {
+ if (strchr(tokens, *stop) != NULL) {
+ *stop = '\0';
+ stop++;
+ break;
+ }
+ stop++;
+ }
+
+ if (sscanf(start, "%i", &value) == 1) {
+ *text = stop;
+ return value;
+ }
+
+ *text = NULL;
+ return -1;
+}
+
+int dvbcfg_parse_char(char **text, char *tokens)
+{
+ char *start = *text;
+ char *stop = *text;
+ char value;
+
+ while (*stop != '\0') {
+ if (strchr(tokens, *stop) != NULL) {
+ *stop = '\0';
+ stop++;
+ break;
+ }
+ stop++;
+ }
+
+ if (sscanf(start, "%c", &value) == 1) {
+ *text = stop;
+ return value;
+ }
+
+ *text = NULL;
+ return -1;
+}
+
+int dvbcfg_parse_setting(char **text, char *tokens, const struct dvbcfg_setting *settings)
+{
+ char *start = *text;
+ char *stop = *text;
+
+ while (*stop != '\0') {
+ if (strchr(tokens, *stop) != NULL) {
+ *stop = '\0';
+ stop++;
+ break;
+ }
+ stop++;
+ }
+
+ while (settings->name) {
+ if (strcmp(start, settings->name) == 0) {
+ *text = stop;
+ return settings->value;
+ }
+ settings++;
+ }
+
+ *text = NULL;
+ return -1;
+}
+
+void dvbcfg_parse_string(char **text, char *tokens, char *dest, unsigned long size)
+{
+ char *start = *text;
+ char *stop = *text;
+ unsigned long length;
+
+ while ((*stop != '\0') && (strchr(tokens, *stop) == NULL))
+ stop++;
+
+ length = (stop - start) + 1;
+
+ if (length <= size) {
+ if (strchr(tokens, *stop) != NULL) {
+ *stop = '\0';
+ *text = stop + 1;
+ } else
+ *text = stop;
+ memcpy(dest, start, length);
+ return;
+ }
+
+ *text = NULL;
+ return;
+}
+
+const char *dvbcfg_lookup_setting(unsigned int setting, const struct dvbcfg_setting *settings)
+{
+ while (settings->name) {
+ if (setting == settings->value)
+ return settings->name;
+ settings++;
+ }
+
+ return NULL;
+}
diff --git a/lib/libdvbcfg/dvbcfg_common.h b/lib/libdvbcfg/dvbcfg_common.h
new file mode 100644
index 0000000..2b5e876
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_common.h
@@ -0,0 +1,37 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * common functions
+ *
+ * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef DVBCFG_COMMON_H
+#define DVBCFG_COMMON_H 1
+
+struct dvbcfg_setting {
+ const char *name;
+ unsigned int value;
+};
+
+extern int dvbcfg_parse_int(char **text, char *tokens);
+extern int dvbcfg_parse_char(char **text, char *tokens);
+extern int dvbcfg_parse_setting(char **text, char *tokens, const struct dvbcfg_setting *settings);
+extern void dvbcfg_parse_string(char **text, char *tokens, char *dest, unsigned long size);
+extern const char *dvbcfg_lookup_setting(unsigned int setting, const struct dvbcfg_setting *settings);
+
+#endif
diff --git a/lib/libdvbcfg/dvbcfg_scanfile.c b/lib/libdvbcfg/dvbcfg_scanfile.c
new file mode 100644
index 0000000..ec305a4
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_scanfile.c
@@ -0,0 +1,282 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * scan channel file support
+ *
+ * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _GNU_SOURCE
+
+#include <malloc.h>
+#include <ctype.h>
+
+#include "dvbcfg_scanfile.h"
+#include "dvbcfg_common.h"
+
+static const struct dvbcfg_setting dvbcfg_fec_list[] = {
+ { "1/2", DVBFE_FEC_1_2 },
+ { "2/3", DVBFE_FEC_2_3 },
+ { "3/4", DVBFE_FEC_3_4 },
+ { "4/5", DVBFE_FEC_4_5 },
+ { "5/6", DVBFE_FEC_5_6 },
+ { "6/7", DVBFE_FEC_6_7 },
+ { "7/8", DVBFE_FEC_7_8 },
+ { "8/9", DVBFE_FEC_8_9 },
+ { "AUTO", DVBFE_FEC_AUTO },
+ { "NONE", DVBFE_FEC_NONE },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_dvbc_modulation_list[] = {
+ { "QAM16", DVBFE_DVBC_MOD_QAM_16 },
+ { "QAM32", DVBFE_DVBC_MOD_QAM_32 },
+ { "QAM64", DVBFE_DVBC_MOD_QAM_64 },
+ { "QAM128", DVBFE_DVBC_MOD_QAM_128 },
+ { "QAM256", DVBFE_DVBC_MOD_QAM_256 },
+ { "AUTO", DVBFE_DVBC_MOD_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_bandwidth_list[] = {
+ { "6MHz", DVBFE_DVBT_BANDWIDTH_6_MHZ },
+ { "7MHz", DVBFE_DVBT_BANDWIDTH_7_MHZ },
+ { "8MHz", DVBFE_DVBT_BANDWIDTH_8_MHZ },
+ { "AUTO", DVBFE_DVBT_BANDWIDTH_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_constellation_list[] = {
+ { "QAM16", DVBFE_DVBT_CONST_QAM_16 },
+ { "QAM32", DVBFE_DVBT_CONST_QAM_32 },
+ { "QAM64", DVBFE_DVBT_CONST_QAM_64 },
+ { "QAM128", DVBFE_DVBT_CONST_QAM_128 },
+ { "QAM256", DVBFE_DVBT_CONST_QAM_256 },
+ { "QPSK", DVBFE_DVBT_CONST_QPSK },
+ { "AUTO", DVBFE_DVBT_CONST_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_transmission_mode_list[] = {
+ { "2k", DVBFE_DVBT_TRANSMISSION_MODE_2K },
+ { "8k", DVBFE_DVBT_TRANSMISSION_MODE_8K },
+ { "AUTO", DVBFE_DVBT_TRANSMISSION_MODE_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_guard_interval_list[] = {
+ { "1/32", DVBFE_DVBT_GUARD_INTERVAL_1_32 },
+ { "1/16", DVBFE_DVBT_GUARD_INTERVAL_1_16 },
+ { "1/8", DVBFE_DVBT_GUARD_INTERVAL_1_8 },
+ { "1/4", DVBFE_DVBT_GUARD_INTERVAL_1_4 },
+ { "AUTO", DVBFE_DVBT_GUARD_INTERVAL_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_hierarchy_list[] = {
+ { "1", DVBFE_DVBT_HIERARCHY_1 },
+ { "2", DVBFE_DVBT_HIERARCHY_2 },
+ { "4", DVBFE_DVBT_HIERARCHY_4 },
+ { "AUTO", DVBFE_DVBT_HIERARCHY_AUTO },
+ { "NONE", DVBFE_DVBT_HIERARCHY_NONE },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_atsc_modulation_list[] = {
+ { "8VSB", DVBFE_ATSC_MOD_VSB_8 },
+ { "16VSB", DVBFE_ATSC_MOD_VSB_16 },
+ { "QAM64", DVBFE_ATSC_MOD_QAM_64 },
+ { "QAM256", DVBFE_ATSC_MOD_QAM_256 },
+ { NULL, 0 }
+};
+
+int dvbcfg_scanfile_parse(FILE *file, dvbcfg_scancallback callback, void *private_data)
+{
+ char *line_buf = NULL;
+ size_t line_size = 0;
+ int line_len = 0;
+ int ret_val = 0;
+
+ while ((line_len = getline(&line_buf, &line_size, file)) > 0) {
+ char *line_tmp = line_buf;
+ char *line_pos = line_buf;
+ struct dvbcfg_scanfile tmp;
+
+ /* remove newline and comments (started with hashes) */
+ while ((*line_tmp != '\0') && (*line_tmp != '\n') && (*line_tmp != '#'))
+ line_tmp++;
+ *line_tmp = '\0';
+
+ /* always use inversion auto */
+ tmp.fe_params.inversion = DVBFE_INVERSION_AUTO;
+
+ /* parse frontend type */
+ switch(dvbcfg_parse_char(&line_pos, " ")) {
+ case 'T':
+ tmp.fe_type = DVBFE_TYPE_DVBT;
+ break;
+ case 'C':
+ tmp.fe_type = DVBFE_TYPE_DVBC;
+ break;
+ case 'S':
+ tmp.fe_type = DVBFE_TYPE_DVBS;
+ break;
+ case 'A':
+ tmp.fe_type = DVBFE_TYPE_ATSC;
+ break;
+ default:
+ continue;
+ }
+
+ /* parse frontend specific settings */
+ switch (tmp.fe_type) {
+ case DVBFE_TYPE_ATSC:
+
+ /* parse frequency */
+ tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* modulation */
+ tmp.fe_params.u.atsc.modulation =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_atsc_modulation_list);
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBC:
+
+ /* parse frequency */
+ tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* symbol rate */
+ tmp.fe_params.u.dvbc.symbol_rate = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* fec */
+ tmp.fe_params.u.dvbc.fec_inner =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* modulation */
+ tmp.fe_params.u.dvbc.modulation =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_dvbc_modulation_list);
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBS:
+
+ /* parse frequency */
+ tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* polarization */
+ tmp.polarization = tolower(dvbcfg_parse_char(&line_pos, " "));
+ if (!line_pos)
+ continue;
+ if ((tmp.polarization != 'h') &&
+ (tmp.polarization != 'v') &&
+ (tmp.polarization != 'l') &&
+ (tmp.polarization != 'r'))
+ continue;
+
+ /* symbol rate */
+ tmp.fe_params.u.dvbs.symbol_rate = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* fec */
+ tmp.fe_params.u.dvbc.fec_inner =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBT:
+
+ /* parse frequency */
+ tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, " ");
+ if (!line_pos)
+ continue;
+
+ /* bandwidth */
+ tmp.fe_params.u.dvbt.bandwidth =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_bandwidth_list);
+ if (!line_pos)
+ continue;
+
+ /* fec hp */
+ tmp.fe_params.u.dvbt.code_rate_HP =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* fec lp */
+ tmp.fe_params.u.dvbt.code_rate_LP =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* constellation */
+ tmp.fe_params.u.dvbt.constellation =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_constellation_list);
+ if (!line_pos)
+ continue;
+
+ /* transmission mode */
+ tmp.fe_params.u.dvbt.transmission_mode =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_transmission_mode_list);
+ if (!line_pos)
+ continue;
+
+ /* guard interval */
+ tmp.fe_params.u.dvbt.guard_interval =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_guard_interval_list);
+ if (!line_pos)
+ continue;
+
+ /* hierarchy */
+ tmp.fe_params.u.dvbt.hierarchy_information =
+ dvbcfg_parse_setting(&line_pos, " ", dvbcfg_hierarchy_list);
+ if (!line_pos)
+ continue;
+
+ break;
+ }
+
+ /* invoke callback */
+ if ((ret_val = callback(&tmp, private_data)) != 0) {
+ if (ret_val < 0)
+ ret_val = 0;
+ break;
+ }
+ }
+
+ if (line_buf)
+ free(line_buf);
+
+ return ret_val;
+}
diff --git a/lib/libdvbcfg/dvbcfg_scanfile.h b/lib/libdvbcfg/dvbcfg_scanfile.h
new file mode 100644
index 0000000..d7a20b1
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_scanfile.h
@@ -0,0 +1,61 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * scan channel file support
+ *
+ * Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef DVBCFG_SCANFILE_H
+#define DVBCFG_SCANFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libdvbapi/dvbfe.h>
+#include <stdio.h>
+
+struct dvbcfg_scanfile {
+ enum dvbfe_type fe_type;
+ struct dvbfe_parameters fe_params;
+ char polarization; /* l,r,v,h - only used for dvb-s */
+};
+
+/**
+ * Callback used in dvbcfg_scanfile_parse()
+ *
+ * @param channel Selected channel
+ * @param private_data Private data for the callback
+ * @return 0 to continue, other values to stop (values > 0 are forwarded; see below)
+ */
+typedef int (*dvbcfg_scancallback)(struct dvbcfg_scanfile *channel, void *private_data);
+
+/**
+ * Parse a linuxtv scan file
+ *
+ * @param file Linuxtv scan file
+ * @param callback Callback called for each scan entry
+ * @param private_data Private data for the callback
+ * @return on success 0 or value from the callback if it's > 0, error code on failure
+ */
+extern int dvbcfg_scanfile_parse(FILE *file, dvbcfg_scancallback callback, void *private_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DVBCFG_SCANFILE_H */
diff --git a/lib/libdvbcfg/dvbcfg_zapchannel.c b/lib/libdvbcfg/dvbcfg_zapchannel.c
new file mode 100644
index 0000000..2c2605e
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_zapchannel.c
@@ -0,0 +1,384 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * zap channel file support
+ *
+ * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define _GNU_SOURCE
+
+#include <malloc.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "dvbcfg_zapchannel.h"
+#include "dvbcfg_common.h"
+
+static const struct dvbcfg_setting dvbcfg_inversion_list[] = {
+ { "INVERSION_ON", DVBFE_INVERSION_ON },
+ { "INVERSION_OFF", DVBFE_INVERSION_OFF },
+ { "INVERSION_AUTO", DVBFE_INVERSION_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_fec_list[] = {
+ { "FEC_1_2", DVBFE_FEC_1_2 },
+ { "FEC_2_3", DVBFE_FEC_2_3 },
+ { "FEC_3_4", DVBFE_FEC_3_4 },
+ { "FEC_4_5", DVBFE_FEC_4_5 },
+ { "FEC_5_6", DVBFE_FEC_5_6 },
+ { "FEC_6_7", DVBFE_FEC_6_7 },
+ { "FEC_7_8", DVBFE_FEC_7_8 },
+ { "FEC_8_9", DVBFE_FEC_8_9 },
+ { "FEC_AUTO", DVBFE_FEC_AUTO },
+ { "FEC_NONE", DVBFE_FEC_NONE },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_dvbc_modulation_list[] = {
+ { "QAM_16", DVBFE_DVBC_MOD_QAM_16 },
+ { "QAM_32", DVBFE_DVBC_MOD_QAM_32 },
+ { "QAM_64", DVBFE_DVBC_MOD_QAM_64 },
+ { "QAM_128", DVBFE_DVBC_MOD_QAM_128 },
+ { "QAM_256", DVBFE_DVBC_MOD_QAM_256 },
+ { "QAM_AUTO", DVBFE_DVBC_MOD_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_bandwidth_list[] = {
+ { "BANDWIDTH_6_MHZ", DVBFE_DVBT_BANDWIDTH_6_MHZ },
+ { "BANDWIDTH_7_MHZ", DVBFE_DVBT_BANDWIDTH_7_MHZ },
+ { "BANDWIDTH_8_MHZ", DVBFE_DVBT_BANDWIDTH_8_MHZ },
+ { "BANDWIDTH_AUTO", DVBFE_DVBT_BANDWIDTH_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_constellation_list[] = {
+ { "QAM_16", DVBFE_DVBT_CONST_QAM_16 },
+ { "QAM_32", DVBFE_DVBT_CONST_QAM_32 },
+ { "QAM_64", DVBFE_DVBT_CONST_QAM_64 },
+ { "QAM_128", DVBFE_DVBT_CONST_QAM_128 },
+ { "QAM_256", DVBFE_DVBT_CONST_QAM_256 },
+ { "QPSK", DVBFE_DVBT_CONST_QPSK },
+ { "QAM_AUTO", DVBFE_DVBT_CONST_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_transmission_mode_list[] = {
+ { "TRANSMISSION_MODE_2K", DVBFE_DVBT_TRANSMISSION_MODE_2K },
+ { "TRANSMISSION_MODE_8K", DVBFE_DVBT_TRANSMISSION_MODE_8K },
+ { "TRANSMISSION_MODE_AUTO", DVBFE_DVBT_TRANSMISSION_MODE_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_guard_interval_list[] = {
+ { "GUARD_INTERVAL_1_32", DVBFE_DVBT_GUARD_INTERVAL_1_32 },
+ { "GUARD_INTERVAL_1_16", DVBFE_DVBT_GUARD_INTERVAL_1_16 },
+ { "GUARD_INTERVAL_1_8", DVBFE_DVBT_GUARD_INTERVAL_1_8 },
+ { "GUARD_INTERVAL_1_4", DVBFE_DVBT_GUARD_INTERVAL_1_4 },
+ { "GUARD_INTERVAL_AUTO", DVBFE_DVBT_GUARD_INTERVAL_AUTO },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_hierarchy_list[] = {
+ { "HIERARCHY_1", DVBFE_DVBT_HIERARCHY_1 },
+ { "HIERARCHY_2", DVBFE_DVBT_HIERARCHY_2 },
+ { "HIERARCHY_4", DVBFE_DVBT_HIERARCHY_4 },
+ { "HIERARCHY_AUTO", DVBFE_DVBT_HIERARCHY_AUTO },
+ { "HIERARCHY_NONE", DVBFE_DVBT_HIERARCHY_NONE },
+ { NULL, 0 }
+};
+
+static const struct dvbcfg_setting dvbcfg_atsc_modulation_list[] = {
+ { "8VSB", DVBFE_ATSC_MOD_VSB_8 },
+ { "16VSB", DVBFE_ATSC_MOD_VSB_16 },
+ { "QAM_64", DVBFE_ATSC_MOD_QAM_64 },
+ { "QAM_256", DVBFE_ATSC_MOD_QAM_256 },
+ { NULL, 0 }
+};
+
+int dvbcfg_zapchannel_parse(FILE *file, dvbcfg_zapcallback callback, void *private_data)
+{
+ char *line_buf = NULL;
+ size_t line_size = 0;
+ int line_len = 0;
+ int ret_val = 0;
+
+ while ((line_len = getline(&line_buf, &line_size, file)) > 0) {
+ char *line_tmp = line_buf;
+ char *line_pos = line_buf;
+ struct dvbcfg_zapchannel tmp;
+
+ /* remove newline and comments (started with hashes) */
+ while ((*line_tmp != '\0') && (*line_tmp != '\n') && (*line_tmp != '#'))
+ line_tmp++;
+ *line_tmp = '\0';
+
+ /* parse name */
+ dvbcfg_parse_string(&line_pos, ":", tmp.name, sizeof(tmp.name));
+ if (!line_pos)
+ continue;
+
+ /* parse frequency */
+ tmp.fe_params.frequency = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos)
+ continue;
+
+ /* try to determine frontend type */
+ if (strstr(line_pos, ":FEC_")) {
+ if (strstr(line_pos, ":HIERARCHY_"))
+ tmp.fe_type = DVBFE_TYPE_DVBT;
+ else
+ tmp.fe_type = DVBFE_TYPE_DVBC;
+ } else {
+ if (strstr(line_pos, "VSB:") || strstr(line_pos, "QAM_"))
+ tmp.fe_type = DVBFE_TYPE_ATSC;
+ else
+ tmp.fe_type = DVBFE_TYPE_DVBS;
+ }
+
+ /* parse frontend specific settings */
+ switch (tmp.fe_type) {
+ case DVBFE_TYPE_ATSC:
+ /* inversion */
+ tmp.fe_params.inversion = DVBFE_INVERSION_AUTO;
+
+ /* modulation */
+ tmp.fe_params.u.atsc.modulation =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_atsc_modulation_list);
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBC:
+ /* inversion */
+ tmp.fe_params.inversion =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_inversion_list);
+ if (!line_pos)
+ continue;
+
+ /* symbol rate */
+ tmp.fe_params.u.dvbc.symbol_rate = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos)
+ continue;
+
+ /* fec */
+ tmp.fe_params.u.dvbc.fec_inner =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* modulation */
+ tmp.fe_params.u.dvbc.modulation =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_dvbc_modulation_list);
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBS:
+ /* adjust frequency */
+ tmp.fe_params.frequency *= 1000;
+
+ /* inversion */
+ tmp.fe_params.inversion = DVBFE_INVERSION_AUTO;
+
+ /* fec */
+ tmp.fe_params.u.dvbs.fec_inner = DVBFE_FEC_AUTO;
+
+ /* polarization */
+ tmp.polarization = tolower(dvbcfg_parse_char(&line_pos, ":"));
+ if (!line_pos)
+ continue;
+ if ((tmp.polarization != 'h') &&
+ (tmp.polarization != 'v') &&
+ (tmp.polarization != 'l') &&
+ (tmp.polarization != 'r'))
+ continue;
+
+ /* satellite switch position */
+ tmp.diseqc_switch = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos)
+ continue;
+
+ /* symbol rate */
+ tmp.fe_params.u.dvbs.symbol_rate =
+ dvbcfg_parse_int(&line_pos, ":") * 1000;
+ if (!line_pos)
+ continue;
+
+ break;
+
+ case DVBFE_TYPE_DVBT:
+ /* inversion */
+ tmp.fe_params.inversion =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_inversion_list);
+ if (!line_pos)
+ continue;
+
+ /* bandwidth */
+ tmp.fe_params.u.dvbt.bandwidth =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_bandwidth_list);
+ if (!line_pos)
+ continue;
+
+ /* fec hp */
+ tmp.fe_params.u.dvbt.code_rate_HP =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* fec lp */
+ tmp.fe_params.u.dvbt.code_rate_LP =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_fec_list);
+ if (!line_pos)
+ continue;
+
+ /* constellation */
+ tmp.fe_params.u.dvbt.constellation =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_constellation_list);
+ if (!line_pos)
+ continue;
+
+ /* transmission mode */
+ tmp.fe_params.u.dvbt.transmission_mode =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_transmission_mode_list);
+ if (!line_pos)
+ continue;
+
+ /* guard interval */
+ tmp.fe_params.u.dvbt.guard_interval =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_guard_interval_list);
+ if (!line_pos)
+ continue;
+
+ /* hierarchy */
+ tmp.fe_params.u.dvbt.hierarchy_information =
+ dvbcfg_parse_setting(&line_pos, ":", dvbcfg_hierarchy_list);
+ if (!line_pos)
+ continue;
+
+ break;
+ }
+
+ /* parse video and audio pids and service id */
+ tmp.video_pid = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos)
+ continue;
+ tmp.audio_pid = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos)
+ continue;
+ tmp.service_id = dvbcfg_parse_int(&line_pos, ":");
+ if (!line_pos) /* old files don't have a service id */
+ tmp.service_id = 0;
+
+ /* invoke callback */
+ if ((ret_val = callback(&tmp, private_data)) != 0) {
+ if (ret_val < 0)
+ ret_val = 0;
+ break;
+ }
+ }
+
+ if (line_buf)
+ free(line_buf);
+
+ return ret_val;
+}
+
+int dvbcfg_zapchannel_save(FILE *file, dvbcfg_zapcallback callback, void *private_data)
+{
+ int ret_val = 0;
+ struct dvbcfg_zapchannel tmp;
+
+ while ((ret_val = callback(&tmp, private_data)) == 0) {
+ /* name */
+ if ((ret_val = fprintf(file, "%s:", tmp.name)) < 0)
+ return ret_val;
+
+ /* frontend specific settings */
+ switch (tmp.fe_type) {
+ case DVBFE_TYPE_ATSC:
+ if ((ret_val = fprintf(file, "%i:%s:",
+ tmp.fe_params.frequency,
+ dvbcfg_lookup_setting(tmp.fe_params.u.atsc.modulation,
+ dvbcfg_atsc_modulation_list))) < 0)
+ return ret_val;
+
+ break;
+
+ case DVBFE_TYPE_DVBC:
+ if ((ret_val = fprintf(file, "%i:%s:%i:%s:%s:",
+ tmp.fe_params.frequency,
+ dvbcfg_lookup_setting(tmp.fe_params.inversion,
+ dvbcfg_inversion_list),
+ tmp.fe_params.u.dvbc.symbol_rate,
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbc.fec_inner,
+ dvbcfg_fec_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbc.modulation,
+ dvbcfg_dvbc_modulation_list))) < 0)
+ return ret_val;
+
+ break;
+
+ case DVBFE_TYPE_DVBS:
+ if ((ret_val = fprintf(file, "%i:%c:%i:%i:",
+ tmp.fe_params.frequency / 1000,
+ tolower(tmp.polarization),
+ tmp.diseqc_switch,
+ tmp.fe_params.u.dvbs.symbol_rate / 1000)) < 0)
+ return ret_val;
+
+ break;
+ case DVBFE_TYPE_DVBT:
+ if ((ret_val = fprintf(file, "%i:%s:%s:%s:%s:%s:%s:%s:%s:",
+ tmp.fe_params.frequency,
+ dvbcfg_lookup_setting(tmp.fe_params.inversion,
+ dvbcfg_inversion_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.bandwidth,
+ dvbcfg_bandwidth_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.code_rate_HP,
+ dvbcfg_fec_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.code_rate_LP,
+ dvbcfg_fec_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.constellation,
+ dvbcfg_constellation_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.transmission_mode,
+ dvbcfg_transmission_mode_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.guard_interval,
+ dvbcfg_guard_interval_list),
+ dvbcfg_lookup_setting(tmp.fe_params.u.dvbt.hierarchy_information,
+ dvbcfg_hierarchy_list))) < 0)
+ return ret_val;
+
+ break;
+ }
+
+ /* video and audio pids and service id */
+ if ((ret_val = fprintf(file, "%i:%i:%i\n",
+ tmp.video_pid, tmp.audio_pid, tmp.service_id)) < 0)
+ return ret_val;
+
+ }
+
+ if (ret_val < 0)
+ ret_val = 0;
+
+ return ret_val;
+}
diff --git a/lib/libdvbcfg/dvbcfg_zapchannel.h b/lib/libdvbcfg/dvbcfg_zapchannel.h
new file mode 100644
index 0000000..67ec62e
--- /dev/null
+++ b/lib/libdvbcfg/dvbcfg_zapchannel.h
@@ -0,0 +1,77 @@
+/*
+ * dvbcfg - support for linuxtv configuration files
+ * zap channel file support
+ *
+ * Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
+ * Copyright (C) 2005 Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef DVBCFG_ZAPCHANNEL_H
+#define DVBCFG_ZAPCHANNEL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libdvbapi/dvbfe.h>
+#include <stdio.h>
+
+struct dvbcfg_zapchannel {
+ char name[128];
+ int video_pid;
+ int audio_pid;
+ int service_id;
+ enum dvbfe_type fe_type;
+ struct dvbfe_parameters fe_params;
+ char polarization; /* l,r,v,h - only used for dvb-s */
+ int diseqc_switch; /* only used for dvb-s */
+};
+
+/**
+ * Callback used in dvbcfg_zapchannel_parse() and dvbcfg_zapchannel_save()
+ *
+ * @param channel Selected channel
+ * @param private_data Private data for the callback
+ * @return 0 to continue, other values to stop (values > 0 are forwarded; see below)
+ */
+typedef int (*dvbcfg_zapcallback)(struct dvbcfg_zapchannel *channel, void *private_data);
+
+/**
+ * Parse a linuxtv channel file
+ *
+ * @param file Linuxtv channel file
+ * @param callback Callback called for each channel
+ * @param private_data Private data for the callback
+ * @return on success 0 or value from the callback if it's > 0, error code on failure
+ */
+extern int dvbcfg_zapchannel_parse(FILE *file, dvbcfg_zapcallback callback, void *private_data);
+
+/**
+ * Save to a linuxtv channel file
+ *
+ * @param file Linuxtv channel file
+ * @param callback Callback called for each channel
+ * @param private_data Private data for the callback
+ * @return on success 0 or value from the callback if it's > 0, error code on failure
+ */
+extern int dvbcfg_zapchannel_save(FILE *file, dvbcfg_zapcallback callback, void *private_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DVBCFG_ZAPCHANNEL_H */
diff --git a/lib/libdvbcfg/zapchannel.txt b/lib/libdvbcfg/zapchannel.txt
new file mode 100644
index 0000000..cdfdb87
--- /dev/null
+++ b/lib/libdvbcfg/zapchannel.txt
@@ -0,0 +1,72 @@
+/**
+ * The zapchannel file format specifies tuning parameters for channels. Each line describes
+ * a single channel, and consists of multiple options separated by ':'. The exact
+ * format of each line depends on the DVB type of the channel (i.e. DVBS, DVBT, DVBC, or ATSC).
+ *
+ * Note: the lines have been split across multiple lines in the following due to length issues.
+ *
+ * The format for DVBT channels is:
+ *
+ * <name>:<frequency>:<inversion>:<bandwidth>:<fec_hp>:<fec_lp>:
+ * <constellation>:<transmission>:<guard_interval>:<hierarchy>:
+ * <video_pid>:<audio_pid>:<channel_number>
+ *
+ * name: name of the channel
+ * frequency: frequency in Hz
+ * inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO.
+ * bandwidth: one of BANDWIDTH_6_MHZ, BANDWIDTH_7_MHZ, or BANDWIDTH_8_MHZ.
+ * fec_hp: FEC of the high priority stream, one of: FEC_1_2, FEC_2_3,
+ * FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, FEC_8_9, or FEC_AUTO.
+ * fec_lp: FEC of the low priority stream, one of: FEC_1_2, FEC_2_3,
+ * FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7, FEC_7_8, FEC_8_9, FEC_AUTO, or FEC_NONE.
+ * constellation: one of QPSK, QAM_128, QAM_16, QAM_256, QAM_32, or QAM_64.
+ * transmission: one of TRANSMISSION_MODE_2K, or TRANSMISSION_MODE_8K.
+ * guard_interval: one of GUARD_INTERVAL_1_32, GUARD_INTERVAL_1_16, GUARD_INTERVAL_1_8, or GUARD_INTERVAL_1_4.
+ * hierarchy: one of HIERARCHY_NONE, HIERARCHY_1, HIERARCHY_2, or HIERARCHY_4.
+ * video_pid: PID of the video stream.
+ * audio_pid: PID of the audio stream.
+ * channel_number: Transport stream channel number of the program.
+ *
+ * DVBC:
+ *
+ * <name>:<frequency>:<inversion>:<symbol_rate>:<fec>:
+ * <modulation>:<video_pid>:<audio_pid>:<channel_number>
+ *
+ * name: name of the channel
+ * frequency: frequency in Hz
+ * inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO.
+ * symbol_rate: Symbol rate of the channel in ksyms.
+ * fec: One of: FEC_1_2, FEC_2_3, FEC_3_4, FEC_4_5, FEC_5_6, FEC_6_7,
+ * FEC_7_8, FEC_8_9, or FEC_AUTO.
+ * modulation: one of QAM_16, QAM_32, QAM_64, QAM_128, QAM_256, QAM_AUTO.
+ * video_pid: PID of the video stream.
+ * audio_pid: PID of the audio stream.
+ * channel_number: Transport stream channel number of the program.
+ *
+ * DVBS:
+ *
+ * <name>:<frequency>:<polarization>:<satellite_switches>:<symbol_rate>:<video_pid>:<audio_pid>:<channel_number>
+ *
+ * name: name of the channel
+ * frequency: frequency in kHz
+ * polarization: one of H,V,L, or R.
+ * satellite_switches: Treated as a 2 bit value controlling switches in SEC equipment:
+ * bit 0: controls "satellite switch", 0: A, 1: B
+ * bit 1: controls "switch option", 0: A, 1: B
+ * symbol_rate: Symbol rate of the channel in ksyms.
+ * video_pid: PID of the video stream.
+ * audio_pid: PID of the audio stream.
+ * channel_number: Transport stream channel number of the program.
+ *
+ * ATSC:
+ *
+ * <name>:<frequency>:<inversion>:<modulation>:<video_pid>:<audio_pid>:<channel_number>
+ *
+ * name: name of the channel
+ * frequency: frequency in GHz
+ * inversion: one of INVERSION_OFF, INVERSION_ON, or INVERSION_AUTO.
+ * modulation: one of 8VSB, 16VSB, QAM_64, or QAM_256.
+ * video_pid: PID of the video stream.
+ * audio_pid: PID of the audio stream.
+ * channel_number: Transport stream channel number of the program.
+ */
diff --git a/lib/libdvben50221/Makefile b/lib/libdvben50221/Makefile
new file mode 100644
index 0000000..797ea2a
--- /dev/null
+++ b/lib/libdvben50221/Makefile
@@ -0,0 +1,49 @@
+# Makefile for linuxtv.org dvb-apps/lib/libdvben50221
+
+includes = asn_1.h \
+ en50221_app_ai.h \
+ en50221_app_auth.h \
+ en50221_app_ca.h \
+ en50221_app_datetime.h \
+ en50221_app_dvb.h \
+ en50221_app_epg.h \
+ en50221_app_lowspeed.h \
+ en50221_app_mmi.h \
+ en50221_app_rm.h \
+ en50221_app_smartcard.h \
+ en50221_app_tags.h \
+ en50221_app_teletext.h \
+ en50221_app_utils.h \
+ en50221_errno.h \
+ en50221_session.h \
+ en50221_stdcam.h \
+ en50221_transport.h
+
+objects = asn_1.o \
+ en50221_app_ai.o \
+ en50221_app_auth.o \
+ en50221_app_ca.o \
+ en50221_app_datetime.o \
+ en50221_app_dvb.o \
+ en50221_app_epg.o \
+ en50221_app_lowspeed.o \
+ en50221_app_mmi.o \
+ en50221_app_rm.o \
+ en50221_app_smartcard.o \
+ en50221_app_teletext.o \
+ en50221_app_utils.o \
+ en50221_session.o \
+ en50221_stdcam.o \
+ en50221_stdcam_hlci.o \
+ en50221_stdcam_llci.o \
+ en50221_transport.o
+
+lib_name = libdvben50221
+
+CPPFLAGS += -I../../lib -DLOG_LEVEL=1 # FIXME
+
+.PHONY: all
+
+all: library
+
+include ../../Make.rules
diff --git a/lib/libdvben50221/asn_1.c b/lib/libdvben50221/asn_1.c
new file mode 100644
index 0000000..803eb60
--- /dev/null
+++ b/lib/libdvben50221/asn_1.c
@@ -0,0 +1,83 @@
+/*
+ ASN.1 routines, implementation for libdvben50221
+ an implementation for the High Level Common Interface
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include "asn_1.h"
+
+int asn_1_decode(uint16_t * length, uint8_t * asn_1_array,
+ uint32_t asn_1_array_len)
+{
+ uint8_t length_field;
+
+ if (asn_1_array_len < 1)
+ return -1;
+ length_field = asn_1_array[0];
+
+ if (length_field < 0x80) {
+ // there is only one word
+ *length = length_field & 0x7f;
+ return 1;
+ } else if (length_field == 0x81) {
+ if (asn_1_array_len < 2)
+ return -1;
+
+ *length = asn_1_array[1];
+ return 2;
+ } else if (length_field == 0x82) {
+ if (asn_1_array_len < 3)
+ return -1;
+
+ *length = (asn_1_array[1] << 8) | asn_1_array[2];
+ return 3;
+ }
+
+ return -1;
+}
+
+int asn_1_encode(uint16_t length, uint8_t * asn_1_array,
+ uint32_t asn_1_array_len)
+{
+ if (length < 0x80) {
+ if (asn_1_array_len < 1)
+ return -1;
+
+ asn_1_array[0] = length & 0x7f;
+ return 1;
+ } else if (length < 0x100) {
+ if (asn_1_array_len < 2)
+ return -1;
+
+ asn_1_array[0] = 0x81;
+ asn_1_array[1] = length;
+ return 2;
+ } else {
+ if (asn_1_array_len < 3)
+ return -1;
+
+ asn_1_array[0] = 0x82;
+ asn_1_array[1] = length >> 8;
+ asn_1_array[2] = length;
+ return 3;
+ }
+
+ // never reached
+}
diff --git a/lib/libdvben50221/asn_1.h b/lib/libdvben50221/asn_1.h
new file mode 100644
index 0000000..c8774db
--- /dev/null
+++ b/lib/libdvben50221/asn_1.h
@@ -0,0 +1,41 @@
+/*
+ ASN.1 routines, implementation for libdvben50221
+ an implementation for the High Level Common Interface
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __ASN_1_H__
+#define __ASN_1_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+
+int asn_1_decode(uint16_t * length, uint8_t * asn_1_array,
+ uint32_t asn_1_array_len);
+int asn_1_encode(uint16_t length, uint8_t * asn_1_array,
+ uint32_t asn_1_array_len);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_ai.c b/lib/libdvben50221/en50221_app_ai.c
new file mode 100644
index 0000000..b7ded66
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_ai.c
@@ -0,0 +1,191 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_ai.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_ai {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_ai_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_ai_parse_app_info(struct en50221_app_ai *ai,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+struct en50221_app_ai *en50221_app_ai_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_ai *ai = NULL;
+
+ // create structure and set it up
+ ai = malloc(sizeof(struct en50221_app_ai));
+ if (ai == NULL) {
+ return NULL;
+ }
+ ai->funcs = funcs;
+ ai->callback = NULL;
+
+ pthread_mutex_init(&ai->lock, NULL);
+
+ // done
+ return ai;
+}
+
+void en50221_app_ai_destroy(struct en50221_app_ai *ai)
+{
+ pthread_mutex_destroy(&ai->lock);
+ free(ai);
+}
+
+void en50221_app_ai_register_callback(struct en50221_app_ai *ai,
+ en50221_app_ai_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&ai->lock);
+ ai->callback = callback;
+ ai->callback_arg = arg;
+ pthread_mutex_unlock(&ai->lock);
+}
+
+int en50221_app_ai_enquiry(struct en50221_app_ai *ai,
+ uint16_t session_number)
+{
+ uint8_t data[4];
+
+ data[0] = (TAG_APP_INFO_ENQUIRY >> 16) & 0xFF;
+ data[1] = (TAG_APP_INFO_ENQUIRY >> 8) & 0xFF;
+ data[2] = TAG_APP_INFO_ENQUIRY & 0xFF;
+ data[3] = 0;
+
+ return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4);
+}
+
+int en50221_app_ai_entermenu(struct en50221_app_ai *ai,
+ uint16_t session_number)
+{
+ uint8_t data[4];
+
+ data[0] = (TAG_ENTER_MENU >> 16) & 0xFF;
+ data[1] = (TAG_ENTER_MENU >> 8) & 0xFF;
+ data[2] = TAG_ENTER_MENU & 0xFF;
+ data[3] = 0;
+
+ return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4);
+}
+
+int en50221_app_ai_message(struct en50221_app_ai *ai,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_APP_INFO:
+ return en50221_app_ai_parse_app_info(ai, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+
+
+
+
+static int en50221_app_ai_parse_app_info(struct en50221_app_ai *ai,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // parse the length field
+ int length_field_len;
+ uint16_t asn_data_length;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return -1;
+ }
+ // check it
+ if (asn_data_length < 6) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *app_info = data + length_field_len;
+
+ // parse the fields
+ uint8_t application_type = app_info[0];
+ uint16_t application_manufacturer = (app_info[1] << 8) | app_info[2];
+ uint16_t manufacturer_code = (app_info[3] << 8) | app_info[4];
+ uint8_t menu_string_length = app_info[5];
+ uint8_t *menu_string = app_info + 6;
+
+ // check the menu_string_length
+ if (menu_string_length > (asn_data_length - 6)) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received bad menu string length - adjusting\n");
+ menu_string_length = asn_data_length - 6;
+ }
+ // tell the app
+ pthread_mutex_lock(&ai->lock);
+ en50221_app_ai_callback cb = ai->callback;
+ void *cb_arg = ai->callback_arg;
+ pthread_mutex_unlock(&ai->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ application_type, application_manufacturer,
+ manufacturer_code, menu_string_length,
+ menu_string);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_ai.h b/lib/libdvben50221/en50221_app_ai.h
new file mode 100644
index 0000000..18b5cd2
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_ai.h
@@ -0,0 +1,136 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_AI_H__
+#define __EN50221_APPLICATION_AI_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_AI_RESOURCEID MKRID(2,1,1)
+
+#define APPLICATION_TYPE_CA 0x01
+#define APPLICATION_TYPE_EPG 0x02
+
+/**
+ * Type definition for application callback function - called when we receive
+ * an application info object.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Resource id concerned.
+ * @param application_type Type of application.
+ * @param application_manufacturer Manufacturer of application.
+ * @param manufacturer_code Manufacturer specific code.
+ * @param menu_string_length Length of menu string.
+ * @param menu_string The menu string itself.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_ai_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t application_type,
+ uint16_t application_manufacturer,
+ uint16_t manufacturer_code,
+ uint8_t menu_string_length,
+ uint8_t * menu_string);
+
+/**
+ * Opaque type representing an application information resource.
+ */
+struct en50221_app_ai;
+
+/**
+ * Create an instance of an application information resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_ai *en50221_app_ai_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of an application information resource.
+ *
+ * @param ai Instance to destroy.
+ */
+extern void en50221_app_ai_destroy(struct en50221_app_ai *ai);
+
+/**
+ * Register a callback for reception of application_info objects.
+ *
+ * @param ai Application information instance.
+ * @param callback Callback function.
+ * @param arg Private argument passed during calls to the callback.
+ */
+extern void en50221_app_ai_register_callback(struct en50221_app_ai *ai,
+ en50221_app_ai_callback,
+ void *arg);
+
+/**
+ * send a enquiry for the app_info provided by a module
+ *
+ * @param ai Application information instance.
+ * @param session_number Session to send on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ai_enquiry(struct en50221_app_ai *ai,
+ uint16_t session_number);
+
+/**
+ * send a enter_menu tag, this will make the application
+ * open a new MMI session to provide a Menu, or so.
+ *
+ * @param ai Application information instance.
+ * @param session_number Session to send on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ai_entermenu(struct en50221_app_ai *ai,
+ uint16_t session_number);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param ai Application information instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ai_message(struct en50221_app_ai *ai,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_auth.c b/lib/libdvben50221/en50221_app_auth.c
new file mode 100644
index 0000000..a8902c1
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_auth.c
@@ -0,0 +1,180 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_auth.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_auth {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_auth_request_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_auth_parse_request(struct en50221_app_auth *private,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+struct en50221_app_auth *en50221_app_auth_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_auth *auth = NULL;
+
+ // create structure and set it up
+ auth = malloc(sizeof(struct en50221_app_auth));
+ if (auth == NULL) {
+ return NULL;
+ }
+ auth->funcs = funcs;
+ auth->callback = NULL;
+
+ pthread_mutex_init(&auth->lock, NULL);
+
+ // done
+ return auth;
+}
+
+void en50221_app_auth_destroy(struct en50221_app_auth *auth)
+{
+ pthread_mutex_destroy(&auth->lock);
+ free(auth);
+}
+
+void en50221_app_auth_register_request_callback(struct en50221_app_auth *auth,
+ en50221_app_auth_request_callback callback, void *arg)
+{
+ pthread_mutex_lock(&auth->lock);
+ auth->callback = callback;
+ auth->callback_arg = arg;
+ pthread_mutex_unlock(&auth->lock);
+}
+
+int en50221_app_auth_send(struct en50221_app_auth *auth,
+ uint16_t session_number,
+ uint16_t auth_protocol_id, uint8_t * auth_data,
+ uint32_t auth_data_length)
+{
+ uint8_t buf[10];
+
+ // the header
+ buf[0] = (TAG_AUTH_RESP >> 16) & 0xFF;
+ buf[1] = (TAG_AUTH_RESP >> 8) & 0xFF;
+ buf[2] = TAG_AUTH_RESP & 0xFF;
+
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(auth_data_length + 2, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ // the phase_id
+ buf[3 + length_field_len] = auth_protocol_id >> 8;
+ buf[3 + length_field_len + 1] = auth_protocol_id;
+
+ // build the iovecs
+ struct iovec iov[2];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len + 2;
+ iov[1].iov_base = auth_data;
+ iov[1].iov_len = auth_data_length;
+
+ // sendit
+ return auth->funcs->send_datav(auth->funcs->arg, session_number,
+ iov, 2);
+}
+
+int en50221_app_auth_message(struct en50221_app_auth *auth,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_AUTH_REQ:
+ return en50221_app_auth_parse_request(auth, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+static int en50221_app_auth_parse_request(struct en50221_app_auth *auth,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *auth_data = data + length_field_len;
+
+ // process it
+ uint16_t auth_protocol_id = (auth_data[0] << 8) | auth_data[1];
+
+ // tell the app
+ pthread_mutex_lock(&auth->lock);
+ en50221_app_auth_request_callback cb = auth->callback;
+ void *cb_arg = auth->callback_arg;
+ pthread_mutex_unlock(&auth->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ auth_protocol_id, auth_data + 2,
+ asn_data_length - 2);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_auth.h b/lib/libdvben50221/en50221_app_auth.h
new file mode 100644
index 0000000..2b1d2e7
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_auth.h
@@ -0,0 +1,123 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_auth_H__
+#define __EN50221_APPLICATION_auth_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_AUTH_RESOURCEID MKRID(16,1,1)
+
+/**
+ * Type definition for request - called when we receive a auth request from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param auth_protocol_id Auth protocol id.
+ * @param auth_data Data for the request.
+ * @param auth_data_lenghth Number of bytes.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_auth_request_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint16_t auth_protcol_id,
+ uint8_t *auth_data,
+ uint32_t auth_data_length);
+
+/**
+ * Opaque type representing a auth resource.
+ */
+struct en50221_app_auth;
+
+/**
+ * Create an instance of the auth resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_auth *en50221_app_auth_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the auth resource.
+ *
+ * @param auth Instance to destroy.
+ */
+extern void en50221_app_auth_destroy(struct en50221_app_auth *auth);
+
+/**
+ * Register the callback for when we receive a request.
+ *
+ * @param auth auth resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_auth_register_request_callback(struct en50221_app_auth *auth,
+ en50221_app_auth_request_callback callback,
+ void *arg);
+
+/**
+ * Send an auth response to the CAM.
+ *
+ * @param auth auth resource instance.
+ * @param session_number Session number to send it on.
+ * @param auth_protocol_id Auth protocol id.
+ * @param auth_data Auth data.
+ * @param auth_data_length Number of bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_auth_send(struct en50221_app_auth *auth,
+ uint16_t session_number,
+ uint16_t auth_protocol_id,
+ uint8_t *auth_data,
+ uint32_t auth_data_length);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param auth Authentication instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_auth_message(struct en50221_app_auth *auth,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_ca.c b/lib/libdvben50221/en50221_app_ca.c
new file mode 100644
index 0000000..22d4499
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_ca.c
@@ -0,0 +1,631 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include <libucsi/mpeg/descriptor.h>
+#include "en50221_app_ca.h"
+#include "asn_1.h"
+
+// tags supported by this resource
+#define TAG_CA_INFO_ENQUIRY 0x9f8030
+#define TAG_CA_INFO 0x9f8031
+#define TAG_CA_PMT 0x9f8032
+#define TAG_CA_PMT_REPLY 0x9f8033
+
+struct en50221_app_ca {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_ca_info_callback ca_info_callback;
+ void *ca_info_callback_arg;
+
+ en50221_app_ca_pmt_reply_callback ca_pmt_reply_callback;
+ void *ca_pmt_reply_callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+struct ca_pmt_descriptor {
+ uint8_t *descriptor;
+ uint16_t length;
+
+ struct ca_pmt_descriptor *next;
+};
+
+struct ca_pmt_stream {
+ uint8_t stream_type;
+ uint16_t pid;
+ struct ca_pmt_descriptor *descriptors;
+ uint32_t descriptors_length;
+ uint32_t descriptors_count;
+
+ struct ca_pmt_stream *next;
+};
+
+static int en50221_ca_extract_pmt_descriptors(struct mpeg_pmt_section *pmt,
+ struct ca_pmt_descriptor **outdescriptors);
+static int en50221_ca_extract_streams(struct mpeg_pmt_section *pmt,
+ struct ca_pmt_stream **outstreams);
+static void en50221_ca_try_move_pmt_descriptors(struct ca_pmt_descriptor **pmt_descriptors,
+ struct ca_pmt_stream **pmt_streams);
+static uint32_t en50221_ca_calculate_length(struct ca_pmt_descriptor *pmt_descriptors,
+ uint32_t *pmt_descriptors_length,
+ struct ca_pmt_stream *pmt_streams);
+static int en50221_app_ca_parse_info(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length);
+static int en50221_app_ca_parse_reply(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_ca *en50221_app_ca_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_ca *ca = NULL;
+
+ // create structure and set it up
+ ca = malloc(sizeof(struct en50221_app_ca));
+ if (ca == NULL) {
+ return NULL;
+ }
+ ca->funcs = funcs;
+ ca->ca_info_callback = NULL;
+ ca->ca_pmt_reply_callback = NULL;
+
+ pthread_mutex_init(&ca->lock, NULL);
+
+ // done
+ return ca;
+}
+
+void en50221_app_ca_destroy(struct en50221_app_ca *ca)
+{
+ pthread_mutex_destroy(&ca->lock);
+ free(ca);
+}
+
+void en50221_app_ca_register_info_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_info_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&ca->lock);
+ ca->ca_info_callback = callback;
+ ca->ca_info_callback_arg = arg;
+ pthread_mutex_unlock(&ca->lock);
+}
+
+void en50221_app_ca_register_pmt_reply_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_pmt_reply_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&ca->lock);
+ ca->ca_pmt_reply_callback = callback;
+ ca->ca_pmt_reply_callback_arg = arg;
+ pthread_mutex_unlock(&ca->lock);
+}
+
+int en50221_app_ca_info_enq(struct en50221_app_ca *ca,
+ uint16_t session_number)
+{
+ uint8_t data[4];
+
+ data[0] = (TAG_CA_INFO_ENQUIRY >> 16) & 0xFF;
+ data[1] = (TAG_CA_INFO_ENQUIRY >> 8) & 0xFF;
+ data[2] = TAG_CA_INFO_ENQUIRY & 0xFF;
+ data[3] = 0;
+ return ca->funcs->send_data(ca->funcs->arg, session_number, data, 4);
+}
+
+int en50221_app_ca_pmt(struct en50221_app_ca *ca,
+ uint16_t session_number,
+ uint8_t * ca_pmt, uint32_t ca_pmt_length)
+{
+ uint8_t buf[10];
+
+ // set up the tag
+ buf[0] = (TAG_CA_PMT >> 16) & 0xFF;
+ buf[1] = (TAG_CA_PMT >> 8) & 0xFF;
+ buf[2] = TAG_CA_PMT & 0xFF;
+
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(ca_pmt_length, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ // build the iovecs
+ struct iovec iov[2];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len;
+ iov[1].iov_base = ca_pmt;
+ iov[1].iov_len = ca_pmt_length;
+
+ // create the data and send it
+ return ca->funcs->send_datav(ca->funcs->arg, session_number, iov, 2);
+}
+
+int en50221_app_ca_message(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_CA_INFO:
+ return en50221_app_ca_parse_info(ca, slot_id,
+ session_number, data + 3,
+ data_length - 3);
+ case TAG_CA_PMT_REPLY:
+ return en50221_app_ca_parse_reply(ca, slot_id,
+ session_number, data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+int en50221_ca_format_pmt(struct mpeg_pmt_section *pmt, uint8_t * data,
+ uint32_t data_length, int move_ca_descriptors,
+ uint8_t ca_pmt_list_management,
+ uint8_t ca_pmt_cmd_id)
+{
+ struct ca_pmt_descriptor *pmt_descriptors = NULL;
+ uint32_t pmt_descriptors_length = 0;
+ struct ca_pmt_stream *pmt_streams = NULL;
+ uint32_t total_required_length = 0;
+ struct ca_pmt_descriptor *cur_d;
+ struct ca_pmt_stream *cur_s;
+ int result = -1;
+
+ // extract the descriptors and streams
+ if (en50221_ca_extract_pmt_descriptors(pmt, &pmt_descriptors))
+ goto cleanup;
+ if (en50221_ca_extract_streams(pmt, &pmt_streams))
+ goto cleanup;
+
+ // try and merge them if we have no PMT descriptors
+ if ((pmt_descriptors == NULL) && move_ca_descriptors) {
+ en50221_ca_try_move_pmt_descriptors(&pmt_descriptors,
+ &pmt_streams);
+ }
+ // calculate the length of all descriptors/streams and the total length required
+ total_required_length =
+ en50221_ca_calculate_length(pmt_descriptors,
+ &pmt_descriptors_length,
+ pmt_streams);
+
+ // ensure we were supplied with enough data
+ if (total_required_length > data_length) {
+ goto cleanup;
+ }
+ // format the start of the PMT
+ uint32_t data_pos = 0;
+ data[data_pos++] = ca_pmt_list_management;
+ data[data_pos++] = mpeg_pmt_section_program_number(pmt) >> 8;
+ data[data_pos++] = mpeg_pmt_section_program_number(pmt);
+ data[data_pos++] =
+ (pmt->head.version_number << 1) | pmt->head.
+ current_next_indicator;
+ data[data_pos++] = (pmt_descriptors_length >> 8) & 0x0f;
+ data[data_pos++] = pmt_descriptors_length;
+
+ // append the PMT descriptors
+ if (pmt_descriptors_length) {
+ data[data_pos++] = ca_pmt_cmd_id;
+ cur_d = pmt_descriptors;
+ while (cur_d) {
+ memcpy(data + data_pos, cur_d->descriptor,
+ cur_d->length);
+ data_pos += cur_d->length;
+ cur_d = cur_d->next;
+ }
+ }
+ // now, append the streams
+ cur_s = pmt_streams;
+ while (cur_s) {
+ data[data_pos++] = cur_s->stream_type;
+ data[data_pos++] = (cur_s->pid >> 8) & 0x1f;
+ data[data_pos++] = cur_s->pid;
+ data[data_pos++] = (cur_s->descriptors_length >> 8) & 0x0f;
+ data[data_pos++] = cur_s->descriptors_length;
+
+ // append the stream descriptors
+ if (cur_s->descriptors_length) {
+ data[data_pos++] = ca_pmt_cmd_id;
+ cur_d = cur_s->descriptors;
+ while (cur_d) {
+ memcpy(data + data_pos, cur_d->descriptor,
+ cur_d->length);
+ data_pos += cur_d->length;
+ cur_d = cur_d->next;
+ }
+ }
+ cur_s = cur_s->next;
+ }
+ result = data_pos;
+
+
+ cleanup:
+ // free the PMT descriptors
+ cur_d = pmt_descriptors;
+ while (cur_d) {
+ struct ca_pmt_descriptor *next = cur_d->next;
+ free(cur_d);
+ cur_d = next;
+ }
+
+ // free the streams
+ cur_s = pmt_streams;
+ while (cur_s) {
+ struct ca_pmt_stream *next_s = cur_s->next;
+
+ // free the stream descriptors
+ cur_d = cur_s->descriptors;
+ while (cur_d) {
+ struct ca_pmt_descriptor *next_d = cur_d->next;
+ free(cur_d);
+ cur_d = next_d;
+ }
+
+ free(cur_s);
+ cur_s = next_s;
+ }
+ return result;
+}
+
+
+
+
+
+
+
+static int en50221_ca_extract_pmt_descriptors(struct mpeg_pmt_section *pmt,
+ struct ca_pmt_descriptor **outdescriptors)
+{
+ struct ca_pmt_descriptor *descriptors = NULL;
+ struct ca_pmt_descriptor *descriptors_tail = NULL;
+ struct ca_pmt_descriptor *cur_d;
+
+ struct descriptor *cur_descriptor;
+ mpeg_pmt_section_descriptors_for_each(pmt, cur_descriptor) {
+ if (cur_descriptor->tag == dtag_mpeg_ca) {
+ // create a new structure for this one
+ struct ca_pmt_descriptor *new_d =
+ malloc(sizeof(struct ca_pmt_descriptor));
+ if (new_d == NULL) {
+ goto error_exit;
+ }
+ new_d->descriptor = (uint8_t *) cur_descriptor;
+ new_d->length = cur_descriptor->len + 2;
+ new_d->next = NULL;
+
+ // append it to the list
+ if (descriptors == NULL) {
+ descriptors = new_d;
+ } else {
+ descriptors_tail->next = new_d;
+ }
+ descriptors_tail = new_d;
+ }
+ }
+ *outdescriptors = descriptors;
+ return 0;
+
+error_exit:
+ cur_d = descriptors;
+ while (cur_d) {
+ struct ca_pmt_descriptor *next = cur_d->next;
+ free(cur_d);
+ cur_d = next;
+ }
+ return -1;
+}
+
+static int en50221_ca_extract_streams(struct mpeg_pmt_section *pmt,
+ struct ca_pmt_stream **outstreams)
+{
+ struct ca_pmt_stream *streams = NULL;
+ struct ca_pmt_stream *streams_tail = NULL;
+ struct mpeg_pmt_stream *cur_stream;
+ struct descriptor *cur_descriptor;
+ struct ca_pmt_stream *cur_s;
+
+ mpeg_pmt_section_streams_for_each(pmt, cur_stream) {
+ struct ca_pmt_descriptor *descriptors_tail = NULL;
+
+ // create a new structure
+ struct ca_pmt_stream *new_s =
+ malloc(sizeof(struct ca_pmt_stream));
+ if (new_s == NULL) {
+ goto exit_cleanup;
+ }
+ new_s->stream_type = cur_stream->stream_type;
+ new_s->pid = cur_stream->pid;
+ new_s->descriptors = NULL;
+ new_s->next = NULL;
+ new_s->descriptors_count = 0;
+
+ // append it to the list
+ if (streams == NULL) {
+ streams = new_s;
+ } else {
+ streams_tail->next = new_s;
+ }
+ streams_tail = new_s;
+
+ // now process the descriptors
+ mpeg_pmt_stream_descriptors_for_each(cur_stream,
+ cur_descriptor) {
+ if (cur_descriptor->tag == dtag_mpeg_ca) {
+ // create a new structure
+ struct ca_pmt_descriptor *new_d =
+ malloc(sizeof(struct ca_pmt_descriptor));
+ if (new_d == NULL) {
+ goto exit_cleanup;
+ }
+ new_d->descriptor =
+ (uint8_t *) cur_descriptor;
+ new_d->length = cur_descriptor->len + 2;
+ new_d->next = NULL;
+
+ // append it to the list
+ if (new_s->descriptors == NULL) {
+ new_s->descriptors = new_d;
+ } else {
+ descriptors_tail->next = new_d;
+ }
+ descriptors_tail = new_d;
+ new_s->descriptors_count++;
+ }
+ }
+ }
+ *outstreams = streams;
+ return 0;
+
+exit_cleanup:
+ // free the streams
+ cur_s = streams;
+ while (cur_s) {
+ struct ca_pmt_stream *next_s = cur_s->next;
+
+ // free the stream descriptors
+ struct ca_pmt_descriptor *cur_d = cur_s->descriptors;
+ while (cur_d) {
+ struct ca_pmt_descriptor *next_d = cur_d->next;
+ free(cur_d);
+ cur_d = next_d;
+ }
+
+ free(cur_s);
+ cur_s = next_s;
+ }
+ return -1;
+}
+
+static void en50221_ca_try_move_pmt_descriptors(struct ca_pmt_descriptor **pmt_descriptors,
+ struct ca_pmt_stream **pmt_streams)
+{
+ // get the first stream
+ struct ca_pmt_stream *first_stream = *pmt_streams;
+ if (first_stream == NULL)
+ return;
+
+ // Check that all the other streams with CA descriptors have exactly the same CA descriptors
+ struct ca_pmt_stream *cur_stream = first_stream->next;
+ while (cur_stream) {
+ // if there are differing numbers of descriptors, exit right now
+ if (cur_stream->descriptors_count != first_stream->descriptors_count)
+ return;
+
+ // now verify the descriptors match
+ struct ca_pmt_descriptor *cur_descriptor = cur_stream->descriptors;
+ struct ca_pmt_descriptor *first_cur_descriptor = first_stream->descriptors;
+ while (cur_descriptor) {
+ // check the descriptors are the same length
+ if (cur_descriptor->length != first_cur_descriptor->length)
+ return;
+
+ // check their contents match
+ if (memcmp(cur_descriptor->descriptor,
+ first_cur_descriptor->descriptor,
+ cur_descriptor->length)) {
+ return;
+ }
+ // move to next
+ cur_descriptor = cur_descriptor->next;
+ first_cur_descriptor = first_cur_descriptor->next;
+ }
+
+ // move to next
+ cur_stream = cur_stream->next;
+ }
+
+ // if we end up here, all descriptors in all streams matched
+
+ // hook the first stream's descriptors into the PMT's
+ *pmt_descriptors = first_stream->descriptors;
+ first_stream->descriptors = NULL;
+ first_stream->descriptors_count = 0;
+
+ // now free up all the descriptors in the other streams
+ cur_stream = first_stream->next;
+ while (cur_stream) {
+ struct ca_pmt_descriptor *cur_descriptor = cur_stream->descriptors;
+ while (cur_descriptor) {
+ struct ca_pmt_descriptor *next = cur_descriptor->next;
+ free(cur_descriptor);
+ cur_descriptor = next;
+ }
+ cur_stream->descriptors = NULL;
+ cur_stream->descriptors_count = 0;
+ cur_stream = cur_stream->next;
+ }
+}
+
+static uint32_t en50221_ca_calculate_length(struct ca_pmt_descriptor *pmt_descriptors,
+ uint32_t *pmt_descriptors_length,
+ struct ca_pmt_stream *pmt_streams)
+{
+ uint32_t total_required_length = 6; // header
+ struct ca_pmt_stream *cur_s;
+
+ // calcuate the PMT descriptors length
+ (*pmt_descriptors_length) = 0;
+ struct ca_pmt_descriptor *cur_d = pmt_descriptors;
+ while (cur_d) {
+ (*pmt_descriptors_length) += cur_d->length;
+ cur_d = cur_d->next;
+ }
+
+ // add on 1 byte for the ca_pmt_cmd_id if we have some descriptors.
+ if (*pmt_descriptors_length)
+ (*pmt_descriptors_length)++;
+
+ // update the total required length
+ total_required_length += *pmt_descriptors_length;
+
+ // calculate the length of descriptors in the streams
+ cur_s = pmt_streams;
+ while (cur_s) {
+ // calculate the size of descriptors in this stream
+ cur_s->descriptors_length = 0;
+ cur_d = cur_s->descriptors;
+ while (cur_d) {
+ cur_s->descriptors_length += cur_d->length;
+ cur_d = cur_d->next;
+ }
+
+ // add on 1 byte for the ca_pmt_cmd_id if we have some descriptors.
+ if (cur_s->descriptors_length)
+ cur_s->descriptors_length++;
+
+ // update the total required length;
+ total_required_length += 5 + cur_s->descriptors_length;
+
+ cur_s = cur_s->next;
+ }
+
+ // done
+ return total_required_length;
+}
+
+static int en50221_app_ca_parse_info(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ data += length_field_len;
+
+ // parse
+ uint32_t ca_id_count = asn_data_length / 2;
+
+ // byteswap the IDs
+ uint16_t *ids = (uint16_t *) data;
+ uint32_t i;
+ for (i = 0; i < ca_id_count; i++) {
+ bswap16(data);
+ data += 2;
+ }
+
+ // tell the app
+ pthread_mutex_lock(&ca->lock);
+ en50221_app_ca_info_callback cb = ca->ca_info_callback;
+ void *cb_arg = ca->ca_info_callback_arg;
+ pthread_mutex_unlock(&ca->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, ca_id_count,
+ ids);
+ }
+ return 0;
+}
+
+static int en50221_app_ca_parse_reply(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length < 4) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ data += length_field_len;
+ data_length -= length_field_len;
+
+ // process the reply table to fix endian issues
+ uint32_t pos = 4;
+ bswap16(data);
+ while (pos < asn_data_length) {
+ bswap16(data + pos);
+ pos += 3;
+ }
+
+ // tell the app
+ pthread_mutex_lock(&ca->lock);
+ en50221_app_ca_pmt_reply_callback cb = ca->ca_pmt_reply_callback;
+ void *cb_arg = ca->ca_pmt_reply_callback_arg;
+ pthread_mutex_unlock(&ca->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ (struct en50221_app_pmt_reply *) data,
+ asn_data_length);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_ca.h b/lib/libdvben50221/en50221_app_ca.h
new file mode 100644
index 0000000..7405b06
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_ca.h
@@ -0,0 +1,264 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_ca_H__
+#define __EN50221_APPLICATION_ca_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+#include <libucsi/mpeg/pmt_section.h>
+#include <libucsi/dvb/descriptor.h>
+
+#define CA_LIST_MANAGEMENT_MORE 0x00
+#define CA_LIST_MANAGEMENT_FIRST 0x01
+#define CA_LIST_MANAGEMENT_LAST 0x02
+#define CA_LIST_MANAGEMENT_ONLY 0x03
+#define CA_LIST_MANAGEMENT_ADD 0x04
+#define CA_LIST_MANAGEMENT_UPDATE 0x05
+
+#define CA_PMT_CMD_ID_OK_DESCRAMBLING 0x01
+#define CA_PMT_CMD_ID_OK_MMI 0x02
+#define CA_PMT_CMD_ID_QUERY 0x03
+#define CA_PMT_CMD_ID_NOT_SELECTED 0x04
+
+#define CA_ENABLE_DESCRAMBLING_POSSIBLE 0x01
+#define CA_ENABLE_DESCRAMBLING_POSSIBLE_PURCHASE 0x02
+#define CA_ENABLE_DESCRAMBLING_POSSIBLE_TECHNICAL 0x03
+#define CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_NO_ENTITLEMENT 0x71
+#define CA_ENABLE_DESCRAMBLING_NOT_POSSIBLE_TECHNICAL 0x73
+
+
+#define EN50221_APP_CA_RESOURCEID MKRID(3,1,1)
+
+/**
+ * PMT reply structure.
+ */
+struct en50221_app_pmt_reply {
+ uint16_t program_number;
+ EBIT3(uint8_t reserved_1 : 2;,
+ uint8_t version_number : 5;,
+ uint8_t current_next_indicator : 1;);
+ EBIT2(uint8_t CA_enable_flag : 1;,
+ uint8_t CA_enable : 7;);
+ /* struct en50221_app_pmt_stream streams[] */
+} __attribute__ ((packed));
+
+/**
+ * A stream within a pmt reply structure.
+ */
+struct en50221_app_pmt_stream {
+ EBIT2(uint16_t reserved_1 : 3;,
+ uint16_t es_pid :13;);
+ EBIT2(uint8_t CA_enable_flag : 1;,
+ uint8_t CA_enable : 7;);
+} __attribute__ ((packed));
+
+/**
+ * Convenience iterator for the streams field of the en50221_app_pmt_reply structure.
+ *
+ * @param pmt Pointer to the en50221_app_pmt_reply structure.
+ * @param pos Variable holding a pointer to the current en50221_app_pmt_stream.
+ * @param size Total size of the PMT reply.
+ */
+#define en50221_app_pmt_reply_streams_for_each(pmt, pos, size) \
+ for ((pos) = en50221_app_pmt_reply_streams_first(pmt, size); \
+ (pos); \
+ (pos) = en50221_app_pmt_reply_streams_next(pmt, pos, size))
+
+
+/**
+ * Type definition for command - called when we receive a ca info response.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param ca_id_count Number of ca_system_ids.
+ * @param ca_ids Pointer to list of ca_system_ids.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_ca_info_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t ca_id_count,
+ uint16_t * ca_ids);
+
+/**
+ * Type definition for pmt_reply - called when we receive a pmt_reply.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param reply Pointer to a struct en50221_app_pmt_reply.
+ * @param reply_size Total size of the struct en50221_app_pmt_reply in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_ca_pmt_reply_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ struct en50221_app_pmt_reply *reply,
+ uint32_t reply_size);
+
+/**
+ * Opaque type representing a ca resource.
+ */
+struct en50221_app_ca;
+
+/**
+ * Create an instance of the ca resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_ca *en50221_app_ca_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the ca resource.
+ *
+ * @param ca Instance to destroy.
+ */
+extern void en50221_app_ca_destroy(struct en50221_app_ca *ca);
+
+/**
+ * Register the callback for when we receive a ca info.
+ *
+ * @param ca ca resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_ca_register_info_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_info_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a pmt_reply.
+ *
+ * @param ca ca resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_ca_register_pmt_reply_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_pmt_reply_callback callback,
+ void *arg);
+
+/**
+ * Send a ca_info_req to the CAM.
+ *
+ * @param ca ca resource instance.
+ * @param session_number Session number to send it on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ca_info_enq(struct en50221_app_ca *ca,
+ uint16_t session_number);
+
+/**
+ * Send a ca_pmt structure to the CAM.
+ *
+ * @param ca ca resource instance.
+ * @param session_number Session number to send it on.
+ * @param ca_pmt A ca_pmt structure formatted with the en50221_ca_format_pmt() function.
+ * @param ca_pmt_length Length of ca_pmt structure in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ca_pmt(struct en50221_app_ca *ca,
+ uint16_t session_number,
+ uint8_t * ca_pmt,
+ uint32_t ca_pmt_length);
+
+/**
+ * Transform a libucsi PMT into a binary structure for sending to a CAM.
+ *
+ * @param pmt The source PMT structure.
+ * @param data Pointer to data buffer to write it to.
+ * @param data_length Number of bytes available in data buffer.
+ * @param move_ca_descriptors If non-zero, will attempt to move CA descriptors
+ * in order to reduce the size of the formatted CAPMT.
+ * @param ca_pmt_list_management One of the CA_LIST_MANAGEMENT_*.
+ * @param ca_pmt_cmd_id One of the CA_PMT_CMD_ID_*.
+ * @return Number of bytes used, or -1 on error.
+ */
+extern int en50221_ca_format_pmt(struct mpeg_pmt_section *pmt,
+ uint8_t * data,
+ uint32_t data_length,
+ int move_ca_descriptors,
+ uint8_t ca_pmt_list_management,
+ uint8_t ca_pmt_cmd_id);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param ca CA instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_ca_message(struct en50221_app_ca *ca,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+
+
+
+static inline struct en50221_app_pmt_stream *
+ en50221_app_pmt_reply_streams_first(struct en50221_app_pmt_reply *reply,
+ uint32_t reply_size)
+{
+ uint32_t pos = sizeof(struct en50221_app_pmt_reply);
+
+ if (pos >= reply_size)
+ return NULL;
+
+ return (struct en50221_app_pmt_stream *) ((uint8_t *) reply + pos);
+}
+
+static inline struct en50221_app_pmt_stream *
+ en50221_app_pmt_reply_streams_next(struct en50221_app_pmt_reply *reply,
+ struct en50221_app_pmt_stream *pos,
+ uint32_t reply_size)
+{
+ uint8_t *end = (uint8_t *) reply + reply_size;
+ uint8_t *next =
+ (uint8_t *) pos +
+ sizeof(struct en50221_app_pmt_stream);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct en50221_app_pmt_stream *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libdvben50221/en50221_app_datetime.c b/lib/libdvben50221/en50221_app_datetime.c
new file mode 100644
index 0000000..6777003
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_datetime.c
@@ -0,0 +1,173 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include <libucsi/dvb/types.h>
+#include "en50221_app_datetime.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_datetime {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_datetime_enquiry_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime *datetime,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_datetime *en50221_app_datetime_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_datetime *datetime = NULL;
+
+ // create structure and set it up
+ datetime = malloc(sizeof(struct en50221_app_datetime));
+ if (datetime == NULL) {
+ return NULL;
+ }
+ datetime->funcs = funcs;
+ datetime->callback = NULL;
+
+ pthread_mutex_init(&datetime->lock, NULL);
+
+ // done
+ return datetime;
+}
+
+void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime)
+{
+ pthread_mutex_destroy(&datetime->lock);
+ free(datetime);
+}
+
+void en50221_app_datetime_register_enquiry_callback(struct en50221_app_datetime *datetime,
+ en50221_app_datetime_enquiry_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&datetime->lock);
+ datetime->callback = callback;
+ datetime->callback_arg = arg;
+ pthread_mutex_unlock(&datetime->lock);
+}
+
+int en50221_app_datetime_send(struct en50221_app_datetime *datetime,
+ uint16_t session_number,
+ time_t utc_time, int time_offset)
+{
+ uint8_t data[11];
+ int data_length;
+
+ data[0] = (TAG_DATE_TIME >> 16) & 0xFF;
+ data[1] = (TAG_DATE_TIME >> 8) & 0xFF;
+ data[2] = TAG_DATE_TIME & 0xFF;
+ if (time_offset != -1) {
+ data[3] = 7;
+ unixtime_to_dvbdate(utc_time, data + 4);
+ data[9] = time_offset >> 8;
+ data[10] = time_offset;
+ data_length = 11;
+ } else {
+ data[3] = 5;
+ unixtime_to_dvbdate(utc_time, data + 4);
+ data_length = 9;
+ }
+ return datetime->funcs->send_data(datetime->funcs->arg,
+ session_number, data,
+ data_length);
+}
+
+int en50221_app_datetime_message(struct en50221_app_datetime *datetime,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_DATE_TIME_ENQUIRY:
+ return en50221_app_datetime_parse_enquiry(datetime,
+ slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+
+
+
+
+
+
+
+static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime *datetime,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t response_interval = data[1];
+
+ // tell the app
+ pthread_mutex_lock(&datetime->lock);
+ en50221_app_datetime_enquiry_callback cb = datetime->callback;
+ void *cb_arg = datetime->callback_arg;
+ pthread_mutex_unlock(&datetime->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ response_interval);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_datetime.h b/lib/libdvben50221/en50221_app_datetime.h
new file mode 100644
index 0000000..4660630
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_datetime.h
@@ -0,0 +1,119 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_DATETIME_H__
+#define __EN50221_APPLICATION_DATETIME_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_DATETIME_RESOURCEID MKRID(36,1,1)
+
+/**
+ * Type definition for enquiry - called when we receive a date/time enquiry from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param response_interval Response interval requested by CAM.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_datetime_enquiry_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t response_interval);
+
+/**
+ * Opaque type representing a datetime resource.
+ */
+struct en50221_app_datetime;
+
+/**
+ * Create an instance of the datetime resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_datetime
+ *en50221_app_datetime_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the datetime resource.
+ *
+ * @param datetime Instance to destroy.
+ */
+extern void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime);
+
+/**
+ * Register the callback for when we receive a enquiry request.
+ *
+ * @param datetime datetime resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_datetime_register_enquiry_callback(struct en50221_app_datetime *datetime,
+ en50221_app_datetime_enquiry_callback callback,
+ void *arg);
+
+/**
+ * Send the time to the CAM.
+ *
+ * @param datetime datetime resource instance.
+ * @param session_number Session number to send it on.
+ * @param utc_time UTC time in unix time format.
+ * @param time_offset If -1, the field will not be transmitted, otherwise it is the offset between
+ * UTC and local time in minutes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_datetime_send(struct en50221_app_datetime *datetime,
+ uint16_t session_number,
+ time_t utc_time,
+ int time_offset);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param datetime datetime instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_datetime_message(struct en50221_app_datetime *datetime,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_dvb.c b/lib/libdvben50221/en50221_app_dvb.c
new file mode 100644
index 0000000..21b2bec
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_dvb.c
@@ -0,0 +1,282 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_dvb.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_dvb {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_dvb_tune_callback tune_callback;
+ void *tune_callback_arg;
+
+ en50221_app_dvb_replace_callback replace_callback;
+ void *replace_callback_arg;
+
+ en50221_app_dvb_clear_replace_callback clear_replace_callback;
+ void *clear_replace_callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_dvb_parse_tune(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+static int en50221_app_dvb_parse_replace(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+static int en50221_app_dvb_parse_clear_replace(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_dvb *en50221_app_dvb_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_dvb *dvb = NULL;
+
+ // create structure and set it up
+ dvb = malloc(sizeof(struct en50221_app_dvb));
+ if (dvb == NULL) {
+ return NULL;
+ }
+ dvb->funcs = funcs;
+ dvb->tune_callback = NULL;
+ dvb->replace_callback = NULL;
+ dvb->clear_replace_callback = NULL;
+
+ pthread_mutex_init(&dvb->lock, NULL);
+
+ // done
+ return dvb;
+}
+
+void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb)
+{
+ pthread_mutex_destroy(&dvb->lock);
+ free(dvb);
+}
+
+void en50221_app_dvb_register_tune_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_tune_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&dvb->lock);
+ dvb->tune_callback = callback;
+ dvb->tune_callback_arg = arg;
+ pthread_mutex_unlock(&dvb->lock);
+}
+
+void en50221_app_dvb_register_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_replace_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&dvb->lock);
+ dvb->replace_callback = callback;
+ dvb->replace_callback_arg = arg;
+ pthread_mutex_unlock(&dvb->lock);
+}
+
+void en50221_app_dvb_register_clear_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_clear_replace_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&dvb->lock);
+ dvb->clear_replace_callback = callback;
+ dvb->clear_replace_callback_arg = arg;
+ pthread_mutex_unlock(&dvb->lock);
+}
+
+int en50221_app_dvb_ask_release(struct en50221_app_dvb *dvb,
+ uint16_t session_number)
+{
+ uint8_t data[4];
+
+ data[0] = (TAG_ASK_RELEASE >> 16) & 0xFF;
+ data[1] = (TAG_ASK_RELEASE >> 8) & 0xFF;
+ data[2] = TAG_ASK_RELEASE & 0xFF;
+ data[3] = 0;
+
+ return dvb->funcs->send_data(dvb->funcs->arg, session_number, data, 4);
+}
+
+int en50221_app_dvb_message(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_TUNE:
+ return en50221_app_dvb_parse_tune(dvb, slot_id,
+ session_number, data + 3,
+ data_length - 3);
+ case TAG_REPLACE:
+ return en50221_app_dvb_parse_replace(dvb, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_CLEAR_REPLACE:
+ return en50221_app_dvb_parse_clear_replace(dvb, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+
+
+
+
+
+
+
+static int en50221_app_dvb_parse_tune(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length)
+{
+ // validate data
+ if (data_length < 9) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 8) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *tune_data = data + 1;
+
+ // parse it
+ uint16_t network_id = (tune_data[0] << 8) | tune_data[1];
+ uint16_t original_network_id = (tune_data[2] << 8) | tune_data[3];
+ uint16_t transport_stream_id = (tune_data[4] << 8) | tune_data[5];
+ uint16_t service_id = (tune_data[6] << 8) | tune_data[7];
+
+ // tell the app
+ pthread_mutex_lock(&dvb->lock);
+ en50221_app_dvb_tune_callback cb = dvb->tune_callback;
+ void *cb_arg = dvb->tune_callback_arg;
+ pthread_mutex_unlock(&dvb->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, network_id,
+ original_network_id, transport_stream_id,
+ service_id);
+ }
+ return 0;
+}
+
+static int en50221_app_dvb_parse_replace(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length < 6) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 5) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *replace_data = data + 1;
+
+ // parse it
+ uint8_t replacement_ref = replace_data[0];
+ uint16_t replace_pid =
+ ((replace_data[1] & 0x1f) << 8) | replace_data[2];
+ uint16_t replacement_pid =
+ ((replace_data[3] & 0x1f) << 8) | replace_data[4];
+
+ // tell the app
+ pthread_mutex_lock(&dvb->lock);
+ en50221_app_dvb_replace_callback cb = dvb->replace_callback;
+ void *cb_arg = dvb->replace_callback_arg;
+ pthread_mutex_unlock(&dvb->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, replacement_ref,
+ replace_pid, replacement_pid);
+ }
+ return 0;
+}
+
+static int en50221_app_dvb_parse_clear_replace(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *replace_data = data + 1;
+
+ // parse it
+ uint8_t replacement_ref = replace_data[0];
+
+ // tell the app
+ pthread_mutex_lock(&dvb->lock);
+ en50221_app_dvb_clear_replace_callback cb =
+ dvb->clear_replace_callback;
+ void *cb_arg = dvb->clear_replace_callback_arg;
+ pthread_mutex_unlock(&dvb->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ replacement_ref);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_dvb.h b/lib/libdvben50221/en50221_app_dvb.h
new file mode 100644
index 0000000..be74e6b
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_dvb.h
@@ -0,0 +1,176 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_DVB_H__
+#define __EN50221_APPLICATION_DVB_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_DVB_RESOURCEID MKRID(32,1,1)
+
+
+/**
+ * Type definition for tune - called when we receive a tune request from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param network_id Network id requested by CAM.
+ * @param original_network_id Original Network id requested by CAM.
+ * @param transport_stream_id Transport stream id requested by CAM.
+ * @param service_id Service id requested by CAM.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_dvb_tune_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint16_t network_id,
+ uint32_t original_network_id,
+ uint16_t transport_stream_id,
+ uint16_t service_id);
+
+/**
+ * Type definition for replace - called when we receive a replace request from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param replacement_ref Replacement ref.
+ * @param replaced_pid PID to replace.
+ * @param replacement_pid PID to replace it with.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_dvb_replace_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t replacement_ref,
+ uint16_t replaced_pid,
+ uint16_t replacement_pid);
+
+
+/**
+ * Type definition for clear_replace - called when we receive a clear_replace request from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param replacement_ref Replacement ref.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_dvb_clear_replace_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t replacement_ref);
+
+
+/**
+ * Opaque type representing a dvb resource.
+ */
+struct en50221_app_dvb;
+
+/**
+ * Create an instance of the dvb resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_dvb *en50221_app_dvb_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the dvb resource.
+ *
+ * @param dvb Instance to destroy.
+ */
+extern void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb);
+
+/**
+ * Register the callback for when we receive a tune request.
+ *
+ * @param dvb DVB resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_dvb_register_tune_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_tune_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a replace request.
+ *
+ * @param dvb DVB resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_dvb_register_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_replace_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a clear replace request.
+ *
+ * @param dvb DVB resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_dvb_register_clear_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_clear_replace_callback callback,
+ void *arg);
+
+/**
+ * Send an ask release request to the CAM.
+ *
+ * @param dvb DVB resource instance.
+ * @param session_number Session number to send it on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_dvb_ask_release(struct en50221_app_dvb *dvb,
+ uint16_t session_number);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param dvb dvb instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_dvb_message(struct en50221_app_dvb *dvb,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_epg.c b/lib/libdvben50221/en50221_app_epg.c
new file mode 100644
index 0000000..87b4743
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_epg.c
@@ -0,0 +1,167 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include <libucsi/dvb/types.h>
+#include "en50221_app_epg.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_epg {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_epg_reply_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_epg_parse_reply(struct en50221_app_epg *private,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_epg *en50221_app_epg_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_epg *epg = NULL;
+
+ // create structure and set it up
+ epg = malloc(sizeof(struct en50221_app_epg));
+ if (epg == NULL) {
+ return NULL;
+ }
+ epg->funcs = funcs;
+ epg->callback = NULL;
+
+ pthread_mutex_init(&epg->lock, NULL);
+
+ // done
+ return epg;
+}
+
+void en50221_app_epg_destroy(struct en50221_app_epg *epg)
+{
+ pthread_mutex_destroy(&epg->lock);
+ free(epg);
+}
+
+void en50221_app_epg_register_enquiry_callback(struct en50221_app_epg *epg,
+ en50221_app_epg_reply_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&epg->lock);
+ epg->callback = callback;
+ epg->callback_arg = arg;
+ pthread_mutex_unlock(&epg->lock);
+}
+
+int en50221_app_epg_enquire(struct en50221_app_epg *epg,
+ uint16_t session_number,
+ uint8_t command_id,
+ uint16_t network_id,
+ uint16_t original_network_id,
+ uint16_t transport_stream_id,
+ uint16_t service_id, uint16_t event_id)
+{
+ uint8_t data[15];
+
+ data[0] = (TAG_EPG_ENQUIRY >> 16) & 0xFF;
+ data[1] = (TAG_EPG_ENQUIRY >> 8) & 0xFF;
+ data[2] = TAG_EPG_ENQUIRY & 0xFF;
+ data[3] = 11;
+ data[4] = command_id;
+ data[5] = network_id >> 8;
+ data[6] = network_id;
+ data[7] = original_network_id >> 8;
+ data[8] = original_network_id;
+ data[9] = transport_stream_id >> 8;
+ data[10] = transport_stream_id;
+ data[11] = service_id >> 8;
+ data[12] = service_id;
+ data[13] = event_id >> 8;
+ data[14] = event_id;
+ return epg->funcs->send_data(epg->funcs->arg, session_number, data, 15);
+}
+
+int en50221_app_epg_message(struct en50221_app_epg *epg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ struct en50221_app_epg *private = (struct en50221_app_epg *) epg;
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_EPG_REPLY:
+ return en50221_app_epg_parse_reply(private, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+static int en50221_app_epg_parse_reply(struct en50221_app_epg *epg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t event_status = data[1];
+
+ // tell the app
+ pthread_mutex_lock(&epg->lock);
+ en50221_app_epg_reply_callback cb = epg->callback;
+ void *cb_arg = epg->callback_arg;
+ pthread_mutex_unlock(&epg->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, event_status);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_epg.h b/lib/libdvben50221/en50221_app_epg.h
new file mode 100644
index 0000000..dcfe9da
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_epg.h
@@ -0,0 +1,138 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_epg_H__
+#define __EN50221_APPLICATION_epg_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EPG_COMMAND_ID_MMI 0x02
+#define EPG_COMMAND_ID_QUERY 0x03
+
+#define EPG_EVENTSTATUS_ENTITLEMENT_UNKNOWN 0x00
+#define EPG_EVENTSTATUS_ENTITLEMENT_AVAILABLE 0x01
+#define EPG_EVENTSTATUS_ENTITLEMENT_NOT_AVAILABLE 0x02
+#define EPG_EVENTSTATUS_MMI_DIALOGUE_REQUIRED 0x03
+#define EPG_EVENTSTATUS_MMI_COMPLETE_UNKNOWN 0x04
+#define EPG_EVENTSTATUS_MMI_COMPLETE_AVAILABLE 0x05
+#define EPG_EVENTSTATUS_MMI_COMPLETE_NOT_AVAILABLE 0x06
+
+#define EN50221_APP_EPG_RESOURCEID(INSTANCE_NUM) MKRID(120,(INSTANCE_NUM),1)
+
+
+
+/**
+ * Type definition for reply - called when we receive an EPG reply from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param event_status One of the EPG_EVENTSTATUS_* values.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_epg_reply_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t event_status);
+
+/**
+ * Opaque type representing a epg resource.
+ */
+struct en50221_app_epg;
+
+/**
+ * Create an instance of the epg resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_epg *en50221_app_epg_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the epg resource.
+ *
+ * @param epg Instance to destroy.
+ */
+extern void en50221_app_epg_destroy(struct en50221_app_epg *epg);
+
+/**
+ * Register the callback for when we receive a enquiry response.
+ *
+ * @param epg epg resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_epg_register_reply_callback(struct en50221_app_epg *epg,
+ en50221_app_epg_reply_callback callback,
+ void *arg);
+
+/**
+ * Enquire about the entitlement status for an EPG entry.
+ *
+ * @param epg epg resource instance.
+ * @param session_number Session number to send it on.
+ * @param command_id One of the EPG_COMMAND_ID_* fields.
+ * @param network_id Network ID concerned.
+ * @param original_network_id Original network ID concerned.
+ * @param transport_stream_id Transport stream ID concerned.
+ * @param service_id Service ID concerned.
+ * @param event_id Event ID concerned.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_epg_enquire(struct en50221_app_epg *epg,
+ uint16_t session_number,
+ uint8_t command_id,
+ uint16_t network_id,
+ uint16_t original_network_id,
+ uint16_t transport_stream_id,
+ uint16_t service_id,
+ uint16_t event_id);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param epg epg instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_epg_message(struct en50221_app_epg *epg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_lowspeed.c b/lib/libdvben50221/en50221_app_lowspeed.c
new file mode 100644
index 0000000..a66598a
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_lowspeed.c
@@ -0,0 +1,533 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_lowspeed.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_lowspeed_session {
+ uint16_t session_number;
+ uint8_t *block_chain;
+ uint32_t block_length;
+
+ struct en50221_app_lowspeed_session *next;
+};
+
+struct en50221_app_lowspeed {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_lowspeed_command_callback command_callback;
+ void *command_callback_arg;
+
+ en50221_app_lowspeed_send_callback send_callback;
+ void *send_callback_arg;
+
+ struct en50221_app_lowspeed_session *sessions;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_lowspeed_parse_connect_on_channel(struct en50221_app_lowspeed_command *command,
+ uint8_t *data,
+ int data_length);
+static int en50221_app_lowspeed_parse_command(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length);
+static int en50221_app_lowspeed_parse_send(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ int more_last,
+ uint8_t *data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_lowspeed *en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_lowspeed *lowspeed = NULL;
+
+ // create structure and set it up
+ lowspeed = malloc(sizeof(struct en50221_app_lowspeed));
+ if (lowspeed == NULL) {
+ return NULL;
+ }
+ lowspeed->funcs = funcs;
+ lowspeed->command_callback = NULL;
+ lowspeed->send_callback = NULL;
+ lowspeed->sessions = NULL;
+
+ pthread_mutex_init(&lowspeed->lock, NULL);
+
+ // done
+ return lowspeed;
+}
+
+void en50221_app_lowspeed_destroy(struct en50221_app_lowspeed *lowspeed)
+{
+ struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions;
+ while (cur_s) {
+ struct en50221_app_lowspeed_session *next = cur_s->next;
+ if (cur_s->block_chain)
+ free(cur_s->block_chain);
+ free(cur_s);
+ cur_s = next;
+ }
+
+ pthread_mutex_destroy(&lowspeed->lock);
+ free(lowspeed);
+}
+
+void en50221_app_lowspeed_clear_session(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number)
+{
+ pthread_mutex_lock(&lowspeed->lock);
+ struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions;
+ struct en50221_app_lowspeed_session *prev_s = NULL;
+ while (cur_s) {
+ if (cur_s->session_number == session_number) {
+ if (cur_s->block_chain)
+ free(cur_s->block_chain);
+ if (prev_s) {
+ prev_s->next = cur_s->next;
+ } else {
+ lowspeed->sessions = cur_s->next;
+ }
+ free(cur_s);
+ return;
+ }
+
+ prev_s = cur_s;
+ cur_s = cur_s->next;
+ }
+ pthread_mutex_unlock(&lowspeed->lock);
+}
+
+void en50221_app_lowspeed_register_command_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_command_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&lowspeed->lock);
+ lowspeed->command_callback = callback;
+ lowspeed->command_callback_arg = arg;
+ pthread_mutex_unlock(&lowspeed->lock);
+}
+
+void en50221_app_lowspeed_register_send_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_send_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&lowspeed->lock);
+ lowspeed->send_callback = callback;
+ lowspeed->send_callback_arg = arg;
+ pthread_mutex_unlock(&lowspeed->lock);
+}
+
+int en50221_app_lowspeed_send_comms_reply(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number,
+ uint8_t comms_reply_id,
+ uint8_t return_value)
+{
+ uint8_t data[6];
+
+ data[0] = (TAG_COMMS_REPLY >> 16) & 0xFF;
+ data[1] = (TAG_COMMS_REPLY >> 8) & 0xFF;
+ data[2] = TAG_COMMS_REPLY & 0xFF;
+ data[3] = 2;
+ data[4] = comms_reply_id;
+ data[5] = return_value;
+ return lowspeed->funcs->send_data(lowspeed->funcs->arg,
+ session_number, data, 6);
+}
+
+int en50221_app_lowspeed_send_comms_data(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number,
+ uint8_t phase_id,
+ uint32_t tx_data_length,
+ uint8_t * tx_data)
+{
+ uint8_t buf[10];
+
+ // the spec defines this limit
+ if (tx_data_length > 254) {
+ return -1;
+ }
+ // set up the tag
+ buf[0] = (TAG_COMMS_RECV_LAST >> 16) & 0xFF;
+ buf[1] = (TAG_COMMS_RECV_LAST >> 8) & 0xFF;
+ buf[2] = TAG_COMMS_RECV_LAST & 0xFF;
+
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(tx_data_length + 1, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ // the phase_id
+ buf[3 + length_field_len] = phase_id;
+
+ // build the iovecs
+ struct iovec iov[2];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len + 1;
+ iov[1].iov_base = tx_data;
+ iov[1].iov_len = tx_data_length;
+
+ // create the data and send it
+ return lowspeed->funcs->send_datav(lowspeed->funcs->arg,
+ session_number, iov, 2);
+}
+
+int en50221_app_lowspeed_message(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_COMMS_COMMAND:
+ return en50221_app_lowspeed_parse_command(lowspeed,
+ slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_COMMS_SEND_LAST:
+ return en50221_app_lowspeed_parse_send(lowspeed, slot_id,
+ session_number, 1,
+ data + 3,
+ data_length - 3);
+ case TAG_COMMS_SEND_MORE:
+ return en50221_app_lowspeed_parse_send(lowspeed, slot_id,
+ session_number, 0,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+static int en50221_app_lowspeed_parse_connect_on_channel(struct en50221_app_lowspeed_command *command,
+ uint8_t *data,
+ int data_length)
+{
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // check the tag
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+ if (tag != TAG_CONNECTION_DESCRIPTOR) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received bad CONNECT_ON_CHANNEL\n");
+ return -1;
+ }
+ data += 3;
+ data_length -= 3;
+
+ // parse the descriptor-length-field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ data += length_field_len;
+ data_length -= length_field_len;
+
+ // check length field
+ if (asn_data_length > data_length) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length < 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // get the descriptor type
+ command->u.connect_on_channel.descriptor_type = data[0];
+ data++;
+ data_length--;
+ asn_data_length--;
+
+ // deal with the descriptor itself
+ switch (command->u.connect_on_channel.descriptor_type) {
+ case CONNECTION_DESCRIPTOR_TYPE_TELEPHONE:
+ {
+ // get the raw descriptor and validate length
+ struct descriptor *d = (struct descriptor *) data;
+ if (asn_data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length != (2 + d->len)) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ if (d->tag != dtag_dvb_telephone) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received invalid telephone descriptor\n");
+ return -1;
+ }
+ // parse the telephone descriptor
+ command->u.connect_on_channel.descriptor.telephone = dvb_telephone_descriptor_codec(d);
+ if (command->u.connect_on_channel.descriptor.telephone == NULL) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received invalid telephone descriptor\n");
+ return -1;
+ }
+ data += 2 + d->len;
+ data_length -= 2 + d->len;
+ break;
+ }
+
+ case CONNECTION_DESCRIPTOR_TYPE_CABLE:
+ if (asn_data_length != 1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ command->u.connect_on_channel.descriptor.cable_channel_id = data[0];
+ data++;
+ data_length--;
+ break;
+ default:
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unknown connection descriptor %02x\n",
+ command->u.connect_on_channel.descriptor_type);
+ return -1;
+ }
+
+ // parse the last bit
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ command->u.connect_on_channel.retry_count = data[0];
+ command->u.connect_on_channel.timeout = data[1];
+
+ // ok
+ return 0;
+}
+
+static int en50221_app_lowspeed_parse_command(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length < 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ data += length_field_len;
+
+ // get command id
+ uint8_t command_id = data[0];
+ data++;
+ asn_data_length--;
+
+ // parse the command
+ struct en50221_app_lowspeed_command command;
+ switch (command_id) {
+ case COMMS_COMMAND_ID_CONNECT_ON_CHANNEL:
+ if (en50221_app_lowspeed_parse_connect_on_channel
+ (&command, data, asn_data_length)) {
+ return -1;
+ }
+ break;
+ case COMMS_COMMAND_ID_SET_PARAMS:
+ if (asn_data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ command.u.set_params.buffer_size = data[0];
+ command.u.set_params.timeout = data[1];
+ break;
+ case COMMS_COMMAND_ID_GET_NEXT_BUFFER:
+ if (asn_data_length != 1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ command.u.get_next_buffer.phase_id = data[0];
+ break;
+
+ case COMMS_COMMAND_ID_DISCONNECT_ON_CHANNEL:
+ case COMMS_COMMAND_ID_ENQUIRE_STATUS:
+ break;
+
+ default:
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected command_id %02x\n", command_id);
+ return -1;
+ }
+
+ // tell the app
+ pthread_mutex_lock(&lowspeed->lock);
+ en50221_app_lowspeed_command_callback cb = lowspeed->command_callback;
+ void *cb_arg = lowspeed->command_callback_arg;
+ pthread_mutex_unlock(&lowspeed->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, command_id,
+ &command);
+ }
+ return 0;
+}
+
+static int en50221_app_lowspeed_parse_send(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ int more_last,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // skip over the length field
+ data += length_field_len;
+
+ // find previous session
+ pthread_mutex_lock(&lowspeed->lock);
+ struct en50221_app_lowspeed_session *cur_s = lowspeed->sessions;
+ while (cur_s) {
+ if (cur_s->session_number == session_number)
+ break;
+ cur_s = cur_s->next;
+ }
+
+ // more data is still to come
+ if (!more_last) {
+ // if there was no previous session, create one
+ if (cur_s == NULL) {
+ cur_s = malloc(sizeof(struct en50221_app_lowspeed_session));
+ if (cur_s == NULL) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Ran out of memory\n");
+ pthread_mutex_unlock(&lowspeed->lock);
+ return -1;
+ }
+ cur_s->session_number = session_number;
+ cur_s->block_chain = NULL;
+ cur_s->block_length = 0;
+ cur_s->next = lowspeed->sessions;
+ lowspeed->sessions = cur_s;
+ }
+ // append the data
+ uint8_t *new_data = realloc(cur_s->block_chain,
+ cur_s->block_length + asn_data_length);
+ if (new_data == NULL) {
+ print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n");
+ pthread_mutex_unlock(&lowspeed->lock);
+ return -1;
+ }
+ memcpy(new_data + cur_s->block_length, data, asn_data_length);
+ cur_s->block_chain = new_data;
+ cur_s->block_length += asn_data_length;
+
+ // done
+ pthread_mutex_unlock(&lowspeed->lock);
+ return 0;
+ }
+ // we hit the last of a possible chain of fragments
+ int do_free = 0;
+ if (cur_s != NULL) {
+ // we have a preceding fragment - need to append
+ uint8_t *new_data = realloc(cur_s->block_chain,
+ cur_s->block_length + asn_data_length);
+ if (new_data == NULL) {
+ print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n");
+ pthread_mutex_unlock(&lowspeed->lock);
+ return -1;
+ }
+ memcpy(new_data + cur_s->block_length, data, asn_data_length);
+ asn_data_length = cur_s->block_length + asn_data_length;
+ data = new_data;
+ cur_s->block_chain = NULL;
+ cur_s->block_length = 0;
+ do_free = 1;
+ }
+ // check the reassembled data length
+ if (asn_data_length < 1) {
+ pthread_mutex_unlock(&lowspeed->lock);
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ if (do_free)
+ free(data);
+ return -1;
+ }
+ // now, parse the data
+ uint8_t phase_id = data[0];
+
+ // tell the app
+ en50221_app_lowspeed_send_callback cb = lowspeed->send_callback;
+ void *cb_arg = lowspeed->send_callback_arg;
+ pthread_mutex_unlock(&lowspeed->lock);
+ int cbstatus = 0;
+ if (cb) {
+ cbstatus =
+ cb(cb_arg, slot_id, session_number, phase_id, data + 1, asn_data_length - 1);
+ }
+ // done
+ if (do_free)
+ free(data);
+ return cbstatus;
+}
diff --git a/lib/libdvben50221/en50221_app_lowspeed.h b/lib/libdvben50221/en50221_app_lowspeed.h
new file mode 100644
index 0000000..0ef983c
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_lowspeed.h
@@ -0,0 +1,219 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_LOWSPEED_H__
+#define __EN50221_APPLICATION_LOWSPEED_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+#include <libucsi/dvb/descriptor.h>
+
+#define COMMS_COMMAND_ID_CONNECT_ON_CHANNEL 0x01
+#define COMMS_COMMAND_ID_DISCONNECT_ON_CHANNEL 0x02
+#define COMMS_COMMAND_ID_SET_PARAMS 0x03
+#define COMMS_COMMAND_ID_ENQUIRE_STATUS 0x04
+#define COMMS_COMMAND_ID_GET_NEXT_BUFFER 0x05
+
+#define CONNECTION_DESCRIPTOR_TYPE_TELEPHONE 0x01
+#define CONNECTION_DESCRIPTOR_TYPE_CABLE 0x02
+
+#define COMMS_REPLY_ID_CONNECT_ACK 0x01
+#define COMMS_REPLY_ID_DISCONNECT_ACK 0x02
+#define COMMS_REPLY_ID_SET_PARAMS_ACK 0x03
+#define COMMS_REPLY_ID_STATUS_REPLY 0x04
+#define COMMS_REPLY_ID_GET_NEXT_BUFFER_ACK 0x05
+#define COMMS_REPLY_ID_SEND_ACK 0x06
+
+#define EN50221_APP_LOWSPEED_RESOURCEID(DEVICE_TYPE, DEVICE_NUMBER) MKRID(96,((DEVICE_TYPE)<<2)|((DEVICE_NUMBER) & 0x03),1)
+
+
+/**
+ * Structure holding information on a received comms command.
+ */
+struct en50221_app_lowspeed_command {
+ union {
+ struct {
+ uint8_t descriptor_type; // CONNECTION_DESCRIPTOR_TYPE_*
+ uint8_t retry_count;
+ uint8_t timeout;
+ union {
+ struct dvb_telephone_descriptor *telephone;
+ uint8_t cable_channel_id;
+ } descriptor;
+ } connect_on_channel;
+
+ struct {
+ uint8_t buffer_size;
+ uint8_t timeout;
+ } set_params;
+
+ struct {
+ uint8_t phase_id;
+ } get_next_buffer;
+ } u;
+};
+
+/**
+ * Type definition for command - called when we receive a comms command.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param command_id One of the COMMS_COMMAND_ID_* values
+ * @param command Pointer to a lowspeed command structure containing the command data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_lowspeed_command_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t command_id,
+ struct en50221_app_lowspeed_command *command);
+
+/**
+ * Type definition for send - called when we receive data to send. The block can be segmented into
+ * multiple pieces - last_more indicates the details of this.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param phase_id Comms phase id.
+ * @param data The data.
+ * @param length Number of bytes.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_lowspeed_send_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t phase_id,
+ uint8_t *data,
+ uint32_t length);
+
+/**
+ * Opaque type representing a lowspeed resource.
+ */
+struct en50221_app_lowspeed;
+
+/**
+ * Create an instance of the lowspeed resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_lowspeed *
+ en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the lowspeed resource.
+ *
+ * @param lowspeed Instance to destroy.
+ */
+extern void en50221_app_lowspeed_destroy(struct en50221_app_lowspeed *lowspeed);
+
+/**
+ * Informs the lowspeed object that a session to it has been closed - cleans up internal state.
+ *
+ * @param lowspeed lowspeed resource instance.
+ * @param session_number The session concerned.
+ */
+extern void en50221_app_lowspeed_clear_session(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number);
+
+/**
+ * Register the callback for when we receive a comms command.
+ *
+ * @param lowspeed lowspeed resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_lowspeed_register_command_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_command_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive data to send.
+ *
+ * @param lowspeed lowspeed resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_lowspeed_register_send_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_send_callback callback,
+ void *arg);
+
+/**
+ * Send a comms reply to the CAM.
+ *
+ * @param lowspeed lowspeed resource instance.
+ * @param session_number Session number to send it on.
+ * @param comms_reply_id One of the COMMS_REPLY_ID_* values.
+ * @param return_value Comms reply specific value.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_lowspeed_send_comms_reply(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number,
+ uint8_t comms_reply_id,
+ uint8_t return_value);
+
+/**
+ * Send received data to the CAM.
+ *
+ * @param lowspeed lowspeed resource instance.
+ * @param session_number Session number to send it on.
+ * @param phase_id Comms phase id.
+ * @param tx_data_length Length of data in bytes (max 254 bytes as per spec).
+ * @param tx_data Data.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_lowspeed_send_comms_data(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number,
+ uint8_t phase_id,
+ uint32_t tx_data_length,
+ uint8_t * tx_data);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param lowspeed lowspeed instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_lowspeed_message(struct en50221_app_lowspeed *lowspeed,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_mmi.c b/lib/libdvben50221/en50221_app_mmi.c
new file mode 100644
index 0000000..830eaa3
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_mmi.c
@@ -0,0 +1,1397 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include <libucsi/dvb/types.h>
+#include "en50221_app_mmi.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_mmi_session {
+ uint16_t session_number;
+
+ uint8_t *menu_block_chain;
+ uint32_t menu_block_length;
+
+ uint8_t *list_block_chain;
+ uint32_t list_block_length;
+
+ uint8_t *subtitlesegment_block_chain;
+ uint32_t subtitlesegment_block_length;
+
+ uint8_t *subtitledownload_block_chain;
+ uint32_t subtitledownload_block_length;
+
+ struct en50221_app_mmi_session *next;
+};
+
+struct en50221_app_mmi {
+ struct en50221_app_send_functions *funcs;
+ struct en50221_app_mmi_session *sessions;
+
+ en50221_app_mmi_close_callback closecallback;
+ void *closecallback_arg;
+
+ en50221_app_mmi_display_control_callback displaycontrolcallback;
+ void *displaycontrolcallback_arg;
+
+ en50221_app_mmi_keypad_control_callback keypadcontrolcallback;
+ void *keypadcontrolcallback_arg;
+
+ en50221_app_mmi_subtitle_segment_callback subtitlesegmentcallback;
+ void *subtitlesegmentcallback_arg;
+
+ en50221_app_mmi_scene_end_mark_callback sceneendmarkcallback;
+ void *sceneendmarkcallback_arg;
+
+ en50221_app_mmi_scene_control_callback scenecontrolcallback;
+ void *scenecontrolcallback_arg;
+
+ en50221_app_mmi_subtitle_download_callback subtitledownloadcallback;
+ void *subtitledownloadcallback_arg;
+
+ en50221_app_mmi_flush_download_callback flushdownloadcallback;
+ void *flushdownloadcallback_arg;
+
+ en50221_app_mmi_enq_callback enqcallback;
+ void *enqcallback_arg;
+
+ en50221_app_mmi_menu_callback menucallback;
+ void *menucallback_arg;
+
+ en50221_app_mmi_list_callback listcallback;
+ void *listcallback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_mmi_parse_close(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_display_control(struct en50221_app_mmi
+ *mmi, uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_keypad_control(struct en50221_app_mmi
+ *mmi, uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_enq(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length);
+static int en50221_app_mmi_parse_list_menu(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_scene_end_mark(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_scene_control(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_parse_flush_download(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_mmi_defragment(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * indata,
+ uint32_t indata_length,
+ uint8_t ** outdata,
+ uint32_t * outdata_length);
+static int en50221_app_mmi_defragment_text(uint8_t * data,
+ uint32_t data_length,
+ uint8_t ** outdata,
+ uint32_t * outdata_length,
+ uint32_t * outconsumed);
+
+
+
+struct en50221_app_mmi *en50221_app_mmi_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_mmi *mmi = NULL;
+
+ // create structure and set it up
+ mmi = malloc(sizeof(struct en50221_app_mmi));
+ if (mmi == NULL) {
+ return NULL;
+ }
+ mmi->funcs = funcs;
+ mmi->closecallback = NULL;
+ mmi->displaycontrolcallback = NULL;
+ mmi->keypadcontrolcallback = NULL;
+ mmi->subtitlesegmentcallback = NULL;
+ mmi->sceneendmarkcallback = NULL;
+ mmi->scenecontrolcallback = NULL;
+ mmi->subtitledownloadcallback = NULL;
+ mmi->flushdownloadcallback = NULL;
+ mmi->enqcallback = NULL;
+ mmi->menucallback = NULL;
+ mmi->listcallback = NULL;
+ mmi->sessions = NULL;
+
+ pthread_mutex_init(&mmi->lock, NULL);
+
+ // done
+ return mmi;
+}
+
+void en50221_app_mmi_destroy(struct en50221_app_mmi *mmi)
+{
+ struct en50221_app_mmi_session *cur_s = mmi->sessions;
+ while (cur_s) {
+ struct en50221_app_mmi_session *next = cur_s->next;
+ if (cur_s->menu_block_chain)
+ free(cur_s->menu_block_chain);
+ if (cur_s->list_block_chain)
+ free(cur_s->list_block_chain);
+ if (cur_s->subtitlesegment_block_chain)
+ free(cur_s->subtitlesegment_block_chain);
+ if (cur_s->subtitledownload_block_chain)
+ free(cur_s->subtitledownload_block_chain);
+ free(cur_s);
+ cur_s = next;
+ }
+
+ pthread_mutex_destroy(&mmi->lock);
+ free(mmi);
+}
+
+void en50221_app_mmi_clear_session(struct en50221_app_mmi *mmi,
+ uint16_t session_number)
+{
+ pthread_mutex_lock(&mmi->lock);
+ struct en50221_app_mmi_session *cur_s = mmi->sessions;
+ struct en50221_app_mmi_session *prev_s = NULL;
+ while (cur_s) {
+ if (cur_s->session_number == session_number) {
+ if (cur_s->menu_block_chain)
+ free(cur_s->menu_block_chain);
+ if (cur_s->list_block_chain)
+ free(cur_s->list_block_chain);
+ if (cur_s->subtitlesegment_block_chain)
+ free(cur_s->subtitlesegment_block_chain);
+ if (cur_s->subtitledownload_block_chain)
+ free(cur_s->subtitledownload_block_chain);
+ if (prev_s) {
+ prev_s->next = cur_s->next;
+ } else {
+ mmi->sessions = cur_s->next;
+ }
+ free(cur_s);
+ return;
+ }
+
+ prev_s = cur_s;
+ cur_s = cur_s->next;
+ }
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_close_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_close_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->closecallback = callback;
+ mmi->closecallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_display_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_display_control_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->displaycontrolcallback = callback;
+ mmi->displaycontrolcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_keypad_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_keypad_control_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->keypadcontrolcallback = callback;
+ mmi->keypadcontrolcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_subtitle_segment_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_segment_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->subtitlesegmentcallback = callback;
+ mmi->subtitlesegmentcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_scene_end_mark_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_end_mark_callback callback, void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->sceneendmarkcallback = callback;
+ mmi->sceneendmarkcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_scene_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_control_callback callback, void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->scenecontrolcallback = callback;
+ mmi->scenecontrolcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_subtitle_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_download_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->subtitledownloadcallback = callback;
+ mmi->subtitledownloadcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_flush_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_flush_download_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->flushdownloadcallback = callback;
+ mmi->flushdownloadcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_enq_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_enq_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->enqcallback = callback;
+ mmi->enqcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_menu_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_menu_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->menucallback = callback;
+ mmi->menucallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+void en50221_app_mmi_register_list_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_list_callback callback,
+ void *arg)
+{
+ pthread_mutex_lock(&mmi->lock);
+ mmi->listcallback = callback;
+ mmi->listcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
+}
+
+int en50221_app_mmi_close(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t cmd_id, uint8_t delay)
+{
+ uint8_t data[6];
+ int data_length = 5;
+
+ data[0] = (TAG_CLOSE_MMI >> 16) & 0xFF;
+ data[1] = (TAG_CLOSE_MMI >> 8) & 0xFF;
+ data[2] = TAG_CLOSE_MMI & 0xFF;
+ data[3] = 1;
+ data[4] = cmd_id;
+ if (cmd_id == MMI_CLOSE_MMI_CMD_ID_DELAY) {
+ data[3] = 2;
+ data[5] = delay;
+ data_length = 6;
+ }
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data,
+ data_length);
+}
+
+int en50221_app_mmi_display_reply(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t reply_id,
+ struct en50221_app_mmi_display_reply_details *details)
+{
+ uint8_t data[32];
+ struct iovec iov[2];
+ uint32_t iov_count;
+ int length_field_len;
+
+ // fill out the start of the header
+ data[0] = (TAG_DISPLAY_REPLY >> 16) & 0xFF;
+ data[1] = (TAG_DISPLAY_REPLY >> 8) & 0xFF;
+ data[2] = TAG_DISPLAY_REPLY & 0xFF;
+
+ switch (reply_id) {
+ case MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK:
+ data[3] = 2;
+ data[4] = reply_id;
+ data[5] = details->u.mode_ack.mmi_mode;
+ iov[0].iov_base = data;
+ iov[0].iov_len = 6;
+ iov_count = 1;
+ break;
+
+ case MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES:
+ case MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES:
+ if ((length_field_len =
+ asn_1_encode(details->u.char_table.table_length + 1, data + 3, 3)) < 0) {
+ return -1;
+ }
+ data[3 + length_field_len] = reply_id;
+ iov[0].iov_base = data;
+ iov[0].iov_len = 3 + length_field_len + 1;
+ iov[1].iov_base = details->u.char_table.table;
+ iov[1].iov_len = details->u.char_table.table_length;
+ iov_count = 2;
+ break;
+
+ case MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS:
+ case MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS:
+ {
+ if ((length_field_len =
+ asn_1_encode(1 + 9 + (details->u.gfx.num_pixel_depths * 2), data + 3, 3)) < 0) {
+ return -1;
+ }
+ data[3 + length_field_len] = reply_id;
+ data[3 + length_field_len + 1] = details->u.gfx.width >> 8;
+ data[3 + length_field_len + 2] = details->u.gfx.width;
+ data[3 + length_field_len + 3] = details->u.gfx.height >> 8;
+ data[3 + length_field_len + 4] = details->u.gfx.height;
+ data[3 + length_field_len + 5] =
+ ((details->u.gfx.aspect_ratio & 0x0f) << 4) |
+ ((details->u.gfx.gfx_relation_to_video & 0x07) << 1) |
+ (details->u.gfx.multiple_depths & 1);
+ data[3 + length_field_len + 6] = details->u.gfx.display_bytes >> 4;
+ data[3 + length_field_len + 7] =
+ ((details->u.gfx.display_bytes & 0x0f) << 4) |
+ ((details->u.gfx.composition_buffer_bytes & 0xf0) >> 4);
+ data[3 + length_field_len + 8] =
+ ((details->u.gfx.composition_buffer_bytes & 0x0f) << 4) |
+ ((details->u.gfx.object_cache_bytes & 0xf0) >> 4);
+ data[3 + length_field_len + 9] =
+ ((details->u.gfx.object_cache_bytes & 0x0f) << 4) |
+ (details->u.gfx.num_pixel_depths & 0x0f);
+
+ // render the pixel depths themselves
+ uint8_t *pixdepths =
+ alloca(details->u.gfx.num_pixel_depths * 2);
+ if (pixdepths == NULL) {
+ return -1;
+ }
+ uint32_t i;
+ for (i = 0; i < details->u.gfx.num_pixel_depths; i++) {
+ pixdepths[0] =
+ ((details->u.gfx.pixel_depths[i].display_depth & 0x07) << 5) |
+ ((details->u.gfx.pixel_depths[i].pixels_per_byte & 0x07) << 2);
+ pixdepths[1] =
+ details->u.gfx.pixel_depths[i].region_overhead;
+ pixdepths += 2;
+ }
+
+ // make up the iovs
+ iov[0].iov_base = data;
+ iov[0].iov_len = 3 + length_field_len + 10;
+ iov[1].iov_base = pixdepths;
+ iov[1].iov_len =
+ details->u.gfx.num_pixel_depths * 2;
+ iov_count = 2;
+ break;
+ }
+
+ default:
+ data[3] = 1;
+ data[4] = reply_id;
+ iov[0].iov_base = data;
+ iov[0].iov_len = 5;
+ iov_count = 1;
+ break;
+ }
+
+ // sendit
+ return mmi->funcs->send_datav(mmi->funcs->arg, session_number, iov, iov_count);
+}
+
+int en50221_app_mmi_keypress(struct en50221_app_mmi *mmi,
+ uint16_t session_number, uint8_t keycode)
+{
+ uint8_t data[5];
+
+ data[0] = (TAG_KEYPRESS >> 16) & 0xFF;
+ data[1] = (TAG_KEYPRESS >> 8) & 0xFF;
+ data[2] = TAG_KEYPRESS & 0xFF;
+ data[3] = 1;
+ data[4] = keycode;
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5);
+}
+
+int en50221_app_mmi_display_message(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t display_message_id)
+{
+ uint8_t data[5];
+
+ data[0] = (TAG_DISPLAY_MESSAGE >> 16) & 0xFF;
+ data[1] = (TAG_DISPLAY_MESSAGE >> 8) & 0xFF;
+ data[2] = TAG_DISPLAY_MESSAGE & 0xFF;
+ data[3] = 1;
+ data[4] = display_message_id;
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5);
+}
+
+int en50221_app_mmi_scene_done(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t decoder_continue,
+ uint8_t scene_reveal, uint8_t scene_tag)
+{
+ uint8_t data[5];
+
+ data[0] = (TAG_SCENE_DONE >> 16) & 0xFF;
+ data[1] = (TAG_SCENE_DONE >> 8) & 0xFF;
+ data[2] = TAG_SCENE_DONE & 0xFF;
+ data[3] = 1;
+ data[4] =
+ (decoder_continue ? 0x80 : 0x00) |
+ (scene_reveal ? 0x40 : 0x00) |
+ (scene_tag & 0x0f);
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5);
+}
+
+int en50221_app_mmi_download_reply(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint16_t object_id,
+ uint8_t download_reply_id)
+{
+ uint8_t data[7];
+
+ data[0] = (TAG_DOWNLOAD_REPLY >> 16) & 0xFF;
+ data[1] = (TAG_DOWNLOAD_REPLY >> 8) & 0xFF;
+ data[2] = TAG_DOWNLOAD_REPLY & 0xFF;
+ data[3] = 3;
+ data[4] = object_id >> 8;
+ data[5] = object_id;
+ data[6] = download_reply_id;
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 7);
+}
+
+int en50221_app_mmi_answ(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t answ_id,
+ uint8_t * text, uint32_t text_count)
+{
+ uint8_t buf[10];
+
+ // set up the tag
+ buf[0] = (TAG_ANSWER >> 16) & 0xFF;
+ buf[1] = (TAG_ANSWER >> 8) & 0xFF;
+ buf[2] = TAG_ANSWER & 0xFF;
+
+ // encode the length field
+ struct iovec iov[2];
+ int length_field_len = 0;
+ int iov_count = 1;
+ if (answ_id == MMI_ANSW_ID_ANSWER) {
+ if ((length_field_len = asn_1_encode(text_count + 1, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ buf[3 + length_field_len] = answ_id;
+
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len + 1;
+ iov[1].iov_base = text;
+ iov[1].iov_len = text_count;
+ iov_count = 2;
+ } else {
+ buf[3] = 1;
+ buf[4] = answ_id;
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 5;
+ iov_count = 1;
+ }
+
+ // create the data and send it
+ return mmi->funcs->send_datav(mmi->funcs->arg, session_number, iov,
+ iov_count);
+}
+
+int en50221_app_mmi_menu_answ(struct en50221_app_mmi *mmi,
+ uint16_t session_number, uint8_t choice_ref)
+{
+ uint8_t data[5];
+
+ data[0] = (TAG_MENU_ANSWER >> 16) & 0xFF;
+ data[1] = (TAG_MENU_ANSWER >> 8) & 0xFF;
+ data[2] = TAG_MENU_ANSWER & 0xFF;
+ data[3] = 1;
+ data[4] = choice_ref;
+ return mmi->funcs->send_data(mmi->funcs->arg, session_number, data, 5);
+}
+
+int en50221_app_mmi_message(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_CLOSE_MMI:
+ return en50221_app_mmi_parse_close(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_DISPLAY_CONTROL:
+ return en50221_app_mmi_parse_display_control(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_KEYPAD_CONTROL:
+ return en50221_app_mmi_parse_keypad_control(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_ENQUIRY:
+ return en50221_app_mmi_parse_enq(mmi, slot_id,
+ session_number, data + 3,
+ data_length - 3);
+ case TAG_MENU_LAST:
+ return en50221_app_mmi_parse_list_menu(mmi, slot_id,
+ session_number, tag,
+ 1, data + 3,
+ data_length - 3);
+ case TAG_MENU_MORE:
+ return en50221_app_mmi_parse_list_menu(mmi, slot_id,
+ session_number, tag,
+ 0, data + 3,
+ data_length - 3);
+ case TAG_LIST_LAST:
+ return en50221_app_mmi_parse_list_menu(mmi, slot_id,
+ session_number, tag,
+ 1, data + 3,
+ data_length - 3);
+ case TAG_LIST_MORE:
+ return en50221_app_mmi_parse_list_menu(mmi, slot_id,
+ session_number, tag,
+ 0, data + 3,
+ data_length - 3);
+ case TAG_SUBTITLE_SEGMENT_LAST:
+ return en50221_app_mmi_parse_subtitle(mmi, slot_id,
+ session_number, tag,
+ 1, data + 3,
+ data_length - 3);
+ case TAG_SUBTITLE_SEGMENT_MORE:
+ return en50221_app_mmi_parse_subtitle(mmi, slot_id,
+ session_number, tag,
+ 0, data + 3,
+ data_length - 3);
+ case TAG_SCENE_END_MARK:
+ return en50221_app_mmi_parse_scene_end_mark(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_SCENE_CONTROL:
+ return en50221_app_mmi_parse_scene_control(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_SUBTITLE_DOWNLOAD_LAST:
+ return en50221_app_mmi_parse_subtitle(mmi, slot_id,
+ session_number, tag,
+ 1, data + 3,
+ data_length - 3);
+ case TAG_SUBTITLE_DOWNLOAD_MORE:
+ return en50221_app_mmi_parse_subtitle(mmi, slot_id,
+ session_number, tag,
+ 0, data + 3,
+ data_length - 3);
+ case TAG_FLUSH_DOWNLOAD:
+ return en50221_app_mmi_parse_flush_download(mmi, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+
+
+static int en50221_app_mmi_parse_close(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] > (data_length - 1)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t cmd_id = data[1];
+ uint8_t delay = 0;
+ if (cmd_id == MMI_CLOSE_MMI_CMD_ID_DELAY) {
+ if (data[0] != 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ delay = data[2];
+ }
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_close_callback cb = mmi->closecallback;
+ void *cb_arg = mmi->closecallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, cmd_id, delay);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_display_control(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] > (data_length - 1)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t cmd_id = data[1];
+ uint8_t mmi_mode = 0;
+ if (cmd_id == MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE) {
+ if (data[0] != 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received short data\n");
+ return -1;
+ }
+ mmi_mode = data[2];
+ }
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_display_control_callback cb = mmi->displaycontrolcallback;
+ void *cb_arg = mmi->displaycontrolcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, cmd_id, mmi_mode);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_keypad_control(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length < 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // skip over the length field
+ data += length_field_len;
+
+ // extract the information
+ uint8_t cmd_id = data[0];
+ uint8_t *keycodes = data + 1;
+
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_keypad_control_callback cb = mmi->keypadcontrolcallback;
+ void *cb_arg = mmi->keypadcontrolcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, cmd_id,
+ keycodes, asn_data_length - 1);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_enq(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data, uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length < 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // skip over the length field
+ data += length_field_len;
+
+ // extract the information
+ uint8_t blind_answer = (data[0] & 0x01) ? 1 : 0;
+ uint8_t answer_length = data[1];
+ uint8_t *text = data + 2;
+
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_enq_callback cb = mmi->enqcallback;
+ void *cb_arg = mmi->enqcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, blind_answer,
+ answer_length, text, asn_data_length - 2);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_list_menu(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ int result = 0;
+ uint8_t *text_flags = NULL;
+ struct en50221_app_mmi_text *text_data = NULL;
+ uint32_t i;
+ uint8_t text_count = 0;
+
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // skip over the length field
+ data += length_field_len;
+
+ // defragment
+ pthread_mutex_lock(&mmi->lock);
+ uint8_t *outdata;
+ uint32_t outdata_length;
+ int dfstatus =
+ en50221_app_mmi_defragment(mmi, session_number, tag_id,
+ more_last,
+ data, asn_data_length,
+ &outdata, &outdata_length);
+ if (dfstatus <= 0) {
+ pthread_mutex_unlock(&mmi->lock);
+ return dfstatus;
+ }
+ data = outdata;
+ data_length = outdata_length;
+
+ // check the reassembled data length
+ if (data_length < 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ pthread_mutex_unlock(&mmi->lock);
+ result = -1;
+ goto exit_cleanup;
+ }
+ // now, parse the data
+ uint8_t choice_nb = data[0];
+ text_count = choice_nb + 3;
+ if (choice_nb == 0xff)
+ text_count = 3;
+ data++;
+ data_length--;
+
+ // variables for extracted text state
+ text_flags = alloca(text_count);
+ if (text_flags == NULL) {
+ pthread_mutex_unlock(&mmi->lock);
+ result = -1;
+ goto exit_cleanup;
+ }
+ memset(text_flags, 0, text_count);
+ text_data = (struct en50221_app_mmi_text *)
+ alloca(sizeof(struct en50221_app_mmi_text) * text_count);
+ if (text_data == NULL) {
+ pthread_mutex_unlock(&mmi->lock);
+ result = -1;
+ goto exit_cleanup;
+ }
+ memset(text_data, 0,
+ sizeof(struct en50221_app_mmi_text) * text_count);
+
+ // extract the text!
+ for (i = 0; i < text_count; i++) {
+ uint32_t consumed = 0;
+ int cur_status =
+ en50221_app_mmi_defragment_text(data, data_length,
+ &text_data[i].text,
+ &text_data[i].text_length,
+ &consumed);
+ if (cur_status < 0) {
+ pthread_mutex_unlock(&mmi->lock);
+ result = -1;
+ goto exit_cleanup;
+ }
+
+ text_flags[i] = cur_status;
+ data += consumed;
+ data_length -= consumed;
+ }
+
+ // work out what to pass to the user
+ struct en50221_app_mmi_text *text_data_for_user = (struct en50221_app_mmi_text *)
+ alloca(sizeof(struct en50221_app_mmi_text) * text_count);
+ if (text_data_for_user == NULL) {
+ result = -1;
+ goto exit_cleanup;
+ }
+ memcpy(text_data_for_user, text_data,
+ sizeof(struct en50221_app_mmi_text) * text_count);
+ struct en50221_app_mmi_text *text_ptr = NULL;
+ if (text_count > 3) {
+ text_ptr = &text_data_for_user[3];
+ }
+ uint8_t *items_raw = NULL;
+ uint32_t items_raw_length = 0;
+ if (choice_nb == 0xff) {
+ items_raw = data;
+ items_raw_length = data_length;
+ }
+ // do callback
+ result = 0;
+ switch (tag_id) {
+ case TAG_MENU_LAST:
+ {
+ en50221_app_mmi_menu_callback cb = mmi->menucallback;
+ void *cb_arg = mmi->menucallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ result =
+ cb(cb_arg, slot_id, session_number,
+ &text_data_for_user[0],
+ &text_data_for_user[1],
+ &text_data_for_user[2],
+ text_count - 3, text_ptr,
+ items_raw_length, items_raw);
+ }
+ break;
+ }
+
+ case TAG_LIST_LAST:
+ {
+ en50221_app_mmi_list_callback cb = mmi->listcallback;
+ void *cb_arg = mmi->listcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ result =
+ cb(cb_arg, slot_id, session_number,
+ &text_data_for_user[0],
+ &text_data_for_user[1],
+ &text_data_for_user[2],
+ text_count - 3, text_ptr,
+ items_raw_length, items_raw);
+ }
+ break;
+ }
+
+ default:
+ pthread_mutex_unlock(&mmi->lock);
+ break;
+ }
+
+exit_cleanup:
+ if ((dfstatus == 2) && outdata)
+ free(outdata);
+ if (text_flags && text_data) {
+ for (i = 0; i < text_count; i++) {
+ if ((text_flags[i] == 2) && text_data[i].text) {
+ free(text_data[i].text);
+ }
+ }
+ }
+ return result;
+}
+
+static int en50221_app_mmi_parse_subtitle(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t tag_id, int more_last,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // skip over the length field
+ data += length_field_len;
+
+ // defragment
+ pthread_mutex_lock(&mmi->lock);
+ uint8_t *outdata;
+ uint32_t outdata_length;
+ int dfstatus =
+ en50221_app_mmi_defragment(mmi, session_number, tag_id,
+ more_last,
+ data, asn_data_length,
+ &outdata, &outdata_length);
+ if (dfstatus <= 0) {
+ pthread_mutex_unlock(&mmi->lock);
+ return dfstatus;
+ }
+ // do callback
+ int cbstatus = 0;
+ switch (tag_id) {
+ case TAG_SUBTITLE_SEGMENT_LAST:
+ {
+ en50221_app_mmi_subtitle_segment_callback cb =
+ mmi->subtitlesegmentcallback;
+ void *cb_arg = mmi->subtitlesegmentcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ cbstatus =
+ cb(cb_arg, slot_id, session_number, outdata, outdata_length);
+ }
+ break;
+ }
+
+ case TAG_SUBTITLE_DOWNLOAD_LAST:
+ {
+ en50221_app_mmi_subtitle_download_callback cb =
+ mmi->subtitledownloadcallback;
+ void *cb_arg = mmi->subtitledownloadcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ cbstatus =
+ cb(cb_arg, slot_id, session_number, outdata, outdata_length);
+ }
+ break;
+ }
+ }
+
+ // free the data returned by the defragment call if asked to
+ if (dfstatus == 2) {
+ free(outdata);
+ }
+ // done
+ return cbstatus;
+}
+
+static int en50221_app_mmi_parse_scene_end_mark(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t flags = data[1];
+
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_scene_end_mark_callback cb =
+ mmi->sceneendmarkcallback;
+ void *cb_arg = mmi->sceneendmarkcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ (flags & 0x80) ? 1 : 0,
+ (flags & 0x40) ? 1 : 0,
+ (flags & 0x20) ? 1 : 0, flags & 0x0f);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_scene_control(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t flags = data[1];
+
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_scene_control_callback cb = mmi->scenecontrolcallback;
+ void *cb_arg = mmi->scenecontrolcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number,
+ (flags & 0x80) ? 1 : 0,
+ (flags & 0x40) ? 1 : 0, flags & 0x0f);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_parse_flush_download(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ // validate data
+ if (data_length != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 0) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ // tell the app
+ pthread_mutex_lock(&mmi->lock);
+ en50221_app_mmi_flush_download_callback cb = mmi->flushdownloadcallback;
+ void *cb_arg = mmi->flushdownloadcallback_arg;
+ pthread_mutex_unlock(&mmi->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number);
+ }
+ return 0;
+}
+
+static int en50221_app_mmi_defragment(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint32_t tag_id,
+ int more_last,
+ uint8_t * indata,
+ uint32_t indata_length,
+ uint8_t ** outdata,
+ uint32_t * outdata_length)
+{
+ struct en50221_app_mmi_session *cur_s = mmi->sessions;
+ while (cur_s) {
+ if (cur_s->session_number == session_number)
+ break;
+ cur_s = cur_s->next;
+ }
+
+ // more data is still to come
+ if (!more_last) {
+ // if there was no previous session, create one
+ if (cur_s == NULL) {
+ cur_s = malloc(sizeof(struct en50221_app_mmi_session));
+ if (cur_s == NULL) {
+ print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n");
+ return -1;
+ }
+ cur_s->session_number = session_number;
+ cur_s->menu_block_chain = NULL;
+ cur_s->menu_block_length = 0;
+ cur_s->list_block_chain = NULL;
+ cur_s->list_block_length = 0;
+ cur_s->subtitlesegment_block_chain = NULL;
+ cur_s->subtitlesegment_block_length = 0;
+ cur_s->subtitledownload_block_chain = NULL;
+ cur_s->subtitledownload_block_length = 0;
+ cur_s->next = mmi->sessions;
+ mmi->sessions = cur_s;
+ }
+ // find the block/block_length to use
+ uint8_t **block_chain;
+ uint32_t *block_length;
+ switch (tag_id) {
+ case TAG_MENU_LAST:
+ case TAG_MENU_MORE:
+ block_chain = &cur_s->menu_block_chain;
+ block_length = &cur_s->menu_block_length;
+ break;
+ case TAG_LIST_LAST:
+ case TAG_LIST_MORE:
+ block_chain = &cur_s->list_block_chain;
+ block_length = &cur_s->list_block_length;
+ break;
+ case TAG_SUBTITLE_SEGMENT_LAST:
+ case TAG_SUBTITLE_SEGMENT_MORE:
+ block_chain = &cur_s->subtitlesegment_block_chain;
+ block_length = &cur_s->subtitlesegment_block_length;
+ break;
+ case TAG_SUBTITLE_DOWNLOAD_LAST:
+ case TAG_SUBTITLE_DOWNLOAD_MORE:
+ block_chain = &cur_s->subtitledownload_block_chain;
+ block_length = &cur_s->subtitledownload_block_length;
+ break;
+ default:
+ return -1;
+ }
+
+ // append the data
+ uint8_t *new_data =
+ realloc(*block_chain, *block_length + indata_length);
+ if (new_data == NULL) {
+ print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n");
+ return -1;
+ }
+ memcpy(new_data + *block_length, indata, indata_length);
+ *block_chain = new_data;
+ *block_length += indata_length;
+
+ // success, but block not complete yet
+ return 0;
+ }
+ // we hit the last of a possible chain of fragments
+ if (cur_s != NULL) {
+ // find the block/block_length to use
+ uint8_t **block_chain;
+ uint32_t *block_length;
+ switch (tag_id) {
+ case TAG_MENU_LAST:
+ case TAG_MENU_MORE:
+ block_chain = &cur_s->menu_block_chain;
+ block_length = &cur_s->menu_block_length;
+ break;
+ case TAG_LIST_LAST:
+ case TAG_LIST_MORE:
+ block_chain = &cur_s->list_block_chain;
+ block_length = &cur_s->list_block_length;
+ break;
+ case TAG_SUBTITLE_SEGMENT_LAST:
+ case TAG_SUBTITLE_SEGMENT_MORE:
+ block_chain = &cur_s->subtitlesegment_block_chain;
+ block_length = &cur_s->subtitlesegment_block_length;
+ break;
+ case TAG_SUBTITLE_DOWNLOAD_LAST:
+ case TAG_SUBTITLE_DOWNLOAD_MORE:
+ block_chain = &cur_s->subtitledownload_block_chain;
+ block_length = &cur_s->subtitledownload_block_length;
+ break;
+ default:
+ return -1;
+ }
+
+ // we have a preceding fragment - need to append
+ uint8_t *new_data =
+ realloc(*block_chain, *block_length + indata_length);
+ if (new_data == NULL) {
+ print(LOG_LEVEL, ERROR, 1, "Ran out of memory\n");
+ return -1;
+ }
+ memcpy(new_data + *block_length, indata, indata_length);
+ *outdata_length = *block_length + indata_length;
+ *outdata = new_data;
+ *block_chain = NULL;
+ *block_length = 0;
+
+ // success, and indicate to free the block when done
+ return 2;
+ }
+ // success, but indicate it is not to be freed
+ *outdata_length = indata_length;
+ *outdata = indata;
+ return 1;
+}
+
+static int en50221_app_mmi_defragment_text(uint8_t * data,
+ uint32_t data_length,
+ uint8_t ** outdata,
+ uint32_t * outdata_length,
+ uint32_t * outconsumed)
+{
+ uint8_t *text = NULL;
+ uint32_t text_length = 0;
+ uint32_t consumed = 0;
+
+ while (1) {
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Short data\n");
+ if (text)
+ free(text);
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+ data += 3;
+ data_length -= 3;
+ consumed += 3;
+
+ // get the length of the data and adjust
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len =
+ asn_1_decode(&asn_data_length, data,
+ data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ if (text)
+ free(text);
+ return -1;
+ }
+ data += length_field_len;
+ data_length -= length_field_len;
+ consumed += length_field_len;
+
+ // deal with the tags
+ if (tag == TAG_TEXT_LAST) {
+ if (text == NULL) {
+ *outdata = data;
+ *outdata_length = asn_data_length;
+ *outconsumed = consumed + asn_data_length;
+ return 1;
+ } else {
+ // append the data
+ uint8_t *new_text = realloc(text,
+ text_length + asn_data_length);
+ if (new_text == NULL) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Ran out of memory\n");
+ if (text)
+ free(text);
+ return -1;
+ }
+ memcpy(new_text + text_length, data,
+ asn_data_length);
+ *outdata = new_text;
+ *outdata_length =
+ text_length + asn_data_length;
+ *outconsumed = consumed + asn_data_length;
+ return 2;
+ }
+
+ } else if (tag == TAG_TEXT_MORE) {
+ // append the data
+ uint8_t *new_text =
+ realloc(text, text_length + asn_data_length);
+ if (new_text == NULL) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Ran out of memory\n");
+ if (text)
+ free(text);
+ return -1;
+ }
+ memcpy(new_text + text_length, data,
+ asn_data_length);
+ text = new_text;
+ text_length += asn_data_length;
+
+ // consume the data
+ data += asn_data_length;
+ data_length -= asn_data_length;
+ consumed += asn_data_length;
+ } else {
+ // unknown tag
+ print(LOG_LEVEL, ERROR, 1,
+ "Unknown MMI text tag\n");
+ if (text)
+ free(text);
+ return -1;
+ }
+ }
+}
diff --git a/lib/libdvben50221/en50221_app_mmi.h b/lib/libdvben50221/en50221_app_mmi.h
new file mode 100644
index 0000000..5c5b727
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_mmi.h
@@ -0,0 +1,618 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_mmi_H__
+#define __EN50221_APPLICATION_mmi_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_MMI_RESOURCEID MKRID(64,1,1)
+
+#define MMI_CLOSE_MMI_CMD_ID_IMMEDIATE 0x00
+#define MMI_CLOSE_MMI_CMD_ID_DELAY 0x01
+
+#define MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE 0x01
+#define MMI_DISPLAY_CONTROL_CMD_ID_GET_DISPLAY_CHAR_TABLES 0x02
+#define MMI_DISPLAY_CONTROL_CMD_ID_GET_INPUT_CHAR_TABLES 0x03
+#define MMI_DISPLAY_CONTROL_CMD_ID_GET_OVERLAY_GFX_CHARACTERISTICS 0x04
+#define MMI_DISPLAY_CONTROL_CMD_ID_GET_FULLSCREEN_GFX_CHARACTERISTICS 0x05
+
+#define MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK 0x01
+#define MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES 0x02
+#define MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES 0x03
+#define MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS 0x04
+#define MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS 0x05
+#define MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID 0xF0
+#define MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE 0xF1
+#define MMI_DISPLAY_REPLY_ID_UNKNOWN_CHAR_TABLE 0xF2
+
+#define MMI_MODE_HIGH_LEVEL 0x01
+#define MMI_MODE_LOW_LEVEL_OVERLAY_GFX 0x02
+#define MMI_MODE_LOW_LEVEL_FULLSCREEN_GFX 0x03
+
+#define MMI_KEYPAD_CONTROL_CMD_ID_INTERCEPT_ALL 0x01
+#define MMI_KEYPAD_CONTROL_CMD_ID_IGNORE_ALL 0x02
+#define MMI_KEYPAD_CONTROL_CMD_ID_INTERCEPT_SELECTED 0x03
+#define MMI_KEYPAD_CONTROL_CMD_ID_IGNORE_SELECTED 0x04
+#define MMI_KEYPAD_CONTROL_CMD_ID_REJECT_KEYPRESS 0x05
+
+#define MMI_GFX_VIDEO_RELATION_NONE 0x00
+#define MMI_GFX_VIDEO_RELATION_MATCHES_EXACTLY 0x07
+
+#define MMI_DISPLAY_MESSAGE_ID_OK 0x00
+#define MMI_DISPLAY_MESSAGE_ID_ERROR 0x01
+#define MMI_DISPLAY_MESSAGE_ID_OUT_OF_MEMORY 0x02
+#define MMI_DISPLAY_MESSAGE_ID_SUBTITLE_SYNTAX_ERROR 0x03
+#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_REGION 0x04
+#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_CLUT 0x05
+#define MMI_DISPLAY_MESSAGE_ID_UNDEFINED_OBJECT 0x06
+#define MMI_DISPLAY_MESSAGE_ID_INCOMPATABLE_OBJECT 0x07
+#define MMI_DISPLAY_MESSAGE_ID_UNKNOWN_CHARACTER 0x08
+#define MMI_DISPLAY_MESSAGE_ID_DISPLAY_CHANGED 0x09
+
+#define MMI_DOWNLOAD_REPLY_ID_OK 0x00
+#define MMI_DOWNLOAD_REPLY_ID_NOT_OBJECT_SEGMENT 0x01
+#define MMI_DOWNLOAD_REPLY_ID_OUT_OF_MEMORY 0x02
+
+#define MMI_ANSW_ID_CANCEL 0x00
+#define MMI_ANSW_ID_ANSWER 0x01
+
+/**
+ * A pixel depth as supplied with display_reply details
+ */
+struct en50221_app_mmi_pixel_depth {
+ uint8_t display_depth;
+ uint8_t pixels_per_byte;
+ uint8_t region_overhead;
+};
+
+/**
+ * Details returned with a display_reply
+ */
+struct en50221_app_mmi_display_reply_details {
+ union {
+ struct {
+ uint16_t width;
+ uint16_t height;
+ uint8_t aspect_ratio;
+ uint8_t gfx_relation_to_video; /* one of MMI_GFX_VIDEO_RELATION_* */
+ uint8_t multiple_depths;
+ uint16_t display_bytes;
+ uint8_t composition_buffer_bytes;
+ uint8_t object_cache_bytes;
+ uint8_t num_pixel_depths;
+ struct en50221_app_mmi_pixel_depth *pixel_depths;
+ } gfx; /* MMI_DISPLAY_REPLY_ID_LIST_OVERLAY_GFX_CHARACTERISTICS or
+ MMI_DISPLAY_REPLY_ID_LIST_FULLSCREEN_GFX_CHARACTERISTICS */
+
+ struct {
+ uint32_t table_length;
+ uint8_t *table;
+ } char_table; /* MMI_DISPLAY_REPLY_ID_LIST_DISPLAY_CHAR_TABLES or
+ MMI_DISPLAY_REPLY_ID_LIST_INPUT_CHAR_TABLES */
+
+ struct {
+ uint8_t mmi_mode; /* one of the MMI_MODE_* values */
+ } mode_ack; /* for MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK */
+ } u;
+};
+
+/**
+ * Pointer to a text string.
+ */
+struct en50221_app_mmi_text {
+ uint8_t *text;
+ uint32_t text_length;
+};
+
+/**
+ * Type definition for close - called when we receive an mmi_close from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param cmd_id One of the MMI_CLOSE_MMI_CMD_ID_* values.
+ * @param delay Delay supplied with MMI_CLOSE_MMI_CMD_ID_DELAY.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_close_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t cmd_id,
+ uint8_t delay);
+
+/**
+ * Type definition for display_control callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param cmd_id One of the MMI_DISPLAY_CONTROL_CMD_ID_* values.
+ * @param delay One of the MMI_MODE_* values.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_display_control_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t cmd_id,
+ uint8_t mmi_mode);
+
+/**
+ * Type definition for keypad_control callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param cmd_id One of the MMI_KEYPAD_CONTROL_CMD_ID_* values.
+ * @param key_codes Pointer to the key codes.
+ * @param key_codes_count Number of key codes.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_keypad_control_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t cmd_id,
+ uint8_t *key_codes,
+ uint32_t key_codes_count);
+
+/**
+ * Type definition for subtitle_segment callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param segment Pointer to the segment data.
+ * @param segment_size Size of segment data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_subtitle_segment_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *segment,
+ uint32_t segment_size);
+
+/**
+ * Type definition for scene_end_mark callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param decoder_continue_flag
+ * @param scene_reveal_flag
+ * @param send_scene_done
+ * @param scene_tag
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_scene_end_mark_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t decoder_continue_flag,
+ uint8_t scene_reveal_flag,
+ uint8_t send_scene_done,
+ uint8_t scene_tag);
+
+/**
+ * Type definition for scene_control callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param decoder_continue_flag
+ * @param scene_reveal_flag
+ * @param scene_tag
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_scene_control_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t decoder_continue_flag,
+ uint8_t scene_reveal_flag,
+ uint8_t scene_tag);
+
+/**
+ * Type definition for subtitle_download callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param segment Pointer to the segment data.
+ * @param segment_size Size of segment data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_subtitle_download_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *segment,
+ uint32_t segment_size);
+
+/**
+ * Type definition for flush_download callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_flush_download_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number);
+
+/**
+ * Type definition for enq callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param blind_answer 1=>Obscure text input in some manner,
+ * @param expected_answer_length Expected max number of characters to be returned.
+ * @param text Pointer to the text data.
+ * @param text_size Size of text data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_enq_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t blind_answer,
+ uint8_t expected_answer_length,
+ uint8_t * text,
+ uint32_t text_size);
+
+/**
+ * Type definition for menu callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param title Title text.
+ * @param sub_title Sub-Title text.
+ * @param bottom Bottom text.
+ * @param item_count Number of text elements in items.
+ * @param items Pointer to array of en50221_app_mmi_text structures which are standard menu choices,
+ * @param item_raw_length Length of item raw data.
+ * @param items_raw If nonstandard items were supplied, pointer to their data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_menu_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ struct en50221_app_mmi_text *title,
+ struct en50221_app_mmi_text *sub_title,
+ struct en50221_app_mmi_text *bottom,
+ uint32_t item_count,
+ struct en50221_app_mmi_text *items,
+ uint32_t item_raw_length,
+ uint8_t *items_raw);
+
+/**
+ * Type definition for list callback.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param title Title text.
+ * @param sub_title Sub-Title text.
+ * @param bottom Bottom text.
+ * @param item_count Number of text elements in items.
+ * @param items Pointer to array of en50221_app_mmi_text structures which are standard menu choices,
+ * @param item_raw_length Length of item raw data.
+ * @param items_raw If nonstandard items were supplied, pointer to their data.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_mmi_list_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ struct en50221_app_mmi_text *title,
+ struct en50221_app_mmi_text *sub_title,
+ struct en50221_app_mmi_text *bottom,
+ uint32_t item_count,
+ struct en50221_app_mmi_text *items,
+ uint32_t item_raw_length,
+ uint8_t *items_raw);
+
+/**
+ * Opaque type representing a mmi resource.
+ */
+struct en50221_app_mmi;
+
+/**
+ * Create an instance of the mmi resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_mmi *en50221_app_mmi_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the mmi resource.
+ *
+ * @param mmi Instance to destroy.
+ */
+extern void en50221_app_mmi_destroy(struct en50221_app_mmi *mmi);
+
+/**
+ * Informs the mmi object that a session to it has been closed - cleans up internal state.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number The session concerned.
+ */
+extern void en50221_app_mmi_clear_session(struct en50221_app_mmi *mmi,
+ uint16_t session_number);
+
+/**
+ * Register the callback for when we receive an mmi_close request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_close_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_close_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a display control request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_display_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_display_control_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a keypad control request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_keypad_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_keypad_control_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a subtitle segment request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_subtitle_segment_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_segment_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a scene end mark request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_scene_end_mark_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_end_mark_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a scene control request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_scene_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_control_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a subtitle download request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_subtitle_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_download_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a flush download request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_flush_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_flush_download_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive an enq request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_enq_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_enq_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a menu request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_menu_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_menu_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a list request.
+ *
+ * @param mmi mmi resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_mmi_register_list_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_list_callback callback,
+ void *arg);
+
+/**
+ * Send an mmi_close to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param cmd_id One of the MMI_CLOSE_MMI_CMD_ID_* values.
+ * @param delay Delay to use if MMI_CLOSE_MMI_CMD_ID_DELAY specified.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_close(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t cmd_id, uint8_t delay);
+
+/**
+ * Send a display_reply to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param reply_id One of the MMI_DISPLAY_REPLY_ID_* values.
+ * @param details The details of the reply - can be NULL if the chosen reply_id does not need it.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_display_reply(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t reply_id,
+ struct en50221_app_mmi_display_reply_details *details);
+
+/**
+ * Send a keypress to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param keycode The keycode.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_keypress(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t keycode);
+
+/**
+ * Send a display message to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param display_message_id One of the MMI_DISPLAY_MESSAGE_ID_* values.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_display_message(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t display_message_id);
+
+/**
+ * Send a scene done message to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param decoder_continue Copy of flag in scene_end_mark.
+ * @param scene_reveal Copy of flag in scene_end_mark.
+ * @param scene_tag Scene tag this responds to.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_scene_done(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t decoder_continue,
+ uint8_t scene_reveal,
+ uint8_t scene_tag);
+
+/**
+ * Send a download reply to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param object_id Object id.
+ * @param download_reply_id One of the MMI_DOWNLOAD_REPLY_ID_* values.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_download_reply(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint16_t object_id,
+ uint8_t download_reply_id);
+
+/**
+ * Send an answ to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param answ_id One of the MMI_ANSW_ID_* values.
+ * @param text The text if MMI_ANSW_ID_ANSWER.
+ * @param text_count Length of text.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_answ(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t answ_id,
+ uint8_t * text,
+ uint32_t text_count);
+
+/**
+ * Send a menu answ to the cam.
+ *
+ * @param mmi mmi resource instance.
+ * @param session_number Session number to send it on.
+ * @param choice_ref Option chosen by user (0=>canceled).
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_menu_answ(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t choice_ref);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param mmi mmi instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_mmi_message(struct en50221_app_mmi *mmi,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_rm.c b/lib/libdvben50221/en50221_app_rm.c
new file mode 100644
index 0000000..7a5bc2f
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_rm.c
@@ -0,0 +1,307 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include <libucsi/endianops.h>
+#include "en50221_app_rm.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_rm {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_rm_enq_callback enqcallback;
+ void *enqcallback_arg;
+
+ en50221_app_rm_reply_callback replycallback;
+ void *replycallback_arg;
+
+ en50221_app_rm_changed_callback changedcallback;
+ void *changedcallback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_rm_parse_profile_enq(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_rm_parse_profile_reply(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_app_rm_parse_profile_change(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+struct en50221_app_rm *en50221_app_rm_create(struct
+ en50221_app_send_functions
+ *funcs)
+{
+ struct en50221_app_rm *rm = NULL;
+
+ // create structure and set it up
+ rm = malloc(sizeof(struct en50221_app_rm));
+ if (rm == NULL) {
+ return NULL;
+ }
+ rm->funcs = funcs;
+ rm->enqcallback = NULL;
+ rm->replycallback = NULL;
+ rm->changedcallback = NULL;
+
+ pthread_mutex_init(&rm->lock, NULL);
+
+ // done
+ return rm;
+}
+
+void en50221_app_rm_destroy(struct en50221_app_rm *rm)
+{
+ pthread_mutex_destroy(&rm->lock);
+ free(rm);
+}
+
+void en50221_app_rm_register_enq_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_enq_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&rm->lock);
+ rm->enqcallback = callback;
+ rm->enqcallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
+}
+
+void en50221_app_rm_register_reply_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_reply_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&rm->lock);
+ rm->replycallback = callback;
+ rm->replycallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
+}
+
+void en50221_app_rm_register_changed_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_changed_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&rm->lock);
+ rm->changedcallback = callback;
+ rm->changedcallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
+}
+
+int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number)
+{
+ uint8_t buf[4];
+
+ // set up the tag
+ buf[0] = (TAG_PROFILE_ENQUIRY >> 16) & 0xFF;
+ buf[1] = (TAG_PROFILE_ENQUIRY >> 8) & 0xFF;
+ buf[2] = TAG_PROFILE_ENQUIRY & 0xFF;
+ buf[3] = 0;
+
+ // create the data and send it
+ return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4);
+}
+
+int en50221_app_rm_reply(struct en50221_app_rm *rm,
+ uint16_t session_number,
+ uint32_t resource_id_count,
+ uint32_t * resource_ids)
+{
+ uint8_t buf[10];
+
+ // set up the tag
+ buf[0] = (TAG_PROFILE >> 16) & 0xFF;
+ buf[1] = (TAG_PROFILE >> 8) & 0xFF;
+ buf[2] = TAG_PROFILE & 0xFF;
+
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(resource_id_count * 4, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ // copy the data and byteswap it
+ uint32_t *copy_resource_ids = alloca(4 * resource_id_count);
+ if (copy_resource_ids == NULL) {
+ return -1;
+ }
+ uint8_t *data = (uint8_t *) copy_resource_ids;
+ memcpy(data, resource_ids, resource_id_count * 4);
+ uint32_t i;
+ for (i = 0; i < resource_id_count; i++) {
+ bswap32(data);
+ data += 4;
+ }
+
+ // build the iovecs
+ struct iovec iov[2];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len;
+ iov[1].iov_base = (uint8_t *) copy_resource_ids;
+ iov[1].iov_len = resource_id_count * 4;
+
+ // create the data and send it
+ return rm->funcs->send_datav(rm->funcs->arg, session_number, iov, 2);
+}
+
+int en50221_app_rm_changed(struct en50221_app_rm *rm,
+ uint16_t session_number)
+{
+ uint8_t buf[4];
+
+ // set up the tag
+ buf[0] = (TAG_PROFILE_CHANGE >> 16) & 0xFF;
+ buf[1] = (TAG_PROFILE_CHANGE >> 8) & 0xFF;
+ buf[2] = TAG_PROFILE_CHANGE & 0xFF;
+ buf[3] = 0;
+
+ // create the data and send it
+ return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4);
+}
+
+int en50221_app_rm_message(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ // dispatch it
+ switch (tag) {
+ case TAG_PROFILE_ENQUIRY:
+ return en50221_app_rm_parse_profile_enq(rm, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_PROFILE:
+ return en50221_app_rm_parse_profile_reply(rm, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_PROFILE_CHANGE:
+ return en50221_app_rm_parse_profile_change(rm, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+static int en50221_app_rm_parse_profile_enq(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ (void) data;
+ (void) data_length;
+
+ pthread_mutex_lock(&rm->lock);
+ en50221_app_rm_enq_callback cb = rm->enqcallback;
+ void *cb_arg = rm->enqcallback_arg;
+ pthread_mutex_unlock(&rm->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number);
+ }
+ return 0;
+}
+
+static int en50221_app_rm_parse_profile_reply(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t resources_count = asn_data_length / 4;
+ uint32_t *resource_ids = (uint32_t *) (data + length_field_len);
+ data += length_field_len;
+
+ // byteswap it
+ uint32_t i;
+ for (i = 0; i < resources_count; i++) {
+ bswap32(data);
+ data += 4;
+ }
+
+ // inform observer
+ pthread_mutex_lock(&rm->lock);
+ en50221_app_rm_reply_callback cb = rm->replycallback;
+ void *cb_arg = rm->replycallback_arg;
+ pthread_mutex_unlock(&rm->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, resources_count, resource_ids);
+ }
+ return 0;
+}
+
+static int en50221_app_rm_parse_profile_change(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ (void) data;
+ (void) data_length;
+
+ pthread_mutex_lock(&rm->lock);
+ en50221_app_rm_changed_callback cb = rm->changedcallback;
+ void *cb_arg = rm->changedcallback_arg;
+ pthread_mutex_unlock(&rm->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_rm.h b/lib/libdvben50221/en50221_app_rm.h
new file mode 100644
index 0000000..ec97372
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_rm.h
@@ -0,0 +1,187 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_RM_H__
+#define __EN50221_APPLICATION_RM_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_RM_RESOURCEID MKRID(1,1,1)
+
+/**
+ * Type definition for profile_enq callback function - called when we receive
+ * a profile_enq from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_rm_enq_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number);
+
+/**
+ * Type definition for profile_reply callback function - called when we receive
+ * a profile_reply from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id_count Number of resource_ids.
+ * @param resource_ids The resource ids themselves.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_rm_reply_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id_count,
+ uint32_t *resource_ids);
+/**
+ * Type definition for profile_changed callback function - called when we receive
+ * a profile_changed from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_rm_changed_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number);
+
+
+
+/**
+ * Opaque type representing a resource manager.
+ */
+struct en50221_app_rm;
+
+/**
+ * Create an instance of the resource manager.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_rm *en50221_app_rm_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the resource manager.
+ *
+ * @param rm Instance to destroy.
+ */
+extern void en50221_app_rm_destroy(struct en50221_app_rm *rm);
+
+/**
+ * Register the callback for when we receive a profile_enq from a CAM.
+ *
+ * @param rm Resource manager instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_rm_register_enq_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_enq_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a profile_reply from a CAM.
+ *
+ * @param rm Resource manager instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_rm_register_reply_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_reply_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive a profile_changed from a CAM.
+ *
+ * @param rm Resource manager instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_rm_register_changed_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_changed_callback callback,
+ void *arg);
+
+/**
+ * Send a profile_enq to a CAM.
+ *
+ * @param rm Resource manager resource instance.
+ * @param session_number Session number to send it on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number);
+
+/**
+ * Send a profile_reply to a CAM.
+ *
+ * @param rm Resource manager resource instance.
+ * @param session_number Session number to send it on.
+ * @param resource_id_count Number of resource ids.
+ * @param resource_ids The resource IDs themselves
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_rm_reply(struct en50221_app_rm *rm,
+ uint16_t session_number,
+ uint32_t resource_id_count,
+ uint32_t * resource_ids);
+
+/**
+ * Send a profile_changed to a CAM.
+ *
+ * @param rm Resource manager resource instance.
+ * @param session_number Session number to send it on.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_rm_changed(struct en50221_app_rm *rm, uint16_t session_number);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param rm rm instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_rm_message(struct en50221_app_rm *rm,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_smartcard.c b/lib/libdvben50221/en50221_app_smartcard.c
new file mode 100644
index 0000000..763c6c4
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_smartcard.c
@@ -0,0 +1,296 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_smartcard.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_smartcard {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_smartcard_command_callback command_callback;
+ void *command_callback_arg;
+
+ en50221_app_smartcard_send_callback send_callback;
+ void *send_callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+static int en50221_app_smartcard_parse_send(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+struct en50221_app_smartcard *en50221_app_smartcard_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_smartcard *smartcard = NULL;
+
+ // create structure and set it up
+ smartcard = malloc(sizeof(struct en50221_app_smartcard));
+ if (smartcard == NULL) {
+ return NULL;
+ }
+ smartcard->funcs = funcs;
+ smartcard->command_callback = NULL;
+ smartcard->send_callback = NULL;
+
+ pthread_mutex_init(&smartcard->lock, NULL);
+
+ // done
+ return smartcard;
+}
+
+void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard)
+{
+ pthread_mutex_destroy(&smartcard->lock);
+ free(smartcard);
+}
+
+void en50221_app_smartcard_register_command_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_command_callback callback, void *arg)
+{
+ pthread_mutex_lock(&smartcard->lock);
+ smartcard->command_callback = callback;
+ smartcard->command_callback_arg = arg;
+ pthread_mutex_unlock(&smartcard->lock);
+}
+
+void en50221_app_smartcard_register_send_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_send_callback callback, void *arg)
+{
+ pthread_mutex_lock(&smartcard->lock);
+ smartcard->send_callback = callback;
+ smartcard->send_callback_arg = arg;
+ pthread_mutex_unlock(&smartcard->lock);
+}
+
+int en50221_app_smartcard_command_reply(struct en50221_app_smartcard *smartcard,
+ uint16_t session_number,
+ uint8_t reply_id, uint8_t status,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ uint8_t hdr[10];
+ struct iovec iovec[2];
+ int iov_count = 0;
+
+ // the tag
+ hdr[0] = (TAG_SMARTCARD_REPLY >> 16) & 0xFF;
+ hdr[1] = (TAG_SMARTCARD_REPLY >> 8) & 0xFF;
+ hdr[2] = TAG_SMARTCARD_REPLY & 0xFF;
+
+ // the rest of the data
+ if (reply_id == SMARTCARD_REPLY_ID_ANSW_TO_RESET) {
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(data_length + 2, data + 3, 3)) < 0) {
+ return -1;
+ }
+ // the rest of the header
+ hdr[3 + length_field_len] = reply_id;
+ hdr[3 + length_field_len + 1] = status;
+ iovec[0].iov_base = hdr;
+ iovec[0].iov_len = 3 + length_field_len + 2;
+
+ // the data
+ iovec[1].iov_base = data;
+ iovec[1].iov_len = data_length;
+ iov_count = 2;
+ } else {
+ hdr[3] = 2;
+ hdr[4] = reply_id;
+ hdr[5] = status;
+ iovec[0].iov_base = data;
+ iovec[0].iov_len = 6;
+ iov_count = 1;
+ }
+
+ return smartcard->funcs->send_datav(smartcard->funcs->arg, session_number, iovec, iov_count);
+}
+
+int en50221_app_smartcard_receive(struct en50221_app_smartcard *smartcard,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length,
+ uint8_t SW1, uint8_t SW2)
+{
+ uint8_t buf[10];
+ uint8_t trailer[10];
+
+ // set up the tag
+ buf[0] = (TAG_SMARTCARD_RCV >> 16) & 0xFF;
+ buf[1] = (TAG_SMARTCARD_RCV >> 8) & 0xFF;
+ buf[2] = TAG_SMARTCARD_RCV & 0xFF;
+
+ // encode the length field
+ int length_field_len;
+ if ((length_field_len = asn_1_encode(data_length + 2, buf + 3, 3)) < 0) {
+ return -1;
+ }
+ // set up the trailer
+ trailer[0] = SW1;
+ trailer[1] = SW2;
+
+ // build the iovecs
+ struct iovec iov[3];
+ iov[0].iov_base = buf;
+ iov[0].iov_len = 3 + length_field_len;
+ iov[1].iov_base = data;
+ iov[1].iov_len = data_length;
+ iov[2].iov_base = trailer;
+ iov[2].iov_len = 2;
+
+ // create the data and send it
+ return smartcard->funcs->send_datav(smartcard->funcs->arg,
+ session_number, iov, 3);
+}
+
+int en50221_app_smartcard_message(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t *data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_SMARTCARD_COMMAND:
+ return en50221_app_smartcard_parse_command(smartcard,
+ slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ case TAG_SMARTCARD_SEND:
+ return en50221_app_smartcard_parse_send(smartcard, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+
+
+
+
+
+static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ if (data_length != 2) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (data[0] != 1) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t command_id = data[1];
+
+ // tell the app
+ pthread_mutex_lock(&smartcard->lock);
+ en50221_app_smartcard_command_callback cb = smartcard->command_callback;
+ void *cb_arg = smartcard->command_callback_arg;
+ pthread_mutex_unlock(&smartcard->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, command_id);
+ }
+ return 0;
+}
+
+static int en50221_app_smartcard_parse_send(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+ // check it
+ if (asn_data_length < 8) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ data += length_field_len;
+
+ // parse
+ uint8_t CLA = data[0];
+ uint8_t INS = data[1];
+ uint8_t P1 = data[2];
+ uint8_t P2 = data[3];
+ uint16_t length_in = (data[4] << 8) | data[5];
+ uint8_t *data_in = data + 6;
+
+ // validate the length
+ if ((length_in + 8) != asn_data_length) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint16_t length_out =
+ (data[6 + length_in] << 8) | data[6 + length_in + 1];
+
+ // tell the app
+ pthread_mutex_lock(&smartcard->lock);
+ en50221_app_smartcard_send_callback cb = smartcard->send_callback;
+ void *cb_arg = smartcard->send_callback_arg;
+ pthread_mutex_unlock(&smartcard->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, CLA, INS, P1,
+ P2, data_in, length_in, length_out);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_smartcard.h b/lib/libdvben50221/en50221_app_smartcard.h
new file mode 100644
index 0000000..bbad4a9
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_smartcard.h
@@ -0,0 +1,200 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_smartcard_H__
+#define __EN50221_APPLICATION_smartcard_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define SMARTCARD_COMMAND_ID_CONNECT 0x01
+#define SMARTCARD_COMMAND_ID_DISCONNECT 0x02
+#define SMARTCARD_COMMAND_ID_POWERON_CARD 0x03
+#define SMARTCARD_COMMAND_ID_POWEROFF_CARD 0x04
+#define SMARTCARD_COMMAND_ID_RESET_CARD 0x05
+#define SMARTCARD_COMMAND_ID_RESET_STATUS 0x06
+#define SMARTCARD_COMMAND_ID_READ_ANSW_TO_RESET 0x07
+
+#define SMARTCARD_REPLY_ID_CONNECTED 0x01
+#define SMARTCARD_REPLY_ID_FREE 0x02
+#define SMARTCARD_REPLY_ID_BUSY 0x03
+#define SMARTCARD_REPLY_ID_ANSW_TO_RESET 0x04
+#define SMARTCARD_REPLY_ID_NO_ANSW_TO_RESET 0x05
+
+#define SMARTCARD_STATUS_CARD_INSERTED 0x01
+#define SMARTCARD_STATUS_CARD_REMOVED 0x02
+#define SMARTCARD_STATUS_CARD_IN_PLACE_POWEROFF 0x03
+#define SMARTCARD_STATUS_CARD_IN_PLACE_POWERON 0x04
+#define SMARTCARD_STATUS_CARD_NO_CARD 0x05
+#define SMARTCARD_STATUS_CARD_UNRESPONSIVE_CARD 0x06
+#define SMARTCARD_STATUS_CARD_REFUSED_CARD 0x07
+
+#define EN50221_APP_SMARTCARD_RESOURCEID(DEVICE_NUMBER) MKRID(112, ((DEVICE_NUMBER)& 0x0f), 1)
+
+
+
+/**
+ * Type definition for command - called when we receive a command.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param command_id One of the SMARTCARD_COMMAND_ID_* values
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_smartcard_command_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t command_id);
+
+/**
+ * Type definition for command - called when we receive a send command.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param CLA CLA value.
+ * @param INS INS value.
+ * @param P1 P1 value.
+ * @param P2 P2 value.
+ * @param in Data to send to the card
+ * @param in_length Number of bytes to send.
+ * @param out_length Number of bytes expected.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_smartcard_send_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t CLA,
+ uint8_t INS,
+ uint8_t P1,
+ uint8_t P2,
+ uint8_t *in,
+ uint32_t in_length,
+ uint32_t out_length);
+
+/**
+ * Opaque type representing a smartcard resource.
+ */
+struct en50221_app_smartcard;
+
+/**
+ * Create an instance of the smartcard resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_smartcard *
+ en50221_app_smartcard_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the smartcard resource.
+ *
+ * @param smartcard Instance to destroy.
+ */
+extern void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard);
+
+/**
+ * Register the callback for when we receive a comms command.
+ *
+ * @param smartcard smartcard resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_smartcard_register_command_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_command_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for when we receive data to send.
+ *
+ * @param smartcard smartcard resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_smartcard_register_send_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_send_callback callback,
+ void *arg);
+
+/**
+ * Send a command response to the CAM.
+ *
+ * @param smartcard smartcard resource instance.
+ * @param session_number Session number to send it on.
+ * @param reply_id One of the SMARTCARD_REPLY_ID_* values.
+ * @param status One of the SMARTCARD_STATUS_* values.
+ * @param data Data to send when it is a SMARTCARD_REPLY_ID_ANSW_TO_RESET.
+ * @param data_length Length of data to send.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_smartcard_command_reply(struct en50221_app_smartcard *smartcard,
+ uint16_t session_number,
+ uint8_t reply_id,
+ uint8_t status,
+ uint8_t * data,
+ uint32_t data_length);
+
+/**
+ * Send data received from a smartcart to the CAM.
+ *
+ * @param smartcard smartcard resource instance.
+ * @param session_number Session number to send it on.
+ * @param data Data to send when it is a SMARTCARD_REPLY_ID_ANSW_TO_RESET.
+ * @param data_length Length of data to send.
+ * @param SW1 SW1 value.
+ * @param SW2 SW2 value.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_smartcard_receive(struct en50221_app_smartcard *smartcard,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t SW1, uint8_t SW2);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param smartcard smartcard instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_smartcard_message(struct en50221_app_smartcard *smartcard,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_tags.h b/lib/libdvben50221/en50221_app_tags.h
new file mode 100644
index 0000000..0f5c2fc
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_tags.h
@@ -0,0 +1,104 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APP_TAGS_H__
+#define __EN50221_APP_TAGS_H__
+
+/* Resource Manager */
+#define TAG_PROFILE_ENQUIRY 0x9f8010
+#define TAG_PROFILE 0x9f8011
+#define TAG_PROFILE_CHANGE 0x9f8012
+
+/* Application Info */
+#define TAG_APP_INFO_ENQUIRY 0x9f8020
+#define TAG_APP_INFO 0x9f8021
+#define TAG_ENTER_MENU 0x9f8022
+
+/* CA Support */
+#define TAG_CA_INFO_ENQUIRY 0x9f8030
+#define TAG_CA_INFO 0x9f8031
+#define TAG_CA_PMT 0x9f8032
+#define TAG_CA_PMT_REPLY 0x9f8033
+
+/* Host Control */
+#define TAG_TUNE 0x9f8400
+#define TAG_REPLACE 0x9f8401
+#define TAG_CLEAR_REPLACE 0x9f8402
+#define TAG_ASK_RELEASE 0x9f8403
+
+/* Date and Time */
+#define TAG_DATE_TIME_ENQUIRY 0x9f8440
+#define TAG_DATE_TIME 0x9f8441
+
+/* Man Machine Interface (MMI) */
+#define TAG_CLOSE_MMI 0x9f8800
+#define TAG_DISPLAY_CONTROL 0x9f8801
+#define TAG_DISPLAY_REPLY 0x9f8802
+#define TAG_TEXT_LAST 0x9f8803
+#define TAG_TEXT_MORE 0x9f8804
+#define TAG_KEYPAD_CONTROL 0x9f8805
+#define TAG_KEYPRESS 0x9f8806
+#define TAG_ENQUIRY 0x9f8807
+#define TAG_ANSWER 0x9f8808
+#define TAG_MENU_LAST 0x9f8809
+#define TAG_MENU_MORE 0x9f880a
+#define TAG_MENU_ANSWER 0x9f880b
+#define TAG_LIST_LAST 0x9f880c
+#define TAG_LIST_MORE 0x9f880d
+#define TAG_SUBTITLE_SEGMENT_LAST 0x9f880e
+#define TAG_SUBTITLE_SEGMENT_MORE 0x9f880f
+#define TAG_DISPLAY_MESSAGE 0x9f8810
+#define TAG_SCENE_END_MARK 0x9f8811
+#define TAG_SCENE_DONE 0x9f8812
+#define TAG_SCENE_CONTROL 0x9f8813
+#define TAG_SUBTITLE_DOWNLOAD_LAST 0x9f8814
+#define TAG_SUBTITLE_DOWNLOAD_MORE 0x9f8815
+#define TAG_FLUSH_DOWNLOAD 0x9f8816
+#define TAG_DOWNLOAD_REPLY 0x9f8817
+
+/* Low Speed Communications */
+#define TAG_COMMS_COMMAND 0x9f8c00
+#define TAG_CONNECTION_DESCRIPTOR 0x9f8c01
+#define TAG_COMMS_REPLY 0x9f8c02
+#define TAG_COMMS_SEND_LAST 0x9f8c03
+#define TAG_COMMS_SEND_MORE 0x9f8c04
+#define TAG_COMMS_RECV_LAST 0x9f8c05
+#define TAG_COMMS_RECV_MORE 0x9f8c06
+
+/* Authentication */
+#define TAG_AUTH_REQ 0x9f8200
+#define TAG_AUTH_RESP 0x9f8201
+
+/* Teletext */
+#define TAG_TELETEXT_EBU 0x9f9000
+
+/* Smartcard */
+#define TAG_SMARTCARD_COMMAND 0x9f8e00
+#define TAG_SMARTCARD_REPLY 0x9f8e01
+#define TAG_SMARTCARD_SEND 0x9f8e02
+#define TAG_SMARTCARD_RCV 0x9f8e03
+
+/* EPG */
+#define TAG_EPG_ENQUIRY 0x9f8f00
+#define TAG_EPG_REPLY 0x9f8f01
+
+#endif
diff --git a/lib/libdvben50221/en50221_app_teletext.c b/lib/libdvben50221/en50221_app_teletext.c
new file mode 100644
index 0000000..b839407
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_teletext.c
@@ -0,0 +1,141 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <string.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <pthread.h>
+#include "en50221_app_teletext.h"
+#include "en50221_app_tags.h"
+#include "asn_1.h"
+
+struct en50221_app_teletext {
+ struct en50221_app_send_functions *funcs;
+
+ en50221_app_teletext_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t lock;
+};
+
+static int en50221_app_teletext_parse_ebu(struct en50221_app_teletext *teletext,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t * data,
+ uint32_t data_length);
+
+
+
+struct en50221_app_teletext *
+ en50221_app_teletext_create(struct en50221_app_send_functions *funcs)
+{
+ struct en50221_app_teletext *teletext = NULL;
+
+ // create structure and set it up
+ teletext = malloc(sizeof(struct en50221_app_teletext));
+ if (teletext == NULL) {
+ return NULL;
+ }
+ teletext->funcs = funcs;
+ teletext->callback = NULL;
+
+ pthread_mutex_init(&teletext->lock, NULL);
+
+ // done
+ return teletext;
+}
+
+void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext)
+{
+ pthread_mutex_destroy(&teletext->lock);
+ free(teletext);
+}
+
+void en50221_app_teletext_register_callback(struct en50221_app_teletext *teletext,
+ en50221_app_teletext_callback callback, void *arg)
+{
+ pthread_mutex_lock(&teletext->lock);
+ teletext->callback = callback;
+ teletext->callback_arg = arg;
+ pthread_mutex_unlock(&teletext->lock);
+}
+
+int en50221_app_teletext_message(struct en50221_app_teletext *teletext,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data, uint32_t data_length)
+{
+ (void) resource_id;
+
+ // get the tag
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
+
+ switch (tag) {
+ case TAG_TELETEXT_EBU:
+ return en50221_app_teletext_parse_ebu(teletext, slot_id,
+ session_number,
+ data + 3,
+ data_length - 3);
+ }
+
+ print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
+ return -1;
+}
+
+
+static int en50221_app_teletext_parse_ebu(struct en50221_app_teletext *teletext,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *data,
+ uint32_t data_length)
+{
+ // first of all, decode the length field
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data, data_length)) < 0) {
+ print(LOG_LEVEL, ERROR, 1, "ASN.1 decode error\n");
+ return -1;
+ }
+
+ // check it
+ if (asn_data_length > (data_length - length_field_len)) {
+ print(LOG_LEVEL, ERROR, 1, "Received short data\n");
+ return -1;
+ }
+ uint8_t *teletext_data = data + length_field_len;
+
+ // tell the app
+ pthread_mutex_lock(&teletext->lock);
+ en50221_app_teletext_callback cb = teletext->callback;
+ void *cb_arg = teletext->callback_arg;
+ pthread_mutex_unlock(&teletext->lock);
+ if (cb) {
+ return cb(cb_arg, slot_id, session_number, teletext_data,
+ asn_data_length);
+ }
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_app_teletext.h b/lib/libdvben50221/en50221_app_teletext.h
new file mode 100644
index 0000000..b5b85f1
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_teletext.h
@@ -0,0 +1,107 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APPLICATION_teletext_H__
+#define __EN50221_APPLICATION_teletext_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_app_utils.h>
+
+#define EN50221_APP_TELETEXT_RESOURCEID MKRID(128, 1, 1)
+
+
+/**
+ * Type definition for request - called when we receive teletext from a CAM.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number concerned.
+ * @param teletext_data Data for the request.
+ * @param teletext_data_lenghth Number of bytes.
+ * @return 0 on success, -1 on failure.
+ */
+typedef int (*en50221_app_teletext_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint8_t *teletext_data,
+ uint32_t teletext_data_length);
+
+/**
+ * Opaque type representing a teletext resource.
+ */
+struct en50221_app_teletext;
+
+/**
+ * Create an instance of the teletext resource.
+ *
+ * @param funcs Send functions to use.
+ * @return Instance, or NULL on failure.
+ */
+extern struct en50221_app_teletext *
+ en50221_app_teletext_create(struct en50221_app_send_functions *funcs);
+
+/**
+ * Destroy an instance of the teletext resource.
+ *
+ * @param teletext Instance to destroy.
+ */
+extern void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext);
+
+/**
+ * Register the callback for when we receive a request.
+ *
+ * @param teletext teletext resource instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_app_teletext_register_callback(struct en50221_app_teletext *teletext,
+ en50221_app_teletext_callback callback,
+ void *arg);
+
+/**
+ * Pass data received for this resource into it for parsing.
+ *
+ * @param teletext teletext instance.
+ * @param slot_id Slot ID concerned.
+ * @param session_number Session number concerned.
+ * @param resource_id Resource ID concerned.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, -1 on failure.
+ */
+extern int en50221_app_teletext_message(struct en50221_app_teletext *teletext,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data,
+ uint32_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_app_utils.c b/lib/libdvben50221/en50221_app_utils.c
new file mode 100644
index 0000000..df2632a
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_utils.c
@@ -0,0 +1,38 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "en50221_app_utils.h"
+
+struct en50221_app_public_resource_id
+ *en50221_app_decode_public_resource_id(struct en50221_app_public_resource_id *idf,
+ uint32_t resource_id)
+{
+ // reject private resources
+ if ((resource_id & 0xc0000000) == 0xc0000000)
+ return NULL;
+
+ idf->resource_class = (resource_id >> 16) & 0xffff; // use the resource_id as the MSBs of class
+ idf->resource_type = (resource_id >> 6) & 0x3ff;
+ idf->resource_version = resource_id & 0x3f;
+ return idf;
+}
diff --git a/lib/libdvben50221/en50221_app_utils.h b/lib/libdvben50221/en50221_app_utils.h
new file mode 100644
index 0000000..5c64760
--- /dev/null
+++ b/lib/libdvben50221/en50221_app_utils.h
@@ -0,0 +1,112 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef __EN50221_APP_UTILS_H__
+#define __EN50221_APP_UTILS_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/uio.h>
+
+/**
+ * A decomposed public resource structure.
+ *
+ * we will ignore private resource (resource_id_type==3),
+ * because they are not used by any modules at all and
+ * would need special code for any private resource anyway.
+ */
+struct en50221_app_public_resource_id {
+ uint16_t resource_class;
+ uint16_t resource_type;
+ uint8_t resource_version;
+};
+
+typedef int (*en50221_send_data) (void *arg,
+ uint16_t session_number,
+ uint8_t * data,
+ uint16_t data_length);
+typedef int (*en50221_send_datav) (void *arg,
+ uint16_t session_number,
+ struct iovec * vector,
+ int iov_count);
+
+/**
+ * An abstraction away from hardcoded send functions so different layers may be
+ * slotted in under the application layer.
+ */
+struct en50221_app_send_functions {
+ /**
+ * Argument to pass to these functions.
+ */
+ void *arg;
+
+ /**
+ * Send data.
+ */
+ en50221_send_data send_data;
+
+ /**
+ * Send vector data.
+ */
+ en50221_send_datav send_datav;
+};
+
+/**
+ * Make a host-endian uint32_t formatted resource id.
+ *
+ * @param CLASS Class of resource.
+ * @param TYPE Type of resource.
+ * @param VERSION Version of resource.
+ * @return Formatted resource id.
+ */
+#define MKRID(CLASS, TYPE, VERSION) ((((CLASS)&0xffff)<<16) | (((TYPE)&0x3ff)<<6) | ((VERSION)&0x3f))
+
+/**
+ * Decode a host-endian public resource_id into an en50221_app_public_resource_id structure.
+ *
+ * @param idf Structure to write decoded resource_id into.
+ * @param resource_id ID to decode.
+ * @return Pointer to idf on success, or NULL if this is not a public resource.
+ */
+struct en50221_app_public_resource_id *
+ en50221_app_decode_public_resource_id(struct en50221_app_public_resource_id *idf,
+ uint32_t resource_id);
+
+/**
+ * Encode an en50221_app_public_resource_id structure into a host-endian uint32_t.
+ *
+ * @param idf Structure to encode.
+ * @return The encoded value
+ */
+static inline uint32_t en50221_app_encode_public_resource_id(struct en50221_app_public_resource_id *idf) {
+ return MKRID(idf->resource_class, idf->resource_type, idf->resource_version);
+}
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_errno.h b/lib/libdvben50221/en50221_errno.h
new file mode 100644
index 0000000..0b53087
--- /dev/null
+++ b/lib/libdvben50221/en50221_errno.h
@@ -0,0 +1,49 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 session layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef EN50221_ERRNO
+#define EN50221_ERRNO 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EN50221ERR_CAREAD -1 /* error during read from CA device. */
+#define EN50221ERR_CAWRITE -2 /* error during write to CA device. */
+#define EN50221ERR_TIMEOUT -3 /* timeout occured waiting for a response from a device. */
+#define EN50221ERR_BADSLOTID -4 /* bad slot ID supplied by user - the offending slot_id will not be set. */
+#define EN50221ERR_BADCONNECTIONID -5 /* bad connection ID supplied by user. */
+#define EN50221ERR_BADSTATE -6 /* slot/connection in the wrong state. */
+#define EN50221ERR_BADCAMDATA -7 /* CAM supplied an invalid request. */
+#define EN50221ERR_OUTOFMEMORY -8 /* memory allocation failed. */
+#define EN50221ERR_ASNENCODE -9 /* ASN.1 encode failure - indicates library bug. */
+#define EN50221ERR_OUTOFCONNECTIONS -10 /* no more connections available. */
+#define EN50221ERR_OUTOFSLOTS -11 /* no more slots available - the offending slot_id will not be set. */
+#define EN50221ERR_IOVLIMIT -12 /* Too many struct iovecs were used. */
+#define EN50221ERR_BADSESSIONNUMBER -13 /* Bad session number suppplied by user. */
+#define EN50221ERR_OUTOFSESSIONS -14 /* no more sessions available. */
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_session.c b/lib/libdvben50221/en50221_session.c
new file mode 100644
index 0000000..3fb9902
--- /dev/null
+++ b/lib/libdvben50221/en50221_session.c
@@ -0,0 +1,1055 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <sys/uio.h>
+#include <pthread.h>
+#include "en50221_transport.h"
+#include "en50221_session.h"
+#include "en50221_errno.h"
+#include "asn_1.h"
+
+
+// these are the possible session statuses
+#define S_STATUS_OPEN 0x00 // session is opened
+#define S_STATUS_CLOSE_NO_RES 0xF0 // could not open session, no proper resource available
+#define S_STATUS_CLOSE_RES_UNAVAILABLE 0xF1 // could not open session, resource unavailable
+#define S_STATUS_CLOSE_RES_LOW_VERSION 0xF2 // could not open session, resource version too low
+#define S_STATUS_CLOSE_RES_BUSY 0xF3 // could not open session, resource is busy
+
+#define ST_OPEN_SESSION_REQ 0x91 // h<--m
+#define ST_OPEN_SESSION_RES 0x92 // h-->m
+#define ST_CREATE_SESSION 0x93 // h-->m
+#define ST_CREATE_SESSION_RES 0x94 // h<--m
+#define ST_CLOSE_SESSION_REQ 0x95 // h<->m
+#define ST_CLOSE_SESSION_RES 0x96 // h<->m
+#define ST_SESSION_NUMBER 0x90 // h<->m
+
+#define S_STATE_IDLE 0x01 // this session is not in use
+#define S_STATE_ACTIVE 0x02 // this session is in use
+#define S_STATE_IN_CREATION 0x04 // this session waits for a ST_CREATE_SESSION_RES to become active
+#define S_STATE_IN_DELETION 0x08 // this session waits for ST_CLOSE_SESSION_RES to become idle again
+
+
+// for each session we store its identifier, the resource-id
+// it is linked to and the callback of the specific resource
+struct en50221_session {
+ uint8_t state;
+ uint32_t resource_id;
+ uint8_t slot_id;
+ uint8_t connection_id;
+
+ en50221_sl_resource_callback callback;
+ void *callback_arg;
+
+ pthread_mutex_t session_lock;
+};
+
+struct en50221_session_layer {
+ uint32_t max_sessions;
+ struct en50221_transport_layer *tl;
+
+ en50221_sl_lookup_callback lookup;
+ void *lookup_arg;
+
+ en50221_sl_session_callback session;
+ void *session_arg;
+
+ pthread_mutex_t global_lock;
+ pthread_mutex_t setcallback_lock;
+
+ int error;
+
+ struct en50221_session *sessions;
+};
+
+static void en50221_sl_transport_callback(void *arg, int reason,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id);
+static int en50221_sl_alloc_new_session(struct en50221_session_layer *sl,
+ uint32_t resource_id,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ en50221_sl_resource_callback
+ callback, void *arg);
+
+
+
+
+struct en50221_session_layer *en50221_sl_create(struct en50221_transport_layer *tl,
+ uint32_t max_sessions)
+{
+ struct en50221_session_layer *sl = NULL;
+ uint32_t i;
+
+ // setup structure
+ sl = (struct en50221_session_layer *)
+ malloc(sizeof(struct en50221_session_layer));
+ if (sl == NULL)
+ goto error_exit;
+ sl->max_sessions = max_sessions;
+ sl->lookup = NULL;
+ sl->session = NULL;
+ sl->tl = tl;
+ sl->error = 0;
+
+ // init the mutex
+ pthread_mutex_init(&sl->global_lock, NULL);
+ pthread_mutex_init(&sl->setcallback_lock, NULL);
+
+ // create the slots
+ sl->sessions = malloc(sizeof(struct en50221_session) * max_sessions);
+ if (sl->sessions == NULL)
+ goto error_exit;
+
+ // set them up
+ for (i = 0; i < max_sessions; i++) {
+ sl->sessions[i].state = S_STATE_IDLE;
+ sl->sessions[i].callback = NULL;
+
+ pthread_mutex_init(&sl->sessions[i].session_lock, NULL);
+ }
+
+ // register ourselves with the transport layer
+ en50221_tl_register_callback(tl, en50221_sl_transport_callback, sl);
+
+ return sl;
+
+error_exit:
+ en50221_sl_destroy(sl);
+ return NULL;
+}
+
+void en50221_sl_destroy(struct en50221_session_layer *sl)
+{
+ uint32_t i;
+
+ if (sl) {
+ if (sl->sessions) {
+ for (i = 0; i < sl->max_sessions; i++) {
+ pthread_mutex_destroy(&sl->sessions[i].session_lock);
+ }
+ free(sl->sessions);
+ }
+
+ pthread_mutex_destroy(&sl->setcallback_lock);
+ pthread_mutex_destroy(&sl->global_lock);
+
+ free(sl);
+ }
+}
+
+int en50221_sl_get_error(struct en50221_session_layer *sl)
+{
+ return sl->error;
+}
+
+void en50221_sl_register_lookup_callback(struct en50221_session_layer *sl,
+ en50221_sl_lookup_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&sl->setcallback_lock);
+ sl->lookup = callback;
+ sl->lookup_arg = arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+}
+
+void en50221_sl_register_session_callback(struct en50221_session_layer *sl,
+ en50221_sl_session_callback
+ callback, void *arg)
+{
+ pthread_mutex_lock(&sl->setcallback_lock);
+ sl->session = callback;
+ sl->session_arg = arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+}
+
+int en50221_sl_create_session(struct en50221_session_layer *sl,
+ int slot_id, uint8_t connection_id,
+ uint32_t resource_id,
+ en50221_sl_resource_callback callback,
+ void *arg)
+{
+ // lookup next free session_id:
+ pthread_mutex_lock(&sl->global_lock);
+ int session_number =
+ en50221_sl_alloc_new_session(sl, resource_id, slot_id,
+ connection_id, callback, arg);
+ if (session_number == -1) {
+ pthread_mutex_unlock(&sl->global_lock);
+ return -1;
+ }
+ pthread_mutex_unlock(&sl->global_lock);
+
+ // make up the header
+ uint8_t hdr[8];
+ hdr[0] = ST_CREATE_SESSION;
+ hdr[1] = 6;
+ hdr[2] = resource_id >> 24;
+ hdr[3] = resource_id >> 16;
+ hdr[4] = resource_id >> 8;
+ hdr[5] = resource_id;
+ hdr[6] = session_number >> 8;
+ hdr[7] = session_number;
+
+ // send this command
+ if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 8)) {
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (sl->sessions[session_number].state == S_STATE_IN_CREATION) {
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ }
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ sl->error = en50221_tl_get_error(sl->tl);
+ return -1;
+ }
+ // ok.
+ return session_number;
+}
+
+int en50221_sl_destroy_session(struct en50221_session_layer *sl,
+ uint16_t session_number)
+{
+ if (session_number >= sl->max_sessions) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ return -1;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (!(sl->sessions[session_number].state & (S_STATE_ACTIVE | S_STATE_IN_DELETION))) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return -1;
+ }
+ // set the state
+ sl->sessions[session_number].state = S_STATE_IN_DELETION;
+
+ // get essential details
+ uint8_t slot_id = sl->sessions[session_number].slot_id;
+ uint8_t connection_id = sl->sessions[session_number].connection_id;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // sendit
+ uint8_t hdr[4];
+ hdr[0] = ST_CLOSE_SESSION_REQ;
+ hdr[1] = 2;
+ hdr[2] = session_number >> 8;
+ hdr[3] = session_number;
+ if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 4)) {
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (sl->sessions[session_number].state == S_STATE_IN_DELETION) {
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ }
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ sl->error = en50221_tl_get_error(sl->tl);
+ return -1;
+ }
+
+ return 0;
+}
+
+int en50221_sl_send_data(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ uint8_t *data,
+ uint16_t data_length)
+{
+ if (session_number >= sl->max_sessions) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ return -1;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (sl->sessions[session_number].state != S_STATE_ACTIVE) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return -1;
+ }
+ // get essential details
+ uint8_t slot_id = sl->sessions[session_number].slot_id;
+ uint8_t connection_id = sl->sessions[session_number].connection_id;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // sendit
+ struct iovec iov[2];
+ uint8_t hdr[4];
+ hdr[0] = ST_SESSION_NUMBER;
+ hdr[1] = 2;
+ hdr[2] = session_number >> 8;
+ hdr[3] = session_number;
+ iov[0].iov_base = hdr;
+ iov[0].iov_len = 4;
+ iov[1].iov_base = data;
+ iov[1].iov_len = data_length;
+ if (en50221_tl_send_datav(sl->tl, slot_id, connection_id, iov, 2)) {
+ sl->error = en50221_tl_get_error(sl->tl);
+ return -1;
+ }
+
+ return 0;
+}
+
+int en50221_sl_send_datav(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ struct iovec *vector,
+ int iov_count)
+{
+ if (session_number >= sl->max_sessions) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ return -1;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (sl->sessions[session_number].state != S_STATE_ACTIVE) {
+ sl->error = EN50221ERR_BADSESSIONNUMBER;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return -1;
+ }
+ if (iov_count > 9) {
+ sl->error = EN50221ERR_IOVLIMIT;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return -1;
+ }
+ uint8_t slot_id = sl->sessions[session_number].slot_id;
+ uint8_t connection_id = sl->sessions[session_number].connection_id;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // make up the header
+ struct iovec out_iov[10];
+ uint8_t hdr[4];
+ hdr[0] = ST_SESSION_NUMBER;
+ hdr[1] = 2;
+ hdr[2] = session_number >> 8;
+ hdr[3] = session_number;
+ out_iov[0].iov_base = hdr;
+ out_iov[0].iov_len = 4;
+
+ // make up the data
+ memcpy(&out_iov[1], vector, iov_count * sizeof(struct iovec));
+
+ // send this command
+ if (en50221_tl_send_datav(sl->tl, slot_id, connection_id, out_iov, iov_count + 1)) {
+ sl->error = en50221_tl_get_error(sl->tl);
+ return -1;
+ }
+ return 0;
+}
+
+int en50221_sl_broadcast_data(struct en50221_session_layer *sl,
+ int slot_id, uint32_t resource_id,
+ uint8_t *data, uint16_t data_length)
+{
+ uint32_t i;
+
+ for (i = 0; i < sl->max_sessions; i++) {
+ pthread_mutex_lock(&sl->sessions[i].session_lock);
+
+ if (sl->sessions[i].state != S_STATE_ACTIVE) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+ if ((slot_id != -1)
+ && (slot_id != sl->sessions[i].slot_id)) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+
+ if (sl->sessions[i].resource_id == resource_id) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ en50221_sl_send_data(sl, i, data, data_length);
+ } else {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ }
+ }
+
+ return 0;
+}
+
+
+
+static void en50221_sl_handle_open_session_request(struct en50221_session_layer *sl,
+ uint8_t *data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (data_length < 5) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ if (data[0] != 4) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ // get the resource id
+ uint32_t requested_resource_id =
+ (data[1] << 24) | (data[2] << 16) | (data[3] << 8) | data[4];
+
+ // get lookup callback details
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_lookup_callback lcb = sl->lookup;
+ void *lcb_arg = sl->lookup_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ // first of all, lookup this resource id
+ int status = S_STATUS_CLOSE_NO_RES;
+ en50221_sl_resource_callback resource_callback = NULL;
+ void *resource_arg = NULL;
+ uint32_t connected_resource_id;
+ if (lcb) {
+ status =
+ lcb(lcb_arg, slot_id, requested_resource_id,
+ &resource_callback, &resource_arg,
+ &connected_resource_id);
+ switch (status) {
+ case 0:
+ status = S_STATUS_OPEN;
+ break;
+
+ case -1:
+ status = S_STATUS_CLOSE_NO_RES;
+ break;
+
+ case -2:
+ status = S_STATUS_CLOSE_RES_LOW_VERSION;
+ break;
+
+ case -3:
+ status = S_STATUS_CLOSE_RES_UNAVAILABLE;
+ break;
+ }
+ }
+ // if we found it, get a new session for it
+ int session_number = -1;
+ if (status == S_STATUS_OPEN) {
+ // lookup next free session_id:
+ pthread_mutex_lock(&sl->global_lock);
+ session_number =
+ en50221_sl_alloc_new_session(sl, connected_resource_id,
+ slot_id, connection_id,
+ resource_callback,
+ resource_arg);
+ pthread_mutex_unlock(&sl->global_lock);
+
+ if (session_number == -1) {
+ status = S_STATUS_CLOSE_NO_RES;
+ } else {
+ // inform upper layers/ check availability
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+ if (cb) {
+ if (cb(cb_arg, S_SCALLBACK_REASON_CAMCONNECTING,
+ slot_id, session_number,
+ connected_resource_id)) {
+ status = S_STATUS_CLOSE_RES_BUSY;
+ }
+ } else {
+ status = S_STATUS_CLOSE_RES_UNAVAILABLE;
+ }
+ }
+ }
+ // send response
+ uint8_t hdr[9];
+ hdr[0] = ST_OPEN_SESSION_RES;
+ hdr[1] = 7;
+ hdr[2] = status;
+ hdr[3] = connected_resource_id >> 24;
+ hdr[4] = connected_resource_id >> 16;
+ hdr[5] = connected_resource_id >> 8;
+ hdr[6] = connected_resource_id;
+ hdr[7] = session_number >> 8;
+ hdr[8] = session_number;
+ if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 9)) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Transport layer error %i occurred\n",
+ en50221_tl_get_error(sl->tl));
+ status = S_STATUS_CLOSE_NO_RES;
+ // fallthrough
+ }
+ // inform upper layers what happened
+ if (session_number != -1) {
+ // setup session state apppropriately from upper layer response
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (status != S_STATUS_OPEN) {
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ } else {
+ sl->sessions[session_number].state = S_STATE_ACTIVE;
+ }
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // tell upper layers
+ if (sl->sessions[session_number].state == S_STATE_ACTIVE) {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ if (status == S_STATUS_OPEN) {
+ if (cb)
+ cb(cb_arg,
+ S_SCALLBACK_REASON_CAMCONNECTED,
+ slot_id, session_number,
+ connected_resource_id);
+ } else {
+ sl->sessions[session_number].state =
+ S_STATE_IDLE;
+ if (cb)
+ cb(cb_arg,
+ S_SCALLBACK_REASON_CAMCONNECTFAIL,
+ slot_id, session_number,
+ connected_resource_id);
+ }
+ }
+ }
+}
+
+static void en50221_sl_handle_close_session_request(struct en50221_session_layer *sl,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ if (data[0] != 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ // extract session number
+ uint16_t session_number = (data[1] << 8) | data[2];
+
+ // check session number is ok
+ uint8_t code = 0x00;
+ uint32_t resource_id = 0;
+ if (session_number >= sl->max_sessions) {
+ code = 0xF0; // session close error
+ print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n",
+ slot_id);
+ } else {
+ pthread_mutex_lock(&sl->sessions[session_number].
+ session_lock);
+ if (slot_id != sl->sessions[session_number].slot_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ code = 0xF0; // session close error
+ }
+ if (connection_id != sl->sessions[session_number].connection_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ code = 0xF0; // session close error
+ }
+ if (!(sl->sessions[session_number].state & (S_STATE_ACTIVE | S_STATE_IN_DELETION))) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ code = 0xF0; // session close error
+ }
+
+ if (code == 0x00) {
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ code = 0x00; // close ok
+ }
+ resource_id = sl->sessions[session_number].resource_id;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ }
+
+ // make up the response
+ uint8_t hdr[5];
+ hdr[0] = ST_CLOSE_SESSION_RES;
+ hdr[1] = 3;
+ hdr[2] = code;
+ hdr[3] = session_number >> 8;
+ hdr[4] = session_number;
+
+ // sendit
+ if (en50221_tl_send_data(sl->tl, slot_id, connection_id, hdr, 5)) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Transport layer reports error %i on slot %i\n",
+ en50221_tl_get_error(sl->tl), slot_id);
+ }
+ // callback to announce destruction to resource if it was ok
+ if (code == 0x00) {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_CLOSE, slot_id,
+ session_number, resource_id);
+ }
+}
+
+static void en50221_sl_handle_create_session_response(struct en50221_session_layer *sl,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (data_length < 8) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ if (data[0] != 7) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ // extract session number
+ uint16_t session_number = (data[5] << 8) | data[6];
+
+ // check session number is ok
+ if (session_number >= sl->max_sessions) {
+ print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n",
+ slot_id);
+ return;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (slot_id != sl->sessions[session_number].slot_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (connection_id != sl->sessions[session_number].connection_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (sl->sessions[session_number].state != S_STATE_IN_CREATION) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ // extract status
+ if (data[1] != S_STATUS_OPEN) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Session creation failed 0x%02x\n", data[1]);
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // inform upper layers
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_CONNECTFAIL, slot_id,
+ session_number,
+ sl->sessions[session_number].resource_id);
+ return;
+ }
+ // set it active
+ sl->sessions[session_number].state = S_STATE_ACTIVE;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // inform upper layers
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_CONNECTED, slot_id,
+ session_number,
+ sl->sessions[session_number].resource_id);
+}
+
+static void en50221_sl_handle_close_session_response(struct en50221_session_layer *sl,
+ uint8_t *data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (data_length < 5) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ if (data[0] != 4) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ return;
+ }
+ // extract session number
+ uint16_t session_number = (data[2] << 8) | data[3];
+
+ // check session number is ok
+ if (session_number >= sl->max_sessions) {
+ print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id);
+ return;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (slot_id != sl->sessions[session_number].slot_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (connection_id != sl->sessions[session_number].connection_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (sl->sessions[session_number].state != S_STATE_IN_DELETION) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ // extract status
+ if (data[1] != 0x00) {
+ print(LOG_LEVEL, ERROR, 1, "Session close failed 0x%02x\n", data[1]);
+ // just fallthrough anyway
+ }
+ // completed
+ sl->sessions[session_number].state = S_STATE_IDLE;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+}
+
+static void en50221_sl_handle_session_package(struct en50221_session_layer *sl,
+ uint8_t *data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %i\n",
+ slot_id);
+ return;
+ }
+ if (data[0] != 2) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %i\n",
+ slot_id);
+ return;
+ }
+ // get session number
+ uint16_t session_number = (data[1] << 8) | data[2];
+
+ // check it
+ if (session_number >= sl->max_sessions) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with bad session_number from module on slot %i\n",
+ slot_id);
+ return;
+ }
+
+ pthread_mutex_lock(&sl->sessions[session_number].session_lock);
+ if (slot_id != sl->sessions[session_number].slot_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (connection_id != sl->sessions[session_number].connection_id) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unexpected session on invalid slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+ if (sl->sessions[session_number].state != S_STATE_ACTIVE) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with bad session_number from module on slot %i\n",
+ slot_id);
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+ return;
+ }
+
+ en50221_sl_resource_callback cb = sl->sessions[session_number].callback;
+ void *cb_arg = sl->sessions[session_number].callback_arg;
+ uint32_t resource_id = sl->sessions[session_number].resource_id;
+ pthread_mutex_unlock(&sl->sessions[session_number].session_lock);
+
+ // there can be > 1 APDU following the package - all for the same session/resource_id tho.
+ data += 3;
+ data_length -= 3;
+ while (data_length) {
+ // check length field
+ if (data_length < 3) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received invalid sized session package from slot %i\n",
+ slot_id);
+ return;
+ }
+ // parse the APDU's length field
+ int length_field_len;
+ uint16_t asn_data_length;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data + 3, data_length - 3)) < 0) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received invalid sized session package from slot %i\n",
+ slot_id);
+ return;
+ }
+ uint32_t apdu_length = 3 + length_field_len + asn_data_length;
+
+ // check there is enough data
+ if (apdu_length > data_length) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received invalid sized session package from slot %i\n",
+ slot_id);
+ return;
+ }
+ // pass the APDU up to the higher layers
+ if (cb)
+ cb(cb_arg, slot_id, session_number, resource_id, data, apdu_length);
+
+ // next!
+ data += apdu_length;
+ data_length -= apdu_length;
+ }
+
+}
+
+static void en50221_sl_transport_callback(void *arg, int reason,
+ uint8_t *data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ struct en50221_session_layer *sl =
+ (struct en50221_session_layer *) arg;
+ uint32_t i;
+
+ // deal with the reason for this callback
+ switch (reason) {
+ case T_CALLBACK_REASON_DATA:
+ // fallthrough into rest of this function
+ break;
+
+ case T_CALLBACK_REASON_CONNECTIONOPEN:
+ {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_TC_CONNECT,
+ slot_id, connection_id, 0);
+ return;
+ }
+
+ case T_CALLBACK_REASON_CAMCONNECTIONOPEN:
+ {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ if (cb)
+ cb(cb_arg,
+ S_SCALLBACK_REASON_TC_CAMCONNECT,
+ slot_id, connection_id, 0);
+ return;
+ }
+
+ case T_CALLBACK_REASON_CONNECTIONCLOSE:
+ {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ for (i = 0; i < sl->max_sessions; i++) {
+ pthread_mutex_lock(&sl->sessions[i].session_lock);
+
+ if (sl->sessions[i].state == S_STATE_IDLE) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+ if (sl->sessions[i].connection_id != connection_id) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+
+ sl->sessions[i].state = S_STATE_IDLE;
+
+ uint8_t _slot_id = sl->sessions[i].slot_id;
+ uint32_t resource_id = sl->sessions[i].resource_id;
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_CLOSE, _slot_id, i, resource_id);
+ }
+ return;
+ }
+
+ case T_CALLBACK_REASON_SLOTCLOSE:
+ {
+ pthread_mutex_lock(&sl->setcallback_lock);
+ en50221_sl_session_callback cb = sl->session;
+ void *cb_arg = sl->session_arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
+
+ for (i = 0; i < sl->max_sessions; i++) {
+ pthread_mutex_lock(&sl->sessions[i].session_lock);
+
+ if (sl->sessions[i].state == S_STATE_IDLE) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+ if (sl->sessions[i].slot_id != slot_id) {
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+ continue;
+ }
+ sl->sessions[i].state = S_STATE_IDLE;
+
+ uint32_t resource_id = sl->sessions[i].resource_id;
+ pthread_mutex_unlock(&sl->sessions[i].session_lock);
+
+ if (cb)
+ cb(cb_arg, S_SCALLBACK_REASON_CLOSE, slot_id, i, resource_id);
+
+ }
+ return;
+ }
+ }
+
+ // sanity check data length
+ if (data_length < 1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %i\n",
+ slot_id);
+ return;
+ }
+ // deal with the data
+ uint8_t spdu_tag = data[0];
+ switch (spdu_tag) {
+ case ST_OPEN_SESSION_REQ:
+ en50221_sl_handle_open_session_request(sl, data + 1,
+ data_length - 1,
+ slot_id,
+ connection_id);
+ break;
+
+ case ST_CLOSE_SESSION_REQ:
+ en50221_sl_handle_close_session_request(sl, data + 1,
+ data_length - 1,
+ slot_id,
+ connection_id);
+ break;
+
+ case ST_SESSION_NUMBER:
+ en50221_sl_handle_session_package(sl, data + 1,
+ data_length - 1, slot_id,
+ connection_id);
+ break;
+
+ case ST_CREATE_SESSION_RES:
+ en50221_sl_handle_create_session_response(sl, data + 1,
+ data_length - 1,
+ slot_id,
+ connection_id);
+ break;
+
+ case ST_CLOSE_SESSION_RES:
+ en50221_sl_handle_close_session_response(sl, data + 1,
+ data_length - 1,
+ slot_id,
+ connection_id);
+ break;
+
+ default:
+ print(LOG_LEVEL, ERROR, 1,
+ "Received unknown session tag %02x from module on slot %i",
+ spdu_tag, slot_id);
+ break;
+ }
+}
+
+static int en50221_sl_alloc_new_session(struct en50221_session_layer *sl,
+ uint32_t resource_id,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ en50221_sl_resource_callback
+ callback, void *arg)
+{
+ int session_number = -1;
+ uint32_t i;
+ for (i = 1; i < sl->max_sessions; i++) {
+ if (sl->sessions[i].state == S_STATE_IDLE) {
+ session_number = i;
+ break;
+ }
+ }
+ if (session_number == -1) {
+ sl->error = EN50221ERR_OUTOFSESSIONS;
+ return -1;
+ }
+ // setup the session
+ sl->sessions[session_number].state = S_STATE_IN_CREATION;
+ sl->sessions[session_number].resource_id = resource_id;
+ sl->sessions[session_number].slot_id = slot_id;
+ sl->sessions[session_number].connection_id = connection_id;
+ sl->sessions[session_number].callback = callback;
+ sl->sessions[session_number].callback_arg = arg;
+
+ // ok
+ return session_number;
+}
diff --git a/lib/libdvben50221/en50221_session.h b/lib/libdvben50221/en50221_session.h
new file mode 100644
index 0000000..7b33518
--- /dev/null
+++ b/lib/libdvben50221/en50221_session.h
@@ -0,0 +1,232 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 session layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian@jusst.de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#ifndef __EN50221_SESSION_H__
+#define __EN50221_SESSION_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <libdvben50221/en50221_transport.h>
+
+#define S_SCALLBACK_REASON_CAMCONNECTING 0x00 // CAM originated session connecting to resource (check for availability)
+#define S_SCALLBACK_REASON_CAMCONNECTED 0x01 // CAM originated session connection established succesfully
+#define S_SCALLBACK_REASON_CAMCONNECTFAIL 0x02 // CAM originated session connection failed
+#define S_SCALLBACK_REASON_CONNECTED 0x03 // Host originated session ACKed by CAM.
+#define S_SCALLBACK_REASON_CONNECTFAIL 0x04 // Host originated session NACKed by CAM.
+#define S_SCALLBACK_REASON_CLOSE 0x05 // Session closed
+#define S_SCALLBACK_REASON_TC_CONNECT 0x06 // A host originated transport connection has been established.
+#define S_SCALLBACK_REASON_TC_CAMCONNECT 0x07 // A CAM originated transport connection has been established.
+
+
+/**
+ * Opaque type representing a session layer.
+ */
+struct en50221_session_layer;
+
+/**
+ * Type definition for resource callback function - called by session layer when data
+ * arrives for a particular resource.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number.
+ * @param resource_id Resource id.
+ * @param data The data.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, or -1 on failure.
+ */
+typedef int (*en50221_sl_resource_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id,
+ uint8_t * data,
+ uint32_t data_length);
+
+/**
+ * Type definition for resource lookup callback function - used by the session layer to
+ * look up requested resources.
+ *
+ * @param arg Private argument.
+ * @param slot_id Slot id the request came from.
+ * @param requested_resource_id Resource id requested.
+ * @param callback_out Output parameter for pointer to resource callback function.
+ * @param arg_out Output parameter for arg to pass to resource callback.
+ * @param resource_id_out Set this to the resource_id connected to (e.g. may differ from resource_id due to versions).
+ * @return 0 on success,
+ * -1 if the resource was not found,
+ * -2 if it exists, but had a lower version, or
+ * -3 if it exists, but was unavailable.
+ */
+typedef int (*en50221_sl_lookup_callback) (void *arg,
+ uint8_t slot_id,
+ uint32_t requested_resource_id,
+ en50221_sl_resource_callback * callback_out,
+ void **arg_out,
+ uint32_t *resource_id_out);
+
+
+/**
+ * Type definition for session callback function - used to inform top level code when a CAM
+ * modifies a session to a resource.
+ *
+ * @param arg Private argument.
+ * @param reason One of the S_CCALLBACK_REASON_* values above.
+ * @param slot_id Slot id concerned.
+ * @param session_number Session number.
+ * @param resource_id Resource id.
+ * @return 0 on sucess, or -1 on error.
+ */
+typedef int (*en50221_sl_session_callback) (void *arg, int reason,
+ uint8_t slot_id,
+ uint16_t session_number,
+ uint32_t resource_id);
+
+/**
+ * Construct a new instance of the session layer.
+ *
+ * @param tl The en50221_transport_layer instance to use.
+ * @param max_sessions Maximum number of sessions supported.
+ * @return The en50221_session_layer instance, or NULL on error.
+ */
+extern struct en50221_session_layer *en50221_sl_create(struct en50221_transport_layer *tl,
+ uint32_t max_sessions);
+
+/**
+ * Destroy an instance of the session layer.
+ *
+ * @param tl The en50221_session_layer instance.
+ */
+extern void en50221_sl_destroy(struct en50221_session_layer *sl);
+
+/**
+ * Gets the last error.
+ *
+ * @param tl The en50221_session_layer instance.
+ * @return One of the EN50221ERR_* values.
+ */
+extern int en50221_sl_get_error(struct en50221_session_layer *tl);
+
+/**
+ * Register the callback for resource lookup.
+ *
+ * @param sl The en50221_session_layer instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_sl_register_lookup_callback(struct en50221_session_layer *sl,
+ en50221_sl_lookup_callback callback,
+ void *arg);
+
+/**
+ * Register the callback for informing about session from a cam.
+ *
+ * @param sl The en50221_session_layer instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_sl_register_session_callback(struct en50221_session_layer *sl,
+ en50221_sl_session_callback callback,
+ void *arg);
+
+/**
+ * Create a new session to a module in a slot.
+ *
+ * @param sl The en50221_session_layer instance.
+ * @param slot The slot to connect to.
+ * @param resource_id The resource_id to connect to.
+ * @param callback The callback for received data.
+ * @param arg Argument to pass to the callback.
+ * @return The new session_number, or -1 on error.
+ */
+extern int en50221_sl_create_session(struct en50221_session_layer *sl, int slot_id,
+ uint8_t connection_id,
+ uint32_t resource_id,
+ en50221_sl_resource_callback callback,
+ void *arg);
+
+/**
+ * Destroy a session.
+ *
+ * @param sl The en50221_session_layer instance.
+ * @param session_number The session to destroy.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_sl_destroy_session(struct en50221_session_layer *sl,
+ uint16_t session_number);
+
+/**
+ * this function is used to take a data-block, pack into
+ * into a SPDU (SESSION_NUMBER) and send it to the transport layer
+ *
+ * @param sl The en50221_session_layer instance to use.
+ * @param session_number Session number concerned.
+ * @param data Data to send.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_sl_send_data(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ uint8_t * data,
+ uint16_t data_length);
+
+/**
+ * this function is used to take a data-block, pack into
+ * into a SPDU (SESSION_NUMBER) and send it to the transport layer
+ *
+ * @param sl The en50221_session_layer instance to use.
+ * @param session_number Session number concerned.
+ * @param vector IOVEC to send.
+ * @param iov_count Number of elements in io vector.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_sl_send_datav(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ struct iovec *vector,
+ int iov_count);
+
+/**
+ * this is used to send a message to all sessions, linked
+ * to resource res
+ *
+ * @param tl The en50221_session_layer instance to use.
+ * @param slot_id Set to -1 to send to any slot. Other values will send to only that slot.
+ * @param resource_id Resource id concerned.
+ * @param data Data to send.
+ * @param data_length Length of data in bytes.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_sl_broadcast_data(struct en50221_session_layer *sl,
+ int slot_id,
+ uint32_t resource_id,
+ uint8_t * data,
+ uint16_t data_length);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvben50221/en50221_stdcam.c b/lib/libdvben50221/en50221_stdcam.c
new file mode 100644
index 0000000..a00a844
--- /dev/null
+++ b/lib/libdvben50221/en50221_stdcam.c
@@ -0,0 +1,54 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <libdvbapi/dvbca.h>
+#include "en50221_stdcam.h"
+
+struct en50221_stdcam *en50221_stdcam_create(int adapter, int slotnum,
+ struct en50221_transport_layer *tl,
+ struct en50221_session_layer *sl)
+{
+ struct en50221_stdcam *result = NULL;
+
+ int cafd = dvbca_open(adapter, 0);
+ if (cafd == -1)
+ return NULL;
+
+ int ca_type = dvbca_get_interface_type(cafd, slotnum);
+ switch(ca_type) {
+ case DVBCA_INTERFACE_LINK:
+ result = en50221_stdcam_llci_create(cafd, slotnum, tl, sl);
+ break;
+
+ case DVBCA_INTERFACE_HLCI:
+ result = en50221_stdcam_hlci_create(cafd, slotnum);
+ break;
+ }
+
+ if (result == NULL)
+ close(cafd);
+ return result;
+}
diff --git a/lib/libdvben50221/en50221_stdcam.h b/lib/libdvben50221/en50221_stdcam.h
new file mode 100644
index 0000000..154ff76
--- /dev/null
+++ b/lib/libdvben50221/en50221_stdcam.h
@@ -0,0 +1,102 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef EN50221_STDCAM_H
+#define EN50221_STDCAM_H 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <libdvben50221/en50221_app_ai.h>
+#include <libdvben50221/en50221_app_ca.h>
+#include <libdvben50221/en50221_app_mmi.h>
+#include <libdvben50221/en50221_session.h>
+#include <libdvben50221/en50221_transport.h>
+
+enum en50221_stdcam_status {
+ EN50221_STDCAM_CAM_NONE,
+ EN50221_STDCAM_CAM_INRESET,
+ EN50221_STDCAM_CAM_OK,
+ EN50221_STDCAM_CAM_BAD,
+};
+
+struct en50221_stdcam {
+ /* one of more of the following may be NULL if a CAM does not support it */
+ struct en50221_app_ai *ai_resource;
+ struct en50221_app_ca *ca_resource;
+ struct en50221_app_mmi *mmi_resource;
+
+ /* if any of these are -1, no connection is in place to this resource yet */
+ int ai_session_number;
+ int ca_session_number;
+ int mmi_session_number;
+
+ /* poll the stdcam instance */
+ enum en50221_stdcam_status (*poll)(struct en50221_stdcam *stdcam);
+
+ /* inform the stdcam of the current DVB time */
+ void (*dvbtime)(struct en50221_stdcam *stdcam, time_t dvbtime);
+
+ /* destroy the stdcam instance */
+ void (*destroy)(struct en50221_stdcam *stdcam, int closefd);
+};
+
+/**
+ * Create an instance of the STDCAM for an LLCI interface.
+ *
+ * @param cafd FD of the CA device.
+ * @param slotnum Slotnum on that CA device.
+ * @param tl Transport layer instance to use.
+ * @param sl Session layer instance to use.
+ * @return en50221_stdcam instance, or NULL on error.
+ */
+extern struct en50221_stdcam *en50221_stdcam_llci_create(int cafd, int slotnum,
+ struct en50221_transport_layer *tl,
+ struct en50221_session_layer *sl);
+
+/**
+ * Create an instance of the STDCAM for an HLCI interface.
+ *
+ * @param cafd FD of the CA device.
+ * @param slotnum Slotnum on that CA device.
+ * @return en50221_stdcam instance, or NULL on error.
+ */
+extern struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum);
+
+/**
+ * Convenience method to create a STDCAM interface for a ca device on a particular adapter.
+ *
+ * @param adapter The DVB adapter concerned.
+ * @param slotnum The ca slot number on that adapter.
+ * @param tl Transport layer instance to use (unused for HLCI cams).
+ * @param sl Session layer instance to use (unused for HLCI cams).
+ * @return en50221_stdcam instance, or NULL on error.
+ */
+extern struct en50221_stdcam *en50221_stdcam_create(int adapter, int slotnum,
+ struct en50221_transport_layer *tl,
+ struct en50221_session_layer *sl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libdvben50221/en50221_stdcam_hlci.c b/lib/libdvben50221/en50221_stdcam_hlci.c
new file mode 100644
index 0000000..f21637b
--- /dev/null
+++ b/lib/libdvben50221/en50221_stdcam_hlci.c
@@ -0,0 +1,216 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <libdvbapi/dvbca.h>
+#include "en50221_app_utils.h"
+#include "en50221_app_tags.h"
+#include "en50221_stdcam.h"
+
+
+struct en50221_stdcam_hlci {
+ struct en50221_stdcam stdcam;
+
+ int cafd;
+ int slotnum;
+ int initialised;
+ struct en50221_app_send_functions sendfuncs;
+};
+
+static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd);
+static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam);
+static int hlci_cam_added(struct en50221_stdcam_hlci *hlci);
+static int hlci_send_data(void *arg, uint16_t session_number,
+ uint8_t * data, uint16_t data_length);
+static int hlci_send_datav(void *arg, uint16_t session_number,
+ struct iovec *vector, int iov_count);
+
+
+
+
+struct en50221_stdcam *en50221_stdcam_hlci_create(int cafd, int slotnum)
+{
+ // try and allocate space for the HLCI stdcam
+ struct en50221_stdcam_hlci *hlci =
+ malloc(sizeof(struct en50221_stdcam_hlci));
+ if (hlci == NULL) {
+ return NULL;
+ }
+ memset(hlci, 0, sizeof(struct en50221_stdcam_hlci));
+
+ // create the sendfuncs
+ hlci->sendfuncs.arg = hlci;
+ hlci->sendfuncs.send_data = hlci_send_data;
+ hlci->sendfuncs.send_datav = hlci_send_datav;
+
+ // create the resources (NOTE: we just use fake session numbers here)
+ hlci->stdcam.ai_resource = en50221_app_ai_create(&hlci->sendfuncs);
+ hlci->stdcam.ai_session_number = 0;
+ hlci->stdcam.ca_resource = en50221_app_ca_create(&hlci->sendfuncs);
+ hlci->stdcam.ca_session_number = 1;
+// hlci->stdcam.mmi_resource = en50221_app_mmi_create(&hlci->sendfuncs);
+ hlci->stdcam.mmi_session_number = -1;
+
+ // done
+ hlci->stdcam.destroy = en50221_stdcam_hlci_destroy;
+ hlci->stdcam.poll = en50221_stdcam_hlci_poll;
+ hlci->slotnum = slotnum;
+ hlci->cafd = cafd;
+ return &hlci->stdcam;
+}
+
+static void en50221_stdcam_hlci_destroy(struct en50221_stdcam *stdcam, int closefd)
+{
+ struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
+
+ if (hlci->stdcam.ai_resource)
+ en50221_app_ai_destroy(hlci->stdcam.ai_resource);
+ if (hlci->stdcam.ca_resource)
+ en50221_app_ca_destroy(hlci->stdcam.ca_resource);
+ if (hlci->stdcam.mmi_resource)
+ en50221_app_mmi_destroy(hlci->stdcam.mmi_resource);
+
+ if (closefd)
+ close(hlci->cafd);
+
+ free(hlci);
+}
+
+static enum en50221_stdcam_status en50221_stdcam_hlci_poll(struct en50221_stdcam *stdcam)
+{
+ struct en50221_stdcam_hlci *hlci = (struct en50221_stdcam_hlci *) stdcam;
+
+ switch(dvbca_get_cam_state(hlci->cafd, hlci->slotnum)) {
+ case DVBCA_CAMSTATE_MISSING:
+ hlci->initialised = 0;
+ break;
+
+ case DVBCA_CAMSTATE_READY:
+ case DVBCA_CAMSTATE_INITIALISING:
+ if (!hlci->initialised)
+ hlci_cam_added(hlci);
+ break;
+ }
+
+ // delay to prevent busy loop
+ usleep(10);
+
+ if (!hlci->initialised) {
+ return EN50221_STDCAM_CAM_NONE;
+ }
+ return EN50221_STDCAM_CAM_OK;
+}
+
+
+
+static int hlci_cam_added(struct en50221_stdcam_hlci *hlci)
+{
+ uint8_t buf[256];
+ int size;
+
+ // get application information
+ if (en50221_app_ai_enquiry(hlci->stdcam.ai_resource, 0)) {
+ return -EIO;
+ }
+ if ((size = dvbca_hlci_read(hlci->cafd, TAG_APP_INFO, buf, sizeof(buf))) < 0) {
+ return size;
+ }
+ if (en50221_app_ai_message(hlci->stdcam.ai_resource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) {
+ return -EIO;
+ }
+
+ // we forge a fake CA_INFO here so the main app works - since it will expect a CA_INFO
+ // this will be replaced with a proper call (below) when the driver support is there
+ buf[0] = TAG_CA_INFO >> 16;
+ buf[1] = (uint8_t) (TAG_CA_INFO >> 8);
+ buf[2] = (uint8_t) TAG_CA_INFO;
+ buf[3] = 0;
+ if (en50221_app_ca_message(hlci->stdcam.ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) {
+ return -EIO;
+ }
+
+ /*
+ // get CA information
+ if (en50221_app_ca_info_enq(ca_resource, 0)) {
+ fprintf(stderr, "Failed to send CA INFO enquiry\n");
+ cafd = -1;
+ return -1;
+ }
+ if ((size = dvbca_hlci_read(cafd, TAG_CA_INFO, buf, sizeof(buf))) < 0) {
+ fprintf(stderr, "Failed to read CA INFO\n");
+ cafd = -1;
+ return -1;
+ }
+ if (en50221_app_ca_message(ca_resource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, size)) {
+ fprintf(stderr, "Failed to parse CA INFO\n");
+ cafd = -1;
+ return -1;
+ }
+ */
+
+ // done
+ hlci->initialised = 1;
+ return 0;
+}
+
+static int hlci_send_data(void *arg, uint16_t session_number,
+ uint8_t * data, uint16_t data_length)
+{
+ (void) session_number;
+ struct en50221_stdcam_hlci *hlci = arg;
+
+ return dvbca_hlci_write(hlci->cafd, data, data_length);
+}
+
+static int hlci_send_datav(void *arg, uint16_t session_number,
+ struct iovec *vector, int iov_count)
+{
+ (void) session_number;
+ struct en50221_stdcam_hlci *hlci = arg;
+
+ // calculate the total length of the data to send
+ uint32_t data_size = 0;
+ int i;
+ for (i = 0; i < iov_count; i++) {
+ data_size += vector[i].iov_len;
+ }
+
+ // allocate memory for it
+ uint8_t *buf = malloc(data_size);
+ if (buf == NULL) {
+ return -1;
+ }
+ // merge the iovecs
+ uint32_t pos = 0;
+ for (i = 0; i < iov_count; i++) {
+ memcpy(buf + pos, vector[i].iov_base, vector[i].iov_len);
+ pos += vector[i].iov_len;
+ }
+
+ // sendit and cleanup
+ int status = dvbca_hlci_write(hlci->cafd, buf, data_size);
+ free(buf);
+ return status;
+}
diff --git a/lib/libdvben50221/en50221_stdcam_llci.c b/lib/libdvben50221/en50221_stdcam_llci.c
new file mode 100644
index 0000000..2266bbf
--- /dev/null
+++ b/lib/libdvben50221/en50221_stdcam_llci.c
@@ -0,0 +1,437 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <string.h>
+#include <errno.h>
+#include <libdvbapi/dvbca.h>
+#include <libdvbmisc/dvbmisc.h>
+#include "en50221_app_rm.h"
+#include "en50221_app_datetime.h"
+#include "en50221_app_utils.h"
+#include "en50221_app_tags.h"
+#include "en50221_stdcam.h"
+
+#define LLCI_RESPONSE_TIMEOUT_MS 1000
+#define LLCI_POLL_DELAY_MS 100
+
+/* resource IDs we support */
+static uint32_t resource_ids[] =
+{ EN50221_APP_RM_RESOURCEID,
+ EN50221_APP_CA_RESOURCEID,
+ EN50221_APP_AI_RESOURCEID,
+ EN50221_APP_MMI_RESOURCEID,
+ EN50221_APP_DATETIME_RESOURCEID,
+};
+#define RESOURCE_IDS_COUNT sizeof(resource_ids)/4
+
+struct llci_resource {
+ struct en50221_app_public_resource_id resid;
+ uint32_t binary_resource_id;
+ en50221_sl_resource_callback callback;
+ void *arg;
+};
+
+struct en50221_stdcam_llci {
+ struct en50221_stdcam stdcam;
+
+ int cafd;
+ int slotnum;
+ int state;
+
+ struct llci_resource resources[RESOURCE_IDS_COUNT];
+
+ struct en50221_transport_layer *tl;
+ struct en50221_session_layer *sl;
+ struct en50221_app_send_functions sendfuncs;
+ int tl_slot_id;
+
+ struct en50221_app_rm *rm_resource;
+
+ struct en50221_app_datetime *datetime_resource;
+ int datetime_session_number;
+ uint8_t datetime_response_interval;
+ time_t datetime_next_send;
+ time_t datetime_dvbtime;
+};
+
+static enum en50221_stdcam_status en50221_stdcam_llci_poll(struct en50221_stdcam *stdcam);
+static void en50221_stdcam_llci_dvbtime(struct en50221_stdcam *stdcam, time_t dvbtime);
+static void en50221_stdcam_llci_destroy(struct en50221_stdcam *stdcam, int closefd);
+static void llci_cam_added(struct en50221_stdcam_llci *llci);
+static void llci_cam_in_reset(struct en50221_stdcam_llci *llci);
+static void llci_cam_removed(struct en50221_stdcam_llci *llci);
+
+
+static int llci_lookup_callback(void *arg, uint8_t _slot_id, uint32_t requested_resource_id,
+ en50221_sl_resource_callback *callback_out, void **arg_out,
+ uint32_t *connected_resource_id);
+static int llci_session_callback(void *arg, int reason, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id);
+static int llci_rm_enq_callback(void *arg, uint8_t _slot_id, uint16_t session_number);
+static int llci_rm_reply_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id_count, uint32_t *_resource_ids);
+static int llci_rm_changed_callback(void *arg, uint8_t _slot_id, uint16_t session_number);
+
+static int llci_datetime_enquiry_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint8_t response_interval);
+
+
+struct en50221_stdcam *en50221_stdcam_llci_create(int cafd, int slotnum,
+ struct en50221_transport_layer *tl,
+ struct en50221_session_layer *sl)
+{
+ // try and allocate space for the LLCI stdcam
+ struct en50221_stdcam_llci *llci =
+ malloc(sizeof(struct en50221_stdcam_llci));
+ if (llci == NULL) {
+ return NULL;
+ }
+ memset(llci, 0, sizeof(struct en50221_stdcam_llci));
+
+ // create the sendfuncs
+ llci->sendfuncs.arg = sl;
+ llci->sendfuncs.send_data = (en50221_send_data) en50221_sl_send_data;
+ llci->sendfuncs.send_datav = (en50221_send_datav) en50221_sl_send_datav;
+
+ // create the resource manager resource
+ int resource_idx = 0;
+ llci->rm_resource = en50221_app_rm_create(&llci->sendfuncs);
+ en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_RM_RESOURCEID);
+ llci->resources[resource_idx].binary_resource_id = EN50221_APP_RM_RESOURCEID;
+ llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_rm_message;
+ llci->resources[resource_idx].arg = llci->rm_resource;
+ en50221_app_rm_register_enq_callback(llci->rm_resource, llci_rm_enq_callback, llci);
+ en50221_app_rm_register_reply_callback(llci->rm_resource, llci_rm_reply_callback, llci);
+ en50221_app_rm_register_changed_callback(llci->rm_resource, llci_rm_changed_callback, llci);
+ resource_idx++;
+
+ // create the datetime resource
+ llci->datetime_resource = en50221_app_datetime_create(&llci->sendfuncs);
+ en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_DATETIME_RESOURCEID);
+ llci->resources[resource_idx].binary_resource_id = EN50221_APP_DATETIME_RESOURCEID;
+ llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_datetime_message;
+ llci->resources[resource_idx].arg = llci->datetime_resource;
+ en50221_app_datetime_register_enquiry_callback(llci->datetime_resource, llci_datetime_enquiry_callback, llci);
+ resource_idx++;
+ llci->datetime_session_number = -1;
+ llci->datetime_response_interval = 0;
+ llci->datetime_next_send = 0;
+ llci->datetime_dvbtime = 0;
+
+ // create the application information resource
+ llci->stdcam.ai_resource = en50221_app_ai_create(&llci->sendfuncs);
+ en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_AI_RESOURCEID);
+ llci->resources[resource_idx].binary_resource_id = EN50221_APP_AI_RESOURCEID;
+ llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_ai_message;
+ llci->resources[resource_idx].arg = llci->stdcam.ai_resource;
+ llci->stdcam.ai_session_number = -1;
+ resource_idx++;
+
+ // create the CA resource
+ llci->stdcam.ca_resource = en50221_app_ca_create(&llci->sendfuncs);
+ en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_CA_RESOURCEID);
+ llci->resources[resource_idx].binary_resource_id = EN50221_APP_CA_RESOURCEID;
+ llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_ca_message;
+ llci->resources[resource_idx].arg = llci->stdcam.ca_resource;
+ llci->stdcam.ca_session_number = -1;
+ resource_idx++;
+
+ // create the MMI resource
+ llci->stdcam.mmi_resource = en50221_app_mmi_create(&llci->sendfuncs);
+ en50221_app_decode_public_resource_id(&llci->resources[resource_idx].resid, EN50221_APP_MMI_RESOURCEID);
+ llci->resources[resource_idx].binary_resource_id = EN50221_APP_MMI_RESOURCEID;
+ llci->resources[resource_idx].callback = (en50221_sl_resource_callback) en50221_app_mmi_message;
+ llci->resources[resource_idx].arg = llci->stdcam.mmi_resource;
+ llci->stdcam.mmi_session_number = -1;
+ resource_idx++;
+
+ // register session layer callbacks
+ en50221_sl_register_lookup_callback(sl, llci_lookup_callback, llci);
+ en50221_sl_register_session_callback(sl, llci_session_callback, llci);
+
+ // done
+ llci->stdcam.destroy = en50221_stdcam_llci_destroy;
+ llci->stdcam.poll = en50221_stdcam_llci_poll;
+ llci->stdcam.dvbtime = en50221_stdcam_llci_dvbtime;
+ llci->cafd = cafd;
+ llci->slotnum = slotnum;
+ llci->tl = tl;
+ llci->sl = sl;
+ llci->tl_slot_id = -1;
+ llci->state = EN50221_STDCAM_CAM_NONE;
+ return &llci->stdcam;
+}
+
+static void en50221_stdcam_llci_dvbtime(struct en50221_stdcam *stdcam, time_t dvbtime)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam;
+
+ llci->datetime_dvbtime = dvbtime;
+}
+
+static void en50221_stdcam_llci_destroy(struct en50221_stdcam *stdcam, int closefd)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam;
+
+ // "remove" the cam
+ llci_cam_removed(llci);
+
+ // destroy resources
+ if (llci->rm_resource)
+ en50221_app_rm_destroy(llci->rm_resource);
+ if (llci->datetime_resource)
+ en50221_app_datetime_destroy(llci->datetime_resource);
+ if (llci->stdcam.ai_resource)
+ en50221_app_ai_destroy(llci->stdcam.ai_resource);
+ if (llci->stdcam.ca_resource)
+ en50221_app_ca_destroy(llci->stdcam.ca_resource);
+ if (llci->stdcam.mmi_resource)
+ en50221_app_mmi_destroy(llci->stdcam.mmi_resource);
+
+ if (closefd)
+ close(llci->cafd);
+
+ free(llci);
+}
+
+
+
+
+static enum en50221_stdcam_status en50221_stdcam_llci_poll(struct en50221_stdcam *stdcam)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) stdcam;
+
+ switch(dvbca_get_cam_state(llci->cafd, llci->slotnum)) {
+ case DVBCA_CAMSTATE_MISSING:
+ if (llci->state != EN50221_STDCAM_CAM_NONE)
+ llci_cam_removed(llci);
+ break;
+
+ case DVBCA_CAMSTATE_READY:
+ if (llci->state == EN50221_STDCAM_CAM_NONE)
+ llci_cam_added(llci);
+ else if (llci->state == EN50221_STDCAM_CAM_INRESET)
+ llci_cam_in_reset(llci);
+ break;
+ }
+
+ // poll the stack
+ int error;
+ if ((error = en50221_tl_poll(llci->tl)) != 0) {
+ print(LOG_LEVEL, ERROR, 1, "Error reported by stack:%i\n", en50221_tl_get_error(llci->tl));
+ }
+
+ // send date/time response
+ if (llci->datetime_session_number != -1) {
+ time_t cur_time = time(NULL);
+ if (llci->datetime_response_interval && (cur_time > llci->datetime_next_send)) {
+ en50221_app_datetime_send(llci->datetime_resource,
+ llci->datetime_session_number,
+ llci->datetime_dvbtime, 0);
+ llci->datetime_next_send = cur_time + llci->datetime_response_interval;
+ }
+ }
+
+ return llci->state;
+}
+
+static void llci_cam_added(struct en50221_stdcam_llci *llci)
+{
+ // clear down any old structures
+ if (llci->tl_slot_id != -1) {
+ llci_cam_removed(llci);
+ }
+
+ // reset the CAM
+ dvbca_reset(llci->cafd, llci->slotnum);
+ llci->state = EN50221_STDCAM_CAM_INRESET;
+}
+
+static void llci_cam_in_reset(struct en50221_stdcam_llci *llci)
+{
+ if (dvbca_get_cam_state(llci->cafd, llci->slotnum) != DVBCA_CAMSTATE_READY) {
+ return;
+ }
+
+ // register the slot
+ if ((llci->tl_slot_id = en50221_tl_register_slot(llci->tl, llci->cafd, llci->slotnum,
+ LLCI_RESPONSE_TIMEOUT_MS, LLCI_POLL_DELAY_MS)) < 0) {
+ llci->state = EN50221_STDCAM_CAM_BAD;
+ return;
+ }
+
+ // create a new connection on the slot
+ if (en50221_tl_new_tc(llci->tl, llci->tl_slot_id) < 0) {
+ llci->state = EN50221_STDCAM_CAM_BAD;
+ llci->tl_slot_id = -1;
+ en50221_tl_destroy_slot(llci->tl, llci->tl_slot_id);
+ return;
+ }
+
+ llci->state = EN50221_STDCAM_CAM_OK;
+}
+
+static void llci_cam_removed(struct en50221_stdcam_llci *llci)
+{
+ if (llci->tl_slot_id != -1) {
+ en50221_tl_destroy_slot(llci->tl, llci->tl_slot_id);
+ llci->tl_slot_id = -1;
+ llci->datetime_session_number = -1;
+ llci->stdcam.ai_session_number = -1;
+ llci->stdcam.ca_session_number = -1;
+ llci->stdcam.mmi_session_number = -1;
+ }
+ llci->state = EN50221_STDCAM_CAM_NONE;
+}
+
+
+
+static int llci_lookup_callback(void *arg, uint8_t _slot_id, uint32_t requested_resource_id,
+ en50221_sl_resource_callback *callback_out, void **arg_out,
+ uint32_t *connected_resource_id)
+{
+ struct en50221_app_public_resource_id resid;
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+
+ // decode the resource id
+ if (!en50221_app_decode_public_resource_id(&resid, requested_resource_id)) {
+ return -1;
+ }
+
+ // try and find an instance of the resource
+ uint32_t i;
+ for(i=0; i<RESOURCE_IDS_COUNT; i++) {
+ if ((resid.resource_class == llci->resources[i].resid.resource_class) &&
+ (resid.resource_type == llci->resources[i].resid.resource_type)) {
+
+ // limit sessions to certain resources
+ switch(requested_resource_id) {
+ case EN50221_APP_DATETIME_RESOURCEID:
+ if (llci->datetime_session_number != -1)
+ return -3;
+ break;
+ case EN50221_APP_AI_RESOURCEID:
+ if (llci->stdcam.ai_session_number != -1)
+ return -3;
+ break;
+ case EN50221_APP_CA_RESOURCEID:
+ if (llci->stdcam.ca_session_number != -1)
+ return -3;
+ break;
+ case EN50221_APP_MMI_RESOURCEID:
+ if (llci->stdcam.mmi_session_number != -1)
+ return -3;
+ break;
+ }
+
+ // resource is ok.
+ *callback_out = llci->resources[i].callback;
+ *arg_out = llci->resources[i].arg;
+ *connected_resource_id = llci->resources[i].binary_resource_id;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+static int llci_session_callback(void *arg, int reason, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+
+ switch(reason) {
+ case S_SCALLBACK_REASON_CAMCONNECTED:
+ if (resource_id == EN50221_APP_RM_RESOURCEID) {
+ en50221_app_rm_enq(llci->rm_resource, session_number);
+ } else if (resource_id == EN50221_APP_DATETIME_RESOURCEID) {
+ llci->datetime_session_number = session_number;
+ } else if (resource_id == EN50221_APP_AI_RESOURCEID) {
+ en50221_app_ai_enquiry(llci->stdcam.ai_resource, session_number);
+ llci->stdcam.ai_session_number = session_number;
+ } else if (resource_id == EN50221_APP_CA_RESOURCEID) {
+ en50221_app_ca_info_enq(llci->stdcam.ca_resource, session_number);
+ llci->stdcam.ca_session_number = session_number;
+ } else if (resource_id == EN50221_APP_MMI_RESOURCEID) {
+ llci->stdcam.mmi_session_number = session_number;
+ }
+
+ break;
+ case S_SCALLBACK_REASON_CLOSE:
+ if (resource_id == EN50221_APP_MMI_RESOURCEID) {
+ llci->stdcam.mmi_session_number = -1;
+ }
+
+ break;
+ }
+ return 0;
+}
+
+static int llci_rm_enq_callback(void *arg, uint8_t _slot_id, uint16_t session_number)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+
+ if (en50221_app_rm_reply(llci->rm_resource, session_number, RESOURCE_IDS_COUNT, resource_ids)) {
+ print(LOG_LEVEL, ERROR, 1, "Failed to send RM ENQ on slot %02x\n", _slot_id);
+ }
+ return 0;
+}
+
+static int llci_rm_reply_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint32_t resource_id_count, uint32_t *_resource_ids)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+ (void) resource_id_count;
+ (void) _resource_ids;
+
+ if (en50221_app_rm_changed(llci->rm_resource, session_number)) {
+ print(LOG_LEVEL, ERROR, 1, "Failed to send RM REPLY on slot %02x\n", _slot_id);
+ }
+ return 0;
+}
+
+static int llci_rm_changed_callback(void *arg, uint8_t _slot_id, uint16_t session_number)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+
+ if (en50221_app_rm_enq(llci->rm_resource, session_number)) {
+ print(LOG_LEVEL, ERROR, 1, "Failed to send RM CHANGED on slot %02x\n", _slot_id);
+ }
+ return 0;
+}
+
+static int llci_datetime_enquiry_callback(void *arg, uint8_t _slot_id, uint16_t session_number, uint8_t response_interval)
+{
+ struct en50221_stdcam_llci *llci = (struct en50221_stdcam_llci *) arg;
+ (void) _slot_id;
+
+ llci->datetime_response_interval = response_interval;
+ llci->datetime_next_send = 0;
+ if (response_interval) {
+ llci->datetime_next_send = time(NULL) + response_interval;
+ }
+ en50221_app_datetime_send(llci->datetime_resource, session_number, llci->datetime_dvbtime, 0);
+
+ return 0;
+}
diff --git a/lib/libdvben50221/en50221_transport.c b/lib/libdvben50221/en50221_transport.c
new file mode 100644
index 0000000..f6f46db
--- /dev/null
+++ b/lib/libdvben50221/en50221_transport.c
@@ -0,0 +1,1296 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 transport layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <time.h>
+#include <libdvbmisc/dvbmisc.h>
+#include <libdvbapi/dvbca.h>
+#include "en50221_errno.h"
+#include "en50221_transport.h"
+#include "asn_1.h"
+
+// these are the Transport Tags, like
+// described in EN50221, Annex A.4.1.13 (pg70)
+#define T_SB 0x80 // sb primitive h<--m
+#define T_RCV 0x81 // receive primitive h-->m
+#define T_CREATE_T_C 0x82 // create transport connection primitive h-->m
+#define T_C_T_C_REPLY 0x83 // ctc reply primitive h<--m
+#define T_DELETE_T_C 0x84 // delete tc primitive h<->m
+#define T_D_T_C_REPLY 0x85 // dtc reply primitive h<->m
+#define T_REQUEST_T_C 0x86 // request transport connection primitive h<--m
+#define T_NEW_T_C 0x87 // new tc / reply to t_request primitive h-->m
+#define T_T_C_ERROR 0x77 // error creating tc primitive h-->m
+#define T_DATA_LAST 0xA0 // convey data from higher constructed h<->m
+ // layers
+#define T_DATA_MORE 0xA1 // convey data from higher constructed h<->m
+ // layers
+
+struct en50221_message {
+ struct en50221_message *next;
+ uint32_t length;
+ uint8_t data[0];
+};
+
+struct en50221_connection {
+ uint32_t state; // the current state: idle/in_delete/in_create/active
+ struct timeval tx_time; // time last request was sent from host->module, or 0 if ok
+ struct timeval last_poll_time; // time of last poll transmission
+ uint8_t *chain_buffer; // used to save parts of chained packets
+ uint32_t buffer_length;
+
+ struct en50221_message *send_queue;
+ struct en50221_message *send_queue_tail;
+};
+
+struct en50221_slot {
+ int ca_hndl;
+ uint8_t slot; // CAM slot
+ struct en50221_connection *connections;
+
+ pthread_mutex_t slot_lock;
+
+ uint32_t response_timeout;
+ uint32_t poll_delay;
+};
+
+struct en50221_transport_layer {
+ uint8_t max_slots;
+ uint8_t max_connections_per_slot;
+ struct en50221_slot *slots;
+ struct pollfd *slot_pollfds;
+ int slots_changed;
+
+ pthread_mutex_t global_lock;
+ pthread_mutex_t setcallback_lock;
+
+ int error;
+ int error_slot;
+
+ en50221_tl_callback callback;
+ void *callback_arg;
+};
+
+static int en50221_tl_process_data(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t * data,
+ uint32_t data_length);
+static int en50221_tl_poll_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id);
+static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id);
+static void queue_message(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ struct en50221_message *msg);
+static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer
+ *tl, uint8_t slot_id,
+ uint8_t connection_id);
+static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id);
+static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer
+ *tl, uint8_t slot_id,
+ uint8_t connection_id);
+static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id);
+static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ uint8_t * data,
+ uint32_t data_length);
+static int en50221_tl_handle_sb(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ uint8_t * data, uint32_t data_length);
+
+
+struct en50221_transport_layer *en50221_tl_create(uint8_t max_slots,
+ uint8_t
+ max_connections_per_slot)
+{
+ struct en50221_transport_layer *tl = NULL;
+ int i;
+ int j;
+
+ // setup structure
+ tl = (struct en50221_transport_layer *)
+ malloc(sizeof(struct en50221_transport_layer));
+ if (tl == NULL)
+ goto error_exit;
+ tl->max_slots = max_slots;
+ tl->max_connections_per_slot = max_connections_per_slot;
+ tl->slots = NULL;
+ tl->slot_pollfds = NULL;
+ tl->slots_changed = 1;
+ tl->callback = NULL;
+ tl->callback_arg = NULL;
+ tl->error_slot = 0;
+ tl->error = 0;
+ pthread_mutex_init(&tl->global_lock, NULL);
+ pthread_mutex_init(&tl->setcallback_lock, NULL);
+
+ // create the slots
+ tl->slots = malloc(sizeof(struct en50221_slot) * max_slots);
+ if (tl->slots == NULL)
+ goto error_exit;
+
+ // set them up
+ for (i = 0; i < max_slots; i++) {
+ tl->slots[i].ca_hndl = -1;
+
+ // create the connections for this slot
+ tl->slots[i].connections =
+ malloc(sizeof(struct en50221_connection) * max_connections_per_slot);
+ if (tl->slots[i].connections == NULL)
+ goto error_exit;
+
+ // create a mutex for the slot
+ pthread_mutex_init(&tl->slots[i].slot_lock, NULL);
+
+ // set them up
+ for (j = 0; j < max_connections_per_slot; j++) {
+ tl->slots[i].connections[j].state = T_STATE_IDLE;
+ tl->slots[i].connections[j].tx_time.tv_sec = 0;
+ tl->slots[i].connections[j].last_poll_time.tv_sec = 0;
+ tl->slots[i].connections[j].last_poll_time.tv_usec = 0;
+ tl->slots[i].connections[j].chain_buffer = NULL;
+ tl->slots[i].connections[j].buffer_length = 0;
+ tl->slots[i].connections[j].send_queue = NULL;
+ tl->slots[i].connections[j].send_queue_tail = NULL;
+ }
+ }
+
+ // create the pollfds
+ tl->slot_pollfds = malloc(sizeof(struct pollfd) * max_slots);
+ if (tl->slot_pollfds == NULL) {
+ goto error_exit;
+ }
+ memset(tl->slot_pollfds, 0, sizeof(struct pollfd) * max_slots);
+
+ return tl;
+
+ error_exit:
+ en50221_tl_destroy(tl);
+ return NULL;
+}
+
+// Destroy an instance of the transport layer
+void en50221_tl_destroy(struct en50221_transport_layer *tl)
+{
+ int i, j;
+
+ if (tl) {
+ if (tl->slots) {
+ for (i = 0; i < tl->max_slots; i++) {
+ if (tl->slots[i].connections) {
+ for (j = 0; j < tl->max_connections_per_slot; j++) {
+ if (tl->slots[i].connections[j].chain_buffer) {
+ free(tl->slots[i].connections[j].chain_buffer);
+ }
+
+ struct en50221_message *cur_msg =
+ tl->slots[i].connections[j].send_queue;
+ while (cur_msg) {
+ struct en50221_message *next_msg = cur_msg->next;
+ free(cur_msg);
+ cur_msg = next_msg;
+ }
+ tl->slots[i].connections[j].send_queue = NULL;
+ tl->slots[i].connections[j].send_queue_tail = NULL;
+ }
+ free(tl->slots[i].connections);
+ pthread_mutex_destroy(&tl->slots[i].slot_lock);
+ }
+ }
+ free(tl->slots);
+ }
+ if (tl->slot_pollfds) {
+ free(tl->slot_pollfds);
+ }
+ pthread_mutex_destroy(&tl->setcallback_lock);
+ pthread_mutex_destroy(&tl->global_lock);
+ free(tl);
+ }
+}
+
+// this can be called from the user-space app to
+// register new slots that we should work with
+int en50221_tl_register_slot(struct en50221_transport_layer *tl,
+ int ca_hndl, uint8_t slot,
+ uint32_t response_timeout,
+ uint32_t poll_delay)
+{
+ // lock
+ pthread_mutex_lock(&tl->global_lock);
+
+ // we browse through the array of slots
+ // to look for the first unused one
+ int i;
+ int16_t slot_id = -1;
+ for (i = 0; i < tl->max_slots; i++) {
+ if (tl->slots[i].ca_hndl == -1) {
+ slot_id = i;
+ break;
+ }
+ }
+ if (slot_id == -1) {
+ tl->error = EN50221ERR_OUTOFSLOTS;
+ pthread_mutex_unlock(&tl->global_lock);
+ return -1;
+ }
+ // set up the slot struct
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ tl->slots[slot_id].ca_hndl = ca_hndl;
+ tl->slots[slot_id].slot = slot;
+ tl->slots[slot_id].response_timeout = response_timeout;
+ tl->slots[slot_id].poll_delay = poll_delay;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+
+ tl->slots_changed = 1;
+ pthread_mutex_unlock(&tl->global_lock);
+ return slot_id;
+}
+
+void en50221_tl_destroy_slot(struct en50221_transport_layer *tl,
+ uint8_t slot_id)
+{
+ int i;
+
+ if (slot_id >= tl->max_slots)
+ return;
+
+ // lock
+ pthread_mutex_lock(&tl->global_lock);
+
+ // clear the slot
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ tl->slots[slot_id].ca_hndl = -1;
+ for (i = 0; i < tl->max_connections_per_slot; i++) {
+ tl->slots[slot_id].connections[i].state = T_STATE_IDLE;
+ tl->slots[slot_id].connections[i].tx_time.tv_sec = 0;
+ tl->slots[slot_id].connections[i].last_poll_time.tv_sec = 0;
+ tl->slots[slot_id].connections[i].last_poll_time.tv_usec = 0;
+ if (tl->slots[slot_id].connections[i].chain_buffer) {
+ free(tl->slots[slot_id].connections[i].
+ chain_buffer);
+ }
+ tl->slots[slot_id].connections[i].chain_buffer = NULL;
+ tl->slots[slot_id].connections[i].buffer_length = 0;
+
+ struct en50221_message *cur_msg =
+ tl->slots[slot_id].connections[i].send_queue;
+ while (cur_msg) {
+ struct en50221_message *next_msg = cur_msg->next;
+ free(cur_msg);
+ cur_msg = next_msg;
+ }
+ tl->slots[slot_id].connections[i].send_queue = NULL;
+ tl->slots[slot_id].connections[i].send_queue_tail = NULL;
+ }
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+
+ // tell upper layers
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, T_CALLBACK_REASON_SLOTCLOSE, NULL, 0, slot_id, 0);
+
+ tl->slots_changed = 1;
+ pthread_mutex_unlock(&tl->global_lock);
+}
+
+int en50221_tl_poll(struct en50221_transport_layer *tl)
+{
+ uint8_t data[4096];
+ int slot_id;
+ int j;
+
+ // make up pollfds if the slots have changed
+ pthread_mutex_lock(&tl->global_lock);
+ if (tl->slots_changed) {
+ for (slot_id = 0; slot_id < tl->max_slots; slot_id++) {
+ if (tl->slots[slot_id].ca_hndl != -1) {
+ tl->slot_pollfds[slot_id].fd = tl->slots[slot_id].ca_hndl;
+ tl->slot_pollfds[slot_id].events = POLLIN | POLLPRI | POLLERR;
+ tl->slot_pollfds[slot_id].revents = 0;
+ } else {
+ tl->slot_pollfds[slot_id].fd = 0;
+ tl->slot_pollfds[slot_id].events = 0;
+ tl->slot_pollfds[slot_id].revents = 0;
+ }
+ }
+ tl->slots_changed = 0;
+ }
+ pthread_mutex_unlock(&tl->global_lock);
+
+ // anything happened?
+ if (poll(tl->slot_pollfds, tl->max_slots, 10) < 0) {
+ tl->error_slot = -1;
+ tl->error = EN50221ERR_CAREAD;
+ return -1;
+ }
+ // go through all slots (even though poll may not have reported any events
+ for (slot_id = 0; slot_id < tl->max_slots; slot_id++) {
+
+ // check if this slot is still used and get its handle
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ continue;
+ }
+ int ca_hndl = tl->slots[slot_id].ca_hndl;
+
+ if (tl->slot_pollfds[slot_id].revents & (POLLPRI | POLLIN)) {
+ // read data
+ uint8_t r_slot_id;
+ uint8_t connection_id;
+ int readcnt = dvbca_link_read(ca_hndl, &r_slot_id,
+ &connection_id,
+ data, sizeof(data));
+ if (readcnt < 0) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAREAD;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // process it if we got some
+ if (readcnt > 0) {
+ if (tl->slots[slot_id].slot != r_slot_id) {
+ // this message is for an other CAM of the same CA
+ int new_slot_id;
+ for (new_slot_id = 0; new_slot_id < tl->max_slots; new_slot_id++) {
+ if ((tl->slots[new_slot_id].ca_hndl == ca_hndl) &&
+ (tl->slots[new_slot_id].slot == r_slot_id))
+ break;
+ }
+ if (new_slot_id != tl->max_slots) {
+ // we found the requested CAM
+ pthread_mutex_lock(&tl->slots[new_slot_id].slot_lock);
+ if (en50221_tl_process_data(tl, new_slot_id, data, readcnt)) {
+ pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock);
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ pthread_mutex_unlock(&tl->slots[new_slot_id].slot_lock);
+ } else {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ } else
+ if (en50221_tl_process_data(tl, slot_id, data, readcnt)) {
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ }
+ } else if (tl->slot_pollfds[slot_id].revents & POLLERR) {
+ // an error was reported
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAREAD;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // poll the connections on this slot + check for timeouts
+ for (j = 0; j < tl->max_connections_per_slot; j++) {
+ // ignore connection if idle
+ if (tl->slots[slot_id].connections[j].state == T_STATE_IDLE) {
+ continue;
+ }
+ // send queued data
+ if (tl->slots[slot_id].connections[j].state &
+ (T_STATE_IN_CREATION | T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) {
+ // send data if there is some to go and we're not waiting for a response already
+ if (tl->slots[slot_id].connections[j].send_queue &&
+ (tl->slots[slot_id].connections[j].tx_time.tv_sec == 0)) {
+
+ // get the message
+ struct en50221_message *msg =
+ tl->slots[slot_id].connections[j].send_queue;
+ if (msg->next != NULL) {
+ tl->slots[slot_id].connections[j].send_queue = msg->next;
+ } else {
+ tl->slots[slot_id].connections[j].send_queue = NULL;
+ tl->slots[slot_id].connections[j].send_queue_tail = NULL;
+ }
+
+ // send the message
+ if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
+ tl->slots[slot_id].slot,
+ j,
+ msg->data, msg->length) < 0) {
+ free(msg);
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ print(LOG_LEVEL, ERROR, 1, "CAWrite failed");
+ return -1;
+ }
+ gettimeofday(&tl->slots[slot_id].connections[j].tx_time, 0);
+
+ // fixup connection state for T_DELETE_T_C
+ if (msg->length && (msg->data[0] == T_DELETE_T_C)) {
+ tl->slots[slot_id].connections[j].state = T_STATE_IN_DELETION;
+ if (tl->slots[slot_id].connections[j].chain_buffer) {
+ free(tl->slots[slot_id].connections[j].chain_buffer);
+ }
+ tl->slots[slot_id].connections[j].chain_buffer = NULL;
+ tl->slots[slot_id].connections[j].buffer_length = 0;
+ }
+
+ free(msg);
+ }
+ }
+ // poll it if we're not expecting a reponse and the poll time has elapsed
+ if (tl->slots[slot_id].connections[j].state & T_STATE_ACTIVE) {
+ if ((tl->slots[slot_id].connections[j].tx_time.tv_sec == 0) &&
+ (time_after(tl->slots[slot_id].connections[j].last_poll_time,
+ tl->slots[slot_id].poll_delay))) {
+
+ gettimeofday(&tl->slots[slot_id].connections[j].last_poll_time, 0);
+ if (en50221_tl_poll_tc(tl, slot_id, j)) {
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ }
+ }
+
+ // check for timeouts - in any state
+ if (tl->slots[slot_id].connections[j].tx_time.tv_sec &&
+ (time_after(tl->slots[slot_id].connections[j].tx_time,
+ tl->slots[slot_id].response_timeout))) {
+
+ if (tl->slots[slot_id].connections[j].state &
+ (T_STATE_IN_CREATION |T_STATE_IN_DELETION)) {
+ tl->slots[slot_id].connections[j].state = T_STATE_IDLE;
+ } else if (tl->slots[slot_id].connections[j].state &
+ (T_STATE_ACTIVE | T_STATE_ACTIVE_DELETEQUEUED)) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_TIMEOUT;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ }
+ }
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ }
+
+ return 0;
+}
+
+void en50221_tl_register_callback(struct en50221_transport_layer *tl,
+ en50221_tl_callback callback, void *arg)
+{
+ pthread_mutex_lock(&tl->setcallback_lock);
+ tl->callback = callback;
+ tl->callback_arg = arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+}
+
+int en50221_tl_get_error_slot(struct en50221_transport_layer *tl)
+{
+ return tl->error_slot;
+}
+
+int en50221_tl_get_error(struct en50221_transport_layer *tl)
+{
+ return tl->error;
+}
+
+int en50221_tl_send_data(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ uint8_t * data, uint32_t data_size)
+{
+#ifdef DEBUG_TXDATA
+ printf("[[[[[[[[[[[[[[[[[[[[\n");
+ uint32_t ii = 0;
+ for (ii = 0; ii < data_size; ii++) {
+ printf("%02x: %02x\n", ii, data[ii]);
+ }
+ printf("]]]]]]]]]]]]]]]]]]]]\n");
+#endif
+
+ if (slot_id >= tl->max_slots) {
+ tl->error = EN50221ERR_BADSLOTID;
+ return -1;
+ }
+
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (connection_id >= tl->max_connections_per_slot) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // allocate msg structure
+ struct en50221_message *msg =
+ malloc(sizeof(struct en50221_message) + data_size + 10);
+ if (msg == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // make up data to send
+ int length_field_len;
+ msg->data[0] = T_DATA_LAST;
+ if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) {
+ free(msg);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_ASNENCODE;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ msg->data[1 + length_field_len] = connection_id;
+ memcpy(msg->data + 1 + length_field_len + 1, data, data_size);
+ msg->length = 1 + length_field_len + 1 + data_size;
+
+ // queue it for transmission
+ queue_message(tl, slot_id, connection_id, msg);
+
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return 0;
+}
+
+int en50221_tl_send_datav(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ struct iovec *vector, int iov_count)
+{
+#ifdef DEBUG_TXDATA
+ printf("[[[[[[[[[[[[[[[[[[[[\n");
+ uint32_t ii = 0;
+ uint32_t iipos = 0;
+ for (ii = 0; ii < (uint32_t) iov_count; ii++) {
+ uint32_t jj;
+ for (jj = 0; jj < vector[ii].iov_len; jj++) {
+ printf("%02x: %02x\n", jj + iipos,
+ *((uint8_t *) (vector[ii].iov_base) + jj));
+ }
+ iipos += vector[ii].iov_len;
+ }
+ printf("]]]]]]]]]]]]]]]]]]]]\n");
+#endif
+
+ if (slot_id >= tl->max_slots) {
+ tl->error = EN50221ERR_BADSLOTID;
+ return -1;
+ }
+
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (connection_id >= tl->max_connections_per_slot) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // calculate the total length of the data to send
+ uint32_t data_size = 0;
+ int i;
+ for (i = 0; i < iov_count; i++) {
+ data_size += vector[i].iov_len;
+ }
+
+ // allocate msg structure
+ struct en50221_message *msg =
+ malloc(sizeof(struct en50221_message) + data_size + 10);
+ if (msg == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // make up data to send
+ int length_field_len;
+ msg->data[0] = T_DATA_LAST;
+ if ((length_field_len = asn_1_encode(data_size + 1, msg->data + 1, 3)) < 0) {
+ free(msg);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_ASNENCODE;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ msg->data[1 + length_field_len] = connection_id;
+ msg->length = 1 + length_field_len + 1 + data_size;
+ msg->next = NULL;
+
+ // merge the iovecs
+ uint32_t pos = 1 + length_field_len + 1;
+ for (i = 0; i < iov_count; i++) {
+ memcpy(msg->data + pos, vector[i].iov_base,
+ vector[i].iov_len);
+ pos += vector[i].iov_len;
+ }
+
+ // queue it for transmission
+ queue_message(tl, slot_id, connection_id, msg);
+
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return 0;
+}
+
+int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id)
+{
+ // check
+ if (slot_id >= tl->max_slots) {
+ tl->error = EN50221ERR_BADSLOTID;
+ return -1;
+ }
+
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // allocate a new connection if possible
+ int conid = en50221_tl_alloc_new_tc(tl, slot_id);
+ if (conid == -1) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFCONNECTIONS;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // allocate msg structure
+ struct en50221_message *msg =
+ malloc(sizeof(struct en50221_message) + 3);
+ if (msg == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // make up the data to send
+ msg->data[0] = T_CREATE_T_C;
+ msg->data[1] = 1;
+ msg->data[2] = conid;
+ msg->length = 3;
+ msg->next = NULL;
+
+ // queue it for transmission
+ queue_message(tl, slot_id, conid, msg);
+
+ // done
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return conid;
+}
+
+int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // check
+ if (slot_id >= tl->max_slots) {
+ tl->error = EN50221ERR_BADSLOTID;
+ return -1;
+ }
+
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (connection_id >= tl->max_connections_per_slot) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (!(tl->slots[slot_id].connections[connection_id].state &
+ (T_STATE_ACTIVE | T_STATE_IN_DELETION))) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADSTATE;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // allocate msg structure
+ struct en50221_message *msg =
+ malloc(sizeof(struct en50221_message) + 3);
+ if (msg == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ // make up the data to send
+ msg->data[0] = T_DELETE_T_C;
+ msg->data[1] = 1;
+ msg->data[2] = connection_id;
+ msg->length = 3;
+ msg->next = NULL;
+
+ // queue it for transmission
+ queue_message(tl, slot_id, connection_id, msg);
+ tl->slots[slot_id].connections[connection_id].state =
+ T_STATE_ACTIVE_DELETEQUEUED;
+
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return 0;
+}
+
+int en50221_tl_get_connection_state(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id)
+{
+ if (slot_id >= tl->max_slots) {
+ tl->error = EN50221ERR_BADSLOTID;
+ return -1;
+ }
+
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ if (tl->slots[slot_id].ca_hndl == -1) {
+ tl->error = EN50221ERR_BADSLOTID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ if (connection_id >= tl->max_connections_per_slot) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+ return -1;
+ }
+ int state = tl->slots[slot_id].connections[connection_id].state;
+ pthread_mutex_unlock(&tl->slots[slot_id].slot_lock);
+
+ return state;
+}
+
+
+
+
+// ask the module for new data
+static int en50221_tl_poll_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id)
+{
+ gettimeofday(&tl->slots[slot_id].connections[connection_id].
+ tx_time, 0);
+
+ // send command
+ uint8_t hdr[3];
+ hdr[0] = T_DATA_LAST;
+ hdr[1] = 1;
+ hdr[2] = connection_id;
+ if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
+ tl->slots[slot_id].slot,
+ connection_id, hdr, 3) < 0) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ return 0;
+}
+
+// handle incoming data
+static int en50221_tl_process_data(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t * data,
+ uint32_t data_length)
+{
+ int result;
+
+#ifdef DEBUG_RXDATA
+ printf("-------------------\n");
+ uint32_t ii = 0;
+ for (ii = 0; ii < data_length; ii++) {
+ printf("%02x: %02x\n", ii, data[ii]);
+ }
+ printf("+++++++++++++++++++\n");
+#endif
+
+ // process the received data
+ while (data_length) {
+ // parse the header
+ uint8_t tpdu_tag = data[0];
+ uint16_t asn_data_length;
+ int length_field_len;
+ if ((length_field_len = asn_1_decode(&asn_data_length, data + 1, data_length - 1)) < 0) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid asn from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ if ((asn_data_length < 1) ||
+ (asn_data_length > (data_length - (1 + length_field_len)))) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received data with invalid length from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ uint8_t connection_id = data[1 + length_field_len];
+ data += 1 + length_field_len + 1;
+ data_length -= (1 + length_field_len + 1);
+ asn_data_length--;
+
+ // check the connection_id
+ if (connection_id >= tl->max_connections_per_slot) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received bad connection id %02x from module on slot %02x\n",
+ connection_id, slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCONNECTIONID;
+ return -1;
+ }
+ // process the TPDUs
+ switch (tpdu_tag) {
+ case T_C_T_C_REPLY:
+ if ((result = en50221_tl_handle_create_tc_reply(tl, slot_id, connection_id)) < 0) {
+ return -1;
+ }
+ break;
+ case T_DELETE_T_C:
+ if ((result = en50221_tl_handle_delete_tc(tl, slot_id, connection_id)) < 0) {
+ return -1;
+ }
+ break;
+ case T_D_T_C_REPLY:
+ if ((result = en50221_tl_handle_delete_tc_reply(tl, slot_id, connection_id)) < 0) {
+ return -1;
+ }
+ break;
+ case T_REQUEST_T_C:
+ if ((result = en50221_tl_handle_request_tc(tl, slot_id, connection_id)) < 0) {
+ return -1;
+ }
+ break;
+ case T_DATA_MORE:
+ if ((result = en50221_tl_handle_data_more(tl, slot_id,
+ connection_id,
+ data,
+ asn_data_length)) < 0) {
+ return -1;
+ }
+ break;
+ case T_DATA_LAST:
+ if ((result = en50221_tl_handle_data_last(tl, slot_id,
+ connection_id,
+ data,
+ asn_data_length)) < 0) {
+ return -1;
+ }
+ break;
+ case T_SB:
+ if ((result = en50221_tl_handle_sb(tl, slot_id,
+ connection_id,
+ data,
+ asn_data_length)) < 0) {
+ return -1;
+ }
+ break;
+ default:
+ print(LOG_LEVEL, ERROR, 1,
+ "Recieved unexpected TPDU tag %02x from module on slot %02x\n",
+ tpdu_tag, slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+
+ // skip over the consumed data
+ data += asn_data_length;
+ data_length -= asn_data_length;
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_create_tc_reply(struct en50221_transport_layer
+ *tl, uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // set this connection to state active
+ if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_CREATION) {
+ tl->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE;
+ tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
+
+ // tell upper layers
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, T_CALLBACK_REASON_CONNECTIONOPEN, NULL, 0, slot_id, connection_id);
+ } else {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_C_T_C_REPLY for connection not in "
+ "T_STATE_IN_CREATION from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_delete_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // immediately delete this connection and send D_T_C_REPLY
+ if (tl->slots[slot_id].connections[connection_id].state &
+ (T_STATE_ACTIVE | T_STATE_IN_DELETION)) {
+ // clear down the slot
+ tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE;
+ if (tl->slots[slot_id].connections[connection_id].chain_buffer) {
+ free(tl->slots[slot_id].connections[connection_id].chain_buffer);
+ }
+ tl->slots[slot_id].connections[connection_id].chain_buffer = NULL;
+ tl->slots[slot_id].connections[connection_id].buffer_length = 0;
+
+ // send the reply
+ uint8_t hdr[3];
+ hdr[0] = T_D_T_C_REPLY;
+ hdr[1] = 1;
+ hdr[2] = connection_id;
+ if (dvbca_link_write(tl->slots[slot_id].ca_hndl,
+ tl->slots[slot_id].slot,
+ connection_id, hdr, 3) < 0) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ // tell upper layers
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, T_CALLBACK_REASON_CONNECTIONCLOSE, NULL, 0, slot_id, connection_id);
+ } else {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_DELETE_T_C for inactive connection from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer
+ *tl, uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // delete this connection, should be in T_STATE_IN_DELETION already
+ if (tl->slots[slot_id].connections[connection_id].state == T_STATE_IN_DELETION) {
+ tl->slots[slot_id].connections[connection_id].state = T_STATE_IDLE;
+ } else {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_D_T_C_REPLY received for connection not in "
+ "T_STATE_IN_DELETION from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_request_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id)
+{
+ // allocate a new connection if possible
+ int conid = en50221_tl_alloc_new_tc(tl, slot_id);
+ int ca_hndl = tl->slots[slot_id].ca_hndl;
+ if (conid == -1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Too many connections requested by module on slot %02x\n",
+ slot_id);
+
+ // send the error
+ uint8_t hdr[4];
+ hdr[0] = T_T_C_ERROR;
+ hdr[1] = 2;
+ hdr[2] = connection_id;
+ hdr[3] = 1;
+ if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ tl->slots[slot_id].connections[connection_id].tx_time.
+ tv_sec = 0;
+ } else {
+ // send the NEW_T_C on the connection we received it on
+ uint8_t hdr[4];
+ hdr[0] = T_NEW_T_C;
+ hdr[1] = 2;
+ hdr[2] = connection_id;
+ hdr[3] = conid;
+ if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
+ tl->slots[slot_id].connections[conid].state = T_STATE_IDLE;
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
+
+ // send the CREATE_T_C on the new connnection
+ hdr[0] = T_CREATE_T_C;
+ hdr[1] = 1;
+ hdr[2] = conid;
+ if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, conid, hdr, 3) < 0) {
+ tl->slots[slot_id].connections[conid].state = T_STATE_IDLE;
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ gettimeofday(&tl->slots[slot_id].connections[conid].tx_time, 0);
+
+ // tell upper layers
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+ if (cb)
+ cb(cb_arg, T_CALLBACK_REASON_CAMCONNECTIONOPEN, NULL, 0, slot_id, conid);
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_data_more(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // connection in correct state?
+ if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_DATA_MORE for connection not in "
+ "T_STATE_ACTIVE from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ // a chained data packet is coming in, save
+ // it to the buffer and wait for more
+ tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
+ int new_data_length =
+ tl->slots[slot_id].connections[connection_id].buffer_length + data_length;
+ uint8_t *new_data_buffer =
+ realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
+ if (new_data_buffer == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ return -1;
+ }
+ tl->slots[slot_id].connections[connection_id].chain_buffer = new_data_buffer;
+
+ memcpy(tl->slots[slot_id].connections[connection_id].chain_buffer +
+ tl->slots[slot_id].connections[connection_id].buffer_length,
+ data, data_length);
+ tl->slots[slot_id].connections[connection_id].buffer_length = new_data_length;
+
+ return 0;
+}
+
+static int en50221_tl_handle_data_last(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ uint8_t * data,
+ uint32_t data_length)
+{
+ // connection in correct state?
+ if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_DATA_LAST received for connection not in "
+ "T_STATE_ACTIVE from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ // last package of a chain or single package comes in
+ tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
+ if (tl->slots[slot_id].connections[connection_id].chain_buffer == NULL) {
+ // single package => dispatch immediately
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+
+ if (cb && data_length) {
+ pthread_mutex_unlock(&tl->slots[slot_id].
+ slot_lock);
+ cb(cb_arg, T_CALLBACK_REASON_DATA, data, data_length, slot_id, connection_id);
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ }
+ } else {
+ int new_data_length =
+ tl->slots[slot_id].connections[connection_id].buffer_length + data_length;
+ uint8_t *new_data_buffer =
+ realloc(tl->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
+ if (new_data_buffer == NULL) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_OUTOFMEMORY;
+ return -1;
+ }
+
+ memcpy(new_data_buffer +
+ tl->slots[slot_id].connections[connection_id].
+ buffer_length, data, data_length);
+
+ // clean the buffer position
+ tl->slots[slot_id].connections[connection_id].chain_buffer = NULL;
+ tl->slots[slot_id].connections[connection_id].buffer_length = 0;
+
+ // tell the upper layers
+ pthread_mutex_lock(&tl->setcallback_lock);
+ en50221_tl_callback cb = tl->callback;
+ void *cb_arg = tl->callback_arg;
+ pthread_mutex_unlock(&tl->setcallback_lock);
+ if (cb && data_length) {
+ pthread_mutex_unlock(&tl->slots[slot_id].
+ slot_lock);
+ cb(cb_arg, T_CALLBACK_REASON_DATA, new_data_buffer,
+ new_data_length, slot_id, connection_id);
+ pthread_mutex_lock(&tl->slots[slot_id].slot_lock);
+ }
+
+ free(new_data_buffer);
+ }
+
+ return 0;
+}
+
+static int en50221_tl_handle_sb(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ uint8_t * data, uint32_t data_length)
+{
+ // is the connection id ok?
+ if (tl->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Received T_SB for connection not in T_STATE_ACTIVE from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ // did we get enough data in the T_SB?
+ if (data_length != 1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "Recieved T_SB with invalid length from module on slot %02x\n",
+ slot_id);
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_BADCAMDATA;
+ return -1;
+ }
+ // tell it to send the data if it says there is some
+ if (data[0] & 0x80) {
+ int ca_hndl = tl->slots[slot_id].ca_hndl;
+
+ // send the RCV
+ uint8_t hdr[3];
+ hdr[0] = T_RCV;
+ hdr[1] = 1;
+ hdr[2] = connection_id;
+ if (dvbca_link_write(ca_hndl, tl->slots[slot_id].slot, connection_id, hdr, 3) < 0) {
+ tl->error_slot = slot_id;
+ tl->error = EN50221ERR_CAWRITE;
+ return -1;
+ }
+ gettimeofday(&tl->slots[slot_id].connections[connection_id].tx_time, 0);
+
+ } else {
+ // no data - indicate not waiting for anything now
+ tl->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
+ }
+
+ return 0;
+}
+
+static int en50221_tl_alloc_new_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id)
+{
+ // we browse through the array of connection
+ // types, to look for the first unused one
+ int i, conid = -1;
+ for (i = 1; i < tl->max_connections_per_slot; i++) {
+ if (tl->slots[slot_id].connections[i].state == T_STATE_IDLE) {
+ conid = i;
+ break;
+ }
+ }
+ if (conid == -1) {
+ print(LOG_LEVEL, ERROR, 1,
+ "CREATE_T_C failed: no more connections available\n");
+ return -1;
+ }
+ // set up the connection struct
+ tl->slots[slot_id].connections[conid].state = T_STATE_IN_CREATION;
+ tl->slots[slot_id].connections[conid].chain_buffer = NULL;
+ tl->slots[slot_id].connections[conid].buffer_length = 0;
+
+ return conid;
+}
+
+static void queue_message(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ struct en50221_message *msg)
+{
+ msg->next = NULL;
+ if (tl->slots[slot_id].connections[connection_id].send_queue_tail) {
+ tl->slots[slot_id].connections[connection_id].send_queue_tail->next = msg;
+ tl->slots[slot_id].connections[connection_id].send_queue_tail = msg;
+ } else {
+ tl->slots[slot_id].connections[connection_id].send_queue = msg;
+ tl->slots[slot_id].connections[connection_id].send_queue_tail = msg;
+ }
+}
diff --git a/lib/libdvben50221/en50221_transport.h b/lib/libdvben50221/en50221_transport.h
new file mode 100644
index 0000000..7882060
--- /dev/null
+++ b/lib/libdvben50221/en50221_transport.h
@@ -0,0 +1,234 @@
+/*
+ en50221 encoder An implementation for libdvb
+ an implementation for the en50221 session layer
+
+ Copyright (C) 2004, 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2005 Julian Scheel (julian at jusst dot de)
+ Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+
+ This library is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of
+ the License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+
+#ifndef __EN50221_TRANSPORT_H__
+#define __EN50221_TRANSPORT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/uio.h>
+
+/**
+ * Callback reasons.
+ */
+#define T_CALLBACK_REASON_CONNECTIONOPEN 0x00 // A connection we opened _to_ the cam has been ACKed
+#define T_CALLBACK_REASON_CAMCONNECTIONOPEN 0x01 // The cam has opened a connection to _us_.
+#define T_CALLBACK_REASON_DATA 0x02 // Data received
+#define T_CALLBACK_REASON_CONNECTIONCLOSE 0x03 // The cam has told us to close a connection.
+#define T_CALLBACK_REASON_SLOTCLOSE 0x04 // The cam in the supplied slot id has been removed.
+
+// these are the states a TC can be in
+#define T_STATE_IDLE 0x01 // this transport connection is not in use
+#define T_STATE_ACTIVE 0x02 // this transport connection is in use
+#define T_STATE_ACTIVE_DELETEQUEUED 0x04 // this transport connection is about to be deleted
+#define T_STATE_IN_CREATION 0x08 // this transport waits for a T_C_T_C_REPLY to become active
+#define T_STATE_IN_DELETION 0x10 // this transport waits for T_D_T_C_REPLY to become idle again
+
+/**
+ * Opaque type representing a transport layer.
+ */
+struct en50221_transport_layer;
+
+/**
+ * Type definition for callback function - used when events are received from a module.
+ *
+ * **IMPORTANT** For all callback reasons except T_CALLBACK_REASON_DATA, an internal lock is held in the
+ * transport layer. Therefore, to avoid deadlock, you *must not* call back into the transport layer for
+ * these reasons.
+ *
+ * However, for T_CALLBACK_REASON_DATA, the internal lock is not held, so calling back into the transport
+ * layer is fine in this case.
+ *
+ * @param arg Private data.
+ * @param reason One of the T_CALLBACK_REASON_* values.
+ * @param data The data.
+ * @param data_length Length of the data.
+ * @param slot_id Slot_id the data was received from.
+ * @param connection_id Connection_id the data was received from.
+ */
+typedef void (*en50221_tl_callback) (void *arg, int reason,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id);
+
+
+/**
+ * Construct a new instance of the transport layer.
+ *
+ * @param max_slots Maximum number of slots to support.
+ * @param max_connections_per_slot Maximum connections per slot.
+ * @return The en50221_transport_layer instance, or NULL on error.
+ */
+extern struct en50221_transport_layer *en50221_tl_create(uint8_t max_slots,
+ uint8_t max_connections_per_slot);
+
+/**
+ * Destroy an instance of the transport layer.
+ *
+ * @param tl The en50221_transport_layer instance.
+ */
+extern void en50221_tl_destroy(struct en50221_transport_layer *tl);
+
+/**
+ * Register a new slot with the library.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param ca_hndl FD for talking to the slot.
+ * @param slot CAM slot where the requested CAM of the CA is in.
+ * @param response_timeout Maximum timeout in ms to a response we send before signalling a timeout.
+ * @param poll_delay Interval between polls in ms.
+ * @return slot_id on sucess, or -1 on error.
+ */
+extern int en50221_tl_register_slot(struct en50221_transport_layer *tl,
+ int ca_hndl, uint8_t slot,
+ uint32_t response_timeout,
+ uint32_t poll_delay);
+
+/**
+ * Destroy a registered slot - e.g. if a CAM is removed, or an error occurs. Does
+ * not attempt to reset the CAM.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id Slot to destroy.
+ */
+extern void en50221_tl_destroy_slot(struct en50221_transport_layer *tl, uint8_t slot_id);
+
+/**
+ * Performs one iteration of the transport layer poll -
+ * checking for incoming data furthermore it will handle
+ * the timeouts of certain commands like T_DELETE_T_C it
+ * should be called by the application regularly, generally
+ * faster than the poll delay.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @return 0 on succes, or -1 if there was an error of some sort.
+ */
+extern int en50221_tl_poll(struct en50221_transport_layer *tl);
+
+/**
+ * Register the callback for data reception.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param callback The callback. Set to NULL to remove the callback completely.
+ * @param arg Private data passed as arg0 of the callback.
+ */
+extern void en50221_tl_register_callback(struct en50221_transport_layer *tl,
+ en50221_tl_callback callback, void *arg);
+
+/**
+ * Gets the ID of the slot an error occurred on.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @return The offending slot id.
+ */
+extern int en50221_tl_get_error_slot(struct en50221_transport_layer *tl);
+
+/**
+ * Gets the last error.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @return One of the EN50221ERR_* values.
+ */
+extern int en50221_tl_get_error(struct en50221_transport_layer *tl);
+
+/**
+ * This function is used to take a data-block, pack into
+ * into a TPDU (DATA_LAST) and send it to the device
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id ID of the slot.
+ * @param connection_id Connection id.
+ * @param data Data to send.
+ * @param data_length Number of bytes to send.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_tl_send_data(struct en50221_transport_layer *tl,
+ uint8_t slot_id,
+ uint8_t connection_id,
+ uint8_t * data,
+ uint32_t data_length);
+
+/**
+ * This function is used to take a data-block, pack into
+ * into a TPDU (DATA_LAST) and send it to the device
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id ID of the slot.
+ * @param connection_id Connection id.
+ * @param vector iov to send.
+ * @param io_count Number of elements in vector.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_tl_send_datav(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ struct iovec *vector, int iov_count);
+
+/**
+ * Create a new transport connection to the cam.
+ *
+ * **IMPORTANT** When this function returns, it means the request to create a connection
+ * has been submitted. You will need to poll using en50221_tl_get_connection_state() to find out
+ * if/when the connection is established. A callback with T_CALLBACK_REASON_CONNECTIONOPEN reason
+ * will also be sent when it is acked by the CAM.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id ID of the slot.
+ * @return The allocated connection id on success, or -1 on error.
+ */
+extern int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id);
+
+/**
+ * Deallocates a transport connection.
+ *
+ * **IMPORTANT** When this function returns, it means the request to destroy a connection
+ * has been submitted. You will need to poll using en50221_tl_get_connection_state() to find out
+ * if/when the connection is destroyed.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id ID of the slot.
+ * @param connection_id Connection id to send the request _on_.
+ * @return 0 on success, or -1 on error.
+ */
+extern int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id, uint8_t connection_id);
+
+/**
+ * Checks the state of a connection.
+ *
+ * @param tl The en50221_transport_layer instance.
+ * @param slot_id ID of the slot.
+ * @param connection_id Connection id to send the request _on_.
+ * @return One of the T_STATE_* values.
+ */
+extern int en50221_tl_get_connection_state(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/lib/libdvbmisc/dvbmisc.h b/lib/libdvbmisc/dvbmisc.h
new file mode 100644
index 0000000..8ac6eee
--- /dev/null
+++ b/lib/libdvbmisc/dvbmisc.h
@@ -0,0 +1,72 @@
+/*
+ libdvbmisc - DVB miscellaneous library
+
+ Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#ifndef DVB_MISC_H
+#define DVB_MISC_H
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define ERROR 0
+#define NOTICE 1
+#define INFO 2
+#define DEBUG 3
+
+#define print(x, y, z, fmt, arg...) do { \
+ if (z) { \
+ if ((x > ERROR) && (x > y)) \
+ vprint("%s: " fmt "\n", __func__ , ##arg); \
+ else if ((x > NOTICE) && (x > y)) \
+ vprint("%s: " fmt "\n",__func__ , ##arg); \
+ else if ((x > INFO) && (x > y)) \
+ vprint("%s: " fmt "\n", __func__ , ##arg); \
+ else if ((x > DEBUG) && (x > y)) \
+ vprint("%s: " fmt "\n", __func__ , ##arg); \
+ } else { \
+ if (x > y) \
+ vprint(fmt, ##arg); \
+ } \
+} while(0)
+
+static inline void vprint(char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+}
+
+static inline int time_after(struct timeval oldtime, uint32_t delta_ms)
+{
+ // calculate the oldtime + add on the delta
+ uint64_t oldtime_ms = (oldtime.tv_sec * 1000) + (oldtime.tv_usec / 1000);
+ oldtime_ms += delta_ms;
+
+ // calculate the nowtime
+ struct timeval nowtime;
+ gettimeofday(&nowtime, 0);
+ uint64_t nowtime_ms = (nowtime.tv_sec * 1000) + (nowtime.tv_usec / 1000);
+
+ // check
+ return nowtime_ms > oldtime_ms;
+}
+
+#endif
diff --git a/lib/libdvbsec/Makefile b/lib/libdvbsec/Makefile
new file mode 100644
index 0000000..3d405f4
--- /dev/null
+++ b/lib/libdvbsec/Makefile
@@ -0,0 +1,17 @@
+# Makefile for linuxtv.org dvb-apps/lib/libdvbsec
+
+includes = dvbsec_api.h \
+ dvbsec_cfg.h
+
+objects = dvbsec_api.o \
+ dvbsec_cfg.o
+
+lib_name = libdvbsec
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include ../../Make.rules
diff --git a/lib/libdvbsec/dvbsec_api.c b/lib/libdvbsec/dvbsec_api.c
new file mode 100644
index 0000000..5f2ae22
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_api.c
@@ -0,0 +1,951 @@
+/*
+ libdvbsec - an SEC library
+
+ Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <linux/types.h>
+#include <libdvbapi/dvbfe.h>
+#include "dvbsec_api.h"
+
+// uncomment this to make dvbsec_command print out debug instead of talking to a frontend
+// #define TEST_SEC_COMMAND 1
+
+int dvbsec_set(struct dvbfe_handle *fe,
+ struct dvbsec_config *sec_config,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option,
+ struct dvbfe_parameters *params,
+ int timeout)
+{
+ int tmp;
+ struct dvbfe_parameters localparams;
+ struct dvbfe_parameters *topass = params;
+
+ // perform SEC
+ if (sec_config != NULL) {
+ switch(sec_config->config_type) {
+ case DVBSEC_CONFIG_NONE:
+ break;
+
+ case DVBSEC_CONFIG_POWER:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+
+ case DVBSEC_CONFIG_STANDARD:
+ {
+ // calculate the correct oscillator value
+ enum dvbsec_diseqc_oscillator osc = DISEQC_OSCILLATOR_LOW;
+ if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
+ osc = DISEQC_OSCILLATOR_HIGH;
+
+ if ((tmp = dvbsec_std_sequence(fe,
+ osc,
+ polarization,
+ sat_pos,
+ switch_option)) < 0)
+ return tmp;
+ break;
+ }
+
+ case DVBSEC_CONFIG_ADVANCED:
+ {
+ // are we high or not?
+ int high = 0;
+ if (sec_config->switch_frequency && (sec_config->switch_frequency < params->frequency))
+ high = 1;
+
+ // determine correct string
+ char *cmd = NULL;
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_h;
+ else
+ cmd = sec_config->adv_cmd_hi_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_v;
+ else
+ cmd = sec_config->adv_cmd_hi_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_l;
+ else
+ cmd = sec_config->adv_cmd_hi_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ if (!high)
+ cmd = sec_config->adv_cmd_lo_r;
+ else
+ cmd = sec_config->adv_cmd_hi_r;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ // do it
+ if (cmd)
+ if ((tmp = dvbsec_command(fe, cmd)) < 0)
+ return tmp;
+ break;
+ }
+ }
+
+ // work out the correct LOF value
+ uint32_t lof = 0;
+ if ((sec_config->switch_frequency == 0) || (params->frequency < sec_config->switch_frequency)) {
+ // LOW band
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ lof = sec_config->lof_lo_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ lof = sec_config->lof_lo_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ lof = sec_config->lof_lo_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ lof = sec_config->lof_lo_r;
+ break;
+ case DISEQC_POLARIZATION_UNCHANGED:
+ break;
+ }
+ } else {
+ // HIGH band
+ switch(polarization) {
+ case DISEQC_POLARIZATION_H:
+ lof = sec_config->lof_hi_h;
+ break;
+ case DISEQC_POLARIZATION_V:
+ lof = sec_config->lof_hi_v;
+ break;
+ case DISEQC_POLARIZATION_L:
+ lof = sec_config->lof_hi_l;
+ break;
+ case DISEQC_POLARIZATION_R:
+ lof = sec_config->lof_hi_r;
+ break;
+ case DISEQC_POLARIZATION_UNCHANGED:
+ break;
+ }
+ }
+
+ // do frequency adjustment
+ if (lof) {
+ memcpy(&localparams, params, sizeof(struct dvbfe_parameters));
+ int tmpfreq = localparams.frequency - lof;
+
+ if (tmpfreq < 0)
+ tmpfreq *= -1;
+ localparams.frequency = (uint32_t) tmpfreq;
+ topass = &localparams;
+ }
+ }
+
+ // set the frontend!
+ return dvbfe_set(fe, topass, timeout);
+}
+
+int dvbsec_std_sequence(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option)
+{
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+
+ switch(polarization) {
+ case DISEQC_POLARIZATION_V:
+ case DISEQC_POLARIZATION_R:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+ case DISEQC_POLARIZATION_H:
+ case DISEQC_POLARIZATION_L:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ dvbsec_diseqc_set_committed_switches(fe,
+ DISEQC_ADDRESS_ANY_DEVICE,
+ oscillator,
+ polarization,
+ sat_pos,
+ switch_option);
+
+ usleep(15000);
+
+ switch(sat_pos) {
+ case DISEQC_SWITCH_A:
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
+ break;
+ case DISEQC_SWITCH_B:
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
+ break;
+ default:
+ break;
+ }
+
+ if (sat_pos != DISEQC_SWITCH_UNCHANGED)
+ usleep(15000);
+
+ switch(oscillator) {
+ case DISEQC_OSCILLATOR_LOW:
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+ break;
+ case DISEQC_OSCILLATOR_HIGH:
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_reset state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x00 };
+
+ if (state == DISEQC_RESET_CLEAR)
+ data[2] = 0x01;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_power(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_power state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x02 };
+
+ if (state == DISEQC_POWER_ON)
+ data[2] = 0x03;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_listen state)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x30 };
+
+ if (state == DISEQC_LISTEN_AWAKE)
+ data[2] = 0x31;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x38, 0x00 };
+
+ switch(oscillator) {
+ case DISEQC_OSCILLATOR_LOW:
+ data[3] |= 0x10;
+ break;
+ case DISEQC_OSCILLATOR_HIGH:
+ data[3] |= 0x11;
+ break;
+ case DISEQC_OSCILLATOR_UNCHANGED:
+ break;
+ }
+ switch(polarization) {
+ case DISEQC_POLARIZATION_V:
+ case DISEQC_POLARIZATION_R:
+ data[3] |= 0x20;
+ break;
+ case DISEQC_POLARIZATION_H:
+ case DISEQC_POLARIZATION_L:
+ data[3] |= 0x22;
+ break;
+ default:
+ break;
+ }
+ switch(sat_pos) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x40;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x44;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(switch_option) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x80;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x88;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+
+ if (data[3] == 0)
+ return 0;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_switch s1,
+ enum dvbsec_diseqc_switch s2,
+ enum dvbsec_diseqc_switch s3,
+ enum dvbsec_diseqc_switch s4)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x39, 0x00 };
+
+ switch(s1) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x10;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x11;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s2) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x20;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x22;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s3) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x40;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x44;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+ switch(s4) {
+ case DISEQC_SWITCH_A:
+ data[3] |= 0x80;
+ break;
+ case DISEQC_SWITCH_B:
+ data[3] |= 0x88;
+ break;
+ case DISEQC_SWITCH_UNCHANGED:
+ break;
+ }
+
+ if (data[3] == 0)
+ return 0;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_analog_id id,
+ uint8_t value)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x48, value };
+
+ if (id == DISEQC_ANALOG_ID_A1)
+ data[2] = 0x49;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint32_t frequency)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x58, 0x00, 0x00, 0x00 };
+ int len = 5;
+
+ uint32_t bcdval = 0;
+ int i;
+ for(i=0; i<=24;i+=4) {
+ bcdval |= ((frequency % 10) << i);
+ frequency /= 10;
+ }
+
+ data[3] = bcdval >> 16;
+ data[4] = bcdval >> 8;
+ if (bcdval & 0xff) {
+ data[5] = bcdval;
+ len++;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, len);
+}
+
+int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint16_t channel)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x59, 0x00, 0x00};
+
+ data[3] = channel >> 8;
+ data[4] = channel;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x60};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x63};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x66};
+
+ if (direction == DISEQC_DIRECTION_WEST)
+ data[2] = 0x67;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction,
+ enum dvbsec_diseqc_drive_mode mode,
+ uint8_t value)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x68, 0x00};
+
+ if (direction == DISEQC_DIRECTION_WEST)
+ data[2] = 0x69;
+
+ switch(mode) {
+ case DISEQC_DRIVE_MODE_STEPS:
+ data[3] = (value & 0x7f) | 0x80;
+ break;
+ case DISEQC_DRIVE_MODE_TIMEOUT:
+ data[3] = value & 0x7f;
+ break;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6A, id};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6B, id};
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ int val1,
+ int val2)
+{
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6F, 0x00, 0x00};
+ int len = 3;
+
+ if (val1 != -1) {
+ data[3] = val1;
+ len++;
+ }
+ if (val2 != -1) {
+ data[4] = val2;
+ len = 5;
+ }
+
+ return dvbfe_do_diseqc_command(fe, data, len);
+}
+
+int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ float angle)
+{
+ int integer = (int) angle;
+ uint8_t data[] = { DISEQC_FRAMING_MASTER_NOREPLY, address, 0x6e, 0x00, 0x00};
+
+ // transform the fraction into the correct representation
+ int fraction = (int) (((angle - integer) * 16.0) + 0.9) & 0x0f;
+ switch(fraction) {
+ case 1:
+ case 4:
+ case 7:
+ case 9:
+ case 12:
+ case 15:
+ fraction--;
+ break;
+ }
+
+ // generate the command
+ if (integer < -256) {
+ return -EINVAL;
+ } else if (integer < 0) {
+ integer = -integer;
+ data[3] = 0xf0;
+ } else if (integer < 256) {
+ data[3] = 0x00;
+ } else if (integer < 512) {
+ integer -= 256;
+ data[3] = 0x10;
+ } else {
+ return -EINVAL;
+ }
+ data[3] |= ((integer / 16) & 0x0f);
+ integer = integer % 16;
+ data[4] |= ((integer & 0x0f) << 4) | fraction;
+
+ return dvbfe_do_diseqc_command(fe, data, sizeof(data));
+}
+
+static int skipwhite(char **line, char *end)
+{
+ while(**line) {
+ if (end && (*line >= end))
+ return -1;
+ if (!isspace(**line))
+ return 0;
+ (*line)++;
+ }
+
+ return -1;
+}
+
+static int getstringupto(char **line, char *end, char *matches, char **ptrdest, int *ptrlen)
+{
+ char *start = *line;
+
+ while(**line) {
+ if (end && (*line >= end))
+ break;
+ if (strchr(matches, **line)) {
+ *ptrdest = start;
+ *ptrlen = *line - start;
+ return 0;
+ }
+ (*line)++;
+ }
+
+ *ptrdest = start;
+ *ptrlen = *line - start;
+ return 0;
+}
+
+static int parsefunction(char **line,
+ char **nameptr, int *namelen,
+ char **argsptr, int *argslen)
+{
+ if (skipwhite(line, NULL))
+ return -1;
+
+ if (getstringupto(line, NULL, "(", nameptr, namelen))
+ return -1;
+ if ((*line) == 0)
+ return -1;
+ (*line)++; // skip the '('
+ if (getstringupto(line, NULL, ")", argsptr, argslen))
+ return -1;
+ if ((*line) == 0)
+ return -1;
+ (*line)++; // skip the ')'
+
+ return 0;
+}
+
+static int parseintarg(char **args, char *argsend, int *result)
+{
+ char tmp[32];
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 31)
+ arglen = 31;
+ strncpy(tmp, arg, arglen);
+ tmp[arglen] = 0;
+
+ if (sscanf(tmp, "%i", result) != 1)
+ return -1;
+
+ return 0;
+}
+
+static int parsechararg(char **args, char *argsend, int *result)
+{
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 0)
+ *result = arg[0];
+
+ return 0;
+}
+
+static int parsefloatarg(char **args, char *argsend, float *result)
+{
+ char tmp[32];
+ char *arg;
+ int arglen;
+
+ // skip whitespace
+ if (skipwhite(args, argsend))
+ return -1;
+
+ // get the arg
+ if (getstringupto(args, argsend, ",", &arg, &arglen))
+ return -1;
+ if ((**args) == ',')
+ (*args)++; // skip the ',' if present
+ if (arglen > 31)
+ arglen = 31;
+ strncpy(tmp, arg, arglen);
+ arg[arglen] = 0;
+
+ if (sscanf(tmp, "%f", result) != 1)
+ return -1;
+
+ return 0;
+}
+
+static enum dvbsec_diseqc_switch parse_switch(int c)
+{
+ switch(toupper(c)) {
+ case 'A':
+ return DISEQC_SWITCH_A;
+ case 'B':
+ return DISEQC_SWITCH_B;
+ default:
+ return DISEQC_SWITCH_UNCHANGED;
+ }
+}
+
+int dvbsec_command(struct dvbfe_handle *fe, char *command)
+{
+ char *name;
+ char *args;
+ int namelen;
+ int argslen;
+ int address;
+ int iarg;
+ int iarg2;
+ int iarg3;
+ int iarg4;
+ float farg;
+
+ while(!parsefunction(&command, &name, &namelen, &args, &argslen)) {
+ char *argsend = args+argslen;
+
+ if (!strncasecmp(name, "tone", namelen)) {
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("tone: %c\n", iarg);
+#else
+ if (toupper(iarg) == 'B') {
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_ON);
+ } else {
+ dvbfe_set_22k_tone(fe, DVBFE_SEC_TONE_OFF);
+ }
+#endif
+ } else if (!strncasecmp(name, "voltage", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("voltage: %i\n", iarg);
+#else
+ switch(iarg) {
+ case 0:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_OFF);
+ break;
+ case 13:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_13);
+ break;
+ case 18:
+ dvbfe_set_voltage(fe, DVBFE_SEC_VOLTAGE_18);
+ break;
+ default:
+ return -1;
+ }
+#endif
+ } else if (!strncasecmp(name, "toneburst", namelen)) {
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("toneburst: %c\n", iarg);
+#else
+ if (toupper(iarg) == 'B') {
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_B);
+ } else {
+ dvbfe_set_tone_data_burst(fe, DVBFE_SEC_MINI_A);
+ }
+#endif
+ } else if (!strncasecmp(name, "highvoltage", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("highvoltage: %i\n", iarg);
+#else
+ dvbfe_set_high_lnb_voltage(fe, iarg ? 1 : 0);
+#endif
+ } else if (!strncasecmp(name, "dishnetworks", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("dishnetworks: %i\n", iarg);
+#else
+ dvbfe_do_dishnetworks_legacy_command(fe, iarg);
+#endif
+ } else if (!strncasecmp(name, "wait", namelen)) {
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("wait: %i\n", iarg);
+#else
+ if (iarg)
+ usleep(iarg * 1000);
+#endif
+ } else if (!strncasecmp(name, "Dreset", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dreset: %i %i\n", address, iarg);
+#else
+ if (iarg) {
+ dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET);
+ } else {
+ dvbsec_diseqc_set_reset(fe, address, DISEQC_RESET_CLEAR);
+ }
+#endif
+ } else if (!strncasecmp(name, "Dpower", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dpower: %i %i\n", address, iarg);
+#else
+ if (iarg) {
+ dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_ON);
+ } else {
+ dvbsec_diseqc_set_power(fe, address, DISEQC_POWER_OFF);
+ }
+#endif
+ } else if (!strncasecmp(name, "Dcommitted", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg2))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg3))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg4))
+ return -1;
+
+ enum dvbsec_diseqc_oscillator oscillator;
+ switch(toupper(iarg)) {
+ case 'H':
+ oscillator = DISEQC_OSCILLATOR_HIGH;
+ break;
+ case 'L':
+ oscillator = DISEQC_OSCILLATOR_LOW;
+ break;
+ default:
+ oscillator = DISEQC_OSCILLATOR_UNCHANGED;
+ break;
+ }
+
+ int polarization = -1;
+ switch(toupper(iarg2)) {
+ case 'H':
+ polarization = DISEQC_POLARIZATION_H;
+ break;
+ case 'V':
+ polarization = DISEQC_POLARIZATION_V;
+ break;
+ case 'L':
+ polarization = DISEQC_POLARIZATION_L;
+ break;
+ case 'R':
+ polarization = DISEQC_POLARIZATION_R;
+ break;
+ default:
+ polarization = -1;
+ break;
+ }
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dcommitted: %i %i %i %i %i\n", address,
+ oscillator,
+ polarization,
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#else
+ dvbsec_diseqc_set_committed_switches(fe, address,
+ oscillator,
+ polarization,
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#endif
+ } else if (!strncasecmp(name, "Duncommitted", namelen)) {
+ if (parsechararg(&args, argsend, &address))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg2))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg3))
+ return -1;
+ if (parsechararg(&args, argsend, &iarg4))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Duncommitted: %i %i %i %i %i\n", address,
+ parse_switch(iarg),
+ parse_switch(iarg2),
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#else
+ dvbsec_diseqc_set_uncommitted_switches(fe, address,
+ parse_switch(iarg),
+ parse_switch(iarg2),
+ parse_switch(iarg3),
+ parse_switch(iarg4));
+#endif
+ } else if (!strncasecmp(name, "Dfrequency", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dfrequency: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_set_frequency(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dchannel", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dchannel: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_set_channel(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dgotopreset", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parseintarg(&args, argsend, &iarg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dgotopreset: %i %i\n", address, iarg);
+#else
+ dvbsec_diseqc_goto_satpos_preset(fe, address, iarg);
+#endif
+ } else if (!strncasecmp(name, "Dgotobearing", namelen)) {
+ if (parseintarg(&args, argsend, &address))
+ return -1;
+ if (parsefloatarg(&args, argsend, &farg))
+ return -1;
+
+#ifdef TEST_SEC_COMMAND
+ printf("Dgotobearing: %i %f\n", address, farg);
+#else
+ dvbsec_diseqc_goto_rotator_bearing(fe, address, farg);
+#endif
+ } else {
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/lib/libdvbsec/dvbsec_api.h b/lib/libdvbsec/dvbsec_api.h
new file mode 100644
index 0000000..7e454d7
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_api.h
@@ -0,0 +1,436 @@
+/*
+ libdvbsec - an SEC library
+
+ Copyright (C) 2005 Manu Abraham <abraham.manu@gmail.com>
+ Copyright (C) 2006 Andrew de Quincey <adq_dvb@lidskialf.net>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#ifndef DVBSEC_API_H
+#define DVBSEC_API_H 1
+
+#include <stdint.h>
+
+struct dvbfe_handle;
+struct dvbfe_parameters;
+
+enum dvbsec_diseqc_framing {
+ DISEQC_FRAMING_MASTER_NOREPLY = 0xE0,
+ DISEQC_FRAMING_MASTER_NOREPLY_REPEAT = 0xE1,
+ DISEQC_FRAMING_MASTER_REPLY = 0xE2,
+ DISEQC_FRAMING_MASTER_REPLY_REPEAT = 0xE3,
+ DISEQC_FRAMING_SLAVE_OK = 0xE4,
+ DISEQC_FRAMING_SLAVE_UNSUPPORTED = 0xE5,
+ DISEQC_FRAMING_SLAVE_PARITY_ERROR = 0xE6,
+ DISEQC_FRAMING_SLAVE_UNRECOGNISED = 0xE7,
+};
+
+enum dvbsec_diseqc_address {
+ DISEQC_ADDRESS_ANY_DEVICE = 0x00,
+
+ DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV = 0x10,
+ DISEQC_ADDRESS_LNB = 0x11,
+ DISEQC_ADDRESS_LNB_WITH_LOOP = 0x12,
+ DISEQC_ADDRESS_SWITCHER = 0x14,
+ DISEQC_ADDRESS_SWITCHER_WITH_LOOP = 0x15,
+ DISEQC_ADDRESS_SMATV = 0x18,
+
+ DISEQC_ADDRESS_ANY_POLARISER = 0x20,
+ DISEQC_ADDRESS_LINEAR_POLARISER = 0x21,
+
+ DISEQC_ADDRESS_ANY_POSITIONER = 0x30,
+ DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER = 0x31,
+ DISEQC_ADDRESS_ELEVATION_POSITIONER = 0x32,
+
+ DISEQC_ADDRESS_ANY_INSTALLER_AID = 0x40,
+ DISEQC_ADDRESS_SIGNAL_STRENGTH = 0x41,
+
+ DISEQC_ADDRESS_ANY_INTERFACE = 0x70,
+ DISEQC_ADDRESS_HEADEND_INTERFACE = 0x71,
+
+ DISEQC_ADDRESS_REALLOC_BASE = 0x60,
+ DISEQC_ADDRESS_OEM_BASE = 0xf0,
+};
+
+enum dvbsec_diseqc_reset {
+ DISEQC_RESET,
+ DISEQC_RESET_CLEAR,
+};
+
+enum dvbsec_diseqc_power {
+ DISEQC_POWER_OFF,
+ DISEQC_POWER_ON,
+};
+
+enum dvbsec_diseqc_listen {
+ DISEQC_LISTEN_SLEEP,
+ DISEQC_LISTEN_AWAKE,
+};
+
+enum dvbsec_diseqc_polarization {
+ DISEQC_POLARIZATION_UNCHANGED = 0,
+ DISEQC_POLARIZATION_H = 'h',
+ DISEQC_POLARIZATION_V = 'v',
+ DISEQC_POLARIZATION_L = 'l',
+ DISEQC_POLARIZATION_R = 'r',
+};
+
+enum dvbsec_diseqc_oscillator {
+ DISEQC_OSCILLATOR_UNCHANGED = 0,
+ DISEQC_OSCILLATOR_LOW,
+ DISEQC_OSCILLATOR_HIGH,
+};
+
+enum dvbsec_diseqc_switch {
+ DISEQC_SWITCH_UNCHANGED = 0,
+ DISEQC_SWITCH_A,
+ DISEQC_SWITCH_B,
+};
+
+enum dvbsec_diseqc_analog_id {
+ DISEQC_ANALOG_ID_A0,
+ DISEQC_ANALOG_ID_A1,
+};
+
+enum dvbsec_diseqc_drive_mode {
+ DISEQC_DRIVE_MODE_STEPS,
+ DISEQC_DRIVE_MODE_TIMEOUT,
+};
+
+enum dvbsec_diseqc_direction {
+ DISEQC_DIRECTION_EAST,
+ DISEQC_DIRECTION_WEST,
+};
+
+enum dvbsec_config_type {
+ DVBSEC_CONFIG_NONE = 0,
+ DVBSEC_CONFIG_POWER,
+ DVBSEC_CONFIG_STANDARD,
+ DVBSEC_CONFIG_ADVANCED,
+};
+
+
+#define MAX_SEC_CMD_LEN 100
+
+struct dvbsec_config
+{
+ char id[32]; /* ID of this SEC config structure */
+ uint32_t switch_frequency; /* switching frequency - supply 0 for none. */
+ uint32_t lof_lo_v; /* frequency to subtract for V + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_h; /* frequency to subtract for H + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_l; /* frequency to subtract for L + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_lo_r; /* frequency to subtract for R + LOW band channels - or for switch_frequency == 0 */
+ uint32_t lof_hi_v; /* frequency to subtract for V + HIGH band channels */
+ uint32_t lof_hi_h; /* frequency to subtract for H + HIGH band channels */
+ uint32_t lof_hi_l; /* frequency to subtract for L + HIGH band channels */
+ uint32_t lof_hi_r; /* frequency to subtract for R + HIGH band channels */
+
+ /**
+ * The SEC control to be used depends on the type:
+ *
+ * NONE - no SEC commands will be issued. (Frequency adjustment will still be performed).
+ *
+ * POWER - only the SEC power will be turned on.
+ *
+ * STANDARD - the standard DISEQC back compatable sequence is used.
+ *
+ * ADVANCED - SEC strings are supplied by the user describing the exact sequence
+ * of operations to use.
+ */
+ enum dvbsec_config_type config_type;
+
+ /* stuff for type == dvbsec_config_ADVANCED */
+ char adv_cmd_lo_h[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/H. */
+ char adv_cmd_lo_v[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/V. */
+ char adv_cmd_lo_l[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/L. */
+ char adv_cmd_lo_r[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for LOW/R. */
+ char adv_cmd_hi_h[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/H. */
+ char adv_cmd_hi_v[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/V. */
+ char adv_cmd_hi_l[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/L. */
+ char adv_cmd_hi_r[MAX_SEC_CMD_LEN]; /* ADVANCED SEC command to use for HI/R. */
+};
+
+/**
+ * Helper function for tuning adapters with SEC support. This function will do
+ * everything required, including frequency adjustment based on the parameters
+ * in sec_config.
+ *
+ * Note: Since the SEC configuration structure can be set to disable any SEC
+ * operations, this function can be reused for ALL DVB style devices (just
+ * set all LOF=0,type=dvbsec_config_NONE for devices which do not require
+ * SEC control).
+ *
+ * The sec configuration structures can be looked up using the dvbcfg_sec library.
+ *
+ * @param fe Frontend concerned.
+ * @param sec_config SEC configuration structure. May be NULL to disable SEC/frequency adjustment.
+ * @param polarization Polarization of signal.
+ * @param sat_pos Satellite position - only used if type == DISEQC_SEC_CONFIG_STANDARD.
+ * @param switch_option Switch option - only used if type == DISEQC_SEC_CONFIG_STANDARD.
+ * @param params Tuning parameters.
+ * @param timeout <0 => wait forever for lock. 0=>return immediately, >0=>
+ * number of milliseconds to wait for a lock.
+ * @return 0 on locked (or if timeout==0 and everything else worked), or
+ * nonzero on failure (including no lock).
+ */
+extern int dvbsec_set(struct dvbfe_handle *fe,
+ struct dvbsec_config *sec_config,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option,
+ struct dvbfe_parameters *params,
+ int timeout);
+
+/**
+ * This will issue the standardised back-compatable DISEQC/SEC command
+ * sequence as defined in the DISEQC spec:
+ *
+ * i.e. tone off, set voltage, wait15, DISEQC, wait15, toneburst, wait15, set tone.
+ *
+ * @param fe Frontend concerned.
+ * @param oscillator Value to set the lo/hi switch to.
+ * @param polarization Value to set the polarisation switch to.
+ * @param sat_pos Value to set the satellite position switch to.
+ * @param switch_option Value to set the "swtch option" switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_std_sequence(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option);
+
+/**
+ * Execute an SEC command string on the provided frontend. Please see the documentation
+ * in dvbsec_cfg.h on the command format,
+ *
+ * @param fe Frontend concerned.
+ * @param command The command to execute.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_command(struct dvbfe_handle *fe, char *command);
+
+/**
+ * Control the reset status of an attached DISEQC device.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_reset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_reset state);
+
+/**
+ * Control the power status of an attached DISEQC peripheral.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_power(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_power state);
+
+/**
+ * Control the listening status of an attached DISEQC peripheral.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param state The state to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_listen(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_listen state);
+
+/**
+ * Set the state of the committed switches of a DISEQC device.
+ * These are switches which are defined to have a standard name.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param oscillator Value to set the lo/hi switch to.
+ * @param polarization Value to set the polarization switch to.
+ * @param sat_pos Value to set the satellite position switch to.
+ * @param switch_option Value to set the switch option switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_committed_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_oscillator oscillator,
+ enum dvbsec_diseqc_polarization polarization,
+ enum dvbsec_diseqc_switch sat_pos,
+ enum dvbsec_diseqc_switch switch_option);
+
+/**
+ * Set the state of the uncommitted switches of a DISEQC device.
+ * These provide another four switching possibilities.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param s1 Value to set the S1 switch to.
+ * @param s2 Value to set the S2 switch to.
+ * @param s3 Value to set the S3 switch to.
+ * @param s3 Value to set the S4 switch to.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_uncommitted_switches(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_switch s1,
+ enum dvbsec_diseqc_switch s2,
+ enum dvbsec_diseqc_switch s3,
+ enum dvbsec_diseqc_switch s4);
+
+/**
+ * Set an analogue value.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id The id of the analogue value to set.
+ * @param value The value to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_analog_value(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_analog_id id,
+ uint8_t value);
+
+/**
+ * Set the desired frequency.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param frequency The frequency to set in GHz.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_frequency(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint32_t frequency);
+
+/**
+ * Set the desired channel.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param channel ID of the channel to set.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_channel(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint16_t channel);
+
+/**
+ * Halt the satellite positioner.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_halt_satpos(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address);
+
+/**
+ * Disable satellite positioner limits.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_disable_satpos_limits(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address);
+
+/**
+ * Set satellite positioner limits.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_set_satpos_limit(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction);
+
+/**
+ * Drive satellite positioner motor.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param direction Direction to drive in.
+ * @param mode Drive mode to use
+ * (TIMEOUT=>value is a timeout in seconds, or STEPS=>value is a count of steps to use)
+ * @param value Value associated with the drive mode (range 0->127)
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_drive_satpos_motor(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ enum dvbsec_diseqc_direction direction,
+ enum dvbsec_diseqc_drive_mode mode,
+ uint8_t value);
+
+/**
+ * Store satellite positioner preset id at current position.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id ID of the preset.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_store_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id);
+
+/**
+ * Send a satellite positioner to a pre-set position.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param id ID of the preset.
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_goto_satpos_preset(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ uint8_t id);
+
+/**
+ * Recalculate satellite positions based on the current position, using
+ * magic positioner specific values.
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param val1 value1 (range 0->255, pass -1 to ignore).
+ * @param val2 value2 (range 0->255, pass -1 to ignore).
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_recalculate_satpos_positions(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ int val1,
+ int val2);
+
+/**
+ * Send a terrestrial aerial rotator to a particular bearing
+ * (0 degrees = north, fractional angles allowed).
+ *
+ * @param fe Frontend concerned.
+ * @param address Address of the device.
+ * @param angle Angle to rotate to (-256.0 -> 512.0)
+ * @return 0 on success, or nonzero on error.
+ */
+extern int dvbsec_diseqc_goto_rotator_bearing(struct dvbfe_handle *fe,
+ enum dvbsec_diseqc_address address,
+ float angle);
+
+#endif
diff --git a/lib/libdvbsec/dvbsec_cfg.c b/lib/libdvbsec/dvbsec_cfg.c
new file mode 100644
index 0000000..4b05a32
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_cfg.c
@@ -0,0 +1,366 @@
+/**
+ * dvbsec_cfg (i.e. linuxtv sec format) configuration file support.
+ *
+ * Copyright (c) 2005 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <linux/types.h>
+#include "dvbsec_cfg.h"
+
+int dvbcfg_issection(char* line, char* sectionname)
+{
+ int len;
+
+ len = strlen(line);
+ if (len < 2)
+ return 0;
+
+ if ((line[0] != '[') || (line[len-1] != ']'))
+ return 0;
+
+ line++;
+ while(isspace(*line))
+ line++;
+
+ if (strncmp(line, sectionname, strlen(sectionname)))
+ return 0;
+
+ return 1;
+}
+
+char* dvbcfg_iskey(char* line, char* keyname)
+{
+ int len = strlen(keyname);
+
+ /* does the key match? */
+ if (strncmp(line, keyname, len))
+ return NULL;
+
+ /* skip keyname & any whitespace */
+ line += len;
+ while(isspace(*line))
+ line++;
+
+ /* should be the '=' sign */
+ if (*line != '=')
+ return 0;
+
+ /* more whitespace skipping */
+ line++;
+ while(isspace(*line))
+ line++;
+
+ /* finally, return the value */
+ return line;
+}
+
+int dvbsec_cfg_load(FILE *f,
+ void *arg,
+ dvbsec_cfg_callback cb)
+{
+ struct dvbsec_config tmpsec;
+ char *linebuf = NULL;
+ size_t line_size = 0;
+ int len;
+ int insection = 0;
+ char *value;
+
+ /* process each line */
+ while((len = getline(&linebuf, &line_size, f)) > 0) {
+ char *line = linebuf;
+
+ /* chop any comments */
+ char *hashpos = strchr(line, '#');
+ if (hashpos)
+ *hashpos = 0;
+ char *lineend = line + strlen(line);
+
+ /* trim the line */
+ while(*line && isspace(*line))
+ line++;
+ while((lineend != line) && isspace(*(lineend-1)))
+ lineend--;
+ *lineend = 0;
+
+ /* skip blank lines */
+ if (*line == 0)
+ continue;
+
+ if (dvbcfg_issection(line, "sec")) {
+ if (insection) {
+ if (cb(arg, &tmpsec))
+ return 0;
+ }
+ insection = 1;
+ memset(&tmpsec, 0, sizeof(tmpsec));
+
+ } else if ((value = dvbcfg_iskey(line, "name")) != NULL) {
+ strncpy(tmpsec.id, value, sizeof(tmpsec.id));
+ } else if ((value = dvbcfg_iskey(line, "switch-frequency")) != NULL) {
+ tmpsec.switch_frequency = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-v")) != NULL) {
+ tmpsec.lof_lo_v = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-h")) != NULL) {
+ tmpsec.lof_lo_h = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-l")) != NULL) {
+ tmpsec.lof_lo_l = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-lo-r")) != NULL) {
+ tmpsec.lof_lo_r = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-v")) != NULL) {
+ tmpsec.lof_hi_v = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-h")) != NULL) {
+ tmpsec.lof_hi_h = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-l")) != NULL) {
+ tmpsec.lof_hi_l = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "lof-hi-r")) != NULL) {
+ tmpsec.lof_hi_r = atoi(value);
+ } else if ((value = dvbcfg_iskey(line, "config-type")) != NULL) {
+ if (!strcasecmp(value, "none")) {
+ tmpsec.config_type = DVBSEC_CONFIG_NONE;
+ } else if (!strcasecmp(value, "power")) {
+ tmpsec.config_type = DVBSEC_CONFIG_POWER;
+ } else if (!strcasecmp(value, "standard")) {
+ tmpsec.config_type = DVBSEC_CONFIG_STANDARD;
+ } else if (!strcasecmp(value, "advanced")) {
+ tmpsec.config_type = DVBSEC_CONFIG_ADVANCED;
+ } else {
+ insection = 0;
+ }
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-v")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_v, value, sizeof(tmpsec.adv_cmd_lo_v));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-h")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_h, value, sizeof(tmpsec.adv_cmd_lo_h));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-r")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_r, value, sizeof(tmpsec.adv_cmd_lo_r));
+ } else if ((value = dvbcfg_iskey(line, "cmd-lo-l")) != NULL) {
+ strncpy(tmpsec.adv_cmd_lo_l, value, sizeof(tmpsec.adv_cmd_lo_l));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-v")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_v, value, sizeof(tmpsec.adv_cmd_hi_v));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-h")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_h, value, sizeof(tmpsec.adv_cmd_hi_h));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-r")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_r, value, sizeof(tmpsec.adv_cmd_hi_r));
+ } else if ((value = dvbcfg_iskey(line, "cmd-hi-l")) != NULL) {
+ strncpy(tmpsec.adv_cmd_hi_l, value, sizeof(tmpsec.adv_cmd_hi_l));
+ } else {
+ insection = 0;
+ }
+ }
+
+ // output the final section if there is one
+ if (insection) {
+ if (cb(arg, &tmpsec))
+ return 0;
+ }
+
+ if (linebuf)
+ free(linebuf);
+ return 0;
+}
+
+static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec);
+static int dvbsec_cfg_find_default(const char *sec_id, struct dvbsec_config *sec);
+
+struct findparams {
+ const char *sec_id;
+ struct dvbsec_config *sec_dest;
+};
+
+int dvbsec_cfg_find(const char *config_file,
+ const char *sec_id,
+ struct dvbsec_config *sec)
+{
+ struct findparams findp;
+
+ // clear the structure
+ memset(sec, 0, sizeof(struct dvbsec_config));
+
+ // open the file
+ if (config_file != NULL) {
+ FILE *f = fopen(config_file, "r");
+ if (f == NULL)
+ return -EIO;
+
+ // parse each entry
+ findp.sec_id = sec_id;
+ findp.sec_dest = sec;
+ dvbsec_cfg_load(f, &findp, dvbsec_cfg_find_callback);
+
+ // done
+ fclose(f);
+
+ // find it?
+ if (sec->id[0])
+ return 0;
+ }
+
+ return dvbsec_cfg_find_default(sec_id, sec);
+}
+
+static int dvbsec_cfg_find_callback(void *arg, struct dvbsec_config *sec)
+{
+ struct findparams *findp = arg;
+
+ if (strcmp(findp->sec_id, sec->id))
+ return 0;
+
+ memcpy(findp->sec_dest, sec, sizeof(struct dvbsec_config));
+ return 1;
+}
+
+int dvbsec_cfg_save(FILE *f,
+ struct dvbsec_config *secs,
+ int count)
+{
+ int i;
+
+ for(i=0; i<count; i++) {
+ char *config_type = "";
+ switch(secs[i].config_type) {
+ case DVBSEC_CONFIG_NONE:
+ config_type = "none";
+ break;
+ case DVBSEC_CONFIG_POWER:
+ config_type = "power";
+ break;
+ case DVBSEC_CONFIG_STANDARD:
+ config_type = "standard";
+ break;
+ case DVBSEC_CONFIG_ADVANCED:
+ config_type = "advanced";
+ break;
+ }
+
+ fprintf(f, "[lnb]\n");
+ fprintf(f, "switch-frequency=%i\n", secs[i].switch_frequency);
+ if (secs[i].lof_lo_v)
+ fprintf(f, "lof-lo-v=%i\n", secs[i].lof_lo_v);
+ if (secs[i].lof_lo_h)
+ fprintf(f, "lof-lo-h=%i\n", secs[i].lof_lo_h);
+ if (secs[i].lof_lo_l)
+ fprintf(f, "lof-lo-l=%i\n", secs[i].lof_lo_l);
+ if (secs[i].lof_lo_r)
+ fprintf(f, "lof-lo-r=%i\n", secs[i].lof_lo_r);
+ if (secs[i].lof_hi_v)
+ fprintf(f, "lof-hi-v=%i\n", secs[i].lof_hi_v);
+ if (secs[i].lof_hi_h)
+ fprintf(f, "lof-hi-h=%i\n", secs[i].lof_hi_h);
+ if (secs[i].lof_hi_l)
+ fprintf(f, "lof-hi-l=%i\n", secs[i].lof_hi_l);
+ if (secs[i].lof_hi_r)
+ fprintf(f, "lof-hi-r=%i\n", secs[i].lof_hi_r);
+ fprintf(f, "config-type=%s\n", config_type);
+
+ if (secs[i].config_type == DVBSEC_CONFIG_ADVANCED) {
+ if (secs[i].adv_cmd_lo_h[0])
+ fprintf(f, "cmd-lo-h=%s\n", secs[i].adv_cmd_lo_h);
+ if (secs[i].adv_cmd_lo_v[0])
+ fprintf(f, "cmd-lo-v=%s\n", secs[i].adv_cmd_lo_v);
+ if (secs[i].adv_cmd_lo_r[0])
+ fprintf(f, "cmd-lo-r=%s\n", secs[i].adv_cmd_lo_r);
+ if (secs[i].adv_cmd_lo_l[0])
+ fprintf(f, "cmd-lo-l=%s\n", secs[i].adv_cmd_lo_l);
+ if (secs[i].adv_cmd_hi_h[0])
+ fprintf(f, "cmd-hi-h=%s\n", secs[i].adv_cmd_hi_h);
+ if (secs[i].adv_cmd_hi_v[0])
+ fprintf(f, "cmd-hi-v=%s\n", secs[i].adv_cmd_hi_v);
+ if (secs[i].adv_cmd_hi_r[0])
+ fprintf(f, "cmd-hi-r=%s\n", secs[i].adv_cmd_hi_r);
+ if (secs[i].adv_cmd_hi_l[0])
+ fprintf(f, "cmd-hi-l=%s\n", secs[i].adv_cmd_hi_l);
+ }
+
+ fprintf(f, "\n");
+ }
+
+ return 0;
+}
+
+static struct dvbsec_config defaults[] = {
+
+ {
+ .id = "NULL",
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "UNIVERSAL",
+ .switch_frequency = 11700000,
+ .lof_lo_v = 9750000,
+ .lof_lo_h = 9750000,
+ .lof_hi_v = 10600000,
+ .lof_hi_h = 10600000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "DBS",
+ .switch_frequency = 0,
+ .lof_lo_v = 11250000,
+ .lof_lo_h = 11250000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "STANDARD",
+ .switch_frequency = 0,
+ .lof_lo_v = 10000000,
+ .lof_lo_h = 10000000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "ENHANCED",
+ .switch_frequency = 0,
+ .lof_lo_v = 9750000,
+ .lof_lo_h = 9750000,
+ .config_type = DVBSEC_CONFIG_STANDARD,
+ },
+ {
+ .id = "C-BAND",
+ .switch_frequency = 0,
+ .lof_lo_v = 5150000,
+ .lof_lo_h = 5150000,
+ .config_type = DVBSEC_CONFIG_POWER,
+ },
+ {
+ .id = "C-MULTI",
+ .switch_frequency = 0,
+ .lof_lo_v = 5150000,
+ .lof_lo_h = 5750000,
+ .config_type = DVBSEC_CONFIG_POWER,
+ },
+};
+#define defaults_count (sizeof(defaults) / sizeof(struct dvbsec_config))
+
+static int dvbsec_cfg_find_default(const char *sec_id,
+ struct dvbsec_config *sec)
+{
+ unsigned int i;
+
+ for(i=0; i< defaults_count; i++) {
+ if (!strncmp(sec_id, defaults[i].id, sizeof(defaults[i].id))) {
+ memcpy(sec, &defaults[i], sizeof(struct dvbsec_config));
+ return 0;
+ }
+ }
+
+ return -1;
+}
diff --git a/lib/libdvbsec/dvbsec_cfg.h b/lib/libdvbsec/dvbsec_cfg.h
new file mode 100644
index 0000000..d4546de
--- /dev/null
+++ b/lib/libdvbsec/dvbsec_cfg.h
@@ -0,0 +1,203 @@
+/**
+ * dvbsec_cfg (i.e. linuxtv SEC format) configuration file support.
+ *
+ * Copyright (c) 2006 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/**
+ * This library allows SEC (Satellite Equipment Control) configurations
+ * to be retrieved. Each configuration is identified by a unique satellite_id.
+ *
+ * In order to make things as easy as possible for users, there are a set of
+ * defaults hardcoded into the library covering the majority of LNB types. When
+ * these are used, the standard back-compatable sequence defined in the DISEQC
+ * standard will be used - this will suffice for _most_ situations.
+ *
+ * UNIVERSAL - Europe, 10800 to 11800 MHz and 11600 to 12700 Mhz, Dual LO, loband 9750, hiband 10600 MHz.
+ * DBS - Expressvu, North America, 12200 to 12700 MHz, Single LO, 11250 MHz.
+ * STANDARD - 10945 to 11450 Mhz, Single LO, 10000Mhz.
+ * ENHANCED - Astra, 10700 to 11700 MHz, Single LO, 9750MHz.
+ * C-BAND - Big Dish, 3700 to 4200 MHz, Single LO, 5150Mhz.
+ * C-MULTI - Big Dish - Multipoint LNBf, 3700 to 4200 MHz, Dual LO, H:5150MHz, V:5750MHz.
+ *
+ * However, for the power user with a more complex setup, these simple defaults
+ * are not enough. Therefore, it is also possible to define additional SEC
+ * configurations in an external configuration file. This file consists of multiple
+ * entries in the following format:
+ *
+ * [sec]
+ * name=<sec_id>
+ * switch-frequency=<switching frequency (SLOF)>
+ * lof-lo-v=<low band + V + frequency>
+ * lof-lo-h=<low band + H + frequency>
+ * lof-lo-l=<low band + L + frequency>
+ * lof-lo-r=<low band + R + frequency>
+ * lof-hi-v=<high band + V + frequency>
+ * lof-hi-h=<high band + H + frequency>
+ * lof-hi-l=<high band + L + frequency>
+ * lof-hi-r=<high band + R + frequency>
+ * config-type=<none|power|standard|advanced>
+ * cmd-lo-v=<sec sequence>
+ * cmd-lo-h=<sec sequence>
+ * cmd-lo-r=<sec sequence>
+ * cmd-lo-l=<sec sequence>
+ * cmd-hi-v=<sec sequence>
+ * cmd-hi-h=<sec sequence>
+ * cmd-hi-r=<sec sequence>
+ * cmd-hi-l=<sec sequence>
+ *
+ * The sec_id is whatever unique value you wish. If it is the same as one of the hardcoded defaults, the configuration
+ * details from the file will be used instead of the hardcoded ones.
+ * The switch-frequency (or SLOF) indicates the point seperating low band frequencies from high band frequencies.
+ * Set this value to 0 if there is only one frequency band.
+ * The lof-lo-v is the frequency adjustment for V + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-h is the frequency adjustment for H + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-l is the frequency adjustment for L + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-lo-r is the frequency adjustment for R + low band (i.e. less than SLOF), or is used if switch-frequency==0.
+ * The lof-hi-v is the frequency adjustment for V + high band (unused if switch-frequency==0).
+ * The lof-hi-h is the frequency adjustment for H + high band (unused if switch-frequency==0).
+ * The lof-hi-l is the frequency adjustment for L + high band (unused if switch-frequency==0).
+ * The lof-hi-r is the frequency adjustment for R + high band (unused if switch-frequency==0).
+ *
+ * config-type indicates the desired type of SEC command to use, it may be:
+ * none - No SEC commands will be issued (frequency adjustment will still be performed).
+ * power - Only the SEC power is turned on.
+ * standard - The standard DISEQC back compatable sequence will be issued.
+ * advanced - The DISEQC sequence described in the appropriate sec cmd string will be used.
+ *
+ * The cmd-<lo|hi>-<v|h|l|r> describes the SEC cmd string to use in advanced mode for each of the possible combinations of
+ * frequency band and polarisation. If a certain combination is not required, it may be omitted. It consists of a
+ * space seperated combination of commands - those available are as follows:
+ *
+ * tone(<0|1>) - control the 22kHz tone 0:off, 1:on
+ * voltage(<0|13|18>) - control the LNB voltage 0v, 13v, or 18v
+ * toneburst(<a|b>) - issue a toneburst (mini command) for position A or B.
+ * highvoltage(<0|1>) - control high lnb voltage for long cable runs 0: normal, 1:add 1v to LNB voltage.
+ * dishnetworks(<integer>) - issue a dishnetworks legacy command.
+ * wait(<integer>) - wait for the given number of milliseconds.
+ * Dreset(<address>, <0|1>) - control the reset state of a DISEC device, 0:disable reset, 1:enable reset.
+ * Dpower(<address>, <0|1>) - control the power of a DISEC device, 0:off, 1:on.
+ * Dcommitted(<address>, <h|l|x>, <v|h|l|r|x>, <a|b|x>, <a|b|x>) - Write to the committed switches of a DISEC device.
+ * The parameters are for band, polarisation, satelliteposition, switchoption:
+ * band - h:high band, l:low band
+ * polarisation - v: vertical, h:horizontal,r:right,l:left
+ * satelliteposition - a:position A, b: position B
+ * switchoption - a:position A, b: position B
+ * The special value 'x' means "no change to this switch".
+ *
+ * Duncommitted(<address>, <a|b|x>, <a|b|x>, <a|b|x>, <a|b|x>) - Write to the uncommitted switches of the a DISEC device.
+ * The parameters are for switch1, switch2, switch3, switch4, and may be set to position a or b.
+ * The special value 'x' means "no change to this switch".
+ *
+ * Dfrequency(<address>, <frequency in GHz>) - set the frequency of a DISEC device.
+ * Dchannel(<address>, <channel id>) - set the desired channel id of a DISEC device.
+ * Dgotopreset(<address>, <preset id>) - tell a DISEC satellite positioner to move to the given preset id.
+ * Dgotobearing(<address>, <bearing in degrees>) - tell a DISEQC terrestrial rotator to go to the
+ * given bearing (range -256.0 -> 512.0 degrees, fractions allowed).
+ *
+ * In the above DISEQC commands, <address> is the integer (normally in hex format) address of the
+ * diseqc device to communicate with. A list of possiblities is as follows:
+ *
+ * DISEQC_ADDRESS_ANY_DEVICE = 0x00
+ *
+ * DISEQC_ADDRESS_ANY_LNB_SWITCHER_SMATV = 0x10
+ * DISEQC_ADDRESS_LNB = 0x11
+ * DISEQC_ADDRESS_LNB_WITH_LOOP = 0x12
+ * DISEQC_ADDRESS_SWITCHER = 0x14
+ * DISEQC_ADDRESS_SWITCHER_WITH_LOOP = 0x15
+ * DISEQC_ADDRESS_SMATV = 0x18
+ *
+ * DISEQC_ADDRESS_ANY_POLARISER = 0x20
+ * DISEQC_ADDRESS_LINEAR_POLARISER = 0x21
+ *
+ * DISEQC_ADDRESS_ANY_POSITIONER = 0x30
+ * DISEQC_ADDRESS_POLAR_AZIMUTH_POSITIONER = 0x31
+ * DISEQC_ADDRESS_ELEVATION_POSITIONER = 0x32
+ *
+ * DISEQC_ADDRESS_ANY_INSTALLER_AID = 0x40
+ * DISEQC_ADDRESS_SIGNAL_STRENGTH = 0x41
+ *
+ * DISEQC_ADDRESS_ANY_INTERFACE = 0x70
+ * DISEQC_ADDRESS_HEADEND_INTERFACE = 0x71
+ *
+ * DISEQC_ADDRESS_REALLOC_BASE = 0x60
+ * DISEQC_ADDRESS_OEM_BASE = 0xf0
+ */
+
+#ifndef DVBSEC_CFG_H
+#define DVBSEC_CFG_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <libdvbsec/dvbsec_api.h>
+
+/**
+ * Callback function used in dvbsec_cfg_load().
+ *
+ * @param arg Private information to caller.
+ * @param channel The current channel details.
+ * @return 0 to continue, 1 to stop loading.
+ */
+typedef int (*dvbsec_cfg_callback)(void *arg, struct dvbsec_config *sec);
+
+/**
+ * Load an SEC file.
+ *
+ * @param f File to load from.
+ * @param arg Value to pass to 'arg' in callback above.
+ * @param cb Callback function called for each sec loaded from the file.
+ * @return 0 on success, or nonzero error code on failure.
+ */
+extern int dvbsec_cfg_load(FILE *f, void *arg,
+ dvbsec_cfg_callback cb);
+
+/**
+ * Convenience function to parse an SEC config file. This will also consult the set
+ * of hardcoded defaults if no config file was supplied, or a match was not found in
+ * the config file.
+ *
+ * @param config_file Config filename to load, or NULL to just check defaults.
+ * @param sec_id ID of SEC configuration.
+ * @param sec Where to put the details if found.
+ * @return 0 on success, nonzero on error.
+ */
+extern int dvbsec_cfg_find(const char *config_file,
+ const char *sec_id,
+ struct dvbsec_config *sec);
+
+/**
+ * Save SEC format config file.
+ *
+ * @param f File to save to.
+ * @param secs Pointer to array of SECs to save.
+ * @param count Number of entries in the above array.
+ * @return 0 on success, or nonzero error code on failure.
+ */
+extern int dvbsec_cfg_save(FILE *f,
+ struct dvbsec_config *secs,
+ int count);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/Makefile b/lib/libesg/Makefile
new file mode 100644
index 0000000..abb9d4f
--- /dev/null
+++ b/lib/libesg/Makefile
@@ -0,0 +1,27 @@
+# Makefile for linuxtv.org dvb-apps/lib/libesg
+
+includes = types.h
+
+objects = types.o
+
+lib_name = libesg
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include bootstrap/Makefile
+include encapsulation/Makefile
+include representation/Makefile
+include transport/Makefile
+
+.PHONY: $(sub-install)
+
+install:: $(sub-install)
+
+$(sub-install):
+ $(MAKE) -C $@ install
+
+include ../../Make.rules
diff --git a/lib/libesg/TODO b/lib/libesg/TODO
new file mode 100644
index 0000000..952215a
--- /dev/null
+++ b/lib/libesg/TODO
@@ -0,0 +1,18 @@
+*** General
+- Add enums for constants
+
+*** EncodingVersion
+- GZIP : use zlib
+- BiM : ???
+
+*** BOOTSTRAP
+- ESGProviderDiscoveryDescriptor : XML parsing with libexpat ?
+
+*** TRANSPORT
+- Indexation
+
+*** ENCAPSULATION
+- Auxiliary Data
+
+*** REPRESENTATION
+- BiM Decoder Init
diff --git a/lib/libesg/bootstrap/Makefile b/lib/libesg/bootstrap/Makefile
new file mode 100644
index 0000000..16a2457
--- /dev/null
+++ b/lib/libesg/bootstrap/Makefile
@@ -0,0 +1,24 @@
+# Makefile for linuxtv.org dvb-apps/lib/libesg/bootstrap
+
+.PHONY: sub-error-bootstrap
+
+sub-error-bootstrap:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += bootstrap/access_descriptor.o \
+ bootstrap/provider_discovery_descriptor.o
+
+sub-install += bootstrap
+
+else
+
+includes = access_descriptor.h \
+ provider_discovery_descriptor.h
+
+include ../../../Make.rules
+
+lib_name = libesg/bootstrap
+
+endif
diff --git a/lib/libesg/bootstrap/access_descriptor.c b/lib/libesg/bootstrap/access_descriptor.c
new file mode 100644
index 0000000..e8f89a3
--- /dev/null
+++ b/lib/libesg/bootstrap/access_descriptor.c
@@ -0,0 +1,115 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/bootstrap/access_descriptor.h>
+
+struct esg_access_descriptor *esg_access_descriptor_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_access_descriptor *access_descriptor;
+ struct esg_entry *entry;
+ struct esg_entry *last_entry;
+ uint32_t entry_length;
+ uint16_t entry_index;
+ uint8_t ip_index;
+
+ if ((buffer == NULL) || (size <= 2)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ access_descriptor = (struct esg_access_descriptor *) malloc(sizeof(struct esg_access_descriptor));
+ memset(access_descriptor, 0, sizeof(struct esg_access_descriptor));
+ access_descriptor->entry_list = NULL;
+
+ access_descriptor->n_o_entries = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ last_entry = NULL;
+ for (entry_index = 0; entry_index < access_descriptor->n_o_entries; entry_index++) {
+ entry = (struct esg_entry *) malloc(sizeof(struct esg_entry));
+ memset(entry, 0, sizeof(struct esg_entry));
+ entry->_next = NULL;
+
+ if (last_entry == NULL) {
+ access_descriptor->entry_list = entry;
+ } else {
+ last_entry->_next = entry;
+ }
+ last_entry = entry;
+
+ entry->version = buffer[pos];
+ pos += 1;
+
+ pos += vluimsbf8(buffer + pos, size - pos, &entry_length);
+
+ if (size < pos + entry_length) {
+ esg_access_descriptor_free(access_descriptor);
+ return NULL;
+ }
+
+ entry->multiple_stream_transport = (buffer[pos] & 0x80) ? 1 : 0;
+ entry->ip_version_6 = (buffer[pos] & 0x40) ? 1 : 0;
+ pos += 1;
+
+ entry->provider_id = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ if (entry->ip_version_6) {
+ for (ip_index = 0; ip_index < 16; ip_index++) {
+ entry->source_ip.ipv6[ip_index] = buffer[pos+ip_index];
+ entry->destination_ip.ipv6[ip_index] = buffer[pos+16+ip_index];
+ }
+ pos += 32;
+ } else {
+ for (ip_index = 0; ip_index < 4; ip_index++) {
+ entry->source_ip.ipv4[ip_index] = buffer[pos+ip_index];
+ entry->destination_ip.ipv4[ip_index] = buffer[pos+4+ip_index];
+ }
+ pos += 8;
+ }
+ entry->port = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ entry->tsi = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+ }
+
+ return access_descriptor;
+}
+
+void esg_access_descriptor_free(struct esg_access_descriptor *access_descriptor) {
+ struct esg_entry *entry;
+ struct esg_entry *next_entry;
+
+ if (access_descriptor == NULL) {
+ return;
+ }
+
+ for(entry = access_descriptor->entry_list; entry; entry = next_entry) {
+ next_entry = entry->_next;
+ free(entry);
+ }
+
+ free(access_descriptor);
+}
diff --git a/lib/libesg/bootstrap/access_descriptor.h b/lib/libesg/bootstrap/access_descriptor.h
new file mode 100644
index 0000000..49aec46
--- /dev/null
+++ b/lib/libesg/bootstrap/access_descriptor.h
@@ -0,0 +1,86 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_BOOTSTRAP_ACCESS_DESCRIPTOR_H
+#define _ESG_BOOTSTRAP_ACCESS_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libesg/types.h>
+
+/**
+ * esg_entry structure.
+ */
+struct esg_entry {
+ uint8_t version;
+ uint8_t multiple_stream_transport;
+ uint8_t ip_version_6;
+ uint16_t provider_id;
+ union esg_ip_address source_ip;
+ union esg_ip_address destination_ip;
+ uint16_t port;
+ uint16_t tsi;
+
+ struct esg_entry *_next;
+};
+
+/**
+ * esg_access_descriptor structure.
+ */
+struct esg_access_descriptor {
+ uint16_t n_o_entries;
+ struct esg_entry *entry_list;
+};
+
+/**
+ * Process an esg_access_descriptor.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_access_descriptor structure, or NULL on error.
+ */
+extern struct esg_access_descriptor *esg_access_descriptor_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_access_descriptor.
+ *
+ * @param esg Pointer to an esg_access_descriptor structure.
+ */
+extern void esg_access_descriptor_free(struct esg_access_descriptor *access_descriptor);
+
+/**
+ * Convenience iterator for esg_entry_list field of an esg_access_descriptor.
+ *
+ * @param access_descriptor The esg_access_descriptor pointer.
+ * @param entry Variable holding a pointer to the current esg_entry.
+ */
+#define esg_access_descriptor_entry_list_for_each(access_descriptor, entry) \
+ for ((entry) = (access_descriptor)->entry_list; \
+ (entry); \
+ (entry) = (entry)->_next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/bootstrap/provider_discovery_descriptor.c b/lib/libesg/bootstrap/provider_discovery_descriptor.c
new file mode 100644
index 0000000..833a038
--- /dev/null
+++ b/lib/libesg/bootstrap/provider_discovery_descriptor.c
@@ -0,0 +1,50 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/bootstrap/provider_discovery_descriptor.h>
+
+struct esg_provider_discovery_descriptor *esg_esg_provider_discovery_descriptor_decode(uint8_t *buffer, uint32_t size) {
+ struct esg_provider_discovery_descriptor *provider;
+
+ provider = (struct esg_provider_discovery_descriptor *) malloc(sizeof(struct esg_provider_discovery_descriptor));
+ memset(provider, 0, sizeof(struct esg_provider_discovery_descriptor));
+
+ provider->xml = (uint8_t *) malloc(size);
+ memcpy(provider->xml, buffer, size);
+
+ provider->size = size;
+
+ return provider;
+}
+
+void esg_provider_discovery_descriptor_free(struct esg_provider_discovery_descriptor *provider) {
+ if (provider == NULL) {
+ return;
+ }
+
+ if (provider->xml) {
+ free(provider->xml);
+ }
+
+ free(provider);
+}
diff --git a/lib/libesg/bootstrap/provider_discovery_descriptor.h b/lib/libesg/bootstrap/provider_discovery_descriptor.h
new file mode 100644
index 0000000..36065ec
--- /dev/null
+++ b/lib/libesg/bootstrap/provider_discovery_descriptor.h
@@ -0,0 +1,59 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_BOOTSTRAP_PROVIDER_DISCOVERY_DESCRIPTOR_H
+#define _ESG_BOOTSTRAP_PROVIDER_DISCOVERY_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_provider_discovery_descriptor structure.
+ */
+struct esg_provider_discovery_descriptor {
+ uint8_t *xml;
+ uint32_t size;
+};
+
+/**
+ * Process an esg_provider_discovery_descriptor.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_provider_discovery_descriptor structure, or NULL on error.
+ */
+extern struct esg_provider_discovery_descriptor *esg_esg_provider_discovery_descriptor_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_provider_discovery_descriptor.
+ *
+ * @param esg Pointer to an esg_provider_discovery_descriptor structure.
+ */
+extern void esg_provider_discovery_descriptor_free(struct esg_provider_discovery_descriptor *provider);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/encapsulation/Makefile b/lib/libesg/encapsulation/Makefile
new file mode 100644
index 0000000..2f222ed
--- /dev/null
+++ b/lib/libesg/encapsulation/Makefile
@@ -0,0 +1,28 @@
+# Makefile for linuxtv.org dvb-apps/lib/libesg/encapsulation
+
+.PHONY: sub-error-encapsulation
+
+sub-error-encapsulation:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += encapsulation/container.o \
+ encapsulation/fragment_management_information.o \
+ encapsulation/data_repository.o \
+ encapsulation/string_repository.o
+
+sub-install += encapsulation
+
+else
+
+includes = container.h \
+ fragment_management_information.h \
+ data_repository.h \
+ string_repository.h
+
+include ../../../Make.rules
+
+lib_name = libesg/encapsulation
+
+endif
diff --git a/lib/libesg/encapsulation/auxiliary_data.h b/lib/libesg/encapsulation/auxiliary_data.h
new file mode 100644
index 0000000..e05b241
--- /dev/null
+++ b/lib/libesg/encapsulation/auxiliary_data.h
@@ -0,0 +1,62 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_ENCAPSULATION_AUXILIARY_DATA_H
+#define _ESG_ENCAPSULATION_AUXILIARY_DATA_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_any_attribute structure.
+ */
+struct esg_any_attribute {
+ uint8_t version_id;
+ uint8_t *extension;
+
+ struct esg_any_attribure *_next;
+};
+
+/**
+ * esg_binary_header structure.
+ */
+struct esg_binary_header {
+ uint16_t encoding_metadatauri_mimetype;
+ struct esg_any_attribute *any_attribute_list;
+};
+
+/**
+ * esg_encapsulated_aux_data struct.
+ */
+struct esg_encapsulated_aux_data {
+ struct esg_binary_header *binary_header;
+ uint32_t aux_data_length;
+ uint8_t aux_data;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/encapsulation/container.c b/lib/libesg/encapsulation/container.c
new file mode 100644
index 0000000..15b17bf
--- /dev/null
+++ b/lib/libesg/encapsulation/container.c
@@ -0,0 +1,206 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/encapsulation/container.h>
+#include <libesg/encapsulation/fragment_management_information.h>
+#include <libesg/encapsulation/data_repository.h>
+#include <libesg/encapsulation/string_repository.h>
+#include <libesg/representation/init_message.h>
+#include <libesg/transport/session_partition_declaration.h>
+
+struct esg_container *esg_container_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_container *container;
+ struct esg_container_structure *structure;
+ struct esg_container_structure *last_structure;
+ uint8_t structure_index;
+
+ if ((buffer == NULL) || (size <= 1)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ container = (struct esg_container *) malloc(sizeof(struct esg_container));
+ memset(container, 0, sizeof(struct esg_container));
+
+ // Container header
+ container->header = (struct esg_container_header *) malloc(sizeof(struct esg_container_header));
+ memset(container->header, 0, sizeof(struct esg_container_header));
+
+ container->header->num_structures = buffer[pos];
+ pos += 1;
+
+ if (size < pos + (container->header->num_structures * 8)) {
+ esg_container_free(container);
+ return NULL;
+ }
+
+ last_structure = NULL;
+ for (structure_index = 0; structure_index < container->header->num_structures; structure_index++) {
+ structure = (struct esg_container_structure *) malloc(sizeof(struct esg_container_structure));
+ memset(structure, 0, sizeof(struct esg_container_structure));
+ structure->_next = NULL;
+
+ if (last_structure == NULL) {
+ container->header->structure_list = structure;
+ } else {
+ last_structure->_next = structure;
+ }
+ last_structure = structure;
+
+ structure->type = buffer[pos];
+ pos += 1;
+
+ structure->id = buffer[pos];
+ pos += 1;
+
+ structure->ptr = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2];
+ pos += 3;
+
+ structure->length = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2];
+ pos += 3;
+
+ if (size < (structure->ptr + structure->length)) {
+ esg_container_free(container);
+ return NULL;
+ }
+
+ // Decode structure
+ switch (structure->type) {
+ case 0x01: {
+ switch (structure->id) {
+ case 0x00: {
+ structure->data = (void *) esg_encapsulation_structure_decode(buffer + structure->ptr, structure->length);
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ break;
+ }
+ case 0x02: {
+ switch (structure->id) {
+ case 0x00: {
+ structure->data = (void *) esg_string_repository_decode(buffer + structure->ptr, structure->length);
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ break;
+ }
+ case 0x03: {
+ //TODO
+ break;
+ }
+ case 0x04: {
+ //TODO
+ break;
+ }
+ case 0x05: {
+ //TODO
+ break;
+ }
+ case 0xE0: {
+ switch (structure->id) {
+ case 0x00: {
+ structure->data = (void *) esg_data_repository_decode(buffer + structure->ptr, structure->length);
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ break;
+ }
+ case 0xE1: {
+ switch (structure->id) {
+ case 0xFF: {
+ structure->data = (void *) esg_session_partition_declaration_decode(buffer + structure->ptr, structure->length);
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ break;
+ }
+ case 0xE2: {
+ switch (structure->id) {
+ case 0x00: {
+ structure->data = (void *) esg_init_message_decode(buffer + structure->ptr, structure->length);
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ break;
+ }
+ default: {
+ esg_container_free(container);
+ return NULL;
+ }
+ }
+ }
+
+ // Container structure body
+ container->structure_body_ptr = pos;
+ container->structure_body_length = size - pos;
+ container->structure_body = (uint8_t *) malloc(size - pos);
+ memcpy(container->structure_body, buffer + pos, size - pos);
+
+ return container;
+}
+
+void esg_container_free(struct esg_container *container) {
+ struct esg_container_structure *structure;
+ struct esg_container_structure *next_structure;
+
+ if (container == NULL) {
+ return;
+ }
+
+ if (container->header) {
+ for(structure = container->header->structure_list; structure; structure = next_structure) {
+ next_structure = structure->_next;
+ free(structure);
+ }
+
+ free(container->header);
+ }
+
+ if (container->structure_body) {
+ free(container->structure_body);
+ }
+
+ free(container);
+}
diff --git a/lib/libesg/encapsulation/container.h b/lib/libesg/encapsulation/container.h
new file mode 100644
index 0000000..dc54ef2
--- /dev/null
+++ b/lib/libesg/encapsulation/container.h
@@ -0,0 +1,94 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_ENCAPSULATION_CONTAINER_H
+#define _ESG_ENCAPSULATION_CONTAINER_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_container_structure structure.
+ */
+struct esg_container_structure {
+ uint8_t type;
+ uint8_t id;
+ uint32_t ptr;
+ uint32_t length;
+
+ void *data;
+
+ struct esg_container_structure *_next;
+};
+
+/**
+ * esg_container_header structure.
+ */
+struct esg_container_header {
+ uint8_t num_structures;
+ struct esg_container_structure *structure_list;
+};
+
+/**
+ * esg_container structure
+ */
+struct esg_container {
+ struct esg_container_header *header;
+ uint32_t structure_body_ptr;
+ uint32_t structure_body_length;
+ uint8_t *structure_body;
+};
+
+/**
+ * Process an esg_container.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_container structure, or NULL on error.
+ */
+extern struct esg_container *esg_container_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_container.
+ *
+ * @param container Pointer to an esg_container structure.
+ */
+extern void esg_container_free(struct esg_container *container);
+
+/**
+ * Convenience iterator for structure_list field of an esg_container_header.
+ *
+ * @param container The esg_container_header pointer.
+ * @param structure Variable holding a pointer to the current esg_container_structure.
+ */
+#define esg_container_header_structure_list_for_each(header, structure) \
+ for ((structure) = (header)->structure_list; \
+ (structure); \
+ (structure) = (structure)->_next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/encapsulation/data_repository.c b/lib/libesg/encapsulation/data_repository.c
new file mode 100644
index 0000000..629e5ea
--- /dev/null
+++ b/lib/libesg/encapsulation/data_repository.c
@@ -0,0 +1,53 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/encapsulation/data_repository.h>
+
+struct esg_data_repository *esg_data_repository_decode(uint8_t *buffer, uint32_t size) {
+ struct esg_data_repository *data_repository;
+
+ if ((buffer == NULL) || (size <= 0)) {
+ return NULL;
+ }
+
+ data_repository = (struct esg_data_repository *) malloc(sizeof(struct esg_data_repository));
+ memset(data_repository, 0, sizeof(struct esg_data_repository));
+
+ data_repository->length = size;
+ data_repository->data = (uint8_t *) malloc(size);
+ memcpy(data_repository->data, buffer, size);
+
+ return data_repository;
+}
+
+void esg_data_repository_free(struct esg_data_repository *data_repository) {
+ if (data_repository == NULL) {
+ return;
+ }
+
+ if (data_repository->data) {
+ free(data_repository->data);
+ }
+
+ free(data_repository);
+}
diff --git a/lib/libesg/encapsulation/data_repository.h b/lib/libesg/encapsulation/data_repository.h
new file mode 100644
index 0000000..4c691cf
--- /dev/null
+++ b/lib/libesg/encapsulation/data_repository.h
@@ -0,0 +1,59 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_ENCAPSULATION_DATA_REPOSITORY_H
+#define _ESG_ENCAPSULATION_DATA_REPOSITORY_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_data_repository structure.
+ */
+struct esg_data_repository {
+ uint32_t length;
+ uint8_t *data;
+};
+
+/**
+ * Process an esg_data_repository.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_data_repository structure, or NULL on error.
+ */
+extern struct esg_data_repository *esg_data_repository_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_data_repository.
+ *
+ * @param data_repository Pointer to an esg_data_repository structure.
+ */
+extern void esg_data_repository_free(struct esg_data_repository *data_repository);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/encapsulation/fragment_management_information.c b/lib/libesg/encapsulation/fragment_management_information.c
new file mode 100644
index 0000000..b08265d
--- /dev/null
+++ b/lib/libesg/encapsulation/fragment_management_information.c
@@ -0,0 +1,118 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/encapsulation/fragment_management_information.h>
+
+struct esg_encapsulation_structure *esg_encapsulation_structure_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_encapsulation_structure *structure;
+ struct esg_encapsulation_entry *entry;
+ struct esg_encapsulation_entry *last_entry;
+
+ if ((buffer == NULL) || (size <= 2)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ structure = (struct esg_encapsulation_structure *) malloc(sizeof(struct esg_encapsulation_structure));
+ memset(structure, 0, sizeof(struct esg_encapsulation_structure));
+ structure->entry_list = NULL;
+
+ // Encapsulation header
+ structure->header = (struct esg_encapsulation_header *) malloc(sizeof(struct esg_encapsulation_header));
+ // buffer[pos] reserved
+ structure->header->fragment_reference_format = buffer[pos+1];
+ pos += 2;
+
+ // Encapsulation entry list
+ last_entry = NULL;
+ while (size > pos) {
+ entry = (struct esg_encapsulation_entry *) malloc(sizeof(struct esg_encapsulation_entry));
+ memset(entry, 0, sizeof(struct esg_encapsulation_entry));
+ entry->_next = NULL;
+
+ if (last_entry == NULL) {
+ structure->entry_list = entry;
+ } else {
+ last_entry->_next = entry;
+ }
+ last_entry = entry;
+
+ // Fragment reference
+ switch (structure->header->fragment_reference_format) {
+ case 0x21: {
+ entry->fragment_reference = (struct esg_fragment_reference *) malloc(sizeof(struct esg_fragment_reference));
+ memset(entry->fragment_reference, 0, sizeof(struct esg_fragment_reference));
+
+ entry->fragment_reference->fragment_type = buffer[pos];
+ pos += 1;
+
+ entry->fragment_reference->data_repository_offset = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2];
+ pos += 3;
+
+ break;
+ }
+ default: {
+ esg_encapsulation_structure_free(structure);
+ return NULL;
+ }
+ }
+
+ // Fragment version & id
+ entry->fragment_version = buffer[pos];
+ pos += 1;
+
+ entry->fragment_id = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2];
+ pos += 3;
+ }
+
+ return structure;
+}
+
+void esg_encapsulation_structure_free(struct esg_encapsulation_structure *structure) {
+ struct esg_encapsulation_entry *entry;
+ struct esg_encapsulation_entry *next_entry;
+
+ if (structure == NULL) {
+ return;
+ }
+
+ if (structure->header) {
+ free(structure->header);
+ }
+
+ if (structure->entry_list) {
+ for(entry = structure->entry_list; entry; entry = next_entry) {
+ next_entry = entry->_next;
+ if (entry->fragment_reference) {
+ free(entry->fragment_reference);
+ }
+ free(entry);
+ }
+
+ free(structure->entry_list);
+ }
+
+ free(structure);
+}
diff --git a/lib/libesg/encapsulation/fragment_management_information.h b/lib/libesg/encapsulation/fragment_management_information.h
new file mode 100644
index 0000000..04050b5
--- /dev/null
+++ b/lib/libesg/encapsulation/fragment_management_information.h
@@ -0,0 +1,96 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_ENCAPSULATION_FRAGMENT_MANAGEMENT_INFORMATION_H
+#define _ESG_ENCAPSULATION_FRAGMENT_MANAGEMENT_INFORMATION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_encapsulation_header structure.
+ */
+struct esg_encapsulation_header {
+ uint8_t fragment_reference_format;
+};
+
+/**
+ * esg_fragment_reference structure.
+ */
+struct esg_fragment_reference {
+ uint8_t fragment_type;
+ uint32_t data_repository_offset;
+};
+
+/**
+ * esg_encapsulation_entry structure.
+ */
+struct esg_encapsulation_entry {
+ struct esg_fragment_reference *fragment_reference;
+ uint8_t fragment_version;
+ uint32_t fragment_id;
+
+ struct esg_encapsulation_entry *_next;
+};
+
+/**
+ * esg_encapsulation_structure structure.
+ */
+struct esg_encapsulation_structure {
+ struct esg_encapsulation_header *header;
+ struct esg_encapsulation_entry *entry_list;
+};
+
+/**
+ * Process an esg_encapsulation_structure.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_encapsulation_structure structure, or NULL on error.
+ */
+extern struct esg_encapsulation_structure *esg_encapsulation_structure_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_encapsulation_structure.
+ *
+ * @param container Pointer to an esg_container structure.
+ */
+extern void esg_encapsulation_structure_free(struct esg_encapsulation_structure *structure);
+
+/**
+ * Convenience iterator for entry_list field of an esg_encapsulation_structure.
+ *
+ * @param structure The esg_encapsulation_structure pointer.
+ * @param entry Variable holding a pointer to the current esg_encapsulation_entry.
+ */
+#define esg_encapsulation_structure_entry_list_for_each(structure, entry) \
+ for ((entry) = (structure)->entry_list; \
+ (entry); \
+ (entry) = (entry)->_next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/encapsulation/string_repository.c b/lib/libesg/encapsulation/string_repository.c
new file mode 100644
index 0000000..3b88742
--- /dev/null
+++ b/lib/libesg/encapsulation/string_repository.c
@@ -0,0 +1,54 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/encapsulation/string_repository.h>
+
+struct esg_string_repository *esg_string_repository_decode(uint8_t *buffer, uint32_t size) {
+ struct esg_string_repository *string_repository;
+
+ if ((buffer == NULL) || (size <= 1)) {
+ return NULL;
+ }
+
+ string_repository = (struct esg_string_repository *) malloc(sizeof(struct esg_string_repository));
+ memset(string_repository, 0, sizeof(struct esg_string_repository));
+
+ string_repository->encoding_type = buffer[0];
+ string_repository->length = size-1;
+ string_repository->data = (uint8_t *) malloc(size-1);
+ memcpy(string_repository->data, buffer+1, size-1);
+
+ return string_repository;
+}
+
+void esg_string_repository_free(struct esg_string_repository *string_repository) {
+ if (string_repository == NULL) {
+ return;
+ }
+
+ if (string_repository->data) {
+ free(string_repository->data);
+ }
+
+ free(string_repository);
+}
diff --git a/lib/libesg/encapsulation/string_repository.h b/lib/libesg/encapsulation/string_repository.h
new file mode 100644
index 0000000..0cf64c2
--- /dev/null
+++ b/lib/libesg/encapsulation/string_repository.h
@@ -0,0 +1,60 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_ENCAPSULATION_STRING_REPOSITORY_H
+#define _ESG_ENCAPSULATION_STRING_REPOSITORY_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_string_repository structure.
+ */
+struct esg_string_repository {
+ uint8_t encoding_type;
+ uint32_t length;
+ uint8_t *data;
+};
+
+/**
+ * Process an esg_string_repository.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_string_repository structure, or NULL on error.
+ */
+extern struct esg_string_repository *esg_string_repository_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_string_repository.
+ *
+ * @param data_repository Pointer to an esg_string_repository structure.
+ */
+extern void esg_string_repository_free(struct esg_string_repository *string_repository);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/representation/Makefile b/lib/libesg/representation/Makefile
new file mode 100644
index 0000000..059f8bd
--- /dev/null
+++ b/lib/libesg/representation/Makefile
@@ -0,0 +1,26 @@
+# Makefile for linuxtv.org dvb-apps/lib/libesg/representation
+
+.PHONY: sub-error-representation
+
+sub-error-representation:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += representation/encapsulated_textual_esg_xml_fragment.o \
+ representation/init_message.o \
+ representation/textual_decoder_init.o
+
+sub-install += representation
+
+else
+
+includes = encapsulated_textual_esg_xml_fragment.h \
+ init_message.h \
+ textual_decoder_init.h
+
+include ../../../Make.rules
+
+lib_name = libesg/representation
+
+endif
diff --git a/lib/libesg/representation/bim_decoder_init.h b/lib/libesg/representation/bim_decoder_init.h
new file mode 100644
index 0000000..4860da9
--- /dev/null
+++ b/lib/libesg/representation/bim_decoder_init.h
@@ -0,0 +1,40 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_REPRESENTATION_BIM_DECODER_INIT_H
+#define _ESG_REPRESENTATION_BIM_DECODER_INIT_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * esg_bim_decoder_init structure.
+ */
+struct esg_bim_decoder_init {
+// TODO
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h b/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h
new file mode 100644
index 0000000..8ab39dd
--- /dev/null
+++ b/lib/libesg/representation/encapsulated_bim_esg_xml_fragment.h
@@ -0,0 +1,40 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_REPRESENTATION_ENCAPSULATED_BIM_ESG_XML_FRAGMENT_H
+#define _ESG_REPRESENTATION_ENCAPSULATED_BIM_ESG_XML_FRAGMENT_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * esg_encapsulated_bim_esg_xml_fragment structure.
+ */
+struct esg_encapsulated_bim_esg_xml_fragment {
+ //TODO
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c
new file mode 100644
index 0000000..199c857
--- /dev/null
+++ b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.c
@@ -0,0 +1,70 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/types.h>
+#include <libesg/representation/encapsulated_textual_esg_xml_fragment.h>
+
+struct esg_encapsulated_textual_esg_xml_fragment *esg_encapsulated_textual_esg_xml_fragment_decode(uint8_t *buffer, uint32_t size) {
+ struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment;
+ uint32_t pos;
+ uint32_t length;
+ uint8_t offset_pos;
+
+ if ((buffer == NULL) || (size <= 0)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ esg_xml_fragment = (struct esg_encapsulated_textual_esg_xml_fragment *) malloc(sizeof(struct esg_encapsulated_textual_esg_xml_fragment));
+ memset(esg_xml_fragment, 0, sizeof(struct esg_encapsulated_textual_esg_xml_fragment));
+
+ offset_pos = vluimsbf8(buffer+pos+2, size-pos-2, &length);
+
+ if (size-pos-2 < offset_pos+length) {
+ esg_encapsulated_textual_esg_xml_fragment_free(esg_xml_fragment);
+ return NULL;
+ }
+
+ esg_xml_fragment->esg_xml_fragment_type = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2+offset_pos;
+
+ esg_xml_fragment->data_length = length;
+ esg_xml_fragment->data = (uint8_t *) malloc(length);
+ memcpy(esg_xml_fragment->data, buffer+pos, length);
+ pos += length;
+
+ return esg_xml_fragment;
+}
+
+void esg_encapsulated_textual_esg_xml_fragment_free(struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment) {
+ if (esg_xml_fragment == NULL) {
+ return;
+ }
+
+ if (esg_xml_fragment->data) {
+ free(esg_xml_fragment->data);
+ }
+
+ free(esg_xml_fragment);
+}
diff --git a/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h
new file mode 100644
index 0000000..ee8aba1
--- /dev/null
+++ b/lib/libesg/representation/encapsulated_textual_esg_xml_fragment.h
@@ -0,0 +1,60 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_REPRESENTATION_ENCAPSULATED_TEXTUAL_ESG_XML_FRAGMENT_H
+#define _ESG_REPRESENTATION_ENCAPSULATED_TEXTUAL_ESG_XML_FRAGMENT_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_encapsulated_textual_esg_xml_fragment structure.
+ */
+struct esg_encapsulated_textual_esg_xml_fragment {
+ uint16_t esg_xml_fragment_type;
+ uint32_t data_length;
+ uint8_t *data;
+};
+
+/**
+ * Process an esg_encapsulated_textual_esg_xml_fragment.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_encapsulated_textual_esg_xml_fragment structure, or NULL on error.
+ */
+extern struct esg_encapsulated_textual_esg_xml_fragment *esg_encapsulated_textual_esg_xml_fragment_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_encapsulated_textual_esg_xml_fragment.
+ *
+ * @param data_repository Pointer to an esg_encapsulated_textual_esg_xml_fragment structure.
+ */
+extern void esg_encapsulated_textual_esg_xml_fragment_free(struct esg_encapsulated_textual_esg_xml_fragment *esg_xml_fragment);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/representation/init_message.c b/lib/libesg/representation/init_message.c
new file mode 100644
index 0000000..0038607
--- /dev/null
+++ b/lib/libesg/representation/init_message.c
@@ -0,0 +1,112 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/representation/init_message.h>
+#include <libesg/representation/textual_decoder_init.h>
+#include <libesg/representation/bim_decoder_init.h>
+
+struct esg_init_message *esg_init_message_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_init_message *init_message;
+
+ if ((buffer == NULL) || (size <= 3)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ init_message = (struct esg_init_message *) malloc(sizeof(struct esg_init_message));
+ memset(init_message, 0, sizeof(struct esg_init_message));
+
+ init_message->encoding_version = buffer[pos];
+ pos += 1;
+
+ init_message->indexing_flag = (buffer[pos] & 0x80) >> 7;
+ pos += 1;
+
+ init_message->decoder_init_ptr = buffer[pos];
+ pos += 1;
+
+ if (init_message->indexing_flag) {
+ init_message->indexing_version = buffer[pos];
+ pos += 1;
+ }
+
+ switch (init_message->encoding_version) {
+ case 0xF1: {
+ struct esg_bim_encoding_parameters *encoding_parameters = (struct esg_bim_encoding_parameters *) malloc(sizeof(struct esg_bim_encoding_parameters));
+ memset(encoding_parameters, 0, sizeof(struct esg_bim_encoding_parameters));
+ init_message->encoding_parameters = (void *) encoding_parameters;
+
+ encoding_parameters->buffer_size_flag = (buffer[pos] & 0x80) >> 7;
+ encoding_parameters->position_code_flag = (buffer[pos] & 0x40) >> 6;
+ pos += 1;
+
+ encoding_parameters->character_encoding = buffer[pos];
+ pos += 1;
+
+ if (encoding_parameters->buffer_size_flag) {
+ encoding_parameters->buffer_size = (buffer[pos] << 16) | (buffer[pos+1] << 8) | buffer[pos+2];
+ pos += 3;
+ }
+
+// TODO
+// init_message->decoder_init = (void *) esg_bim_decoder_init_decode(buffer + init_message->decoder_init_ptr, size - init_message->decoder_init_ptr);
+ break;
+ }
+ case 0xF2:
+ case 0xF3: {
+ struct esg_textual_encoding_parameters *encoding_parameters = (struct esg_textual_encoding_parameters *) malloc(sizeof(struct esg_textual_encoding_parameters));
+ memset(encoding_parameters, 0, sizeof(struct esg_textual_encoding_parameters));
+ init_message->encoding_parameters = (void *) encoding_parameters;
+
+ encoding_parameters->character_encoding = buffer[pos];
+ pos += 1;
+
+ init_message->decoder_init = (void *) esg_textual_decoder_init_decode(buffer + init_message->decoder_init_ptr, size - init_message->decoder_init_ptr);
+ break;
+ }
+ default: {
+ esg_init_message_free(init_message);
+ return NULL;
+ }
+ }
+
+ return init_message;
+}
+
+void esg_init_message_free(struct esg_init_message *init_message) {
+ if (init_message == NULL) {
+ return;
+ }
+
+ if (init_message->encoding_parameters) {
+ free(init_message->encoding_parameters);
+ }
+
+ if (init_message->decoder_init) {
+ free(init_message->decoder_init);
+ }
+
+ free(init_message);
+}
diff --git a/lib/libesg/representation/init_message.h b/lib/libesg/representation/init_message.h
new file mode 100644
index 0000000..a525495
--- /dev/null
+++ b/lib/libesg/representation/init_message.h
@@ -0,0 +1,80 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_REPRESENTATION_INIT_MESSAGE_H
+#define _ESG_REPRESENTATION_INIT_MESSAGE_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_textual_encoding_parameters structure.
+ */
+struct esg_textual_encoding_parameters {
+ uint8_t character_encoding;
+};
+
+/**
+ * esg_bim_encoding_parameters structure.
+ */
+struct esg_bim_encoding_parameters {
+ uint8_t buffer_size_flag;
+ uint8_t position_code_flag;
+ uint8_t character_encoding;
+ uint32_t buffer_size; // if buffer_size_flag
+};
+
+/**
+ * esg_init_message structure.
+ */
+struct esg_init_message {
+ uint8_t encoding_version;
+ uint8_t indexing_flag;
+ uint8_t decoder_init_ptr;
+ uint8_t indexing_version; // if indexing_flag
+ void *encoding_parameters;
+ void *decoder_init;
+};
+
+/**
+ * Process an esg_init_message.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_string_repository structure, or NULL on error.
+ */
+extern struct esg_init_message *esg_init_message_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_init_message.
+ *
+ * @param init_message Pointer to an esg_init_message structure.
+ */
+extern void esg_init_message_free(struct esg_init_message *init_message);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/representation/textual_decoder_init.c b/lib/libesg/representation/textual_decoder_init.c
new file mode 100644
index 0000000..c797d0e
--- /dev/null
+++ b/lib/libesg/representation/textual_decoder_init.c
@@ -0,0 +1,128 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/types.h>
+#include <libesg/representation/textual_decoder_init.h>
+
+struct esg_textual_decoder_init *esg_textual_decoder_init_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_textual_decoder_init *decoder_init;
+ struct esg_namespace_prefix *namespace_prefix;
+ struct esg_namespace_prefix *last_namespace_prefix;
+ struct esg_xml_fragment_type *xml_fragment_type;
+ struct esg_xml_fragment_type *last_xml_fragment_type;
+ uint32_t decoder_init_length;
+ uint8_t num_index;
+
+ if ((buffer == NULL) || (size <= 1)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ decoder_init = (struct esg_textual_decoder_init *) malloc(sizeof(struct esg_textual_decoder_init));
+ memset(decoder_init, 0, sizeof(struct esg_textual_decoder_init));
+ decoder_init->namespace_prefix_list = NULL;
+ decoder_init->xml_fragment_type_list = NULL;
+
+ decoder_init->version = buffer[pos];
+ pos += 1;
+
+ pos += vluimsbf8(buffer+pos, size-pos, &decoder_init_length);
+
+ if (size < pos + decoder_init_length) {
+ esg_textual_decoder_init_free(decoder_init);
+ return NULL;
+ }
+
+ decoder_init->num_namespace_prefixes = buffer[pos];
+ pos += 1;
+
+ last_namespace_prefix = NULL;
+ for (num_index = 0; num_index < decoder_init->num_namespace_prefixes; num_index++) {
+ namespace_prefix = (struct esg_namespace_prefix *) malloc(sizeof(struct esg_namespace_prefix));
+ memset(namespace_prefix, 0, sizeof(struct esg_namespace_prefix));
+ namespace_prefix->_next = NULL;
+
+ if (last_namespace_prefix == NULL) {
+ decoder_init->namespace_prefix_list = namespace_prefix;
+ } else {
+ last_namespace_prefix->_next = namespace_prefix;
+ }
+ last_namespace_prefix = namespace_prefix;
+
+ namespace_prefix->prefix_string_ptr = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ namespace_prefix->namespace_uri_ptr = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+ }
+
+ decoder_init->num_fragment_types = buffer[pos];
+ pos += 1;
+
+ last_xml_fragment_type = NULL;
+ for (num_index = 0; num_index < decoder_init->num_fragment_types; num_index++) {
+ xml_fragment_type = (struct esg_xml_fragment_type *) malloc(sizeof(struct esg_xml_fragment_type));
+ memset(xml_fragment_type, 0, sizeof(struct esg_xml_fragment_type));
+ xml_fragment_type->_next = NULL;
+
+ if (last_xml_fragment_type == NULL) {
+ decoder_init->xml_fragment_type_list = xml_fragment_type;
+ } else {
+ last_xml_fragment_type->_next = xml_fragment_type;
+ }
+ last_xml_fragment_type = xml_fragment_type;
+
+ xml_fragment_type->xpath_ptr = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ xml_fragment_type->xml_fragment_type = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+ }
+
+ return decoder_init;
+}
+
+void esg_textual_decoder_init_free(struct esg_textual_decoder_init *decoder_init) {
+ struct esg_namespace_prefix *namespace_prefix;
+ struct esg_namespace_prefix *next_namespace_prefix;
+ struct esg_xml_fragment_type *xml_fragment_type;
+ struct esg_xml_fragment_type *next_xml_fragment_type;
+
+ if (decoder_init == NULL) {
+ return;
+ }
+
+ for(namespace_prefix = decoder_init->namespace_prefix_list; namespace_prefix; namespace_prefix = next_namespace_prefix) {
+ next_namespace_prefix = namespace_prefix->_next;
+ free(namespace_prefix);
+ }
+
+ for(xml_fragment_type = decoder_init->xml_fragment_type_list; xml_fragment_type; xml_fragment_type = next_xml_fragment_type) {
+ next_xml_fragment_type = xml_fragment_type->_next;
+ free(xml_fragment_type);
+ }
+
+ free(decoder_init);
+}
diff --git a/lib/libesg/representation/textual_decoder_init.h b/lib/libesg/representation/textual_decoder_init.h
new file mode 100644
index 0000000..c1352cc
--- /dev/null
+++ b/lib/libesg/representation/textual_decoder_init.h
@@ -0,0 +1,104 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_REPRESENTATION_TEXTUAL_DECODER_INIT_H
+#define _ESG_REPRESENTATION_TEXTUAL_DECODER_INIT_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_namespace_prefix structure.
+ */
+struct esg_namespace_prefix {
+ uint16_t prefix_string_ptr;
+ uint16_t namespace_uri_ptr;
+
+ struct esg_namespace_prefix *_next;
+};
+
+/**
+ * esg_fragment_type structure.
+ */
+struct esg_xml_fragment_type {
+ uint16_t xpath_ptr;
+ uint16_t xml_fragment_type;
+
+ struct esg_xml_fragment_type *_next;
+};
+
+/**
+ * esg_textual_decoder_init structure.
+ */
+struct esg_textual_decoder_init {
+ uint8_t version;
+ uint8_t num_namespace_prefixes;
+ struct esg_namespace_prefix *namespace_prefix_list;
+ uint8_t num_fragment_types;
+ struct esg_xml_fragment_type *xml_fragment_type_list;
+};
+
+/**
+ * Process an esg_textual_decoder_init.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_textual_decoder_init structure, or NULL on error.
+ */
+extern struct esg_textual_decoder_init *esg_textual_decoder_init_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_textual_decoder_init.
+ *
+ * @param decoder_init Pointer to an esg_textual_decoder_init structure.
+ */
+extern void esg_textual_decoder_init_free(struct esg_textual_decoder_init *decoder_init);
+
+/**
+ * Convenience iterator for namespace_prefix_list field of an esg_textual_decoder_init.
+ *
+ * @param decoder_init The esg_textual_decoder_init pointer.
+ * @param namespace_prefix Variable holding a pointer to the current esg_namespace_prefix.
+ */
+#define esg_textual_decoder_namespace_prefix_list_for_each(decoder_init, namespace_prefix) \
+ for ((namespace_prefix) = (decoder_init)->namespace_prefix_list; \
+ (namespace_prefix); \
+ (namespace_prefix) = (namespace_prefix)->_next)
+
+/**
+ * Convenience iterator for xml_fragment_type_list field of an esg_textual_decoder_init.
+ *
+ * @param decoder_init The esg_textual_decoder_init pointer.
+ * @param xml_fragment_type Variable holding a pointer to the current esg_xml_fragment_type.
+ */
+#define esg_textual_decoder_xml_fragment_type_list_for_each(decoder_init, xml_fragment_type) \
+ for ((xml_fragment_type) = (decoder_init)->xml_fragment_type_list; \
+ (xml_fragment_type); \
+ (xml_fragment_type) = (xml_fragment_type)->_next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/transport/Makefile b/lib/libesg/transport/Makefile
new file mode 100644
index 0000000..7900770
--- /dev/null
+++ b/lib/libesg/transport/Makefile
@@ -0,0 +1,22 @@
+# Makefile for linuxtv.org dvb-apps/lib/libesg/transport
+
+.PHONY: sub-error-transport
+
+sub-error-transport:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += transport/session_partition_declaration.o
+
+sub-install += transport
+
+else
+
+includes = session_partition_declaration.h
+
+include ../../../Make.rules
+
+lib_name = libesg/transport
+
+endif
diff --git a/lib/libesg/transport/session_partition_declaration.c b/lib/libesg/transport/session_partition_declaration.c
new file mode 100644
index 0000000..d590bd3
--- /dev/null
+++ b/lib/libesg/transport/session_partition_declaration.c
@@ -0,0 +1,253 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libesg/transport/session_partition_declaration.h>
+
+struct esg_session_partition_declaration *esg_session_partition_declaration_decode(uint8_t *buffer, uint32_t size) {
+ uint32_t pos;
+ struct esg_session_partition_declaration *partition;
+ struct esg_session_field *field;
+ struct esg_session_field *last_field;
+ uint8_t field_index;
+ struct esg_session_ip_stream *ip_stream;
+ struct esg_session_ip_stream *last_ip_stream;
+ uint8_t ip_stream_index;
+ uint8_t ip_index;
+ struct esg_session_ip_stream_field *ip_stream_field;
+ struct esg_session_ip_stream_field *last_ip_stream_field;
+ uint8_t *field_buffer;
+ uint32_t field_length;
+ union esg_session_ip_stream_field_value *field_value;
+
+ if ((buffer == NULL) || (size <= 2)) {
+ return NULL;
+ }
+
+ pos = 0;
+
+ partition = (struct esg_session_partition_declaration *) malloc(sizeof(struct esg_session_partition_declaration));
+ memset(partition, 0, sizeof(struct esg_session_partition_declaration));
+ partition->field_list = NULL;
+ partition->ip_stream_list = NULL;
+
+ partition->num_fields = buffer[pos];
+ pos += 1;
+
+ partition->overlapping = (buffer[pos] & 0x80) ? 1 : 0;
+ pos += 1;
+
+ if (size < (pos + 5*(partition->num_fields))) {
+ esg_session_partition_declaration_free(partition);
+ return NULL;
+ }
+
+ last_field = NULL;
+ for (field_index = 0; field_index < partition->num_fields; field_index++) {
+ field = (struct esg_session_field *) malloc(sizeof(struct esg_session_field));
+ memset(field, 0, sizeof(struct esg_session_field));
+ field->_next = NULL;
+
+ if (last_field == NULL) {
+ partition->field_list = field;
+ } else {
+ last_field->_next = field;
+ }
+ last_field = field;
+
+ field->identifier = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ field->encoding = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ field->length = buffer[pos];
+ pos += 1;
+ }
+
+ partition->n_o_ip_streams = buffer[pos];
+ pos += 1;
+
+ partition->ip_version_6 = (buffer[pos] & 0x80) ? 1 : 0;
+ pos += 1;
+
+ last_ip_stream = NULL;
+ for (ip_stream_index = 0; ip_stream_index < partition->n_o_ip_streams; ip_stream_index++) {
+ ip_stream = (struct esg_session_ip_stream *) malloc(sizeof(struct esg_session_ip_stream));
+ memset(ip_stream, 0, sizeof(struct esg_session_ip_stream));
+ ip_stream->_next = NULL;
+
+ if (last_ip_stream == NULL) {
+ partition->ip_stream_list = ip_stream;
+ } else {
+ last_ip_stream->_next = ip_stream;
+ }
+ last_ip_stream = ip_stream;
+
+ ip_stream->id = buffer[pos];
+ pos += 1;
+
+ if (partition->ip_version_6) {
+ for (ip_index = 0; ip_index < 16; ip_index++) {
+ ip_stream->source_ip.ipv6[ip_index] = buffer[pos+ip_index];
+ ip_stream->destination_ip.ipv6[ip_index] = buffer[pos+16+ip_index];
+ }
+ pos += 32;
+ } else {
+ for (ip_index = 0; ip_index < 4; ip_index++) {
+ ip_stream->source_ip.ipv4[ip_index] = buffer[pos+ip_index];
+ ip_stream->destination_ip.ipv4[ip_index] = buffer[pos+4+ip_index];
+ }
+ pos += 8;
+ }
+ ip_stream->port = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ ip_stream->session_id = (buffer[pos] << 8) | buffer[pos+1];
+ pos += 2;
+
+ last_ip_stream_field = NULL;
+ esg_session_partition_declaration_field_list_for_each(partition, field) {
+ ip_stream_field = (struct esg_session_ip_stream_field *) malloc(sizeof(struct esg_session_ip_stream_field));
+ memset(ip_stream_field, 0, sizeof(struct esg_session_ip_stream_field));
+ ip_stream_field->_next = NULL;
+ ip_stream_field->start_field_value = NULL;
+ ip_stream_field->end_field_value = NULL;
+
+ if (last_ip_stream_field == NULL) {
+ ip_stream->field_list = ip_stream_field;
+ } else {
+ last_ip_stream_field->_next = ip_stream_field;
+ }
+ last_ip_stream_field = ip_stream_field;
+
+ field_length = field->length;
+ if (field->length != 0) {
+ field_length = field->length;
+ } else {
+ pos += vluimsbf8(buffer + pos, size - pos, &field_length);
+ }
+
+ switch (field->encoding) {
+ case 0x0000: {
+ if (partition->overlapping == 1) {
+ field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value));
+ memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value));
+ ip_stream_field->start_field_value = field_value;
+
+ field_buffer = (uint8_t *) malloc(field_length);
+ memset(field_buffer, 0, field_length);
+ memcpy(field_buffer, buffer + pos, field_length);
+
+ ip_stream_field->start_field_value->string = field_buffer;
+ pos += field_length;
+ }
+ field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value));
+ memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value));
+ ip_stream_field->end_field_value = field_value;
+
+ field_buffer = (uint8_t *) malloc(field_length);
+ memset(field_buffer, 0, field_length);
+ memcpy(field_buffer, buffer + pos, field_length);
+
+ ip_stream_field->end_field_value->string = field_buffer;
+ pos += field_length;
+
+ break;
+ }
+ case 0x0101: {
+ if (partition->overlapping == 1) {
+ field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value));
+ memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value));
+ ip_stream_field->start_field_value = field_value;
+
+ ip_stream_field->start_field_value->unsigned_short = (buffer[pos] << 8) | buffer[pos+1];
+ pos += field_length;
+ }
+ field_value = (union esg_session_ip_stream_field_value *) malloc(sizeof(union esg_session_ip_stream_field_value));
+ memset(field_value, 0, sizeof(union esg_session_ip_stream_field_value));
+ ip_stream_field->end_field_value = field_value;
+
+ ip_stream_field->end_field_value->unsigned_short = (buffer[pos] << 8) | buffer[pos+1];
+ pos += field_length;
+
+ break;
+ }
+ default: {
+ esg_session_partition_declaration_free(partition);
+ return NULL;
+ }
+ }
+ }
+ }
+
+ return partition;
+}
+
+void esg_session_partition_declaration_free(struct esg_session_partition_declaration *partition) {
+ struct esg_session_field *field;
+ struct esg_session_field *next_field;
+ struct esg_session_ip_stream *ip_stream;
+ struct esg_session_ip_stream *next_ip_stream;
+ struct esg_session_ip_stream_field *ip_stream_field;
+ struct esg_session_ip_stream_field *next_ip_stream_field;
+
+ if (partition == NULL) {
+ return;
+ }
+
+ for(ip_stream = partition->ip_stream_list; ip_stream; ip_stream = next_ip_stream) {
+ next_ip_stream = ip_stream->_next;
+
+ field = partition->field_list;
+ for(ip_stream_field = next_ip_stream->field_list; ip_stream_field; ip_stream_field = next_ip_stream_field) {
+ next_ip_stream_field = ip_stream_field->_next;
+
+ switch (field->encoding) {
+ case 0x0000: {
+ if (ip_stream_field->start_field_value != NULL) {
+ free(ip_stream_field->start_field_value->string);
+ }
+ free(ip_stream_field->end_field_value->string);
+ break;
+ }
+ case 0x0101: {
+ // Nothing to free
+ break;
+ }
+ }
+
+ free(ip_stream_field);
+
+ field = field->_next;
+ }
+
+ free(ip_stream);
+ }
+
+ for(field = partition->field_list; field; field = next_field) {
+ next_field = field->_next;
+ free(field);
+ }
+
+ free(partition);
+}
diff --git a/lib/libesg/transport/session_partition_declaration.h b/lib/libesg/transport/session_partition_declaration.h
new file mode 100644
index 0000000..8f2fa1a
--- /dev/null
+++ b/lib/libesg/transport/session_partition_declaration.h
@@ -0,0 +1,139 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_TRANSPORT_SESSION_PARTITION_DECLARATION_H
+#define _ESG_TRANSPORT_SESSION_PARTITION_DECLARATION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libesg/types.h>
+
+/**
+ * esg_session_field structure.
+ */
+struct esg_session_field {
+ uint16_t identifier;
+ uint16_t encoding;
+ uint8_t length;
+
+ struct esg_session_field *_next;
+};
+
+/**
+ * esg_session_ip_stream_field_value union.
+ */
+union esg_session_ip_stream_field_value {
+ uint8_t *string;
+ uint16_t unsigned_short;
+};
+
+/**
+ * esg_session_ip_stream_field structure.
+ */
+struct esg_session_ip_stream_field {
+ union esg_session_ip_stream_field_value *start_field_value;
+ union esg_session_ip_stream_field_value *end_field_value;
+
+ struct esg_session_ip_stream_field *_next;
+};
+
+/**
+ * esg_session_ip_stream structure.
+ */
+struct esg_session_ip_stream {
+ uint8_t id;
+ union esg_ip_address source_ip;
+ union esg_ip_address destination_ip;
+ uint16_t port;
+ uint16_t session_id;
+ struct esg_session_ip_stream_field *field_list;
+
+ struct esg_session_ip_stream *_next;
+};
+
+/**
+ * esg_session_partition_declaration structure.
+ */
+struct esg_session_partition_declaration {
+ uint8_t num_fields;
+ uint8_t overlapping;
+ struct esg_session_field *field_list;
+ uint8_t n_o_ip_streams;
+ uint8_t ip_version_6;
+ struct esg_session_ip_stream *ip_stream_list;
+};
+
+/**
+ * Process an esg_session_partition_declaration.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @return Pointer to an esg_session_partition_declaration structure, or NULL on error.
+ */
+extern struct esg_session_partition_declaration *esg_session_partition_declaration_decode(uint8_t *buffer, uint32_t size);
+
+/**
+ * Free an esg_session_partition_declaration.
+ *
+ * @param esg Pointer to an esg_session_partition_declaration structure.
+ */
+extern void esg_session_partition_declaration_free(struct esg_session_partition_declaration *partition);
+
+/**
+ * Convenience iterator for field_list field of an esg_session_partition_declaration.
+ *
+ * @param partition The esg_session_partition_declaration pointer.
+ * @param field Variable holding a pointer to the current esg_session_field.
+ */
+#define esg_session_partition_declaration_field_list_for_each(partition, field) \
+ for ((field) = (partition)->field_list; \
+ (field); \
+ (field) = (field)->_next)
+
+/**
+ * Convenience iterator for ip_stream_list field of an esg_session_partition_declaration.
+ *
+ * @param partition The esg_session_partition_declaration pointer.
+ * @param ip_stream Variable holding a pointer to the current esg_session_ip_stream.
+ */
+#define esg_session_partition_declaration_ip_stream_list_for_each(partition, ip_stream) \
+ for ((ip_stream) = (partition)->ip_stream_list; \
+ (ip_stream); \
+ (ip_stream) = (ip_stream)->_next)
+
+/**
+ * Convenience iterator for field_list field of an esg_session_ip_stream.
+ *
+ * @param ip_stream The esg_session_ip_stream pointer.
+ * @param field Variable holding a pointer to the current esg_session_ip_stream.
+ */
+#define esg_session_ip_stream_field_list_for_each(ip_stream, field) \
+ for ((field) = (ip_stream)->field_list; \
+ (field); \
+ (field) = (field)->_next)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/types.c b/lib/libesg/types.c
new file mode 100644
index 0000000..51f1cbd
--- /dev/null
+++ b/lib/libesg/types.c
@@ -0,0 +1,37 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libesg/types.h>
+
+uint8_t vluimsbf8(uint8_t *buffer, uint32_t size, uint32_t *length) {
+ uint8_t offset = 0;
+ *length = 0;
+
+ do {
+ if (size < offset) {
+ offset = 0;
+ *length = 0;
+ break;
+ }
+ *length = (*length << 7) + (buffer[offset] & 0x7F);
+ } while (buffer[offset++] & 0x80);
+
+ return offset;
+}
diff --git a/lib/libesg/types.h b/lib/libesg/types.h
new file mode 100644
index 0000000..b6725af
--- /dev/null
+++ b/lib/libesg/types.h
@@ -0,0 +1,53 @@
+/*
+ * ESG parser
+ *
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ESG_TYPES_H
+#define _ESG_TYPES_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+/**
+ * esg_ip_address
+ */
+union esg_ip_address {
+ uint8_t ipv4[4];
+ uint8_t ipv6[16];
+};
+
+/**
+ * Process a vluimsbf8 length.
+ *
+ * @param buffer Binary buffer to decode.
+ * @param size Binary buffer size.
+ * @param length Read length value
+ * @return vluimsbf8 size
+ */
+extern uint8_t vluimsbf8(uint8_t *buffer, uint32_t size, uint32_t *length);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libesg/xml/provider_discovery_descriptor.xsd b/lib/libesg/xml/provider_discovery_descriptor.xsd
new file mode 100644
index 0000000..5956343
--- /dev/null
+++ b/lib/libesg/xml/provider_discovery_descriptor.xsd
@@ -0,0 +1,22 @@
+<schema targetNamespace="urn:dvb:ipdc:esgbs:2005" xmlns:bs="urn:dvb:ipdc:esgbs:2005"
+ xmlns:mpeg7="urn:mpeg:mpeg7:schema:2001" xmlns="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified" attributeFormDefault="unqualified">
+ <import namespace="urn:mpeg:mpeg7:schema:2001" />
+ <complexType name="ESGProviderType">
+ <sequence>
+ <element name="ProviderURI" type="anyURI"/>
+ <element name="ProviderName" type="mpeg7:TextualType"/>
+ <element name="ProviderLogo" type="mpeg7:TitleMediaType" minOccurs="0"/>
+ <element name="ProviderID" type="positiveInteger"/>
+ <element name="ProviderInformationURL" type="anyURI" minOccurs="0"/>
+ <element name="PrivateAuxiliaryData" type="anyType" minOccurs="0"/>
+ </sequence>
+ </complexType>
+ <element name="ESGProviderDiscovery">
+ <complexType>
+ <sequence>
+ <element name="ServiceProvider" type="bs:ESGProviderType" maxOccurs="unbounded"/>
+ </sequence>
+ </complexType>
+ </element>
+</schema>
diff --git a/lib/libucsi/Makefile b/lib/libucsi/Makefile
new file mode 100644
index 0000000..19ab268
--- /dev/null
+++ b/lib/libucsi/Makefile
@@ -0,0 +1,34 @@
+# Makefile for linuxtv.org dvb-apps/lib/libucsi
+
+includes = crc32.h \
+ descriptor.h \
+ endianops.h \
+ section.h \
+ section_buf.h \
+ transport_packet.h \
+ types.h
+
+objects = crc32.o \
+ section_buf.o \
+ transport_packet.o
+
+lib_name = libucsi
+
+CPPFLAGS += -I../../lib
+
+.PHONY: all
+
+all: library
+
+include atsc/Makefile
+include dvb/Makefile
+include mpeg/Makefile
+
+.PHONY: $(sub-install)
+
+install:: $(sub-install)
+
+$(sub-install):
+ $(MAKE) -C $@ install
+
+include ../../Make.rules
diff --git a/lib/libucsi/atsc/Makefile b/lib/libucsi/atsc/Makefile
new file mode 100644
index 0000000..c3d8e6b
--- /dev/null
+++ b/lib/libucsi/atsc/Makefile
@@ -0,0 +1,55 @@
+# Makefile for linuxtv.org dvb-apps/lib/libucsi/atsc
+
+.PHONY: sub-error-atsc
+
+sub-error-atsc:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += atsc/atsc_text.o \
+ atsc/cvct_section.o \
+ atsc/dccsct_section.o \
+ atsc/dcct_section.o \
+ atsc/eit_section.o \
+ atsc/ett_section.o \
+ atsc/mgt_section.o \
+ atsc/rrt_section.o \
+ atsc/stt_section.o \
+ atsc/tvct_section.o \
+ atsc/types.o
+
+sub-install += atsc
+
+else
+
+includes = ac3_descriptor.h \
+ caption_service_descriptor.h \
+ component_name_descriptor.h \
+ content_advisory_descriptor.h \
+ cvct_section.h \
+ dcc_arriving_request_descriptor.h \
+ dcc_departing_request_descriptor.h \
+ dccsct_section.h \
+ dcct_section.h \
+ descriptor.h \
+ eit_section.h \
+ ett_section.h \
+ extended_channel_name_descriptor.h \
+ genre_descriptor.h \
+ mgt_section.h \
+ rc_descriptor.h \
+ rrt_section.h \
+ section.h \
+ service_location_descriptor.h \
+ stt_section.h \
+ stuffing_descriptor.h \
+ time_shifted_service_descriptor.h \
+ tvct_section.h \
+ types.h
+
+include ../../../Make.rules
+
+lib_name = libucsi/atsc
+
+endif
diff --git a/lib/libucsi/atsc/ac3_descriptor.h b/lib/libucsi/atsc/ac3_descriptor.h
new file mode 100644
index 0000000..489695b
--- /dev/null
+++ b/lib/libucsi/atsc/ac3_descriptor.h
@@ -0,0 +1,112 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_atsc@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_AC3_DESCRIPTOR
+#define _UCSI_ATSC_AC3_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+enum atsc_ac3_channels {
+ ATSC_AC3_CHANNELS_1_PLUS_1 = 0x0,
+ ATSC_AC3_CHANNELS_1_0 = 0x1,
+ ATSC_AC3_CHANNELS_2_0 = 0x2,
+ ATSC_AC3_CHANNELS_3_0 = 0x3,
+ ATSC_AC3_CHANNELS_2_1 = 0x4,
+ ATSC_AC3_CHANNELS_3_1 = 0x5,
+ ATSC_AC3_CHANNELS_2_2 = 0x6,
+ ATSC_AC3_CHANNELS_3_2 = 0x7,
+ ATSC_AC3_CHANNELS_1 = 0x8,
+ ATSC_AC3_CHANNELS_LTEQ_2 = 0x9,
+ ATSC_AC3_CHANNELS_LTEQ_3 = 0xa,
+ ATSC_AC3_CHANNELS_LTEQ_4 = 0xb,
+ ATSC_AC3_CHANNELS_LTEQ_5 = 0xc,
+ ATSC_AC3_CHANNELS_LTEQ_6 = 0xd,
+};
+
+/**
+ * atsc_ac3_descriptor structure.
+ */
+struct atsc_ac3_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t sample_rate_code : 3; ,
+ uint8_t bsid : 5; );
+ EBIT2(uint8_t bit_rate_code : 6; ,
+ uint8_t surround_mode : 2; );
+ EBIT3(uint8_t bsmod : 3; ,
+ uint8_t num_channels : 4; ,
+ uint8_t full_svc : 1; );
+ /* uint8_t additional_info[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_ac3_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return atsc_ac3_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_ac3_descriptor*
+ atsc_ac3_descriptor_codec(struct descriptor* d)
+{
+ int pos = 0;
+
+ if (d->len < (pos+4))
+ return NULL;
+ pos += 4;
+
+ return (struct atsc_ac3_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to additional_info field of a atsc_ac3_descriptor.
+ *
+ * @param d atsc_ac3_descriptor pointer.
+ * @return Pointer to additional_info field.
+ */
+static inline uint8_t *atsc_ac3_descriptor_additional_info(struct atsc_ac3_descriptor *d)
+{
+ int pos = sizeof(struct atsc_ac3_descriptor);
+
+ return ((uint8_t *) d) + pos;
+}
+
+/**
+ * Determine length of additional_info field of a atsc_ac3_descriptor.
+ *
+ * @param d atsc_ac3_descriptor pointer.
+ * @return Length of field in bytes.
+ */
+static inline int atsc_ac3_descriptor_additional_info_length(struct atsc_ac3_descriptor* d)
+{
+ return d->d.len - 3;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/atsc_text.c b/lib/libucsi/atsc/atsc_text.c
new file mode 100644
index 0000000..d79c83f
--- /dev/null
+++ b/lib/libucsi/atsc/atsc_text.c
@@ -0,0 +1,743 @@
+/*
+* section and descriptor parser
+*
+* Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+*
+* This library is free software; you can redistribute it and/or
+* modify it under the terms of the GNU Lesser General Public
+* License as published by the Free Software Foundation; either
+* version 2.1 of the License, or (at your option) any later version.
+*
+* This library is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+* Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public
+* License along with this library; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+*/
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include "libucsi/endianops.h"
+#include "libucsi/atsc/types.h"
+
+#define HUFFTREE_LITERAL_MASK 0x80
+#define HUFFSTRING_END 0x00
+#define HUFFSTRING_ESCAPE 0x1b
+
+#define DEST_ALLOC_DELTA 20
+
+struct hufftree_entry {
+ uint8_t left_idx;
+ uint8_t right_idx;
+} __ucsi_packed;
+
+struct huffbuff {
+ uint8_t *buf;
+ uint32_t buf_len;
+
+ uint32_t cur_byte;
+ uint8_t cur_bit;
+};
+
+
+static struct hufftree_entry program_description_hufftree[][128] = {
+ { {0x14, 0x15}, {0x9b, 0xd6}, {0xc9, 0xcf}, {0xd7, 0xc7}, {0x01, 0xa2},
+ {0xce, 0xcb}, {0x02, 0x03}, {0xc5, 0xcc}, {0xc6, 0xc8}, {0x04, 0xc4},
+ {0x05, 0xc2}, {0x06, 0xc3}, {0xd2, 0x07}, {0xd3, 0x08}, {0xca, 0xd4},
+ {0x09, 0xcd}, {0xd0, 0x0a}, {0xc1, 0x0b}, {0x0c, 0x0d}, {0x0e, 0x0f},
+ {0x10, 0x11}, {0x12, 0x13}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x38, 0x39}, {0xad, 0xaf}, {0xb7, 0xda}, {0xa8, 0xb3}, {0xb5, 0x01},
+ {0x02, 0x9b}, {0xb4, 0xf1}, {0xa2, 0xd5}, {0xd6, 0xd9}, {0x03, 0x04},
+ {0x05, 0xcf}, {0x06, 0xc9}, {0xf9, 0xea}, {0xeb, 0xf5}, {0xf6, 0x07},
+ {0x08, 0x09}, {0xb2, 0xc5}, {0xc6, 0xb1}, {0x0a, 0xee}, {0xcb, 0x0b},
+ {0xd4, 0x0c}, {0xc4, 0xc8}, {0xd2, 0x0d}, {0x0e, 0x0f}, {0xc7, 0xca},
+ {0xce, 0xd0}, {0xd7, 0x10}, {0xc2, 0x11}, {0xcc, 0xec}, {0xe5, 0xe7},
+ {0x12, 0xcd}, {0x13, 0x14}, {0xc3, 0x15}, {0x16, 0x17}, {0xed, 0x18},
+ {0x19, 0xf2}, {0x1a, 0xd3}, {0x1b, 0x1c}, {0xe4, 0x1d}, {0xc1, 0xe3},
+ {0x1e, 0xe9}, {0xf0, 0xe2}, {0xf7, 0x1f}, {0xf3, 0xe6}, {0x20, 0x21},
+ {0x22, 0xe8}, {0xef, 0x23}, {0x24, 0x25}, {0x26, 0x27}, {0x28, 0x29},
+ {0x2a, 0xf4}, {0x2b, 0x2c}, {0x2d, 0x2e}, {0x2f, 0xe1}, {0x30, 0x31},
+ {0x32, 0x33}, {0x34, 0x35}, {0x36, 0x37}, },
+ { {0x9b, 0x9b}, },
+ { {0x03, 0x04}, {0x80, 0xae}, {0xc8, 0xd4}, {0x01, 0x02}, {0x9b, 0xa0}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x02, 0xf3}, {0xa0, 0xf4}, {0x9b, 0x01}, },
+ { {0x9b, 0x9b}, },
+ { {0xac, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x01, 0xa0}, {0x9b, 0xa2}, },
+ { {0x07, 0x08}, {0xe2, 0xe4}, {0xe5, 0xe6}, {0xa0, 0xf2}, {0xe1, 0x01},
+ {0x02, 0xf3}, {0xe3, 0x03}, {0x04, 0x05}, {0x9b, 0x06}, },
+ { {0x04, 0x80}, {0xca, 0xd3}, {0xa2, 0x01}, {0x9b, 0x02}, {0x03, 0xa0}, },
+ { {0x9b, 0xa0}, },
+ { {0x03, 0x04}, {0x9b, 0xb7}, {0xf4, 0xa0}, {0xb0, 0xf3}, {0x01, 0x02}, },
+ { {0xb9, 0x02}, {0xb8, 0x9b}, {0xa0, 0x01}, },
+ { {0xae, 0x02}, {0xb6, 0x9b}, {0x01, 0xa0}, },
+ { {0xa0, 0x01}, {0x9b, 0xb0}, },
+ { {0xae, 0x01}, {0x9b, 0xa0}, },
+ { {0xae, 0x01}, {0xa0, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x01}, {0xac, 0xae}, },
+ { {0x9b, 0x9b}, },
+ { {0x02, 0x03}, {0x9b, 0xa0}, {0xb5, 0xb6}, {0xb8, 0x01}, },
+ { {0x9b, 0xa0}, },
+ { {0x9b, 0xa0}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0xa0}, },
+ { {0x9b, 0x9b}, },
+ { {0x08, 0x09}, {0xe6, 0xf5}, {0xf3, 0xf4}, {0x9b, 0xe4}, {0x01, 0xed},
+ {0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x06}, {0xec, 0xee}, {0x07, 0xa0}, },
+ { {0x05, 0x06}, {0x9b, 0xec}, {0xf5, 0x01}, {0x02, 0xe1}, {0xef, 0xe5},
+ {0xe9, 0xf2}, {0x03, 0x04}, },
+ { {0x06, 0x07}, {0x9b, 0xe9}, {0xf9, 0xf2}, {0xf5, 0x01}, {0x02, 0x03},
+ {0xec, 0xef}, {0xe1, 0x04}, {0xe8, 0x05}, },
+ { {0x05, 0x06}, {0xf9, 0xf2}, {0xf5, 0x9b}, {0xe5, 0xef}, {0x01, 0x02},
+ {0xe9, 0xe1}, {0x03, 0x04}, },
+ { {0x06, 0x07}, {0xe1, 0xe9}, {0xee, 0xf6}, {0xe4, 0xec}, {0xf3, 0x01},
+ {0x02, 0xf2}, {0x03, 0x04}, {0x9b, 0x05}, },
+ { {0x02, 0x03}, {0xe5, 0xec}, {0x9b, 0xef}, {0x01, 0xf2}, },
+ { {0x05, 0x06}, {0xf5, 0xef}, {0x9b, 0xec}, {0xe9, 0x01}, {0xe1, 0xf2},
+ {0x02, 0xe5}, {0x03, 0x04}, },
+ { {0x03, 0x04}, {0x9b, 0xe5}, {0xe9, 0xf5}, {0xe1, 0x01}, {0xef, 0x02}, },
+ { {0x04, 0x05}, {0xa0, 0xc9}, {0xf3, 0x9b}, {0xae, 0xf2}, {0x01, 0x02},
+ {0x03, 0xee}, },
+ { {0xef, 0x05}, {0x9b, 0xae}, {0xe9, 0xe5}, {0x01, 0xf5}, {0x02, 0xe1},
+ {0x03, 0x04}, },
+ { {0xe5, 0x03}, {0xe1, 0xe9}, {0xf2, 0x9b}, {0x01, 0x02}, },
+ { {0x03, 0x04}, {0x9b, 0xe9}, {0xf5, 0x01}, {0xe5, 0x02}, {0xef, 0xe1}, },
+ { {0xe1, 0x05}, {0x9b, 0xe3}, {0xef, 0x01}, {0xf5, 0xe5}, {0x02, 0x03},
+ {0xe9, 0x04}, },
+ { {0xe5, 0x03}, {0x9b, 0xe9}, {0x01, 0xe1}, {0xef, 0x02}, },
+ { {0x03, 0x04}, {0xa7, 0xee}, {0xec, 0xf2}, {0xf3, 0x01}, {0x9b, 0x02}, },
+ { {0xe1, 0x06}, {0x9b, 0xe8}, {0xe9, 0x01}, {0xf2, 0xec}, {0x02, 0xef},
+ {0x03, 0xe5}, {0x04, 0x05}, },
+ { {0x9b, 0x9b}, },
+ { {0x03, 0x04}, {0x9b, 0xae}, {0x01, 0xe9}, {0x02, 0xe1}, {0xe5, 0xef}, },
+ { {0x09, 0x0a}, {0xf6, 0xf9}, {0x01, 0xae}, {0xe3, 0xe9}, {0xf5, 0x9b},
+ {0xe5, 0xef}, {0x02, 0x03}, {0xe1, 0x04}, {0xe8, 0x05}, {0x06, 0xf4},
+ {0x07, 0x08}, },
+ { {0xe8, 0x07}, {0xe5, 0xf7}, {0xd6, 0xe1}, {0x9b, 0xe9}, {0xf2, 0x01},
+ {0x02, 0x03}, {0x04, 0xef}, {0x05, 0x06}, },
+ { {0xae, 0x01}, {0x9b, 0xee}, },
+ { {0xe9, 0x02}, {0xe5, 0x9b}, {0xa0, 0x01}, },
+ { {0x03, 0x04}, {0x9b, 0xe8}, {0xe5, 0xe1}, {0xef, 0x01}, {0xe9, 0x02}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0xef}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x18, 0x19}, {0xe8, 0xef}, {0xf8, 0x9b}, {0xa7, 0xf7}, {0xfa, 0x01},
+ {0x02, 0x03}, {0x04, 0xe5}, {0xae, 0x05}, {0xe6, 0xe2}, {0x06, 0xf6},
+ {0xeb, 0xf5}, {0xe9, 0x07}, {0xf0, 0xf9}, {0xe7, 0x08}, {0x09, 0xe4},
+ {0x0a, 0xe3}, {0x0b, 0xed}, {0x0c, 0xf3}, {0x0d, 0x0e}, {0x0f, 0xec},
+ {0x10, 0xf4}, {0x11, 0x12}, {0xf2, 0xa0}, {0x13, 0x14}, {0x15, 0xee},
+ {0x16, 0x17}, },
+ { {0x0b, 0x0c}, {0xe4, 0xf3}, {0x9b, 0xae}, {0xe2, 0x01}, {0x02, 0x03},
+ {0xec, 0xa0}, {0x04, 0xe9}, {0xf2, 0xf5}, {0x05, 0xf9}, {0xe1, 0x06},
+ {0xef, 0x07}, {0xe5, 0x08}, {0x09, 0x0a}, },
+ { {0x0f, 0x10}, {0xf1, 0xae}, {0xc4, 0xf9}, {0xac, 0x01}, {0xe3, 0x02},
+ {0x9b, 0xf2}, {0x03, 0x04}, {0xa0, 0xec}, {0xf5, 0x05}, {0x06, 0xe9},
+ {0x07, 0xeb}, {0x08, 0xf4}, {0x09, 0xe5}, {0x0a, 0xef}, {0xe1, 0xe8},
+ {0x0b, 0x0c}, {0x0d, 0x0e}, },
+ { {0x13, 0x14}, {0xa7, 0xbb}, {0xe6, 0xed}, {0xf7, 0xe7}, {0xf6, 0x01},
+ {0x02, 0x9b}, {0xee, 0x03}, {0x04, 0xec}, {0x05, 0xf5}, {0x06, 0xac},
+ {0xe4, 0xf9}, {0xf2, 0x07}, {0x08, 0x09}, {0xae, 0x0a}, {0xef, 0x0b},
+ {0xe1, 0xf3}, {0x0c, 0xe9}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xe5, 0x11},
+ {0x12, 0xa0}, },
+ { {0x1d, 0x1e}, {0xa9, 0xe8}, {0xf5, 0x9b}, {0x01, 0xad}, {0xbb, 0xeb},
+ {0xfa, 0x02}, {0xa7, 0xe6}, {0xe2, 0xe7}, {0x03, 0x04}, {0x05, 0x06},
+ {0xe9, 0xf8}, {0x07, 0xac}, {0xef, 0xf0}, {0x08, 0xed}, {0xf6, 0xf9},
+ {0x09, 0xf7}, {0x0a, 0x0b}, {0xae, 0x0c}, {0xe3, 0x0d}, {0xe5, 0xf4},
+ {0x0e, 0x0f}, {0xe4, 0x10}, {0xec, 0x11}, {0xe1, 0x12}, {0x13, 0x14},
+ {0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x18}, {0xf2, 0xa0}, {0x19, 0x1a},
+ {0x1b, 0x1c}, },
+ { {0x09, 0x0a}, {0xae, 0x9b}, {0xec, 0x01}, {0xf5, 0x02}, {0xf4, 0xe6},
+ {0x03, 0xe1}, {0xe5, 0xe9}, {0x04, 0xf2}, {0xef, 0x05}, {0x06, 0x07},
+ {0xa0, 0x08}, },
+ { {0x0e, 0x0f}, {0xad, 0xe7}, {0x9b, 0xa7}, {0xf9, 0x01}, {0xec, 0x02},
+ {0xac, 0xf2}, {0x03, 0xae}, {0xf3, 0xf5}, {0x04, 0x05}, {0xef, 0x06},
+ {0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0x0b}, {0xe5, 0x0c},
+ {0xa0, 0x0d}, },
+ { {0x0d, 0x0e}, {0xa7, 0xac}, {0xf3, 0xad}, {0x01, 0x02}, {0x9b, 0xf9},
+ {0xf5, 0xae}, {0x03, 0xee}, {0x04, 0xf2}, {0x05, 0x06}, {0xf4, 0x07},
+ {0x08, 0x09}, {0xef, 0xe1}, {0xa0, 0x0a}, {0xe9, 0x0b}, {0x0c, 0xe5}, },
+ { {0x14, 0x15}, {0xac, 0xe2}, {0xf8, 0x9b}, {0xae, 0xfa}, {0x01, 0xeb},
+ {0x02, 0xa0}, {0x03, 0x04}, {0xf0, 0x05}, {0x06, 0xe6}, {0xf6, 0x07},
+ {0xe4, 0xed}, {0xe7, 0x08}, {0xe1, 0xef}, {0xf2, 0x09}, {0x0a, 0x0b},
+ {0xec, 0x0c}, {0xe5, 0xe3}, {0x0d, 0xf4}, {0x0e, 0xf3}, {0x0f, 0x10},
+ {0x11, 0xee}, {0x12, 0x13}, },
+ { {0x03, 0xef}, {0x9b, 0xe1}, {0xe5, 0xf5}, {0x01, 0x02}, },
+ { {0x08, 0x09}, {0xec, 0xf9}, {0xa7, 0xee}, {0x01, 0xac}, {0x9b, 0xae},
+ {0x02, 0x03}, {0x04, 0xf3}, {0x05, 0xe9}, {0x06, 0xa0}, {0x07, 0xe5}, },
+ { {0x16, 0x17}, {0xa7, 0xad}, {0xee, 0xe3}, {0xeb, 0xf2}, {0x9b, 0xe2},
+ {0x01, 0x02}, {0xf5, 0x03}, {0xf4, 0xac}, {0x04, 0x05}, {0xe6, 0xed},
+ {0xf6, 0x06}, {0xae, 0xf0}, {0x07, 0x08}, {0xf3, 0x09}, {0x0a, 0xe4},
+ {0x0b, 0x0c}, {0xf9, 0x0d}, {0xef, 0x0e}, {0xe1, 0x0f}, {0x10, 0xe9},
+ {0xec, 0x11}, {0xa0, 0xe5}, {0x12, 0x13}, {0x14, 0x15}, },
+ { {0x0c, 0x0d}, {0xa7, 0xbb}, {0x9b, 0x01}, {0xf9, 0xae}, {0xe2, 0x02},
+ {0xed, 0xf3}, {0x03, 0xf5}, {0xef, 0xf0}, {0x04, 0x05}, {0xe9, 0x06},
+ {0x07, 0x08}, {0x09, 0xa0}, {0xe1, 0xe5}, {0x0a, 0x0b}, },
+ { {0x19, 0x1a}, {0xad, 0xbb}, {0xe2, 0xea}, {0xed, 0xf2}, {0xfa, 0xe6},
+ {0xec, 0x01}, {0x02, 0x03}, {0x9b, 0xf5}, {0x04, 0xa7}, {0xf6, 0xf9},
+ {0x05, 0x06}, {0xeb, 0xef}, {0x07, 0x08}, {0x09, 0x0a}, {0xac, 0x0b},
+ {0x0c, 0xe3}, {0xae, 0x0d}, {0xee, 0xe9}, {0x0e, 0xe1}, {0x0f, 0xf3},
+ {0x10, 0x11}, {0xf4, 0x12}, {0xe7, 0xe5}, {0x13, 0x14}, {0xe4, 0x15},
+ {0x16, 0x17}, {0xa0, 0x18}, },
+ { {0x1a, 0x1b}, {0xc2, 0x9b}, {0xad, 0xac}, {0xf8, 0x01}, {0xae, 0x02},
+ {0x03, 0xe5}, {0xe7, 0xe8}, {0xf9, 0xe9}, {0xeb, 0x04}, {0xe3, 0xe1},
+ {0x05, 0xf6}, {0x06, 0xe4}, {0x07, 0xe2}, {0xf0, 0x08}, {0x09, 0xf3},
+ {0xf4, 0xf7}, {0xef, 0x0a}, {0x0b, 0x0c}, {0x0d, 0xec}, {0x0e, 0x0f},
+ {0x10, 0xf5}, {0xed, 0x11}, {0xe6, 0xa0}, {0x12, 0xf2}, {0x13, 0x14},
+ {0x15, 0xee}, {0x16, 0x17}, {0x18, 0x19}, },
+ { {0x0e, 0x0f}, {0xad, 0xed}, {0xf9, 0x9b}, {0xae, 0x01}, {0xf3, 0x02},
+ {0x03, 0xf5}, {0xf4, 0xf0}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0xe8},
+ {0xa0, 0xe1}, {0xec, 0x07}, {0xf2, 0x08}, {0xe5, 0x09}, {0x0a, 0x0b},
+ {0x0c, 0x0d}, },
+ { {0x9b, 0xf5}, },
+ { {0x19, 0x1a}, {0xa9, 0xbb}, {0xf6, 0xe6}, {0x01, 0x9b}, {0xad, 0xe2},
+ {0xf0, 0x02}, {0xa7, 0x03}, {0x04, 0x05}, {0xf5, 0xe3}, {0xac, 0xe7},
+ {0xf2, 0x06}, {0xeb, 0x07}, {0xec, 0xed}, {0xee, 0xf9}, {0x08, 0xae},
+ {0x09, 0x0a}, {0xe4, 0x0b}, {0x0c, 0xf4}, {0x0d, 0xf3}, {0x0e, 0x0f},
+ {0x10, 0xe1}, {0xef, 0x11}, {0xe9, 0x12}, {0x13, 0xe5}, {0x14, 0xa0},
+ {0x15, 0x16}, {0x17, 0x18}, },
+ { {0xa0, 0x16}, {0xa2, 0xa7}, {0xe2, 0xeb}, {0xed, 0xee}, {0x9b, 0xf7},
+ {0x01, 0x02}, {0x03, 0xbb}, {0xf9, 0xf0}, {0x04, 0x05}, {0xec, 0x06},
+ {0x07, 0x08}, {0xf5, 0xe1}, {0x09, 0xac}, {0xe3, 0x0a}, {0xe8, 0x0b},
+ {0xe9, 0x0c}, {0xef, 0xf3}, {0xae, 0x0d}, {0x0e, 0xe5}, {0x0f, 0x10},
+ {0x11, 0xf4}, {0x12, 0x13}, {0x14, 0x15}, },
+ { {0x14, 0x15}, {0xbb, 0xe2}, {0xad, 0xed}, {0x01, 0x9b}, {0xa7, 0xe3},
+ {0xac, 0xec}, {0xee, 0x02}, {0xf7, 0x03}, {0x04, 0xf9}, {0x05, 0x06},
+ {0x07, 0x08}, {0xf4, 0xae}, {0xf5, 0x09}, {0x0a, 0xf2}, {0xe1, 0xf3},
+ {0x0b, 0x0c}, {0x0d, 0xe9}, {0x0e, 0x0f}, {0xef, 0xe5}, {0x10, 0xa0},
+ {0xe8, 0x11}, {0x12, 0x13}, },
+ { {0x11, 0x12}, {0xef, 0xf6}, {0x9b, 0xeb}, {0xf9, 0x01}, {0xa0, 0xe2},
+ {0x02, 0xe1}, {0x03, 0xed}, {0x04, 0xe3}, {0xe9, 0x05}, {0xe4, 0xe5},
+ {0xe7, 0x06}, {0xec, 0xf0}, {0x07, 0x08}, {0x09, 0x0a}, {0x0b, 0xf3},
+ {0x0c, 0xf4}, {0xee, 0x0d}, {0xf2, 0x0e}, {0x0f, 0x10}, },
+ { {0x05, 0xe5}, {0xf3, 0xf9}, {0x9b, 0x01}, {0xef, 0x02}, {0x03, 0xe1},
+ {0x04, 0xe9}, },
+ { {0x0a, 0x0b}, {0xae, 0x9b}, {0xec, 0xed}, {0x01, 0x02}, {0xf3, 0xee},
+ {0xf2, 0x03}, {0xe5, 0x04}, {0xe8, 0xa0}, {0xe1, 0x05}, {0xef, 0x06},
+ {0x07, 0x08}, {0xe9, 0x09}, },
+ { {0x05, 0x06}, {0xa0, 0xac}, {0xad, 0xf4}, {0xe9, 0x01}, {0x02, 0xe1},
+ {0xe5, 0x03}, {0x9b, 0x04}, },
+ { {0x11, 0xa0}, {0xbf, 0xe1}, {0xe2, 0xe6}, {0xed, 0xe4}, {0xe9, 0xf7},
+ {0xa7, 0x01}, {0x02, 0xbb}, {0x03, 0x04}, {0xec, 0x05}, {0x9b, 0xee},
+ {0x06, 0xef}, {0x07, 0xac}, {0xe5, 0xf3}, {0x08, 0x09}, {0x0a, 0xae},
+ {0x0b, 0x0c}, {0x0d, 0x0e}, {0x0f, 0x10}, },
+ { {0x06, 0x07}, {0xa0, 0xae}, {0xe1, 0xe5}, {0xec, 0xfa}, {0x9b, 0xef},
+ {0xe9, 0x01}, {0x02, 0x03}, {0x04, 0x05}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+};
+
+static struct hufftree_entry program_title_hufftree[][128] = {
+ { {0x1b, 0x1c}, {0xb4, 0xa4}, {0xb2, 0xb7}, {0xda, 0x01}, {0xd1, 0x02},
+ {0x03, 0x9b}, {0x04, 0xd5}, {0xd9, 0x05}, {0xcb, 0xd6}, {0x06, 0xcf},
+ {0x07, 0x08}, {0xca, 0x09}, {0xc9, 0xc5}, {0xc6, 0x0a}, {0xd2, 0xc4},
+ {0xc7, 0xcc}, {0xd0, 0xc8}, {0xd7, 0xce}, {0x0b, 0xc1}, {0x0c, 0xc2},
+ {0xcd, 0xc3}, {0x0d, 0x0e}, {0x0f, 0x10}, {0xd3, 0x11}, {0xd4, 0x12},
+ {0x13, 0x14}, {0x15, 0x16}, {0x17, 0x18}, {0x19, 0x1a}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x29, 0x2a}, {0xd8, 0xe5}, {0xb9, 0x01}, {0xa7, 0xb1}, {0xec, 0xd1},
+ {0x02, 0xad}, {0xb2, 0xda}, {0xe3, 0xb3}, {0x03, 0xe4}, {0xe6, 0x04},
+ {0x9b, 0xe2}, {0x05, 0x06}, {0x07, 0x08}, {0x09, 0xd5}, {0x0a, 0xd6},
+ {0x0b, 0xd9}, {0x0c, 0xa6}, {0xe9, 0xcb}, {0xc5, 0xcf}, {0x0d, 0x0e},
+ {0xca, 0xc9}, {0x0f, 0xc7}, {0x10, 0x11}, {0xe1, 0x12}, {0x13, 0xc6},
+ {0xd2, 0xc8}, {0xce, 0xc1}, {0xc4, 0xd0}, {0xcc, 0x14}, {0x15, 0xef},
+ {0xc2, 0xd7}, {0x16, 0xcd}, {0x17, 0xf4}, {0xd4, 0x18}, {0x19, 0x1a},
+ {0xc3, 0xd3}, {0x1b, 0x1c}, {0x1d, 0x1e}, {0x1f, 0x20}, {0x21, 0x22},
+ {0x23, 0x24}, {0x25, 0x26}, {0x27, 0x28}, },
+ { {0x01, 0x80}, {0xa0, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0xb1, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0xa0}, },
+ { {0x04, 0xf3}, {0xe4, 0xb9}, {0x01, 0xf4}, {0xa0, 0x9b}, {0x02, 0x03}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x01, 0x02}, {0x9b, 0xc1}, {0xc8, 0xd3}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0xa0}, },
+ { {0x07, 0x08}, {0xb1, 0xd2}, {0xd3, 0xd4}, {0xd5, 0xad}, {0xcd, 0xc1},
+ {0x01, 0x02}, {0x03, 0xa0}, {0x04, 0x9b}, {0x05, 0x06}, },
+ { {0xa0, 0x05}, {0xc9, 0xd7}, {0xd3, 0x01}, {0x02, 0x9b}, {0xae, 0x80},
+ {0x03, 0x04}, },
+ { {0x9b, 0x9b}, },
+ { {0x02, 0x03}, {0xad, 0x9b}, {0x01, 0x80}, {0xa0, 0xb0}, },
+ { {0x04, 0x05}, {0x80, 0x9b}, {0xb1, 0xb2}, {0xa0, 0xb0}, {0xb9, 0x01},
+ {0x02, 0x03}, },
+ { {0x02, 0x03}, {0xb1, 0xba}, {0x01, 0xb0}, {0x9b, 0x80}, },
+ { {0x80, 0x01}, {0xb0, 0x9b}, },
+ { {0x9b, 0xb8}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0xb0}, },
+ { {0x9b, 0xa0}, },
+ { {0x02, 0x03}, {0xb1, 0xb3}, {0xb9, 0xb0}, {0x01, 0x9b}, },
+ { {0x9b, 0xa0}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x80}, },
+ { {0x9b, 0x9b}, },
+ { {0x13, 0x14}, {0xaa, 0xad}, {0xae, 0xf6}, {0xe7, 0xf4}, {0xe2, 0xe9},
+ {0x01, 0x02}, {0xc2, 0xf0}, {0x9b, 0xf3}, {0xe3, 0xe6}, {0xf7, 0x03},
+ {0xf5, 0x04}, {0x05, 0x06}, {0xf2, 0x07}, {0x08, 0x09}, {0x0a, 0x0b},
+ {0x0c, 0xe4}, {0xa0, 0x0d}, {0xec, 0xee}, {0x0e, 0xed}, {0x0f, 0x10},
+ {0x11, 0x12}, },
+ { {0x08, 0x09}, {0xc1, 0xd3}, {0x9b, 0x01}, {0xc3, 0x02}, {0xe9, 0xec},
+ {0x03, 0xf2}, {0xf5, 0x04}, {0xef, 0xe1}, {0x05, 0xe5}, {0x06, 0x07}, },
+ { {0x0b, 0x0c}, {0xc1, 0xf9}, {0x01, 0xc2}, {0xcf, 0xe5}, {0xf5, 0x9b},
+ {0xe9, 0x02}, {0xa0, 0x03}, {0x04, 0x05}, {0xf2, 0x06}, {0xec, 0x07},
+ {0xe1, 0x08}, {0x09, 0xe8}, {0x0a, 0xef}, },
+ { {0x05, 0x06}, {0xf9, 0x9b}, {0x01, 0xf5}, {0x02, 0xf2}, {0xe9, 0xe5},
+ {0xef, 0x03}, {0xe1, 0x04}, },
+ { {0x0a, 0x0b}, {0xf1, 0xf5}, {0xf3, 0x01}, {0xed, 0xf9}, {0xc3, 0x02},
+ {0xec, 0xee}, {0xe4, 0xf8}, {0x03, 0x9b}, {0xf6, 0x04}, {0x05, 0xe1},
+ {0x06, 0x07}, {0x08, 0x09}, },
+ { {0x07, 0x08}, {0xa0, 0x9b}, {0xcc, 0x01}, {0xe5, 0x02}, {0xec, 0xf5},
+ {0xef, 0x03}, {0xe9, 0xf2}, {0x04, 0x05}, {0xe1, 0x06}, },
+ { {0x09, 0x0a}, {0xae, 0xec}, {0xf9, 0xc1}, {0xe8, 0x01}, {0x9b, 0x02},
+ {0x03, 0x04}, {0xe1, 0xf5}, {0xe9, 0x05}, {0xe5, 0x06}, {0xf2, 0xef},
+ {0x07, 0x08}, },
+ { {0xef, 0x05}, {0x80, 0x9b}, {0xf5, 0x01}, {0x02, 0xe9}, {0xe1, 0x03},
+ {0xe5, 0x04}, },
+ { {0xee, 0x0b}, {0xba, 0xd4}, {0xae, 0xf2}, {0xe3, 0x01}, {0xa0, 0x02},
+ {0x80, 0x9b}, {0xed, 0x03}, {0xc9, 0xf3}, {0xf4, 0x04}, {0x05, 0x06},
+ {0x07, 0x08}, {0x09, 0x0a}, },
+ { {0x02, 0x03}, {0x9b, 0xf5}, {0x01, 0xe1}, {0xef, 0xe5}, },
+ { {0x05, 0xe9}, {0xe1, 0xef}, {0xf5, 0xee}, {0x9b, 0xe5}, {0x01, 0x02},
+ {0x03, 0x04}, },
+ { {0x04, 0x05}, {0xa0, 0x9b}, {0x01, 0xf5}, {0x02, 0xe5}, {0xef, 0x03},
+ {0xe1, 0xe9}, },
+ { {0x08, 0x09}, {0xaa, 0xd4}, {0x01, 0x9b}, {0xe3, 0x02}, {0xf2, 0x03},
+ {0xe5, 0x04}, {0xf5, 0xf9}, {0xe9, 0x05}, {0xef, 0x06}, {0x07, 0xe1}, },
+ { {0xe5, 0x08}, {0xce, 0xa0}, {0xc6, 0xf5}, {0x01, 0x02}, {0x9b, 0xc2},
+ {0x03, 0xe1}, {0x04, 0xef}, {0x05, 0xe9}, {0x06, 0x07}, },
+ { {0x09, 0x0a}, {0xe4, 0xf3}, {0xe6, 0xf6}, {0xf7, 0xf0}, {0xf2, 0x01},
+ {0xec, 0x02}, {0x03, 0xa0}, {0x9b, 0x04}, {0x05, 0xf5}, {0x06, 0x07},
+ {0xee, 0x08}, },
+ { {0x0b, 0x0c}, {0xa0, 0xf3}, {0xf9, 0xae}, {0xd2, 0xc7}, {0x01, 0x9b},
+ {0x02, 0xf5}, {0x03, 0x04}, {0x05, 0xe9}, {0xec, 0x06}, {0xe5, 0x07},
+ {0xef, 0x08}, {0xe1, 0x09}, {0xf2, 0x0a}, },
+ { {0x01, 0xf5}, {0x9b, 0xd6}, },
+ { {0x04, 0x05}, {0xe8, 0x9b}, {0x01, 0xf5}, {0x02, 0xe1}, {0xe9, 0xef},
+ {0x03, 0xe5}, },
+ { {0x10, 0x11}, {0xaa, 0xec}, {0xf1, 0xae}, {0xa0, 0xf7}, {0xed, 0xee},
+ {0x01, 0x02}, {0x9b, 0xeb}, {0x03, 0x04}, {0x05, 0x06}, {0xe3, 0x07},
+ {0xef, 0x08}, {0xe9, 0xf5}, {0x09, 0xe1}, {0xe5, 0xf0}, {0xe8, 0x0a},
+ {0x0b, 0x0c}, {0x0d, 0xf4}, {0x0e, 0x0f}, },
+ { {0xe8, 0x0a}, {0xad, 0xce}, {0x9b, 0x01}, {0xd6, 0x02}, {0xf5, 0xf7},
+ {0x03, 0x04}, {0xe1, 0xe5}, {0xe9, 0x05}, {0xf2, 0x06}, {0xef, 0x07},
+ {0x08, 0x09}, },
+ { {0xee, 0x03}, {0xec, 0xae}, {0x01, 0x9b}, {0x02, 0xf0}, },
+ { {0x06, 0xe9}, {0xa0, 0xc3}, {0xef, 0x9b}, {0xe5, 0x01}, {0x80, 0x02},
+ {0x03, 0xe1}, {0x04, 0x05}, },
+ { {0x06, 0x07}, {0xc6, 0xd7}, {0x01, 0x9b}, {0xf2, 0x02}, {0x03, 0xe8},
+ {0xe5, 0xe1}, {0x04, 0xe9}, {0xef, 0x05}, },
+ { {0x9b, 0x9b}, },
+ { {0x02, 0xef}, {0xe1, 0x9b}, {0x01, 0xe5}, },
+ { {0x01, 0xef}, {0x9b, 0xe1}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x19, 0x1a}, {0x9b, 0xba}, {0xe5, 0xea}, {0xf8, 0x01}, {0x02, 0xe6},
+ {0xa7, 0x03}, {0xfa, 0xe8}, {0x04, 0xf7}, {0x05, 0xf5}, {0xe2, 0x06},
+ {0xeb, 0x07}, {0xf0, 0x08}, {0x80, 0xf6}, {0xe7, 0x09}, {0xe4, 0x0a},
+ {0xa0, 0xe9}, {0x0b, 0xe3}, {0xf9, 0x0c}, {0x0d, 0xed}, {0x0e, 0x0f},
+ {0xf3, 0x10}, {0x11, 0xec}, {0x12, 0xf4}, {0xf2, 0x13}, {0xee, 0x14},
+ {0x15, 0x16}, {0x17, 0x18}, },
+ { {0x0a, 0x0b}, {0xf3, 0x9b}, {0xf5, 0xe2}, {0x01, 0x80}, {0xa0, 0x02},
+ {0xe5, 0xf2}, {0xe9, 0x03}, {0xec, 0x04}, {0xf9, 0x05}, {0xef, 0x06},
+ {0xe1, 0x07}, {0x08, 0x09}, },
+ { {0x10, 0x11}, {0xc3, 0xcc}, {0xc7, 0x9b}, {0xe3, 0x01}, {0x80, 0xec},
+ {0xf9, 0x02}, {0xf3, 0x03}, {0xf5, 0x04}, {0x05, 0xf2}, {0x06, 0xe9},
+ {0xa0, 0x07}, {0x08, 0xef}, {0xf4, 0x09}, {0x0a, 0xe1}, {0x0b, 0xe8},
+ {0xeb, 0xe5}, {0x0c, 0x0d}, {0x0e, 0x0f}, },
+ { {0x0e, 0x0f}, {0xae, 0xf5}, {0xf7, 0x01}, {0xec, 0x02}, {0xe4, 0xe7},
+ {0xf2, 0x03}, {0x9b, 0xef}, {0x04, 0xf6}, {0x05, 0x06}, {0xf9, 0xf3},
+ {0x07, 0xe9}, {0xe1, 0x08}, {0x09, 0x80}, {0x0a, 0x0b}, {0xe5, 0x0c},
+ {0x0d, 0xa0}, },
+ { {0x1e, 0x1f}, {0x9b, 0xa1}, {0xad, 0xe8}, {0xea, 0xf1}, {0xf5, 0xfa},
+ {0x01, 0x02}, {0x03, 0x04}, {0xba, 0xf8}, {0xa7, 0xe2}, {0xe9, 0x05},
+ {0x06, 0x07}, {0xe6, 0xed}, {0xe7, 0xeb}, {0x08, 0x09}, {0xf6, 0xf0},
+ {0x0a, 0xef}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0xf9}, {0x0f, 0xe4},
+ {0xec, 0x10}, {0xe5, 0x11}, {0xf4, 0xf7}, {0x12, 0x13}, {0xe1, 0x14},
+ {0x15, 0x16}, {0xee, 0xf3}, {0x17, 0x80}, {0x18, 0x19}, {0xf2, 0x1a},
+ {0x1b, 0xa0}, {0x1c, 0x1d}, },
+ { {0xa0, 0x0b}, {0xf5, 0x9b}, {0x01, 0xec}, {0xf3, 0xf2}, {0x80, 0xe1},
+ {0x02, 0x03}, {0xf4, 0xe9}, {0xef, 0xe6}, {0x04, 0x05}, {0x06, 0x07},
+ {0xe5, 0x08}, {0x09, 0x0a}, },
+ { {0x0f, 0x10}, {0xba, 0xf9}, {0xa7, 0xf4}, {0x9b, 0x01}, {0xe7, 0xec},
+ {0x02, 0xee}, {0x03, 0xef}, {0xf5, 0x04}, {0xf2, 0x05}, {0x06, 0xe9},
+ {0x07, 0xf3}, {0xe1, 0x08}, {0x09, 0x0a}, {0x0b, 0xe5}, {0x80, 0x0c},
+ {0xe8, 0xa0}, {0x0d, 0x0e}, },
+ { {0xe5, 0x0d}, {0xe2, 0xf5}, {0xf7, 0x9b}, {0xec, 0x01}, {0xf9, 0xee},
+ {0x02, 0x03}, {0x04, 0xf2}, {0x05, 0x80}, {0x06, 0xa0}, {0xe1, 0xef},
+ {0x07, 0xf4}, {0xe9, 0x08}, {0x09, 0x0a}, {0x0b, 0x0c}, },
+ { {0x15, 0x16}, {0xa1, 0xf8}, {0xe9, 0xeb}, {0x01, 0x80}, {0x9b, 0xfa},
+ {0xe2, 0x02}, {0x03, 0x04}, {0xa0, 0xf0}, {0x05, 0x06}, {0x07, 0xe1},
+ {0x08, 0xe6}, {0xf2, 0xed}, {0xf6, 0x09}, {0xe4, 0x0a}, {0xef, 0xf4},
+ {0xec, 0xf3}, {0xe7, 0xe5}, {0x0b, 0xe3}, {0x0c, 0x0d}, {0x0e, 0x0f},
+ {0x10, 0x11}, {0x12, 0x13}, {0xee, 0x14}, },
+ { {0xef, 0x01}, {0x9b, 0xe1}, },
+ { {0x0b, 0x0c}, {0xd4, 0xef}, {0xe6, 0xec}, {0xf7, 0xe1}, {0x01, 0xba},
+ {0x02, 0x9b}, {0xf9, 0x03}, {0x04, 0x05}, {0xf3, 0x06}, {0x07, 0x08},
+ {0xe9, 0xa0}, {0x09, 0x80}, {0xe5, 0x0a}, },
+ { {0x15, 0x16}, {0xa7, 0xba}, {0xe3, 0xf7}, {0xf2, 0xad}, {0xe2, 0x01},
+ {0x02, 0x9b}, {0xe6, 0x03}, {0xed, 0xf6}, {0x04, 0xeb}, {0x05, 0xf4},
+ {0x06, 0x07}, {0x08, 0xf3}, {0x09, 0xf5}, {0x0a, 0xef}, {0x0b, 0x0c},
+ {0x80, 0xf9}, {0xe1, 0x0d}, {0xe4, 0xe9}, {0xa0, 0x0e}, {0x0f, 0xec},
+ {0xe5, 0x10}, {0x11, 0x12}, {0x13, 0x14}, },
+ { {0x0a, 0x0b}, {0xf9, 0x9b}, {0xf5, 0xf3}, {0x01, 0x02}, {0xe2, 0xed},
+ {0x80, 0x03}, {0xf0, 0xef}, {0x04, 0xa0}, {0x05, 0xe9}, {0x06, 0xe1},
+ {0x07, 0x08}, {0x09, 0xe5}, },
+ { {0x18, 0x19}, {0xe2, 0xea}, {0xf2, 0xe8}, {0xec, 0xed}, {0xfa, 0x9b},
+ {0x01, 0xf5}, {0x02, 0x03}, {0xf6, 0x04}, {0xba, 0xe6}, {0x05, 0x06},
+ {0xeb, 0xef}, {0x07, 0xa7}, {0xf9, 0x08}, {0x09, 0x0a}, {0x0b, 0xe3},
+ {0x0c, 0xee}, {0xe1, 0x0d}, {0xf3, 0x0e}, {0xe9, 0x0f}, {0x10, 0xf4},
+ {0x80, 0xe4}, {0xe5, 0x11}, {0x12, 0xe7}, {0xa0, 0x13}, {0x14, 0x15},
+ {0x16, 0x17}, },
+ { {0x1b, 0x1c}, {0xae, 0xfa}, {0xbf, 0x01}, {0xa7, 0x9b}, {0x02, 0xe9},
+ {0xf8, 0xf9}, {0x03, 0xe5}, {0xe8, 0x04}, {0xe1, 0xeb}, {0x05, 0xe2},
+ {0x06, 0x07}, {0xe3, 0x08}, {0xe7, 0xf4}, {0x09, 0x80}, {0xf6, 0xf0},
+ {0x0a, 0xe4}, {0x0b, 0xf3}, {0xf7, 0x0c}, {0x0d, 0xef}, {0xec, 0xa0},
+ {0x0e, 0x0f}, {0xed, 0xe6}, {0x10, 0xf5}, {0x11, 0x12}, {0x13, 0x14},
+ {0x15, 0xf2}, {0x16, 0xee}, {0x17, 0x18}, {0x19, 0x1a}, },
+ { {0x0e, 0x0f}, {0xed, 0xa7}, {0x9b, 0xe4}, {0x01, 0xf9}, {0xf3, 0xf2},
+ {0xf4, 0x02}, {0xe8, 0x03}, {0xec, 0xf0}, {0x04, 0xe1}, {0xe9, 0x05},
+ {0x06, 0x80}, {0xa0, 0x07}, {0x08, 0x09}, {0x0a, 0xe5}, {0xef, 0x0b},
+ {0x0c, 0x0d}, },
+ { {0x9b, 0xf5}, },
+ { {0x18, 0x19}, {0xba, 0xac}, {0xf6, 0x9b}, {0xf0, 0xe2}, {0x01, 0xe6},
+ {0x02, 0xa7}, {0xae, 0xe7}, {0x03, 0xe3}, {0xf5, 0x04}, {0xed, 0x05},
+ {0x06, 0x07}, {0xeb, 0x08}, {0x09, 0xee}, {0xf2, 0x0a}, {0xe4, 0x0b},
+ {0xf9, 0xec}, {0x0c, 0x0d}, {0xf4, 0x80}, {0x0e, 0xef}, {0xf3, 0xa0},
+ {0xe1, 0x0f}, {0xe9, 0x10}, {0x11, 0xe5}, {0x12, 0x13}, {0x14, 0x15},
+ {0x16, 0x17}, },
+ { {0x19, 0x1a}, {0xa7, 0xac}, {0xbf, 0xc3}, {0xc8, 0xe4}, {0xe6, 0xed},
+ {0xf2, 0xae}, {0xec, 0xee}, {0xf9, 0x01}, {0x02, 0x03}, {0x04, 0xba},
+ {0x05, 0x9b}, {0xf5, 0x06}, {0x07, 0x08}, {0x09, 0xeb}, {0xf0, 0x0a},
+ {0x0b, 0x0c}, {0xe1, 0xe3}, {0x0d, 0xe8}, {0x0e, 0x0f}, {0xef, 0x10},
+ {0x11, 0xf3}, {0x12, 0xe9}, {0x13, 0xe5}, {0x14, 0x15}, {0xf4, 0x16},
+ {0x17, 0xa0}, {0x18, 0x80}, },
+ { {0x14, 0x15}, {0xba, 0xbf}, {0xe4, 0xf7}, {0x9b, 0xa7}, {0x01, 0xee},
+ {0x02, 0x03}, {0x04, 0xe3}, {0xe2, 0xed}, {0x05, 0xf9}, {0x06, 0xf4},
+ {0x07, 0xec}, {0x08, 0xf5}, {0xf2, 0x09}, {0xe1, 0xf3}, {0x0a, 0xef},
+ {0x0b, 0x0c}, {0x0d, 0xe9}, {0x80, 0xe5}, {0x0e, 0xa0}, {0x0f, 0xe8},
+ {0x10, 0x11}, {0x12, 0x13}, },
+ { {0x11, 0x12}, {0xeb, 0xfa}, {0x80, 0xe6}, {0x9b, 0x01}, {0xa0, 0x02},
+ {0x03, 0xe9}, {0xe1, 0x04}, {0xe4, 0xf0}, {0xed, 0xe2}, {0xe3, 0xe7},
+ {0xec, 0x05}, {0xe5, 0x06}, {0x07, 0x08}, {0x09, 0xf4}, {0x0a, 0x0b},
+ {0x0c, 0xf3}, {0xee, 0x0d}, {0x0e, 0xf2}, {0x0f, 0x10}, },
+ { {0x04, 0xe5}, {0xf3, 0xef}, {0x9b, 0x01}, {0xe1, 0x02}, {0x03, 0xe9}, },
+ { {0x0b, 0x0c}, {0xa7, 0xe2}, {0xec, 0xe3}, {0xf2, 0x01}, {0x9b, 0x02},
+ {0x03, 0x04}, {0xe9, 0xef}, {0xee, 0xe5}, {0xe1, 0x80}, {0x05, 0xa0},
+ {0x06, 0x07}, {0x08, 0x09}, {0xf3, 0x0a}, },
+ { {0x05, 0x06}, {0x9b, 0xa0}, {0xe1, 0xe5}, {0xe9, 0x01}, {0x80, 0xf0},
+ {0x02, 0xf4}, {0x03, 0x04}, },
+ { {0xa0, 0x13}, {0xe3, 0xad}, {0xe4, 0xe9}, {0xee, 0xef}, {0xf0, 0xf4},
+ {0xf6, 0xa1}, {0xe1, 0xed}, {0x01, 0xe2}, {0x02, 0x03}, {0x04, 0xa7},
+ {0x05, 0x06}, {0xf7, 0x07}, {0x9b, 0xec}, {0x08, 0xe5}, {0x09, 0x0a},
+ {0x0b, 0x0c}, {0x0d, 0x0e}, {0xf3, 0x0f}, {0x10, 0x11}, {0x80, 0x12}, },
+ { {0x05, 0x06}, {0xe5, 0xfa}, {0xa0, 0xf9}, {0x9b, 0x01}, {0x80, 0xe9},
+ {0x02, 0xe1}, {0x03, 0x04}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+ { {0x9b, 0x9b}, },
+};
+
+
+
+static inline void huffbuff_init(struct huffbuff *hbuf, uint8_t *buf, uint32_t buf_len)
+{
+ memset(hbuf, 0, sizeof(struct huffbuff));
+ hbuf->buf = buf;
+ hbuf->buf_len = buf_len;
+}
+
+static inline int huffbuff_bits(struct huffbuff *hbuf, uint8_t nbits)
+{
+ uint8_t result = 0;
+
+ if (nbits > 8)
+ return -1;
+
+ while(nbits--) {
+ if (hbuf->cur_byte >= hbuf->buf_len) {
+ return -1;
+ }
+
+ result <<= 1;
+ if (hbuf->buf[hbuf->cur_byte] & (0x80 >> hbuf->cur_bit))
+ result |= 1;
+
+ if (++hbuf->cur_bit > 7) {
+ hbuf->cur_byte++;
+ hbuf->cur_bit = 0;
+ }
+ }
+
+ return result;
+}
+
+static inline int append_unicode_char(uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos,
+ uint32_t c)
+{
+ uint8_t tmp[3];
+ int tmplen = 0;
+
+ // encode the unicode character first of all
+ if (c < 0x80) {
+ tmp[0] = c;
+ tmplen = 1;
+ } else if (c < 0x800) {
+ tmp[0] = 0xc0 | ((c >> 6) & 0x1f);
+ tmp[1] = 0x80 | (c & 0x3f);
+ tmplen = 2;
+ } else if (c < 0x10000) {
+ tmp[0] = 0xe0 | ((c >> 12) & 0x0f);
+ tmp[1] = 0x80 | ((c >> 6) & 0x3f);
+ tmp[2] = 0x80 | (c & 0x3f);
+ tmplen = 3;
+ } else {
+ return -1;
+ }
+
+ // do we have enough buffer space?
+ if ((*destbufpos + tmplen) >= *destbuflen) {
+ uint8_t *new_dest = realloc(*destbuf, *destbuflen + DEST_ALLOC_DELTA);
+ if (new_dest == NULL)
+ return -ENOMEM;
+ *destbuf = new_dest;
+ *destbuflen += DEST_ALLOC_DELTA;
+ }
+
+ // copy it into position
+ memcpy(*destbuf + *destbufpos, tmp, tmplen);
+ *destbufpos += tmplen;
+
+ return 0;
+}
+
+static inline int unicode_decode(uint8_t *srcbuf, size_t srcbuflen, int mode,
+ uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos)
+{
+ size_t i;
+ uint32_t msb = mode << 8;
+
+ for(i=0; i< srcbuflen; i++) {
+ if (append_unicode_char(destbuf, destbuflen, destbufpos, msb + srcbuf[i]))
+ return -1;
+ }
+
+ return *destbufpos;
+}
+
+static int huffman_decode_uncompressed(struct huffbuff *hbuf,
+ uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos)
+{
+ int c;
+
+ while(hbuf->cur_byte < hbuf->buf_len) {
+ // get next byte
+ if ((c = huffbuff_bits(hbuf, 8)) < 0)
+ return -1;
+
+ switch(c) {
+ case HUFFSTRING_END:
+ return 0;
+
+ case HUFFSTRING_ESCAPE:
+ return HUFFSTRING_ESCAPE;
+
+ default:
+ if (append_unicode_char(destbuf, destbuflen, destbufpos, c))
+ return -1;
+
+ // if it is 7 bit, we swap back to the compressed context
+ if ((c & 0x80) == 0)
+ return c;
+
+ // characters following an 8 bit uncompressed char are uncompressed as well
+ break;
+ }
+ }
+
+ // ran out of string; pretend we saw an end of string char
+ return HUFFSTRING_END;
+}
+
+static int huffman_decode(uint8_t *src, size_t srclen,
+ uint8_t **destbuf, size_t *destbuflen, size_t *destbufpos,
+ struct hufftree_entry hufftree[][128])
+{
+ struct huffbuff hbuf;
+ int bit;
+ struct hufftree_entry *tree = hufftree[0];
+ uint8_t treeidx = 0;
+ uint8_t treeval;
+ int tmp;
+
+ huffbuff_init(&hbuf, src, srclen);
+
+ while(hbuf.cur_byte < hbuf.buf_len) {
+ // get the next bit
+ if ((bit = huffbuff_bits(&hbuf, 1)) < 0)
+ return *destbufpos;
+
+ if (!bit) {
+ treeval = tree[treeidx].left_idx;
+ } else {
+ treeval = tree[treeidx].right_idx;
+ }
+
+ if (treeval & HUFFTREE_LITERAL_MASK) {
+ switch(treeval & ~HUFFTREE_LITERAL_MASK) {
+ case HUFFSTRING_END:
+ return 0;
+
+ case HUFFSTRING_ESCAPE:
+ if ((tmp =
+ huffman_decode_uncompressed(&hbuf,
+ destbuf, destbuflen, destbufpos)) < 0)
+ return tmp;
+ if (tmp == 0)
+ return *destbufpos;
+
+ tree = hufftree[tmp];
+ treeidx = 0;
+ break;
+
+ default:
+ // stash it
+ if (append_unicode_char(destbuf, destbuflen, destbufpos,
+ treeval & ~HUFFTREE_LITERAL_MASK))
+ return -1;
+ tree = hufftree[treeval & ~HUFFTREE_LITERAL_MASK];
+ treeidx = 0;
+ break;
+ }
+ } else {
+ treeidx = treeval;
+ }
+ }
+
+ return *destbufpos;
+}
+
+int atsc_text_segment_decode(struct atsc_text_string_segment *segment,
+ uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos)
+{
+ if (segment->mode > ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX)
+ return -1;
+
+ // mode==0 MUST be used for compressed text
+ if ((segment->mode) && (segment->compression_type))
+ return -1;
+
+ uint8_t *buf = atsc_text_string_segment_bytes(segment);
+
+ switch(segment->compression_type) {
+ case ATSC_TEXT_COMPRESS_NONE:
+ return unicode_decode(buf, segment->number_bytes, segment->mode,
+ destbuf, destbufsize, destbufpos);
+
+ case ATSC_TEXT_COMPRESS_PROGRAM_TITLE:
+ return huffman_decode(buf, segment->number_bytes,
+ destbuf, destbufsize, destbufpos,
+ program_title_hufftree);
+
+ case ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION:
+ return huffman_decode(buf, segment->number_bytes,
+ destbuf, destbufsize, destbufpos,
+ program_description_hufftree);
+ }
+
+ return -1;
+}
diff --git a/lib/libucsi/atsc/caption_service_descriptor.h b/lib/libucsi/atsc/caption_service_descriptor.h
new file mode 100644
index 0000000..29d1794
--- /dev/null
+++ b/lib/libucsi/atsc/caption_service_descriptor.h
@@ -0,0 +1,137 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR
+#define _UCSI_ATSC_CAPTION_SERVICE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * atsc_caption_service_descriptor structure.
+ */
+struct atsc_caption_service_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 3; ,
+ uint8_t number_of_services : 5; );
+ /* struct atsc_caption_service_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a atsc_caption_service_descriptor.
+ */
+struct atsc_caption_service_entry {
+ iso639lang_t language_code;
+ EBIT3(uint8_t digital_cc : 1; ,
+ uint8_t reserved : 1; ,
+ uint8_t value : 6; );
+ EBIT3(uint16_t easy_reader : 1; ,
+ uint16_t wide_aspect_ratio : 1; ,
+ uint16_t reserved1 :14; );
+} __ucsi_packed;
+
+/**
+ * Process an atsc_caption_service_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_caption_service_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_caption_service_descriptor*
+ atsc_caption_service_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_caption_service_descriptor *ret =
+ (struct atsc_caption_service_descriptor *) d;
+ uint8_t *buf = (uint8_t*) d + 2;
+ int pos = 0;
+ int idx;
+
+ if (d->len < 1)
+ return NULL;
+ pos++;
+
+ for(idx = 0; idx < ret->number_of_services; idx++) {
+ if (d->len < (pos + sizeof(struct atsc_caption_service_entry)))
+ return NULL;
+
+ bswap16(buf+pos+4);
+
+ pos += sizeof(struct atsc_caption_service_entry);
+ }
+
+ return (struct atsc_caption_service_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a atsc_caption_service_descriptor.
+ *
+ * @param d atsc_caption_service_descriptor pointer.
+ * @param pos Variable holding a pointer to the current atsc_caption_service_entry.
+ * @param idx Field iterator integer.
+ */
+#define atsc_caption_service_descriptor_entries_for_each(d, pos, idx) \
+ for ((pos) = atsc_caption_service_descriptor_entries_first(d), idx=0; \
+ (pos); \
+ (pos) = atsc_caption_service_descriptor_entries_next(d, pos, ++idx))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_caption_service_entry*
+ atsc_caption_service_descriptor_entries_first(struct atsc_caption_service_descriptor *d)
+{
+ if (d->number_of_services == 0)
+ return NULL;
+
+ return (struct atsc_caption_service_entry *)
+ ((uint8_t*) d + sizeof(struct atsc_caption_service_descriptor));
+}
+
+static inline struct atsc_caption_service_entry*
+ atsc_caption_service_descriptor_entries_next(struct atsc_caption_service_descriptor *d,
+ struct atsc_caption_service_entry *pos,
+ int idx)
+{
+ if (idx >= d->number_of_services)
+ return NULL;
+
+ return (struct atsc_caption_service_entry *)
+ ((uint8_t *) pos + sizeof(struct atsc_caption_service_entry));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/component_name_descriptor.h b/lib/libucsi/atsc/component_name_descriptor.h
new file mode 100644
index 0000000..3b9cab7
--- /dev/null
+++ b/lib/libucsi/atsc/component_name_descriptor.h
@@ -0,0 +1,92 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR
+#define _UCSI_ATSC_COMPONENT_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+#include <libucsi/atsc/types.h>
+
+/**
+ * atsc_component_name_descriptor structure.
+ */
+struct atsc_component_name_descriptor {
+ struct descriptor d;
+
+ /* struct atsc_text text[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_component_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_component_name_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_component_name_descriptor*
+ atsc_component_name_descriptor_codec(struct descriptor* d)
+{
+ uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor);
+
+ if (atsc_text_validate(txt, d->len))
+ return NULL;
+
+ return (struct atsc_component_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of an atsc_component_name_descriptor.
+ *
+ * @param d atsc_component_name_descriptor pointer.
+ * @return Pointer to the atsc_text data, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_component_name_descriptor_text(struct atsc_component_name_descriptor *d)
+{
+ uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_component_name_descriptor);
+
+ return (struct atsc_text*) txt;
+}
+
+/**
+ * Accessor for the length of the text field of an atsc_component_name_descriptor_text.
+ *
+ * @param d atsc_component_name_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ atsc_component_name_descriptor_text_length(struct atsc_component_name_descriptor *d)
+{
+ return d->d.len;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/content_advisory_descriptor.h b/lib/libucsi/atsc/content_advisory_descriptor.h
new file mode 100644
index 0000000..da19813
--- /dev/null
+++ b/lib/libucsi/atsc/content_advisory_descriptor.h
@@ -0,0 +1,235 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR
+#define _UCSI_ATSC_CONTENT_ADVISORY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * atsc_content_advisory_descriptor structure.
+ */
+struct atsc_content_advisory_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 2; ,
+ uint8_t rating_region_count : 6; );
+ /* struct atsc_content_advisory_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a atsc_content_advisory_descriptor.
+ */
+struct atsc_content_advisory_entry {
+ uint8_t rating_region;
+ uint8_t rated_dimensions;
+ /* struct atsc_content_advisory_entry_dimension dimensions[] */
+ /* struct atsc_content_advisory_entry_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a atsc_content_advisory_descriptor.
+ */
+struct atsc_content_advisory_entry_dimension {
+ uint8_t rating_dimension_j;
+ EBIT2(uint8_t reserved : 4; ,
+ uint8_t rating_value : 4; );
+} __ucsi_packed;
+
+/**
+ * Part2 of an atsc_content_advisory_entry.
+ */
+struct atsc_content_advisory_entry_part2 {
+ uint8_t rating_description_length;
+ /* struct atsc_text description */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_content_advisory_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_content_advisory_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_content_advisory_descriptor*
+ atsc_content_advisory_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_content_advisory_descriptor *ret =
+ (struct atsc_content_advisory_descriptor *) d;
+ uint8_t *buf = (uint8_t*) d + 2;
+ int pos = 0;
+ int idx;
+
+ if (d->len < 1)
+ return NULL;
+ pos++;
+
+ for(idx = 0; idx < ret->rating_region_count; idx++) {
+ if (d->len < (pos + sizeof(struct atsc_content_advisory_entry)))
+ return NULL;
+ struct atsc_content_advisory_entry *entry =
+ (struct atsc_content_advisory_entry *) (buf + pos);
+ pos += sizeof(struct atsc_content_advisory_entry);
+
+ if (d->len < (pos + (sizeof(struct atsc_content_advisory_entry_dimension) *
+ entry->rated_dimensions)))
+ return NULL;
+ pos += sizeof(struct atsc_content_advisory_entry_dimension) * entry->rated_dimensions;
+
+ if (d->len < (pos + sizeof(struct atsc_content_advisory_entry_part2)))
+ return NULL;
+ struct atsc_content_advisory_entry_part2 *part2 =
+ (struct atsc_content_advisory_entry_part2 *) (buf + pos);
+ pos += sizeof(struct atsc_content_advisory_entry_part2);
+
+ if (d->len < (pos + part2->rating_description_length))
+ return NULL;
+
+ if (atsc_text_validate(buf+pos, part2->rating_description_length))
+ return NULL;
+
+ pos += part2->rating_description_length;
+ }
+
+ return (struct atsc_content_advisory_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a atsc_content_advisory_descriptor.
+ *
+ * @param d atsc_content_advisory_descriptor pointer.
+ * @param pos Variable holding a pointer to the current atsc_content_advisory_entry.
+ * @param idx Integer used to count which entry we are in.
+ */
+#define atsc_content_advisory_descriptor_entries_for_each(d, pos, idx) \
+ for ((pos) = atsc_content_advisory_descriptor_entries_first(d), idx=0; \
+ (pos); \
+ (pos) = atsc_content_advisory_descriptor_entries_next(d, pos, ++idx))
+
+/**
+ * Iterator for dimensions field of a atsc_content_advisory_entry.
+ *
+ * @param d atsc_content_advisory_entry pointer.
+ * @param pos Variable holding a pointer to the current atsc_content_advisory_entry_dimension.
+ * @param idx Integer used to count which dimension we are in.
+ */
+#define atsc_content_advisory_entry_dimensions_for_each(d, pos, idx) \
+ for ((pos) = atsc_content_advisory_entry_dimensions_first(d), idx=0; \
+ (pos); \
+ (pos) = atsc_content_advisory_entry_dimensions_next(d, pos, ++idx))
+
+/**
+ * Accessor for the part2 field of an atsc_content_advisory_entry.
+ *
+ * @param entry atsc_content_advisory_entry pointer.
+ * @return struct atsc_content_advisory_entry_part2 pointer.
+ */
+static inline struct atsc_content_advisory_entry_part2 *
+ atsc_content_advisory_entry_part2(struct atsc_content_advisory_entry *entry)
+{
+ int pos = sizeof(struct atsc_content_advisory_entry);
+ pos += entry->rated_dimensions * sizeof(struct atsc_content_advisory_entry_dimension);
+
+ return (struct atsc_content_advisory_entry_part2 *) (((uint8_t*) entry) + pos);
+}
+
+
+/**
+ * Accessor for the description field of an atsc_content_advisory_entry_part2.
+ *
+ * @param part2 atsc_content_advisory_entry_part2 pointer.
+ * @return Pointer to the atsc_text data, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_content_advisory_entry_part2_description(struct atsc_content_advisory_entry_part2 *part2)
+{
+ uint8_t *txt = ((uint8_t*) part2) + sizeof(struct atsc_content_advisory_entry_part2);
+
+ return (struct atsc_text *) txt;
+}
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_content_advisory_entry*
+ atsc_content_advisory_descriptor_entries_first(struct atsc_content_advisory_descriptor *d)
+{
+ if (d->rating_region_count == 0)
+ return NULL;
+
+ return (struct atsc_content_advisory_entry *)
+ ((uint8_t*) d + sizeof(struct atsc_content_advisory_descriptor));
+}
+
+static inline struct atsc_content_advisory_entry*
+ atsc_content_advisory_descriptor_entries_next(struct atsc_content_advisory_descriptor *d,
+ struct atsc_content_advisory_entry *pos,
+ int idx)
+{
+ if (idx >= d->rating_region_count)
+ return NULL;
+ struct atsc_content_advisory_entry_part2 *part2 =
+ atsc_content_advisory_entry_part2(pos);
+
+ return (struct atsc_content_advisory_entry *)
+ ((uint8_t *) part2 +
+ sizeof(struct atsc_content_advisory_entry_part2) +
+ part2->rating_description_length);
+}
+
+static inline struct atsc_content_advisory_entry_dimension*
+ atsc_content_advisory_entry_dimensions_first(struct atsc_content_advisory_entry *e)
+{
+ if (e->rated_dimensions == 0)
+ return NULL;
+
+ return (struct atsc_content_advisory_entry_dimension *)
+ ((uint8_t*) e + sizeof(struct atsc_content_advisory_entry));
+}
+
+static inline struct atsc_content_advisory_entry_dimension*
+ atsc_content_advisory_entry_dimensions_next(struct atsc_content_advisory_entry *e,
+ struct atsc_content_advisory_entry_dimension *pos,
+ int idx)
+{
+ uint8_t *next = (uint8_t *) pos + sizeof(struct atsc_content_advisory_entry_dimension);
+
+ if (idx >= e->rated_dimensions)
+ return NULL;
+ return (struct atsc_content_advisory_entry_dimension *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/cvct_section.c b/lib/libucsi/atsc/cvct_section.c
new file mode 100644
index 0000000..6edbc03
--- /dev/null
+++ b/lib/libucsi/atsc/cvct_section.c
@@ -0,0 +1,77 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/cvct_section.h>
+
+struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = sizeof(struct atsc_section_psip);
+ size_t len = section_ext_length(&(psip->ext_head));
+ int idx;
+
+ if (len < sizeof(struct atsc_cvct_section))
+ return NULL;
+ struct atsc_cvct_section *cvct = (struct atsc_cvct_section *) psip;
+
+ pos++;
+ for(idx =0; idx < cvct->num_channels_in_section; idx++) {
+ if ((pos + sizeof(struct atsc_cvct_channel)) > len)
+ return NULL;
+ struct atsc_cvct_channel *channel = (struct atsc_cvct_channel *) (buf+pos);
+
+ pos += 7*2;
+
+ bswap32(buf+pos);
+ bswap32(buf+pos+4);
+ bswap16(buf+pos+8);
+ bswap16(buf+pos+10);
+ bswap16(buf+pos+12);
+ bswap16(buf+pos+14);
+ bswap16(buf+pos+16);
+ pos+=18;
+
+ if ((pos + channel->descriptors_length) > len)
+ return NULL;
+ if (verify_descriptors(buf + pos, channel->descriptors_length))
+ return NULL;
+
+ pos += channel->descriptors_length;
+ }
+
+ if ((pos + sizeof(struct atsc_cvct_section_part2)) > len)
+ return NULL;
+ struct atsc_cvct_section_part2 *part2 = (struct atsc_cvct_section_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+ pos+=2;
+
+ if ((pos + part2->descriptors_length) > len)
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+
+ pos += part2->descriptors_length;
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_cvct_section *) psip;
+}
diff --git a/lib/libucsi/atsc/cvct_section.h b/lib/libucsi/atsc/cvct_section.h
new file mode 100644
index 0000000..c3d418a
--- /dev/null
+++ b/lib/libucsi/atsc/cvct_section.h
@@ -0,0 +1,228 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_CVCT_SECTION_H
+#define _UCSI_ATSC_CVCT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+
+/**
+ * atsc_cvct_section structure.
+ */
+struct atsc_cvct_section {
+ struct atsc_section_psip head;
+
+ uint8_t num_channels_in_section;
+ /* struct atsc_cvct_channel channels[] */
+ /* struct atsc_cvct_channel_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_cvct_channel {
+ uint16_t short_name[7]; // UTF-16 network ordered
+ EBIT4(uint32_t reserved : 4; ,
+ uint32_t major_channel_number :10; ,
+ uint32_t minor_channel_number :10; ,
+ uint32_t modulation_mode : 8; );
+ uint32_t carrier_frequency;
+ uint16_t channel_TSID;
+ uint16_t program_number;
+ EBIT8(uint16_t ETM_location : 2; ,
+ uint16_t access_controlled : 1; ,
+ uint16_t hidden : 1; ,
+ uint16_t path_select : 1; ,
+ uint16_t out_of_band : 1; ,
+ uint16_t hide_guide : 1; ,
+ uint16_t reserved2 : 3; ,
+ uint16_t service_type : 6; );
+ uint16_t source_id;
+ EBIT2(uint16_t reserved3 : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_cvct_section_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+static inline struct atsc_cvct_channel *atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct);
+static inline struct atsc_cvct_channel *
+ atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct, struct atsc_cvct_channel *pos, int idx);
+
+/**
+ * Process a atsc_cvct_section.
+ *
+ * @param section Pointer to anj atsc_section_psip structure.
+ * @return atsc_cvct_section pointer, or NULL on error.
+ */
+struct atsc_cvct_section *atsc_cvct_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the transport_stream_id field of a CVCT.
+ *
+ * @param cvdt CVDT pointer.
+ * @return The transport_stream_id.
+ */
+static inline uint16_t atsc_cvct_section_transport_stream_id(struct atsc_cvct_section *cvct)
+{
+ return cvct->head.ext_head.table_id_ext;
+}
+
+/**
+ * Iterator for the tables field in an atsc_cvct_section.
+ *
+ * @param mgt atsc_cvct_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_cvct_channel.
+ * @param idx Integer used to count which table we in.
+ */
+#define atsc_cvct_section_channels_for_each(mgt, pos, idx) \
+ for ((pos) = atsc_cvct_section_channels_first(mgt), idx=0; \
+ (pos); \
+ (pos) = atsc_cvct_section_channels_next(mgt, pos, ++idx))
+
+/**
+ * Iterator for the descriptors field in a atsc_cvct_channel structure.
+ *
+ * @param table atsc_cvct_channel pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_cvct_channel_descriptors_for_each(table, pos) \
+ for ((pos) = atsc_cvct_channel_descriptors_first(table); \
+ (pos); \
+ (pos) = atsc_cvct_channel_descriptors_next(table, pos))
+
+/**
+ * Accessor for the second part of an atsc_cvct_section.
+ *
+ * @param mgt atsc_cvct_section pointer.
+ * @return atsc_cvct_section_part2 pointer.
+ */
+static inline struct atsc_cvct_section_part2 *
+ atsc_cvct_section_part2(struct atsc_cvct_section *mgt)
+{
+ int pos = sizeof(struct atsc_cvct_section);
+
+ struct atsc_cvct_channel *cur_table;
+ int idx;
+ atsc_cvct_section_channels_for_each(mgt, cur_table, idx) {
+ pos += sizeof(struct atsc_cvct_channel);
+ pos += cur_table->descriptors_length;
+ }
+
+ return (struct atsc_cvct_section_part2 *) (((uint8_t*) mgt) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_cvct_section structure.
+ *
+ * @param part2 atsc_cvct_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_cvct_section_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_cvct_section_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_cvct_section_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_cvct_channel *
+ atsc_cvct_section_channels_first(struct atsc_cvct_section *cvct)
+{
+ size_t pos = sizeof(struct atsc_cvct_section);
+
+ if (cvct->num_channels_in_section == 0)
+ return NULL;
+
+ return (struct atsc_cvct_channel*) (((uint8_t *) cvct) + pos);
+}
+
+static inline struct atsc_cvct_channel *
+ atsc_cvct_section_channels_next(struct atsc_cvct_section *cvct,
+ struct atsc_cvct_channel *pos,
+ int idx)
+{
+ if (idx >= cvct->num_channels_in_section)
+ return NULL;
+
+ return (struct atsc_cvct_channel *)
+ (((uint8_t*) pos) + sizeof(struct atsc_cvct_channel) + pos->descriptors_length);
+}
+
+static inline struct descriptor *
+ atsc_cvct_channel_descriptors_first(struct atsc_cvct_channel *table)
+{
+ size_t pos = sizeof(struct atsc_cvct_channel);
+
+ if (table->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) table) + pos);
+}
+
+static inline struct descriptor *
+ atsc_cvct_channel_descriptors_next(struct atsc_cvct_channel *table,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) table + sizeof(struct atsc_cvct_channel),
+ table->descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_cvct_section_part2_descriptors_first(struct atsc_cvct_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_cvct_section_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_cvct_section_part2_descriptors_next(struct atsc_cvct_section_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_cvct_section_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/dcc_arriving_request_descriptor.h b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h
new file mode 100644
index 0000000..af76eac
--- /dev/null
+++ b/lib/libucsi/atsc/dcc_arriving_request_descriptor.h
@@ -0,0 +1,107 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR
+#define _UCSI_ATSC_DCC_ARRIVING_REQUEST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+enum atsc_dcc_arriving_request_type {
+ DCC_ARRIVAL_TYPE_DEFER_10SEC = 0x01,
+ DCC_ARRIVAL_TYPE_DEFER = 0x02,
+};
+
+/**
+ * atsc_dcc_arriving_request_descriptor structure.
+ */
+struct atsc_dcc_arriving_request_descriptor {
+ struct descriptor d;
+
+ uint8_t dcc_arriving_request_type;
+ uint8_t dcc_arriving_request_text_length;
+ /* struct atsc_text text[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_dcc_arriving_request_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_dcc_arriving_request_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_dcc_arriving_request_descriptor*
+ atsc_dcc_arriving_request_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_dcc_arriving_request_descriptor *ret =
+ (struct atsc_dcc_arriving_request_descriptor *) d;
+
+ if (d->len < 2)
+ return NULL;
+
+ if (d->len != 2 + ret->dcc_arriving_request_text_length)
+ return NULL;
+
+ if (atsc_text_validate((uint8_t*) d + sizeof(struct atsc_dcc_arriving_request_descriptor),
+ ret->dcc_arriving_request_text_length))
+ return NULL;
+
+ return (struct atsc_dcc_arriving_request_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of an atsc_dcc_arriving_request_descriptor.
+ *
+ * @param d atsc_dcc_arriving_request_descriptor pointer.
+ * @return Pointer to the atsc_text data, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_dcc_arriving_request_descriptor_text(struct atsc_dcc_arriving_request_descriptor *d)
+{
+ uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_arriving_request_descriptor);
+
+ return (struct atsc_text*) txt;
+}
+
+/**
+ * Accessor for the length of the text field of an atsc_dcc_arriving_request_descriptor.
+ *
+ * @param d atsc_dcc_arriving_request_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ atsc_dcc_arriving_request_descriptor_text_length(struct
+ atsc_dcc_arriving_request_descriptor *d)
+{
+ return d->d.len - 2;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/dcc_departing_request_descriptor.h b/lib/libucsi/atsc/dcc_departing_request_descriptor.h
new file mode 100644
index 0000000..851f0cc
--- /dev/null
+++ b/lib/libucsi/atsc/dcc_departing_request_descriptor.h
@@ -0,0 +1,108 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR
+#define _UCSI_ATSC_DCC_DEPARTING_REQUEST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+enum atsc_dcc_departing_request_type {
+ DCC_DEPART_TYPE_IMMEDIATE = 0x01,
+ DCC_DEPART_TYPE_DEFER_10SEC = 0x02,
+ DCC_DEPART_TYPE_DEFER = 0x03,
+};
+
+/**
+ * atsc_dcc_departing_request_descriptor structure.
+ */
+struct atsc_dcc_departing_request_descriptor {
+ struct descriptor d;
+
+ uint8_t dcc_departing_request_type;
+ uint8_t dcc_departing_request_text_length;
+ /* struct atsc_text text[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_dcc_departing_request_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_dcc_departing_request_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_dcc_departing_request_descriptor*
+ atsc_dcc_departing_request_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_dcc_departing_request_descriptor *ret =
+ (struct atsc_dcc_departing_request_descriptor *) d;
+
+ if (d->len < 2)
+ return NULL;
+
+ if (d->len != 2 + ret->dcc_departing_request_text_length)
+ return NULL;
+
+ if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor),
+ ret->dcc_departing_request_text_length))
+ return NULL;
+
+ return (struct atsc_dcc_departing_request_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of an atsc_dcc_departing_request_descriptor.
+ *
+ * @param d atsc_dcc_departing_request_descriptor pointer.
+ * @return Pointer to the atsc_text data, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_dcc_departing_request_descriptor_text(struct atsc_dcc_departing_request_descriptor *d)
+{
+ uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_dcc_departing_request_descriptor);
+
+ return (struct atsc_text*) txt;
+}
+
+/**
+ * Accessor for the length of the text field of an atsc_dcc_departing_request_descriptor.
+ *
+ * @param d atsc_dcc_departing_request_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ atsc_dcc_departing_request_descriptor_text_length(struct
+ atsc_dcc_departing_request_descriptor *d)
+{
+ return d->d.len - 2;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/dccsct_section.c b/lib/libucsi/atsc/dccsct_section.c
new file mode 100644
index 0000000..59ad069
--- /dev/null
+++ b/lib/libucsi/atsc/dccsct_section.c
@@ -0,0 +1,109 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/dccsct_section.h>
+
+struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = 0;
+ size_t len = section_ext_length(&(psip->ext_head));
+ int idx;
+
+ if (len < sizeof(struct atsc_dccsct_section))
+ return NULL;
+ struct atsc_dccsct_section *dccsct = (struct atsc_dccsct_section *) psip;
+
+ pos += sizeof(struct atsc_dccsct_section);
+ for(idx =0; idx < dccsct->updates_defined; idx++) {
+ if (len < (pos + sizeof(struct atsc_dccsct_update)))
+ return NULL;
+ struct atsc_dccsct_update *update = (struct atsc_dccsct_update *) (buf+pos);
+
+ pos += sizeof(struct atsc_dccsct_update);
+ if (len < (pos + update->update_data_length))
+ return NULL;
+
+ switch(update->update_type) {
+ case ATSC_DCCST_UPDATE_NEW_GENRE: {
+ int sublen = sizeof(struct atsc_dccsct_update_new_genre);
+ if (update->update_data_length < sublen)
+ return NULL;
+
+ if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen))
+ return NULL;
+ break;
+ }
+ case ATSC_DCCST_UPDATE_NEW_STATE: {
+ int sublen = sizeof(struct atsc_dccsct_update_new_state);
+ if (update->update_data_length < sublen)
+ return NULL;
+
+ if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen))
+ return NULL;
+ break;
+ }
+ case ATSC_DCCST_UPDATE_NEW_COUNTY: {
+ int sublen = sizeof(struct atsc_dccsct_update_new_county);
+ if (update->update_data_length < sublen)
+ return NULL;
+ bswap16(buf+pos+1);
+
+ if (atsc_text_validate(buf+pos+sublen, update->update_data_length - sublen))
+ return NULL;
+ break;
+ }
+ }
+
+ pos += update->update_data_length;
+ if (len < (pos + sizeof(struct atsc_dccsct_update_part2)))
+ return NULL;
+ struct atsc_dccsct_update_part2 *part2 = (struct atsc_dccsct_update_part2 *) buf + pos;
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_dccsct_update_part2);
+ if (len < (pos + part2->descriptors_length))
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+
+ pos += part2->descriptors_length;
+ }
+
+ if (len < (pos + sizeof(struct atsc_dccsct_section_part2)))
+ return NULL;
+ struct atsc_dccsct_section_part2 *part2 = (struct atsc_dccsct_section_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_dccsct_section_part2);
+ if (len < (pos + part2->descriptors_length))
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+
+ pos += part2->descriptors_length;
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_dccsct_section *) psip;
+}
diff --git a/lib/libucsi/atsc/dccsct_section.h b/lib/libucsi/atsc/dccsct_section.h
new file mode 100644
index 0000000..f9f3522
--- /dev/null
+++ b/lib/libucsi/atsc/dccsct_section.h
@@ -0,0 +1,327 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_DCCSCT_SECTION_H
+#define _UCSI_ATSC_DCCSCT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+#include <libucsi/atsc/types.h>
+
+enum atsc_dccst_update_types {
+ ATSC_DCCST_UPDATE_NEW_GENRE = 0x01,
+ ATSC_DCCST_UPDATE_NEW_STATE = 0x02,
+ ATSC_DCCST_UPDATE_NEW_COUNTY = 0x03,
+};
+
+/**
+ * atsc_dccsct_section structure.
+ */
+struct atsc_dccsct_section {
+ struct atsc_section_psip head;
+
+ uint8_t updates_defined;
+ /* struct atsc_dccsct_update updates */
+ /* struct atsc_dccsct_section_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_dccsct_update {
+ uint8_t update_type;
+ uint8_t update_data_length;
+ /* struct atsc_dccsct_update_XXX data -- depends on update_type */
+ /* struct atsc_dccsct_update_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_dccsct_update_new_genre {
+ uint8_t genre_category_code;
+ /* atsc_text name */
+} __ucsi_packed;
+
+struct atsc_dccsct_update_new_state {
+ uint8_t dcc_state_location_code;
+ /* atsc_text name */
+} __ucsi_packed;
+
+struct atsc_dccsct_update_new_county {
+ uint8_t state_code;
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t dcc_county_location_code :10; );
+ /* atsc_text name */
+} __ucsi_packed;
+
+struct atsc_dccsct_update_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_dccsct_section_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_dccsct_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_dccsct_section pointer, or NULL on error.
+ */
+struct atsc_dccsct_section *atsc_dccsct_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the dccsct_type field of a dccsct.
+ *
+ * @param dccsct dccsct pointer.
+ * @return The dccsct_type.
+ */
+static inline uint16_t atsc_dccsct_section_dccsct_type(struct atsc_dccsct_section *dccsct)
+{
+ return dccsct->head.ext_head.table_id_ext;
+}
+
+/**
+ * Iterator for the updates field in an atsc_dccsct_section.
+ *
+ * @param dccsct atsc_dccsct_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_dccsct_update.
+ * @param idx Integer used to count which test we are in.
+ */
+#define atsc_dccsct_section_updates_for_each(dccsct, pos, idx) \
+ for ((pos) = atsc_dccsct_section_updates_first(dccsct), idx=0; \
+ (pos); \
+ (pos) = atsc_dccsct_section_updates_next(dccsct, pos, ++idx))
+
+/**
+ * Accessor for the data field of a new genre atsc_dccsct_update.
+ *
+ * @param update atsc_dccsct_update pointer.
+ * @return struct atsc_dccsct_update_new_genre pointer.
+ */
+static inline struct atsc_dccsct_update_new_genre *atsc_dccsct_update_new_genre(struct atsc_dccsct_update *update)
+{
+ if (update->update_type != ATSC_DCCST_UPDATE_NEW_GENRE)
+ return NULL;
+
+ return (struct atsc_dccsct_update_new_genre *)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update));
+}
+
+/**
+ * Accessor for the name field of an atsc_dccsct_update_new_genre.
+ *
+ * @param update atsc_dccsct_update_new_genre pointer.
+ * @return text pointer.
+ */
+static inline struct atsc_text *atsc_dccsct_update_new_genre_name(struct atsc_dccsct_update *update)
+{
+ if ((update->update_data_length - 1) == 0)
+ return NULL;
+
+ return (struct atsc_text *)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_genre));
+}
+
+/**
+ * Accessor for the data field of a new state atsc_dccsct_update.
+ *
+ * @param update atsc_dccsct_update pointer.
+ * @return struct atsc_dccsct_update_new_state pointer.
+ */
+static inline struct atsc_dccsct_update_new_state *
+ atsc_dccsct_update_new_state(struct atsc_dccsct_update *update)
+{
+ if (update->update_type != ATSC_DCCST_UPDATE_NEW_STATE)
+ return NULL;
+
+ return (struct atsc_dccsct_update_new_state *)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update));
+}
+
+/**
+ * Accessor for the name field of an atsc_dccsct_update_new_state.
+ *
+ * @param update atsc_dccsct_update_new_state pointer.
+ * @return text pointer.
+ */
+static inline struct atsc_text *atsc_dccsct_update_new_state_name(struct atsc_dccsct_update *update)
+{
+ if ((update->update_data_length - 1) == 0)
+ return NULL;
+
+ return (struct atsc_text *)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_state));
+}
+
+/**
+ * Accessor for the data field of a new county atsc_dccsct_update.
+ *
+ * @param update atsc_dccsct_update pointer.
+ * @return struct atsc_dccsct_update_new_county pointer.
+ */
+static inline struct atsc_dccsct_update_new_county *
+ atsc_dccsct_update_new_county(struct atsc_dccsct_update *update)
+{
+ if (update->update_type != ATSC_DCCST_UPDATE_NEW_COUNTY)
+ return NULL;
+
+ return (struct atsc_dccsct_update_new_county *)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update));
+}
+
+/**
+ * Accessor for the name field of an atsc_dccsct_update_new_county.
+ *
+ * @param update atsc_dccsct_update_new_county pointer.
+ * @return text pointer.
+ */
+static inline struct atsc_text *atsc_dccsct_update_new_county_name(struct atsc_dccsct_update *update)
+{
+ if ((update->update_data_length - 3) == 0)
+ return NULL;
+
+ return (struct atsc_text*)
+ (((uint8_t*) update) + sizeof(struct atsc_dccsct_update_new_county));
+}
+
+/**
+ * Accessor for the part2 field of an atsc_dccsct_update.
+ *
+ * @param update atsc_dccsct_update pointer.
+ * @return struct atsc_dccsct_test_part2 pointer.
+ */
+static inline struct atsc_dccsct_update_part2 *atsc_dccsct_update_part2(struct atsc_dccsct_update *update)
+{
+ int pos = sizeof(struct atsc_dccsct_update);
+ pos += update->update_data_length;
+
+ return (struct atsc_dccsct_update_part2 *) (((uint8_t*) update) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in an atsc_dccsct_update_part2 structure.
+ *
+ * @param part2 atsc_dccsct_update_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_dccsct_update_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_dccsct_update_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_dccsct_update_part2_descriptors_next(part2, pos))
+
+/**
+ * Iterator for the descriptors field in a atsc_dccsct_section_part2 structure.
+ *
+ * @param part2 atsc_dccsct_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_dccsct_section_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_dccsct_section_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_dccsct_section_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_dccsct_update *
+ atsc_dccsct_section_updates_first(struct atsc_dccsct_section *dccsct)
+{
+ size_t pos = sizeof(struct atsc_dccsct_section);
+
+ if (dccsct->updates_defined == 0)
+ return NULL;
+
+ return (struct atsc_dccsct_update*) (((uint8_t *) dccsct) + pos);
+}
+
+static inline struct atsc_dccsct_update*
+ atsc_dccsct_section_updates_next(struct atsc_dccsct_section *dccsct,
+ struct atsc_dccsct_update *pos,
+ int idx)
+{
+ if (idx >= dccsct->updates_defined)
+ return NULL;
+
+ struct atsc_dccsct_update_part2 *part2 = atsc_dccsct_update_part2(pos);
+ int len = sizeof(struct atsc_dccsct_update_part2);
+ len += part2->descriptors_length;
+
+ return (struct atsc_dccsct_update *) (((uint8_t*) part2) + len);
+}
+
+static inline struct descriptor *
+ atsc_dccsct_update_part2_descriptors_first(struct atsc_dccsct_update_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_dccsct_update_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_dccsct_update_part2_descriptors_next(struct atsc_dccsct_update_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_update_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_dccsct_section_part2_descriptors_first(struct atsc_dccsct_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_dccsct_section_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_dccsct_section_part2_descriptors_next(struct atsc_dccsct_section_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dccsct_section_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/dcct_section.c b/lib/libucsi/atsc/dcct_section.c
new file mode 100644
index 0000000..7d0b83b
--- /dev/null
+++ b/lib/libucsi/atsc/dcct_section.c
@@ -0,0 +1,96 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/dcct_section.h>
+
+struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = 0;
+ size_t len = section_ext_length(&(psip->ext_head));
+ int testidx;
+ int termidx;
+
+ if (len < sizeof(struct atsc_dcct_section))
+ return NULL;
+ struct atsc_dcct_section *dcct = (struct atsc_dcct_section *) psip;
+
+ pos += sizeof(struct atsc_dcct_section);
+ for(testidx =0; testidx < dcct->dcc_test_count; testidx++) {
+ if (len < (pos + sizeof(struct atsc_dcct_test)))
+ return NULL;
+ struct atsc_dcct_test *test = (struct atsc_dcct_test *) (buf+pos);
+
+ bswap24(buf+pos);
+ bswap24(buf+pos+3);
+ bswap32(buf+pos+6);
+ bswap32(buf+pos+10);
+
+ pos += sizeof(struct atsc_dcct_test);
+ for(termidx =0; termidx < test->dcc_term_count; termidx++) {
+ if (len < (pos + sizeof(struct atsc_dcct_term)))
+ return NULL;
+ struct atsc_dcct_term *term = (struct atsc_dcct_term *) (buf+pos);
+
+ bswap64(buf+pos+1);
+ bswap16(buf+pos+9);
+
+ pos += sizeof(struct atsc_dcct_term);
+ if (len < (pos + term->descriptors_length))
+ return NULL;
+ if (verify_descriptors(buf + pos, term->descriptors_length))
+ return NULL;
+
+ pos += term->descriptors_length;
+ }
+
+ if (len < (pos + sizeof(struct atsc_dcct_test_part2)))
+ return NULL;
+ struct atsc_dcct_test_part2 *part2 = (struct atsc_dcct_test_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_dcct_test_part2);
+ if (len < (pos + part2->descriptors_length))
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+ pos += part2->descriptors_length;
+ }
+
+ if (len < (pos + sizeof(struct atsc_dcct_section_part2)))
+ return NULL;
+ struct atsc_dcct_section_part2 *part2 = (struct atsc_dcct_section_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_dcct_section_part2);
+ if (len < (pos + part2->descriptors_length))
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+
+ pos += part2->descriptors_length;
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_dcct_section *) psip;
+}
diff --git a/lib/libucsi/atsc/dcct_section.h b/lib/libucsi/atsc/dcct_section.h
new file mode 100644
index 0000000..647bd4b
--- /dev/null
+++ b/lib/libucsi/atsc/dcct_section.h
@@ -0,0 +1,380 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_DCCT_SECTION_H
+#define _UCSI_ATSC_DCCT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+#include <libucsi/atsc/types.h>
+
+enum atsc_dcc_context {
+ ATSC_DCC_CONTEXT_TEMPORARY_RETUNE = 0,
+ ATSC_DCC_CONTEXT_CHANNEL_REDIRECT = 1,
+};
+
+enum atsc_dcc_selection_type {
+ ATSC_DCC_SELECTION_UNCONDITIONAL_CHANNEL_CHANGE = 0x00,
+ ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_INCLUSION = 0x01,
+ ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_INCLUSION = 0x02,
+ ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ONE_OR_MORE = 0x05,
+ ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_ALL = 0x06,
+ ATSC_DCC_SELECTION_GENRE_CATEGORY_ONE_OR_MORE = 0x07,
+ ATSC_DCC_SELECTION_GENRE_CATEGORY_ALL = 0x08,
+ ATSC_DCC_SELECTION_CANNOT_BE_AUTHORIZED = 0x09,
+ ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_INCLUSION = 0x0c,
+ ATSC_DCC_SELECTION_RATING_BLOCKED = 0x0d,
+ ATSC_DCC_SELECTION_RETURN_TO_ORIGINAL_CHANNEL = 0x0f,
+ ATSC_DCC_SELECTION_NUMERIC_POSTAL_CODE_EXCLUSION = 0x11,
+ ATSC_DCC_SELECTION_ALPHANUMERIC_POSTAL_CODE_EXCLUSION = 0x12,
+ ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ONE_OR_MORE = 0x15,
+ ATSC_DCC_SELECTION_DEMOGRAPHIC_CATEGORY_NOT_ALL = 0x16,
+ ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ONE_OR_MORE = 0x17,
+ ATSC_DCC_SELECTION_GENRE_CATEGORY_NOT_ALL = 0x18,
+ ATSC_DCC_SELECTION_GEOGRAPHIC_LOCATION_EXCLUSION = 0x1c,
+ ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_A = 0x20,
+ ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_B = 0x21,
+ ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_C = 0x22,
+ ATSC_DCC_SELECTION_VIEWER_DIRECT_SELECT_D = 0x23,
+};
+
+/**
+ * atsc_dcct_section structure.
+ */
+struct atsc_dcct_section {
+ struct atsc_section_psip head;
+
+ uint8_t dcc_test_count;
+ /* struct atsc_dcct_test tests */
+ /* struct atsc_dcct_section_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_dcct_test {
+ EBIT4(uint32_t dcc_context : 1; ,
+ uint32_t reserved : 3; ,
+ uint32_t dcc_from_major_channel_number :10; ,
+ uint32_t dcc_from_minor_channel_number :10; );
+ EBIT3(uint32_t reserved1 : 4; ,
+ uint32_t dcc_to_major_channel_number :10; ,
+ uint32_t dcc_to_minor_channel_number :10; );
+ atsctime_t start_time;
+ atsctime_t end_time;
+ uint8_t dcc_term_count;
+ /* struct atsc_dcct_term terms */
+ /* struct atsc_dcct_test_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_dcct_term {
+ uint8_t dcc_selection_type;
+ uint64_t dcc_selection_id;
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_dcct_test_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_dcct_section_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+static inline struct atsc_dcct_test *
+ atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct);
+static inline struct atsc_dcct_test *
+ atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct,
+ struct atsc_dcct_test *pos,
+ int idx);
+static inline struct atsc_dcct_term *
+ atsc_dcct_test_terms_first(struct atsc_dcct_test *test);
+static inline struct atsc_dcct_term *
+ atsc_dcct_test_terms_next(struct atsc_dcct_test *test,
+ struct atsc_dcct_term *pos,
+ int idx);
+
+
+/**
+ * Process an atsc_dcct_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_dcct_section pointer, or NULL on error.
+ */
+struct atsc_dcct_section *atsc_dcct_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the dcc_subtype field of a dcct.
+ *
+ * @param dcct dcct pointer.
+ * @return The dcc_subtype.
+ */
+static inline uint8_t atsc_dcct_section_dcc_subtype(struct atsc_dcct_section *dcct)
+{
+ return dcct->head.ext_head.table_id_ext >> 8;
+}
+
+/**
+ * Accessor for the dcc_id field of a dcct.
+ *
+ * @param dcct dcct pointer.
+ * @return The dcc_id.
+ */
+static inline uint8_t atsc_dcct_section_dcc_id(struct atsc_dcct_section *dcct)
+{
+ return dcct->head.ext_head.table_id_ext & 0xff;
+}
+
+/**
+ * Iterator for the tests field in an atsc_dcct_section.
+ *
+ * @param dcct atsc_dcct_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_dcct_test.
+ * @param idx Integer used to count which test we are in.
+ */
+#define atsc_dcct_section_tests_for_each(dcct, pos, idx) \
+ for ((pos) = atsc_dcct_section_tests_first(dcct), idx=0; \
+ (pos); \
+ (pos) = atsc_dcct_section_tests_next(dcct, pos, ++idx))
+
+/**
+ * Iterator for the terms field in an atsc_dcct_test.
+ *
+ * @param test atsc_dcct_test pointer.
+ * @param pos Variable containing a pointer to the current atsc_dcct_term.
+ * @param idx Integer used to count which test we are in.
+ */
+#define atsc_dcct_test_terms_for_each(test, pos, idx) \
+ for ((pos) = atsc_dcct_test_terms_first(test), idx=0; \
+ (pos); \
+ (pos) = atsc_dcct_test_terms_next(test, pos, ++idx))
+
+/**
+ * Iterator for the descriptors field in a atsc_dcct_term structure.
+ *
+ * @param term atsc_dcct_term pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_dcct_term_descriptors_for_each(term, pos) \
+ for ((pos) = atsc_dcct_term_descriptors_first(term); \
+ (pos); \
+ (pos) = atsc_dcct_term_descriptors_next(term, pos))
+
+/**
+ * Accessor for the part2 field of an atsc_dcct_test.
+ *
+ * @param test atsc_dcct_test pointer.
+ * @return struct atsc_dcct_test_part2 pointer.
+ */
+static inline struct atsc_dcct_test_part2 *atsc_dcct_test_part2(struct atsc_dcct_test *test)
+{
+ int pos = sizeof(struct atsc_dcct_test);
+
+ struct atsc_dcct_term *cur_term;
+ int idx;
+ atsc_dcct_test_terms_for_each(test, cur_term, idx) {
+ pos += sizeof(struct atsc_dcct_term);
+ pos += cur_term->descriptors_length;
+ }
+
+ return (struct atsc_dcct_test_part2 *) (((uint8_t*) test) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_dcct_test_part2 structure.
+ *
+ * @param term atsc_dcct_test_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_dcct_test_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_dcct_test_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_dcct_test_part2_descriptors_next(part2, pos))
+
+/**
+ * Accessor for the part2 field of an atsc_dcct_section.
+ *
+ * @param dcct atsc_dcct_section pointer.
+ * @return struct atsc_dcct_section_part2 pointer.
+ */
+static inline struct atsc_dcct_section_part2 *atsc_dcct_section_part2(struct atsc_dcct_section *dcct)
+{
+ int pos = sizeof(struct atsc_dcct_section);
+
+ struct atsc_dcct_test *cur_test;
+ int testidx;
+ atsc_dcct_section_tests_for_each(dcct, cur_test, testidx) {
+ struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(cur_test);
+ pos += ((uint8_t*) part2 - (uint8_t*) cur_test);
+
+ pos += sizeof(struct atsc_dcct_test_part2);
+ pos += part2->descriptors_length;
+ }
+
+ return (struct atsc_dcct_section_part2 *) (((uint8_t*) dcct) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_dcct_section_part2 structure.
+ *
+ * @param part2 atsc_dcct_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_dcct_section_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_dcct_section_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_dcct_section_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_dcct_test *
+ atsc_dcct_section_tests_first(struct atsc_dcct_section *dcct)
+{
+ size_t pos = sizeof(struct atsc_dcct_section);
+
+ if (dcct->dcc_test_count == 0)
+ return NULL;
+
+ return (struct atsc_dcct_test*) (((uint8_t *) dcct) + pos);
+}
+
+static inline struct atsc_dcct_test *
+ atsc_dcct_section_tests_next(struct atsc_dcct_section *dcct,
+ struct atsc_dcct_test *pos,
+ int idx)
+{
+ if (idx >= dcct->dcc_test_count)
+ return NULL;
+
+ struct atsc_dcct_test_part2 *part2 = atsc_dcct_test_part2(pos);
+ int len = sizeof(struct atsc_dcct_test_part2);
+ len += part2->descriptors_length;
+
+ return (struct atsc_dcct_test *) (((uint8_t*) part2) + len);
+}
+
+static inline struct atsc_dcct_term *
+ atsc_dcct_test_terms_first(struct atsc_dcct_test *test)
+{
+ size_t pos = sizeof(struct atsc_dcct_test);
+
+ if (test->dcc_term_count == 0)
+ return NULL;
+
+ return (struct atsc_dcct_term*) (((uint8_t *) test) + pos);
+}
+
+static inline struct atsc_dcct_term *
+ atsc_dcct_test_terms_next(struct atsc_dcct_test *test,
+ struct atsc_dcct_term *pos,
+ int idx)
+{
+ if (idx >= test->dcc_term_count)
+ return NULL;
+
+ int len = sizeof(struct atsc_dcct_term);
+ len += pos->descriptors_length;
+
+ return (struct atsc_dcct_term *) (((uint8_t*) pos) + len);
+}
+
+static inline struct descriptor *
+ atsc_dcct_term_descriptors_first(struct atsc_dcct_term *term)
+{
+ size_t pos = sizeof(struct atsc_dcct_term);
+
+ if (term->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) term) + pos);
+}
+
+static inline struct descriptor *
+ atsc_dcct_term_descriptors_next(struct atsc_dcct_term *term,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) term + sizeof(struct atsc_dcct_term),
+ term->descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_dcct_test_part2_descriptors_first(struct atsc_dcct_test_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_dcct_test_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_dcct_test_part2_descriptors_next(struct atsc_dcct_test_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_test_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_dcct_section_part2_descriptors_first(struct atsc_dcct_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_dcct_section_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_dcct_section_part2_descriptors_next(struct atsc_dcct_section_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_dcct_section_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/descriptor.h b/lib/libucsi/atsc/descriptor.h
new file mode 100644
index 0000000..a57176a
--- /dev/null
+++ b/lib/libucsi/atsc/descriptor.h
@@ -0,0 +1,68 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_DESCRIPTOR_H
+#define _UCSI_ATSC_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/endianops.h>
+#include <libucsi/atsc/stuffing_descriptor.h>
+#include <libucsi/atsc/ac3_descriptor.h>
+#include <libucsi/atsc/caption_service_descriptor.h>
+#include <libucsi/atsc/component_name_descriptor.h>
+#include <libucsi/atsc/content_advisory_descriptor.h>
+#include <libucsi/atsc/dcc_arriving_request_descriptor.h>
+#include <libucsi/atsc/dcc_departing_request_descriptor.h>
+#include <libucsi/atsc/extended_channel_name_descriptor.h>
+#include <libucsi/atsc/genre_descriptor.h>
+#include <libucsi/atsc/rc_descriptor.h>
+#include <libucsi/atsc/service_location_descriptor.h>
+#include <libucsi/atsc/time_shifted_service_descriptor.h>
+
+/**
+ * Enumeration of ATSC descriptor tags.
+ */
+enum atsc_descriptor_tag {
+ dtag_atsc_stuffing = 0x80,
+ dtag_atsc_ac3_audio = 0x81,
+ dtag_atsc_caption_service = 0x86,
+ dtag_atsc_content_advisory = 0x87,
+ dtag_atsc_extended_channel_name = 0xa0,
+ dtag_atsc_service_location = 0xa1,
+ dtag_atsc_time_shifted_service = 0xa2,
+ dtag_atsc_component_name = 0xa3,
+ dtag_atsc_dcc_departing_request = 0xa8,
+ dtag_atsc_dcc_arriving_request = 0xa9,
+ dtag_atsc_redistribution_control = 0xaa,
+ dtag_atsc_private_information = 0xad,
+ dtag_atsc_content_identifier = 0xb6,
+ dtag_atsc_genre = 0xab,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/eit_section.c b/lib/libucsi/atsc/eit_section.c
new file mode 100644
index 0000000..48cdda6
--- /dev/null
+++ b/lib/libucsi/atsc/eit_section.c
@@ -0,0 +1,71 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/eit_section.h>
+
+struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = 0;
+ size_t len = section_ext_length(&(psip->ext_head));
+ int idx;
+
+ if (len < sizeof(struct atsc_eit_section))
+ return NULL;
+ struct atsc_eit_section *eit = (struct atsc_eit_section *) psip;
+
+ pos += sizeof(struct atsc_eit_section);
+ for(idx =0; idx < eit->num_events_in_section; idx++) {
+ if (len < (pos + sizeof(struct atsc_eit_event)))
+ return NULL;
+ struct atsc_eit_event *event = (struct atsc_eit_event *) (buf+pos);
+
+ bswap16(buf+pos);
+ bswap32(buf+pos+2);
+ bswap32(buf+pos+6);
+
+ pos += sizeof(struct atsc_eit_event);
+ if (len < (pos + event->title_length))
+ return NULL;
+ if (atsc_text_validate(buf+pos, event->title_length))
+ return NULL;
+
+ pos += event->title_length;
+ if (len < (pos + sizeof(struct atsc_eit_event_part2)))
+ return NULL;
+ struct atsc_eit_event_part2 *part2 = (struct atsc_eit_event_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_eit_event_part2);
+ if (len < (pos + part2->descriptors_length))
+ return NULL;
+
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+ pos += part2->descriptors_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_eit_section *) psip;
+}
diff --git a/lib/libucsi/atsc/eit_section.h b/lib/libucsi/atsc/eit_section.h
new file mode 100644
index 0000000..84bef16
--- /dev/null
+++ b/lib/libucsi/atsc/eit_section.h
@@ -0,0 +1,191 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_EIT_SECTION_H
+#define _UCSI_ATSC_EIT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+#include <libucsi/atsc/types.h>
+
+/**
+ * atsc_eit_section structure.
+ */
+struct atsc_eit_section {
+ struct atsc_section_psip head;
+
+ uint8_t num_events_in_section;
+ /* struct atsc_eit_event events[] */
+} __ucsi_packed;
+
+struct atsc_eit_event {
+ EBIT2(uint16_t reserved : 2; ,
+ uint16_t event_id :14; );
+ atsctime_t start_time;
+ EBIT4(uint32_t reserved1 : 2; ,
+ uint32_t ETM_location : 2; ,
+ uint32_t length_in_seconds :20; ,
+ uint32_t title_length : 8; );
+ /* struct atsc_text title_text */
+ /* struct atsc_eit_event_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_eit_event_part2 {
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+
+/**
+ * Process a atsc_eit_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_eit_section pointer, or NULL on error.
+ */
+struct atsc_eit_section *atsc_eit_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the source_id field of an EIT.
+ *
+ * @param eit EIT pointer.
+ * @return The source_id .
+ */
+static inline uint16_t atsc_eit_section_source_id(struct atsc_eit_section *eit)
+{
+ return eit->head.ext_head.table_id_ext;
+}
+
+/**
+ * Iterator for the events field in an atsc_eit_section.
+ *
+ * @param eit atsc_eit_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_eit_event.
+ * @param idx Integer used to count which event we are in.
+ */
+#define atsc_eit_section_events_for_each(eit, pos, idx) \
+ for ((pos) = atsc_eit_section_events_first(eit), idx=0; \
+ (pos); \
+ (pos) = atsc_eit_section_events_next(eit, pos, ++idx))
+
+/**
+ * Accessor for the title_text field of an atsc_eit_event.
+ *
+ * @param event atsc_eit_event pointer.
+ * @return struct atsc_text pointer, or NULL on error.
+ */
+static inline struct atsc_text *atsc_eit_event_name_title_text(struct atsc_eit_event *event)
+{
+ if (event->title_length == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) event) + sizeof(struct atsc_eit_event));
+}
+
+/**
+ * Accessor for the part2 field of an atsc_eit_event.
+ *
+ * @param event atsc_eit_event pointer.
+ * @return struct atsc_eit_event_part2 pointer.
+ */
+static inline struct atsc_eit_event_part2 *atsc_eit_event_part2(struct atsc_eit_event *event)
+{
+ return (struct atsc_eit_event_part2 *)
+ (((uint8_t*) event) + sizeof(struct atsc_eit_event) + event->title_length);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_eit_section structure.
+ *
+ * @param part2 atsc_eit_event_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_eit_event_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_eit_event_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_eit_event_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_eit_event *
+ atsc_eit_section_events_first(struct atsc_eit_section *eit)
+{
+ size_t pos = sizeof(struct atsc_eit_section);
+
+ if (eit->num_events_in_section == 0)
+ return NULL;
+
+ return (struct atsc_eit_event*) (((uint8_t *) eit) + pos);
+}
+
+static inline struct atsc_eit_event *
+ atsc_eit_section_events_next(struct atsc_eit_section *eit,
+ struct atsc_eit_event *pos,
+ int idx)
+{
+ if (idx >= eit->num_events_in_section)
+ return NULL;
+
+ struct atsc_eit_event_part2 *part2 = atsc_eit_event_part2(pos);
+ int len = sizeof(struct atsc_eit_event_part2);
+ len += part2->descriptors_length;
+
+ return (struct atsc_eit_event *) (((uint8_t*) part2) + len);
+}
+
+static inline struct descriptor *
+ atsc_eit_event_part2_descriptors_first(struct atsc_eit_event_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_eit_event_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_eit_event_part2_descriptors_next(struct atsc_eit_event_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_eit_event_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/ett_section.c b/lib/libucsi/atsc/ett_section.c
new file mode 100644
index 0000000..ab2ff9c
--- /dev/null
+++ b/lib/libucsi/atsc/ett_section.c
@@ -0,0 +1,42 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/ett_section.h>
+#include <libucsi/atsc/types.h>
+
+struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = sizeof(struct atsc_section_psip);
+ size_t len = section_ext_length(&(psip->ext_head));
+
+ if (len < sizeof(struct atsc_ett_section))
+ return NULL;
+
+ bswap32(buf + pos);
+ pos += 4;
+
+ if (atsc_text_validate(buf + pos,
+ section_ext_length(&psip->ext_head) - sizeof(struct atsc_ett_section)))
+ return NULL;
+
+ return (struct atsc_ett_section *) psip;
+}
diff --git a/lib/libucsi/atsc/ett_section.h b/lib/libucsi/atsc/ett_section.h
new file mode 100644
index 0000000..e2bb510
--- /dev/null
+++ b/lib/libucsi/atsc/ett_section.h
@@ -0,0 +1,91 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_ETT_SECTION_H
+#define _UCSI_ATSC_ETT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+
+enum atsc_etm_type {
+ ATSC_ETM_CHANNEL = 0x00,
+ ATSC_ETM_EVENT = 0x02,
+};
+
+/**
+ * atsc_ett_section structure.
+ */
+struct atsc_ett_section {
+ struct atsc_section_psip head;
+
+ EBIT3(uint32_t ETM_source_id :16; ,
+ uint32_t ETM_sub_id :14; ,
+ uint32_t ETM_type : 2; );
+ /* struct atsc_text extended_text_message */
+} __ucsi_packed;
+
+/**
+ * Process a atsc_ett_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_ett_section pointer, or NULL on error.
+ */
+struct atsc_ett_section *atsc_ett_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the extended_text_message part of an atsc_ett_section.
+ *
+ * @param ett atsc_ett_section pointer.
+ * @return atsc_text pointer, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_ett_section_extended_text_message(struct atsc_ett_section *ett)
+{
+ int pos = sizeof(struct atsc_ett_section);
+ int len = section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section);
+
+ if (len == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) ett) + pos);
+}
+
+/**
+ * Accessor for the extended_text_message part of an atsc_ett_section.
+ *
+ * @param ett atsc_ett_section pointer.
+ * @return The length.
+ */
+static inline int
+ atsc_ett_section_extended_text_message_length(struct atsc_ett_section *ett)
+{
+ return section_ext_length(&ett->head.ext_head) - sizeof(struct atsc_ett_section);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/extended_channel_name_descriptor.h b/lib/libucsi/atsc/extended_channel_name_descriptor.h
new file mode 100644
index 0000000..d0b714b
--- /dev/null
+++ b/lib/libucsi/atsc/extended_channel_name_descriptor.h
@@ -0,0 +1,92 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR
+#define _UCSI_ATSC_EXTENDED_CHANNEL_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+#include <libucsi/atsc/types.h>
+
+/**
+ * atsc_extended_channel_name_descriptor structure.
+ */
+struct atsc_extended_channel_name_descriptor {
+ struct descriptor d;
+
+ /* struct atsc_text text[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_extended_channel_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_extended_channel_name_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_extended_channel_name_descriptor*
+ atsc_extended_channel_name_descriptor_codec(struct descriptor* d)
+{
+ if (atsc_text_validate(((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor),
+ d->len))
+ return NULL;
+
+ return (struct atsc_extended_channel_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of an atsc_extended_channel_name_descriptor.
+ *
+ * @param d atsc_extended_channel_name_descriptor pointer.
+ * @return Pointer to the atsc_text data, or NULL on error.
+ */
+static inline struct atsc_text*
+ atsc_extended_channel_name_descriptor_text(struct atsc_extended_channel_name_descriptor *d)
+{
+ uint8_t *txt = ((uint8_t*) d) + sizeof(struct atsc_extended_channel_name_descriptor);
+
+ return (struct atsc_text*) txt;
+}
+
+/**
+ * Accessor for the length of the text field of an atsc_extended_channel_name_descriptor.
+ *
+ * @param d atsc_extended_channel_name_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ atsc_extended_channel_name_descriptor_text_length(struct
+ atsc_extended_channel_name_descriptor *d)
+{
+ return d->d.len;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/genre_descriptor.h b/lib/libucsi/atsc/genre_descriptor.h
new file mode 100644
index 0000000..a6fc542
--- /dev/null
+++ b/lib/libucsi/atsc/genre_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_GENRE_DESCRIPTOR
+#define _UCSI_ATSC_GENRE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * atsc_genre_descriptor structure.
+ */
+struct atsc_genre_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 3; ,
+ uint8_t attribute_count : 5; );
+ /* uint8_t attributes[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_genre_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_genre_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_genre_descriptor*
+ atsc_genre_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_genre_descriptor *ret =
+ (struct atsc_genre_descriptor *) d;
+
+ if (d->len < 1)
+ return NULL;
+
+ if (d->len != (1 + ret->attribute_count))
+ return NULL;
+
+ return (struct atsc_genre_descriptor*) d;
+}
+
+/**
+ * Accessor for the attributes field of an atsc_genre_descriptor.
+ *
+ * @param d atsc_genre_descriptor pointer.
+ * @return Pointer to the attributes.
+ */
+static inline uint8_t*
+ atsc_genre_descriptor_attributes(struct atsc_genre_descriptor *d)
+{
+ return ((uint8_t*) d) + sizeof(struct atsc_genre_descriptor);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/mgt_section.c b/lib/libucsi/atsc/mgt_section.c
new file mode 100644
index 0000000..bc6b3f2
--- /dev/null
+++ b/lib/libucsi/atsc/mgt_section.c
@@ -0,0 +1,76 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/mgt_section.h>
+
+struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = sizeof(struct atsc_section_psip);
+ size_t len = section_ext_length(&(psip->ext_head));
+ struct atsc_mgt_section *mgt = (struct atsc_mgt_section *) psip;
+ int i;
+
+ if (len < sizeof(struct atsc_mgt_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+
+ // we cannot use the tables_defined value here because of the braindead ATSC spec!
+ for(i=0; i < mgt->tables_defined; i++) {
+ // we think we're still in the tables - process as normal
+ if ((pos + sizeof(struct atsc_mgt_table)) > len)
+ return NULL;
+ struct atsc_mgt_table *table = (struct atsc_mgt_table *) (buf+pos);
+
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap32(buf+pos+5);
+ bswap16(buf+pos+9);
+
+ pos += sizeof(struct atsc_mgt_table);
+ if ((pos + table->table_type_descriptors_length) > len)
+ return NULL;
+ if (verify_descriptors(buf + pos, table->table_type_descriptors_length))
+ return NULL;
+
+ pos += table->table_type_descriptors_length;
+ }
+
+ if ((pos + sizeof(struct atsc_mgt_section_part2)) > len)
+ return NULL;
+ struct atsc_mgt_section_part2 *part2 = (struct atsc_mgt_section_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+
+ pos += sizeof(struct atsc_mgt_section_part2);
+ if ((pos + part2->descriptors_length) > len)
+ return NULL;
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+ pos += part2->descriptors_length;
+
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_mgt_section *) psip;
+}
diff --git a/lib/libucsi/atsc/mgt_section.h b/lib/libucsi/atsc/mgt_section.h
new file mode 100644
index 0000000..3102a54
--- /dev/null
+++ b/lib/libucsi/atsc/mgt_section.h
@@ -0,0 +1,215 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_MGT_SECTION_H
+#define _UCSI_ATSC_MGT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+
+enum atsc_mgt_section_table_type {
+ ATSC_MGT_TABLE_TYPE_TVCT_CURRENT = 0,
+ ATSC_MGT_TABLE_TYPE_TVCT_NEXT = 1,
+ ATSC_MGT_TABLE_TYPE_CVCT_CURRENT = 2,
+ ATSC_MGT_TABLE_TYPE_CVCT_NEXT = 3,
+ ATSC_MGT_TABLE_TYPE_CHANNEL_ETT = 4,
+ ATSC_MGT_TABLE_TYPE_DCCSCT = 5,
+};
+
+/**
+ * atsc_mgt_section structure.
+ */
+struct atsc_mgt_section {
+ struct atsc_section_psip head;
+
+ uint16_t tables_defined;
+ /* struct atsc_mgt_table tables[] */
+ /* struct atsc_mgt_section_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_mgt_table {
+ uint16_t table_type;
+ EBIT2(uint16_t reserved : 3; ,
+ uint16_t table_type_PID :13; );
+ EBIT2(uint8_t reserved1 : 3; ,
+ uint8_t table_type_version_number : 5; );
+ uint32_t number_bytes;
+ EBIT2(uint16_t reserved2 : 4; ,
+ uint16_t table_type_descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_mgt_section_part2 {
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+static inline struct atsc_mgt_table * atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt);
+static inline struct atsc_mgt_table *
+ atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt, struct atsc_mgt_table *pos, int idx);
+
+/**
+ * Process a atsc_mgt_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_mgt_section pointer, or NULL on error.
+ */
+struct atsc_mgt_section *atsc_mgt_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Iterator for the tables field in an atsc_mgt_section.
+ *
+ * @param mgt atsc_mgt_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_mgt_table.
+ * @param idx Integer used to count which table we in.
+ */
+#define atsc_mgt_section_tables_for_each(mgt, pos, idx) \
+ for ((pos) = atsc_mgt_section_tables_first(mgt), idx=0; \
+ (pos); \
+ (pos) = atsc_mgt_section_tables_next(mgt, pos, ++idx))
+
+/**
+ * Iterator for the descriptors field in a atsc_mgt_table structure.
+ *
+ * @param table atsc_mgt_table pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_mgt_table_descriptors_for_each(table, pos) \
+ for ((pos) = atsc_mgt_table_descriptors_first(table); \
+ (pos); \
+ (pos) = atsc_mgt_table_descriptors_next(table, pos))
+
+/**
+ * Accessor for the second part of an atsc_mgt_section.
+ *
+ * @param mgt atsc_mgt_section pointer.
+ * @return atsc_mgt_section_part2 pointer.
+ */
+static inline struct atsc_mgt_section_part2 *
+ atsc_mgt_section_part2(struct atsc_mgt_section *mgt)
+{
+ int pos = sizeof(struct atsc_mgt_section);
+
+ struct atsc_mgt_table *cur_table;
+ int idx;
+ atsc_mgt_section_tables_for_each(mgt, cur_table, idx) {
+ pos += sizeof(struct atsc_mgt_table);
+ pos += cur_table->table_type_descriptors_length;
+ }
+
+ return (struct atsc_mgt_section_part2 *) (((uint8_t*) mgt) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_mgt_section structure.
+ *
+ * @param part2 atsc_mgt_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_mgt_section_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_mgt_section_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_mgt_section_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_mgt_table *
+ atsc_mgt_section_tables_first(struct atsc_mgt_section *mgt)
+{
+ size_t pos = sizeof(struct atsc_mgt_section);
+
+ if (mgt->tables_defined == 0)
+ return NULL;
+
+ return (struct atsc_mgt_table*) (((uint8_t *) mgt) + pos);
+}
+
+static inline struct atsc_mgt_table *
+ atsc_mgt_section_tables_next(struct atsc_mgt_section *mgt,
+ struct atsc_mgt_table *pos,
+ int idx)
+{
+ if (idx >= mgt->tables_defined)
+ return NULL;
+
+ return (struct atsc_mgt_table *)
+ (((uint8_t*) pos) + sizeof(struct atsc_mgt_table) + pos->table_type_descriptors_length);
+}
+
+static inline struct descriptor *
+ atsc_mgt_table_descriptors_first(struct atsc_mgt_table *table)
+{
+ size_t pos = sizeof(struct atsc_mgt_table);
+
+ if (table->table_type_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) table) + pos);
+}
+
+static inline struct descriptor *
+ atsc_mgt_table_descriptors_next(struct atsc_mgt_table *table,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) table + sizeof(struct atsc_mgt_table),
+ table->table_type_descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_mgt_section_part2_descriptors_first(struct atsc_mgt_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_mgt_section_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_mgt_section_part2_descriptors_next(struct atsc_mgt_section_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_mgt_section_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/rc_descriptor.h b/lib/libucsi/atsc/rc_descriptor.h
new file mode 100644
index 0000000..4fb0e8e
--- /dev/null
+++ b/lib/libucsi/atsc/rc_descriptor.h
@@ -0,0 +1,83 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_RC_DESCRIPTOR
+#define _UCSI_ATSC_RC_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * atsc_rc_descriptor structure.
+ */
+struct atsc_rc_descriptor {
+ struct descriptor d;
+
+ /* uint8_t info[] */
+} __ucsi_packed;
+
+/**
+ * Process an atsc_rc_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_rc_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_rc_descriptor*
+ atsc_rc_descriptor_codec(struct descriptor* d)
+{
+ return (struct atsc_rc_descriptor*) d;
+}
+
+/**
+ * Accessor for the info field of an atsc_rc_descriptor.
+ *
+ * @param d atsc_rc_descriptor pointer.
+ * @return Pointer to the atsc_text data.
+ */
+static inline uint8_t*
+ atsc_rc_descriptor_info(struct atsc_rc_descriptor *d)
+{
+ return ((uint8_t*) d) + sizeof(struct atsc_rc_descriptor);
+}
+
+/**
+ * Accessor for the length of the info field of an atsc_rc_descriptor.
+ *
+ * @param d atsc_rc_descriptor pointer.
+ * @return The length
+ */
+static inline int
+ atsc_rc_descriptor_info_length(struct atsc_rc_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/rrt_section.c b/lib/libucsi/atsc/rrt_section.c
new file mode 100644
index 0000000..6e96c3a
--- /dev/null
+++ b/lib/libucsi/atsc/rrt_section.c
@@ -0,0 +1,108 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/rrt_section.h>
+
+struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = 0;
+ size_t len = section_ext_length(&(psip->ext_head));
+ int idx;
+ int vidx;
+ struct atsc_rrt_section *rrt = (struct atsc_rrt_section *) psip;
+
+ if (len < sizeof(struct atsc_rrt_section))
+ return NULL;
+ pos += sizeof(struct atsc_rrt_section);
+
+ if (len < (pos + rrt->rating_region_name_length))
+ return NULL;
+ if (atsc_text_validate(buf+pos, rrt->rating_region_name_length))
+ return NULL;
+
+ pos += rrt->rating_region_name_length;
+ if (len < (pos + sizeof(struct atsc_rrt_section_part2)))
+ return NULL;
+ struct atsc_rrt_section_part2 *rrtpart2 = (struct atsc_rrt_section_part2 *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_section_part2);
+ for(idx =0; idx < rrtpart2->dimensions_defined; idx++) {
+ if (len < (pos + sizeof(struct atsc_rrt_dimension)))
+ return NULL;
+ struct atsc_rrt_dimension *dimension = (struct atsc_rrt_dimension *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_dimension);
+ if (len < (pos + dimension->dimension_name_length))
+ return NULL;
+ if (atsc_text_validate(buf+pos, dimension->dimension_name_length))
+ return NULL;
+
+ pos += dimension->dimension_name_length;
+ if (len < (pos + sizeof(struct atsc_rrt_dimension_part2)))
+ return NULL;
+ struct atsc_rrt_dimension_part2 *dpart2 = (struct atsc_rrt_dimension_part2 *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_dimension_part2);
+ for(vidx =0; vidx < dpart2->values_defined; vidx++) {
+ if (len < (pos + sizeof(struct atsc_rrt_dimension_value)))
+ return NULL;
+ struct atsc_rrt_dimension_value *value = (struct atsc_rrt_dimension_value *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_dimension_value);
+ if (len < (pos + value->abbrev_rating_value_length))
+ return NULL;
+ if (atsc_text_validate(buf+pos, value->abbrev_rating_value_length))
+ return NULL;
+
+ pos += value->abbrev_rating_value_length;
+ if (len < (pos + sizeof(struct atsc_rrt_dimension_value_part2)))
+ return NULL;
+ struct atsc_rrt_dimension_value_part2 *vpart2 =
+ (struct atsc_rrt_dimension_value_part2 *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_dimension_value_part2);
+ if (len < (pos + vpart2->rating_value_length))
+ return NULL;
+ if (atsc_text_validate(buf+pos, vpart2->rating_value_length))
+ return NULL;
+
+ pos+= vpart2->rating_value_length;
+ }
+ }
+
+ if (len < (pos + sizeof(struct atsc_rrt_section_part3)))
+ return NULL;
+ struct atsc_rrt_section_part3 *part3 = (struct atsc_rrt_section_part3 *) (buf+pos);
+
+ pos += sizeof(struct atsc_rrt_section_part3);
+ if (len < (pos + part3->descriptors_length))
+ return NULL;
+
+ if (verify_descriptors(buf + pos, part3->descriptors_length))
+ return NULL;
+
+ pos += part3->descriptors_length;
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_rrt_section *) psip;
+}
diff --git a/lib/libucsi/atsc/rrt_section.h b/lib/libucsi/atsc/rrt_section.h
new file mode 100644
index 0000000..fba4596
--- /dev/null
+++ b/lib/libucsi/atsc/rrt_section.h
@@ -0,0 +1,379 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_RRT_SECTION_H
+#define _UCSI_ATSC_RRT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+#include <libucsi/atsc/types.h>
+
+/**
+ * atsc_rrt_section structure.
+ */
+struct atsc_rrt_section {
+ struct atsc_section_psip head;
+
+ uint8_t rating_region_name_length;
+ /* struct atsc_text rating_region_name_text */
+ /* struct atsc_rrt_section_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_rrt_section_part2 {
+ uint8_t dimensions_defined;
+ /* struct atsc_rrt_dimension dimensions[] */
+ /* struct atsc_rrt_section_part3 part3 */
+} __ucsi_packed;
+
+struct atsc_rrt_dimension {
+ uint8_t dimension_name_length;
+ /* struct atsc_text dimension_name_text */
+ /* struct atsc_rrt_dimension_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_rrt_dimension_part2 {
+ EBIT3(uint8_t reserved : 3; ,
+ uint8_t graduated_scale : 1; ,
+ uint8_t values_defined : 4; );
+ /* struct atsc_rrt_dimension_value values[] */
+} __ucsi_packed;
+
+struct atsc_rrt_dimension_value {
+ uint8_t abbrev_rating_value_length;
+ /* struct atsc_text abbrev_rating_value_text */
+ /* struct atsc_rrt_dimension_value_part2 */
+} __ucsi_packed;
+
+struct atsc_rrt_dimension_value_part2 {
+ uint8_t rating_value_length;
+ /* struct atsc_text rating_value_text */
+} __ucsi_packed;
+
+struct atsc_rrt_section_part3 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+
+static inline struct atsc_rrt_dimension *
+ atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2);
+static inline struct atsc_rrt_dimension *
+ atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2,
+ struct atsc_rrt_dimension *pos,
+ int idx);
+static inline struct atsc_rrt_dimension_value *
+ atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2);
+static inline struct atsc_rrt_dimension_value *
+ atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2,
+ struct atsc_rrt_dimension_value *pos,
+ int idx);
+
+/**
+ * Process a atsc_rrt_section.
+ *
+ * @param section Pointer to anj atsc_section_psip structure.
+ * @return atsc_rrt_section pointer, or NULL on error.
+ */
+struct atsc_rrt_section *atsc_rrt_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the rating_region field of an RRT.
+ *
+ * @param rrt RRT pointer.
+ * @return The transport_stream_id.
+ */
+static inline uint8_t atsc_rrt_section_rating_region(struct atsc_rrt_section *rrt)
+{
+ return rrt->head.ext_head.table_id_ext & 0xff;
+}
+
+/**
+ * Accessor for the rating_region_name_text field of an RRT.
+ *
+ * @param rrt RRT pointer.
+ * @return struct atsc_text pointer, or NULL.
+ */
+static inline struct atsc_text *atsc_rrt_section_rating_region_name_text(struct atsc_rrt_section *rrt)
+{
+ if (rrt->rating_region_name_length == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) rrt) + sizeof(struct atsc_rrt_section));
+}
+
+/**
+ * Accessor for the part2 field of an RRT.
+ *
+ * @param rrt RRT pointer.
+ * @return struct atsc_rrt_section_part2 pointer.
+ */
+static inline struct atsc_rrt_section_part2 *atsc_rrt_section_part2(struct atsc_rrt_section *rrt)
+{
+ return (struct atsc_rrt_section_part2 *)
+ (((uint8_t*) rrt) + sizeof(struct atsc_rrt_section) +
+ rrt->rating_region_name_length);
+}
+
+/**
+ * Iterator for the dimensions field in an atsc_rrt_section_part2.
+ *
+ * @param rrt atsc_rrt_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_rrt_dimension.
+ * @param idx Integer used to count which dimension we are in.
+ */
+#define atsc_rrt_section_dimensions_for_each(rrt, pos, idx) \
+ for ((pos) = atsc_rrt_section_dimensions_first(rrt), idx=0; \
+ (pos); \
+ (pos) = atsc_rrt_section_dimensions_next(rrt, pos, ++idx))
+
+/**
+ * Accessor for the dimension_name_text field of an atsc_rrt_dimension.
+ *
+ * @param dimension atsc_rrt_dimension pointer.
+ * @return struct atsc_text pointer, or NULL on error.
+ */
+static inline struct atsc_text *atsc_rrt_dimension_name_text(struct atsc_rrt_dimension *dimension)
+{
+ if (dimension->dimension_name_length == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) dimension) + sizeof(struct atsc_rrt_dimension));
+}
+
+/**
+ * Accessor for the part2 field of an atsc_rrt_dimension.
+ *
+ * @param dimension atsc_rrt_dimension pointer.
+ * @return struct atsc_rrt_dimension_part2 pointer.
+ */
+static inline struct atsc_rrt_dimension_part2 *atsc_rrt_dimension_part2(struct atsc_rrt_dimension *dimension)
+{
+ return (struct atsc_rrt_dimension_part2 *)
+ (((uint8_t*) dimension) +
+ sizeof(struct atsc_rrt_dimension) +
+ dimension->dimension_name_length);
+}
+
+/**
+ * Iterator for the values field in a atsc_rrt_dimension_part2 structure.
+ *
+ * @param part2 atsc_rrt_dimension_part2 pointer.
+ * @param pos Variable containing a pointer to the current value.
+ * @param idx Integer used to count which value we are in
+ */
+#define atsc_rrt_dimension_part2_values_for_each(part2, pos, idx) \
+ for ((pos) = atsc_rrt_dimension_part2_values_first(part2), idx=0; \
+ (pos); \
+ (pos) = atsc_rrt_dimension_part2_values_next(part2, pos, ++idx))
+
+/**
+ * Accessor for the dimension_name_text field of an atsc_rrt_dimension.
+ *
+ * @param dimension atsc_rrt_dimension pointer.
+ * @return struct atsc_text pointer.
+ */
+static inline struct atsc_text *
+ atsc_rrt_dimension_value_abbrev_rating_value_text(struct atsc_rrt_dimension_value *value)
+{
+ if (value->abbrev_rating_value_length == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) value) + sizeof(struct atsc_rrt_dimension_value));
+}
+
+/**
+ * Accessor for the part2 field of an atsc_rrt_dimension_value.
+ *
+ * @param value atsc_rrt_dimension_value pointer.
+ * @return struct atsc_rrt_dimension_value_part2 pointer.
+ */
+static inline struct atsc_rrt_dimension_value_part2 *atsc_rrt_dimension_value_part2(struct atsc_rrt_dimension_value *value)
+{
+ return (struct atsc_rrt_dimension_value_part2 *)
+ (((uint8_t*) value) +
+ sizeof(struct atsc_rrt_dimension_value) +
+ value->abbrev_rating_value_length);
+}
+
+/**
+ * Accessor for the rating_value_text field of an atsc_rrt_dimension_value_part2.
+ *
+ * @param part2 atsc_rrt_dimension_value_part2 pointer.
+ * @return struct atsc_text pointer.
+ */
+static inline struct atsc_text *atsc_rrt_dimension_value_part2_rating_value_text(struct atsc_rrt_dimension_value_part2 *part2)
+{
+ if (part2->rating_value_length == 0)
+ return NULL;
+
+ return (struct atsc_text*)(((uint8_t*) part2) + sizeof(struct atsc_rrt_dimension_value_part2));
+}
+
+/**
+ * Accessor for the third part of an atsc_rrt_section.
+ *
+ * @param part2 atsc_rrt_section_part2 pointer.
+ * @return atsc_rrt_section_part3 pointer.
+ */
+static inline struct atsc_rrt_section_part3 *
+ atsc_rrt_section_part3(struct atsc_rrt_section_part2 *part2)
+{
+ int pos = sizeof(struct atsc_rrt_section_part2);
+
+ struct atsc_rrt_dimension *cur_dimension;
+ int idx;
+ atsc_rrt_section_dimensions_for_each(part2, cur_dimension, idx) {
+ pos += sizeof(struct atsc_rrt_dimension);
+ pos += cur_dimension->dimension_name_length;
+ pos += sizeof(struct atsc_rrt_dimension_part2);
+
+ // now we need to iterate over the values. yuck
+ struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(cur_dimension);
+ struct atsc_rrt_dimension_value *cur_value;
+ int vidx;
+ atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) {
+ pos += sizeof(struct atsc_rrt_dimension_value);
+ pos += cur_value->abbrev_rating_value_length;
+
+ struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value);
+ pos += sizeof(struct atsc_rrt_dimension_value_part2);
+ pos += vpart2->rating_value_length;
+ }
+ }
+
+ return (struct atsc_rrt_section_part3 *) (((uint8_t*) part2) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_rrt_section structure.
+ *
+ * @param part3 atsc_rrt_section_part3 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_rrt_section_part3_descriptors_for_each(part3, pos) \
+ for ((pos) = atsc_rrt_section_part3_descriptors_first(part3); \
+ (pos); \
+ (pos) = atsc_rrt_section_part3_descriptors_next(part3, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_rrt_dimension *
+ atsc_rrt_section_dimensions_first(struct atsc_rrt_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_rrt_section_part2);
+
+ if (part2->dimensions_defined == 0)
+ return NULL;
+
+ return (struct atsc_rrt_dimension*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct atsc_rrt_dimension *
+ atsc_rrt_section_dimensions_next(struct atsc_rrt_section_part2 *part2,
+ struct atsc_rrt_dimension *pos,
+ int idx)
+{
+ if (idx >= part2->dimensions_defined)
+ return NULL;
+
+ struct atsc_rrt_dimension_part2 *dpart2 = atsc_rrt_dimension_part2(pos);
+ int len = sizeof(struct atsc_rrt_dimension_part2);
+
+ // now we need to iterate over the values. yuck
+ struct atsc_rrt_dimension_value *cur_value;
+ int vidx;
+ atsc_rrt_dimension_part2_values_for_each(dpart2, cur_value, vidx) {
+ len += sizeof(struct atsc_rrt_dimension_value);
+ len += cur_value->abbrev_rating_value_length;
+
+ struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(cur_value);
+ len += sizeof(struct atsc_rrt_dimension_value_part2);
+ len += vpart2->rating_value_length;
+ }
+
+ return (struct atsc_rrt_dimension *) (((uint8_t*) dpart2) + len);
+}
+
+static inline struct atsc_rrt_dimension_value *
+ atsc_rrt_dimension_part2_values_first(struct atsc_rrt_dimension_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_rrt_dimension_part2);
+
+ if (part2->values_defined == 0)
+ return NULL;
+
+ return (struct atsc_rrt_dimension_value*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct atsc_rrt_dimension_value *
+ atsc_rrt_dimension_part2_values_next(struct atsc_rrt_dimension_part2 *part2,
+ struct atsc_rrt_dimension_value *pos,
+ int idx)
+{
+ if (idx >= part2->values_defined)
+ return NULL;
+
+ struct atsc_rrt_dimension_value_part2 *vpart2 = atsc_rrt_dimension_value_part2(pos);
+ int len = sizeof(struct atsc_rrt_dimension_value_part2);
+ len += vpart2->rating_value_length;
+
+ return (struct atsc_rrt_dimension_value *) (((uint8_t*) vpart2) + len);
+}
+
+static inline struct descriptor *
+ atsc_rrt_section_part3_descriptors_first(struct atsc_rrt_section_part3 *part3)
+{
+ size_t pos = sizeof(struct atsc_rrt_section_part3);
+
+ if (part3->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part3) + pos);
+}
+
+static inline struct descriptor *
+ atsc_rrt_section_part3_descriptors_next(struct atsc_rrt_section_part3 *part3,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part3 + sizeof(struct atsc_rrt_section_part3),
+ part3->descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/section.h b/lib/libucsi/atsc/section.h
new file mode 100644
index 0000000..23d59ea
--- /dev/null
+++ b/lib/libucsi/atsc/section.h
@@ -0,0 +1,84 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/section.h>
+#include <libucsi/atsc/mgt_section.h>
+#include <libucsi/atsc/tvct_section.h>
+#include <libucsi/atsc/cvct_section.h>
+#include <libucsi/atsc/rrt_section.h>
+#include <libucsi/atsc/eit_section.h>
+#include <libucsi/atsc/ett_section.h>
+#include <libucsi/atsc/stt_section.h>
+#include <libucsi/atsc/dcct_section.h>
+#include <libucsi/atsc/dccsct_section.h>
+
+#ifndef _UCSI_ATSC_SECTION_H
+#define _UCSI_ATSC_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define ATSC_BASE_PID 0x1ffb
+
+/**
+ * Enumeration of ATSC section tags.
+ */
+enum atsc_section_tag {
+ stag_atsc_master_guide = 0xc7,
+ stag_atsc_terrestrial_virtual_channel = 0xc8,
+ stag_atsc_cable_virtual_channel = 0xc9,
+ stag_atsc_rating_region = 0xca,
+ stag_atsc_event_information = 0xcb,
+ stag_atsc_extended_text = 0xcc,
+ stag_atsc_system_time = 0xcd,
+};
+
+/**
+ * ATSC specific PSIP section structure.
+ */
+struct atsc_section_psip {
+ struct section_ext ext_head;
+ uint8_t protocol_version;
+} __ucsi_packed;
+
+/**
+ * Decode a PSIP section structure.
+ *
+ * @param section_ext Pointer to the processed section_ext structure.
+ * @return Pointer to the parsed section_psip structure, or NULL if invalid.
+ */
+static inline struct atsc_section_psip *atsc_section_psip_decode(struct section_ext *section_ext)
+{
+ size_t len = section_ext_length(section_ext);
+ if (len < sizeof(struct atsc_section_psip)) {
+ return NULL;
+ }
+
+ return (struct atsc_section_psip *) section_ext;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/service_location_descriptor.h b/lib/libucsi/atsc/service_location_descriptor.h
new file mode 100644
index 0000000..aad5b4a
--- /dev/null
+++ b/lib/libucsi/atsc/service_location_descriptor.h
@@ -0,0 +1,141 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR
+#define _UCSI_ATSC_SERVICE_LOCATION_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+enum atsc_stream_types {
+ ATSC_STREAM_TYPE_VIDEO = 0x02,
+ ATSC_STREAM_TYPE_AUDIO = 0x81,
+};
+
+/**
+ * atsc_service_location_descriptor structure.
+ */
+struct atsc_service_location_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint16_t reserved : 3; ,
+ uint16_t PCR_PID :13; );
+ uint8_t number_elements;
+ /* struct atsc_service_location_element elements[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the elements field of an atsc_service_location_descriptor.
+ */
+struct atsc_caption_service_location_element {
+ uint8_t stream_type;
+ EBIT2(uint16_t reserved : 3; ,
+ uint16_t elementary_PID :13; );
+ iso639lang_t language_code;
+} __ucsi_packed;
+
+/**
+ * Process an atsc_service_location_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_service_location_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_service_location_descriptor*
+ atsc_service_location_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_service_location_descriptor *ret =
+ (struct atsc_service_location_descriptor *) d;
+ uint8_t *buf = (uint8_t*) d + 2;
+ int pos = 0;
+ int idx;
+
+ if (d->len < 3)
+ return NULL;
+ bswap16(buf + pos);
+ pos+=3;
+
+ for(idx = 0; idx < ret->number_elements; idx++) {
+ if (d->len < (pos + sizeof(struct atsc_caption_service_entry)))
+ return NULL;
+
+ bswap16(buf+pos+1);
+
+ pos += sizeof(struct atsc_caption_service_entry);
+ }
+
+ return (struct atsc_service_location_descriptor*) d;
+}
+
+/**
+ * Iterator for elements field of a atsc_service_location_descriptor.
+ *
+ * @param d atsc_service_location_descriptor pointer.
+ * @param pos Variable holding a pointer to the current atsc_service_location_element.
+ * @param idx Integer used to count which dimension we are in.
+ */
+#define atsc_service_location_descriptor_elements_for_each(d, pos, idx) \
+ for ((pos) = atsc_service_location_descriptor_elements_first(d), idx=0; \
+ (pos); \
+ (pos) = atsc_service_location_descriptor_elements_next(d, pos, ++idx))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_caption_service_location_element*
+ atsc_service_location_descriptor_elements_first(struct atsc_service_location_descriptor *d)
+{
+ if (d->number_elements == 0)
+ return NULL;
+
+ return (struct atsc_caption_service_location_element *)
+ ((uint8_t*) d + sizeof(struct atsc_service_location_descriptor));
+}
+
+static inline struct atsc_caption_service_location_element*
+ atsc_service_location_descriptor_elements_next(struct atsc_service_location_descriptor *d,
+ struct atsc_caption_service_location_element *pos,
+ int idx)
+{
+ uint8_t *next = (uint8_t *) pos + sizeof(struct atsc_caption_service_location_element);
+
+ if (idx >= d->number_elements)
+ return NULL;
+ return (struct atsc_caption_service_location_element *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/stt_section.c b/lib/libucsi/atsc/stt_section.c
new file mode 100644
index 0000000..23ddd76
--- /dev/null
+++ b/lib/libucsi/atsc/stt_section.c
@@ -0,0 +1,42 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/stt_section.h>
+
+struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t *buf = (uint8_t *) psip;
+ size_t pos = sizeof(struct atsc_section_psip);
+ size_t len = section_ext_length(&(psip->ext_head));
+
+ if (len < sizeof(struct atsc_stt_section))
+ return NULL;
+
+ bswap32(buf + pos);
+ pos += 5;
+ bswap16(buf + pos);
+ pos += 2;
+
+ if (verify_descriptors(buf + pos, len - sizeof(struct atsc_stt_section)))
+ return NULL;
+
+ return (struct atsc_stt_section *) psip;
+}
diff --git a/lib/libucsi/atsc/stt_section.h b/lib/libucsi/atsc/stt_section.h
new file mode 100644
index 0000000..79db5a1
--- /dev/null
+++ b/lib/libucsi/atsc/stt_section.h
@@ -0,0 +1,105 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_STT_SECTION_H
+#define _UCSI_ATSC_STT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+#include <libucsi/atsc/types.h>
+
+/**
+ * atsc_stt_section structure.
+ */
+struct atsc_stt_section {
+ struct atsc_section_psip head;
+
+ atsctime_t system_time;
+ uint8_t gps_utc_offset;
+ EBIT4(uint16_t DS_status : 1; ,
+ uint16_t reserved : 2; ,
+ uint16_t DS_day_of_month : 5; ,
+ uint16_t DS_hour : 8; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a atsc_stt_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_stt_section pointer, or NULL on error.
+ */
+struct atsc_stt_section *atsc_stt_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Iterator for the services field in a atsc_stt_section.
+ *
+ * @param stt atsc_stt_section pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_stt_section_descriptors_for_each(stt, pos) \
+ for ((pos) = atsc_stt_section_descriptors_first(stt); \
+ (pos); \
+ (pos) = atsc_stt_section_descriptors_next(stt, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ atsc_stt_section_descriptors_first(struct atsc_stt_section *stt)
+{
+ size_t pos = sizeof(struct atsc_stt_section);
+
+ if (pos >= section_ext_length(&stt->head.ext_head))
+ return NULL;
+
+ return (struct descriptor*) ((uint8_t *) stt + pos);
+}
+
+static inline struct descriptor *
+ atsc_stt_section_descriptors_next(struct atsc_stt_section *stt,
+ struct descriptor *pos)
+{
+ int len = section_ext_length(&stt->head.ext_head);
+ len -= sizeof(struct atsc_stt_section);
+
+ return next_descriptor((uint8_t*) stt + sizeof(struct atsc_stt_section),
+ len,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/stuffing_descriptor.h b/lib/libucsi/atsc/stuffing_descriptor.h
new file mode 100644
index 0000000..777c282
--- /dev/null
+++ b/lib/libucsi/atsc/stuffing_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_atsc@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_STUFFING_DESCRIPTOR
+#define _UCSI_ATSC_STUFFING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * atsc_stuffing_descriptor.
+ */
+struct atsc_stuffing_descriptor {
+ struct descriptor d;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process a atsc_stuffing_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return atsc_stuffing_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_stuffing_descriptor*
+ atsc_stuffing_descriptor_codec(struct descriptor* d)
+{
+ return (struct atsc_stuffing_descriptor*) d;
+}
+
+/**
+ * Retrieve a pointer to the data field of a atsc_stuffing_descriptor.
+ *
+ * @param d atsc_stuffing_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ atsc_stuffing_descriptor_data(struct atsc_stuffing_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct atsc_stuffing_descriptor);
+}
+
+/**
+ * Calculate length of the data field of a atsc_stuffing_descriptor.
+ *
+ * @param d atsc_stuffing_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ atsc_stuffing_descriptor_data_length(struct atsc_stuffing_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/time_shifted_service_descriptor.h b/lib/libucsi/atsc/time_shifted_service_descriptor.h
new file mode 100644
index 0000000..599e66d
--- /dev/null
+++ b/lib/libucsi/atsc/time_shifted_service_descriptor.h
@@ -0,0 +1,136 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR
+#define _UCSI_ATSC_TIME_SHIFTED_SERVICE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * atsc_time_shifted_service_descriptor structure.
+ */
+struct atsc_time_shifted_service_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 3; ,
+ uint8_t number_of_services : 5; );
+ /* struct atsc_time_shifted_service services[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the services field of an atsc_time_shifted_service_descriptor.
+ */
+struct atsc_time_shifted_service {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t time_shift :10; );
+ EBIT3(uint32_t reserved2 : 4; ,
+ uint32_t major_channel_number :10; ,
+ uint32_t minor_channel_number :10; );
+} __ucsi_packed;
+
+/**
+ * Process an atsc_time_shifted_service_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return atsc_time_shifted_service_descriptor pointer, or NULL on error.
+ */
+static inline struct atsc_time_shifted_service_descriptor*
+ atsc_time_shifted_service_descriptor_codec(struct descriptor* d)
+{
+ struct atsc_time_shifted_service_descriptor *ret =
+ (struct atsc_time_shifted_service_descriptor *) d;
+ uint8_t *buf = (uint8_t*) d + 2;
+ int pos = 0;
+ int idx;
+
+ if (d->len < 1)
+ return NULL;
+ pos++;
+
+ for(idx = 0; idx < ret->number_of_services; idx++) {
+ if (d->len < (pos + sizeof(struct atsc_time_shifted_service)))
+ return NULL;
+
+ bswap16(buf+pos);
+ bswap24(buf+pos+2);
+
+ pos += sizeof(struct atsc_time_shifted_service);
+ }
+
+ return (struct atsc_time_shifted_service_descriptor*) d;
+}
+
+/**
+ * Iterator for services field of a atsc_time_shifted_service_descriptor.
+ *
+ * @param d atsc_time_shifted_service_descriptor pointer.
+ * @param pos Variable holding a pointer to the current atsc_service_location_element.
+ * @param idx Integer used to count which service we are in.
+ */
+#define atsc_time_shifted_service_descriptor_services_for_each(d, pos, idx) \
+ for ((pos) = atsc_time_shifted_service_descriptor_services_first(d), idx=0; \
+ (pos); \
+ (pos) = atsc_time_shifted_service_descriptor_services_next(d, pos, ++idx))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_time_shifted_service*
+ atsc_time_shifted_service_descriptor_services_first(struct atsc_time_shifted_service_descriptor *d)
+{
+ if (d->number_of_services == 0)
+ return NULL;
+
+ return (struct atsc_time_shifted_service *)
+ ((uint8_t*) d + sizeof(struct atsc_time_shifted_service_descriptor));
+}
+
+static inline struct atsc_time_shifted_service*
+ atsc_time_shifted_service_descriptor_services_next(struct atsc_time_shifted_service_descriptor *d,
+ struct atsc_time_shifted_service *pos,
+ int idx)
+{
+ uint8_t *next = (uint8_t *) pos + sizeof(struct atsc_time_shifted_service);
+
+ if (idx >= d->number_of_services)
+ return NULL;
+ return (struct atsc_time_shifted_service *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/tvct_section.c b/lib/libucsi/atsc/tvct_section.c
new file mode 100644
index 0000000..d187414
--- /dev/null
+++ b/lib/libucsi/atsc/tvct_section.c
@@ -0,0 +1,81 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/atsc/tvct_section.h>
+
+struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *psip)
+{
+ uint8_t * buf = (uint8_t *) psip;
+ size_t pos = sizeof(struct atsc_section_psip);
+ size_t len = section_ext_length(&(psip->ext_head));
+ int idx;
+ struct atsc_tvct_section *tvct = (struct atsc_tvct_section *) psip;
+
+ if (len < sizeof(struct atsc_tvct_section))
+ return NULL;
+
+ pos++;
+
+ for(idx =0; idx < tvct->num_channels_in_section; idx++) {
+
+ if ((pos + sizeof(struct atsc_tvct_channel)) > len)
+ return NULL;
+ struct atsc_tvct_channel *channel = (struct atsc_tvct_channel *) (buf+pos);
+
+ pos += 7*2;
+
+ bswap32(buf+pos);
+ bswap32(buf+pos+4);
+ bswap16(buf+pos+8);
+ bswap16(buf+pos+10);
+ bswap16(buf+pos+12);
+ bswap16(buf+pos+14);
+ bswap16(buf+pos+16);
+ pos+=18;
+
+ if ((pos + channel->descriptors_length) > len)
+ return NULL;
+ if (verify_descriptors(buf + pos, channel->descriptors_length))
+ return NULL;
+
+ pos += channel->descriptors_length;
+ }
+
+ if ((pos + sizeof(struct atsc_tvct_section_part2)) > len)
+ return NULL;
+ struct atsc_tvct_section_part2 *part2 = (struct atsc_tvct_section_part2 *) (buf+pos);
+
+ bswap16(buf+pos);
+ pos+=2;
+
+ if ((pos + part2->descriptors_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, part2->descriptors_length))
+ return NULL;
+
+ pos += part2->descriptors_length;
+
+ if (pos != len)
+ return NULL;
+
+ return (struct atsc_tvct_section *) psip;
+}
diff --git a/lib/libucsi/atsc/tvct_section.h b/lib/libucsi/atsc/tvct_section.h
new file mode 100644
index 0000000..77bc5f4
--- /dev/null
+++ b/lib/libucsi/atsc/tvct_section.h
@@ -0,0 +1,227 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_TVCT_SECTION_H
+#define _UCSI_ATSC_TVCT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/atsc/section.h>
+
+/**
+ * atsc_tvct_section structure.
+ */
+struct atsc_tvct_section {
+ struct atsc_section_psip head;
+
+ uint8_t num_channels_in_section;
+ /* struct atsc_tvct_channel channels[] */
+ /* struct atsc_tvct_channel_part2 part2 */
+} __ucsi_packed;
+
+struct atsc_tvct_channel {
+ uint16_t short_name[7]; // UTF-16 network ordered
+ EBIT4(uint32_t reserved : 4; ,
+ uint32_t major_channel_number :10; ,
+ uint32_t minor_channel_number :10; ,
+ uint32_t modulation_mode : 8; );
+ uint32_t carrier_frequency;
+ uint16_t channel_TSID;
+ uint16_t program_number;
+ EBIT7(uint16_t ETM_location : 2; ,
+ uint16_t access_controlled : 1; ,
+ uint16_t hidden : 1; ,
+ uint16_t reserved1 : 2; ,
+ uint16_t hide_guide : 1; ,
+ uint16_t reserved2 : 3; ,
+ uint16_t service_type : 6; );
+ uint16_t source_id;
+ EBIT2(uint16_t reserved3 : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct atsc_tvct_section_part2 {
+ EBIT2(uint16_t reserved : 6; ,
+ uint16_t descriptors_length :10; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+static inline struct atsc_tvct_channel *atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct);
+static inline struct atsc_tvct_channel *
+ atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct, struct atsc_tvct_channel *pos, int idx);
+
+/**
+ * Process a atsc_tvct_section.
+ *
+ * @param section Pointer to an atsc_section_psip structure.
+ * @return atsc_tvct_section pointer, or NULL on error.
+ */
+struct atsc_tvct_section *atsc_tvct_section_codec(struct atsc_section_psip *section);
+
+/**
+ * Accessor for the transport_stream_id field of a TVCT.
+ *
+ * @param tvct TVCT pointer.
+ * @return The transport_stream_id.
+ */
+static inline uint16_t atsc_tvct_section_transport_stream_id(struct atsc_tvct_section *tvct)
+{
+ return tvct->head.ext_head.table_id_ext;
+}
+
+/**
+ * Iterator for the channels field in an atsc_tvct_section.
+ *
+ * @param mgt atsc_tvct_section pointer.
+ * @param pos Variable containing a pointer to the current atsc_tvct_channel.
+ * @param idx Integer used to count which channel we in.
+ */
+#define atsc_tvct_section_channels_for_each(mgt, pos, idx) \
+ for ((pos) = atsc_tvct_section_channels_first(mgt), idx=0; \
+ (pos); \
+ (pos) = atsc_tvct_section_channels_next(mgt, pos, ++idx))
+
+/**
+ * Iterator for the descriptors field in a atsc_tvct_channel structure.
+ *
+ * @param channel atsc_tvct_channel pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_tvct_channel_descriptors_for_each(channel, pos) \
+ for ((pos) = atsc_tvct_channel_descriptors_first(channel); \
+ (pos); \
+ (pos) = atsc_tvct_channel_descriptors_next(channel, pos))
+
+/**
+ * Accessor for the second part of an atsc_tvct_section.
+ *
+ * @param mgt atsc_tvct_section pointer.
+ * @return atsc_tvct_section_part2 pointer.
+ */
+static inline struct atsc_tvct_section_part2 *
+ atsc_tvct_section_part2(struct atsc_tvct_section *mgt)
+{
+ int pos = sizeof(struct atsc_tvct_section);
+
+ struct atsc_tvct_channel *cur_channel;
+ int idx;
+ atsc_tvct_section_channels_for_each(mgt, cur_channel, idx) {
+ pos += sizeof(struct atsc_tvct_channel);
+ pos += cur_channel->descriptors_length;
+ }
+
+ return (struct atsc_tvct_section_part2 *) (((uint8_t*) mgt) + pos);
+}
+
+/**
+ * Iterator for the descriptors field in a atsc_tvct_section structure.
+ *
+ * @param part2 atsc_tvct_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define atsc_tvct_section_part2_descriptors_for_each(part2, pos) \
+ for ((pos) = atsc_tvct_section_part2_descriptors_first(part2); \
+ (pos); \
+ (pos) = atsc_tvct_section_part2_descriptors_next(part2, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_tvct_channel *
+ atsc_tvct_section_channels_first(struct atsc_tvct_section *tvct)
+{
+ size_t pos = sizeof(struct atsc_tvct_section);
+
+ if (tvct->num_channels_in_section == 0)
+ return NULL;
+
+ return (struct atsc_tvct_channel*) (((uint8_t *) tvct) + pos);
+}
+
+static inline struct atsc_tvct_channel *
+ atsc_tvct_section_channels_next(struct atsc_tvct_section *tvct,
+ struct atsc_tvct_channel *pos,
+ int idx)
+{
+ if (idx >= tvct->num_channels_in_section)
+ return NULL;
+
+ return (struct atsc_tvct_channel *)
+ (((uint8_t*) pos) + sizeof(struct atsc_tvct_channel) + pos->descriptors_length);
+}
+
+static inline struct descriptor *
+ atsc_tvct_channel_descriptors_first(struct atsc_tvct_channel *channel)
+{
+ size_t pos = sizeof(struct atsc_tvct_channel);
+
+ if (channel->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) channel) + pos);
+}
+
+static inline struct descriptor *
+ atsc_tvct_channel_descriptors_next(struct atsc_tvct_channel *channel,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) channel + sizeof(struct atsc_tvct_channel),
+ channel->descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ atsc_tvct_section_part2_descriptors_first(struct atsc_tvct_section_part2 *part2)
+{
+ size_t pos = sizeof(struct atsc_tvct_section_part2);
+
+ if (part2->descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor*) (((uint8_t *) part2) + pos);
+}
+
+static inline struct descriptor *
+ atsc_tvct_section_part2_descriptors_next(struct atsc_tvct_section_part2 *part2,
+ struct descriptor *pos)
+{
+ return next_descriptor((uint8_t*) part2 + sizeof(struct atsc_tvct_section_part2),
+ part2->descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/atsc/types.c b/lib/libucsi/atsc/types.c
new file mode 100644
index 0000000..8f4b7ea
--- /dev/null
+++ b/lib/libucsi/atsc/types.c
@@ -0,0 +1,71 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <string.h>
+#include "libucsi/atsc/types.h"
+
+/* GPS epoch == unix time_t at 06/Jan/1980 */
+#define GPS_EPOCH 315964800
+
+
+int atsc_text_validate(uint8_t *buf, int len)
+{
+ int i;
+ int j;
+ int number_strings;
+ int number_segments;
+ int number_bytes;
+ int pos = 0;
+
+ if (len == 0)
+ return 0;
+ number_strings = buf[pos];
+ pos++;
+
+ for(i=0; i< number_strings; i++) {
+ if (len < (pos+4))
+ return -1;
+ number_segments = buf[pos+3];
+ pos+=4;
+
+ for(j=0; j < number_segments; j++) {
+ if (len < (pos+3))
+ return -1;
+ number_bytes = buf[pos+2];
+ pos+=3;
+
+ if (len < (pos + number_bytes))
+ return -1;
+ pos += number_bytes;
+ }
+ }
+
+ return 0;
+}
+
+time_t atsctime_to_unixtime(atsctime_t atsc)
+{
+ return atsc + GPS_EPOCH;
+}
+
+atsctime_t unixtime_to_atsctime(time_t t)
+{
+ return t - GPS_EPOCH;
+}
diff --git a/lib/libucsi/atsc/types.h b/lib/libucsi/atsc/types.h
new file mode 100644
index 0000000..4d4b802
--- /dev/null
+++ b/lib/libucsi/atsc/types.h
@@ -0,0 +1,227 @@
+ /*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_ATSC_TYPES_H
+#define _UCSI_ATSC_TYPES_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+#include <time.h>
+#include <libucsi/types.h>
+
+enum atsc_vct_modulation {
+ ATSC_VCT_MODULATION_ANALOG = 0x01,
+ ATSC_VCT_MODULATION_SCTE_MODE1 = 0x02,
+ ATSC_VCT_MODULATION_SCTE_MODE2 = 0x03,
+ ATSC_VCT_MODULATION_8VSB = 0x04,
+ ATSC_VCT_MODULATION_16VSB = 0x05,
+};
+
+enum atsc_vct_service_type {
+ ATSC_VCT_SERVICE_TYPE_ANALOG = 0x01,
+ ATSC_VCT_SERVICE_TYPE_TV = 0x02,
+ ATSC_VCT_SERVICE_TYPE_AUDIO = 0x03,
+ ATSC_VCT_SERVICE_TYPE_DATA = 0x04,
+};
+
+enum atsc_etm_location {
+ ATSC_VCT_ETM_NONE = 0x00,
+ ATSC_VCT_ETM_IN_THIS_PTC = 0x01,
+ ATSC_VCT_ETM_IN_CHANNEL_TSID = 0x02,
+};
+
+enum atsc_text_compress_type {
+ ATSC_TEXT_COMPRESS_NONE = 0x00,
+ ATSC_TEXT_COMPRESS_PROGRAM_TITLE = 0x01,
+ ATSC_TEXT_COMPRESS_PROGRAM_DESCRIPTION = 0x02,
+};
+
+enum atsc_text_segment_mode {
+ ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MIN = 0x00,
+ ATSC_TEXT_SEGMENT_MODE_UNICODE_RANGE_MAX = 0x33,
+ ATSC_TEXT_SEGMENT_MODE_SCSU = 0x3e,
+ ATSC_TEXT_SEGMENT_MODE_UTF16 = 0x3f,
+ ATSC_TEXT_SEGMENT_MODE_TAIWAN_BITMAP = 0x40,
+ ATSC_TEXT_SEGMENT_MODE_TAIWAN_CODEWORD_BITMAP = 0x41,
+};
+
+typedef uint32_t atsctime_t;
+
+struct atsc_text {
+ uint8_t number_strings;
+ /* struct atsc_text_string strings[] */
+};
+
+struct atsc_text_string {
+ iso639lang_t language_code;
+ uint8_t number_segments;
+ /* struct atsc_text_string_segment segments[] */
+};
+
+struct atsc_text_string_segment {
+ uint8_t compression_type;
+ uint8_t mode;
+ uint8_t number_bytes;
+ /* uint8_t bytes[] */
+};
+
+/**
+ * Iterator for strings field of an atsc_text structure.
+ *
+ * @param txt atsc_text pointer.
+ * @param pos Variable holding a pointer to the current atsc_text_string.
+ * @param idx Iterator variable.
+ */
+#define atsc_text_strings_for_each(txt, pos, idx) \
+ for ((pos) = atsc_text_strings_first(txt), idx=0; \
+ (pos); \
+ (pos) = atsc_text_strings_next(txt, pos, ++idx))
+
+/**
+ * Iterator for segments field of an atsc_text_string structure.
+ *
+ * @param str atsc_text_string pointer.
+ * @param pos Variable holding a pointer to the current atsc_text_string_segment.
+ * @param idx Iterator variable.
+ */
+#define atsc_text_string_segments_for_each(str, pos, idx) \
+ for ((pos) = atsc_text_string_segments_first(str), idx=0; \
+ (pos); \
+ (pos) = atsc_text_string_segments_next(str, pos, ++idx))
+
+/**
+ * Accessor for the bytes field of an atsc_text_string_segment.
+ *
+ * @param seg atsc_text_string_segment pointer.
+ * @return Pointer to the bytes.
+ */
+static inline uint8_t*
+ atsc_text_string_segment_bytes(struct atsc_text_string_segment *d)
+{
+ return ((uint8_t*) d) + sizeof(struct atsc_text_string_segment);
+}
+
+/**
+ * Validate a buffer containing an atsc_text structure.
+ *
+ * @param buf Start of the atsc_text structure.
+ * @param len Length in bytes of the buffer.
+ * @return 0 if valid, nonzero if not.
+ */
+extern int atsc_text_validate(uint8_t *buf, int len);
+
+/**
+ * Decodes an atsc_text_segment with mode < 0x3e. Decompression of the ATSC text encoding IS
+ * supported. The output text will be in the UTF-8 encoding.
+ *
+ * @param segment Pointer to the segment to decode.
+ * @param destbuf Pointer to the malloc()ed buffer to append text to (pass NULL if none).
+ * @param destbufsize Size of destbuf in bytes.
+ * @param destbufpos Position within destbuf. This will be updated to point after the end of the
+ * string on exit.
+ * @return New value of destbufpos, or < 0 on error.
+ */
+extern int atsc_text_segment_decode(struct atsc_text_string_segment *segment,
+ uint8_t **destbuf, size_t *destbufsize, size_t *destbufpos);
+
+/**
+ * Convert from ATSC time to unix time_t.
+ *
+ * @param atsc ATSC time.
+ * @return The time value.
+ */
+extern time_t atsctime_to_unixtime(atsctime_t atsc);
+
+/**
+ * Convert from unix time_t to atsc time.
+ *
+ * @param t unix time_t.
+ * @return The atsc time value.
+ */
+extern atsctime_t unixtime_to_atsctime(time_t t);
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct atsc_text_string*
+ atsc_text_strings_first(struct atsc_text *txt)
+{
+ if (txt->number_strings == 0)
+ return NULL;
+
+ return (struct atsc_text_string *)
+ ((uint8_t*) txt + sizeof(struct atsc_text));
+}
+
+static inline struct atsc_text_string*
+ atsc_text_strings_next(struct atsc_text *txt, struct atsc_text_string *pos, int idx)
+{
+ int i;
+ uint8_t *buf;
+
+ if (idx >= txt->number_strings)
+ return NULL;
+
+ buf = ((uint8_t*) pos) + sizeof(struct atsc_text_string);
+ for(i=0; i < pos->number_segments; i++) {
+ struct atsc_text_string_segment *seg =
+ (struct atsc_text_string_segment *) buf;
+
+ buf += sizeof(struct atsc_text_string_segment);
+ buf += seg->number_bytes;
+ }
+
+ return (struct atsc_text_string *) buf;
+}
+
+static inline struct atsc_text_string_segment*
+ atsc_text_string_segments_first(struct atsc_text_string *str)
+{
+ if (str->number_segments == 0)
+ return NULL;
+
+ return (struct atsc_text_string_segment *)
+ ((uint8_t*) str + sizeof(struct atsc_text_string));
+}
+
+static inline struct atsc_text_string_segment*
+ atsc_text_string_segments_next(struct atsc_text_string *str,
+ struct atsc_text_string_segment *pos, int idx)
+{
+ if (idx >= str->number_segments)
+ return NULL;
+
+ return (struct atsc_text_string_segment *)
+ (((uint8_t*) pos) + sizeof(struct atsc_text_string_segment) + pos->number_bytes);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/crc32.c b/lib/libucsi/crc32.c
new file mode 100644
index 0000000..dc1de5c
--- /dev/null
+++ b/lib/libucsi/crc32.c
@@ -0,0 +1,89 @@
+/**
+ * crc32 calculation routines.
+ *
+ * Copyright (c) 2005 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdint.h>
+
+uint32_t crc32tbl[] =
+{
+ 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
+ 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
+ 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
+ 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
+ 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
+ 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
+ 0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
+ 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
+ 0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
+ 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
+ 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
+ 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
+ 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
+ 0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
+ 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
+ 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
+ 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
+ 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
+ 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
+ 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
+ 0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
+ 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
+ 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
+ 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
+ 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
+ 0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
+ 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
+ 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
+ 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
+ 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
+ 0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
+ 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
+ 0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
+ 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
+ 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
+ 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
+ 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
+ 0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
+ 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
+ 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
+ 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
+ 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
+ 0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
+ 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
+ 0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
+ 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
+ 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
+ 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
+ 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
+ 0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
+ 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
+ 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
diff --git a/lib/libucsi/crc32.h b/lib/libucsi/crc32.h
new file mode 100644
index 0000000..7d781ce
--- /dev/null
+++ b/lib/libucsi/crc32.h
@@ -0,0 +1,58 @@
+/**
+ * crc32 calculation routines.
+ *
+ * Copyright (c) 2005 by Andrew de Quincey <adq_dvb@lidskialf.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_CRC32_H
+#define _UCSI_CRC32_H 1
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#define CRC32_INIT (~0)
+
+extern uint32_t crc32tbl[];
+
+/**
+ * Calculate a CRC32 over a piece of data.
+ *
+ * @param crc Current CRC value (use CRC32_INIT for first call).
+ * @param buf Buffer to calculate over.
+ * @param len Number of bytes.
+ * @return Calculated CRC.
+ */
+static inline uint32_t crc32(uint32_t crc, uint8_t* buf, size_t len)
+{
+ size_t i;
+
+ for (i=0; i< len; i++) {
+ crc = (crc << 8) ^ crc32tbl[((crc >> 24) ^ buf[i]) & 0xff];
+ }
+
+ return crc;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/descriptor.h b/lib/libucsi/descriptor.h
new file mode 100644
index 0000000..606e45d
--- /dev/null
+++ b/lib/libucsi/descriptor.h
@@ -0,0 +1,129 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DESCRIPTOR_H
+#define _UCSI_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/endianops.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+/**
+ * Generic descriptor header.
+ */
+struct descriptor {
+ uint8_t tag;
+ uint8_t len;
+} __ucsi_packed;
+
+/**
+ * Retreive pointer to the next descriptor structure.
+ *
+ * @param buf The buffer of descriptors.
+ * @param len Size of the buffer.
+ * @param pos Current descriptor.
+ * @return Pointer to next descriptor, or NULL if there are none.
+ */
+static inline struct descriptor *
+ next_descriptor(uint8_t * buf, size_t len, struct descriptor * pos)
+{
+ uint8_t* next;
+
+ if (pos == NULL)
+ return NULL;
+
+ next = (uint8_t*) pos + 2 + pos->len;
+ if (next >= buf + len)
+ return NULL;
+
+ return (struct descriptor *) next;
+}
+
+
+/**
+ * The unknown descriptor.
+ */
+struct unknown_descriptor {
+ struct descriptor d;
+
+ /* uint8_t data [] */
+} __ucsi_packed;
+
+/**
+ * Retrieve pointer to the unknown descriptor's data field.
+ *
+ * @param d The descriptor.
+ * @return Pointer to the data field.
+ */
+static inline uint8_t *
+ unknown_descriptor_data(struct unknown_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct unknown_descriptor);
+}
+
+/**
+ * Retrieve size of unknown descriptor's data field.
+ *
+ * @param d The descriptor.
+ * @return Size of data field in bytes.
+ */
+static inline int
+ unknown_descriptor_data_size(struct unknown_descriptor *d)
+{
+ return d->d.len;
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline int verify_descriptors(uint8_t * buf, size_t len)
+{
+ size_t pos = 0;
+
+ while (pos < len) {
+ if ((pos + 2) > len)
+ return -1;
+
+ pos += 2 + buf[pos+1];
+ }
+
+ if (pos != len)
+ return -1;
+
+ return 0;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/Makefile b/lib/libucsi/dvb/Makefile
new file mode 100644
index 0000000..78876dc
--- /dev/null
+++ b/lib/libucsi/dvb/Makefile
@@ -0,0 +1,121 @@
+# Makefile for linuxtv.org dvb-apps/lib/libucsi/dvb
+
+.PHONY: sub-error-dvb
+
+sub-error-dvb:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += dvb/bat_section.o \
+ dvb/dit_section.o \
+ dvb/eit_section.o \
+ dvb/int_section.o \
+ dvb/nit_section.o \
+ dvb/rst_section.o \
+ dvb/sdt_section.o \
+ dvb/sit_section.o \
+ dvb/st_section.o \
+ dvb/tdt_section.o \
+ dvb/tot_section.o \
+ dvb/tva_container_section.o \
+ dvb/types.o
+
+sub-install += dvb
+
+else
+
+includes = ac3_descriptor.h \
+ adaptation_field_data_descriptor.h \
+ ait_application_descriptor.h \
+ ait_application_icons_descriptor.h \
+ ait_application_name_descriptor.h \
+ ait_external_application_authorisation_descriptor.h \
+ ancillary_data_descriptor.h \
+ announcement_support_descriptor.h \
+ application_signalling_descriptor.h \
+ bat_section.h \
+ bouquet_name_descriptor.h \
+ ca_identifier_descriptor.h \
+ cable_delivery_descriptor.h \
+ cell_frequency_link_descriptor.h \
+ cell_list_descriptor.h \
+ component_descriptor.h \
+ content_descriptor.h \
+ content_identifier_descriptor.h \
+ country_availability_descriptor.h \
+ data_broadcast_descriptor.h \
+ data_broadcast_id_descriptor.h \
+ default_authority_descriptor.h \
+ descriptor.h \
+ dit_section.h \
+ dsng_descriptor.h \
+ eit_section.h \
+ extended_event_descriptor.h \
+ frequency_list_descriptor.h \
+ int_section.h \
+ ip_mac_platform_name_descriptor.h \
+ ip_mac_platform_provider_name_descriptor.h \
+ ip_mac_stream_location_descriptor.h \
+ linkage_descriptor.h \
+ local_time_offset_descriptor.h \
+ mhp_data_broadcast_id_descriptor.h \
+ mosaic_descriptor.h \
+ multilingual_bouquet_name_descriptor.h \
+ multilingual_component_descriptor.h \
+ multilingual_network_name_descriptor.h \
+ multilingual_service_name_descriptor.h \
+ network_name_descriptor.h \
+ nit_section.h \
+ nvod_reference_descriptor.h \
+ parental_rating_descriptor.h \
+ partial_transport_stream_descriptor.h \
+ pdc_descriptor.h \
+ private_data_specifier_descriptor.h \
+ related_content_descriptor.h \
+ rnt_rar_over_dvb_stream_descriptor.h \
+ rnt_rar_over_ip_descriptor.h \
+ rnt_rnt_scan_descriptor.h \
+ rst_section.h \
+ s2_satellite_delivery_descriptor.h \
+ satellite_delivery_descriptor.h \
+ scrambling_descriptor.h \
+ sdt_section.h \
+ section.h \
+ service_availability_descriptor.h \
+ service_descriptor.h \
+ service_identifier_descriptor.h \
+ service_list_descriptor.h \
+ service_move_descriptor.h \
+ short_event_descriptor.h \
+ short_smoothing_buffer_descriptor.h \
+ sit_section.h \
+ st_section.h \
+ stream_identifier_descriptor.h \
+ stuffing_descriptor.h \
+ subtitling_descriptor.h \
+ target_ip_address_descriptor.h \
+ target_ipv6_address_descriptor.h \
+ target_ip_slash_descriptor.h \
+ target_ip_source_slash_descriptor.h \
+ target_ipv6_slash_descriptor.h \
+ target_ipv6_source_slash_descriptor.h \
+ tdt_section.h \
+ telephone_descriptor.h \
+ teletext_descriptor.h \
+ terrestrial_delivery_descriptor.h \
+ time_shifted_event_descriptor.h \
+ time_shifted_service_descriptor.h \
+ tot_section.h \
+ transport_stream_descriptor.h \
+ tva_container_section.h \
+ tva_id_descriptor.h \
+ types.h \
+ vbi_data_descriptor.h \
+ vbi_teletext_descriptor.h
+
+include ../../../Make.rules
+
+lib_name = libucsi/dvb
+
+endif
diff --git a/lib/libucsi/dvb/ac3_descriptor.h b/lib/libucsi/dvb/ac3_descriptor.h
new file mode 100644
index 0000000..0a2a5cd
--- /dev/null
+++ b/lib/libucsi/dvb/ac3_descriptor.h
@@ -0,0 +1,88 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_AC3_DESCRIPTOR
+#define _UCSI_DVB_AC3_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_ac3_descriptor structure.
+ */
+struct dvb_ac3_descriptor {
+ struct descriptor d;
+
+ EBIT5(uint8_t ac3_type_flag : 1; ,
+ uint8_t bsid_flag : 1; ,
+ uint8_t mainid_flag : 1; ,
+ uint8_t asvc_flag : 1; ,
+ uint8_t reserved : 4; );
+ /* uint8_t additional_info[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ac3_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_ac3_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ac3_descriptor*
+ dvb_ac3_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_ac3_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_ac3_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to additional_info field of a dvb_ac3_descriptor.
+ *
+ * @param d dvb_ac3_descriptor pointer.
+ * @return Pointer to additional_info field.
+ */
+static inline uint8_t *dvb_ac3_descriptor_additional_info(struct dvb_ac3_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_ac3_descriptor);
+}
+
+/**
+ * Determine length of additional_info field of a dvb_ac3_descriptor.
+ *
+ * @param d dvb_ac3_descriptor pointer.
+ * @return Length of field in bytes.
+ */
+static inline int dvb_ac3_descriptor_additional_info_length(struct dvb_ac3_descriptor *d)
+{
+ return d->d.len - 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/adaptation_field_data_descriptor.h b/lib/libucsi/dvb/adaptation_field_data_descriptor.h
new file mode 100644
index 0000000..b207054
--- /dev/null
+++ b/lib/libucsi/dvb/adaptation_field_data_descriptor.h
@@ -0,0 +1,62 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_ADAPTATION_FIELD_DATA_DESCRIPTOR
+#define _UCSI_DVB_ADAPTATION_FIELD_DATA_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_adaptation_field_data_descriptor structure.
+ */
+struct dvb_adaptation_field_data_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 7; ,
+ uint8_t announcement_switching_data : 1; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_adaptation_field_data_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to dvb_adaptation_field_data_descriptor, or NULL on error.
+ */
+static inline struct dvb_adaptation_field_data_descriptor*
+ dvb_adaptation_field_data_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_adaptation_field_data_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_adaptation_field_data_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ait_application_descriptor.h b/lib/libucsi/dvb/ait_application_descriptor.h
new file mode 100644
index 0000000..95fb7e3
--- /dev/null
+++ b/lib/libucsi/dvb/ait_application_descriptor.h
@@ -0,0 +1,204 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_AIT_APPLICATION_DESCRIPTOR
+#define _UCSI_DVB_AIT_APPLICATION_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for the visibility field.
+ */
+enum {
+ AVB_AIT_APPLICATION_VISIBILITY_HIDDEN = 0x00,
+ AVB_AIT_APPLICATION_VISIBILITY_APPSONLY = 0x01,
+ AVB_AIT_APPLICATION_VISIBILITY_VISIBLE = 0x03,
+};
+
+/**
+ * dvb_ait_application_descriptor structure.
+ */
+struct dvb_ait_application_descriptor {
+ struct descriptor d;
+
+ uint8_t application_profiles_length;
+ /* struct dvb_ait_application_profile profiles [] */
+ /* struct dvb_ait_application_descriptor_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * An entry in the profiles field of a dvb_ait_application_descriptor.
+ */
+struct dvb_ait_application_profile {
+ uint16_t application_profile;
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint8_t version_micro;
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_ait_application_descriptor structure.
+ */
+struct dvb_ait_application_descriptor_part2 {
+ EBIT3(uint8_t service_bound_flag : 1; ,
+ uint8_t visibility : 2; ,
+ uint8_t reserved : 5; );
+ uint8_t application_priority;
+ /* uint8_t transport_protocol_label[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ait_application_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ait_application_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ait_application_descriptor*
+ dvb_ait_application_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t pos2 = 0;
+ uint32_t len = d->len + 2;
+ uint8_t* buf = (uint8_t*) d;
+ struct dvb_ait_application_descriptor *ret =
+ (struct dvb_ait_application_descriptor*) d;
+
+ if (len < sizeof(struct dvb_ait_application_descriptor))
+ return NULL;
+
+ if (len < (sizeof(struct dvb_ait_application_descriptor) + ret->application_profiles_length))
+ return NULL;
+
+ if (ret->application_profiles_length % sizeof(struct dvb_ait_application_profile))
+ return NULL;
+
+ pos += sizeof(struct dvb_ait_application_descriptor);
+ pos2 = 0;
+ while(pos2 < ret->application_profiles_length) {
+ bswap16(buf + pos + pos2);
+ pos2 += sizeof(struct dvb_ait_application_descriptor);
+ }
+ pos += pos2;
+
+ if (len < (pos + sizeof(struct dvb_ait_application_descriptor_part2)))
+ return NULL;
+
+ return ret;
+}
+
+/**
+ * Iterator for the profiles field of a dvb_ait_application_descriptor.
+ *
+ * @param d dvb_ait_application_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ait_application_profile.
+ */
+#define dvb_ait_application_descriptor_profiles_for_each(d, pos) \
+ for ((pos) = dvb_ait_application_descriptor_profiles_first(d); \
+ (pos); \
+ (pos) = dvb_ait_application_descriptor_profiles_next(d, pos))
+
+/**
+ * Accessor for the part2 field of a dvb_ait_application_descriptor.
+ *
+ * @param d dvb_ait_application_descriptor pointer.
+ * @return dvb_ait_application_descriptor_part2 pointer.
+ */
+static inline struct dvb_ait_application_descriptor_part2*
+ dvb_ait_application_descriptor_part2(struct dvb_ait_application_descriptor* d)
+{
+ return (struct dvb_ait_application_descriptor_part2*)
+ ((uint8_t*) d +
+ sizeof(struct dvb_ait_application_descriptor) +
+ d->application_profiles_length);
+}
+
+/**
+ * Accessor for the transport_protocol_label field of a dvb_ait_application_descriptor_part2.
+ *
+ * @param d dvb_ait_application_descriptor_part2 pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_ait_application_descriptor_part2_transport_protocol_label(struct dvb_ait_application_descriptor_part2* d)
+{
+ return (uint8_t*) d +
+ sizeof(struct dvb_ait_application_descriptor_part2);
+}
+
+/**
+ * Calculate the number of bytes in the transport_protocol_label field of a dvb_ait_application_descriptor_part2.
+ *
+ * @param d dvb_ait_application_descriptor pointer.
+ * @param part2 dvb_ait_application_descriptor_part2 pointer.
+ * @return Number of bytes.
+ */
+static inline int
+ dvb_ait_application_descriptor_part2_transport_protocol_label_length(struct dvb_ait_application_descriptor *d,
+ struct dvb_ait_application_descriptor_part2* part2)
+{
+ uint8_t *ptr = (uint8_t*) part2 + sizeof(struct dvb_ait_application_descriptor_part2);
+ uint8_t *end = (uint8_t*) d + d->d.len + 2;
+
+ return (int) (end - ptr);
+}
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ait_application_profile*
+ dvb_ait_application_descriptor_profiles_first(struct dvb_ait_application_descriptor *d)
+{
+ if (d->application_profiles_length == 0)
+ return NULL;
+
+ return (struct dvb_ait_application_profile *)
+ ((uint8_t*) d + sizeof(struct dvb_ait_application_descriptor));
+}
+
+static inline struct dvb_ait_application_profile*
+ dvb_ait_application_descriptor_profiles_next(struct dvb_ait_application_descriptor *d,
+ struct dvb_ait_application_profile *pos)
+{
+ uint8_t *end = (uint8_t*) d +
+ sizeof(struct dvb_ait_application_descriptor) +
+ d->application_profiles_length;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ait_application_profile);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ait_application_profile *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ait_application_icons_descriptor.h b/lib/libucsi/dvb/ait_application_icons_descriptor.h
new file mode 100644
index 0000000..431cd6c
--- /dev/null
+++ b/lib/libucsi/dvb/ait_application_icons_descriptor.h
@@ -0,0 +1,157 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_AIT_APPLICATION_ICONS_DESCRIPTOR
+#define _UCSI_DVB_AIT_APPLICATION_ICONS_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Possible values for the icon_flags field.
+ */
+enum {
+ AIT_APPLICATION_ICON_FLAG_32_32 = 0x001,
+ AIT_APPLICATION_ICON_FLAG_32_32_43 = 0x002,
+ AIT_APPLICATION_ICON_FLAG_24_32_169 = 0x004,
+
+ AIT_APPLICATION_ICON_FLAG_64_64 = 0x008,
+ AIT_APPLICATION_ICON_FLAG_64_64_43 = 0x010,
+ AIT_APPLICATION_ICON_FLAG_48_64_169 = 0x020,
+
+ AIT_APPLICATION_ICON_FLAG_128_128 = 0x040,
+ AIT_APPLICATION_ICON_FLAG_128_128_43 = 0x080,
+ AIT_APPLICATION_ICON_FLAG_96_128_169 = 0x100,
+};
+
+/**
+ * dvb_ait_application_icons_descriptor structure.
+ */
+struct dvb_ait_application_icons_descriptor {
+ struct descriptor d;
+
+ uint8_t icon_locator_length;
+ /* uint8_t icon_locator[] */
+ /* struct dvb_ait_application_icons_descriptor_part2 */
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_ait_application_icons_descriptor.
+ */
+struct dvb_ait_application_icons_descriptor_part2 {
+ uint16_t icon_flags;
+ /* uint8_t reserved[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ait_application_icons_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ait_application_icons_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ait_application_icons_descriptor*
+ dvb_ait_application_icons_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d;
+ uint32_t pos = 0;
+ uint32_t len = d->len + 2;
+ struct dvb_ait_application_icons_descriptor *ret =
+ (struct dvb_ait_application_icons_descriptor *) d;
+
+ if (len < sizeof(struct dvb_ait_application_icons_descriptor))
+ return NULL;
+ if (len < (sizeof(struct dvb_ait_application_icons_descriptor) + ret->icon_locator_length))
+ return NULL;
+
+ pos += sizeof(struct dvb_ait_application_icons_descriptor) + ret->icon_locator_length;
+
+ if ((len - pos) < sizeof(struct dvb_ait_application_icons_descriptor_part2))
+ return NULL;
+ bswap16(buf + pos);
+
+ return ret;
+}
+/**
+ * Accessor for the icon_locator field of a dvb_ait_application_icons_descriptor.
+ *
+ * @param e dvb_ait_application_icons_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_ait_application_icons_descriptor_icon_locator(struct dvb_ait_application_icons_descriptor *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor);
+}
+
+/**
+ * Accessor for the part2 field of a dvb_ait_application_icons_descriptor.
+ *
+ * @param e dvb_ait_application_icons_descriptor Pointer.
+ * @return dvb_ait_application_icons_descriptor_part2 pointer.
+ */
+static inline struct dvb_ait_application_icons_descriptor_part2 *
+ dvb_ait_application_icons_descriptor_part2(struct dvb_ait_application_icons_descriptor *e)
+{
+ return (struct dvb_ait_application_icons_descriptor_part2 *)
+ ((uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor) +
+ e->icon_locator_length);
+}
+
+/**
+ * Accessor for the reserved field of a dvb_ait_application_icons_descriptor_part2.
+ *
+ * @param e dvb_ait_application_icons_part2 pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_ait_application_icons_descriptor_part2_reserved(struct dvb_ait_application_icons_descriptor_part2 *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_ait_application_icons_descriptor_part2);
+}
+
+/**
+ * Calculate the number of bytes in the reserved field of a dvb_ait_application_icons_descriptor_part2.
+ *
+ * @param d dvb_ait_application_icons_descriptorpointer.
+ * @param part2 dvb_ait_application_icons_descriptor_part2 pointer.
+ * @return Number of bytes.
+ */
+static inline int
+ dvb_ait_application_icons_descriptor_part2_reserved_length(struct dvb_ait_application_icons_descriptor *d,
+ struct dvb_ait_application_icons_descriptor_part2* part2)
+{
+ uint8_t *ptr = (uint8_t*) part2 + sizeof(struct dvb_ait_application_icons_descriptor_part2);
+ uint8_t *end = (uint8_t*) d + d->d.len + 2;
+
+ return (int) (end - ptr);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ait_application_name_descriptor.h b/lib/libucsi/dvb/ait_application_name_descriptor.h
new file mode 100644
index 0000000..a4b719e
--- /dev/null
+++ b/lib/libucsi/dvb/ait_application_name_descriptor.h
@@ -0,0 +1,145 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_AIT_APPLICATION_NAME_DESCRIPTOR
+#define _UCSI_DVB_AIT_APPLICATION_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_ait_application_name_descriptor structure.
+ */
+struct dvb_ait_application_name_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ait_application_name names[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the names field of a dvb_ait_application_name_descriptor.
+ */
+struct dvb_ait_application_name {
+ iso639lang_t language_code;
+ uint8_t application_name_length;
+ /* uint8_t name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ait_application_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ait_application_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ait_application_name_descriptor*
+ dvb_ait_application_name_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_ait_application_name *e =
+ (struct dvb_ait_application_name*) (buf + pos);
+
+ pos += sizeof(struct dvb_ait_application_name);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->application_name_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_ait_application_name_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the names field of a dvb_ait_application_name_descriptor.
+ *
+ * @param d dvb_ait_application_name_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ait_application_name.
+ */
+#define dvb_ait_application_name_descriptor_names_for_each(d, pos) \
+ for ((pos) = dvb_ait_application_name_descriptor_names_first(d); \
+ (pos); \
+ (pos) = dvb_ait_application_name_descriptor_names_next(d, pos))
+
+/**
+ * Accessor for the name field of a dvb_ait_application_name.
+ *
+ * @param e dvb_ait_application_name pointer.
+ * @return Pointer to the name field.
+ */
+static inline uint8_t *
+ dvb_ait_application_name_name(struct dvb_ait_application_name *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_ait_application_name);
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ait_application_name*
+ dvb_ait_application_name_descriptor_names_first(struct dvb_ait_application_name_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ait_application_name *)
+ ((uint8_t*) d + sizeof(struct dvb_ait_application_name_descriptor));
+}
+
+static inline struct dvb_ait_application_name*
+ dvb_ait_application_name_descriptor_names_next(struct dvb_ait_application_name_descriptor *d,
+ struct dvb_ait_application_name *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_ait_application_name) +
+ pos->application_name_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ait_application_name *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h b/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h
new file mode 100644
index 0000000..34f584a
--- /dev/null
+++ b/lib/libucsi/dvb/ait_external_application_authorisation_descriptor.h
@@ -0,0 +1,125 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_AIT_EXTERNAL_APPLICATION_AUTHORISATION_DESCRIPTOR
+#define _UCSI_DVB_AIT_EXTERNAL_APPLICATION_AUTHORISATION_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_ait_external_application_authorisation_descriptor structure.
+ */
+struct dvb_ait_external_application_authorisation_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ait_external_application_authorisation auths[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the auths field of a dvb_ait_external_application_authorisation_descriptor.
+ */
+struct dvb_ait_external_application_authorisation {
+ uint32_t organization_id;
+ uint16_t application_id;
+ uint8_t application_priority;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ait_external_application_authorisation_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ait_external_application_authorisation_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ait_external_application_authorisation_descriptor*
+ dvb_ait_external_application_authorisation_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_ait_external_application_authorisation))
+ return NULL;
+
+ while(pos < len) {
+ bswap32(buf + pos);
+ bswap32(buf + pos + 4);
+ pos += sizeof(struct dvb_ait_external_application_authorisation);
+ }
+
+ return (struct dvb_ait_external_application_authorisation_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the auths field of a dvb_ait_external_application_authorisation_descriptor.
+ *
+ * @param d dvb_ait_external_application_authorisation_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ait_external_application_authorisation.
+ */
+#define dvb_ait_external_application_authorisation_descriptor_auths_for_each(d, pos) \
+ for ((pos) = dvb_ait_external_application_authorisation_descriptor_auths_first(d); \
+ (pos); \
+ (pos) = dvb_ait_external_application_authorisation_descriptor_auths_next(d, pos))
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ait_external_application_authorisation*
+ dvb_ait_external_application_authorisation_descriptor_auths_first(struct dvb_ait_external_application_authorisation_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ait_external_application_authorisation *)
+ ((uint8_t*) d + sizeof(struct dvb_ait_external_application_authorisation_descriptor));
+}
+
+static inline struct dvb_ait_external_application_authorisation*
+ dvb_ait_external_application_authorisation_descriptor_auths_next(struct dvb_ait_external_application_authorisation_descriptor *d,
+ struct dvb_ait_external_application_authorisation *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_ait_external_application_authorisation);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ait_external_application_authorisation *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ancillary_data_descriptor.h b/lib/libucsi/dvb/ancillary_data_descriptor.h
new file mode 100644
index 0000000..04b2f59
--- /dev/null
+++ b/lib/libucsi/dvb/ancillary_data_descriptor.h
@@ -0,0 +1,67 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_ANCILLARY_DATA_DESCRIPTOR
+#define _UCSI_DVB_ANCILLARY_DATA_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_ancillary_data_descriptor structure.
+ */
+struct dvb_ancillary_data_descriptor {
+ struct descriptor d;
+ EBIT8(uint8_t reserved : 1; ,
+ uint8_t rds_via_udcp : 1; ,
+ uint8_t mpeg4_ancillary_data : 1; ,
+ uint8_t scale_factor_error_check : 1; ,
+ uint8_t dab_ancillary_data : 1; ,
+ uint8_t announcement_switching_data : 1; ,
+ uint8_t extended_ancillary_data : 1; ,
+ uint8_t dvd_video_ancillary_data : 1; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ancillary_data_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ancillary_data_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ancillary_data_descriptor*
+ dvb_ancillary_data_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_ancillary_data_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_ancillary_data_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/announcement_support_descriptor.h b/lib/libucsi/dvb/announcement_support_descriptor.h
new file mode 100644
index 0000000..9eb20c4
--- /dev/null
+++ b/lib/libucsi/dvb/announcement_support_descriptor.h
@@ -0,0 +1,219 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_ANNOUNCEMENT_SUPPORT_DESCRIPTOR
+#define _UCSI_DVB_ANNOUNCEMENT_SUPPORT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for announcement_support_indicator.
+ */
+enum {
+ DVB_ANNOUNCEMENT_SUPPORT_EMERGENCY = 0x01,
+ DVB_ANNOUNCEMENT_SUPPORT_ROAD_TRAFFIC_FLASH = 0x02,
+ DVB_ANNOUNCEMENT_SUPPORT_PUBLIC_TRANSPORT_FLASH = 0x04,
+ DVB_ANNOUNCEMENT_SUPPORT_WARNING_MESSAGE = 0x08,
+ DVB_ANNOUNCEMENT_SUPPORT_NEWS_FLASH = 0x10,
+ DVB_ANNOUNCEMENT_SUPPORT_WEATHER_FLASH = 0x20,
+ DVB_ANNOUNCEMENT_SUPPORT_EVENT_ANNOUNCEMENT = 0x40,
+ DVB_ANNOUNCEMENT_SUPPORT_PERSONAL_CALL = 0x80,
+};
+
+/**
+ * Possible values for announcement_type.
+ */
+enum {
+ DVB_ANNOUNCEMENT_TYPE_EMERGENCY = 0x00,
+ DVB_ANNOUNCEMENT_TYPE_ROAD_TRAFFIC_FLASH = 0x01,
+ DVB_ANNOUNCEMENT_TYPE_PUBLIC_TRANSPORT_FLASH = 0x02,
+ DVB_ANNOUNCEMENT_TYPE_WARNING_MESSAGE = 0x03,
+ DVB_ANNOUNCEMENT_TYPE_NEWS_FLASH = 0x04,
+ DVB_ANNOUNCEMENT_TYPE_WEATHER_FLASH = 0x05,
+ DVB_ANNOUNCEMENT_TYPE_EVENT_ANNOUNCEMENT = 0x06,
+ DVB_ANNOUNCEMENT_TYPE_PERSONAL_CALL = 0x07,
+};
+
+/**
+ * Possible values for reference_type.
+ */
+enum {
+ DVB_REFERENCE_TYPE_AUDIO = 0x00,
+ DVB_REFERENCE_TYPE_OTHER_AUDIO = 0x01,
+ DVB_REFERENCE_TYPE_OTHER_SERVICE = 0x02,
+ DVB_REFERENCE_TYPE_OTHER_TS = 0x03,
+};
+
+/**
+ * dvb_announcement_support_descriptor structure.
+ */
+struct dvb_announcement_support_descriptor {
+ struct descriptor d;
+ uint16_t announcement_support_indicator;
+ /* struct dvb_announcement_support_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_announcement_support_descriptor.
+ */
+struct dvb_announcement_support_entry {
+ EBIT3(uint8_t announcement_type : 4; ,
+ uint8_t reserved : 1; ,
+ uint8_t reference_type : 3; );
+ /* Only if reference_type == 1, 2 or 3:
+ * struct dvb_announcement_support_reference reference */
+} __ucsi_packed;
+
+/**
+ * The optional reference field only present in a dvb_announcement_support_descriptor if
+ * its reference_type field is 1,2 or 3.
+ */
+struct dvb_announcement_support_reference {
+ uint16_t original_network_id;
+ uint16_t transport_stream_id;
+ uint16_t service_id;
+ uint8_t component_tag;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_announcement_support_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_announcement_support_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_announcement_support_descriptor*
+ dvb_announcement_support_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ if (len < (sizeof(struct dvb_announcement_support_descriptor) - 2))
+ return NULL;
+
+ bswap16(buf+pos);
+
+ pos += 2;
+
+ while(pos < len) {
+ struct dvb_announcement_support_entry *e =
+ (struct dvb_announcement_support_entry*) (buf+pos);
+
+ pos += sizeof(struct dvb_announcement_support_entry);
+
+ if (pos > len)
+ return NULL;
+
+ if ((e->reference_type == 1) ||
+ (e->reference_type == 2) ||
+ (e->reference_type == 3)) {
+ if ((pos + sizeof(struct dvb_announcement_support_reference)) > len)
+ return NULL;
+
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+
+ pos += sizeof(struct dvb_announcement_support_reference);
+ }
+ }
+
+ return (struct dvb_announcement_support_descriptor*) d;
+}
+
+/**
+ * Iterator for the entries field of a dvb_announcement_support_descriptor.
+ *
+ * @param d dvb_announcement_support_descriptor pointer.
+ * @param pod Variable holding a pointer to the current dvb_announcement_support_entry.
+ */
+#define dvb_announcement_support_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_announcement_support_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_announcement_support_descriptor_entries_next(d, pos))
+
+/**
+ * Accessor for the reference field of a dvb_announcement_support_entry if present.
+ *
+ * @param entry dvb_announcement_support_entry pointer.
+ * @return dvb_announcement_support_reference pointer, or NULL on error.
+ */
+static inline struct dvb_announcement_support_reference*
+ dvb_announcement_support_entry_reference(struct dvb_announcement_support_entry* entry)
+{
+ if ((entry->reference_type != 0x01) &&
+ (entry->reference_type != 0x02) &&
+ (entry->reference_type != 0x03))
+ return NULL;
+
+ return (struct dvb_announcement_support_reference*)
+ ((uint8_t*) entry + sizeof(struct dvb_announcement_support_entry));
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_announcement_support_entry*
+ dvb_announcement_support_descriptor_entries_first(struct dvb_announcement_support_descriptor *d)
+{
+ if (d->d.len == 2)
+ return NULL;
+
+ return (struct dvb_announcement_support_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_announcement_support_descriptor));
+}
+
+static inline struct dvb_announcement_support_entry*
+ dvb_announcement_support_descriptor_entries_next(struct dvb_announcement_support_descriptor *d,
+ struct dvb_announcement_support_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t* next = (uint8_t*) pos + sizeof(struct dvb_announcement_support_entry);
+ struct dvb_announcement_support_reference* reference =
+ dvb_announcement_support_entry_reference(pos);
+
+ if (reference)
+ next += sizeof(struct dvb_announcement_support_reference);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_announcement_support_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/application_signalling_descriptor.h b/lib/libucsi/dvb/application_signalling_descriptor.h
new file mode 100644
index 0000000..78211cf
--- /dev/null
+++ b/lib/libucsi/dvb/application_signalling_descriptor.h
@@ -0,0 +1,124 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_APPLICATION_SIGNALLING_DESCRIPTOR
+#define _UCSI_DVB_APPLICATION_SIGNALLING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_application_signalling_descriptor structure.
+ */
+struct dvb_application_signalling_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_application_signalling_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_application_signalling_descriptor.
+ */
+struct dvb_application_signalling_entry {
+ uint16_t application_type;
+ EBIT2(uint8_t reserved : 3; ,
+ uint8_t AIT_version_number : 5; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_application_signalling_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_application_signalling_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_application_signalling_descriptor*
+ dvb_application_signalling_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+ uint8_t* buf = (uint8_t*) d + 2;
+
+ pos += sizeof(struct dvb_application_signalling_descriptor) - 2;
+ if (len % sizeof(struct dvb_application_signalling_entry))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos+=3;
+ }
+
+ return (struct dvb_application_signalling_descriptor*) d;
+}
+
+/**
+ * Iterator for the entries field of a dvb_application_signalling_descriptor.
+ *
+ * @param d dvb_application_signalling_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_application_signalling_entry.
+ */
+#define dvb_application_signalling_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_application_signalling_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_application_signalling_descriptor_entries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_application_signalling_entry*
+ dvb_application_signalling_descriptor_entries_first(struct dvb_application_signalling_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_application_signalling_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_application_signalling_descriptor));
+}
+
+static inline struct dvb_application_signalling_entry*
+ dvb_application_signalling_descriptor_entries_next(struct dvb_application_signalling_descriptor *d,
+ struct dvb_application_signalling_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_application_signalling_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_application_signalling_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/bat_section.c b/lib/libucsi/dvb/bat_section.c
new file mode 100644
index 0000000..99e5cf6
--- /dev/null
+++ b/lib/libucsi/dvb/bat_section.c
@@ -0,0 +1,77 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/bat_section.h>
+
+struct dvb_bat_section * dvb_bat_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+ struct dvb_bat_section * ret = (struct dvb_bat_section *) ext;
+
+ if (len < sizeof(struct dvb_bat_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+
+ if ((pos + ret->bouquet_descriptors_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, ret->bouquet_descriptors_length))
+ return NULL;
+ pos += ret->bouquet_descriptors_length;
+
+ if ((pos + sizeof(struct dvb_bat_section_part2)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += sizeof(struct dvb_bat_section_part2);
+
+ while (pos < len) {
+ struct dvb_bat_transport * transport =
+ (struct dvb_bat_transport *) (buf + pos);
+
+ if ((pos + sizeof(struct dvb_bat_transport)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 2);
+ bswap16(buf + pos + 4);
+
+ pos += sizeof(struct dvb_bat_transport);
+
+ if ((pos + transport->transport_descriptors_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos,
+ transport->transport_descriptors_length))
+ return NULL;
+
+ pos += transport->transport_descriptors_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/bat_section.h b/lib/libucsi/dvb/bat_section.h
new file mode 100644
index 0000000..94ed8a4
--- /dev/null
+++ b/lib/libucsi/dvb/bat_section.h
@@ -0,0 +1,211 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_BAT_SECTION_H
+#define _UCSI_DVB_BAT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_bat_section structure.
+ */
+struct dvb_bat_section {
+ struct section_ext head;
+
+ EBIT2(uint16_t reserved_1 : 4; ,
+ uint16_t bouquet_descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+ /* struct dvb_bat_section_part2 part2 */
+};
+
+/**
+ * Second part of a dvb_bat_section, following the variable length descriptors field.
+ */
+struct dvb_bat_section_part2 {
+ EBIT2(uint16_t reserved_2 : 4; ,
+ uint16_t transport_stream_loop_length :12; );
+ /* struct dvb_bat_transport transports[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the transports field of a dvb_bat_section_part2.
+ */
+struct dvb_bat_transport {
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t transport_descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+};
+
+/**
+ * Process a dvb_bat_section.
+ *
+ * @param section Generic section pointer.
+ * @return dvb_bat_section pointer, or NULL on error.
+ */
+struct dvb_bat_section *dvb_bat_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the bouquet_id field of a BAT.
+ *
+ * @param bat BAT pointer.
+ * @return The bouquet_id.
+ */
+static inline uint16_t dvb_bat_section_bouquet_id(struct dvb_bat_section *bat)
+{
+ return bat->head.table_id_ext;
+}
+
+/**
+ * Iterator for the descriptors field in a dvb_bat_section.
+ *
+ * @param bat dvb_bat_section pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define dvb_bat_section_descriptors_for_each(bat, pos) \
+ for ((pos) = dvb_bat_section_descriptors_first(bat); \
+ (pos); \
+ (pos) = dvb_bat_section_descriptors_next(bat, pos))
+
+/**
+ * Accessor for the second part of a dvb_bat_section.
+ *
+ * @param bat dvb_bat_section pointer.
+ * @return dvb_bat_section_part2 pointer.
+ */
+static inline struct dvb_bat_section_part2 *
+ dvb_bat_section_part2(struct dvb_bat_section *bat)
+{
+ return (struct dvb_bat_section_part2 *)
+ ((uint8_t*) bat +
+ sizeof(struct dvb_bat_section) +
+ bat->bouquet_descriptors_length);
+
+}
+
+/**
+ * Iterator for the transports field of a dvb_bat_section_part2.
+ *
+ * @param part2 dvb_bat_section_part2 pointer.
+ * @param pos Variable containing a pointer to the current dvb_bat_transport.
+ */
+#define dvb_bat_section_transports_for_each(part2, pos) \
+ for ((pos) = dvb_bat_section_transports_first(part2); \
+ (pos); \
+ (pos) = dvb_bat_section_transports_next(part2, pos))
+
+/**
+ * Iterator for the descriptors field of a dvb_bat_transport.
+ *
+ * @param transport dvb_bat_transport pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define dvb_bat_transport_descriptors_for_each(transport, pos) \
+ for ((pos) = dvb_bat_transport_descriptors_first(transport); \
+ (pos); \
+ (pos) = dvb_bat_transport_descriptors_next(transport, pos))
+
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ dvb_bat_section_descriptors_first(struct dvb_bat_section *bat)
+{
+ if (bat->bouquet_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) bat + sizeof(struct dvb_bat_section));
+}
+
+static inline struct descriptor *
+ dvb_bat_section_descriptors_next(struct dvb_bat_section *bat,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) bat + sizeof(struct dvb_bat_section),
+ bat->bouquet_descriptors_length,
+ pos);
+}
+
+static inline struct dvb_bat_transport *
+ dvb_bat_section_transports_first(struct dvb_bat_section_part2 *part2)
+{
+ if (part2->transport_stream_loop_length == 0)
+ return NULL;
+
+ return (struct dvb_bat_transport *)
+ ((uint8_t *) part2 + sizeof(struct dvb_bat_section_part2));
+}
+
+static inline struct dvb_bat_transport *
+ dvb_bat_section_transports_next(struct dvb_bat_section_part2 *part2,
+ struct dvb_bat_transport *pos)
+{
+ uint8_t *end = (uint8_t*) part2 + sizeof(struct dvb_bat_section_part2) +
+ part2->transport_stream_loop_length;
+ uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_bat_transport) +
+ pos->transport_descriptors_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_bat_transport *) next;
+}
+
+static inline struct descriptor *
+ dvb_bat_transport_descriptors_first(struct dvb_bat_transport *t)
+{
+ if (t->transport_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*)t + sizeof(struct dvb_bat_transport));
+}
+
+static inline struct descriptor *
+ dvb_bat_transport_descriptors_next(struct dvb_bat_transport *t,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) t + sizeof(struct dvb_bat_transport),
+ t->transport_descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/bouquet_name_descriptor.h b/lib/libucsi/dvb/bouquet_name_descriptor.h
new file mode 100644
index 0000000..a298849
--- /dev/null
+++ b/lib/libucsi/dvb/bouquet_name_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_BOUQUET_NAME_DESCRIPTOR
+#define _UCSI_DVB_BOUQUET_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_bouquet_name_descriptor structure.
+ */
+struct dvb_bouquet_name_descriptor {
+ struct descriptor d;
+
+ /* uint8_t name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_bouquet_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_bouquet_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_bouquet_name_descriptor*
+ dvb_bouquet_name_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_bouquet_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the name field of a dvb_bouquet_name_descriptor.
+ *
+ * @param d dvb_bouquet_name_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_bouquet_name_descriptor_name(struct dvb_bouquet_name_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_bouquet_name_descriptor);
+}
+
+/**
+ * Determine the length of the name field of a dvb_bouquet_name_descriptor in bytes.
+ *
+ * @param d dvb_bouquet_name_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_bouquet_name_descriptor_name_length(struct dvb_bouquet_name_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ca_identifier_descriptor.h b/lib/libucsi/dvb/ca_identifier_descriptor.h
new file mode 100644
index 0000000..ac670a9
--- /dev/null
+++ b/lib/libucsi/dvb/ca_identifier_descriptor.h
@@ -0,0 +1,94 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CA_IDENTIFIER_DESCRIPTOR
+#define _UCSI_DVB_CA_IDENTIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_ca_identifier_descriptor structure.
+ */
+struct dvb_ca_identifier_descriptor {
+ struct descriptor d;
+
+ /* uint16_t ca_system_ids[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ca_identifier_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ca_identifier_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ca_identifier_descriptor*
+ dvb_ca_identifier_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+ uint8_t *buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+
+ if (len % 2)
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos+=2;
+ }
+
+ return (struct dvb_ca_identifier_descriptor*) d;
+}
+
+/**
+ * Accessor for the ca_system_ids field of a dvb_ca_identifier_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint16_t *
+ dvb_ca_identifier_descriptor_ca_system_ids(struct dvb_ca_identifier_descriptor *d)
+{
+ return (uint16_t *) ((uint8_t *) d + sizeof(struct dvb_ca_identifier_descriptor));
+}
+
+/**
+ * Calculate the number of entries in the ca_system_ids field of a dvb_ca_identifier_descriptor.
+ *
+ * @param d dvb_ca_identifier_descriptor pointer.
+ * @return Number of entries.
+ */
+static inline int
+ dvb_ca_identifier_descriptor_ca_system_ids_count(struct dvb_ca_identifier_descriptor *d)
+{
+ return d->d.len >> 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/cable_delivery_descriptor.h b/lib/libucsi/dvb/cable_delivery_descriptor.h
new file mode 100644
index 0000000..f0f92f3
--- /dev/null
+++ b/lib/libucsi/dvb/cable_delivery_descriptor.h
@@ -0,0 +1,70 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CABLE_DELIVERY_DESCRIPTOR
+#define _UCSI_DVB_CABLE_DELIVERY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_cable_delivery_descriptor structure.
+ */
+struct dvb_cable_delivery_descriptor {
+ struct descriptor d;
+
+ uint32_t frequency; // BCD, units 100Hz
+ EBIT2(uint16_t reserved : 12; ,
+ uint16_t fec_outer : 4; );
+ uint8_t modulation;
+ EBIT2(uint32_t symbol_rate : 28; , // BCD, units 100Hz
+ uint32_t fec_inner : 4; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_cable_delivery_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_cable_delivery_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_cable_delivery_descriptor*
+ dvb_cable_delivery_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_cable_delivery_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 6);
+ bswap32((uint8_t*) d + 9);
+
+ return (struct dvb_cable_delivery_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/cell_frequency_link_descriptor.h b/lib/libucsi/dvb/cell_frequency_link_descriptor.h
new file mode 100644
index 0000000..63f7fd2
--- /dev/null
+++ b/lib/libucsi/dvb/cell_frequency_link_descriptor.h
@@ -0,0 +1,190 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CELL_FREQUENCY_LINK_DESCRIPTOR
+#define _UCSI_DVB_CELL_FREQUENCY_LINK_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_cell_frequency_link_descriptor structure.
+ */
+struct dvb_cell_frequency_link_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_cell_frequency_link_cell cells[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the cells field of a dvb_cell_frequency_link_descriptor.
+ */
+struct dvb_cell_frequency_link_cell {
+ uint16_t cell_id;
+ uint32_t frequency;
+ uint8_t subcell_loop_info_length;
+ /* struct dvb_cell_frequency_link_subcell subcells[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the subcells field of a dvb_cell_frequency_link_cell.
+ */
+struct dvb_cell_frequency_link_cell_subcell {
+ uint8_t cell_id_extension;
+ uint32_t transposer_frequency;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_cell_frequency_link_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_cell_frequency_link_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_cell_frequency_link_descriptor*
+ dvb_cell_frequency_link_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t pos2 = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_cell_frequency_link_cell *e =
+ (struct dvb_cell_frequency_link_cell*) (buf+pos);
+
+ if ((pos + sizeof(struct dvb_cell_frequency_link_cell)) > len)
+ return NULL;
+
+ bswap16(buf+pos);
+ bswap32(buf+pos+2);
+
+ pos += sizeof(struct dvb_cell_frequency_link_cell);
+
+ if ((pos + e->subcell_loop_info_length) > len)
+ return NULL;
+
+ if (e->subcell_loop_info_length % sizeof(struct dvb_cell_frequency_link_cell_subcell))
+ return NULL;
+
+ pos2 = 0;
+ while(pos2 < e->subcell_loop_info_length) {
+ bswap32(buf+pos+pos2+1);
+
+ pos2 += sizeof(struct dvb_cell_frequency_link_cell_subcell);
+ }
+
+ pos += e->subcell_loop_info_length;
+ }
+
+ return (struct dvb_cell_frequency_link_descriptor*) d;
+}
+
+/**
+ * Iterator for the cells field of a dvb_cell_frequency_link_descriptor.
+ *
+ * @param d dvb_cell_frequency_link_descriptor pointer.
+ * @param pos Variable holding a pointer to the current dvb_cell_frequency_link_cell.
+ */
+#define dvb_cell_frequency_link_descriptor_cells_for_each(d, pos) \
+ for ((pos) = dvb_cell_frequency_link_descriptor_cells_first(d); \
+ (pos); \
+ (pos) = dvb_cell_frequency_link_descriptor_cells_next(d, pos))
+
+/**
+ * Iterator for the subcells field of a dvb_cell_frequency_link_cell.
+ *
+ * @param cell dvb_cell_frequency_link_cell pointer.
+ * @param pos Variable holding a pointer to the current dvb_cell_frequency_link_cell_subcell.
+ */
+#define dvb_cell_frequency_link_cell_subcells_for_each(cell, pos) \
+ for ((pos) = dvb_cell_frequency_link_cell_subcells_first(cell); \
+ (pos); \
+ (pos) = dvb_cell_frequency_link_cell_subcells_next(cell, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_cell_frequency_link_cell*
+ dvb_cell_frequency_link_descriptor_cells_first(struct dvb_cell_frequency_link_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_cell_frequency_link_cell *)
+ ((uint8_t*) d + sizeof(struct dvb_cell_frequency_link_descriptor));
+}
+
+static inline struct dvb_cell_frequency_link_cell*
+ dvb_cell_frequency_link_descriptor_cells_next(struct dvb_cell_frequency_link_descriptor *d,
+ struct dvb_cell_frequency_link_cell *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_cell_frequency_link_cell) +
+ pos->subcell_loop_info_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_cell_frequency_link_cell *) next;
+}
+
+static inline struct dvb_cell_frequency_link_cell_subcell*
+ dvb_cell_frequency_link_cell_subcells_first(struct dvb_cell_frequency_link_cell *d)
+{
+ if (d->subcell_loop_info_length == 0)
+ return NULL;
+
+ return (struct dvb_cell_frequency_link_cell_subcell*)
+ ((uint8_t*) d + sizeof(struct dvb_cell_frequency_link_cell));
+}
+
+static inline struct dvb_cell_frequency_link_cell_subcell*
+ dvb_cell_frequency_link_cell_subcells_next(struct dvb_cell_frequency_link_cell *cell,
+ struct dvb_cell_frequency_link_cell_subcell *pos)
+{
+ uint8_t *end = (uint8_t*) cell + cell->subcell_loop_info_length;
+ uint8_t *next = (uint8_t*) pos +
+ sizeof(struct dvb_cell_frequency_link_cell_subcell);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_cell_frequency_link_cell_subcell *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/cell_list_descriptor.h b/lib/libucsi/dvb/cell_list_descriptor.h
new file mode 100644
index 0000000..ddbaf2c
--- /dev/null
+++ b/lib/libucsi/dvb/cell_list_descriptor.h
@@ -0,0 +1,201 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CELL_LIST_DESCRIPTOR
+#define _UCSI_DVB_CELL_LIST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_cell_list_descriptor structure.
+ */
+struct dvb_cell_list_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_cell_list_entry cells[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the cells field of a dvb_cell_list_descriptor.
+ */
+struct dvb_cell_list_entry {
+ uint16_t cell_id;
+ uint16_t cell_latitude;
+ uint16_t cell_longitude;
+ EBIT3(uint32_t cell_extend_of_latitude :12; ,
+ uint32_t cell_extend_of_longitude :12; ,
+ uint32_t subcell_info_loop_length : 8; );
+ /* struct dvb_subcell_list_entry subcells[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the subcells field of a dvb_cell_list_entry.
+ */
+struct dvb_subcell_list_entry {
+ uint8_t cell_id_extension;
+ uint16_t subcell_latitude;
+ uint16_t subcell_longitude;
+ EBIT2(uint32_t subcell_extend_of_latitude :12; ,
+ uint32_t subcell_extend_of_longitude :12; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_cell_list_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_cell_list_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_cell_list_descriptor*
+ dvb_cell_list_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t pos2 = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_cell_list_entry *e =
+ (struct dvb_cell_list_entry*) (buf+pos);
+
+ if ((pos + sizeof(struct dvb_cell_list_entry)) > len)
+ return NULL;
+
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+ bswap32(buf+pos+6);
+
+ pos += sizeof(struct dvb_cell_list_entry);
+
+ if ((pos + e->subcell_info_loop_length) > len)
+ return NULL;
+
+ if (e->subcell_info_loop_length % sizeof(struct dvb_subcell_list_entry))
+ return NULL;
+
+ pos2 = 0;
+ while(pos2 < e->subcell_info_loop_length) {
+ bswap16(buf+pos+pos2+1);
+ bswap16(buf+pos+pos2+3);
+ bswap24(buf+pos+pos2+5);
+
+ pos2 += sizeof(struct dvb_subcell_list_entry);
+ }
+
+ pos += e->subcell_info_loop_length;
+ }
+
+ return (struct dvb_cell_list_descriptor*) d;
+}
+
+/**
+ * Iterator for the cells field of a dvb_cell_list_descriptor.
+ *
+ * @param d dvb_cell_list_descriptor pointer.
+ * @param pos Variable holding a pointer to the current dvb_cell_list_entry.
+ */
+#define dvb_cell_list_descriptor_cells_for_each(d, pos) \
+ for ((pos) = dvb_cell_list_descriptor_cells_first(d); \
+ (pos); \
+ (pos) = dvb_cell_list_descriptor_cells_next(d, pos))
+
+/**
+ * Iterator for the subcells field of a dvb_cell_list_entry.
+ *
+ * @param cell dvb_cell_list_entry pointer.
+ * @param pos Variable holding a pointer to the current dvb_subcell_list_entry.
+ */
+#define dvb_cell_list_entry_subcells_for_each(cell, pos) \
+ for ((pos) = dvb_cell_list_entry_subcells_first(cell); \
+ (pos); \
+ (pos) = dvb_cell_list_entry_subcells_next(cell, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_cell_list_entry*
+ dvb_cell_list_descriptor_cells_first(struct dvb_cell_list_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_cell_list_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_cell_list_descriptor));
+}
+
+static inline struct dvb_cell_list_entry*
+ dvb_cell_list_descriptor_cells_next(struct dvb_cell_list_descriptor *d,
+ struct dvb_cell_list_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_cell_list_entry) +
+ pos->subcell_info_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_cell_list_entry *) next;
+}
+
+static inline struct dvb_subcell_list_entry*
+ dvb_cell_list_entry_subcells_first(struct dvb_cell_list_entry *d)
+{
+ if (d->subcell_info_loop_length == 0)
+ return NULL;
+
+ return (struct dvb_subcell_list_entry*)
+ ((uint8_t*) d + sizeof(struct dvb_cell_list_entry));
+}
+
+static inline struct dvb_subcell_list_entry*
+ dvb_cell_list_entry_subcells_next(struct dvb_cell_list_entry *d,
+ struct dvb_subcell_list_entry *pos)
+{
+ uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_subcell_list_entry);
+ uint8_t *end = (uint8_t*) d +
+ sizeof(struct dvb_cell_list_entry) +
+ d->subcell_info_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_subcell_list_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/component_descriptor.h b/lib/libucsi/dvb/component_descriptor.h
new file mode 100644
index 0000000..31d38e1
--- /dev/null
+++ b/lib/libucsi/dvb/component_descriptor.h
@@ -0,0 +1,147 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_COMPONENT_DESCRIPTOR
+#define _UCSI_DVB_COMPONENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Possible values for stream_content.
+ */
+enum {
+ DVB_STREAM_CONTENT_VIDEO = 0x01,
+ DVB_STREAM_CONTENT_AUDIO = 0x02,
+ DVB_STREAM_CONTENT_SUBTITLE = 0x03,
+ DVB_STREAM_CONTENT_AC3 = 0x04,
+};
+
+/**
+ * Possible values for component_type.
+ */
+enum {
+ DVB_COMPONENT_TYPE_VIDEO_43_25Hz = 0x01,
+ DVB_COMPONENT_TYPE_VIDEO_169_PAN_25Hz = 0x02,
+ DVB_COMPONENT_TYPE_VIDEO_169_NOPAN_25Hz = 0x03,
+ DVB_COMPONENT_TYPE_VIDEO_GT169_25Hz = 0x04,
+
+ DVB_COMPONENT_TYPE_VIDEO_43_30Hz = 0x05,
+ DVB_COMPONENT_TYPE_VIDEO_169_PAN_30Hz = 0x06,
+ DVB_COMPONENT_TYPE_VIDEO_169_NOPAN_30Hz = 0x07,
+ DVB_COMPONENT_TYPE_VIDEO_GT169_30Hz = 0x08,
+
+ DVB_COMPONENT_TYPE_HDVIDEO_43_25Hz = 0x09,
+ DVB_COMPONENT_TYPE_HDVIDEO_169_PAN_25Hz = 0x0a,
+ DVB_COMPONENT_TYPE_HDVIDEO_169_NOPAN_25Hz = 0x0b,
+ DVB_COMPONENT_TYPE_HDVIDEO_GT169_25Hz = 0x0c,
+
+ DVB_COMPONENT_TYPE_HDVIDEO_43_30Hz = 0x0d,
+ DVB_COMPONENT_TYPE_HDVIDEO_169_PAN_30Hz = 0x0e,
+ DVB_COMPONENT_TYPE_HDVIDEO_169_NOPAN_30Hz = 0x0f,
+ DVB_COMPONENT_TYPE_HDVIDEO_GT169_30Hz = 0x10,
+
+ DVB_COMPONENT_TYPE_AUDIO_SINGLE_MONO = 0x01,
+ DVB_COMPONENT_TYPE_AUDIO_DUAL_MONO = 0x02,
+ DVB_COMPONENT_TYPE_AUDIO_STEREO = 0x03,
+ DVB_COMPONENT_TYPE_AUDIO_MULTI_LINGUAL_MULTI_CHAN= 0x04,
+ DVB_COMPONENT_TYPE_AUDIO_SURROUND = 0x05,
+ DVB_COMPONENT_TYPE_AUDIO_VISUAL_IMPAIRED = 0x40,
+ DVB_COMPONENT_TYPE_AUDIO_HARDHEAR = 0x41,
+ DVB_COMPONENT_TYPE_AUDIO_SUPPLEMENTARY = 0x42,
+
+ DVB_COMPONENT_TYPE_SUBTITLE_TELETEXT = 0x01,
+ DVB_COMPONENT_TYPE_SUBTITLE_ASSOC_TELETEXT = 0x02,
+ DVB_COMPONENT_TYPE_SUBTITLE_VBI = 0x03,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB = 0x10,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_43 = 0x11,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_169 = 0x12,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_2211 = 0x13,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR = 0x20,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_43 = 0x21,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_169 = 0x22,
+ DVB_COMPONENT_TYPE_SUBTITLE_DVB_HARDHEAR_2211 = 0x23,
+};
+
+/**
+ * dvb_component_descriptor structure.
+ */
+struct dvb_component_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 4; ,
+ uint8_t stream_content : 4; );
+ uint8_t component_type;
+ uint8_t component_tag;
+ iso639lang_t language_code;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_component_descriptor.
+ *
+ * @param d Pointer to a generic descriptor.
+ * @return dvb_component_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_component_descriptor*
+ dvb_component_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_component_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_component_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of a dvb_component_descriptor.
+ *
+ * @param d dvb_component_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_component_descriptor_text(struct dvb_component_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_component_descriptor);
+}
+
+/**
+ * Determine the length of the text field of a dvb_component_descriptor.
+ *
+ * @param d dvb_component_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_component_descriptor_text_length(struct dvb_component_descriptor *d)
+{
+ return d->d.len - 6;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/content_descriptor.h b/lib/libucsi/dvb/content_descriptor.h
new file mode 100644
index 0000000..d2a63a0
--- /dev/null
+++ b/lib/libucsi/dvb/content_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CONTENT_DESCRIPTOR
+#define _UCSI_DVB_CONTENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+// FIXME: the nibbles
+
+/**
+ * dvb_content_descriptor structure.
+ */
+struct dvb_content_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_content_nibble nibbles[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the nibbles field of a dvb_content_descriptor.
+ */
+struct dvb_content_nibble {
+ EBIT2(uint8_t content_nibble_level_1 : 4; ,
+ uint8_t content_nibble_level_2 : 4; );
+ EBIT2(uint8_t user_nibble_1 : 4; ,
+ uint8_t user_nibble_2 : 4; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_content_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_content_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_content_descriptor*
+ dvb_content_descriptor_codec(struct descriptor* d)
+{
+ if (d->len % sizeof(struct dvb_content_nibble))
+ return NULL;
+
+ return (struct dvb_content_descriptor*) d;
+}
+
+/**
+ * Iterator for the nibbles field of a dvb_content_descriptor.
+ *
+ * @param d dvb_content_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_content_nibble.
+ */
+#define dvb_content_descriptor_nibbles_for_each(d, pos) \
+ for ((pos) = dvb_content_descriptor_nibbles_first(d); \
+ (pos); \
+ (pos) = dvb_content_descriptor_nibbles_next(d, pos))
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_content_nibble*
+ dvb_content_descriptor_nibbles_first(struct dvb_content_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_content_nibble *)
+ ((uint8_t*) d + sizeof(struct dvb_content_descriptor));
+}
+
+static inline struct dvb_content_nibble*
+ dvb_content_descriptor_nibbles_next(struct dvb_content_descriptor *d,
+ struct dvb_content_nibble *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_content_nibble);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_content_nibble *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/content_identifier_descriptor.h b/lib/libucsi/dvb/content_identifier_descriptor.h
new file mode 100644
index 0000000..c2cf9ea
--- /dev/null
+++ b/lib/libucsi/dvb/content_identifier_descriptor.h
@@ -0,0 +1,233 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_CONTENT_IDENTIFIER_DESCRIPTOR
+#define _UCSI_DVB_CONTENT_IDENTIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+
+/**
+ * Possible values for the crid_type.
+ */
+enum {
+ DVB_CRID_TYPE_NONE = 0x00,
+ DVB_CRID_TYPE_ITEM = 0x01,
+ DVB_CRID_TYPE_SERIES = 0x02,
+ DVB_CRID_TYPE_RECOMMENDATION = 0x03,
+};
+
+/**
+ * Possible values for the crid_location.
+ */
+enum {
+ DVB_CRID_LOCATION_THIS_DESCRIPTOR = 0x00,
+ DVB_CRID_LOCATION_CIT = 0x01,
+};
+
+/**
+ * dvb_content_identifier_descriptor structure.
+ */
+struct dvb_content_identifier_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_content_identifier_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_content_identifier_descriptor.
+ */
+struct dvb_content_identifier_entry {
+ EBIT2(uint8_t crid_type : 6; ,
+ uint8_t crid_location : 2; );
+ /* struct dvb_content_identifier_data_00 data0 */
+ /* struct dvb_content_identifier_data_01 data1 */
+} __ucsi_packed;
+
+/**
+ * The data if crid_location == 0
+ */
+struct dvb_content_identifier_entry_data_0 {
+ uint8_t crid_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * The data if crid_location == 1
+ */
+struct dvb_content_identifier_entry_data_1 {
+ uint16_t crid_ref;
+} __ucsi_packed;
+
+
+/**
+ * Process a dvb_content_identifier_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_content_identifier_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_content_identifier_descriptor*
+ dvb_content_identifier_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len + 2;
+ uint32_t pos = 2;
+ uint8_t *buf = (uint8_t*) d;
+
+ while(pos < len) {
+ struct dvb_content_identifier_entry *e =
+ (struct dvb_content_identifier_entry*) (buf + pos);
+
+ if (len < (pos+1))
+ return NULL;
+ pos++;
+
+ switch(e->crid_location) {
+ case 0:
+ if (len < (pos + 1))
+ return NULL;
+ if (len < (pos + 1 + buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ break;
+
+ case 1:
+ if (len < (pos+2))
+ return NULL;
+ bswap16(buf+pos);
+ break;
+ }
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct dvb_content_identifier_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a dvb_content_identifier_descriptor.
+ *
+ * @param d dvb_content_identifier_descriptor pointer.
+ * @param pos Variable holding a pointer to the current dvb_content_identifier_entry.
+ */
+#define dvb_content_identifier_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_content_identifier_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_content_identifier_descriptor_entries_next(d, pos))
+
+/**
+ * Accessor for the data0 field of a dvb_content_identifier_entry.
+ *
+ * @param d dvb_content_identifier_entry pointer.
+ * @return Pointer, or NULL on error.
+ */
+static inline struct dvb_content_identifier_entry_data_0*
+ dvb_content_identifier_entry_data_0(struct dvb_content_identifier_entry *d)
+{
+ if (d->crid_location != 0)
+ return NULL;
+ return (struct dvb_content_identifier_entry_data_0*)
+ ((uint8_t*) d + sizeof(struct dvb_content_identifier_entry));
+}
+/**
+ * Accessor for the data field of a dvb_content_identifier_entry_data_0.
+ *
+ * @param d dvb_content_identifier_entry_data_0 pointer.
+ * @return Pointer, or NULL on error.
+ */
+static inline uint8_t*
+ dvb_content_identifier_entry_data_0_data(struct dvb_content_identifier_entry_data_0 *d)
+{
+ return ((uint8_t*) d + sizeof(struct dvb_content_identifier_entry_data_0));
+}
+
+/**
+ * Accessor for the data1 field of a dvb_content_identifier_entry.
+ *
+ * @param d dvb_content_identifier_entry pointer.
+ * @return Pointer, or NULL on error.
+ */
+static inline struct dvb_content_identifier_entry_data_1*
+ dvb_content_identifier_entry_data_1(struct dvb_content_identifier_entry *d)
+{
+ if (d->crid_location != 1)
+ return NULL;
+ return (struct dvb_content_identifier_entry_data_1*)
+ ((uint8_t*) d + sizeof(struct dvb_content_identifier_entry));
+}
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_content_identifier_entry*
+ dvb_content_identifier_descriptor_entries_first(struct dvb_content_identifier_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_content_identifier_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_content_identifier_descriptor));
+}
+
+static inline struct dvb_content_identifier_entry*
+ dvb_content_identifier_descriptor_entries_next(struct dvb_content_identifier_descriptor *d,
+ struct dvb_content_identifier_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_content_identifier_entry);
+
+ if (next >= end)
+ return NULL;
+
+ switch(pos->crid_location) {
+ case 0:
+ if ((next+2) >= end)
+ return NULL;
+ if ((next+2+next[1]) >= end)
+ return NULL;
+ break;
+
+ case 1:
+ if ((next+3) >= end)
+ return NULL;
+ break;
+ }
+
+ return (struct dvb_content_identifier_entry*) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/country_availability_descriptor.h b/lib/libucsi/dvb/country_availability_descriptor.h
new file mode 100644
index 0000000..65b1661
--- /dev/null
+++ b/lib/libucsi/dvb/country_availability_descriptor.h
@@ -0,0 +1,120 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR
+#define _UCSI_DVB_COUNTRY_AVAILABILITY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_country_availability_descriptor structure.
+ */
+struct dvb_country_availability_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t country_availability_flag : 1; ,
+ uint8_t reserved : 7; );
+ /* struct dvb_country_availability_entry countries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the countries field of a dvb_country_availability_descriptor.
+ */
+struct dvb_country_availability_entry {
+ iso639country_t country_code;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_country_availability_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_country_availability_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_country_availability_descriptor*
+ dvb_country_availability_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+
+ if (len < (sizeof(struct dvb_country_availability_descriptor) - 2))
+ return NULL;
+
+ if ((len - 1) % sizeof(struct dvb_country_availability_entry))
+ return NULL;
+
+ return (struct dvb_country_availability_descriptor*) d;
+}
+
+/**
+ * Iterator for the countries field of a dvb_country_availability_descriptor.
+ *
+ * @param d dvb_country_availability_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_country_availability_entry.
+ */
+#define dvb_country_availability_descriptor_countries_for_each(d, pos) \
+ for ((pos) = dvb_country_availability_descriptor_countries_first(d); \
+ (pos); \
+ (pos) = dvb_country_availability_descriptor_countries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_country_availability_entry*
+ dvb_country_availability_descriptor_countries_first(struct dvb_country_availability_descriptor *d)
+{
+ if (d->d.len == 1)
+ return NULL;
+
+ return (struct dvb_country_availability_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_country_availability_descriptor));
+}
+
+static inline struct dvb_country_availability_entry*
+ dvb_country_availability_descriptor_countries_next(struct dvb_country_availability_descriptor *d,
+ struct dvb_country_availability_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_country_availability_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_country_availability_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/data_broadcast_descriptor.h b/lib/libucsi/dvb/data_broadcast_descriptor.h
new file mode 100644
index 0000000..069e1db
--- /dev/null
+++ b/lib/libucsi/dvb/data_broadcast_descriptor.h
@@ -0,0 +1,139 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DATA_BROADCAST_DESCRIPTOR
+#define _UCSI_DVB_DATA_BROADCAST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_data_broadcast_descriptor structure.
+ */
+struct dvb_data_broadcast_descriptor {
+ struct descriptor d;
+
+ uint16_t data_broadcast_id;
+ uint8_t component_tag;
+ uint8_t selector_length;
+ /* uint8_t selector[] */
+ /* struct dvb_data_broadcast_descriptor_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_data_broadcast_descriptor following the variable length selector field.
+ */
+struct dvb_data_broadcast_descriptor_part2 {
+ iso639lang_t language_code;
+ uint8_t text_length;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_data_broadcast_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_data_broadcast_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_data_broadcast_descriptor*
+ dvb_data_broadcast_descriptor_codec(struct descriptor* d)
+{
+ struct dvb_data_broadcast_descriptor *p =
+ (struct dvb_data_broadcast_descriptor *) d;
+ struct dvb_data_broadcast_descriptor_part2 *p2;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = sizeof(struct dvb_data_broadcast_descriptor) - 2;
+ uint32_t len = d->len;
+
+ if (pos > len)
+ return NULL;
+
+ bswap16(buf + 2);
+
+ pos += p->selector_length;
+
+ if (pos > len)
+ return NULL;
+
+ p2 = (struct dvb_data_broadcast_descriptor_part2*) (buf + 2 + pos);
+
+ pos += sizeof(struct dvb_data_broadcast_descriptor_part2);
+
+ if (pos > len)
+ return NULL;
+
+ pos += p2->text_length;
+
+ if (pos != len)
+ return NULL;
+
+ return p;
+}
+
+/**
+ * Accessor for the selector field of a dvb_data_broadcast_descriptor.
+ *
+ * @param d dvb_data_broadcast_descriptor pointer.
+ * @return pointer to the field.
+ */
+static inline uint8_t *
+ dvb_data_broadcast_descriptor_selector(struct dvb_data_broadcast_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_data_broadcast_descriptor);
+}
+
+/**
+ * Accessor for the second part of a dvb_data_broadcast_descriptor.
+ *
+ * @param d dvb_data_broadcast_descriptor pointer.
+ * @return dvb_data_broadcast_descriptor_part2 pointer.
+ */
+static inline struct dvb_data_broadcast_descriptor_part2 *
+ dvb_data_broadcast_descriptor_part2(struct dvb_data_broadcast_descriptor *d)
+{
+ return (struct dvb_data_broadcast_descriptor_part2*)
+ ((uint8_t*) d + sizeof(struct dvb_data_broadcast_descriptor) +
+ d->selector_length);
+}
+
+/**
+ * Accessor for the text field in a dvb_data_broadcast_descriptor_part2.
+ *
+ * @param d dvb_data_broadcast_descriptor_part2 pointer.
+ * @return pointer to the field.
+ */
+static inline uint8_t *
+ dvb_data_broadcast_descriptor_part2_text(struct dvb_data_broadcast_descriptor_part2 *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_data_broadcast_descriptor_part2);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/data_broadcast_id_descriptor.h b/lib/libucsi/dvb/data_broadcast_id_descriptor.h
new file mode 100644
index 0000000..446927c
--- /dev/null
+++ b/lib/libucsi/dvb/data_broadcast_id_descriptor.h
@@ -0,0 +1,221 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR
+#define _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for data_broadcast_id.
+ */
+enum {
+ DVB_BROADCAST_ID_DATA_PIPE = 0X0001,
+ DVB_BROADCAST_ID_ASYNCHRONOUS_DATA_STREAM = 0X0002,
+ DVB_BROADCAST_ID_SYNCHRONOUS_DATA_STREAM = 0X0003,
+ DVB_BROADCAST_ID_SYNCHRONISED_DATA_STREAM = 0X0004,
+ DVB_BROADCAST_ID_MULTI_PROTOCOL_ENCAPSULATION = 0X0005,
+ DVB_BROADCAST_ID_DATA_CAROUSEL = 0X0006,
+ DVB_BROADCAST_ID_OBJECT_CAROUSEL = 0X0007,
+ DVB_BROADCAST_ID_DVB_ATM_STREAMS = 0X0008,
+ DVB_BROADCAST_ID_HIGHER_PROTOCOLS = 0X0009,
+ DVB_BROADCAST_ID_SOFTWARE_UPDATE = 0x000A,
+ DVB_BROADCAST_ID_IP_MAC_NOTIFICATION_TABLE = 0x000B,
+};
+
+/**
+ * dvb_data_broadcast_id_descriptor structure.
+ */
+struct dvb_data_broadcast_id_descriptor {
+ struct descriptor d;
+
+ uint16_t data_broadcast_id;
+ /* uint8_t id_selector_byte[] */
+} __ucsi_packed;
+
+/**
+ * id_selector_byte for 0x000b data_broadcast_id (IP/MAC Notification Table).
+ */
+struct dvb_id_selector_byte_000b {
+ uint8_t platform_id_data_length;
+ /* struct dvb_ip_mac_notification_info infos[] */
+ /* uint8_t private_data[] */
+} __ucsi_packed;
+
+/**
+ * Entries in the infos field of a dvb_id_selector_byte_0b.
+ */
+struct dvb_ip_mac_notification_info {
+ EBIT2(uint32_t platform_id : 24; ,
+ uint8_t action_type : 8; );
+ EBIT3(uint8_t reserved : 2; ,
+ uint8_t INT_versioning_flag : 1; ,
+ uint8_t INT_version : 5; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_data_broadcast_id_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_data_broadcast_id_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_data_broadcast_id_descriptor*
+ dvb_data_broadcast_id_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_data_broadcast_id_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+
+ return (struct dvb_data_broadcast_id_descriptor*) d;
+}
+
+/**
+ * Accessor for the selector_byte field of a dvb_data_broadcast_id_descriptor.
+ *
+ * @param d dvb_data_broadcast_id_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_data_broadcast_id_descriptor_id_selector_byte(struct dvb_data_broadcast_id_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_data_broadcast_id_descriptor);
+}
+
+/**
+ * Determine the length of the selector_byte field of a dvb_data_broadcast_id_descriptor.
+ *
+ * @param d dvb_data_broadcast_id_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_data_broadcast_id_descriptor_id_selector_byte_length(struct dvb_data_broadcast_id_descriptor *d)
+{
+ return d->d.len - 2;
+}
+
+/**
+ * Accessor for a dvb_id_selector_byte_000b pointer.
+ *
+ * @param d dvb_data_broadcast_id_descriptor pointer.
+ * @return Pointer to the data field.
+ */
+static inline struct dvb_id_selector_byte_000b *
+ dvb_id_selector_byte_000b(struct dvb_data_broadcast_id_descriptor *d)
+{
+ if (d->data_broadcast_id != DVB_BROADCAST_ID_IP_MAC_NOTIFICATION_TABLE)
+ return NULL;
+ return (struct dvb_id_selector_byte_000b *) dvb_data_broadcast_id_descriptor_id_selector_byte(d);
+}
+
+/**
+ * Iterator for the dvb_ip_mac_notification_info field of a dvb_id_selector_byte_000b.
+ *
+ * @param id_selector_byte dvb_id_selector_byte_000b pointer.
+ * @param pos Variable containing a pointer to the current dvb_ip_mac_notification_info.
+ */
+#define dvb_id_selector_byte_000b_ip_mac_notification_info_for_each(id_selector_byte, pos) \
+ for ((pos) = dvb_ip_mac_notification_info_first(id_selector_byte); \
+ (pos); \
+ (pos) = dvb_ip_mac_notification_info_next(id_selector_byte, pos))
+
+/**
+ * Length of the private_data field of a dvb_id_selector_byte_000b.
+ *
+ * @param d descriptor pointer.
+ * @param i dvb_id_selector_byte_000b pointer.
+ * @return Length of the field.
+ */
+static inline uint8_t
+ dvb_id_selector_byte_000b_private_data_length(struct descriptor *d,
+ struct dvb_id_selector_byte_000b *i)
+{
+ return (uint8_t) (d->len -
+ sizeof(struct descriptor) -
+ i->platform_id_data_length -
+ sizeof(struct dvb_id_selector_byte_000b));
+}
+
+/**
+ * Accessor for the private_data field of a dvb_id_selector_byte_000b.
+ *
+ * @param d descriptor pointer.
+ * @param i dvb_id_selector_byte_000b pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_id_selector_byte_000b_private_data(struct descriptor *d,
+ struct dvb_id_selector_byte_000b *i)
+{
+ if (dvb_id_selector_byte_000b_private_data_length(d, i) <= 0)
+ return NULL;
+
+ return (uint8_t *) i + i->platform_id_data_length + sizeof(struct dvb_id_selector_byte_000b);
+}
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ip_mac_notification_info *
+ dvb_ip_mac_notification_info_first(struct dvb_id_selector_byte_000b *d)
+{
+ if (d->platform_id_data_length == 0)
+ return NULL;
+
+ bswap32((uint8_t *) d + sizeof(struct dvb_id_selector_byte_000b));
+
+ return (struct dvb_ip_mac_notification_info *) ((uint8_t *) d + sizeof(struct dvb_id_selector_byte_000b));
+}
+
+static inline struct dvb_ip_mac_notification_info *
+ dvb_ip_mac_notification_info_next(struct dvb_id_selector_byte_000b *d,
+ struct dvb_ip_mac_notification_info *pos)
+{
+ uint8_t *end = (uint8_t *) d + d->platform_id_data_length;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_id_selector_byte_000b) +
+ sizeof(struct dvb_ip_mac_notification_info);
+
+ if (next >= end)
+ return NULL;
+
+ bswap32(next);
+
+ return (struct dvb_ip_mac_notification_info *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#include <libucsi/dvb/mhp_data_broadcast_id_descriptor.h>
diff --git a/lib/libucsi/dvb/default_authority_descriptor.h b/lib/libucsi/dvb/default_authority_descriptor.h
new file mode 100644
index 0000000..0b0ba73
--- /dev/null
+++ b/lib/libucsi/dvb/default_authority_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DEFAULT_AUTHORITY_DESCRIPTOR
+#define _UCSI_DVB_DEFAULT_AUTHORITY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_default_authority_descriptor structure.
+ */
+struct dvb_default_authority_descriptor {
+ struct descriptor d;
+
+ /* char name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_default_authority_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_default_authority_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_default_authority_descriptor*
+ dvb_default_authority_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_default_authority_descriptor*) d;
+}
+
+/**
+ * Accessor for the name field in a dvb_default_authority_descriptor.
+ *
+ * @param d dvb_default_authority_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_default_authority_descriptor_name(struct dvb_default_authority_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_default_authority_descriptor);
+}
+
+/**
+ * Calculate the length of the name field in a dvb_default_authority_descriptor.
+ *
+ * @param d dvb_default_authority_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_default_authority_descriptor_name_length(struct dvb_default_authority_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/descriptor.h b/lib/libucsi/dvb/descriptor.h
new file mode 100644
index 0000000..303e17a
--- /dev/null
+++ b/lib/libucsi/dvb/descriptor.h
@@ -0,0 +1,229 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DESCRIPTOR_H
+#define _UCSI_DVB_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/dvb/ac3_descriptor.h>
+#include <libucsi/dvb/adaptation_field_data_descriptor.h>
+#include <libucsi/dvb/ancillary_data_descriptor.h>
+#include <libucsi/dvb/announcement_support_descriptor.h>
+#include <libucsi/dvb/application_signalling_descriptor.h>
+#include <libucsi/dvb/bouquet_name_descriptor.h>
+#include <libucsi/dvb/ca_identifier_descriptor.h>
+#include <libucsi/dvb/cable_delivery_descriptor.h>
+#include <libucsi/dvb/cell_frequency_link_descriptor.h>
+#include <libucsi/dvb/cell_list_descriptor.h>
+#include <libucsi/dvb/component_descriptor.h>
+#include <libucsi/dvb/content_descriptor.h>
+#include <libucsi/dvb/content_identifier_descriptor.h>
+#include <libucsi/dvb/country_availability_descriptor.h>
+#include <libucsi/dvb/data_broadcast_descriptor.h>
+#include <libucsi/dvb/data_broadcast_id_descriptor.h>
+#include <libucsi/dvb/default_authority_descriptor.h>
+#include <libucsi/dvb/dsng_descriptor.h>
+#include <libucsi/dvb/extended_event_descriptor.h>
+#include <libucsi/dvb/frequency_list_descriptor.h>
+#include <libucsi/dvb/ip_mac_platform_name_descriptor.h>
+#include <libucsi/dvb/ip_mac_platform_provider_name_descriptor.h>
+#include <libucsi/dvb/ip_mac_stream_location_descriptor.h>
+#include <libucsi/dvb/linkage_descriptor.h>
+#include <libucsi/dvb/local_time_offset_descriptor.h>
+#include <libucsi/dvb/mosaic_descriptor.h>
+#include <libucsi/dvb/multilingual_bouquet_name_descriptor.h>
+#include <libucsi/dvb/multilingual_component_descriptor.h>
+#include <libucsi/dvb/multilingual_network_name_descriptor.h>
+#include <libucsi/dvb/multilingual_service_name_descriptor.h>
+#include <libucsi/dvb/network_name_descriptor.h>
+#include <libucsi/dvb/nvod_reference_descriptor.h>
+#include <libucsi/dvb/parental_rating_descriptor.h>
+#include <libucsi/dvb/partial_transport_stream_descriptor.h>
+#include <libucsi/dvb/pdc_descriptor.h>
+#include <libucsi/dvb/private_data_specifier_descriptor.h>
+#include <libucsi/dvb/related_content_descriptor.h>
+#include <libucsi/dvb/satellite_delivery_descriptor.h>
+#include <libucsi/dvb/s2_satellite_delivery_descriptor.h>
+#include <libucsi/dvb/scrambling_descriptor.h>
+#include <libucsi/dvb/service_availability_descriptor.h>
+#include <libucsi/dvb/service_descriptor.h>
+#include <libucsi/dvb/service_identifier_descriptor.h>
+#include <libucsi/dvb/service_list_descriptor.h>
+#include <libucsi/dvb/service_move_descriptor.h>
+#include <libucsi/dvb/short_event_descriptor.h>
+#include <libucsi/dvb/short_smoothing_buffer_descriptor.h>
+#include <libucsi/dvb/stream_identifier_descriptor.h>
+#include <libucsi/dvb/stuffing_descriptor.h>
+#include <libucsi/dvb/subtitling_descriptor.h>
+#include <libucsi/dvb/target_ip_address_descriptor.h>
+#include <libucsi/dvb/target_ipv6_address_descriptor.h>
+#include <libucsi/dvb/target_ip_slash_descriptor.h>
+#include <libucsi/dvb/target_ip_source_slash_descriptor.h>
+#include <libucsi/dvb/target_ipv6_slash_descriptor.h>
+#include <libucsi/dvb/target_ipv6_source_slash_descriptor.h>
+#include <libucsi/dvb/telephone_descriptor.h>
+#include <libucsi/dvb/teletext_descriptor.h>
+#include <libucsi/dvb/terrestrial_delivery_descriptor.h>
+#include <libucsi/dvb/time_shifted_event_descriptor.h>
+#include <libucsi/dvb/time_shifted_service_descriptor.h>
+#include <libucsi/dvb/transport_stream_descriptor.h>
+#include <libucsi/dvb/tva_id_descriptor.h>
+#include <libucsi/dvb/vbi_data_descriptor.h>
+#include <libucsi/dvb/vbi_teletext_descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * The following are disabled because support is incomplete just now.
+ */
+/*
+#include <libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h>
+#include <libucsi/dvb/rnt_rar_over_ip_descriptor.h>
+#include <libucsi/dvb/rnt_rnt_scan_descriptor.h>
+#include <libucsi/dvb/ait_application_descriptor.h>
+#include <libucsi/dvb/ait_application_name_descriptor.h>
+#include <libucsi/dvb/ait_external_application_authorisation_descriptor.h>
+#include <libucsi/dvb/ait_application_icons_descriptor.h>
+*/
+
+/**
+ * The following are not implemented just now
+ */
+/*
+#include <libucsi/dvb/ait_transport_protocol_descriptor.h>
+#include <libucsi/dvb/ait_dvb_j_application_descriptor.h>
+#include <libucsi/dvb/ait_dvb_j_application_location_descriptor.h>
+#include <libucsi/dvb/ait_dvb_html_application_descriptor.h>
+#include <libucsi/dvb/ait_dvb_html_application_location_descriptor.h>
+#include <libucsi/dvb/ait_dvb_html_application_boundary_descriptor.h>
+#include <libucsi/dvb/ait_prefetch_descriptor.h>
+#include <libucsi/dvb/ait_dii_location_descriptor.h>
+#include <libucsi/dvb/ait_ip_signalling_descriptor.h>
+*/
+
+/**
+ * Enumeration of DVB descriptor tags.
+ */
+enum dvb_descriptor_tag {
+ dtag_dvb_network_name = 0x40,
+ dtag_dvb_service_list = 0x41,
+ dtag_dvb_stuffing = 0x42,
+ dtag_dvb_satellite_delivery_system = 0x43,
+ dtag_dvb_cable_delivery_system = 0x44,
+ dtag_dvb_vbi_data = 0x45,
+ dtag_dvb_vbi_teletext = 0x46,
+ dtag_dvb_bouquet_name = 0x47,
+ dtag_dvb_service = 0x48,
+ dtag_dvb_country_availability = 0x49,
+ dtag_dvb_linkage = 0x4a,
+ dtag_dvb_nvod_reference = 0x4b,
+ dtag_dvb_time_shifted_service = 0x4c,
+ dtag_dvb_short_event = 0x4d,
+ dtag_dvb_extended_event = 0x4e,
+ dtag_dvb_time_shifted_event = 0x4f,
+ dtag_dvb_component = 0x50,
+ dtag_dvb_mosaic = 0x51,
+ dtag_dvb_stream_identifier = 0x52,
+ dtag_dvb_ca_identifier = 0x53,
+ dtag_dvb_content = 0x54,
+ dtag_dvb_parental_rating = 0x55,
+ dtag_dvb_teletext = 0x56,
+ dtag_dvb_telephone = 0x57,
+ dtag_dvb_local_time_offset = 0x58,
+ dtag_dvb_subtitling = 0x59,
+ dtag_dvb_terrestial_delivery_system = 0x5a,
+ dtag_dvb_multilingual_network_name = 0x5b,
+ dtag_dvb_multilingual_bouquet_name = 0x5c,
+ dtag_dvb_multilingual_service_name = 0x5d,
+ dtag_dvb_multilingual_component = 0x5e,
+ dtag_dvb_private_data_specifier = 0x5f,
+ dtag_dvb_service_move = 0x60,
+ dtag_dvb_short_smoothing_buffer = 0x61,
+ dtag_dvb_frequency_list = 0x62,
+ dtag_dvb_partial_transport_stream = 0x63,
+ dtag_dvb_data_broadcast = 0x64,
+ dtag_dvb_scrambling = 0x65,
+ dtag_dvb_data_broadcast_id = 0x66,
+ dtag_dvb_transport_stream = 0x67,
+ dtag_dvb_dsng = 0x68,
+ dtag_dvb_pdc = 0x69,
+ dtag_dvb_ac3 = 0x6a,
+ dtag_dvb_ancillary_data = 0x6b,
+ dtag_dvb_cell_list = 0x6c,
+ dtag_dvb_cell_frequency_link = 0x6d,
+ dtag_dvb_announcement_support = 0x6e,
+ dtag_dvb_application_signalling = 0x6f,
+ dtag_dvb_adaptation_field_data = 0x70,
+ dtag_dvb_service_identifier = 0x71,
+ dtag_dvb_service_availability = 0x72,
+ dtag_dvb_default_authority = 0x73,
+ dtag_dvb_related_content = 0x74,
+ dtag_dvb_tva_id = 0x75,
+ dtag_dvb_content_identifier = 0x76,
+ dtag_dvb_time_slice_fec_identifier = 0x77,
+ dtag_dvb_ecm_repetition_rate = 0x78,
+ dtag_dvb_s2_satellite_delivery_descriptor= 0x79,
+ dtag_dvb_enhanced_ac3_descriptor = 0x7a,
+ dtag_dvb_dts_descriptor = 0x7b,
+ dtag_dvb_aac_descriptor = 0x7c,
+ dtag_dvb_extension_descriptor = 0x7f,
+
+ /* descriptors which may only appear in an RNT */
+ dtag_dvb_rnt_rar_over_dvb_stream = 0x40,
+ dtag_dvb_rnt_rar_over_ip = 0x41,
+ dtag_dvb_rnt_rnt_scan = 0x42,
+
+ /* descriptors which may only appear in an AIT */
+ dtag_dvb_ait_application = 0x00,
+ dtag_dvb_ait_application_name = 0x01,
+ dtag_dvb_ait_transport_protocol = 0x02,
+ dtag_dvb_ait_dvb_j_application = 0x03,
+ dtag_dvb_ait_dvb_j_application_location = 0x04,
+ dtag_dvb_ait_external_application_authorisation = 0x05,
+ dtag_dvb_ait_dvb_html_application = 0x08,
+ dtag_dvb_ait_dvb_html_application_location = 0x09,
+ dtab_dvb_ait_dvb_html_application_boundary = 0x0a,
+ dtag_dvb_ait_application_icons = 0x0b,
+ dtag_dvb_ait_prefetch = 0x0c,
+ dtag_dvb_ait_dii_location = 0x0d,
+ dtag_dvb_ait_ip_signalling = 0x11,
+
+ /* descriptors which may only appear in INT */
+ dtag_dvb_target_ip_address = 0x09,
+ dtag_dvb_target_ipv6_address = 0x0a,
+ dtag_dvb_ip_mac_platform_name = 0x0c,
+ dtag_dvb_ip_mac_platform_provider_name = 0x0d,
+ dtag_dvb_target_ip_slash = 0x0f,
+ dtag_dvb_target_ip_source_slash = 0x10,
+ dtag_dvb_target_ipv6_slash = 0x11,
+ dtag_dvb_target_ipv6_source_slash = 0x12,
+ dtag_dvb_ip_mac_stream_location = 0x13,
+
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/dit_section.c b/lib/libucsi/dvb/dit_section.c
new file mode 100644
index 0000000..4f69d4e
--- /dev/null
+++ b/lib/libucsi/dvb/dit_section.c
@@ -0,0 +1,32 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/dit_section.h>
+
+struct dvb_dit_section * dvb_dit_section_codec(struct section * section)
+{
+ struct dvb_dit_section * ret = (struct dvb_dit_section *)section;
+
+ if (section->length < 1)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/dit_section.h b/lib/libucsi/dvb/dit_section.h
new file mode 100644
index 0000000..69fce4f
--- /dev/null
+++ b/lib/libucsi/dvb/dit_section.h
@@ -0,0 +1,54 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DIT_SECTION_H
+#define _UCSI_DVB_DIT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_dit_section structure.
+ */
+struct dvb_dit_section {
+ struct section head;
+
+ EBIT2(uint8_t transition_flag : 1; ,
+ uint8_t reserved : 7; );
+};
+
+/**
+ * Process a dvb_dit_section.
+ *
+ * @param section Pointer to a generic section header.
+ * @return Pointer to a dvb_dit_section, or NULL on error.
+ */
+struct dvb_dit_section * dvb_dit_section_codec(struct section *section);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/dsng_descriptor.h b/lib/libucsi/dvb/dsng_descriptor.h
new file mode 100644
index 0000000..6fd369b
--- /dev/null
+++ b/lib/libucsi/dvb/dsng_descriptor.h
@@ -0,0 +1,80 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_DSNG_DESCRIPTOR
+#define _UCSI_DVB_DSNG_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_dsng_descriptor structure.
+ */
+struct dvb_dsng_descriptor {
+ struct descriptor d;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_dsng_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to a dvb_dsng_descriptor, or NULL on error.
+ */
+static inline struct dvb_dsng_descriptor*
+ dvb_dsng_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_dsng_descriptor*) d;
+}
+
+/**
+ * Accessor for the data field in a dvb_dsng_descriptor.
+ *
+ * @param d dvb_dsng_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *dvb_dsng_descriptor_data(struct dvb_dsng_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_dsng_descriptor);
+}
+
+/**
+ * Determine the length of the data field in a dvb_dsng_descriptor.
+ *
+ * @param d dvb_dsng_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int dvb_dsng_descriptor_data_length(struct dvb_dsng_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/eit_section.c b/lib/libucsi/dvb/eit_section.c
new file mode 100644
index 0000000..97b0261
--- /dev/null
+++ b/lib/libucsi/dvb/eit_section.c
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/eit_section.h>
+
+struct dvb_eit_section *dvb_eit_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct dvb_eit_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+ bswap16(buf + pos);
+ pos += 4;
+
+ while (pos < len) {
+ struct dvb_eit_event * event =
+ (struct dvb_eit_event *) (buf + pos);
+
+ if ((pos + sizeof(struct dvb_eit_event)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 10);
+
+ pos += sizeof(struct dvb_eit_event);
+
+ if ((pos + event->descriptors_loop_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, event->descriptors_loop_length))
+ return NULL;
+
+ pos += event->descriptors_loop_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct dvb_eit_section *) ext;
+}
diff --git a/lib/libucsi/dvb/eit_section.h b/lib/libucsi/dvb/eit_section.h
new file mode 100644
index 0000000..a2f3e4f
--- /dev/null
+++ b/lib/libucsi/dvb/eit_section.h
@@ -0,0 +1,160 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_EIT_SECTION_H
+#define _UCSI_DVB_EIT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+#include <libucsi/dvb/types.h>
+
+
+/**
+ * dvb_eit_section structure.
+ */
+struct dvb_eit_section {
+ struct section_ext head;
+
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint8_t segment_last_section_number;
+ uint8_t last_table_id;
+ /* struct eit_event events[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the events field of a dvb_eit_section.
+ */
+struct dvb_eit_event {
+ uint16_t event_id;
+ dvbdate_t start_time;
+ dvbduration_t duration;
+ EBIT3(uint16_t running_status : 3; ,
+ uint16_t free_ca_mode : 1; ,
+ uint16_t descriptors_loop_length:12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_eit_section.
+ *
+ * @param section Pointer to a generic section_ext structure.
+ * @return Pointer to a dvb_eit_section, or NULL on error.
+ */
+struct dvb_eit_section *dvb_eit_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the service_id field of an EIT.
+ *
+ * @param eit EIT pointer.
+ * @return The service_id.
+ */
+static inline uint16_t dvb_eit_section_service_id(struct dvb_eit_section *eit)
+{
+ return eit->head.table_id_ext;
+}
+
+/**
+ * Iterator for the events field of a dvb_eit_section.
+ *
+ * @param eit dvb_eit_section pointer.
+ * @param pos Variable containing a pointer to the current dvb_eit_event.
+ */
+#define dvb_eit_section_events_for_each(eit, pos) \
+ for ((pos) = dvb_eit_section_events_first(eit); \
+ (pos); \
+ (pos) = dvb_eit_section_events_next(eit, pos))
+
+/**
+ * Iterator for the descriptors field of a dvb_eit_event.
+ *
+ * @param eit dvb_eit_event pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define dvb_eit_event_descriptors_for_each(event, pos) \
+ for ((pos) = dvb_eit_event_descriptors_first(event); \
+ (pos); \
+ (pos) = dvb_eit_event_descriptors_next(event, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_eit_event *
+ dvb_eit_section_events_first(struct dvb_eit_section *eit)
+{
+ size_t pos = sizeof(struct dvb_eit_section);
+
+ if (pos >= section_ext_length(&eit->head))
+ return NULL;
+
+ return (struct dvb_eit_event*) ((uint8_t *) eit + pos);
+}
+
+static inline struct dvb_eit_event *
+ dvb_eit_section_events_next(struct dvb_eit_section *eit,
+ struct dvb_eit_event *pos)
+{
+ uint8_t *end = (uint8_t*) eit + section_ext_length(&eit->head);
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_eit_event) +
+ pos->descriptors_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_eit_event *) next;
+}
+
+static inline struct descriptor *
+ dvb_eit_event_descriptors_first(struct dvb_eit_event * t)
+{
+ if (t->descriptors_loop_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) t + sizeof(struct dvb_eit_event));
+}
+
+static inline struct descriptor *
+ dvb_eit_event_descriptors_next(struct dvb_eit_event * t,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) t + sizeof(struct dvb_eit_event),
+ t->descriptors_loop_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/extended_event_descriptor.h b/lib/libucsi/dvb/extended_event_descriptor.h
new file mode 100644
index 0000000..bba04b0
--- /dev/null
+++ b/lib/libucsi/dvb/extended_event_descriptor.h
@@ -0,0 +1,232 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_EXTENDED_EVENT_DESCRIPTOR
+#define _UCSI_DVB_EXTENDED_EVENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_extended_event_descriptor structure.
+ */
+struct dvb_extended_event_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t descriptor_number : 4; ,
+ uint8_t last_descriptor_number : 4; );
+ iso639lang_t language_code;
+ uint8_t length_of_items;
+ /* struct dvb_extended_event_item items[] */
+ /* struct dvb_extended_event_descriptor_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * An entry in the items field of a dvb_extended_event_descriptor.
+ */
+struct dvb_extended_event_item {
+ uint8_t item_description_length;
+ /* uint8_t item_description[] */
+ /* struct dvb_extended_event_item_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * The second part of a dvb_extended_event_item, following the variable length
+ * description field.
+ */
+struct dvb_extended_event_item_part2 {
+ uint8_t item_length;
+ /* uint8_t item[] */
+} __ucsi_packed;
+
+/**
+ * The second part of a dvb_extended_event_descriptor, following the variable
+ * length items field.
+ */
+struct dvb_extended_event_descriptor_part2 {
+ uint8_t text_length;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_extended_event_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_extended_event_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_extended_event_descriptor*
+ dvb_extended_event_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+ struct dvb_extended_event_descriptor * p =
+ (struct dvb_extended_event_descriptor *) d;
+ struct dvb_extended_event_descriptor_part2 *p2;
+
+ pos += sizeof(struct dvb_extended_event_descriptor) - 2;
+
+ if (pos > len)
+ return NULL;
+
+ pos += p->length_of_items;
+
+ if (pos > len)
+ return NULL;
+
+ p2 = (struct dvb_extended_event_descriptor_part2*) (buf+pos);
+
+ pos += sizeof(struct dvb_extended_event_descriptor_part2);
+
+ if (pos > len)
+ return NULL;
+
+ pos += p2->text_length;
+
+ if (pos != len)
+ return NULL;
+
+ return p;
+}
+
+/**
+ * Iterator for the items field of a dvb_extended_event_descriptor.
+ *
+ * @param d dvb_extended_event_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_extended_event_item.
+ */
+#define dvb_extended_event_descriptor_items_for_each(d, pos) \
+ for ((pos) = dvb_extended_event_descriptor_items_first(d); \
+ (pos); \
+ (pos) = dvb_extended_event_descriptor_items_next(d, pos))
+
+/**
+ * Accessor for the description field of a dvb_extended_event_item.
+ *
+ * @param d dvb_extended_event_item pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_extended_event_item_description(struct dvb_extended_event_item *d)
+{
+ return (uint8_t*) d + sizeof(struct dvb_extended_event_item);
+}
+
+/**
+ * Accessor for the second part of a dvb_extended_event_item.
+ *
+ * @param dvb_extended_event_item pointer.
+ * @return dvb_extended_event_item_part2 pointer.
+ */
+static inline struct dvb_extended_event_item_part2*
+ dvb_extended_event_item_part2(struct dvb_extended_event_item *d)
+{
+ return (struct dvb_extended_event_item_part2*)
+ ((uint8_t*) d + sizeof(struct dvb_extended_event_item) +
+ d->item_description_length);
+}
+
+/**
+ * Accessor for the item field of a dvb_extended_event_item_part2.
+ *
+ * @param d dvb_extended_event_item_part2 pointer.
+ * @return Pointer to the item field.
+ */
+static inline uint8_t*
+ dvb_extended_event_item_part2_item(struct dvb_extended_event_item_part2 *d)
+{
+ return (uint8_t*) d + sizeof(struct dvb_extended_event_item_part2);
+}
+
+/**
+ * Accessor for the second part of a dvb_extended_event_descriptor.
+ *
+ * @param d dvb_extended_event_descriptor pointer.
+ * @return dvb_extended_event_descriptor_part2 pointer.
+ */
+static inline struct dvb_extended_event_descriptor_part2*
+ dvb_extended_event_descriptor_part2(struct dvb_extended_event_descriptor *d)
+{
+ return (struct dvb_extended_event_descriptor_part2*)
+ ((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor) +
+ d->length_of_items);
+}
+
+/**
+ * Accessor for the text field of an dvb_extended_event_descriptor_part2.
+ *
+ * @param d dvb_extended_event_descriptor_part2 pointer.
+ * @return Pointer to the text field.
+ */
+static inline uint8_t*
+ dvb_extended_event_descriptor_part2_text(struct dvb_extended_event_descriptor_part2 *d)
+{
+ return (uint8_t*)
+ ((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor_part2));
+}
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_extended_event_item*
+ dvb_extended_event_descriptor_items_first(struct dvb_extended_event_descriptor *d)
+{
+ if (d->length_of_items == 0)
+ return NULL;
+
+ return (struct dvb_extended_event_item *)
+ ((uint8_t*) d + sizeof(struct dvb_extended_event_descriptor));
+}
+
+static inline struct dvb_extended_event_item*
+ dvb_extended_event_descriptor_items_next(struct dvb_extended_event_descriptor *d,
+ struct dvb_extended_event_item *pos)
+{
+ struct dvb_extended_event_item_part2* part2 =
+ dvb_extended_event_item_part2(pos);
+ uint8_t *end = (uint8_t*) d + sizeof(struct dvb_extended_event_descriptor) + d->length_of_items;
+ uint8_t *next = (uint8_t *) part2 +
+ sizeof(struct dvb_extended_event_item_part2) +
+ part2->item_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_extended_event_item *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/frequency_list_descriptor.h b/lib/libucsi/dvb/frequency_list_descriptor.h
new file mode 100644
index 0000000..4c18cec
--- /dev/null
+++ b/lib/libucsi/dvb/frequency_list_descriptor.h
@@ -0,0 +1,107 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_FREQUENCY_LIST_DESCRIPTOR
+#define _UCSI_DVB_FREQUENCY_LIST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for coding_type.
+ */
+enum {
+ DVB_CODING_TYPE_SATELLITE = 0x01,
+ DVB_CODING_TYPE_CABLE = 0x02,
+ DVB_CODING_TYPE_TERRESTRIAL = 0x03,
+};
+
+/**
+ * dvb_frequency_list_descriptor structure.
+ */
+struct dvb_frequency_list_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 6; ,
+ uint8_t coding_type : 2; );
+ /* uint32_t centre_frequencies [] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_frequency_list_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return dvb_frequency_list_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_frequency_list_descriptor*
+ dvb_frequency_list_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ pos += sizeof(struct dvb_frequency_list_descriptor) - 2;
+
+ if ((len - pos) % 4)
+ return NULL;
+
+ while(pos < len) {
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ return (struct dvb_frequency_list_descriptor*) d;
+}
+
+/**
+ * Accessor for the centre_frequencies field of a dvb_frequency_list_descriptor.
+ *
+ * @param d dvb_frequency_list_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint32_t *
+ dvb_frequency_list_descriptor_centre_frequencies(struct dvb_frequency_list_descriptor *d)
+{
+ return (uint32_t *) ((uint8_t *) d + sizeof(struct dvb_frequency_list_descriptor));
+}
+
+/**
+ * Determine the number of entries in the centre_frequencies field of a dvb_frequency_list_descriptor.
+ *
+ * @param d dvb_frequency_list_descriptor pointer.
+ * @return The number of entries.
+ */
+static inline int
+ dvb_frequency_list_descriptor_centre_frequencies_count(struct dvb_frequency_list_descriptor *d)
+{
+ return (d->d.len - 1) >> 2;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/int_section.c b/lib/libucsi/dvb/int_section.c
new file mode 100644
index 0000000..c2bb15f
--- /dev/null
+++ b/lib/libucsi/dvb/int_section.c
@@ -0,0 +1,79 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2005 Patrick Boettcher (pb@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/int_section.h>
+
+struct dvb_int_section * dvb_int_section_codec(struct section_ext *ext)
+{
+ uint8_t *buf = (uint8_t *) ext;
+ struct dvb_int_section *in = (struct dvb_int_section *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct dvb_int_section))
+ return NULL;
+
+ bswap32(buf+8);
+ bswap16(buf+12);
+ pos += 6;
+
+ if (len - pos < in->platform_descriptors_length)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, in->platform_descriptors_length))
+ return NULL;
+
+ pos += in->platform_descriptors_length;
+
+ while (pos < len) {
+ struct dvb_int_target *s2 = (struct dvb_int_target *) (buf + pos);
+ struct dvb_int_operational_loop *s3;
+
+ bswap16(buf + pos); /* target_descriptor_loop_length swap */
+
+ if (len - pos < s2->target_descriptors_length)
+ return NULL;
+
+ pos += sizeof(struct dvb_int_target);
+
+ if (verify_descriptors(buf + pos, s2->target_descriptors_length))
+ return NULL;
+
+ pos += s2->target_descriptors_length;
+
+ s3 = (struct dvb_int_operational_loop *) (buf + pos);
+
+ bswap16(buf + pos); /* operational_descriptor_loop_length swap */
+
+ if (len - pos < s3->operational_descriptors_length)
+ return NULL;
+
+ pos += sizeof(struct dvb_int_operational_loop);
+
+ if (verify_descriptors(buf + pos, s3->operational_descriptors_length))
+ return NULL;
+
+ pos += s3->operational_descriptors_length;
+ }
+
+ return (struct dvb_int_section *) ext;
+}
diff --git a/lib/libucsi/dvb/int_section.h b/lib/libucsi/dvb/int_section.h
new file mode 100644
index 0000000..932c0e8
--- /dev/null
+++ b/lib/libucsi/dvb/int_section.h
@@ -0,0 +1,245 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2005 Patrick Boettcher (pb@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+#ifndef _UCSI_DVB_INT_SECTION_H
+#define _UCSI_DVB_INT_SECTION_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_int_section structure - IP/MAC notification section.
+ */
+struct dvb_int_section {
+ struct section_ext head;
+
+ EBIT2(uint32_t platform_id :24; ,
+ uint32_t processing_order : 8; );
+ EBIT2(uint16_t reserved2 : 4; ,
+ uint16_t platform_descriptors_length :12; );
+ /* struct descriptor platform_descriptors[] */
+ /* struct dvb_int_target target_loop[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the target_loop field of a dvb_int_section.
+ */
+struct dvb_int_target {
+ EBIT2(uint16_t reserved3 : 4; ,
+ uint16_t target_descriptors_length :12; );
+ /* struct descriptor target_descriptors[] */
+ /* struct dvb_int_operational_loop operational_loop */
+} __ucsi_packed;
+
+/**
+ * The operational_loop field in a dvb_int_target.
+ */
+struct dvb_int_operational_loop {
+ EBIT2(uint16_t reserved4 : 4; ,
+ uint16_t operational_descriptors_length :12; );
+ /* struct descriptor operational_descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_int_section.
+ *
+ * @param section Generic section_ext pointer.
+ * @return dvb_int_section pointer, or NULL on error.
+ */
+extern struct dvb_int_section * dvb_int_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the action_type field of an INT.
+ *
+ * @param intp INT pointer.
+ * @return The action_type.
+ */
+static inline uint8_t dvb_int_section_action_type(struct dvb_int_section *intp)
+{
+ return intp->head.table_id_ext >> 8;
+}
+
+/**
+ * Accessor for the platform_id_hash field of an INT.
+ *
+ * @param intp INT pointer.
+ * @return The platform_id_hash.
+ */
+static inline uint8_t dvb_int_section_platform_id_hash(struct dvb_int_section *intp)
+{
+ return intp->head.table_id_ext & 0xff;
+}
+
+/**
+ * Iterator for platform_descriptors field in a dvb_int_section.
+ *
+ * @param intp dvb_int_section pointer.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define dvb_int_section_platform_descriptors_for_each(intp, pos) \
+ for ((pos) = dvb_int_section_platform_descriptors_first(intp); \
+ (pos); \
+ (pos) = dvb_int_section_platform_descriptors_next(intp, pos))
+
+/**
+ * Iterator for the target_loop field in a dvb_int_section.
+ *
+ * @param intp dvb_int_section pointer.
+ * @param pos Variable holding a pointer to the current dvb_int_target.
+ */
+#define dvb_int_section_target_loop_for_each(intp,pos) \
+ for ((pos) = dvb_int_section_target_loop_first(intp); \
+ (pos); \
+ (pos) = dvb_int_section_target_loop_next(intp, pos))
+
+/**
+ * Iterator for the target_descriptors field in a dvb_int_target.
+ *
+ * @param target dvb_int_target pointer.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define dvb_int_target_target_descriptors_for_each(target, pos) \
+ for ((pos) = dvb_int_target_target_descriptors_first(target); \
+ (pos); \
+ (pos) = dvb_int_target_target_descriptors_next(target, pos))
+
+/**
+ * Accessor for the operational_loop field of a dvb_int_target.
+ *
+ * @param target dvb_int_target pointer.
+ * @return Pointer to a dvb_int_operational_loop.
+ */
+static inline struct dvb_int_operational_loop *
+ dvb_int_target_operational_loop(struct dvb_int_target *target)
+{
+ return (struct dvb_int_operational_loop *)
+ ((uint8_t *) target + sizeof(struct dvb_int_target) + target->target_descriptors_length);
+}
+
+/**
+ * Iterator for the operational_descriptors field in a dvb_int_operational_loop.
+ *
+ * @param oploop dvb_int_operational_loop pointer.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define dvb_int_operational_loop_operational_descriptors_for_each(oploop, pos) \
+ for ((pos) = dvb_int_operational_loop_operational_descriptors_first(oploop); \
+ (pos); \
+ (pos) = dvb_int_operational_loop_operational_descriptors_next(oploop, pos))
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ dvb_int_section_platform_descriptors_first(struct dvb_int_section *in)
+{
+ if (in->platform_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) in + sizeof(struct dvb_int_section));
+}
+
+static inline struct descriptor *
+ dvb_int_section_platform_descriptors_next(struct dvb_int_section *in,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) in + sizeof(struct dvb_int_section),
+ in->platform_descriptors_length,
+ pos);
+}
+
+static inline struct dvb_int_target *
+ dvb_int_section_target_loop_first(struct dvb_int_section *in)
+{
+ if (sizeof(struct dvb_int_section) + in->platform_descriptors_length >= (uint32_t) section_ext_length((struct section_ext *) in))
+ return NULL;
+
+ return (struct dvb_int_target *)
+ ((uint8_t *) in + sizeof(struct dvb_int_section) + in->platform_descriptors_length);
+}
+
+static inline struct dvb_int_target *
+ dvb_int_section_target_loop_next(struct dvb_int_section *in,
+ struct dvb_int_target *pos)
+{
+ struct dvb_int_operational_loop *ol = dvb_int_target_operational_loop(pos);
+ struct dvb_int_target *next =
+ (struct dvb_int_target *) ( (uint8_t *) pos +
+ sizeof(struct dvb_int_target) + pos->target_descriptors_length +
+ sizeof(struct dvb_int_operational_loop) + ol->operational_descriptors_length);
+ struct dvb_int_target *end =
+ (struct dvb_int_target *) ((uint8_t *) in + section_ext_length((struct section_ext *) in) );
+
+ if (next >= end)
+ return 0;
+ return next;
+}
+
+static inline struct descriptor *
+ dvb_int_target_target_descriptors_first(struct dvb_int_target *tl)
+{
+ if (tl->target_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) tl + sizeof(struct dvb_int_target));
+}
+
+static inline struct descriptor *
+ dvb_int_target_target_descriptors_next(struct dvb_int_target *tl,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) tl + sizeof(struct dvb_int_target),
+ tl->target_descriptors_length,
+ pos);
+}
+
+static inline struct descriptor *
+ dvb_int_operational_loop_operational_descriptors_first(struct dvb_int_operational_loop *ol)
+{
+ if (ol->operational_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) ol + sizeof(struct dvb_int_operational_loop));
+}
+
+static inline struct descriptor *
+ dvb_int_operational_loop_operational_descriptors_next(struct dvb_int_operational_loop *ol,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) ol + sizeof(struct dvb_int_operational_loop),
+ ol->operational_descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h b/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h
new file mode 100644
index 0000000..c470e89
--- /dev/null
+++ b/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h
@@ -0,0 +1,87 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR
+#define _UCSI_DVB_IP_MAC_PLATFORM_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_ip_platform_name_descriptor structure.
+ */
+struct dvb_ip_platform_name_descriptor {
+ struct descriptor d;
+
+ iso639lang_t language_code;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ip_platform_name_descriptor.
+ *
+ * @param d Pointer to a generic descriptor.
+ * @return dvb_ip_platform_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ip_platform_name_descriptor*
+ dvb_ip_platform_name_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_ip_platform_name_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_ip_platform_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of a dvb_ip_platform_name_descriptor.
+ *
+ * @param d dvb_ip_platform_name_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_ip_platform_name_descriptor_text(struct dvb_ip_platform_name_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_ip_platform_name_descriptor);
+}
+
+/**
+ * Determine the length of the text field of a dvb_ip_platform_name_descriptor.
+ *
+ * @param d dvb_ip_platform_name_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_ip_platform_name_descriptor_text_length(struct dvb_ip_platform_name_descriptor *d)
+{
+ return d->d.len - 3;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h b/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h
new file mode 100644
index 0000000..ba95b8f
--- /dev/null
+++ b/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h
@@ -0,0 +1,87 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR
+#define _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_ip_platform_provider_name_descriptor structure.
+ */
+struct dvb_ip_platform_provider_name_descriptor {
+ struct descriptor d;
+
+ iso639lang_t language_code;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ip_platform_provider_name_descriptor.
+ *
+ * @param d Pointer to a generic descriptor.
+ * @return dvb_ip_platform_provider_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ip_platform_provider_name_descriptor*
+ dvb_ip_platform_provider_name_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_ip_platform_provider_name_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_ip_platform_provider_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the text field of a dvb_ip_platform_provider_name_descriptor.
+ *
+ * @param d dvb_ip_platform_provider_name_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_ip_platform_provider_name_descriptor_text(struct dvb_ip_platform_provider_name_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_ip_platform_provider_name_descriptor);
+}
+
+/**
+ * Determine the length of the text field of a dvb_ip_platform_provider_name_descriptor.
+ *
+ * @param d dvb_ip_platform_provider_name_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_ip_platform_provider_name_descriptor_text_length(struct dvb_ip_platform_provider_name_descriptor *d)
+{
+ return d->d.len - 3;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h b/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h
new file mode 100644
index 0000000..36216d6
--- /dev/null
+++ b/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h
@@ -0,0 +1,73 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_IP_MAC_STREAM_LOCATION_DESCRIPTOR
+#define _UCSI_DVB_IP_MAC_PLATFORM_PROVIDER_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_ip_mac_stream_location_descriptor structure.
+ */
+struct dvb_ip_mac_stream_location_descriptor {
+ struct descriptor d;
+
+ uint16_t network_id;
+ uint16_t original_network_id;
+ uint16_t transport_stream_id;
+ uint16_t service_id;
+ uint8_t component_tag;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_ip_mac_stream_location_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_ip_mac_stream_location_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_ip_mac_stream_location_descriptor*
+ dvb_ip_mac_stream_location_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+
+ if (d->len != (sizeof(struct dvb_ip_mac_stream_location_descriptor) - 2))
+ return NULL;
+
+ bswap16(buf);
+ bswap16(buf+2);
+ bswap16(buf+4);
+ bswap16(buf+6);
+
+ return (struct dvb_ip_mac_stream_location_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/linkage_descriptor.h b/lib/libucsi/dvb/linkage_descriptor.h
new file mode 100644
index 0000000..d2be789
--- /dev/null
+++ b/lib/libucsi/dvb/linkage_descriptor.h
@@ -0,0 +1,480 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_LINKAGE_DESCRIPTOR
+#define _UCSI_DVB_LINKAGE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Possible values for linkage_type.
+ */
+enum {
+ DVB_LINKAGE_TYPE_INFORMATION = 0x01,
+ DVB_LINKAGE_TYPE_EPG = 0x02,
+ DVB_LINKAGE_TYPE_CA_REPLACEMENT = 0x03,
+ DVB_LINKAGE_TYPE_TS_WITH_BAT_NIT = 0x04,
+ DVB_LINKAGE_TYPE_SERVICE_REPLACMENT = 0x05,
+ DVB_LINKAGE_TYPE_DATA_BCAST = 0x06,
+ DVB_LINKAGE_TYPE_RCS_MAP = 0x07,
+ DVB_LINKAGE_TYPE_MOBILE_HANDOVER = 0x08,
+ DVB_LINKAGE_TYPE_SOFTWARE_UPDATE = 0x09,
+ DVB_LINKAGE_TYPE_TS_WITH_SSU_BAT_NIT = 0x0a,
+ DVB_LINKAGE_TYPE_IP_MAC_NOTIFICATION = 0x0b,
+ DVB_LINKAGE_TYPE_TS_WITH_INT_BAT_NIT = 0x0c,
+};
+
+/**
+ * Possible values for hand_over_type.
+ */
+enum {
+ DVB_HAND_OVER_TYPE_IDENTICAL_NEIGHBOURING_COUNTRY = 0x01,
+ DVB_HAND_OVER_TYPE_LOCAL_VARIATION = 0x02,
+ DVB_HAND_OVER_TYPE_ASSOCIATED_SERVICE = 0x03,
+};
+
+/**
+ * Possible values for origin_type.
+ */
+enum {
+ DVB_ORIGIN_TYPE_NIT = 0x00,
+ DVB_ORIGIN_TYPE_SDT = 0x01,
+};
+
+/**
+ * dvb_linkage_descriptor structure.
+ */
+struct dvb_linkage_descriptor {
+ struct descriptor d;
+
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint16_t service_id;
+ uint8_t linkage_type;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Data for a linkage_type of 0x08.
+ */
+struct dvb_linkage_data_08 {
+ EBIT3(uint8_t hand_over_type : 4; ,
+ uint8_t reserved : 3; ,
+ uint8_t origin_type : 1; );
+ /* uint16_t network_id if hand_over_type == 1,2,3 */
+ /* uint16_t initial_service_id if origin_type = 0 */
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Data for an linkage_type of 0x0b (IP/MAC Notification Table).
+ */
+struct dvb_linkage_data_0b {
+ uint8_t platform_id_data_length;
+ /* struct platform_id ids[] */
+} __ucsi_packed;
+
+/**
+ * Entries in the ids field of a dvb_linkage_data_0b.
+ */
+struct dvb_platform_id {
+ EBIT2(uint32_t platform_id : 24; ,
+ uint8_t platform_name_loop_length : 8; );
+ /* struct platform_name names[] */
+} __ucsi_packed;
+
+/**
+ * Entries in the names field of a dvb_platform_id.
+ */
+struct dvb_platform_name {
+ iso639lang_t language_code;
+ uint8_t platform_name_length;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Data for a linkage_type of 0x0c (IP/MAC Notification Table).
+ */
+struct dvb_linkage_data_0c {
+ uint8_t table_type;
+ /* uint16_t bouquet_id if table_type == 0x02 */
+} __ucsi_packed;
+
+
+/**
+ * Process a dvb_linkage_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_linkage_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_linkage_descriptor*
+ dvb_linkage_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+ struct dvb_linkage_descriptor *p =
+ (struct dvb_linkage_descriptor*) d;
+
+ if (len < (sizeof(struct dvb_linkage_descriptor) - 2))
+ return NULL;
+
+ bswap16(buf);
+ bswap16(buf+2);
+ bswap16(buf+4);
+
+ pos += sizeof(struct dvb_linkage_descriptor) - 2;
+
+ if (p->linkage_type == 0x08) {
+ struct dvb_linkage_data_08 *d08;
+
+ if ((len - pos) < sizeof(struct dvb_linkage_data_08))
+ return NULL;
+ d08 = (struct dvb_linkage_data_08 *) (buf+pos);
+ pos += sizeof(struct dvb_linkage_data_08);
+
+ switch(d08->hand_over_type) {
+ case 1:
+ case 2:
+ case 3:
+ if ((len - pos) < 2)
+ return NULL;
+ bswap16(buf+pos);
+ pos += 2;
+ break;
+ }
+ if (d08->origin_type == 0) {
+ if ((len - pos) < 2)
+ return NULL;
+ bswap16(buf+pos);
+ pos+=2;
+ }
+
+ } else if (p->linkage_type == 0x0b) {
+ uint32_t pos2=0;
+ struct dvb_linkage_data_0b *l_0b = (struct dvb_linkage_data_0b *) (buf + pos);
+
+ if ((len - pos) < sizeof(struct dvb_linkage_data_0b))
+ return NULL;
+
+ pos += sizeof(struct dvb_linkage_data_0b);
+ if ((len - pos) < l_0b->platform_id_data_length)
+ return NULL;
+
+ while (pos2 < l_0b->platform_id_data_length) {
+ bswap32(buf + pos + pos2);
+
+ struct dvb_platform_id *p_id = (struct dvb_platform_id *) (buf + pos + pos2);
+ if ((len - pos - pos2) < p_id->platform_name_loop_length)
+ return NULL;
+
+ pos2 += sizeof(struct dvb_platform_id) + p_id->platform_name_loop_length;
+ }
+
+ pos += pos2;
+ } else if (p->linkage_type == 0x0c) {
+ struct dvb_linkage_data_0c *l_0c = (struct dvb_linkage_data_0c *) (buf + pos);
+
+ if ((len - pos) < sizeof(struct dvb_linkage_data_0c))
+ return NULL;
+ pos += sizeof(struct dvb_linkage_data_0c);
+
+ if (l_0c->table_type == 0x02) {
+ if ((len - pos) < 2)
+ return NULL;
+ bswap16(buf+pos);
+ }
+ }
+
+ return (struct dvb_linkage_descriptor*) d;
+}
+
+/**
+ * Accessor for the data field of a dvb_linkage_descriptor.
+ *
+ * @param d dvb_linkage_descriptor pointer.
+ * @return Pointer to the data field.
+ */
+static inline uint8_t *
+ dvb_linkage_descriptor_data(struct dvb_linkage_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_linkage_descriptor);
+}
+
+/**
+ * Determine the length of the data field of a dvb_linkage_descriptor.
+ *
+ * @param d dvb_linkage_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_linkage_descriptor_data_length(struct dvb_linkage_descriptor *d)
+{
+ return d->d.len - 7;
+}
+
+/**
+ * Accessor for a dvb_linkage_data_08 pointer.
+ *
+ * @param d dvb_linkage_descriptor pointer.
+ * @return Pointer to the data field.
+ */
+static inline struct dvb_linkage_data_08 *
+ dvb_linkage_data_08(struct dvb_linkage_descriptor *d)
+{
+ if (d->linkage_type != 0x08)
+ return NULL;
+ return (struct dvb_linkage_data_08 *) dvb_linkage_descriptor_data(d);
+}
+
+/**
+ * Accessor for the network_id field of a dvb_linkage_data_08.
+ *
+ * @param d dvb_linkage_descriptor pointer
+ * @param d08 dvb_linkage_data_08 pointer.
+ * @return network_id, or -1 if not present
+ */
+static inline int
+ dvb_linkage_data_08_network_id(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08)
+{
+ if (d->linkage_type != 0x08)
+ return -1;
+
+ switch(d08->hand_over_type) {
+ case 1:
+ case 2:
+ case 3:
+ return *((uint16_t*) ((uint8_t*) d08 + sizeof(struct dvb_linkage_data_08)));
+ }
+
+ return -1;
+}
+
+/**
+ * Accessor for the initial_service_id field of a dvb_linkage_data_08.
+ *
+ * @param d dvb_linkage_descriptor pointer
+ * @param d08 dvb_linkage_data_08 pointer.
+ * @return initial_service_id, or -1 if not present
+ */
+static inline int
+ dvb_linkage_data_08_initial_service_id(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08)
+{
+ uint8_t *pos;
+
+ if (d->linkage_type != 0x08)
+ return -1;
+ if (d08->origin_type != 0)
+ return -1;
+
+ pos = ((uint8_t*) d08) + sizeof(struct dvb_linkage_data_08);
+ switch(d08->hand_over_type) {
+ case 1:
+ case 2:
+ case 3:
+ pos +=2;
+ break;
+ }
+
+ return *((uint16_t*) pos);
+}
+
+/**
+ * Accessor for the data field of a dvb_linkage_data_08.
+ *
+ * @param d dvb_linkage_descriptor pointer
+ * @param d08 dvb_linkage_data_08 pointer.
+ * @param length Pointer to int destination for data length.
+ * @return Pointer to the data field, or NULL if invalid
+ */
+static inline uint8_t *
+ dvb_linkage_data_08_data(struct dvb_linkage_descriptor *d, struct dvb_linkage_data_08 *d08, int *length)
+{
+ uint8_t *pos;
+ int used = 0;
+
+ if (d->linkage_type != 0x08) {
+ *length = 0;
+ return NULL;
+ }
+
+ pos = ((uint8_t*) d08) + sizeof(struct dvb_linkage_data_08);
+ switch(d08->hand_over_type) {
+ case 1:
+ case 2:
+ case 3:
+ pos += 2;
+ used += 2;
+ break;
+ }
+ if (d08->origin_type == 0) {
+ pos+=2;
+ used+=2;
+ }
+
+ *length = dvb_linkage_descriptor_data_length(d) - (sizeof(struct dvb_linkage_data_08) + used);
+ return pos;
+}
+
+/**
+ * Accessor for a dvb_linkage_data_0b pointer.
+ *
+ * @param d dvb_linkage_descriptor pointer.
+ * @return Pointer to the data field.
+ */
+static inline struct dvb_linkage_data_0b *
+ dvb_linkage_data_0b(struct dvb_linkage_descriptor *d)
+{
+ if (d->linkage_type != 0x0b)
+ return NULL;
+ return (struct dvb_linkage_data_0b *) dvb_linkage_descriptor_data(d);
+}
+
+/**
+ * Iterator for the platform_id field of a dvb_linkage_data_0b.
+ *
+ * @param linkage dvb_linkage_data_0b pointer.
+ * @param pos Variable containing a pointer to the current dvb_platform_id.
+ */
+#define dvb_linkage_data_0b_platform_id_for_each(linkage, pos) \
+ for ((pos) = dvb_platform_id_first(linkage); \
+ (pos); \
+ (pos) = dvb_platform_id_next(linkage, pos))
+
+/**
+ * Iterator for the platform_name field of a dvb_platform_id.
+ *
+ * @param platid dvb_platform_id pointer.
+ * @param pos Variable containing a pointer to the current dvb_platform_name.
+ */
+#define dvb_platform_id_platform_name_for_each(platid, pos) \
+ for ((pos) = dvb_platform_name_first(platid); \
+ (pos); \
+ (pos) = dvb_platform_name_next(platid, pos))
+
+/**
+ * Accessor for the text field of a dvb_platform_name.
+ *
+ * @param p dvb_platform_name pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_platform_name_text(struct dvb_platform_name *p)
+{
+ return (uint8_t *) p + sizeof(struct dvb_platform_name);
+}
+
+/**
+ * Accessor for a dvb_linkage_data_0c pointer.
+ *
+ * @param d dvb_linkage_descriptor pointer.
+ * @return Pointer to the data field.
+ */
+static inline struct dvb_linkage_data_0c *
+ dvb_linkage_data_0c(struct dvb_linkage_descriptor *d)
+{
+ if (d->linkage_type != 0x0c)
+ return NULL;
+ return (struct dvb_linkage_data_0c *) dvb_linkage_descriptor_data(d);
+}
+
+/**
+ * Accessor for the bouquet_id field of a dvb_linkage_data_0c if table_id == 0x02.
+ *
+ * @param l_0c dvb_linkage_data_0c pointer.
+ * @return The bouquet field, or -1 on error.
+ */
+static inline int
+ dvb_linkage_data_0c_bouquet_id(struct dvb_linkage_data_0c *l_0c)
+{
+ if (l_0c->table_type != 0x02)
+ return -1;
+
+ return *((uint16_t *) ((uint8_t*) l_0c + 1));
+}
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_platform_id *
+ dvb_platform_id_first(struct dvb_linkage_data_0b *d)
+{
+ if (d->platform_id_data_length == 0)
+ return NULL;
+
+ return (struct dvb_platform_id *) ((uint8_t *) d + sizeof(struct dvb_linkage_data_0b));
+}
+
+static inline struct dvb_platform_id *
+ dvb_platform_id_next(struct dvb_linkage_data_0b *d,
+ struct dvb_platform_id *pos)
+{
+ uint8_t *end = (uint8_t *) d + d->platform_id_data_length;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_platform_id) +
+ pos->platform_name_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_platform_id *) next;
+}
+
+static inline struct dvb_platform_name *
+ dvb_platform_name_first(struct dvb_platform_id *p)
+{
+ if (p->platform_name_loop_length == 0)
+ return NULL;
+
+ return (struct dvb_platform_name *) ((uint8_t *) p + sizeof(struct dvb_platform_id));
+}
+
+static inline struct dvb_platform_name *
+ dvb_platform_name_next(struct dvb_platform_id *p,
+ struct dvb_platform_name *pos)
+{
+ uint8_t *end = (uint8_t *) p + p->platform_name_loop_length;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_platform_name) +
+ pos->platform_name_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_platform_name *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/local_time_offset_descriptor.h b/lib/libucsi/dvb/local_time_offset_descriptor.h
new file mode 100644
index 0000000..d0eebb3
--- /dev/null
+++ b/lib/libucsi/dvb/local_time_offset_descriptor.h
@@ -0,0 +1,127 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR
+#define _UCSI_DVB_LOCAL_TIME_OFFSET_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+#include <libucsi/dvb/types.h>
+
+/**
+ * dvb_local_time_offset_descriptor parameter.
+ */
+struct dvb_local_time_offset_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_local_time_offset offsets[] */
+} __ucsi_packed;
+
+/**
+ * Entry in the offsets field of dvb_local_time_offset_descriptor.
+ */
+struct dvb_local_time_offset {
+ iso639country_t country_code;
+ EBIT3(uint8_t country_region_id : 6; ,
+ uint8_t reserved : 1; ,
+ uint8_t local_time_offset_polarity : 1; );
+ dvbhhmm_t local_time_offset;
+ dvbdate_t time_of_change;
+ dvbhhmm_t next_time_offset;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_local_time_offset_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_local_time_offset_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_local_time_offset_descriptor*
+ dvb_local_time_offset_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+ uint32_t pos = 0;
+
+ if (len % sizeof(struct dvb_local_time_offset))
+ return NULL;
+
+ while(pos < len) {
+ pos += sizeof(struct dvb_local_time_offset);
+ }
+
+ return (struct dvb_local_time_offset_descriptor*) d;
+}
+
+/**
+ * Iterator for the offsets field of a dvb_local_time_offset_descriptor.
+ *
+ * @param d dvb_local_time_offset_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_local_time_offset.
+ */
+#define dvb_local_time_offset_descriptor_offsets_for_each(d, pos) \
+ for ((pos) = dvb_local_time_offset_descriptor_offsets_first(d); \
+ (pos); \
+ (pos) = dvb_local_time_offset_descriptor_offsets_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_local_time_offset*
+ dvb_local_time_offset_descriptor_offsets_first(struct dvb_local_time_offset_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_local_time_offset *)
+ ((uint8_t*) d + sizeof(struct dvb_local_time_offset_descriptor));
+}
+
+static inline struct dvb_local_time_offset*
+ dvb_local_time_offset_descriptor_offsets_next(struct dvb_local_time_offset_descriptor *d,
+ struct dvb_local_time_offset *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_local_time_offset);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_local_time_offset *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h b/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h
new file mode 100644
index 0000000..d79b48c
--- /dev/null
+++ b/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h
@@ -0,0 +1,110 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MHP_DATA_BROADCAST_ID_DESCRIPTOR
+#define _UCSI_DVB_MHP_DATA_BROADCAST_ID_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifndef _UCSI_DVB_DATA_BROADCAST_ID_DESCRIPTOR
+#error Must include dvb/data_broadcast_id_descriptor.h first
+#endif
+
+/**
+ * Broadcast IDs for MHP.
+ */
+enum {
+ DVB_BROADCAST_ID_MHP_OBJECT_CAROUSEL = 0x00f0,
+ DVB_BROADCAST_ID_MHP_MPE = 0x00f1,
+};
+
+/**
+ * dvb_mhp_data_broadcast_id_descriptor structure.
+ */
+struct dvb_mhp_data_broadcast_id_descriptor {
+ struct dvb_data_broadcast_id_descriptor d;
+ /* uint16_t application_type[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_mhp_data_broadcast_id_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_mhp_data_broadcast_id_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_mhp_data_broadcast_id_descriptor*
+ dvb_mhp_data_broadcast_id_descriptor_codec(struct dvb_data_broadcast_id_descriptor* d)
+{
+ uint8_t * buf;
+ int len;
+ int pos = 0;
+ struct dvb_mhp_data_broadcast_id_descriptor *res =
+ (struct dvb_mhp_data_broadcast_id_descriptor *) d;
+
+ if ((res->d.data_broadcast_id < 0xf0) || (res->d.data_broadcast_id > 0xfe))
+ return NULL;
+
+ buf = dvb_data_broadcast_id_descriptor_id_selector_byte(d);
+ len = dvb_data_broadcast_id_descriptor_id_selector_byte_length(d);
+
+ if (len % 2)
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos+=2;
+ }
+
+ return res;
+}
+
+/**
+ * Accessor for the application_type field of a dvb_mhp_data_broadcast_id_descriptor.
+ *
+ * @param d dvb_mhp_data_broadcast_id_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint16_t *
+ dvb_mhp_data_broadcast_id_descriptor_id_application_type(struct dvb_mhp_data_broadcast_id_descriptor *d)
+{
+ return (uint16_t *) dvb_data_broadcast_id_descriptor_id_selector_byte((struct dvb_data_broadcast_id_descriptor*) d);
+}
+
+/**
+ * Determine the number of entries in the application_type field of a dvb_mhp_data_broadcast_id_descriptor.
+ *
+ * @param d dvb_data_broadcast_id_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_mhp_data_broadcast_id_descriptor_id_application_type_count(struct dvb_mhp_data_broadcast_id_descriptor *d)
+{
+ return dvb_data_broadcast_id_descriptor_id_selector_byte_length((struct dvb_data_broadcast_id_descriptor*) d) >> 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/mosaic_descriptor.h b/lib/libucsi/dvb/mosaic_descriptor.h
new file mode 100644
index 0000000..6da1e95
--- /dev/null
+++ b/lib/libucsi/dvb/mosaic_descriptor.h
@@ -0,0 +1,324 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MOSAIC_DESCRIPTOR
+#define _UCSI_DVB_MOSAIC_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_mosaic_descriptor structure.
+ */
+struct dvb_mosaic_descriptor {
+ struct descriptor d;
+
+ EBIT4(uint8_t mosaic_entry_point : 1; ,
+ uint8_t number_of_horiz_elementary_cells: 3; ,
+ uint8_t reserved : 1; ,
+ uint8_t number_of_vert_elementary_cells : 3; );
+ /* struct dvb_mosaic_info infos[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the infos field of a dvb_mosaic_descriptor.
+ */
+struct dvb_mosaic_info {
+ EBIT3(uint16_t logical_cell_id : 6; ,
+ uint16_t reserved : 7; ,
+ uint16_t logical_cell_presentation_info : 3; );
+ uint8_t elementary_cell_field_length;
+ /* struct dvb_mosaic_elementary_cell_field fields[] */
+ /* struct dvb_mosaic_info_part2 part2 */
+ /* struct dvb_mosaic_linkage linkage */
+} __ucsi_packed;
+
+/**
+ * An entry in the fields field of a dvb_mosaic_info.
+ */
+struct dvb_mosaic_elementary_cell_field {
+ EBIT2(uint8_t reserved : 2; ,
+ uint8_t elementary_cell_id : 6; );
+} __ucsi_packed;
+
+/**
+ * Part2 of dvb_mosaic_info, following the variable length fields field.
+ */
+struct dvb_mosaic_info_part2 {
+ uint8_t cell_linkage_info;
+} __ucsi_packed;
+
+struct dvb_mosaic_linkage_01 {
+ uint16_t bouquet_id;
+} __ucsi_packed;
+
+struct dvb_mosaic_linkage_02 {
+ uint16_t original_network_id;
+ uint16_t transport_stream_id;
+ uint16_t service_id;
+} __ucsi_packed;
+
+struct dvb_mosaic_linkage_03 {
+ uint16_t original_network_id;
+ uint16_t transport_stream_id;
+ uint16_t service_id;
+} __ucsi_packed;
+
+struct dvb_mosaic_linkage_04 {
+ uint16_t original_network_id;
+ uint16_t transport_stream_id;
+ uint16_t service_id;
+ uint16_t event_id;
+} __ucsi_packed;
+
+/**
+ * Structure describing the linkage field of a dvb_mosaic_info
+ */
+struct dvb_mosaic_linkage {
+ union {
+ struct dvb_mosaic_linkage_01 linkage_01;
+ struct dvb_mosaic_linkage_02 linkage_02;
+ struct dvb_mosaic_linkage_03 linkage_03;
+ struct dvb_mosaic_linkage_04 linkage_04;
+ } u;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_mosaic_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ */
+static inline struct dvb_mosaic_descriptor*
+ dvb_mosaic_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+ struct dvb_mosaic_descriptor * p =
+ (struct dvb_mosaic_descriptor *) d;
+
+ pos += (sizeof(struct dvb_mosaic_descriptor) - 2);
+
+ if (pos > len)
+ return NULL;
+
+ while(pos < len) {
+ struct dvb_mosaic_info *e =
+ (struct dvb_mosaic_info*) (buf+pos);
+ struct dvb_mosaic_info_part2 *e2;
+ struct dvb_mosaic_linkage *linkage;
+
+ if ((pos + sizeof(struct dvb_mosaic_info)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+
+ pos += sizeof(struct dvb_mosaic_info) +
+ e->elementary_cell_field_length;
+
+ if (pos > len)
+ return NULL;
+
+ e2 = (struct dvb_mosaic_info_part2*) (buf+pos);
+
+ pos += sizeof(struct dvb_mosaic_info_part2);
+
+ if (pos > len)
+ return NULL;
+
+ linkage = (struct dvb_mosaic_linkage*) (buf+pos);
+
+ switch(e2->cell_linkage_info) {
+ case 0x01:
+ if ((pos + sizeof(struct dvb_mosaic_linkage_01)) > len)
+ return NULL;
+ bswap16(buf+pos);
+ pos += sizeof(struct dvb_mosaic_linkage_01);
+ break;
+
+ case 0x02:
+ if ((pos + sizeof(struct dvb_mosaic_linkage_02)) > len)
+ return NULL;
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+ pos += sizeof(struct dvb_mosaic_linkage_02);
+ break;
+
+ case 0x03:
+ if ((pos + sizeof(struct dvb_mosaic_linkage_03)) > len)
+ return NULL;
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+ pos += sizeof(struct dvb_mosaic_linkage_03);
+ break;
+
+ case 0x04:
+ if ((pos + sizeof(struct dvb_mosaic_linkage_04)) > len)
+ return NULL;
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+ bswap16(buf+pos+6);
+ pos += sizeof(struct dvb_mosaic_linkage_04);
+ break;
+ }
+ }
+
+ return p;
+}
+
+/**
+ * Iterator over the infos field of a dvb_mosaic_descriptor.
+ *
+ * @param d dvb_mosaic_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_mosaic_info.
+ */
+#define dvb_mosaic_descriptor_infos_for_each(d, pos) \
+ for ((pos) = dvb_mosaic_descriptor_infos_first(d); \
+ (pos); \
+ (pos) = dvb_mosaic_descriptor_infos_next(d, pos))
+
+/**
+ * Iterator over the fields field of a dvb_mosaic_info.
+ *
+ * @param info dvb_mosaic_info pointer.
+ * @param pos Variable containing a pointer to the current dvb_mosaic_elementary_cell_field.
+ */
+#define dvb_mosaic_info_fields_for_each(info, pos) \
+ for ((pos) = dvb_mosaic_info_fields_first(info); \
+ (pos); \
+ (pos) = dvb_mosaic_info_fields_next(info, pos))
+
+/**
+ * Accessor for the second part of the dvb_mosaic_info structure.
+ *
+ * @param entry dvb_mosaic_info pointer.
+ * @return dvb_mosaic_info_part2 pointer.
+ */
+static inline struct dvb_mosaic_info_part2*
+ dvb_mosaic_info_part2(struct dvb_mosaic_info* entry)
+{
+ return (struct dvb_mosaic_info_part2*)
+ ((uint8_t*) entry + sizeof(struct dvb_mosaic_info) +
+ entry->elementary_cell_field_length);
+}
+
+/**
+ * Accessor for the linkage field a dvb_mosaic_info structure.
+ *
+ * @param entry dvb_mosaic_info_part2 pointer.
+ * @return dvb_mosaic_linkage pointer, or NULL on error.
+ */
+static inline struct dvb_mosaic_linkage*
+ dvb_mosaic_linkage(struct dvb_mosaic_info_part2* entry)
+{
+ if ((entry->cell_linkage_info != 0x01) &&
+ (entry->cell_linkage_info != 0x02) &&
+ (entry->cell_linkage_info != 0x03) &&
+ (entry->cell_linkage_info != 0x04))
+ return NULL;
+
+ return (struct dvb_mosaic_linkage*)
+ ((uint8_t*) entry + sizeof(struct dvb_mosaic_info_part2));
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_mosaic_info*
+ dvb_mosaic_descriptor_infos_first(struct dvb_mosaic_descriptor *d)
+{
+ if (d->d.len == 1)
+ return NULL;
+
+ return (struct dvb_mosaic_info *)
+ ((uint8_t*) d + sizeof(struct dvb_mosaic_descriptor));
+}
+
+static inline struct dvb_mosaic_info*
+ dvb_mosaic_descriptor_infos_next(struct dvb_mosaic_descriptor *d,
+ struct dvb_mosaic_info *pos)
+{
+ struct dvb_mosaic_info_part2* part2 = dvb_mosaic_info_part2(pos);
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_mosaic_info) +
+ pos->elementary_cell_field_length +
+ sizeof(struct dvb_mosaic_info_part2);
+
+ if (part2->cell_linkage_info == 0x01)
+ next += sizeof(struct dvb_mosaic_linkage_01);
+ else if (part2->cell_linkage_info == 0x02)
+ next += sizeof(struct dvb_mosaic_linkage_02);
+ else if (part2->cell_linkage_info == 0x03)
+ next += sizeof(struct dvb_mosaic_linkage_03);
+ else if (part2->cell_linkage_info == 0x04)
+ next += sizeof(struct dvb_mosaic_linkage_04);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_mosaic_info *) next;
+}
+
+static inline struct dvb_mosaic_elementary_cell_field*
+ dvb_mosaic_info_fields_first(struct dvb_mosaic_info *d)
+{
+ if (d->elementary_cell_field_length == 0)
+ return NULL;
+
+ return (struct dvb_mosaic_elementary_cell_field*)
+ ((uint8_t*) d + sizeof(struct dvb_mosaic_info));
+}
+
+static inline struct dvb_mosaic_elementary_cell_field*
+ dvb_mosaic_info_fields_next(struct dvb_mosaic_info *d,
+ struct dvb_mosaic_elementary_cell_field* pos)
+{
+ uint8_t *end = (uint8_t*) d + sizeof(struct dvb_mosaic_info) +
+ d->elementary_cell_field_length;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_mosaic_elementary_cell_field);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_mosaic_elementary_cell_field *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h b/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h
new file mode 100644
index 0000000..0d8deb1
--- /dev/null
+++ b/lib/libucsi/dvb/multilingual_bouquet_name_descriptor.h
@@ -0,0 +1,145 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR
+#define _UCSI_DVB_MULTILINGUAL_BOUQUET_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_multilingual_bouquet_name_descriptor structure.
+ */
+struct dvb_multilingual_bouquet_name_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_multilingual_bouquet_name names[]*/
+} __ucsi_packed;
+
+/**
+ * An entry in the names field of a dvb_multilingual_bouquet_name_descriptor.
+ */
+struct dvb_multilingual_bouquet_name {
+ iso639lang_t language_code;
+ uint8_t bouquet_name_length;
+ /* uint8_t name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_multilingual_bouquet_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_multilingual_bouquet_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_multilingual_bouquet_name_descriptor*
+ dvb_multilingual_bouquet_name_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_multilingual_bouquet_name *e =
+ (struct dvb_multilingual_bouquet_name*) (buf+pos);
+
+ pos += sizeof(struct dvb_multilingual_bouquet_name);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->bouquet_name_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_multilingual_bouquet_name_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the names field of a dvb_multilingual_bouquet_name_descriptor.
+ *
+ * @param d dvb_multilingual_bouquet_name_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_multilingual_bouquet_name.
+ */
+#define dvb_multilingual_bouquet_name_descriptor_names_for_each(d, pos) \
+ for ((pos) = dvb_multilingual_bouquet_name_descriptor_names_first(d); \
+ (pos); \
+ (pos) = dvb_multilingual_bouquet_name_descriptor_names_next(d, pos))
+
+/**
+ * Accessor for the name field of a dvb_multilingual_bouquet_name.
+ *
+ * @param e dvb_multilingual_bouquet_name pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_multilingual_bouquet_name_name(struct dvb_multilingual_bouquet_name *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_multilingual_bouquet_name);
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_multilingual_bouquet_name*
+ dvb_multilingual_bouquet_name_descriptor_names_first(struct dvb_multilingual_bouquet_name_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_multilingual_bouquet_name *)
+ ((uint8_t*) d + sizeof(struct dvb_multilingual_bouquet_name_descriptor));
+}
+
+static inline struct dvb_multilingual_bouquet_name*
+ dvb_multilingual_bouquet_name_descriptor_names_next(struct dvb_multilingual_bouquet_name_descriptor *d,
+ struct dvb_multilingual_bouquet_name *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_multilingual_bouquet_name) +
+ pos->bouquet_name_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_multilingual_bouquet_name *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/multilingual_component_descriptor.h b/lib/libucsi/dvb/multilingual_component_descriptor.h
new file mode 100644
index 0000000..ab156af
--- /dev/null
+++ b/lib/libucsi/dvb/multilingual_component_descriptor.h
@@ -0,0 +1,149 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MULTILINGUAL_COMPONENT_DESCRIPTOR
+#define _UCSI_DVB_MULTILINGUAL_COMPONENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_multilingual_component_descriptor structure.
+ */
+struct dvb_multilingual_component_descriptor {
+ struct descriptor d;
+
+ uint8_t component_tag;
+ /* struct dvb_multilingual_component components[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the components field of a dvb_multilingual_component_descriptor.
+ */
+struct dvb_multilingual_component {
+ iso639lang_t language_code;
+ uint8_t text_description_length;
+ /* uint8_t text_char[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_multilingual_component_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_multilingual_component_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_multilingual_component_descriptor*
+ dvb_multilingual_component_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = sizeof(struct dvb_multilingual_component_descriptor) - 2;
+ uint32_t len = d->len;
+
+ if (pos > len)
+ return NULL;
+
+ while(pos < len) {
+ struct dvb_multilingual_component *e =
+ (struct dvb_multilingual_component*) (buf+pos);
+
+ pos += sizeof(struct dvb_multilingual_component);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->text_description_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_multilingual_component_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the components field of a dvb_multilingual_component_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_multilingual_component.
+ */
+#define dvb_multilingual_component_descriptor_components_for_each(d, pos) \
+ for ((pos) = dvb_multilingual_component_descriptor_components_first(d); \
+ (pos); \
+ (pos) = dvb_multilingual_component_descriptor_components_next(d, pos))
+
+/**
+ * Accessor for the text_char field in a dvb_multilingual_component.
+ *
+ * @param e dvb_multilingual_component pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_multilingual_component_text_char(struct dvb_multilingual_component *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_multilingual_component);
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_multilingual_component*
+ dvb_multilingual_component_descriptor_components_first(struct dvb_multilingual_component_descriptor *d)
+{
+ if (d->d.len == 1)
+ return NULL;
+
+ return (struct dvb_multilingual_component *)
+ ((uint8_t*) d + sizeof(struct dvb_multilingual_component_descriptor));
+}
+
+static inline struct dvb_multilingual_component*
+ dvb_multilingual_component_descriptor_components_next(struct dvb_multilingual_component_descriptor *d,
+ struct dvb_multilingual_component *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_multilingual_component) +
+ pos->text_description_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_multilingual_component *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/multilingual_network_name_descriptor.h b/lib/libucsi/dvb/multilingual_network_name_descriptor.h
new file mode 100644
index 0000000..1a7b8c4
--- /dev/null
+++ b/lib/libucsi/dvb/multilingual_network_name_descriptor.h
@@ -0,0 +1,145 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MULTILINGUAL_NETWORK_NAME_DESCRIPTOR
+#define _UCSI_DVB_MULTILINGUAL_NETWORK_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_multilingual_network_name_descriptor structure.
+ */
+struct dvb_multilingual_network_name_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_multilingual_network_name names[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the names field of a dvb_multilingual_network_name_descriptor.
+ */
+struct dvb_multilingual_network_name {
+ iso639lang_t language_code;
+ uint8_t network_name_length;
+ /* uint8_t name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_multilingual_network_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_multilingual_network_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_multilingual_network_name_descriptor*
+ dvb_multilingual_network_name_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_multilingual_network_name *e =
+ (struct dvb_multilingual_network_name*) (buf + pos);
+
+ pos += sizeof(struct dvb_multilingual_network_name);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->network_name_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_multilingual_network_name_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the names field of a dvb_multilingual_network_name_descriptor.
+ *
+ * @param d dvb_multilingual_network_name_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_multilingual_network_name.
+ */
+#define dvb_multilingual_network_name_descriptor_names_for_each(d, pos) \
+ for ((pos) = dvb_multilingual_network_name_descriptor_names_first(d); \
+ (pos); \
+ (pos) = dvb_multilingual_network_name_descriptor_names_next(d, pos))
+
+/**
+ * Accessor for the name field of a dvb_multilingual_network_name.
+ *
+ * @param e dvb_multilingual_network_name pointer.
+ * @return Pointer to the name field.
+ */
+static inline uint8_t *
+ dvb_multilingual_network_name_name(struct dvb_multilingual_network_name *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_multilingual_network_name);
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_multilingual_network_name*
+ dvb_multilingual_network_name_descriptor_names_first(struct dvb_multilingual_network_name_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_multilingual_network_name *)
+ ((uint8_t*) d + sizeof(struct dvb_multilingual_network_name_descriptor));
+}
+
+static inline struct dvb_multilingual_network_name*
+ dvb_multilingual_network_name_descriptor_names_next(struct dvb_multilingual_network_name_descriptor *d,
+ struct dvb_multilingual_network_name *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos +
+ sizeof(struct dvb_multilingual_network_name) +
+ pos->network_name_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_multilingual_network_name *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/multilingual_service_name_descriptor.h b/lib/libucsi/dvb/multilingual_service_name_descriptor.h
new file mode 100644
index 0000000..31bb9c3
--- /dev/null
+++ b/lib/libucsi/dvb/multilingual_service_name_descriptor.h
@@ -0,0 +1,197 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_MULTILINGUAL_SERVICE_NAME_DESCRIPTOR
+#define _UCSI_DVB_MULTILINGUAL_SERVICE_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_multilingual_service_name_descriptor structure.
+ */
+struct dvb_multilingual_service_name_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_multilingual_service_name names[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the service_names field of a dvb_multilingual_service_name_descriptor.
+ */
+struct dvb_multilingual_service_name {
+ iso639lang_t language_code;
+ uint8_t service_provider_name_length;
+ /* uint8_t service_provider_name[] */
+ /* struct dvb_multilingual_service_name_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_multilingual_service_name following the variable length
+ * service_provider_name.
+ */
+struct dvb_multilingual_service_name_part2 {
+ uint8_t service_name_length;
+ /* uint8_t service_name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_multilingual_service_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_multilingual_service_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_multilingual_service_name_descriptor*
+ dvb_multilingual_service_name_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_multilingual_service_name *e =
+ (struct dvb_multilingual_service_name*) (buf+pos);
+ struct dvb_multilingual_service_name_part2 *e2;
+
+ pos += sizeof(struct dvb_multilingual_service_name);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->service_provider_name_length;
+
+ if (pos > len)
+ return NULL;
+
+ e2 = (struct dvb_multilingual_service_name_part2*) (buf+pos);
+
+ pos += sizeof(struct dvb_multilingual_service_name_part2);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e2->service_name_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_multilingual_service_name_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the service_name field of a dvb_multilingual_service_name_descriptor.
+ *
+ * @param d dvb_multilingual_service_name_descriptor pointer,
+ * @param pos Variable containing pointer to the current dvb_multilingual_service_name.
+ */
+#define dvb_multilingual_service_name_descriptor_names_for_each(d, pos) \
+ for ((pos) = dvb_multilingual_service_name_descriptor_names_first(d); \
+ (pos); \
+ (pos) = dvb_multilingual_service_name_descriptor_names_next(d, pos))
+
+/**
+ * Accessor for the service_provider_name field of a dvb_multilingual_service_name.
+ *
+ * @param e dvb_multilingual_service_name pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_multilingual_service_name_service_provider_name(struct dvb_multilingual_service_name *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_multilingual_service_name);
+}
+
+/**
+ * Accessor for the dvb_multilingual_service_name_part2 - second part of a
+ * dvb_multilingual_service_name following the service_name field.
+ *
+ * @param e dvb_multilingual_service_name Pointer.
+ * @return dvb_multilingual_service_name_part2 pointer.
+ */
+static inline struct dvb_multilingual_service_name_part2 *
+ dvb_multilingual_service_name_part2(struct dvb_multilingual_service_name *e)
+{
+ return (struct dvb_multilingual_service_name_part2 *)
+ ((uint8_t *) e + sizeof(struct dvb_multilingual_service_name) +
+ e->service_provider_name_length);
+}
+
+/**
+ * Accessor for the service_name field of a dvb_multilingual_service_name_part2.
+ *
+ * @param e dvb_multilingual_service_name_part2 pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_multilingual_service_name_service_name(struct dvb_multilingual_service_name_part2 *e)
+{
+ return (uint8_t *) e + sizeof(struct dvb_multilingual_service_name_part2);
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_multilingual_service_name*
+ dvb_multilingual_service_name_descriptor_names_first(struct dvb_multilingual_service_name_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_multilingual_service_name *)
+ ((uint8_t*) d + sizeof(struct dvb_multilingual_service_name_descriptor));
+}
+
+static inline struct dvb_multilingual_service_name*
+ dvb_multilingual_service_name_descriptor_names_next(struct dvb_multilingual_service_name_descriptor *d,
+ struct dvb_multilingual_service_name *pos)
+{
+ struct dvb_multilingual_service_name_part2 * part2 =
+ dvb_multilingual_service_name_part2(pos);
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) part2+
+ sizeof(struct dvb_multilingual_service_name_part2) +
+ part2->service_name_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_multilingual_service_name *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/network_name_descriptor.h b/lib/libucsi/dvb/network_name_descriptor.h
new file mode 100644
index 0000000..0754597
--- /dev/null
+++ b/lib/libucsi/dvb/network_name_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_NETWORK_NAME_DESCRIPTOR
+#define _UCSI_DVB_NETWORK_NAME_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_network_name_descriptor structure.
+ */
+struct dvb_network_name_descriptor {
+ struct descriptor d;
+
+ /* char name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_network_name_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_network_name_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_network_name_descriptor*
+ dvb_network_name_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_network_name_descriptor*) d;
+}
+
+/**
+ * Accessor for the name field in a dvb_network_name_descriptor.
+ *
+ * @param d dvb_network_name_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_network_name_descriptor_name(struct dvb_network_name_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_network_name_descriptor);
+}
+
+/**
+ * Calculate the length of the name field in a dvb_network_name_descriptor.
+ *
+ * @param d dvb_network_name_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_network_name_descriptor_name_length(struct dvb_network_name_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/nit_section.c b/lib/libucsi/dvb/nit_section.c
new file mode 100644
index 0000000..664a0cb
--- /dev/null
+++ b/lib/libucsi/dvb/nit_section.c
@@ -0,0 +1,78 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/nit_section.h>
+
+struct dvb_nit_section *dvb_nit_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ struct dvb_nit_section * ret = (struct dvb_nit_section *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct dvb_nit_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+
+ if ((pos + ret->network_descriptors_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, ret->network_descriptors_length))
+ return NULL;
+
+ pos += ret->network_descriptors_length;
+
+ if ((pos + sizeof(struct dvb_nit_section_part2)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+
+ while (pos < len) {
+ struct dvb_nit_transport *transport =
+ (struct dvb_nit_transport *)(buf + pos);
+
+ if ((pos + sizeof(struct dvb_nit_transport)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 2);
+ bswap16(buf + pos + 4);
+
+ pos += sizeof(struct dvb_nit_transport);
+
+ if ((pos + transport->transport_descriptors_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos,
+ transport->transport_descriptors_length))
+ return NULL;
+
+ pos += transport->transport_descriptors_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/nit_section.h b/lib/libucsi/dvb/nit_section.h
new file mode 100644
index 0000000..77ab1a0
--- /dev/null
+++ b/lib/libucsi/dvb/nit_section.h
@@ -0,0 +1,207 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_NIT_SECTION_H
+#define _UCSI_DVB_NIT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_nit_section structure.
+ */
+struct dvb_nit_section {
+ struct section_ext head;
+
+ EBIT2(uint16_t reserved_1 : 4; ,
+ uint16_t network_descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+ /* struct dvb_nit_section_part2 part2 */
+};
+
+/**
+ * Second part of a dvb_nit_section, following the variable length descriptors field.
+ */
+struct dvb_nit_section_part2 {
+ EBIT2(uint16_t reserved_2 : 4; ,
+ uint16_t transport_stream_loop_length :12; );
+ /* struct dvb_nit_transport transports[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the transports field of a dvb_nit_section_part2
+ */
+struct dvb_nit_transport {
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t transport_descriptors_length :12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_nit_section.
+ *
+ * @param section Generic section_ext pointer.
+ * @return dvb_nit_section pointer, or NULL on error.
+ */
+struct dvb_nit_section * dvb_nit_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the network_id field of a NIT.
+ *
+ * @param nit NIT pointer.
+ * @return The network_id.
+ */
+static inline uint16_t dvb_nit_section_network_id(struct dvb_nit_section *nit)
+{
+ return nit->head.table_id_ext;
+}
+
+/**
+ * Iterator over the descriptors field in a dvb_nit_section.
+ *
+ * @param nit dvb_nit_section pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define dvb_nit_section_descriptors_for_each(nit, pos) \
+ for ((pos) = dvb_nit_section_descriptors_first(nit); \
+ (pos); \
+ (pos) = dvb_nit_section_descriptors_next(nit, pos))
+
+/**
+ * Accessor for a pointer to the dvb_nit_section_part2 structure.
+ *
+ * @param nit dvb_nit_section pointer.
+ * @return dvb_nit_section_part2 pointer.
+ */
+static inline struct dvb_nit_section_part2 *dvb_nit_section_part2(struct dvb_nit_section * nit)
+{
+ return (struct dvb_nit_section_part2 *)
+ ((uint8_t*) nit + sizeof(struct dvb_nit_section) +
+ nit->network_descriptors_length);
+}
+
+/**
+ * Iterator over the transports field in a dvb_nit_section_part2.
+ *
+ * @param nit dvb_nit_section pointer.
+ * @param part2 dvb_nit_section_part2 pointer.
+ * @param pos Pointer to the current dvb_nit_transport.
+ */
+#define dvb_nit_section_transports_for_each(nit, part2, pos) \
+ for ((pos) = dvb_nit_section_transports_first(part2); \
+ (pos); \
+ (pos) = dvb_nit_section_transports_next(part2, pos))
+
+/**
+ * Iterator over the descriptors field in a dvb_nit_transport.
+ *
+ * @param transport dvb_nit_transport pointer.
+ * @param pos Pointer to the current descriptor.
+ */
+#define dvb_nit_transport_descriptors_for_each(transport, pos) \
+ for ((pos) = dvb_nit_transport_descriptors_first(transport); \
+ (pos); \
+ (pos) = dvb_nit_transport_descriptors_next(transport, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ dvb_nit_section_descriptors_first(struct dvb_nit_section * nit)
+{
+ if (nit->network_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) nit + sizeof(struct dvb_nit_section));
+}
+
+static inline struct descriptor *
+ dvb_nit_section_descriptors_next(struct dvb_nit_section * nit,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) nit + sizeof(struct dvb_nit_section),
+ nit->network_descriptors_length,
+ pos);
+}
+
+static inline struct dvb_nit_transport *
+ dvb_nit_section_transports_first(struct dvb_nit_section_part2 *part2)
+{
+ if (part2->transport_stream_loop_length == 0)
+ return NULL;
+
+ return (struct dvb_nit_transport *)
+ ((uint8_t *)part2 + sizeof(struct dvb_nit_section_part2));
+}
+
+static inline struct dvb_nit_transport *
+ dvb_nit_section_transports_next(struct dvb_nit_section_part2 *part2,
+ struct dvb_nit_transport *pos)
+{
+ uint8_t *end = (uint8_t*) part2 + sizeof(struct dvb_nit_section_part2) +
+ part2->transport_stream_loop_length;
+ uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_nit_transport) +
+ pos->transport_descriptors_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_nit_transport *) next;
+}
+
+static inline struct descriptor *
+ dvb_nit_transport_descriptors_first(struct dvb_nit_transport *t)
+{
+ if (t->transport_descriptors_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*) t + sizeof(struct dvb_nit_transport));
+}
+
+static inline struct descriptor *
+ dvb_nit_transport_descriptors_next(struct dvb_nit_transport *t,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) t + sizeof(struct dvb_nit_transport),
+ t->transport_descriptors_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/nvod_reference_descriptor.h b/lib/libucsi/dvb/nvod_reference_descriptor.h
new file mode 100644
index 0000000..6180514
--- /dev/null
+++ b/lib/libucsi/dvb/nvod_reference_descriptor.h
@@ -0,0 +1,125 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_NVOD_REFERENCE_DESCRIPTOR
+#define _UCSI_DVB_NVOD_REFERENCE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_nvod_reference_descriptor structure.
+ */
+struct dvb_nvod_reference_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_nvod_reference references[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the references field of a dvb_nvod_reference_descriptor.
+ */
+struct dvb_nvod_reference {
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint16_t service_id;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_nvod_reference_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure pointer.
+ * @return dvb_nvod_reference_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_nvod_reference_descriptor*
+ dvb_nvod_reference_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_nvod_reference))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ bswap16(buf+pos+4);
+ pos += sizeof(struct dvb_nvod_reference);
+ }
+
+ return (struct dvb_nvod_reference_descriptor*) d;
+}
+
+/**
+ * Iterator over the references field in a dvb_nvod_reference_descriptor.
+ *
+ * @param d dvb_nvod_reference_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_nvod_reference.
+ */
+#define dvb_nvod_reference_descriptor_references_for_each(d, pos) \
+ for ((pos) = dvb_nvod_reference_descriptor_references_first(d); \
+ (pos); \
+ (pos) = dvb_nvod_reference_descriptor_references_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_nvod_reference*
+ dvb_nvod_reference_descriptor_references_first(struct dvb_nvod_reference_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_nvod_reference *)
+ ((uint8_t*) d + sizeof(struct dvb_nvod_reference_descriptor));
+}
+
+static inline struct dvb_nvod_reference*
+ dvb_nvod_reference_descriptor_references_next(struct dvb_nvod_reference_descriptor *d,
+ struct dvb_nvod_reference *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_nvod_reference);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_nvod_reference *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/parental_rating_descriptor.h b/lib/libucsi/dvb/parental_rating_descriptor.h
new file mode 100644
index 0000000..72ecd0a
--- /dev/null
+++ b/lib/libucsi/dvb/parental_rating_descriptor.h
@@ -0,0 +1,135 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_PARENTAL_RATING_DESCRIPTOR
+#define _UCSI_DVB_PARENTAL_RATING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Defined values for the rating field.
+ */
+enum {
+ DVB_PARENTAL_RATING_MIN_3YEARS = 0x01,
+ DVB_PARENTAL_RATING_MIN_4YEARS = 0x02,
+ DVB_PARENTAL_RATING_MIN_5YEARS = 0x03,
+ DVB_PARENTAL_RATING_MIN_6YEARS = 0x04,
+ DVB_PARENTAL_RATING_MIN_7YEARS = 0x05,
+ DVB_PARENTAL_RATING_MIN_8YEARS = 0x06,
+ DVB_PARENTAL_RATING_MIN_9YEARS = 0x07,
+ DVB_PARENTAL_RATING_MIN_10YEARS = 0x08,
+ DVB_PARENTAL_RATING_MIN_11YEARS = 0x09,
+ DVB_PARENTAL_RATING_MIN_12YEARS = 0x0a,
+ DVB_PARENTAL_RATING_MIN_13YEARS = 0x0b,
+ DVB_PARENTAL_RATING_MIN_14YEARS = 0x0c,
+ DVB_PARENTAL_RATING_MIN_15YEARS = 0x0d,
+ DVB_PARENTAL_RATING_MIN_16YEARS = 0x0e,
+ DVB_PARENTAL_RATING_MIN_17YEARS = 0x0f,
+};
+
+/**
+ * dvb_parental_rating_descriptor structure.
+ */
+struct dvb_parental_rating_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_parental_rating ratings[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ratings field of a dvb_parental_rating_descriptor.
+ */
+struct dvb_parental_rating {
+ iso639country_t country_code;
+ uint8_t rating;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_parental_rating_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_parental_rating_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_parental_rating_descriptor*
+ dvb_parental_rating_descriptor_codec(struct descriptor* d)
+{
+ if (d->len % sizeof(struct dvb_parental_rating))
+ return NULL;
+
+ return (struct dvb_parental_rating_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ratings field of a dvb_parental_rating_descriptor.
+ *
+ * @param d dvb_parental_rating_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_parental_rating.
+ */
+#define dvb_parental_rating_descriptor_ratings_for_each(d, pos) \
+ for ((pos) = dvb_parental_rating_descriptor_ratings_first(d); \
+ (pos); \
+ (pos) = dvb_parental_rating_descriptor_ratings_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_parental_rating*
+ dvb_parental_rating_descriptor_ratings_first(struct dvb_parental_rating_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_parental_rating *)
+ ((uint8_t*) d + sizeof(struct dvb_parental_rating_descriptor));
+}
+
+static inline struct dvb_parental_rating*
+ dvb_parental_rating_descriptor_ratings_next(struct dvb_parental_rating_descriptor *d,
+ struct dvb_parental_rating *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_parental_rating);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_parental_rating *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/partial_transport_stream_descriptor.h b/lib/libucsi/dvb/partial_transport_stream_descriptor.h
new file mode 100644
index 0000000..6e3aa96
--- /dev/null
+++ b/lib/libucsi/dvb/partial_transport_stream_descriptor.h
@@ -0,0 +1,68 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_PARTIAL_TRANSPORT_STREAM_DESCRIPTOR
+#define _UCSI_DVB_PARTIAL_TRANSPORT_STREAM_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_partial_transport_stream_descriptor structure.
+ */
+struct dvb_partial_transport_stream_descriptor {
+ struct descriptor d;
+
+ EBIT6(uint64_t reserved : 2; ,
+ uint64_t peak_rate :22; ,
+ uint64_t reserved_2 : 2; ,
+ uint64_t minimum_overall_smoothing_rate :22; ,
+ uint64_t reserved_3 : 2; ,
+ uint64_t maximum_overall_smoothing_rate :14; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_partial_transport_stream_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_partial_transport_stream_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_partial_transport_stream_descriptor*
+ dvb_partial_transport_stream_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_partial_transport_stream_descriptor) - 2))
+ return NULL;
+
+ bswap64((uint8_t*) d + 2);
+
+ return (struct dvb_partial_transport_stream_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/pdc_descriptor.h b/lib/libucsi/dvb/pdc_descriptor.h
new file mode 100644
index 0000000..68190be
--- /dev/null
+++ b/lib/libucsi/dvb/pdc_descriptor.h
@@ -0,0 +1,64 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_PDC_DESCRIPTOR
+#define _UCSI_DVB_PDC_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_pdc_descriptor structure.
+ */
+struct dvb_pdc_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint32_t reserved : 4; ,
+ uint32_t programme_id_label :20; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_pdc_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return dvb_pdc_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_pdc_descriptor*
+ dvb_pdc_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_pdc_descriptor) - 2))
+ return NULL;
+
+ bswap24((uint8_t*) d + 2);
+
+ return (struct dvb_pdc_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/private_data_specifier_descriptor.h b/lib/libucsi/dvb/private_data_specifier_descriptor.h
new file mode 100644
index 0000000..f4cc03c
--- /dev/null
+++ b/lib/libucsi/dvb/private_data_specifier_descriptor.h
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR
+#define _UCSI_DVB_PRIVATE_DATA_SPECIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_private_data_specifier_descriptor structure.
+ */
+struct dvb_private_data_specifier_descriptor {
+ struct descriptor d;
+
+ uint32_t private_data_specifier;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_private_data_specifier_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_private_data_specifier_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_private_data_specifier_descriptor*
+ dvb_private_data_specifier_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_private_data_specifier_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct dvb_private_data_specifier_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/related_content_descriptor.h b/lib/libucsi/dvb/related_content_descriptor.h
new file mode 100644
index 0000000..fd6a358
--- /dev/null
+++ b/lib/libucsi/dvb/related_content_descriptor.h
@@ -0,0 +1,56 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_RELATED_CONTENT_DESCRIPTOR
+#define _UCSI_DVB_RELATED_CONTENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_related_content_descriptor structure.
+ */
+struct dvb_related_content_descriptor {
+ struct descriptor d;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_related_content_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_related_content_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_related_content_descriptor*
+ dvb_related_content_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_related_content_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h b/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h
new file mode 100644
index 0000000..ba42d12
--- /dev/null
+++ b/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h
@@ -0,0 +1,110 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_RNT_RAR_OVER_DVB_STREAM_DESCRIPTOR
+#define _UCSI_DVB_RNT_RAR_OVER_DVB_STREAM_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_rnt_rar_over_dvb_stream_descriptor structure.
+ */
+struct dvb_rnt_rar_over_dvb_stream_descriptor {
+ struct descriptor d;
+
+ dvbdate_t first_valid_date;
+ dvbdate_t last_valid_date;
+ EBIT3(uint8_t weighting : 6; ,
+ uint8_t complete_flag : 1; ,
+ uint8_t scheduled_flag : 1; );
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint16_t service_id;
+ uint8_t component_tag;
+ /* struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info scheduled_info */
+} __ucsi_packed;
+
+/**
+ * The scheduled_info field of a dvb_rnt_rar_over_dvb_stream_descriptor (only appears
+ * if scheduled_flag = 1).
+ */
+struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info {
+ dvbdate_t download_start_time;
+ uint8_t download_period_duration;
+ uint8_t download_cycle_time;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_rnt_rar_over_dvb_stream_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_rnt_rar_over_dvb_stream_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_rnt_rar_over_dvb_stream_descriptor*
+ dvb_rnt_rar_over_dvb_stream_descriptor_codec(struct descriptor* d)
+{
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len + 2;
+ struct dvb_rnt_rar_over_dvb_stream_descriptor *ret =
+ (struct dvb_rnt_rar_over_dvb_stream_descriptor *) buf;
+
+ if (len < sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor))
+ return NULL;
+
+ bswap16(buf + 13);
+ bswap16(buf + 15);
+ bswap16(buf + 17);
+
+ if (ret->scheduled_flag == 1) {
+ if (len < (sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor)+
+ sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info)))
+ return NULL;
+ }
+
+ return ret;
+}
+
+/**
+ * Accessor for the scheduled_info field of a dvb_rnt_rar_over_dvb_stream_descriptor.
+ *
+ * @param d dvb_rnt_rar_over_dvb_stream_descriptor pointer.
+ * @return Pointer, or NULL on error.
+ */
+static inline struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info*
+ dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info(struct dvb_rnt_rar_over_dvb_stream_descriptor *d)
+{
+ if (d->scheduled_flag != 1)
+ return NULL;
+ return (struct dvb_rnt_rar_over_dvb_stream_descriptor_scheduled_info*)
+ ((uint8_t*) d + sizeof(struct dvb_rnt_rar_over_dvb_stream_descriptor));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h b/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h
new file mode 100644
index 0000000..b1f2da4
--- /dev/null
+++ b/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h
@@ -0,0 +1,87 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_RNT_RAR_OVER_IP_DESCRIPTOR
+#define _UCSI_DVB_RNT_RAR_OVER_IP_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_rnt_rar_over_ip_descriptor structure.
+ */
+struct dvb_rnt_rar_over_ip_descriptor {
+ struct descriptor d;
+
+ dvbdate_t first_valid_date;
+ dvbdate_t last_valid_date;
+ EBIT3(uint8_t weighting : 6; ,
+ uint8_t complete_flag : 1; ,
+ uint8_t reserved : 1; );
+ uint8_t url_length;
+ /* uint8_t url[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_rnt_rar_over_ip_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_rnt_rar_over_ip_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_rnt_rar_over_ip_descriptor*
+ dvb_rnt_rar_over_ip_descriptor_codec(struct descriptor* d)
+{
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len + 2;
+ struct dvb_rnt_rar_over_ip_descriptor *ret =
+ (struct dvb_rnt_rar_over_ip_descriptor *) buf;
+
+ if (len < sizeof(struct dvb_rnt_rar_over_ip_descriptor))
+ return NULL;
+ if (len < (sizeof(struct dvb_rnt_rar_over_ip_descriptor) + buf[13]))
+ return NULL;
+
+ return ret;
+}
+
+/**
+ * Accessor for the url field of a dvb_rnt_rar_over_ip_descriptor.
+ *
+ * @param d dvb_rnt_rar_over_ip_descriptor pointer.
+ * @return Pointer.
+ */
+static inline uint8_t*
+ dvb_rnt_rar_over_ip_descriptor_url(struct dvb_rnt_rar_over_ip_descriptor *d)
+{
+ return (uint8_t*)
+ ((uint8_t*) d + sizeof(struct dvb_rnt_rar_over_ip_descriptor));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h b/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h
new file mode 100644
index 0000000..cb74f75
--- /dev/null
+++ b/lib/libucsi/dvb/rnt_rnt_scan_descriptor.h
@@ -0,0 +1,125 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_RNT_RNT_SCAN_DESCRIPTOR
+#define _UCSI_DVB_RNT_RNT_SCAN_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_rnt_rnt_scan_descriptor structure.
+ */
+struct dvb_rnt_rnt_scan_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_rnt_rnt_scan_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_rnt_rnt_scan_descriptor.
+ */
+struct dvb_rnt_rnt_scan_entry {
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint8_t scan_weighting;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_rnt_rnt_scan_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_rnt_rnt_scan_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_rnt_rnt_scan_descriptor*
+ dvb_rnt_rnt_scan_descriptor_codec(struct descriptor* d)
+{
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len +2;
+ uint32_t pos = 2;
+
+ if ((len-2) % sizeof(struct dvb_rnt_rnt_scan_entry))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ pos += sizeof(struct dvb_rnt_rnt_scan_entry);
+ }
+
+ return (struct dvb_rnt_rnt_scan_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a dvb_rnt_rnt_scan_descriptor.
+ *
+ * @param d dvb_rnt_rnt_scan_descriptor pointer.
+ * @param pos Variable holding a pointer to the current dvb_rnt_rnt_scan_entry.
+ */
+#define dvb_rnt_rnt_scan_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_rnt_rnt_scan_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_rnt_rnt_scan_descriptor_entries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_rnt_rnt_scan_entry*
+ dvb_rnt_rnt_scan_descriptor_entries_first(struct dvb_rnt_rnt_scan_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_rnt_rnt_scan_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_rnt_rnt_scan_descriptor));
+}
+
+static inline struct dvb_rnt_rnt_scan_entry*
+ dvb_rnt_rnt_scan_descriptor_entries_next(struct dvb_rnt_rnt_scan_descriptor *d,
+ struct dvb_rnt_rnt_scan_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_rnt_rnt_scan_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_rnt_rnt_scan_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/rst_section.c b/lib/libucsi/dvb/rst_section.c
new file mode 100644
index 0000000..259d2b0
--- /dev/null
+++ b/lib/libucsi/dvb/rst_section.c
@@ -0,0 +1,47 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/rst_section.h>
+
+struct dvb_rst_section * dvb_rst_section_codec(struct section *section)
+{
+ uint8_t * buf = (uint8_t *) section;
+ size_t pos = sizeof(struct section);
+ size_t len = section_length(section);
+ struct dvb_rst_section * ret = (struct dvb_rst_section *) section;
+
+ while (pos < len) {
+ if ((pos + sizeof(struct dvb_rst_status)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 2);
+ bswap16(buf + pos + 4);
+ bswap16(buf + pos + 6);
+
+ pos += sizeof(struct dvb_rst_status);
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/rst_section.h b/lib/libucsi/dvb/rst_section.h
new file mode 100644
index 0000000..4b3360b
--- /dev/null
+++ b/lib/libucsi/dvb/rst_section.h
@@ -0,0 +1,110 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_RST_SECTION_H
+#define _UCSI_DVB_RST_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_rst_section structure.
+ */
+struct dvb_rst_section {
+ struct section head;
+
+ /* struct dvb_rst_status statuses[] */
+};
+
+/**
+ * An entry in the statuses field of a dvb_rst_section structure.
+ */
+struct dvb_rst_status {
+ uint16_t transport_stream_id;
+ uint16_t original_network_id;
+ uint16_t service_id;
+ uint16_t event_id;
+ EBIT2(uint8_t reserved : 5; ,
+ uint8_t running_status : 3; );
+};
+
+/**
+ * Process a dvb_rst_section.
+ *
+ * @param section Pointer to a generic section strcuture.
+ * @return dvb_rst_section pointer, or NULL on error.
+ */
+struct dvb_rst_section *dvb_rst_section_codec(struct section *section);
+
+/**
+ * Iterator for entries in the statuses field of a dvb_rst_section.
+ *
+ * @param rst dvb_rst_section pointer.
+ * @param pos Variable containing a pointer to the current dvb_rst_status.
+ */
+#define dvb_rst_section_statuses_for_each(rst, pos) \
+ for ((pos) = dvb_rst_section_statuses_first(rst); \
+ (pos); \
+ (pos) = dvb_rst_section_statuses_next(rst, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_rst_status *
+ dvb_rst_section_statuses_first(struct dvb_rst_section *rst)
+{
+ size_t pos = sizeof(struct dvb_rst_section);
+
+ if (pos >= section_length(&rst->head))
+ return NULL;
+
+ return (struct dvb_rst_status*) ((uint8_t *) rst + pos);
+}
+
+static inline struct dvb_rst_status *
+ dvb_rst_section_statuses_next(struct dvb_rst_section * rst,
+ struct dvb_rst_status * pos)
+{
+ uint8_t *end = (uint8_t*) rst + section_length(&rst->head);
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_rst_status);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_rst_status *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h b/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h
new file mode 100644
index 0000000..8f9fea8
--- /dev/null
+++ b/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_S2_SATELLITE_DELIVERY_DESCRIPTOR
+#define _UCSI_DVB_S2_SATELLITE_DELIVERY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_s2_satellite_delivery_descriptor structure.
+ */
+struct dvb_s2_satellite_delivery_descriptor {
+ struct descriptor d;
+
+ EBIT4(uint8_t scrambling_sequence_selector : 1; ,
+ uint8_t multiple_input_stream : 1; ,
+ uint8_t backwards_compatability : 1; ,
+ uint8_t reserved : 5; );
+ /* uint32_t scrambling_sequence_index if scrambling_sequence_selector = 1 */
+ /* uint8_t input_stream_id if multiple_input_stream = 1 */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_s2_satellite_delivery_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return dvb_s2_satellite_delivery_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_s2_satellite_delivery_descriptor*
+ dvb_s2_satellite_delivery_descriptor_codec(struct descriptor* d)
+{
+ struct dvb_s2_satellite_delivery_descriptor *s2 =
+ (struct dvb_s2_satellite_delivery_descriptor*) d;
+
+ if (d->len < (sizeof(struct dvb_s2_satellite_delivery_descriptor) - 2))
+ return NULL;
+
+ int len = sizeof(struct dvb_s2_satellite_delivery_descriptor);
+ if (s2->scrambling_sequence_selector) {
+ len += 3;
+ }
+ if (s2->multiple_input_stream) {
+ len += 1;
+ }
+
+ if (d->len < len)
+ return NULL;
+
+ return s2;
+}
+
+/**
+ * Accessor for the scrambling_sequence_index field of a dvb_s2_satellite_delivery_descriptor.
+ *
+ * @param s2 dvb_s2_satellite_delivery_descriptor pointer.
+ * @return The scrambling_sequence_index.
+ */
+static inline uint32_t dvb_s2_satellite_delivery_descriptor_scrambling_sequence_index(struct dvb_s2_satellite_delivery_descriptor *s2)
+{
+ uint8_t *tmp = (uint8_t*) s2;
+
+ if (s2->scrambling_sequence_selector) {
+ return ((tmp[4] & 0x03) << 16) | (tmp[5] << 8) | tmp[6];
+ }
+ return 0;
+}
+
+/**
+ * Accessor for the input_stream_id field of a dvb_s2_satellite_delivery_descriptor.
+ *
+ * @param s2 dvb_s2_satellite_delivery_descriptor pointer.
+ * @return The input_stream_id.
+ */
+static inline uint8_t dvb_s2_satellite_delivery_descriptor_input_stream_id(struct dvb_s2_satellite_delivery_descriptor *s2)
+{
+ uint8_t *tmp = (uint8_t*) s2;
+
+ if (!s2->multiple_input_stream)
+ return 0;
+
+ int off = 3;
+ if (s2->scrambling_sequence_selector) {
+ off += 3;
+ }
+ return tmp[off];
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/satellite_delivery_descriptor.h b/lib/libucsi/dvb/satellite_delivery_descriptor.h
new file mode 100644
index 0000000..b93d052
--- /dev/null
+++ b/lib/libucsi/dvb/satellite_delivery_descriptor.h
@@ -0,0 +1,73 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SATELLITE_DELIVERY_DESCRIPTOR
+#define _UCSI_DVB_SATELLITE_DELIVERY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_satellite_delivery_descriptor structure.
+ */
+struct dvb_satellite_delivery_descriptor {
+ struct descriptor d;
+
+ uint32_t frequency; // BCD, units 10kHz
+ uint16_t orbital_position;
+ EBIT5(uint8_t west_east_flag : 1; ,
+ uint8_t polarization : 2; ,
+ uint8_t roll_off : 2; ,
+ uint8_t modulation_system : 1; ,
+ uint8_t modulation_type : 2; );
+ EBIT2(uint32_t symbol_rate : 28; , // BCD, units 100Hz
+ uint32_t fec_inner : 4; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_satellite_delivery_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return dvb_satellite_delivery_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_satellite_delivery_descriptor*
+ dvb_satellite_delivery_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_satellite_delivery_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 6);
+ bswap32((uint8_t*) d + 9);
+
+ return (struct dvb_satellite_delivery_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/scrambling_descriptor.h b/lib/libucsi/dvb/scrambling_descriptor.h
new file mode 100644
index 0000000..4669bc8
--- /dev/null
+++ b/lib/libucsi/dvb/scrambling_descriptor.h
@@ -0,0 +1,61 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SCRAMBLING_DESCRIPTOR
+#define _UCSI_DVB_SCRAMBLING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_scrambling_descriptor structure.
+ */
+struct dvb_scrambling_descriptor {
+ struct descriptor d;
+
+ uint8_t scrambling_mode;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_scrambling_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to dvb_scrambling_descriptor, or NULL on error.
+ */
+static inline struct dvb_scrambling_descriptor*
+ dvb_scrambling_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_scrambling_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_scrambling_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/sdt_section.c b/lib/libucsi/dvb/sdt_section.c
new file mode 100644
index 0000000..4c7824c
--- /dev/null
+++ b/lib/libucsi/dvb/sdt_section.c
@@ -0,0 +1,60 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/sdt_section.h>
+
+struct dvb_sdt_section * dvb_sdt_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct dvb_sdt_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 3;
+
+ while (pos < len) {
+ struct dvb_sdt_service * service =
+ (struct dvb_sdt_service *)(buf + pos);
+
+ if ((pos + sizeof(struct dvb_sdt_service)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 3);
+ pos += sizeof(struct dvb_sdt_service);
+
+ if ((pos + service->descriptors_loop_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, service->descriptors_loop_length))
+ return NULL;
+
+ pos += service->descriptors_loop_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct dvb_sdt_section *) ext;
+}
diff --git a/lib/libucsi/dvb/sdt_section.h b/lib/libucsi/dvb/sdt_section.h
new file mode 100644
index 0000000..03a8569
--- /dev/null
+++ b/lib/libucsi/dvb/sdt_section.h
@@ -0,0 +1,157 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SDT_SECTION_H
+#define _UCSI_DVB_SDT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_sdt_section structure.
+ */
+struct dvb_sdt_section {
+ struct section_ext head;
+
+ uint16_t original_network_id;
+ uint8_t reserved;
+ /* struct dvb_sdt_service services[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the services field of a dvb_sdt_section.
+ */
+struct dvb_sdt_service {
+ uint16_t service_id;
+ EBIT3(uint8_t reserved : 6; ,
+ uint8_t eit_schedule_flag : 1; ,
+ uint8_t eit_present_following_flag : 1; );
+ EBIT3(uint16_t running_status : 3; ,
+ uint16_t free_ca_mode : 1; ,
+ uint16_t descriptors_loop_length :12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_sdt_section.
+ *
+ * @param section Pointer to a generic section_ext structure.
+ * @return dvb_sdt_section pointer, or NULL on error.
+ */
+struct dvb_sdt_section * dvb_sdt_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the transport_stream_id field of an SDT.
+ *
+ * @param sdt SDT pointer.
+ * @return The transport_stream_id.
+ */
+static inline uint16_t dvb_sdt_section_transport_stream_id(struct dvb_sdt_section *sdt)
+{
+ return sdt->head.table_id_ext;
+}
+
+/**
+ * Iterator for the services field in a dvb_sdt_section.
+ *
+ * @param sdt dvb_sdt_section pointer.
+ * @param pos Variable containing a pointer to the current dvb_sdt_service.
+ */
+#define dvb_sdt_section_services_for_each(sdt, pos) \
+ for ((pos) = dvb_sdt_section_services_first(sdt); \
+ (pos); \
+ (pos) = dvb_sdt_section_services_next(sdt, pos))
+
+/**
+ * Iterator for the descriptors field in a dvb_sdt_service.
+ *
+ * @param service dvb_sdt_service pointer.
+ * @param pos Variable containing a pointer to the current descriptor.
+ */
+#define dvb_sdt_service_descriptors_for_each(service, pos) \
+ for ((pos) = dvb_sdt_service_descriptors_first(service); \
+ (pos); \
+ (pos) = dvb_sdt_service_descriptors_next(service, pos))
+
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_sdt_service *
+ dvb_sdt_section_services_first(struct dvb_sdt_section * sdt)
+{
+ size_t pos = sizeof(struct dvb_sdt_section);
+
+ if (pos >= section_ext_length(&sdt->head))
+ return NULL;
+
+ return (struct dvb_sdt_service*) ((uint8_t *) sdt + pos);
+}
+
+static inline struct dvb_sdt_service *
+ dvb_sdt_section_services_next(struct dvb_sdt_section * sdt,
+ struct dvb_sdt_service * pos)
+{
+ uint8_t *end = (uint8_t*) sdt + section_ext_length(&sdt->head);
+ uint8_t *next = (uint8_t*) pos + sizeof(struct dvb_sdt_service) +
+ pos->descriptors_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_sdt_service *) next;
+}
+
+static inline struct descriptor *
+ dvb_sdt_service_descriptors_first(struct dvb_sdt_service *svc)
+{
+ if (svc->descriptors_loop_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*) svc + sizeof(struct dvb_sdt_service));
+}
+
+static inline struct descriptor *
+ dvb_sdt_service_descriptors_next(struct dvb_sdt_service *svc,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) svc + sizeof(struct dvb_sdt_service),
+ svc->descriptors_loop_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/section.h b/lib/libucsi/dvb/section.h
new file mode 100644
index 0000000..8488d71
--- /dev/null
+++ b/lib/libucsi/dvb/section.h
@@ -0,0 +1,107 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SECTION_H
+#define _UCSI_DVB_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/dvb/bat_section.h>
+#include <libucsi/dvb/dit_section.h>
+#include <libucsi/dvb/eit_section.h>
+#include <libucsi/dvb/nit_section.h>
+#include <libucsi/dvb/rst_section.h>
+#include <libucsi/dvb/sdt_section.h>
+#include <libucsi/dvb/sit_section.h>
+#include <libucsi/dvb/st_section.h>
+#include <libucsi/dvb/tdt_section.h>
+#include <libucsi/dvb/tot_section.h>
+#include <libucsi/dvb/tva_container_section.h>
+#include <libucsi/dvb/int_section.h>
+
+/**
+ * The following are not implemented just now.
+ */
+/*
+#include <libucsi/dvb/tva_related_content_section.h>
+#include <libucsi/dvb/tva_content_identifier_section.h>
+#include <libucsi/dvb/tva_resolution_provider_notification_section.h>
+#include <libucsi/dvb/ait_section.h>
+#include <libucsi/dvb/cit_section.h>
+#include <libucsi/dvb/rct_section.h>
+#include <libucsi/dvb/rnt_section.h>
+*/
+
+#define TRANSPORT_NIT_PID 0x10
+#define TRANSPORT_SDT_PID 0x11
+#define TRANSPORT_BAT_PID 0x11
+#define TRANSPORT_EIT_PID 0x12
+#define TRANSPORT_CIT_PID 0x12
+#define TRANSPORT_RST_PID 0x13
+#define TRANSPORT_TDT_PID 0x14
+#define TRANSPORT_TOT_PID 0x14
+#define TRANSPORT_RNT_PID 0x16
+#define TRANSPORT_DIT_PID 0x1e
+#define TRANSPORT_SIT_PID 0x1f
+
+/**
+ * Enumeration of DVB section tags.
+ */
+enum dvb_section_tag {
+ stag_dvb_network_information_actual = 0x40,
+ stag_dvb_network_information_other = 0x41,
+
+ stag_dvb_service_description_actual = 0x42,
+ stag_dvb_service_description_other = 0x46,
+
+ stag_dvb_bouquet_association = 0x4a,
+ stag_dvb_update_notification = 0x4b, /* same syntax as IP_MAC */
+ stag_dvb_ip_mac_notification = 0x4c,
+
+ stag_dvb_event_information_nownext_actual = 0x4e,
+ stag_dvb_event_information_nownext_other = 0x4f,
+ stag_dvb_event_information_schedule_actual = 0x50, /* 0x50->0x5f */
+ stag_dvb_event_information_schedule_other = 0x60, /* 0x60->0x6f */
+
+ stag_dvb_time_date = 0x70,
+ stag_dvb_running_status = 0x71,
+ stag_dvb_stuffing = 0x72,
+ stag_dvb_time_offset = 0x73,
+ stag_dvb_application_information = 0x74,
+ stag_dvb_tva_container = 0x75,
+ stag_dvb_tva_related_content = 0x76,
+ stag_dvb_tva_content_identifier = 0x77,
+ stag_dvb_mpe_fec = 0x78,
+ stag_dvb_tva_resolution_provider_notification = 0x79,
+
+ stag_dvb_discontinuity_information = 0x7e,
+ stag_dvb_selection_information = 0x7f,
+
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/service_availability_descriptor.h b/lib/libucsi/dvb/service_availability_descriptor.h
new file mode 100644
index 0000000..64def75
--- /dev/null
+++ b/lib/libucsi/dvb/service_availability_descriptor.h
@@ -0,0 +1,98 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SERVICE_AVAILABILITY_DESCRIPTOR
+#define _UCSI_DVB_SERVICE_AVAILABILITY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_service_availability_descriptor structure.
+ */
+struct dvb_service_availability_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t availability_flag : 1; ,
+ uint8_t reserved : 7; );
+ /* uint16_t cell_ids[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_service_availability_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return dvb_service_availability_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_service_availability_descriptor*
+ dvb_service_availability_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* buf = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ pos += sizeof(struct dvb_service_availability_descriptor) - 2;
+
+ if ((len - pos) % 2)
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos += 2;
+ }
+
+ return (struct dvb_service_availability_descriptor*) d;
+}
+
+/**
+ * Accessor for the cell_ids field of a dvb_service_availability_descriptor.
+ *
+ * @param d dvb_service_availability_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint16_t *
+ dvb_service_availability_descriptor_cell_ids(struct dvb_service_availability_descriptor *d)
+{
+ return (uint16_t *) ((uint8_t *) d + sizeof(struct dvb_service_availability_descriptor));
+}
+
+/**
+ * Determine the number of entries in the cell_ids field of a dvb_service_availability_descriptor.
+ *
+ * @param d dvb_service_availability_descriptor pointer.
+ * @return The number of entries.
+ */
+static inline int
+ dvb_service_availability_descriptor_cell_ids_count(struct dvb_service_availability_descriptor *d)
+{
+ return (d->d.len - 1) >> 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/service_descriptor.h b/lib/libucsi/dvb/service_descriptor.h
new file mode 100644
index 0000000..dd0f0ec
--- /dev/null
+++ b/lib/libucsi/dvb/service_descriptor.h
@@ -0,0 +1,163 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SERVICE_DESCRIPTOR
+#define _UCSI_DVB_SERVICE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for service_type.
+ */
+enum {
+ DVB_SERVICE_TYPE_DIGITAL_TV = 0x01,
+ DVB_SERVICE_TYPE_DIGITAL_RADIO = 0x02,
+ DVB_SERVICE_TYPE_TELETEXT = 0x03,
+ DVB_SERVICE_TYPE_NVOD_REF = 0x04,
+ DVB_SERVICE_TYPE_NVOD_TIMESHIFT = 0x05,
+ DVB_SERVICE_TYPE_MOSAIC = 0x06,
+ DVB_SERVICE_TYPE_PAL = 0x07,
+ DVB_SERVICE_TYPE_SECAM = 0x08,
+ DVB_SERVICE_TYPE_D_D2_MAC = 0x09,
+ DVB_SERVICE_TYPE_FM_RADIO = 0x0a,
+ DVB_SERVICE_TYPE_NTSC = 0x0b,
+ DVB_SERVICE_TYPE_DATA_BCAST = 0x0c,
+ DVB_SERVICE_TYPE_EN50221 = 0x0d,
+ DVB_SERVICE_TYPE_RCS_MAP = 0x0e,
+ DVB_SERVICE_TYPE_RCS_FLS = 0x0f,
+ DVB_SERVICE_TYPE_MHP = 0x10,
+ DVB_SERVICE_TYPE_MPEG2_HD_DIGITAL_TV = 0x11,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_DIGITAL_TV = 0x16,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_NVOD_TIMESHIFT = 0x17,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_SD_NVOD_REF = 0x18,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_DIGITAL_TV = 0x19,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_NVOD_TIMESHIFT = 0x1a,
+ DVB_SERVICE_TYPE_ADVANCED_CODEC_HD_NVOD_REF = 0x1b,
+};
+
+/**
+ * dvb_service_descriptor structure.
+ */
+struct dvb_service_descriptor {
+ struct descriptor d;
+
+ uint8_t service_type;
+ uint8_t service_provider_name_length;
+ /* uint8_t service_provider_name[] */
+ /* struct dvb_service_descriptor_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_service_descriptor following the variable length
+ * service_provider_name field.
+ */
+struct dvb_service_descriptor_part2 {
+ uint8_t service_name_length;
+ /* uint8_t service_name[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_service_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_service_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_service_descriptor*
+ dvb_service_descriptor_codec(struct descriptor* d)
+{
+ struct dvb_service_descriptor *p =
+ (struct dvb_service_descriptor *) d;
+ struct dvb_service_descriptor_part2 *p2;
+ uint32_t pos = sizeof(struct dvb_service_descriptor) - 2;
+ uint32_t len = d->len;
+
+ if (pos > len)
+ return NULL;
+
+ pos += p->service_provider_name_length;
+
+ if (pos > len)
+ return NULL;
+
+ p2 = (struct dvb_service_descriptor_part2*) ((uint8_t*) d + 2 + pos);
+
+ pos += sizeof(struct dvb_service_descriptor_part2);
+
+ if (pos > len)
+ return NULL;
+
+ pos += p2->service_name_length;
+
+ if (pos != len)
+ return NULL;
+
+ return p;
+}
+
+/**
+ * Accessor for the service_provider_name field of a dvb_service_descriptor.
+ *
+ * @param d dvb_service_descriptor pointer.
+ * @return Pointer to the service_provider_name field.
+ */
+static inline uint8_t *
+ dvb_service_descriptor_service_provider_name(struct dvb_service_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_service_descriptor);
+}
+
+/**
+ * Accessor for the second part of a dvb_service_descriptor.
+ *
+ * @param d dvb_service_descriptor pointer.
+ * @return dvb_service_descriptor_part2 pointer.
+ */
+static inline struct dvb_service_descriptor_part2 *
+ dvb_service_descriptor_part2(struct dvb_service_descriptor *d)
+{
+ return (struct dvb_service_descriptor_part2 *)
+ ((uint8_t*) d + sizeof(struct dvb_service_descriptor) +
+ d->service_provider_name_length);
+}
+
+/**
+ * Accessor for the service_name field of a dvb_service_descriptor_part2.
+ *
+ * @param d dvb_service_descriptor_part2 pointer.
+ * @return Pointer to the service_name field.
+ */
+static inline uint8_t *
+ dvb_service_descriptor_service_name(struct dvb_service_descriptor_part2 *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_service_descriptor_part2);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/service_identifier_descriptor.h b/lib/libucsi/dvb/service_identifier_descriptor.h
new file mode 100644
index 0000000..2037a05
--- /dev/null
+++ b/lib/libucsi/dvb/service_identifier_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SERVICE_IDENTIFIER_DESCRIPTOR
+#define _UCSI_DVB_SERVICE_IDENTIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_service_identifier_descriptor.
+ */
+struct dvb_service_identifier_descriptor {
+ struct descriptor d;
+
+ /* uint8_t identifier[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_service_identifier_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_service_identifier_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_service_identifier_descriptor*
+ dvb_service_identifier_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_service_identifier_descriptor*) d;
+}
+
+/**
+ * Retrieve a pointer to the identifier field of a dvb_service_identifier_descriptor.
+ *
+ * @param d dvb_service_identifier_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_service_identifier_descriptor_identifier(struct dvb_service_identifier_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_service_identifier_descriptor);
+}
+
+/**
+ * Calculate length of the identifier field of a dvb_service_identifier_descriptor.
+ *
+ * @param d dvb_service_identifier_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ dvb_service_identifier_descriptor_identifier_length(struct dvb_service_identifier_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/service_list_descriptor.h b/lib/libucsi/dvb/service_list_descriptor.h
new file mode 100644
index 0000000..0086b25
--- /dev/null
+++ b/lib/libucsi/dvb/service_list_descriptor.h
@@ -0,0 +1,122 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SERVICE_LIST_DESCRIPTOR
+#define _UCSI_DVB_SERVICE_LIST_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_service_list_descriptor structure.
+ */
+struct dvb_service_list_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_service_list_service services[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the services field of a dvb_service_list_descriptor.
+ */
+struct dvb_service_list_service {
+ uint16_t service_id;
+ uint8_t service_type;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_service_list_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_service_list_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_service_list_descriptor*
+ dvb_service_list_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+ uint8_t *p = (uint8_t*) d + 2;
+
+ if (len % sizeof(struct dvb_service_list_service))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(p+pos);
+ pos += sizeof(struct dvb_service_list_service);
+ }
+
+ return (struct dvb_service_list_descriptor*) d;
+}
+
+/**
+ * Iterator for services field in a dvb_service_list_descriptor.
+ *
+ * @param d dvb_service_list_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_service_list_service.
+ */
+#define dvb_service_list_descriptor_services_for_each(d, pos) \
+ for ((pos) = dvb_service_list_descriptor_services_first(d); \
+ (pos); \
+ (pos) = dvb_service_list_descriptor_services_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_service_list_service*
+ dvb_service_list_descriptor_services_first(struct dvb_service_list_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_service_list_service *)
+ ((uint8_t*) d + sizeof(struct dvb_service_list_descriptor));
+}
+
+static inline struct dvb_service_list_service*
+ dvb_service_list_descriptor_services_next(struct dvb_service_list_descriptor *d,
+ struct dvb_service_list_service *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_service_list_service);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_service_list_service *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/service_move_descriptor.h b/lib/libucsi/dvb/service_move_descriptor.h
new file mode 100644
index 0000000..7685e65
--- /dev/null
+++ b/lib/libucsi/dvb/service_move_descriptor.h
@@ -0,0 +1,67 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SERVICE_MOVE_DESCRIPTOR
+#define _UCSI_DVB_SERVICE_MOVE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_service_move_descriptor structure.
+ */
+struct dvb_service_move_descriptor {
+ struct descriptor d;
+
+ uint16_t new_original_network_id;
+ uint16_t new_transport_stream_id;
+ uint16_t new_service_id;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_service_move_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to dvb_service_move_descriptor, or NULL on error.
+ */
+static inline struct dvb_service_move_descriptor*
+ dvb_service_move_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_service_move_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 4);
+ bswap16((uint8_t*) d + 6);
+
+ return (struct dvb_service_move_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/short_event_descriptor.h b/lib/libucsi/dvb/short_event_descriptor.h
new file mode 100644
index 0000000..449c6f0
--- /dev/null
+++ b/lib/libucsi/dvb/short_event_descriptor.h
@@ -0,0 +1,135 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SHORT_EVENT_DESCRIPTOR
+#define _UCSI_DVB_SHORT_EVENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_short_event_descriptor structure.
+ */
+struct dvb_short_event_descriptor {
+ struct descriptor d;
+
+ iso639lang_t language_code;
+ uint8_t event_name_length;
+ /* uint8_t event_name[] */
+ /* struct dvb_short_event_descriptor_part2 part2 */
+} __ucsi_packed;
+
+/**
+ * Second part of a dvb_short_event_descriptor, following the variable length
+ * name field.
+ */
+struct dvb_short_event_descriptor_part2 {
+ uint8_t text_length;
+ /* uint8_t text[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_short_event_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_short_event_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_short_event_descriptor*
+ dvb_short_event_descriptor_codec(struct descriptor* d)
+{
+ struct dvb_short_event_descriptor *p =
+ (struct dvb_short_event_descriptor*) d;
+ struct dvb_short_event_descriptor_part2 *p2;
+ uint32_t pos = sizeof(struct dvb_short_event_descriptor) - 2;
+ uint32_t len = d->len;
+
+ if (pos > len)
+ return NULL;
+
+ pos += p->event_name_length;
+
+ if (pos > len)
+ return NULL;
+
+ p2 = (struct dvb_short_event_descriptor_part2*) ((uint8_t*) d + 2 + pos);
+
+ pos += sizeof(struct dvb_short_event_descriptor_part2);
+
+ if (pos > len)
+ return NULL;
+
+ pos += p2->text_length;
+
+ if (pos != len)
+ return NULL;
+
+ return p;
+}
+
+/**
+ * Accessor for name field in a dvb_short_event_descriptor.
+ *
+ * @param d dvb_short_event_descriptor pointer.
+ * @return Pointer to name field.
+ */
+static inline uint8_t *
+ dvb_short_event_descriptor_event_name(struct dvb_short_event_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_short_event_descriptor);
+}
+
+/**
+ * Accessor for second part of a dvb_short_event_descriptor.
+ *
+ * @param d dvb_short_event_descriptor pointer.
+ * @return dvb_short_event_descriptor_part2 pointer.
+ */
+static inline struct dvb_short_event_descriptor_part2 *
+ dvb_short_event_descriptor_part2(struct dvb_short_event_descriptor *d)
+{
+ return (struct dvb_short_event_descriptor_part2 *)
+ ((uint8_t*) d + sizeof(struct dvb_short_event_descriptor) +
+ d->event_name_length);
+}
+
+/**
+ * Accessor for text field in a dvb_short_event_descriptor_part2.
+ *
+ * @param d dvb_short_event_descriptor_part2 pointer.
+ * @return Pointer to text field.
+ */
+static inline uint8_t *
+ dvb_short_event_descriptor_text(struct dvb_short_event_descriptor_part2 *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_short_event_descriptor_part2);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h b/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h
new file mode 100644
index 0000000..e52d20a
--- /dev/null
+++ b/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h
@@ -0,0 +1,87 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SHORT_SMOOTHING_BUFFER_DESCRIPTOR
+#define _UCSI_DVB_SHORT_SMOOTHING_BUFFER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_short_smoothing_buffer_descriptor structure.
+ */
+struct dvb_short_smoothing_buffer_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t sb_size : 2; ,
+ uint8_t sb_leak_rate : 6; );
+ /* uint8_t reserved [] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_short_smoothing_buffer_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_short_smoothing_buffer_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_short_smoothing_buffer_descriptor*
+ dvb_short_smoothing_buffer_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct dvb_short_smoothing_buffer_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_short_smoothing_buffer_descriptor*) d;
+}
+
+/**
+ * Accessor for reserved field in a dvb_short_smoothing_buffer_descriptor.
+ *
+ * @param d dvb_short_smoothing_buffer_descriptor pointer.
+ * @return Pointer to reserved field.
+ */
+static inline uint8_t *
+ dvb_short_smoothing_buffer_descriptor_reserved(struct dvb_short_smoothing_buffer_descriptor *d)
+{
+ return (uint8_t*) d + sizeof(struct dvb_short_smoothing_buffer_descriptor);
+}
+
+/**
+ * Calculate length of reserved field in a dvb_short_smoothing_buffer_descriptor.
+ *
+ * @param d dvb_short_smoothing_buffer_descriptor pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ dvb_short_smoothing_buffer_descriptor_reserved_length(struct dvb_short_smoothing_buffer_descriptor *d)
+{
+ return d->d.len - 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/sit_section.c b/lib/libucsi/dvb/sit_section.c
new file mode 100644
index 0000000..06c228c
--- /dev/null
+++ b/lib/libucsi/dvb/sit_section.c
@@ -0,0 +1,69 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/sit_section.h>
+
+struct dvb_sit_section * dvb_sit_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ struct dvb_sit_section * ret = (struct dvb_sit_section *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct dvb_sit_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+
+ if ((pos + ret->transmission_info_loop_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, ret->transmission_info_loop_length))
+ return NULL;
+
+ pos += ret->transmission_info_loop_length;
+
+ while (pos < len) {
+ struct dvb_sit_service * service = (void*)(buf + pos);
+
+ if ((pos + sizeof(struct dvb_sit_service)) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 2);
+ bswap16(buf + pos + 4);
+ pos += sizeof(struct dvb_sit_service);
+
+ if ((pos + service->service_loop_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, service->service_loop_length))
+ return NULL;
+
+ pos += service->service_loop_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/sit_section.h b/lib/libucsi/dvb/sit_section.h
new file mode 100644
index 0000000..e06d596
--- /dev/null
+++ b/lib/libucsi/dvb/sit_section.h
@@ -0,0 +1,173 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SIT_SECTION_H
+#define _UCSI_DVB_SIT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_sit_section structure.
+ */
+struct dvb_sit_section {
+ struct section_ext head;
+
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t transmission_info_loop_length :12; );
+ /* struct descriptor descriptors[] */
+ /* struct dvb_sit_service services[] */
+};
+
+/**
+ * An entry in the services field of a dvb_sit_section.
+ */
+struct dvb_sit_service {
+ uint16_t service_id;
+ EBIT3(uint16_t reserved : 1; ,
+ uint16_t running_status : 3; ,
+ uint16_t service_loop_length :12; );
+ /* struct descriptor descriptors[] */
+};
+
+/**
+ * Process a dvb_sit_section.
+ *
+ * @param section Generic section_ext structure.
+ * @return dvb_sit_section pointer, or NULL on error.
+ */
+struct dvb_sit_section * dvb_sit_section_codec(struct section_ext *section);
+
+/**
+ * Iterator for descriptors field in a dvb_sit_section.
+ *
+ * @param sit dvb_sit_section Pointer.
+ * @param pos Variable holding pointer to current descriptor.
+ */
+#define dvb_sit_section_descriptors_for_each(sit, pos) \
+ for ((pos) = dvb_sit_section_descriptors_first(sit); \
+ (pos); \
+ (pos) = dvb_sit_section_descriptors_first(sit))
+
+/**
+ * Iterator for services field in a dvb_sit_section.
+ *
+ * @param sit dvb_sit_section Pointer.
+ * @param pos Variable holding pointer to current dvb_sit_service.
+ */
+#define dvb_sit_section_services_for_each(sit, pos) \
+ for ((pos) = dvb_sit_section_services_first(sit); \
+ (pos); \
+ (pos) = dvb_sit_section_services_next(sit, pos))
+
+/**
+ * Iterator for descriptors field in a dvb_sit_service.
+ *
+ * @param service dvb_sit_service Pointer.
+ * @param pos Variable holding pointer to current descriptor.
+ */
+#define dvb_sit_service_descriptors_for_each(service, pos) \
+ for ((pos) = dvb_sit_service_descriptors_first(service); \
+ (pos); \
+ (pos) = dvb_sit_service_descriptors_next(service, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ dvb_sit_section_descriptors_first(struct dvb_sit_section *sit)
+{
+ if (sit->transmission_info_loop_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) sit + sizeof(struct dvb_sit_section));
+}
+
+static inline struct descriptor *
+ dvb_sit_section_descriptors_next(struct dvb_sit_section *sit,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) sit + sizeof(struct dvb_sit_section),
+ sit->transmission_info_loop_length,
+ pos);
+}
+
+static inline struct dvb_sit_service *
+ dvb_sit_section_services_first(struct dvb_sit_section *sit)
+{
+ size_t pos = sizeof(struct dvb_sit_section) + sit->transmission_info_loop_length;
+
+ if (pos >= section_ext_length(&sit->head))
+ return NULL;
+
+ return (struct dvb_sit_service*) ((uint8_t *) sit + pos);
+}
+
+static inline struct dvb_sit_service *
+ dvb_sit_section_services_next(struct dvb_sit_section *sit,
+ struct dvb_sit_service *pos)
+{
+ uint8_t *end = (uint8_t*) sit + section_ext_length(&sit->head);
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_sit_service) +
+ pos->service_loop_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_sit_service *) next;
+}
+
+static inline struct descriptor *
+ dvb_sit_service_descriptors_first(struct dvb_sit_service * t)
+{
+ if (t->service_loop_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) t + sizeof(struct dvb_sit_service));
+}
+
+static inline struct descriptor *
+ dvb_sit_service_descriptors_next(struct dvb_sit_service *t,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t*) t + sizeof(struct dvb_sit_service),
+ t->service_loop_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/st_section.c b/lib/libucsi/dvb/st_section.c
new file mode 100644
index 0000000..0e60aa1
--- /dev/null
+++ b/lib/libucsi/dvb/st_section.c
@@ -0,0 +1,29 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/st_section.h>
+
+struct dvb_st_section * dvb_st_section_codec(struct section * section)
+{
+ struct dvb_st_section * ret = (struct dvb_st_section *)section;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/st_section.h b/lib/libucsi/dvb/st_section.h
new file mode 100644
index 0000000..52ba888
--- /dev/null
+++ b/lib/libucsi/dvb/st_section.h
@@ -0,0 +1,77 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_ST_SECTION_H
+#define _UCSI_DVB_ST_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * dvb_st_section structure.
+ */
+struct dvb_st_section {
+ struct section head;
+
+ /* uint8_t data[] */
+};
+
+/**
+ * Process a dvb_st_section.
+ *
+ * @param section Generic section header.
+ * @return dvb_st_section pointer, or NULL on error.
+ */
+struct dvb_st_section *dvb_st_section_codec(struct section *section);
+
+/**
+ * Accessor for data field of dvb_st_section.
+ *
+ * @param st dvb_st_section Pointer.
+ * @return Pointer to field.
+ */
+static inline uint8_t*
+ dvb_st_section_data(struct dvb_st_section* st)
+{
+ return (uint8_t*) st + sizeof(struct dvb_st_section);
+}
+
+/**
+ * Calculate length of data field of dvb_st_section.
+ *
+ * @param st dvb_st_section Pointer.
+ * @return Length in bytes.
+ */
+static inline int
+ dvb_st_section_data_length(struct dvb_st_section* st)
+{
+ return st->head.length;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/stream_identifier_descriptor.h b/lib/libucsi/dvb/stream_identifier_descriptor.h
new file mode 100644
index 0000000..262c7e2
--- /dev/null
+++ b/lib/libucsi/dvb/stream_identifier_descriptor.h
@@ -0,0 +1,61 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_STREAM_IDENTIFIER_DESCRIPTOR
+#define _UCSI_DVB_STREAM_IDENTIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_stream_identifier_descriptor structure.
+ */
+struct dvb_stream_identifier_descriptor {
+ struct descriptor d;
+
+ uint8_t component_tag;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_stream_identifier_descriptor.
+ *
+ * @param d Pointer to generic descriptor structure.
+ * @return dvb_stream_identifier_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_stream_identifier_descriptor*
+ dvb_stream_identifier_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_stream_identifier_descriptor) - 2))
+ return NULL;
+
+ return (struct dvb_stream_identifier_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/stuffing_descriptor.h b/lib/libucsi/dvb/stuffing_descriptor.h
new file mode 100644
index 0000000..48e415d
--- /dev/null
+++ b/lib/libucsi/dvb/stuffing_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_STUFFING_DESCRIPTOR
+#define _UCSI_DVB_STUFFING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_stuffing_descriptor.
+ */
+struct dvb_stuffing_descriptor {
+ struct descriptor d;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_stuffing_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_stuffing_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_stuffing_descriptor*
+ dvb_stuffing_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_stuffing_descriptor*) d;
+}
+
+/**
+ * Retrieve a pointer to the data field of a dvb_stuffing_descriptor.
+ *
+ * @param d dvb_stuffing_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ dvb_stuffing_descriptor_data(struct dvb_stuffing_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_stuffing_descriptor);
+}
+
+/**
+ * Calculate length of the data field of a dvb_stuffing_descriptor.
+ *
+ * @param d dvb_stuffing_descriptor pointer.
+ * @return The length in bytes.
+ */
+static inline int
+ dvb_stuffing_descriptor_data_length(struct dvb_stuffing_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/subtitling_descriptor.h b/lib/libucsi/dvb/subtitling_descriptor.h
new file mode 100644
index 0000000..74fc25a
--- /dev/null
+++ b/lib/libucsi/dvb/subtitling_descriptor.h
@@ -0,0 +1,126 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_SUBTITLING_DESCRIPTOR
+#define _UCSI_DVB_SUBTITLING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_subtitling_descriptor structure.
+ */
+struct dvb_subtitling_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_subtitling_entry subtitles[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the subtitles field of the a dvb_subtitling_descriptor.
+ */
+struct dvb_subtitling_entry {
+ iso639lang_t language_code;
+ uint8_t subtitling_type;
+ uint16_t composition_page_id;
+ uint16_t ancillary_page_id;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_subtitling_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_subtitling_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_subtitling_descriptor*
+ dvb_subtitling_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint8_t* ptr = (uint8_t*) d + 2;
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_subtitling_entry))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(ptr+pos+4);
+ bswap16(ptr+pos+6);
+ pos += sizeof(struct dvb_subtitling_entry);
+ }
+
+ return (struct dvb_subtitling_descriptor*) d;
+}
+
+/**
+ * Iterator for subtitles field in dvb_subtitling_descriptor.
+ *
+ * @param d dvb_subtitling_descriptor pointer.
+ * @param pos Variable containing a pointer to current dvb_subtitling_entry.
+ */
+#define dvb_subtitling_descriptor_subtitles_for_each(d, pos) \
+ for ((pos) = dvb_subtitling_descriptor_subtitles_first(d); \
+ (pos); \
+ (pos) = dvb_subtitling_descriptor_subtitles_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_subtitling_entry*
+ dvb_subtitling_descriptor_subtitles_first(struct dvb_subtitling_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_subtitling_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_subtitling_descriptor));
+}
+
+static inline struct dvb_subtitling_entry*
+ dvb_subtitling_descriptor_subtitles_next(struct dvb_subtitling_descriptor *d,
+ struct dvb_subtitling_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_subtitling_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_subtitling_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ip_address_descriptor.h b/lib/libucsi/dvb/target_ip_address_descriptor.h
new file mode 100644
index 0000000..c08b60e
--- /dev/null
+++ b/lib/libucsi/dvb/target_ip_address_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IP_ADDRESS_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IP_ADDRESS_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ip_address_descriptor structure.
+ */
+struct dvb_target_ip_address_descriptor {
+ struct descriptor d;
+
+ uint8_t ipv4_addr_mask[4];
+ /* struct dvb_ipv4_addr ipv4_addr[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv4_addr field of a dvb_target_ip_address_descriptor.
+ */
+struct dvb_ipv4_addr {
+ uint8_t ipv4_addr[4];
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ip_address_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ip_address_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ip_address_descriptor*
+ dvb_target_ip_address_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len - 4;
+
+ if (len % sizeof(struct dvb_ipv4_addr))
+ return NULL;
+
+ return (struct dvb_target_ip_address_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv4_addr field of a dvb_target_ip_address_descriptor.
+ *
+ * @param d dvb_target_ip_address_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv4_addr.
+ */
+#define dvb_target_ip_address_descriptor_ipv4_addr_for_each(d, pos) \
+ for ((pos) = dvb_target_ip_address_descriptor_ipv4_addr_first(d); \
+ (pos); \
+ (pos) = dvb_target_ip_address_descriptor_ipv4_addr_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv4_addr*
+ dvb_target_ip_address_descriptor_ipv4_addr_first(struct dvb_target_ip_address_descriptor *d)
+{
+ if (d->d.len == 4)
+ return NULL;
+
+ return (struct dvb_ipv4_addr *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ip_address_descriptor));
+}
+
+static inline struct dvb_ipv4_addr*
+ dvb_target_ip_address_descriptor_ipv4_addr_next(struct dvb_target_ip_address_descriptor *d,
+ struct dvb_ipv4_addr *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len - 4;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv4_addr);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv4_addr *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ip_slash_descriptor.h b/lib/libucsi/dvb/target_ip_slash_descriptor.h
new file mode 100644
index 0000000..e5bc76a
--- /dev/null
+++ b/lib/libucsi/dvb/target_ip_slash_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IP_SLASH_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IP_SLASH_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ip_slash_descriptor structure.
+ */
+struct dvb_target_ip_slash_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ipv4_slash ipv4_slash[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv4_slash field of a dvb_target_ip_slash_descriptor.
+ */
+struct dvb_ipv4_slash {
+ uint8_t ipv4_addr[4];
+ uint8_t ipv4_slash;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ip_slash_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ip_slash_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ip_slash_descriptor*
+ dvb_target_ip_slash_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_ipv4_slash))
+ return NULL;
+
+ return (struct dvb_target_ip_slash_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv4_slash field of a dvb_target_ip_slash_descriptor.
+ *
+ * @param d dvb_target_ip_slash_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv4_slash.
+ */
+#define dvb_target_ip_slash_descriptor_ipv4_slash_for_each(d, pos) \
+ for ((pos) = dvb_target_ip_slash_descriptor_ipv4_slash_first(d); \
+ (pos); \
+ (pos) = dvb_target_ip_slash_descriptor_ipv4_slash_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv4_slash*
+ dvb_target_ip_slash_descriptor_ipv4_slash_first(struct dvb_target_ip_slash_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ipv4_slash *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ip_slash_descriptor));
+}
+
+static inline struct dvb_ipv4_slash*
+ dvb_target_ip_slash_descriptor_ipv4_slash_next(struct dvb_target_ip_slash_descriptor *d,
+ struct dvb_ipv4_slash *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv4_slash);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv4_slash *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ip_source_slash_descriptor.h b/lib/libucsi/dvb/target_ip_source_slash_descriptor.h
new file mode 100644
index 0000000..8cade48
--- /dev/null
+++ b/lib/libucsi/dvb/target_ip_source_slash_descriptor.h
@@ -0,0 +1,118 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IP_SOURCE_SLASH_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IP_SOURCE_SLASH_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ip_source_slash_descriptor structure.
+ */
+struct dvb_target_ip_source_slash_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ipv4_source_slash ipv4_source_slash[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv4_source_slash field of a dvb_target_ip_source_slash_descriptor.
+ */
+struct dvb_ipv4_source_slash {
+ uint8_t ipv4_source_addr[4];
+ uint8_t ipv4_source_slash;
+ uint8_t ipv4_dest_addr[4];
+ uint8_t ipv4_dest_slash;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ip_source_slash_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ip_source_slash_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ip_source_slash_descriptor*
+ dvb_target_ip_source_slash_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_ipv4_source_slash))
+ return NULL;
+
+ return (struct dvb_target_ip_source_slash_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv4_source_slash field of a dvb_target_ip_source_slash_descriptor.
+ *
+ * @param d dvb_target_ip_source_slash_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv4_source_slash.
+ */
+#define dvb_target_ip_source_slash_descriptor_ipv4_source_slash_for_each(d, pos) \
+ for ((pos) = dvb_target_ip_source_slash_descriptor_ipv4_source_slash_first(d); \
+ (pos); \
+ (pos) = dvb_target_ip_source_slash_descriptor_ipv4_source_slash_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv4_source_slash*
+ dvb_target_ip_source_slash_descriptor_ipv4_source_slash_first(struct dvb_target_ip_source_slash_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ipv4_source_slash *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ip_source_slash_descriptor));
+}
+
+static inline struct dvb_ipv4_source_slash*
+ dvb_target_ip_source_slash_descriptor_ipv4_source_slash_next(struct dvb_target_ip_source_slash_descriptor *d,
+ struct dvb_ipv4_source_slash *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv4_source_slash);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv4_source_slash *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ipv6_address_descriptor.h b/lib/libucsi/dvb/target_ipv6_address_descriptor.h
new file mode 100644
index 0000000..1b28b48
--- /dev/null
+++ b/lib/libucsi/dvb/target_ipv6_address_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IPV6_ADDRESS_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IPV6_ADDRESS_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ipv6_address_descriptor structure.
+ */
+struct dvb_target_ipv6_address_descriptor {
+ struct descriptor d;
+
+ uint8_t ipv6_addr_mask[16];
+ /* struct dvb_ipv6_addr ipv6_addr[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv6_addr field of a dvb_target_ipv6_address_descriptor.
+ */
+struct dvb_ipv6_addr {
+ uint8_t ipv6_addr[16];
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ipv6_address_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ipv6_address_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ipv6_address_descriptor*
+ dvb_target_ipv6_address_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len - 16;
+
+ if (len % sizeof(struct dvb_ipv6_addr))
+ return NULL;
+
+ return (struct dvb_target_ipv6_address_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv6_addr field of a dvb_target_ipv6_address_descriptor.
+ *
+ * @param d dvb_target_ipv6_address_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv6_addr.
+ */
+#define dvb_target_ipv6_address_descriptor_ipv6_addr_for_each(d, pos) \
+ for ((pos) = dvb_target_ipv6_address_descriptor_ipv6_addr_first(d); \
+ (pos); \
+ (pos) = dvb_target_ipv6_address_descriptor_ipv6_addr_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv6_addr*
+ dvb_target_ipv6_address_descriptor_ipv6_addr_first(struct dvb_target_ipv6_address_descriptor *d)
+{
+ if (d->d.len == 16)
+ return NULL;
+
+ return (struct dvb_ipv6_addr *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ipv6_address_descriptor));
+}
+
+static inline struct dvb_ipv6_addr*
+ dvb_target_ipv6_address_descriptor_ipv6_addr_next(struct dvb_target_ipv6_address_descriptor *d,
+ struct dvb_ipv6_addr *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len - 16;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv6_addr);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv6_addr *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ipv6_slash_descriptor.h b/lib/libucsi/dvb/target_ipv6_slash_descriptor.h
new file mode 100644
index 0000000..3dc6d75
--- /dev/null
+++ b/lib/libucsi/dvb/target_ipv6_slash_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IPV6_SLASH_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IPV6_SLASH_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ipv6_slash_descriptor structure.
+ */
+struct dvb_target_ipv6_slash_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ipv6_slash ipv6_slash[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv6_slash field of a dvb_target_ipv6_slash_descriptor.
+ */
+struct dvb_ipv6_slash {
+ uint8_t ipv6_addr[16];
+ uint8_t ipv6_slash;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ipv6_slash_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ipv6_slash_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ipv6_slash_descriptor*
+ dvb_target_ipv6_slash_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_ipv6_slash))
+ return NULL;
+
+ return (struct dvb_target_ipv6_slash_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv6_slash field of a dvb_target_ipv6_slash_descriptor.
+ *
+ * @param d dvb_target_ipv6_slash_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv6_slash.
+ */
+#define dvb_target_ipv6_slash_descriptor_ipv6_slash_for_each(d, pos) \
+ for ((pos) = dvb_target_ipv6_slash_descriptor_ipv6_slash_first(d); \
+ (pos); \
+ (pos) = dvb_target_ipv6_slash_descriptor_ipv6_slash_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv6_slash*
+ dvb_target_ipv6_slash_descriptor_ipv6_slash_first(struct dvb_target_ipv6_slash_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ipv6_slash *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ipv6_slash_descriptor));
+}
+
+static inline struct dvb_ipv6_slash*
+ dvb_target_ipv6_slash_descriptor_ipv6_slash_next(struct dvb_target_ipv6_slash_descriptor *d,
+ struct dvb_ipv6_slash *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv6_slash);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv6_slash *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h b/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h
new file mode 100644
index 0000000..3a4b38e
--- /dev/null
+++ b/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h
@@ -0,0 +1,118 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ * Copyright (C) 2006 Stephane Este-Gracias (sestegra@free.fr)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TARGET_IPV6_SOURCE_SLASH_DESCRIPTOR
+#define _UCSI_DVB_TARGET_IPV6_SOURCE_SLASH_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_target_ipv6_source_slash_descriptor structure.
+ */
+struct dvb_target_ipv6_source_slash_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_ipv6_source_slash ipv6_source_slash[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the ipv6_source_slash field of a dvb_target_ipv6_source_slash_descriptor.
+ */
+struct dvb_ipv6_source_slash {
+ uint8_t ipv6_source_addr[16];
+ uint8_t ipv6_source_slash;
+ uint8_t ipv6_dest_addr[16];
+ uint8_t ipv6_dest_slash;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_target_ipv6_source_slash_descriptor.
+ *
+ * @param d Generic descriptor structure pointer.
+ * @return dvb_target_ipv6_source_slash_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_target_ipv6_source_slash_descriptor*
+ dvb_target_ipv6_source_slash_descriptor_codec(struct descriptor* d)
+{
+ uint32_t len = d->len;
+
+ if (len % sizeof(struct dvb_ipv6_source_slash))
+ return NULL;
+
+ return (struct dvb_target_ipv6_source_slash_descriptor*) d;
+}
+
+/**
+ * Iterator for entries in the ipv6_source_slash field of a dvb_target_ipv6_source_slash_descriptor.
+ *
+ * @param d dvb_target_ipv6_source_slash_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_ipv6_source_slash.
+ */
+#define dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_for_each(d, pos) \
+ for ((pos) = dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_first(d); \
+ (pos); \
+ (pos) = dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_ipv6_source_slash*
+ dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_first(struct dvb_target_ipv6_source_slash_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_ipv6_source_slash *)
+ ((uint8_t*) d + sizeof(struct dvb_target_ipv6_source_slash_descriptor));
+}
+
+static inline struct dvb_ipv6_source_slash*
+ dvb_target_ipv6_source_slash_descriptor_ipv6_source_slash_next(struct dvb_target_ipv6_source_slash_descriptor *d,
+ struct dvb_ipv6_source_slash *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_ipv6_source_slash);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_ipv6_source_slash *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/tdt_section.c b/lib/libucsi/dvb/tdt_section.c
new file mode 100644
index 0000000..ba64fe9
--- /dev/null
+++ b/lib/libucsi/dvb/tdt_section.c
@@ -0,0 +1,33 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/tdt_section.h>
+
+struct dvb_tdt_section * dvb_tdt_section_codec(struct section * section)
+{
+ size_t len = section_length(section);
+ struct dvb_tdt_section * ret = (struct dvb_tdt_section *) section;
+
+ if (len != sizeof(struct dvb_tdt_section))
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/tdt_section.h b/lib/libucsi/dvb/tdt_section.h
new file mode 100644
index 0000000..fc2bcb8
--- /dev/null
+++ b/lib/libucsi/dvb/tdt_section.h
@@ -0,0 +1,54 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TDT_SECTION_H
+#define _UCSI_DVB_TDT_SECTION_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+#include <libucsi/dvb/types.h>
+
+/**
+ * dvb_tdt_section structure.
+ */
+struct dvb_tdt_section {
+ struct section head;
+
+ dvbdate_t utc_time;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_tdt_section.
+ *
+ * @param section Generic section header.
+ * @return dvb_tdt_section pointer, or NULL on error.
+ */
+struct dvb_tdt_section *dvb_tdt_section_codec(struct section *section);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/telephone_descriptor.h b/lib/libucsi/dvb/telephone_descriptor.h
new file mode 100644
index 0000000..3dc43a1
--- /dev/null
+++ b/lib/libucsi/dvb/telephone_descriptor.h
@@ -0,0 +1,150 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TELEPHONE_DESCRIPTOR
+#define _UCSI_DVB_TELEPHONE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_telephone_descriptor stucture.
+ */
+struct dvb_telephone_descriptor {
+ struct descriptor d;
+
+ EBIT3(uint8_t reserved_1 : 2; ,
+ uint8_t foreign_availability : 1; ,
+ uint8_t connection_type : 5; );
+ EBIT4(uint8_t reserved_2 : 1; ,
+ uint8_t country_prefix_length : 2; ,
+ uint8_t international_area_code_length : 3; ,
+ uint8_t operator_code_length : 2; );
+ EBIT3(uint8_t reserved_3 : 1; ,
+ uint8_t national_area_code_length : 3; ,
+ uint8_t core_number_length : 4; );
+ /* uint8_t country_prefix[] */
+ /* uint8_t international_area_code[] */
+ /* uint8_t operator_code[] */
+ /* uint8_t national_area_code[] */
+ /* uint8_t core_number[] */
+} __ucsi_packed;
+
+
+/**
+ * Process a dvb_telephone_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_telephone_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_telephone_descriptor*
+ dvb_telephone_descriptor_codec(struct descriptor* d)
+{
+ struct dvb_telephone_descriptor* p =
+ (struct dvb_telephone_descriptor*) d;
+ uint32_t pos = sizeof(struct dvb_telephone_descriptor) - 2;
+ uint32_t len = d->len;
+
+ if (pos > len)
+ return NULL;
+
+ pos += p->country_prefix_length +
+ p->international_area_code_length +
+ p->operator_code_length +
+ p->national_area_code_length +
+ p->core_number_length;
+
+ if (pos != len)
+ return NULL;
+
+ return p;
+}
+
+/**
+ * Retrieve pointer to country_prefix field of a dvb_telephone_descriptor.
+ *
+ * @param d dvb_telephone_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_telephone_descriptor_country_prefix(struct dvb_telephone_descriptor* d)
+{
+ return (uint8_t*) d + sizeof(struct dvb_telephone_descriptor);
+}
+
+/**
+ * Retrieve pointer to international_area_code field of a dvb_telephone_descriptor.
+ *
+ * @param d dvb_telephone_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_telephone_descriptor_international_area_code(struct dvb_telephone_descriptor* d)
+{
+ return dvb_telephone_descriptor_country_prefix(d) + d->country_prefix_length;
+}
+
+/**
+ * Retrieve pointer to operator_code field of a dvb_telephone_descriptor.
+ *
+ * @param d dvb_telephone_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_telephone_descriptor_operator_code(struct dvb_telephone_descriptor* d)
+{
+ return dvb_telephone_descriptor_international_area_code(d) + d->international_area_code_length;
+}
+
+/**
+ * Retrieve pointer to national_area_code field of a dvb_telephone_descriptor.
+ *
+ * @param d dvb_telephone_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_telephone_descriptor_national_area_code(struct dvb_telephone_descriptor* d)
+{
+ return dvb_telephone_descriptor_operator_code(d) + d->operator_code_length;
+}
+
+/**
+ * Retrieve pointer to core_number field of a dvb_telephone_descriptor.
+ *
+ * @param d dvb_telephone_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ dvb_telephone_descriptor_core_number(struct dvb_telephone_descriptor* d)
+{
+ return dvb_telephone_descriptor_national_area_code(d) + d->national_area_code_length;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/teletext_descriptor.h b/lib/libucsi/dvb/teletext_descriptor.h
new file mode 100644
index 0000000..424c1cb
--- /dev/null
+++ b/lib/libucsi/dvb/teletext_descriptor.h
@@ -0,0 +1,127 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TELETEXT_DESCRIPTOR
+#define _UCSI_DVB_TELETEXT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Possible values for the type field.
+ */
+enum {
+ DVB_TELETEXT_TYPE_INITIAL = 0x01,
+ DVB_TELETEXT_TYPE_SUBTITLE = 0x02,
+ DVB_TELETEXT_TYPE_ADDITIONAL = 0x03,
+ DVB_TELETEXT_TYPE_SCHEDULE = 0x04,
+ DVB_TELETEXT_TYPE_SUBTITLE_HEARING_IMPAIRED= 0x05,
+};
+
+/**
+ * dvb_teletext_descriptor structure.
+ */
+struct dvb_teletext_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_teletext_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_teletext_descriptor.
+ */
+struct dvb_teletext_entry {
+ iso639lang_t language_code;
+ EBIT2(uint8_t type : 5; ,
+ uint8_t magazine_number: 3; );
+ uint8_t page_number;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_teletext_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_teletext_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_teletext_descriptor*
+ dvb_teletext_descriptor_codec(struct descriptor* d)
+{
+ if (d->len % sizeof(struct dvb_teletext_entry))
+ return NULL;
+
+ return (struct dvb_teletext_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a dvb_teletext_descriptor.
+ *
+ * @param d dvb_teletext_descriptor pointer.
+ * @param pos Variable holding a pointer to the current dvb_teletext_entry.
+ */
+#define dvb_teletext_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_teletext_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_teletext_descriptor_entries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_teletext_entry*
+ dvb_teletext_descriptor_entries_first(struct dvb_teletext_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_teletext_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_teletext_descriptor));
+}
+
+static inline struct dvb_teletext_entry*
+ dvb_teletext_descriptor_entries_next(struct dvb_teletext_descriptor *d,
+ struct dvb_teletext_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_teletext_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_teletext_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/terrestrial_delivery_descriptor.h b/lib/libucsi/dvb/terrestrial_delivery_descriptor.h
new file mode 100644
index 0000000..c624dab
--- /dev/null
+++ b/lib/libucsi/dvb/terrestrial_delivery_descriptor.h
@@ -0,0 +1,77 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TERRESTRIAL_DELIVERY_DESCRIPTOR
+#define _UCSI_DVB_TERRESTRIAL_DELIVERY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_terrestrial_delivery_descriptor structure.
+ */
+struct dvb_terrestrial_delivery_descriptor {
+ struct descriptor d;
+
+ uint32_t centre_frequency; // Normal integer, units 10Hz
+ EBIT5(uint8_t bandwidth : 3; ,
+ uint8_t priority : 1; ,
+ uint8_t time_slicing_indicator : 1; ,
+ uint8_t mpe_fec_indicator : 1; ,
+ uint8_t reserved_1 : 2; );
+ EBIT3(uint8_t constellation : 2; ,
+ uint8_t hierarchy_information : 3; ,
+ uint8_t code_rate_hp_stream : 3; );
+ EBIT4(uint8_t code_rate_lp_stream : 3; ,
+ uint8_t guard_interval : 2; ,
+ uint8_t transmission_mode : 2; ,
+ uint8_t other_frequency_flag : 1; );
+ uint32_t reserved_2;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_terrestrial_delivery_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_terrestrial_delivery_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_terrestrial_delivery_descriptor*
+ dvb_terrestrial_delivery_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_terrestrial_delivery_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+ bswap32((uint8_t*) d + 9);
+
+ return (struct dvb_terrestrial_delivery_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/time_shifted_event_descriptor.h b/lib/libucsi/dvb/time_shifted_event_descriptor.h
new file mode 100644
index 0000000..6b4a9f6
--- /dev/null
+++ b/lib/libucsi/dvb/time_shifted_event_descriptor.h
@@ -0,0 +1,65 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR
+#define _UCSI_DVB_TIME_SHIFTED_EVENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_time_shifted_event_descriptor structure.
+ */
+struct dvb_time_shifted_event_descriptor {
+ struct descriptor d;
+
+ uint16_t reference_service_id;
+ uint16_t reference_event_id;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_time_shifted_event_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_time_shifted_event_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_time_shifted_event_descriptor*
+ dvb_time_shifted_event_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_time_shifted_event_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 4);
+
+ return (struct dvb_time_shifted_event_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/time_shifted_service_descriptor.h b/lib/libucsi/dvb/time_shifted_service_descriptor.h
new file mode 100644
index 0000000..c8dcc0e
--- /dev/null
+++ b/lib/libucsi/dvb/time_shifted_service_descriptor.h
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR
+#define _UCSI_DVB_TIME_SHIFTED_SERVICE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_time_shifted_service_descriptor structure.
+ */
+struct dvb_time_shifted_service_descriptor {
+ struct descriptor d;
+
+ uint16_t reference_service_id;
+} __ucsi_packed;
+
+/**
+ * Process a dvb_time_shifted_service_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return Pointer to dvb_time_shifted_service_descriptor, or NULL on error.
+ */
+static inline struct dvb_time_shifted_service_descriptor*
+ dvb_time_shifted_service_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct dvb_time_shifted_service_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+
+ return (struct dvb_time_shifted_service_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/tot_section.c b/lib/libucsi/dvb/tot_section.c
new file mode 100644
index 0000000..5dc7890
--- /dev/null
+++ b/lib/libucsi/dvb/tot_section.c
@@ -0,0 +1,50 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/tot_section.h>
+
+struct dvb_tot_section *dvb_tot_section_codec(struct section *section)
+{
+ uint8_t * buf = (uint8_t *)section;
+ size_t pos = sizeof(struct section);
+ size_t len = section_length(section) - CRC_SIZE;
+ struct dvb_tot_section * ret = (struct dvb_tot_section *)section;
+
+ if (len < sizeof(struct dvb_tot_section))
+ return NULL;
+
+ pos += 5;
+ bswap16(buf + pos);
+ pos += 2;
+
+ if ((pos + ret->descriptors_loop_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, ret->descriptors_loop_length))
+ return NULL;
+
+ pos += ret->descriptors_loop_length;
+
+ if (pos != len)
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/tot_section.h b/lib/libucsi/dvb/tot_section.h
new file mode 100644
index 0000000..3474da1
--- /dev/null
+++ b/lib/libucsi/dvb/tot_section.h
@@ -0,0 +1,97 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TOT_SECTION_H
+#define _UCSI_DVB_TOT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+#include <libucsi/dvb/types.h>
+
+/**
+ * dvb_tot_section structure.
+ */
+struct dvb_tot_section {
+ struct section head;
+
+ dvbdate_t utc_time;
+ EBIT2(uint16_t reserved : 4; ,
+ uint16_t descriptors_loop_length:12; );
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_tot_section.
+ *
+ * @param section Pointer to generic section structure.
+ * @return dvb_tot_section pointer, or NULL on error.
+ */
+struct dvb_tot_section * dvb_tot_section_codec(struct section *section);
+
+/**
+ * Iterator for descriptors field of dvb_tot_section.
+ *
+ * @param tot dvb_tot_section pointer.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define dvb_tot_section_descriptors_for_each(tot, pos) \
+ for ((pos) = dvb_tot_section_descriptors_first(tot); \
+ (pos); \
+ (pos) = dvb_tot_section_descriptors_next(tot, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ dvb_tot_section_descriptors_first(struct dvb_tot_section * tot)
+{
+ if (tot->descriptors_loop_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) tot + sizeof(struct dvb_tot_section));
+}
+
+static inline struct descriptor *
+ dvb_tot_section_descriptors_next(struct dvb_tot_section *tot,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t *) tot + sizeof(struct dvb_tot_section),
+ tot->descriptors_loop_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/transport_stream_descriptor.h b/lib/libucsi/dvb/transport_stream_descriptor.h
new file mode 100644
index 0000000..1797ec5
--- /dev/null
+++ b/lib/libucsi/dvb/transport_stream_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TRANSPORT_STREAM_DESCRIPTOR
+#define _UCSI_DVB_TRANSPORT_STREAM_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_transport_stream_descriptor structure.
+ */
+struct dvb_transport_stream_descriptor {
+ struct descriptor d;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process dvb_transport_stream_descriptor structure.
+ *
+ * @param d Pointer to generic descriptor.
+ * @return dvb_transport_stream_descriptor structure or NULL on error.
+ */
+static inline struct dvb_transport_stream_descriptor*
+ dvb_transport_stream_descriptor_codec(struct descriptor* d)
+{
+ return (struct dvb_transport_stream_descriptor*) d;
+}
+
+/**
+ * Retrieve a pointer to the data field of a dvb_transport_stream_descriptor.
+ *
+ * @param d dvb_transport_stream_descriptor structure.
+ * @return Pointer to data field.
+ */
+static inline uint8_t *
+ dvb_transport_stream_descriptor_data(struct dvb_transport_stream_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_transport_stream_descriptor);
+}
+
+/**
+ * Calculate the length of the data field of a dvb_transport_stream_descriptor.
+ *
+ * @param d dvb_transport_stream_descriptor structure.
+ * @return length of data field in bytes.
+ */
+static inline int
+ dvb_transport_stream_descriptor_data_length(struct dvb_transport_stream_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/tva_container_section.c b/lib/libucsi/dvb/tva_container_section.c
new file mode 100644
index 0000000..f526efc
--- /dev/null
+++ b/lib/libucsi/dvb/tva_container_section.c
@@ -0,0 +1,33 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/dvb/tva_container_section.h>
+
+struct dvb_tva_container_section *dvb_tva_container_section_codec(struct section_ext *ext)
+{
+ size_t len = section_ext_length(ext);
+ struct dvb_tva_container_section* ret = (struct dvb_tva_container_section*) ext;
+
+ if (len < sizeof(struct dvb_tva_container_section))
+ return NULL;
+
+ return ret;
+}
diff --git a/lib/libucsi/dvb/tva_container_section.h b/lib/libucsi/dvb/tva_container_section.h
new file mode 100644
index 0000000..7d0abb1
--- /dev/null
+++ b/lib/libucsi/dvb/tva_container_section.h
@@ -0,0 +1,90 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TVA_CONTAINER_SECTION_H
+#define _UCSI_DVB_TVA_CONTAINER_SECTION_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+#include <libucsi/dvb/types.h>
+
+/**
+ * dvb_tva_container_section structure.
+ */
+struct dvb_tva_container_section {
+ struct section_ext head;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process a dvb_tva_container_section.
+ *
+ * @param section Generic section header.
+ * @return dvb_tdt_section pointer, or NULL on error.
+ */
+struct dvb_tva_container_section *dvb_tva_container_section_codec(struct section_ext *ext);
+
+/**
+ * Accessor for the container_id field of a tva container section.
+ *
+ * @param container dvb_tva_container_section pointer.
+ * @return The container_id.
+ */
+static inline uint16_t dvb_tva_container_section_container_id(struct dvb_tva_container_section *container)
+{
+ return container->head.table_id_ext;
+}
+
+/**
+ * Accessor for the data field of a dvb_data_broadcast_id_descriptor.
+ *
+ * @param d dvb_data_broadcast_id_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+dvb_tva_container_section_data(struct dvb_tva_container_section *s)
+{
+ return (uint8_t *) s + sizeof(struct dvb_tva_container_section);
+}
+
+/**
+ * Determine the number of bytes in the data field of a dvb_tva_container_section.
+ *
+ * @param d dvb_tva_container_section pointer.
+ * @return Length of the field in bytes.
+ */
+static inline int
+dvb_tva_container_section_data_length(struct dvb_tva_container_section *s)
+{
+ return section_ext_length(&s->head) - sizeof(struct dvb_tva_container_section);
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/tva_id_descriptor.h b/lib/libucsi/dvb/tva_id_descriptor.h
new file mode 100644
index 0000000..3b4f3e8
--- /dev/null
+++ b/lib/libucsi/dvb/tva_id_descriptor.h
@@ -0,0 +1,124 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TVA_ID_DESCRIPTOR
+#define _UCSI_DVB_TVA_ID_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * dvb_tva_id_descriptor structure.
+ */
+struct dvb_tva_id_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_tva_id_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the entries field of a dvb_tva_id_descriptor.
+ */
+struct dvb_tva_id_entry {
+ uint16_t tva_id;
+ EBIT2(uint8_t reserved : 5; ,
+ uint8_t running_status : 3; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_tva_id_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return dvb_tva_id_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_tva_id_descriptor*
+ dvb_tva_id_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+ uint8_t* buf = (uint8_t*) d + 2;
+
+ pos += sizeof(struct dvb_tva_id_descriptor) - 2;
+ if (len % sizeof(struct dvb_tva_id_entry))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos+=3;
+ }
+
+ return (struct dvb_tva_id_descriptor*) d;
+}
+
+/**
+ * Iterator for the entries field of a dvb_tva_id_descriptor.
+ *
+ * @param d dvb_tva_id_descriptor pointer.
+ * @param pos Variable containing a pointer to the current dvb_tva_id_entry.
+ */
+#define dvb_tva_id_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_tva_id_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_tva_id_descriptor_entries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_tva_id_entry*
+ dvb_tva_id_descriptor_entries_first(struct dvb_tva_id_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_tva_id_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_tva_id_descriptor));
+}
+
+static inline struct dvb_tva_id_entry*
+ dvb_tva_id_descriptor_entries_next(struct dvb_tva_id_descriptor *d,
+ struct dvb_tva_id_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_tva_id_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_tva_id_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/types.c b/lib/libucsi/dvb/types.c
new file mode 100644
index 0000000..c1cf583
--- /dev/null
+++ b/lib/libucsi/dvb/types.c
@@ -0,0 +1,270 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <string.h>
+#include "types.h"
+
+time_t dvbdate_to_unixtime(dvbdate_t dvbdate)
+{
+ int k = 0;
+ struct tm tm;
+ double mjd;
+
+ /* check for the undefined value */
+ if ((dvbdate[0] == 0xff) &&
+ (dvbdate[1] == 0xff) &&
+ (dvbdate[2] == 0xff) &&
+ (dvbdate[3] == 0xff) &&
+ (dvbdate[4] == 0xff)) {
+ return -1;
+ }
+
+ memset(&tm, 0, sizeof(tm));
+ mjd = (dvbdate[0] << 8) | dvbdate[1];
+
+ tm.tm_year = (int) ((mjd - 15078.2) / 365.25);
+ tm.tm_mon = (int) (((mjd - 14956.1) - (int) (tm.tm_year * 365.25)) / 30.6001);
+ tm.tm_mday = (int) mjd - 14956 - (int) (tm.tm_year * 365.25) - (int) (tm.tm_mon * 30.6001);
+ if ((tm.tm_mon == 14) || (tm.tm_mon == 15)) k = 1;
+ tm.tm_year += k;
+ tm.tm_mon = tm.tm_mon - 2 - k * 12;
+ tm.tm_sec = bcd_to_integer(dvbdate[4]);
+ tm.tm_min = bcd_to_integer(dvbdate[3]);
+ tm.tm_hour = bcd_to_integer(dvbdate[2]);
+
+ return mktime(&tm);
+}
+
+void unixtime_to_dvbdate(time_t unixtime, dvbdate_t dvbdate)
+{
+ struct tm tm;
+ double l = 0;
+ int mjd;
+
+ /* the undefined value */
+ if (unixtime == -1) {
+ memset(dvbdate, 0xff, 5);
+ return;
+ }
+
+ gmtime_r(&unixtime, &tm);
+ tm.tm_mon++;
+ if ((tm.tm_mon == 1) || (tm.tm_mon == 2)) l = 1;
+ mjd = 14956 + tm.tm_mday + (int) ((tm.tm_year - l) * 365.25) + (int) ((tm.tm_mon + 1 + l * 12) * 30.6001);
+
+ dvbdate[0] = (mjd & 0xff00) >> 8;
+ dvbdate[1] = mjd & 0xff;
+ dvbdate[2] = integer_to_bcd(tm.tm_hour);
+ dvbdate[3] = integer_to_bcd(tm.tm_min);
+ dvbdate[4] = integer_to_bcd(tm.tm_sec);
+}
+
+int dvbduration_to_seconds(dvbduration_t dvbduration)
+{
+ int seconds = 0;
+
+ seconds += (bcd_to_integer(dvbduration[0]) * 60 * 60);
+ seconds += (bcd_to_integer(dvbduration[1]) * 60);
+ seconds += bcd_to_integer(dvbduration[2]);
+
+ return seconds;
+}
+
+void seconds_to_dvbduration(int seconds, dvbduration_t dvbduration)
+{
+ int hours, mins;
+
+ hours = seconds / (60*60);
+ seconds -= (hours * 60 * 60);
+ mins = seconds / 60;
+ seconds -= (mins * 60);
+
+ dvbduration[0] = integer_to_bcd(hours);
+ dvbduration[1] = integer_to_bcd(mins);
+ dvbduration[2] = integer_to_bcd(seconds);
+}
+
+int dvbhhmm_to_seconds(dvbhhmm_t dvbhhmm)
+{
+ int seconds = 0;
+
+ seconds += (bcd_to_integer(dvbhhmm[0]) * 60 * 60);
+ seconds += (bcd_to_integer(dvbhhmm[1]) * 60);
+
+ return seconds;
+}
+
+void seconds_to_dvbhhmm(int seconds, dvbhhmm_t dvbhhmm)
+{
+ int hours, mins;
+
+ hours = seconds / (60*60);
+ seconds -= (hours * 60 * 60);
+ mins = seconds / 60;
+
+ dvbhhmm[0] = integer_to_bcd(hours);
+ dvbhhmm[1] = integer_to_bcd(mins);
+}
+
+uint32_t integer_to_bcd(uint32_t intval)
+{
+ uint32_t val = 0;
+
+ int i;
+ for(i=0; i<=28;i+=4) {
+ val |= ((intval % 10) << i);
+ intval /= 10;
+ }
+
+ return val;
+}
+
+uint32_t bcd_to_integer(uint32_t bcdval)
+{
+ uint32_t val = 0;
+
+ int i;
+ for(i=28; i>=0;i-=4) {
+ val += ((bcdval >> i) & 0x0f);
+ if (i != 0) val *= 10;
+ }
+
+ return val;
+}
+
+const char *dvb_charset(char *dvb_text, int dvb_text_length, int *consumed)
+{
+ char *charset = "ISO6937";
+ int used = 0;
+
+ if (dvb_text_length == 0)
+ goto exit;
+ if (dvb_text[0] >= 32)
+ goto exit;
+ if (dvb_text[0] == 0x10) {
+ if (dvb_text_length < 3)
+ goto exit;
+
+ used = 3;
+ uint16_t ext = (dvb_text[1] << 8) | dvb_text[2];
+ switch(ext) {
+ case 0x01:
+ charset = "ISO8859-1";
+ break;
+ case 0x02:
+ charset = "ISO8859-2";
+ break;
+ case 0x03:
+ charset = "ISO8859-3";
+ break;
+ case 0x04:
+ charset = "ISO8859-4";
+ break;
+ case 0x05:
+ charset = "ISO8859-5";
+ break;
+ case 0x06:
+ charset = "ISO8859-6";
+ break;
+ case 0x07:
+ charset = "ISO8859-7";
+ break;
+ case 0x08:
+ charset = "ISO8859-8";
+ break;
+ case 0x09:
+ charset = "ISO8859-9";
+ break;
+ case 0x0a:
+ charset = "ISO8859-10";
+ break;
+ case 0x0b:
+ charset = "ISO8859-11";
+ break;
+ case 0x0d:
+ charset = "ISO8859-13";
+ break;
+ case 0x0e:
+ charset = "ISO8859-14";
+ break;
+ case 0x0f:
+ charset = "ISO8859-15";
+ break;
+ default:
+ used = 0;
+ break;
+ }
+ } else {
+ used = 1;
+ switch(dvb_text[0]) {
+ case 0x01:
+ charset = "ISO8859-5";
+ break;
+ case 0x02:
+ charset = "ISO8859-6";
+ break;
+ case 0x03:
+ charset = "ISO8859-7";
+ break;
+ case 0x04:
+ charset = "ISO8859-8";
+ break;
+ case 0x05:
+ charset = "ISO8859-9";
+ break;
+ case 0x06:
+ charset = "ISO8859-10";
+ break;
+ case 0x07:
+ charset = "ISO8859-11";
+ break;
+ case 0x09:
+ charset = "ISO8859-13";
+ break;
+ case 0x0a:
+ charset = "ISO8859-14";
+ break;
+ case 0x0b:
+ charset = "ISO8859-15";
+ break;
+ case 0x11:
+ charset = "UTF16";
+ break;
+ case 0x12:
+ charset = "EUC-KR";
+ break;
+ case 0x13:
+ charset = "GB2312";
+ break;
+ case 0x14:
+ charset = "GBK";
+ break;
+ case 0x15:
+ charset = "UTF8";
+ break;
+ default:
+ used = 0;
+ break;
+ }
+ }
+exit:
+ *consumed = used;
+ return charset;
+}
diff --git a/lib/libucsi/dvb/types.h b/lib/libucsi/dvb/types.h
new file mode 100644
index 0000000..437c7c3
--- /dev/null
+++ b/lib/libucsi/dvb/types.h
@@ -0,0 +1,127 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_TYPES_H
+#define _UCSI_DVB_TYPES_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+#include <time.h>
+
+typedef uint8_t dvbdate_t[5];
+typedef uint8_t dvbduration_t[3];
+typedef uint8_t dvbhhmm_t[2];
+
+/**
+ * Running status values.
+ */
+enum {
+ DVB_RUNNING_STATUS_NOT_RUNNING = 0x01,
+ DVB_RUNNING_STATUS_FEW_SECONDS = 0x02,
+ DVB_RUNNING_STATUS_PAUSING = 0x03,
+ DVB_RUNNING_STATUS_RUNNING = 0x04,
+};
+
+/**
+ * Convert from a 5 byte DVB UTC date to unix time.
+ * Note: this functions expects the DVB date in network byte order.
+ *
+ * @param d Pointer to DVB date.
+ * @return The unix timestamp, or -1 if the dvbdate was set to the 'undefined' value
+ */
+extern time_t dvbdate_to_unixtime(dvbdate_t dvbdate);
+
+/**
+ * Convert from a unix timestemp to a 5 byte DVB UTC date.
+ * Note: this function will always output the DVB date in
+ * network byte order.
+ *
+ * @param unixtime The unix timestamp, or -1 for the 'undefined' value.
+ * @param utc Pointer to 5 byte DVB date.
+ */
+extern void unixtime_to_dvbdate(time_t unixtime, dvbdate_t dvbdate);
+
+/**
+ * Convert from a DVB BCD duration to a number of seconds.
+ *
+ * @param dvbduration Pointer to 3 byte DVB duration.
+ * @return Number of seconds.
+ */
+extern int dvbduration_to_seconds(dvbduration_t dvbduration);
+
+/**
+ * Convert from a number of seconds to a DVB 3 byte BCD duration.
+ *
+ * @param seconds The number of seconds.
+ * @param dvbduration Pointer to 3 byte DVB duration.
+ */
+extern void seconds_to_dvbduration(int seconds, dvbduration_t dvbduration);
+
+/**
+ * Convert from a DVB BCD HHMM to a number of seconds.
+ *
+ * @param dvbduration Pointer to 2 byte DVB HHMM.
+ * @return Number of seconds.
+ */
+extern int dvbhhmm_to_seconds(dvbhhmm_t dvbhhmm);
+
+/**
+ * Convert from a number of seconds to a DVB 2 byte BCD HHMM.
+ *
+ * @param seconds The number of seconds.
+ * @param dvbduration Pointer to 2 byte DVB HHMM.
+ */
+extern void seconds_to_dvbhhmm(int seconds, dvbhhmm_t dvbhhmm);
+
+/**
+ * Convert a __ucsi_packed BCD value into a normal integer.
+ *
+ * @param bcd The value to convert.
+ * @return The value.
+ */
+extern uint32_t bcd_to_integer(uint32_t bcd);
+
+/**
+ * Convert a normal integer into a __ucsi_packed BCD value.
+ *
+ * @param integer The value to convert.
+ * @return The value.
+ */
+extern uint32_t integer_to_bcd(uint32_t integer);
+
+/**
+ * Determine the (iconv compatable) character set of a dvb string.
+ *
+ * @param dvb_text DVB text concerned.
+ * @param dvb_text_length Length of text.
+ * @param consumed Out parameter of number of bytes used to encode the character set.
+ * @return Name of the character set.
+ */
+extern const char *dvb_charset(char *dvb_text, int dvb_text_length, int *consumed);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/vbi_data_descriptor.h b/lib/libucsi/dvb/vbi_data_descriptor.h
new file mode 100644
index 0000000..b1d8703
--- /dev/null
+++ b/lib/libucsi/dvb/vbi_data_descriptor.h
@@ -0,0 +1,186 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_VBI_DATA_DESCRIPTOR
+#define _UCSI_DVB_VBI_DATA_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for the data_service_id field.
+ */
+enum {
+ DVB_VBI_DATA_SERVICE_ID_EBU = 0x01,
+ DVB_VBI_DATA_SERVICE_ID_INVERTED = 0x02,
+ DVB_VBI_DATA_SERVICE_ID_VPS = 0x04,
+ DVB_VBI_DATA_SERVICE_ID_WSS = 0x05,
+ DVB_VBI_DATA_SERVICE_ID_CC = 0x06,
+ DVB_VBI_DATA_SERVICE_ID_MONO_422 = 0x07,
+};
+
+/**
+ * dvb_vbi_data_descriptor structure
+ */
+struct dvb_vbi_data_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_vbi_data_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the dvb_vbi_data_descriptor entries field.
+ */
+struct dvb_vbi_data_entry {
+ uint8_t data_service_id;
+ uint8_t data_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Format of the dvb_vbi_data_entry data field, if data_service_id == 1,2,4,5,6,7.
+ */
+struct dvb_vbi_data_x {
+ EBIT3(uint8_t reserved : 2; ,
+ uint8_t field_parity : 1; ,
+ uint8_t line_offset : 5; );
+} __ucsi_packed;
+
+/**
+ * Process a dvb_vbi_data_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return dvb_vbi_data_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_vbi_data_descriptor*
+ dvb_vbi_data_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* p = (uint8_t*) d + 2;
+ uint32_t pos = 0;
+ uint32_t len = d->len;
+
+ while(pos < len) {
+ struct dvb_vbi_data_entry *e =
+ (struct dvb_vbi_data_entry*) (p+pos);
+
+ pos += sizeof(struct dvb_vbi_data_entry);
+
+ if (pos > len)
+ return NULL;
+
+ pos += e->data_length;
+
+ if (pos > len)
+ return NULL;
+ }
+
+ return (struct dvb_vbi_data_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field in a dvb_vbi_data_descriptor structure.
+ *
+ * @param d Pointer to dvb_vbi_data_descriptor structure.
+ * @param pos Variable holding pointer to the current dvb_vbi_data_entry structure.
+ */
+#define dvb_vbi_data_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_vbi_data_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_vbi_data_descriptor_entries_next(d, pos))
+
+/**
+ * Get a pointer to the data field of a dvb_vbi_data_entry.
+ *
+ * @param d dvb_vbi_data_entry structure.
+ * @return Pointer to the data field.
+ */
+static inline uint8_t *
+ dvb_vbi_data_entry_data(struct dvb_vbi_data_entry *d)
+{
+ return (uint8_t *) d + sizeof(struct dvb_vbi_data_entry);
+}
+
+/**
+ * Get a pointer to the data field of a dvb_vbi_data_x for id 1,2,4,5,6,7.
+ *
+ * @param d dvb_vbi_data_entry structure.
+ * @return Pointer to the data field, or NULL if invalid
+ */
+static inline struct dvb_vbi_data_x*
+ dvb_vbi_data_entry_data_x(struct dvb_vbi_data_entry *d)
+{
+ switch(d->data_service_id) {
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ return (struct dvb_vbi_data_x*) ((uint8_t *) d + sizeof(struct dvb_vbi_data_entry));
+ }
+
+ return NULL;
+}
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_vbi_data_entry*
+ dvb_vbi_data_descriptor_entries_first(struct dvb_vbi_data_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_vbi_data_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_vbi_data_descriptor));
+}
+
+static inline struct dvb_vbi_data_entry*
+ dvb_vbi_data_descriptor_entries_next(struct dvb_vbi_data_descriptor *d,
+ struct dvb_vbi_data_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_vbi_data_entry) +
+ pos->data_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_vbi_data_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/dvb/vbi_teletext_descriptor.h b/lib/libucsi/dvb/vbi_teletext_descriptor.h
new file mode 100644
index 0000000..fd779d7
--- /dev/null
+++ b/lib/libucsi/dvb/vbi_teletext_descriptor.h
@@ -0,0 +1,116 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_DVB_VBI_TELETEXT_DESCRIPTOR
+#define _UCSI_DVB_VBI_TELETEXT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * dvb_vbi_teletext_descriptor structure
+ */
+struct dvb_vbi_teletext_descriptor {
+ struct descriptor d;
+
+ /* struct dvb_vbi_teletext_entry entries[] */
+} __ucsi_packed;
+
+/**
+ * An entry in a dvb_vbi_teletext_descriptor structure.
+ */
+struct dvb_vbi_teletext_entry {
+ iso639lang_t language_code;
+ EBIT2(uint8_t type : 5; ,
+ uint8_t magazine_number: 3; );
+ uint8_t page_number;
+} __ucsi_packed;
+
+/**
+ * Process an dvb_vbi_teletext_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return dvb_vbi_teletext_descriptor pointer, or NULL on error.
+ */
+static inline struct dvb_vbi_teletext_descriptor*
+ dvb_vbi_teletext_descriptor_codec(struct descriptor* d)
+{
+ if (d->len % sizeof(struct dvb_vbi_teletext_entry))
+ return NULL;
+
+ return (struct dvb_vbi_teletext_descriptor*) d;
+}
+
+/**
+ * Iterator for entries field of a dvb_vbi_teletext_descriptor.
+ *
+ * @param d Pointer to dvb_vbi_teletext_descriptor.
+ * @param pos Variable holding a pointer to the current dvb_vbi_teletext_entry.
+ */
+#define dvb_vbi_teletext_descriptor_entries_for_each(d, pos) \
+ for ((pos) = dvb_vbi_teletext_descriptor_entries_first(d); \
+ (pos); \
+ (pos) = dvb_vbi_teletext_descriptor_entries_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct dvb_vbi_teletext_entry*
+ dvb_vbi_teletext_descriptor_entries_first(struct dvb_vbi_teletext_descriptor *d)
+{
+ if (d->d.len == 0)
+ return NULL;
+
+ return (struct dvb_vbi_teletext_entry *)
+ ((uint8_t*) d + sizeof(struct dvb_vbi_teletext_descriptor));
+}
+
+static inline struct dvb_vbi_teletext_entry*
+ dvb_vbi_teletext_descriptor_entries_next(struct dvb_vbi_teletext_descriptor *d,
+ struct dvb_vbi_teletext_entry *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct dvb_vbi_teletext_entry);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct dvb_vbi_teletext_entry *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/endianops.h b/lib/libucsi/endianops.h
new file mode 100644
index 0000000..23b418b
--- /dev/null
+++ b/lib/libucsi/endianops.h
@@ -0,0 +1,128 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_COMMON_H
+#define _UCSI_COMMON_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+#include <byteswap.h>
+#include <endian.h>
+
+#define __ucsi_packed __attribute__((packed))
+
+
+
+
+#if __BYTE_ORDER == __BIG_ENDIAN
+#define EBIT2(x1,x2) x1 x2
+#define EBIT3(x1,x2,x3) x1 x2 x3
+#define EBIT4(x1,x2,x3,x4) x1 x2 x3 x4
+#define EBIT5(x1,x2,x3,x4,x5) x1 x2 x3 x4 x5
+#define EBIT6(x1,x2,x3,x4,x5,x6) x1 x2 x3 x4 x5 x6
+#define EBIT7(x1,x2,x3,x4,x5,x6,x7) x1 x2 x3 x4 x5 x6 x7
+#define EBIT8(x1,x2,x3,x4,x5,x6,x7,x8) x1 x2 x3 x4 x5 x6 x7 x8
+
+static inline void bswap16(uint8_t *buf) {
+ (void) buf;
+}
+
+static inline void bswap32(uint8_t *buf) {
+ (void) buf;
+}
+
+static inline void bswap64(uint8_t *buf) {
+ (void) buf;
+}
+
+static inline void bswap24(uint8_t *buf) {
+ (void) buf;
+}
+
+static inline void bswap40(uint8_t *buf) {
+ (void) buf;
+}
+
+static inline void bswap48(uint8_t *buf) {
+ (void) buf;
+}
+
+#else
+#define EBIT2(x1,x2) x2 x1
+#define EBIT3(x1,x2,x3) x3 x2 x1
+#define EBIT4(x1,x2,x3,x4) x4 x3 x2 x1
+#define EBIT5(x1,x2,x3,x4,x5) x5 x4 x3 x2 x1
+#define EBIT6(x1,x2,x3,x4,x5,x6) x6 x5 x4 x3 x2 x1
+#define EBIT7(x1,x2,x3,x4,x5,x6,x7) x7 x6 x5 x4 x3 x2 x1
+#define EBIT8(x1,x2,x3,x4,x5,x6,x7,x8) x8 x7 x6 x5 x4 x3 x2 x1
+
+static inline void bswap16(uint8_t * buf) {
+ *((uint16_t*)buf) = bswap_16((*(uint16_t*)buf));
+}
+
+static inline void bswap32(uint8_t * buf) {
+ *((uint32_t*)buf) = bswap_32((*(uint32_t*)buf));
+}
+
+static inline void bswap64(uint8_t * buf) {
+ *((uint64_t*)buf) = bswap_64((*(uint64_t*)buf));
+}
+
+static inline void bswap24(uint8_t * buf) {
+ uint8_t tmp0 = buf[0];
+
+ buf[0] = buf[2];
+ buf[2] = tmp0;
+}
+
+static inline void bswap40(uint8_t * buf) {
+ uint8_t tmp0 = buf[0];
+ uint8_t tmp1 = buf[1];
+
+ buf[0] = buf[4];
+ buf[1] = buf[3];
+ buf[3] = tmp1;
+ buf[4] = tmp0;
+}
+
+static inline void bswap48(uint8_t * buf) {
+ uint8_t tmp0 = buf[0];
+ uint8_t tmp1 = buf[1];
+ uint8_t tmp2 = buf[2];
+
+ buf[0] = buf[5];
+ buf[1] = buf[4];
+ buf[2] = buf[3];
+ buf[3] = tmp2;
+ buf[4] = tmp1;
+ buf[5] = tmp0;
+}
+
+#endif // __BYTE_ORDER
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/Makefile b/lib/libucsi/mpeg/Makefile
new file mode 100644
index 0000000..ace8808
--- /dev/null
+++ b/lib/libucsi/mpeg/Makefile
@@ -0,0 +1,65 @@
+# Makefile for linuxtv.org dvb-apps/lib/libucsi/mpeg
+
+.PHONY: sub-error-mpeg
+
+sub-error-mpeg:
+ $(error You can't use this makefile directly.)
+
+ifneq ($(lib_name),)
+
+objects += mpeg/cat_section.o \
+ mpeg/metadata_section.o \
+ mpeg/odsmt_section.o \
+ mpeg/pat_section.o \
+ mpeg/pmt_section.o \
+ mpeg/tsdt_section.o
+
+sub-install += mpeg
+
+else
+
+includes = audio_stream_descriptor.h \
+ ca_descriptor.h \
+ cat_section.h \
+ content_labelling_descriptor.h \
+ copyright_descriptor.h \
+ data_stream_alignment_descriptor.h \
+ descriptor.h \
+ external_es_id_descriptor.h \
+ fmc_descriptor.h \
+ fmxbuffer_size_descriptor.h \
+ hierarchy_descriptor.h \
+ ibp_descriptor.h \
+ iod_descriptor.h \
+ iso_639_language_descriptor.h \
+ maximum_bitrate_descriptor.h \
+ metadata_descriptor.h \
+ metadata_pointer_descriptor.h \
+ metadata_section.h \
+ metadata_std_descriptor.h \
+ mpeg4_audio_descriptor.h \
+ mpeg4_video_descriptor.h \
+ multiplex_buffer_descriptor.h \
+ multiplex_buffer_utilization_descriptor.h \
+ muxcode_descriptor.h \
+ odsmt_section.h \
+ pat_section.h \
+ pmt_section.h \
+ private_data_indicator_descriptor.h \
+ registration_descriptor.h \
+ section.h \
+ sl_descriptor.h \
+ smoothing_buffer_descriptor.h \
+ std_descriptor.h \
+ system_clock_descriptor.h \
+ target_background_grid_descriptor.h \
+ tsdt_section.h \
+ types.h \
+ video_stream_descriptor.h \
+ video_window_descriptor.h
+
+include ../../../Make.rules
+
+lib_name = libucsi/mpeg
+
+endif
diff --git a/lib/libucsi/mpeg/audio_stream_descriptor.h b/lib/libucsi/mpeg/audio_stream_descriptor.h
new file mode 100644
index 0000000..7e6ea07
--- /dev/null
+++ b/lib/libucsi/mpeg/audio_stream_descriptor.h
@@ -0,0 +1,65 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_AUDIO_STREAM_DESCRIPTOR
+#define _UCSI_MPEG_AUDIO_STREAM_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_audio_stream_descriptor structure
+ */
+struct mpeg_audio_stream_descriptor {
+ struct descriptor d;
+
+ EBIT5(uint8_t free_format_flag : 1; ,
+ uint8_t id : 1; ,
+ uint8_t layer : 2; ,
+ uint8_t variable_rate_audio_indicator : 1; ,
+ uint8_t reserved : 3; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_audio_stream_descriptor.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_audio_stream_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_audio_stream_descriptor*
+ mpeg_audio_stream_descriptor_codec(struct descriptor *d)
+{
+ if (d->len != (sizeof(struct mpeg_audio_stream_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_audio_stream_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/ca_descriptor.h b/lib/libucsi/mpeg/ca_descriptor.h
new file mode 100644
index 0000000..88a65dd
--- /dev/null
+++ b/lib/libucsi/mpeg/ca_descriptor.h
@@ -0,0 +1,91 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_CA_DESCRIPTOR
+#define _UCSI_MPEG_CA_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_ca_descriptor structure
+ */
+struct mpeg_ca_descriptor {
+ struct descriptor d;
+
+ uint16_t ca_system_id;
+ EBIT2(uint16_t reserved : 3; ,
+ uint16_t ca_pid : 13; );
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_ca_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return Pointer to an mpeg_ca_descriptor, or NULL on error.
+ */
+static inline struct mpeg_ca_descriptor*
+ mpeg_ca_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct mpeg_ca_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 4);
+
+ return (struct mpeg_ca_descriptor*) d;
+}
+
+/**
+ * Accessor for pointer to data field of an mpeg_ca_descriptor.
+ *
+ * @param d The mpeg_ca_descriptor structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ mpeg_ca_descriptor_data(struct mpeg_ca_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_ca_descriptor);
+}
+
+/**
+ * Determine length of data field of an mpeg_ca_descriptor.
+ *
+ * @param d The mpeg_ca_descriptor structure.
+ * @return Length of the field in bytes.
+ */
+static inline int
+ mpeg_ca_descriptor_data_length(struct mpeg_ca_descriptor *d)
+{
+ return d->d.len - 4;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/cat_section.c b/lib/libucsi/mpeg/cat_section.c
new file mode 100644
index 0000000..8c974b8
--- /dev/null
+++ b/lib/libucsi/mpeg/cat_section.c
@@ -0,0 +1,34 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/cat_section.h>
+
+struct mpeg_cat_section * mpeg_cat_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *)ext;
+ size_t pos = sizeof(struct section_ext);
+
+ if (verify_descriptors(buf + pos,
+ section_ext_length(ext) - sizeof(struct mpeg_cat_section)))
+ return NULL;
+
+ return (struct mpeg_cat_section *)ext;
+}
diff --git a/lib/libucsi/mpeg/cat_section.h b/lib/libucsi/mpeg/cat_section.h
new file mode 100644
index 0000000..7ed34a3
--- /dev/null
+++ b/lib/libucsi/mpeg/cat_section.h
@@ -0,0 +1,94 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_CAT_SECTION_H
+#define _UCSI_MPEG_CAT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_cat_section structure.
+ */
+struct mpeg_cat_section {
+ struct section_ext head;
+
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_cat_section.
+ *
+ * @param section The generic section_ext structure.
+ * @return Pointer to an mpeg_cat_section structure, or NULL on error.
+ */
+extern struct mpeg_cat_section *mpeg_cat_section_codec(struct section_ext *section);
+
+/**
+ * Convenience iterator for descriptors field of an mpeg_cat_section.
+ *
+ * @param cat The mpeg_cat_section pointer.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define mpeg_cat_section_descriptors_for_each(cat, pos) \
+ for ((pos) = mpeg_cat_section_descriptors_first(cat); \
+ (pos); \
+ (pos) = mpeg_cat_section_descriptors_next(cat, pos))
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ mpeg_cat_section_descriptors_first(struct mpeg_cat_section *cat)
+{
+ size_t pos = sizeof(struct mpeg_cat_section);
+
+ if (pos >= section_ext_length(&cat->head))
+ return NULL;
+
+ return (struct descriptor*)((uint8_t *) cat + pos);
+}
+
+
+static inline struct descriptor *
+ mpeg_cat_section_descriptors_next(struct mpeg_cat_section *cat,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t *) cat + sizeof(struct mpeg_cat_section),
+ section_ext_length(&cat->head) - sizeof(struct mpeg_cat_section),
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/content_labelling_descriptor.h b/lib/libucsi/mpeg/content_labelling_descriptor.h
new file mode 100644
index 0000000..06738ab
--- /dev/null
+++ b/lib/libucsi/mpeg/content_labelling_descriptor.h
@@ -0,0 +1,356 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_CONTENT_LABELLING_DESCRIPTOR
+#define _UCSI_MPEG_CONTENT_LABELLING_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for content_time_base_indicator.
+ */
+enum {
+ MPEG_CONTENT_TIME_BASE_STC = 0x01,
+ MPEG_CONTENT_TIME_BASE_NPT = 0x02,
+};
+
+/**
+ * mpeg_content_labelling_descriptor structure.
+ */
+struct mpeg_content_labelling_descriptor {
+ struct descriptor d;
+
+ uint16_t metadata_application_format;
+ /* struct mpeg_content_labelling_descriptor_application_format_identifier id */
+ /* struct mpeg_content_labelling_descriptor_flags flags */
+ /* struct mpeg_content_labelling_descriptor_reference_id reference_id */
+ /* struct mpeg_content_labelling_descriptor_time_base time_base */
+ /* struct mpeg_content_labelling_descriptor_content_id content_id */
+ /* struct mpeg_content_labelling_descriptor_time_base_association time_base_assoc */
+ /* uint8_t private_data[] */
+} __ucsi_packed;
+
+/**
+ * id field of a content_labelling_descriptor.
+ */
+struct mpeg_content_labelling_descriptor_application_format_identifier {
+ uint32_t id;
+} __ucsi_packed;
+
+/**
+ * Flags field of a content_labelling_descriptor
+ */
+struct mpeg_content_labelling_descriptor_flags {
+ EBIT3(uint8_t content_reference_id_record_flag : 1; ,
+ uint8_t content_time_base_indicator : 4; ,
+ uint8_t reserved : 3; );
+} __ucsi_packed;
+
+/**
+ * Reference_id field of a content_labelling_descriptor.
+ */
+struct mpeg_content_labelling_descriptor_reference_id {
+ uint8_t content_reference_id_record_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * time_base field of a content_labelling_descriptor.
+ */
+struct mpeg_content_labelling_descriptor_time_base {
+ EBIT2(uint64_t reserved_1 : 7; ,
+ uint64_t content_time_base_value :33; );
+ EBIT2(uint64_t reserved_2 : 7; ,
+ uint64_t metadata_time_base_value :33; );
+} __ucsi_packed;
+
+/**
+ * content_id field of a content_labelling_descriptor.
+ */
+struct mpeg_content_labelling_descriptor_content_id {
+ EBIT2(uint8_t reserved : 1; ,
+ uint8_t contentId : 7; );
+} __ucsi_packed;
+
+/**
+ * time_base_assoc field of a content_labelling_descriptor.
+ */
+struct mpeg_content_labelling_descriptor_time_base_association {
+ uint8_t time_base_association_data_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+
+
+/**
+ * Process an mpeg_content_labelling_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return Pointer to an mpeg_content_labelling_descriptor, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor*
+ mpeg_content_labelling_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 2;
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len + 2;
+ struct mpeg_content_labelling_descriptor_flags *flags;
+ int id;
+
+ if (len < sizeof(struct mpeg_content_labelling_descriptor))
+ return NULL;
+
+ bswap16(buf + pos);
+ id = *((uint16_t*) (buf+pos));
+ pos += 2;
+
+ if (id == 0xffff) {
+ if (len < (pos+4))
+ return NULL;
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_flags)))
+ return NULL;
+ flags = (struct mpeg_content_labelling_descriptor_flags*) (buf+pos);
+ pos += sizeof(struct mpeg_content_labelling_descriptor_flags);
+
+ if (flags->content_reference_id_record_flag == 1) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if ((flags->content_time_base_indicator == 1) ||
+ (flags->content_time_base_indicator == 2)) {
+ if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_time_base)))
+ return NULL;
+ bswap40(buf+pos);
+ bswap40(buf+pos+5);
+ pos += sizeof(struct mpeg_content_labelling_descriptor_time_base);
+ }
+
+ if (flags->content_time_base_indicator == 2) {
+ if (len < (pos + sizeof(struct mpeg_content_labelling_descriptor_content_id)))
+ return NULL;
+ pos += sizeof(struct mpeg_content_labelling_descriptor_content_id);
+ }
+
+ if (flags->content_time_base_indicator > 2) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (len < pos)
+ return NULL;
+
+ return (struct mpeg_content_labelling_descriptor*) d;
+}
+
+/**
+ * Accessor for pointer to id field of an mpeg_content_labelling_descriptor.
+ *
+ * @param d The mpeg_content_labelling_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_application_format_identifier*
+ mpeg_content_labelling_descriptor_id(struct mpeg_content_labelling_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d;
+
+ if (d->metadata_application_format != 0xffff)
+ return NULL;
+ return (struct mpeg_content_labelling_descriptor_application_format_identifier*)
+ (buf + sizeof(struct mpeg_content_labelling_descriptor));
+}
+
+/**
+ * Accessor for pointer to flags field of an mpeg_content_labelling_descriptor.
+ *
+ * @param d The mpeg_content_labelling_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_flags*
+ mpeg_content_labelling_descriptor_flags(struct mpeg_content_labelling_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor);
+
+ if (d->metadata_application_format != 0xffff)
+ buf += 4;
+
+ return (struct mpeg_content_labelling_descriptor_flags *) buf;
+}
+
+/**
+ * Accessor for reference_id field of an mpeg_content_labelling_descriptor.
+ *
+ * @param flags Pointer to the mpeg_content_labelling_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_reference_id*
+ mpeg_content_labelling_descriptor_reference_id(struct mpeg_content_labelling_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags);
+
+ if (flags->content_reference_id_record_flag != 1)
+ return NULL;
+
+ return (struct mpeg_content_labelling_descriptor_reference_id *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_content_reference_id.
+ *
+ * @param d The mpeg_content_reference_id structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_content_reference_id_data(struct mpeg_content_labelling_descriptor_reference_id *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor_reference_id);
+}
+
+/**
+ * Accessor for time_base field of an mpeg_content_labelling_descriptor.
+ *
+ * @param flags Pointer to the mpeg_content_labelling_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_time_base*
+ mpeg_content_labelling_descriptor_time_base(struct mpeg_content_labelling_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags);
+
+ if ((flags->content_time_base_indicator!=1) && (flags->content_time_base_indicator!=2))
+ return NULL;
+
+ if (flags->content_reference_id_record_flag == 1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_content_labelling_descriptor_time_base *) buf;
+}
+
+/**
+ * Accessor for content_id field of an mpeg_content_labelling_descriptor.
+ *
+ * @param flags Pointer to the mpeg_content_labelling_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_content_id*
+ mpeg_content_labelling_descriptor_content_id(struct mpeg_content_labelling_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags);
+
+ if (flags->content_time_base_indicator!=2)
+ return NULL;
+
+ if (flags->content_reference_id_record_flag == 1)
+ buf += 1 + buf[1];
+ if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2))
+ buf += sizeof(struct mpeg_content_labelling_descriptor_time_base);
+
+ return (struct mpeg_content_labelling_descriptor_content_id *) buf;
+}
+
+/**
+ * Accessor for time_base_association field of an mpeg_content_labelling_descriptor.
+ *
+ * @param flags Pointer to the mpeg_content_labelling_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_content_labelling_descriptor_time_base_association*
+ mpeg_content_labelling_descriptor_time_base_assoc(struct mpeg_content_labelling_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags);
+
+ if (flags->content_time_base_indicator<3)
+ return NULL;
+
+ if (flags->content_reference_id_record_flag == 1)
+ buf += 1 + buf[1];
+ if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2))
+ buf += sizeof(struct mpeg_content_labelling_descriptor_time_base);
+ if (flags->content_time_base_indicator==2)
+ buf += sizeof(struct mpeg_content_labelling_descriptor_content_id);
+
+ return (struct mpeg_content_labelling_descriptor_time_base_association *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_time_base_association.
+ *
+ * @param d The mpeg_time_base_association structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_time_base_association_data(struct mpeg_content_labelling_descriptor_time_base_association *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_content_labelling_descriptor_time_base_association);
+}
+
+
+/**
+ * Accessor for private_data field of an mpeg_content_labelling_descriptor.
+ *
+ * @param d The mpeg_content_labelling_descriptor structure.
+ * @param flags Pointer to the mpeg_content_labelling_descriptor_flags.
+ * @param length Where the number of bytes in the field should be stored.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_content_labelling_descriptor_data(struct mpeg_content_labelling_descriptor *d,
+ struct mpeg_content_labelling_descriptor_flags *flags,
+ int *length)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_content_labelling_descriptor_flags);
+ uint8_t *end = (uint8_t*) d + d->d.len + 2;
+
+ if (flags->content_reference_id_record_flag == 1)
+ buf += 1 + buf[1];
+ if ((flags->content_time_base_indicator==1) || (flags->content_time_base_indicator==2))
+ buf += sizeof(struct mpeg_content_labelling_descriptor_time_base);
+ if (flags->content_time_base_indicator==2)
+ buf += sizeof(struct mpeg_content_labelling_descriptor_content_id);
+ if (flags->content_time_base_indicator<3)
+ buf += 1 + buf[1];
+
+ *length = end - buf;
+
+ return buf;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/copyright_descriptor.h b/lib/libucsi/mpeg/copyright_descriptor.h
new file mode 100644
index 0000000..5991fe9
--- /dev/null
+++ b/lib/libucsi/mpeg/copyright_descriptor.h
@@ -0,0 +1,89 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_COPYRIGHT_DESCRIPTOR
+#define _UCSI_MPEG_COPYRIGHT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_copyright_descriptor structure.
+ */
+struct mpeg_copyright_descriptor {
+ struct descriptor d;
+
+ uint32_t copyright_identifier;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_copyright_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return mpeg_copyright_descriptor pointer, or NULL on error.
+ */
+static inline struct mpeg_copyright_descriptor*
+ mpeg_copyright_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct mpeg_copyright_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct mpeg_copyright_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to data field of an mpeg_copyright_descriptor.
+ *
+ * @param d mpeg_copyright_descriptor pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ mpeg_copyright_descriptor_data(struct mpeg_copyright_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_copyright_descriptor);
+}
+
+
+/**
+ * Determine length of the data field of an mpeg_copyright_descriptor.
+ *
+ * @param d mpeg_copyright_descriptor pointer.
+ * @return Length of field in bytes.
+ */
+static inline int
+ mpeg_copyright_descriptor_data_length(struct mpeg_copyright_descriptor *d)
+{
+ return d->d.len - 4;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/data_stream_alignment_descriptor.h b/lib/libucsi/mpeg/data_stream_alignment_descriptor.h
new file mode 100644
index 0000000..887495f
--- /dev/null
+++ b/lib/libucsi/mpeg/data_stream_alignment_descriptor.h
@@ -0,0 +1,73 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_DATA_STREAM_ALIGNMENT_DESCRIPTOR
+#define _UCSI_MPEG_DATA_STREAM_ALIGNMENT_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for alignment_type.
+ */
+enum {
+ MPEG_DATA_STREAM_ALIGNMENT_VIDEO_SLICE_OR_AU = 0x01,
+ MPEG_DATA_STREAM_ALIGNMENT_VIDEO_AU = 0x02,
+ MPEG_DATA_STREAM_ALIGNMENT_VIDEO_GOP_OR_SEQ = 0x03,
+ MPEG_DATA_STREAM_ALIGNMENT_VIDEO_SEQ = 0x04,
+
+ MPEG_DATA_STREAM_ALIGNMENT_AUDIO_SYNC_WORD = 0x01,
+};
+
+/**
+ * mpeg_data_stream_alignment_descriptor structure.
+ */
+struct mpeg_data_stream_alignment_descriptor {
+ struct descriptor d;
+
+ uint8_t alignment_type;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_data_stream_alignment_descriptor.
+ *
+ * @param d Pointer to generic descriptor structure.
+ * @return Pointer to mpeg_data_stream_alignment_descriptor, or NULL on error.
+ */
+static inline struct mpeg_data_stream_alignment_descriptor*
+ mpeg_data_stream_alignment_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_data_stream_alignment_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_data_stream_alignment_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/descriptor.h b/lib/libucsi/mpeg/descriptor.h
new file mode 100644
index 0000000..c32775f
--- /dev/null
+++ b/lib/libucsi/mpeg/descriptor.h
@@ -0,0 +1,102 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_DESCRIPTOR_H
+#define _UCSI_MPEG_DESCRIPTOR_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/mpeg/mpeg4_audio_descriptor.h>
+#include <libucsi/mpeg/mpeg4_video_descriptor.h>
+#include <libucsi/mpeg/audio_stream_descriptor.h>
+#include <libucsi/mpeg/ca_descriptor.h>
+#include <libucsi/mpeg/content_labelling_descriptor.h>
+#include <libucsi/mpeg/copyright_descriptor.h>
+#include <libucsi/mpeg/data_stream_alignment_descriptor.h>
+#include <libucsi/mpeg/external_es_id_descriptor.h>
+#include <libucsi/mpeg/fmc_descriptor.h>
+#include <libucsi/mpeg/fmxbuffer_size_descriptor.h>
+#include <libucsi/mpeg/hierarchy_descriptor.h>
+#include <libucsi/mpeg/ibp_descriptor.h>
+#include <libucsi/mpeg/iod_descriptor.h>
+#include <libucsi/mpeg/iso_639_language_descriptor.h>
+#include <libucsi/mpeg/maximum_bitrate_descriptor.h>
+#include <libucsi/mpeg/metadata_descriptor.h>
+#include <libucsi/mpeg/metadata_pointer_descriptor.h>
+#include <libucsi/mpeg/metadata_std_descriptor.h>
+#include <libucsi/mpeg/multiplex_buffer_descriptor.h>
+#include <libucsi/mpeg/multiplex_buffer_utilization_descriptor.h>
+#include <libucsi/mpeg/muxcode_descriptor.h>
+#include <libucsi/mpeg/private_data_indicator_descriptor.h>
+#include <libucsi/mpeg/registration_descriptor.h>
+#include <libucsi/mpeg/sl_descriptor.h>
+#include <libucsi/mpeg/smoothing_buffer_descriptor.h>
+#include <libucsi/mpeg/std_descriptor.h>
+#include <libucsi/mpeg/system_clock_descriptor.h>
+#include <libucsi/mpeg/target_background_grid_descriptor.h>
+#include <libucsi/mpeg/video_stream_descriptor.h>
+#include <libucsi/mpeg/video_window_descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Enumeration of MPEG descriptor tags.
+ */
+enum mpeg_descriptor_tag {
+ dtag_mpeg_video_stream = 0x02,
+ dtag_mpeg_audio_stream = 0x03,
+ dtag_mpeg_hierarchy = 0x04,
+ dtag_mpeg_registration = 0x05,
+ dtag_mpeg_data_stream_alignment = 0x06,
+ dtag_mpeg_target_background_grid = 0x07,
+ dtag_mpeg_video_window = 0x08,
+ dtag_mpeg_ca = 0x09,
+ dtag_mpeg_iso_639_language = 0x0a,
+ dtag_mpeg_system_clock = 0x0b,
+ dtag_mpeg_multiplex_buffer_utilization = 0x0c,
+ dtag_mpeg_copyright = 0x0d,
+ dtag_mpeg_maximum_bitrate = 0x0e,
+ dtag_mpeg_private_data_indicator = 0x0f,
+ dtag_mpeg_smoothing_buffer = 0x10,
+ dtag_mpeg_std = 0x11,
+ dtag_mpeg_ibp = 0x12,
+ dtag_mpeg_4_video = 0x1b,
+ dtag_mpeg_4_audio = 0x1c,
+ dtag_mpeg_iod = 0x1d,
+ dtag_mpeg_sl = 0x1e,
+ dtag_mpeg_fmc = 0x1f,
+ dtag_mpeg_external_es_id = 0x20,
+ dtag_mpeg_muxcode = 0x21,
+ dtag_mpeg_fmxbuffer_size = 0x22,
+ dtag_mpeg_multiplex_buffer = 0x23,
+ dtag_mpeg_content_labelling = 0x24,
+ dtag_mpeg_metadata_pointer = 0x25,
+ dtag_mpeg_metadata = 0x26,
+ dtag_mpeg_metadata_std = 0x27,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/external_es_id_descriptor.h b/lib/libucsi/mpeg/external_es_id_descriptor.h
new file mode 100644
index 0000000..3aa3237
--- /dev/null
+++ b/lib/libucsi/mpeg/external_es_id_descriptor.h
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_EXTERNAL_ES_ID_DESCRIPTOR
+#define _UCSI_MPEG_EXTERNAL_ES_ID_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_external_es_id_descriptor structure.
+ */
+struct mpeg_external_es_id_descriptor {
+ struct descriptor d;
+
+ uint16_t external_es_id;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_external_es_id_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @return mpeg_external_es_id_descriptor pointer, or NULL on error.
+ */
+static inline struct mpeg_external_es_id_descriptor*
+ mpeg_external_es_id_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_external_es_id_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+
+ return (struct mpeg_external_es_id_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/fmc_descriptor.h b/lib/libucsi/mpeg/fmc_descriptor.h
new file mode 100644
index 0000000..5a5bed2
--- /dev/null
+++ b/lib/libucsi/mpeg/fmc_descriptor.h
@@ -0,0 +1,122 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_FMC_DESCRIPTOR
+#define _UCSI_MPEG_FMC_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_fmc_descriptor structure.
+ */
+struct mpeg_fmc_descriptor {
+ struct descriptor d;
+
+ /* struct mpeg_flex_mux muxes[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the muxes field of an mpeg_fmc_descriptor structure.
+ */
+struct mpeg_flex_mux {
+ uint16_t es_id;
+ uint8_t flex_mux_channel;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_fmc_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to an mpeg_fmc_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_fmc_descriptor*
+ mpeg_fmc_descriptor_codec(struct descriptor* d)
+{
+ uint8_t* buf = (uint8_t*) d + 2;
+ int pos = 0;
+ int len = d->len;
+
+ if (len % sizeof(struct mpeg_flex_mux))
+ return NULL;
+
+ while(pos < len) {
+ bswap16(buf+pos);
+ pos += sizeof(struct mpeg_flex_mux);
+ }
+
+ return (struct mpeg_fmc_descriptor*) d;
+}
+
+/**
+ * Convenience iterator for the muxes field of an mpeg_fmc_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @param pos Variable holding a pointer to the the current entry within the muxes field.
+ */
+#define mpeg_fmc_descriptor_muxes_for_each(d, pos) \
+ for ((pos) = mpeg_fmc_descriptor_muxes_first(d); \
+ (pos); \
+ (pos) = mpeg_fmc_descriptor_muxes_next(d, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct mpeg_flex_mux*
+ mpeg_fmc_descriptor_muxes_first(struct mpeg_fmc_descriptor *d)
+{
+ if (d->d.len < sizeof(struct mpeg_flex_mux))
+ return NULL;
+
+ return (struct mpeg_flex_mux *)
+ ((uint8_t*) d + sizeof(struct mpeg_fmc_descriptor));
+}
+
+static inline struct mpeg_flex_mux*
+ mpeg_fmc_descriptor_muxes_next(struct mpeg_fmc_descriptor *d,
+ struct mpeg_flex_mux *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct mpeg_flex_mux);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct mpeg_flex_mux *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h b/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h
new file mode 100644
index 0000000..74f643c
--- /dev/null
+++ b/lib/libucsi/mpeg/fmxbuffer_size_descriptor.h
@@ -0,0 +1,83 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_FMXBUFFER_SIZE_DESCRIPTOR
+#define _UCSI_MPEG_FMXBUFFER_SIZE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+
+/**
+ * mpeg_fmxbuffer_size_descriptor structure.
+ */
+struct mpeg_fmxbuffer_size_descriptor {
+ struct descriptor d;
+
+ /* uint8_t descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_fmxbuffer_size_descriptor structure.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return Pointer to an mpeg_fmxbuffer_size_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_fmxbuffer_size_descriptor*
+ mpeg_fmxbuffer_size_descriptor_codec(struct descriptor* d)
+{
+ return (struct mpeg_fmxbuffer_size_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to descriptors field of mpeg_fmxbuffer_size_descriptor structure.
+ *
+ * @param d mpeg_fmxbuffer_size_descriptor structure pointer.
+ * @return Pointer to the descriptors.
+ */
+static inline uint8_t *
+ mpeg_fmxbuffer_size_descriptor_descriptors(struct mpeg_fmxbuffer_size_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_fmxbuffer_size_descriptor);
+}
+
+/**
+ * Calculate the length of the descriptors field of an mpeg_fmxbuffer_size_descriptor structure.
+ *
+ * @param d mpeg_fmxbuffer_size_descriptor structure pointer.
+ * @return Length of descriptors in bytes.
+ */
+static inline int
+ mpeg_fmxbuffer_size_descriptor_descriptors_length(struct mpeg_fmxbuffer_size_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/hierarchy_descriptor.h b/lib/libucsi/mpeg/hierarchy_descriptor.h
new file mode 100644
index 0000000..a38539d
--- /dev/null
+++ b/lib/libucsi/mpeg/hierarchy_descriptor.h
@@ -0,0 +1,83 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_HIERARCHY_DESCRIPTOR
+#define _UCSI_MPEG_HIERARCHY_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Hierarchy type values.
+ */
+enum {
+ MPEG_HIERARCHY_TYPE_ISO13818_2_SPATIAL_SCALABILITY = 0x01,
+ MPEG_HIERARCHY_TYPE_ISO13818_2_SNR_SCALABILITY = 0x02,
+ MPEG_HIERARCHY_TYPE_ISO13818_2_TEMPORAL_SCALABILITY = 0x03,
+ MPEG_HIERARCHY_TYPE_ISO13818_2_DATA_PARTITIONING = 0x04,
+ MPEG_HIERARCHY_TYPE_ISO13818_3_EXTENSION_BITSTREAM = 0x05,
+ MPEG_HIERARCHY_TYPE_ISO13818_1_PRIVATE_BITSTREAM = 0x06,
+ MPEG_HIERARCHY_TYPE_ISO13818_2_MULTI_VIEW_PROFILE = 0x07,
+ MPEG_HIERARCHY_TYPE_BASE_LAYER = 0x0f,
+};
+
+
+/**
+ * mpeg_hierarchy_descriptor structure.
+ */
+struct mpeg_hierarchy_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved_1 : 4; ,
+ uint8_t hierarchy_type : 4; );
+ EBIT2(uint8_t reserved_2 : 2; ,
+ uint8_t hierarchy_layer_index : 6; );
+ EBIT2(uint8_t reserved_3 : 2; ,
+ uint8_t hierarchy_embedded_layer_index : 6; );
+ EBIT2(uint8_t reserved_4 : 2; ,
+ uint8_t hierarchy_channel : 6; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_hierarchy_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to mpeg_hierarchy_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_hierarchy_descriptor*
+ mpeg_hierarchy_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_hierarchy_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_hierarchy_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/ibp_descriptor.h b/lib/libucsi/mpeg/ibp_descriptor.h
new file mode 100644
index 0000000..e82780a
--- /dev/null
+++ b/lib/libucsi/mpeg/ibp_descriptor.h
@@ -0,0 +1,65 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_IBP_DESCRIPTOR
+#define _UCSI_MPEG_IBP_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_ibp_descriptor structure.
+ */
+struct mpeg_ibp_descriptor {
+ struct descriptor d;
+
+ EBIT3(uint16_t closed_gop_flag : 1; ,
+ uint16_t identical_gop_flag : 1; ,
+ uint16_t max_gop_length : 14; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_ibp_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to the mpeg_ibp_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_ibp_descriptor*
+ mpeg_ibp_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_ibp_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+
+ return (struct mpeg_ibp_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/iod_descriptor.h b/lib/libucsi/mpeg/iod_descriptor.h
new file mode 100644
index 0000000..61de153
--- /dev/null
+++ b/lib/libucsi/mpeg/iod_descriptor.h
@@ -0,0 +1,87 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_IOD_DESCRIPTOR
+#define _UCSI_MPEG_IOD_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_iod_descriptor structure.
+ */
+struct mpeg_iod_descriptor {
+ struct descriptor d;
+
+ uint8_t scope_of_iod_label;
+ uint8_t iod_label;
+ /* uint8_t iod[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_iod_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to an mpeg_iod_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_iod_descriptor*
+ mpeg_iod_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct mpeg_iod_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_iod_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to iod field of an mpeg_iod_descriptor structure.
+ *
+ * @param d Pointer to mpeg_iod_descriptor structure.
+ * @return Pointer to the iod field.
+ */
+static inline uint8_t *
+ mpeg_iod_descriptor_iod(struct mpeg_iod_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_iod_descriptor);
+}
+
+/**
+ * Calculate the length of the iod field of an mpeg_iod_descriptor structure.
+ *
+ * @param d Pointer to mpeg_iod_descriptor structure.
+ * @return The number of bytes.
+ */
+static inline int
+ mpeg_iod_descriptor_iod_length(struct mpeg_iod_descriptor *d)
+{
+ return d->d.len - 2;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/iso_639_language_descriptor.h b/lib/libucsi/mpeg/iso_639_language_descriptor.h
new file mode 100644
index 0000000..5b5aac0
--- /dev/null
+++ b/lib/libucsi/mpeg/iso_639_language_descriptor.h
@@ -0,0 +1,124 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_ISO_639_LANGUAGE_DESCRIPTOR
+#define _UCSI_MPEG_ISO_639_LANGUAGE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+#include <libucsi/types.h>
+
+/**
+ * Possible values for audio_type.
+ */
+enum {
+ MPEG_AUDIO_TYPE_CLEAN_EFFECTS = 0x01,
+ MPEG_AUDIO_TYPE_HEARING_IMPAIRED = 0x02,
+ MPEG_AUDIO_TYPE_VISUAL_IMPAIRED_COMMENTARY = 0x03,
+};
+
+/**
+ * mpeg_iso_639_language_descriptor structure.
+ */
+struct mpeg_iso_639_language_descriptor {
+ struct descriptor d;
+
+ /* struct mpeg_iso_639_language_code languages[] */
+} __ucsi_packed;
+
+/**
+ * An entry in the mpeg_iso_639_language_descriptor languages field.
+ */
+struct mpeg_iso_639_language_code {
+ iso639lang_t language_code;
+ uint8_t audio_type;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_iso_639_language_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to an mpeg_iso_639_language_descriptor structure, or NULL
+ * on error.
+ */
+static inline struct mpeg_iso_639_language_descriptor*
+ mpeg_iso_639_language_descriptor_codec(struct descriptor* d)
+{
+ if (d->len % sizeof(struct mpeg_iso_639_language_code))
+ return NULL;
+
+ return (struct mpeg_iso_639_language_descriptor*) d;
+}
+
+/**
+ * Convenience iterator for the languages field of an mpeg_iso_639_language_descriptor
+ *
+ * @param d Pointer to the mpeg_iso_639_language_descriptor structure.
+ * @param pos Variable holding a pointer to the current entry.
+ */
+#define mpeg_iso_639_language_descriptor_languages_for_each(_d, _pos) \
+ for ((_pos) = mpeg_iso_639_language_descriptor_languages_first(_d); \
+ (_pos); \
+ (_pos) = mpeg_iso_639_language_descriptor_languages_next(_d, _pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct mpeg_iso_639_language_code*
+ mpeg_iso_639_language_descriptor_languages_first(struct mpeg_iso_639_language_descriptor *d)
+{
+ if (d->d.len < sizeof(struct mpeg_iso_639_language_code))
+ return NULL;
+
+ return (struct mpeg_iso_639_language_code *)
+ ((uint8_t*) d + sizeof(struct mpeg_iso_639_language_descriptor));
+}
+
+static inline struct mpeg_iso_639_language_code*
+ mpeg_iso_639_language_descriptor_languages_next(struct mpeg_iso_639_language_descriptor *d,
+ struct mpeg_iso_639_language_code *pos)
+{
+ uint8_t *end = (uint8_t*) d + 2 + d->d.len;
+ uint8_t *next = (uint8_t *) pos + sizeof(struct mpeg_iso_639_language_code);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct mpeg_iso_639_language_code *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/maximum_bitrate_descriptor.h b/lib/libucsi/mpeg/maximum_bitrate_descriptor.h
new file mode 100644
index 0000000..e0bcddb
--- /dev/null
+++ b/lib/libucsi/mpeg/maximum_bitrate_descriptor.h
@@ -0,0 +1,64 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_MAXIMUM_BITRATE_DESCRIPTOR
+#define _UCSI_MPEG_MAXIMUM_BITRATE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_maximum_bitrate_descriptor structure.
+ */
+struct mpeg_maximum_bitrate_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint32_t reserved : 2; ,
+ uint32_t maximum_bitrate : 22; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_maximum_bitrate_descriptor.
+ *
+ * @param d Pointer to generic descriptor structure.
+ * @return Pointer to mpeg_maximum_bitrate_descriptor, or NULL on error.
+ */
+static inline struct mpeg_maximum_bitrate_descriptor*
+ mpeg_maximum_bitrate_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_maximum_bitrate_descriptor) - 2))
+ return NULL;
+
+ bswap24((uint8_t*) d + 2);
+
+ return (struct mpeg_maximum_bitrate_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/metadata_descriptor.h b/lib/libucsi/mpeg/metadata_descriptor.h
new file mode 100644
index 0000000..5b91e05
--- /dev/null
+++ b/lib/libucsi/mpeg/metadata_descriptor.h
@@ -0,0 +1,472 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_METADATA_DESCRIPTOR
+#define _UCSI_MPEG_METADATA_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Values for the decoder_config_flags field.
+ */
+enum {
+ MPEG_DECODER_CONFIG_NONE = 0x00,
+ MPEG_DECODER_CONFIG_IN_DECODER_CONFIG = 0x01,
+ MPEG_DECODER_CONFIG_SAME_METADATA_SERVICE = 0x02,
+ MPEG_DECODER_CONFIG_DSMCC = 0x03,
+ MPEG_DECODER_CONFIG_SAME_PROGRAM = 0x04,
+};
+
+/**
+ * mpeg_metadata_descriptor structure.
+ */
+struct mpeg_metadata_descriptor {
+ struct descriptor d;
+
+ uint16_t metadata_application_format;
+ /* struct mpeg_metadata_descriptor_application_format_identifier appid */
+ /* uint8_t metadata_format */
+ /* struct mpeg_metadata_descriptor_format_identifier formid */
+ /* struct mpeg_metadata_descriptor_flags flags */
+ /* struct mpeg_metadata_descriptor_service_identifier service_identifier */
+ /* struct mpeg_metadata_descriptor_decoder_config decoder_config */
+ /* struct mpeg_metadata_descriptor_decoder_config_id_record decoder_config_id_record */
+ /* struct mpeg_metadata_descriptor_decoder_config_service_id decoder_config_service_id */
+ /* struct mpeg_metadata_descriptor_decoder_config_reserved decoder_config_reserved */
+ /* uint8_t private_data[] */
+} __ucsi_packed;
+
+/**
+ * appid field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_application_format_identifier {
+ uint32_t id;
+} __ucsi_packed;
+
+/**
+ * formid field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_format_identifier {
+ uint32_t id;
+} __ucsi_packed;
+
+/**
+ * Flags field of a metadata_descriptor
+ */
+struct mpeg_metadata_descriptor_flags {
+ uint8_t metadata_service_id;
+ EBIT3(uint8_t decoder_config_flags : 3; ,
+ uint8_t dsm_cc_flag : 1; ,
+ uint8_t reserved : 4; );
+} __ucsi_packed;
+
+/**
+ * service_identifier field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_service_identifier {
+ uint8_t service_identification_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * decoder_config field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_decoder_config {
+ uint8_t decoder_config_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * decoder_config_id_record field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_decoder_config_id_record {
+ uint8_t decoder_config_id_record_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * decoder_config_service_id field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_decoder_config_service_id {
+ uint8_t decoder_config_metadata_service_id;
+} __ucsi_packed;
+
+/**
+ * decoder_config_reserved field of a metadata_descriptor.
+ */
+struct mpeg_metadata_descriptor_decoder_config_reserved {
+ uint8_t reserved_data_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+
+
+
+/**
+ * Process an mpeg_metadata_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return Pointer to an mpeg_metadata_descriptor, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor*
+ mpeg_metadata_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 2;
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len + 2;
+ struct mpeg_metadata_descriptor_flags *flags;
+ int id;
+
+ if (len < sizeof(struct mpeg_metadata_descriptor))
+ return NULL;
+
+ bswap16(buf + pos);
+ id = *((uint16_t*) (buf+pos));
+ pos += 2;
+
+ if (id == 0xffff) {
+ if (len < (pos+4))
+ return NULL;
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ if (len < (pos+1))
+ return NULL;
+
+ id = buf[pos];
+ pos++;
+ if (id == 0xff) {
+ if (len < (pos+4))
+ return NULL;
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ if (len < (pos + sizeof(struct mpeg_metadata_descriptor_flags)))
+ return NULL;
+ flags = (struct mpeg_metadata_descriptor_flags*) (buf+pos);
+ pos += sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if (flags->dsm_cc_flag == 1) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (flags->decoder_config_flags == 1) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (flags->decoder_config_flags == 3) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (flags->decoder_config_flags == 4) {
+ if (len < (pos+1))
+ return NULL;
+ pos++;
+ }
+
+ if ((flags->decoder_config_flags == 5) ||
+ (flags->decoder_config_flags == 6)) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (len < pos)
+ return NULL;
+
+ return (struct mpeg_metadata_descriptor*) d;
+}
+
+/**
+ * Accessor for pointer to appid field of an mpeg_metadata_descriptor.
+ *
+ * @param d The mpeg_metadata_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_application_format_identifier*
+ mpeg_metadata_descriptor_appid(struct mpeg_metadata_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor);
+
+ if (d->metadata_application_format != 0xffff)
+ return NULL;
+ return (struct mpeg_metadata_descriptor_application_format_identifier*) buf;
+}
+
+/**
+ * Accessor for metadata_format field of an mpeg_metadata_descriptor.
+ *
+ * @param d The mpeg_metadata_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline uint8_t
+ mpeg_metadata_descriptor_metadata_format(struct mpeg_metadata_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ return *buf;
+}
+
+/**
+ * Accessor for pointer to formid field of an mpeg_metadata_descriptor.
+ *
+ * @param d The mpeg_metadata_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_format_identifier*
+ mpeg_metadata_descriptor_formid(struct mpeg_metadata_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ if (*buf != 0xff)
+ return NULL;
+
+ return (struct mpeg_metadata_descriptor_format_identifier*) (buf+1);
+}
+
+/**
+ * Accessor for flags field of an mpeg_metadata_descriptor.
+ *
+ * @param d The mpeg_metadata_descriptor structure.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_flags*
+ mpeg_metadata_descriptor_flags(struct mpeg_metadata_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ if (*buf == 0xff)
+ buf+=4;
+
+ return (struct mpeg_metadata_descriptor_flags*) buf;
+}
+
+
+/**
+ * Accessor for service_identifier field of an mpeg_metadata_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_service_identifier*
+ mpeg_metadata_descriptor_sevice_identifier(struct mpeg_metadata_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if (flags->dsm_cc_flag!=1)
+ return NULL;
+
+ return (struct mpeg_metadata_descriptor_service_identifier *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_metadata_descriptor_service_identifier.
+ *
+ * @param d The mpeg_metadata_descriptor_service_identifier structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_descriptor_service_identifier_data(struct mpeg_metadata_descriptor_service_identifier *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_service_identifier);
+}
+
+/**
+ * Accessor for decoder_config field of an mpeg_metadata_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_decoder_config*
+ mpeg_metadata_descriptor_decoder_config(struct mpeg_metadata_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if (flags->decoder_config_flags != 1)
+ return NULL;
+
+ if (flags->dsm_cc_flag==1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_metadata_descriptor_decoder_config*) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_metadata_descriptor_service_identifier.
+ *
+ * @param d The mpeg_metadata_descriptor_service_identifier structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_descriptor_decoder_config_data(struct mpeg_metadata_descriptor_decoder_config *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config);
+}
+
+/**
+ * Accessor for decoder_config_id_record field of an mpeg_metadata_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_decoder_config_id_record*
+ mpeg_metadata_descriptor_decoder_config_id_record(struct mpeg_metadata_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if (flags->decoder_config_flags != 3)
+ return NULL;
+
+ if (flags->dsm_cc_flag==1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_metadata_descriptor_decoder_config_id_record *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_metadata_descriptor_decoder_config_id_record.
+ *
+ * @param d The mpeg_metadata_descriptor_decoder_config_id_record structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_descriptor_decoder_config_id_record_data(struct mpeg_metadata_descriptor_decoder_config_id_record *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config_id_record);
+}
+
+/**
+ * Accessor for decoder_config_service_id field of an mpeg_metadata_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_decoder_config_service_id*
+ mpeg_metadata_descriptor_decoder_config_service_id(struct mpeg_metadata_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if (flags->decoder_config_flags != 4)
+ return NULL;
+
+ if (flags->dsm_cc_flag==1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_metadata_descriptor_decoder_config_service_id *) buf;
+}
+
+/**
+ * Accessor for decoder_config_reserved field of an mpeg_metadata_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_descriptor_decoder_config_reserved*
+ mpeg_metadata_descriptor_decoder_config_reserved(struct mpeg_metadata_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+
+ if ((flags->decoder_config_flags != 5) && (flags->decoder_config_flags != 6))
+ return NULL;
+
+ if (flags->dsm_cc_flag==1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_metadata_descriptor_decoder_config_reserved *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_metadata_descriptor_decoder_config_reserved.
+ *
+ * @param d The mpeg_metadata_descriptor_decoder_config_reserved structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_descriptor_decoder_config_reserved_data(struct mpeg_metadata_descriptor_decoder_config_reserved *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_metadata_descriptor_decoder_config_reserved);
+}
+
+/**
+ * Accessor for private_data field of an mpeg_metadata_descriptor.
+ *
+ * @param d The mpeg_metadata_descriptor structure.
+ * @param flags Pointer to the mpeg_metadata_descriptor_flags.
+ * @param length Where the number of bytes in the field should be stored.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_descriptor_private_data(struct mpeg_metadata_descriptor *d,
+ struct mpeg_metadata_descriptor_flags *flags,
+ int *length)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_descriptor_flags);
+ uint8_t *end = (uint8_t*) d + d->d.len + 2;
+
+
+ if (flags->dsm_cc_flag==1)
+ buf += 1 + buf[1];
+ if (flags->decoder_config_flags==1)
+ buf += 1 + buf[1];
+ if (flags->decoder_config_flags==3)
+ buf += 1 + buf[1];
+ if (flags->decoder_config_flags==4)
+ buf++;
+ if ((flags->decoder_config_flags==5)||(flags->decoder_config_flags==6))
+ buf += 1 + buf[1];
+
+ *length = end - buf;
+ return buf;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/metadata_pointer_descriptor.h b/lib/libucsi/mpeg/metadata_pointer_descriptor.h
new file mode 100644
index 0000000..e4d7503
--- /dev/null
+++ b/lib/libucsi/mpeg/metadata_pointer_descriptor.h
@@ -0,0 +1,360 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_METADATA_POINTER_DESCRIPTOR
+#define _UCSI_MPEG_METADATA_POINTER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * Possible values for the mpeg_carriage_flags field.
+ */
+enum {
+ MPEG_CARRIAGE_SAME_TS = 0x00,
+ MPEG_CARRIAGE_DIFFERENT_TS = 0x01,
+ MPEG_CARRIAGE_PS = 0x02,
+ MPEG_CARRIAGE_OTHER = 0x03,
+};
+
+/**
+ * mpeg_metadata_pointer_descriptor structure.
+ */
+struct mpeg_metadata_pointer_descriptor {
+ struct descriptor d;
+
+ uint16_t metadata_application_format;
+ /* struct mpeg_metadata_pointer_descriptor_application_format_identifier appid */
+ /* uint8_t metadata_format */
+ /* struct mpeg_metadata_pointer_descriptor_format_identifier formid */
+ /* struct mpeg_metadata_pointer_descriptor_flags flags */
+ /* struct mpeg_metadata_pointer_descriptor_locator locator */
+ /* struct mpeg_metadata_pointer_descriptor_program_number program_number */
+ /* struct mpeg_metadata_pointer_descriptor_carriage carriage */
+ /* uint8_t private_data[] */
+} __ucsi_packed;
+
+/**
+ * appid field of a metadata_pointer_descriptor.
+ */
+struct mpeg_metadata_pointer_descriptor_application_format_identifier {
+ uint32_t id;
+} __ucsi_packed;
+
+/**
+ * formid field of a metadata_pointer_descriptor.
+ */
+struct mpeg_metadata_pointer_descriptor_format_identifier {
+ uint32_t id;
+} __ucsi_packed;
+
+/**
+ * Flags field of a metadata_pointer_descriptor
+ */
+struct mpeg_metadata_pointer_descriptor_flags {
+ uint8_t metadata_service_id;
+ EBIT3(uint8_t metadata_locator_record_flag : 1; ,
+ uint8_t mpeg_carriage_flags : 2; ,
+ uint8_t reserved : 5; );
+} __ucsi_packed;
+
+/**
+ * Reference_id field of a metadata_pointer_descriptor.
+ */
+struct mpeg_metadata_pointer_descriptor_locator {
+ uint8_t metadata_locator_record_length;
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * program_number field of a metadata_pointer_descriptor.
+ */
+struct mpeg_metadata_pointer_descriptor_program_number {
+ uint16_t number;
+} __ucsi_packed;
+
+/**
+ * carriage field of a metadata_pointer_descriptor.
+ */
+struct mpeg_metadata_pointer_descriptor_carriage {
+ uint16_t transport_stream_location;
+ uint16_t transport_stream_id;
+} __ucsi_packed;
+
+
+
+
+/**
+ * Process an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d Generic descriptor.
+ * @return Pointer to an mpeg_metadata_pointer_descriptor, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor*
+ mpeg_metadata_pointer_descriptor_codec(struct descriptor* d)
+{
+ uint32_t pos = 2;
+ uint8_t *buf = (uint8_t*) d;
+ uint32_t len = d->len + 2;
+ struct mpeg_metadata_pointer_descriptor_flags *flags;
+ int id;
+
+ if (len < sizeof(struct mpeg_metadata_pointer_descriptor))
+ return NULL;
+
+ bswap16(buf + pos);
+ id = *((uint16_t*) (buf+pos));
+ pos += 2;
+
+ if (id == 0xffff) {
+ if (len < (pos+4))
+ return NULL;
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ if (len < (pos+1))
+ return NULL;
+
+ id = buf[pos];
+ pos++;
+ if (id == 0xff) {
+ if (len < (pos+4))
+ return NULL;
+ bswap32(buf+pos);
+ pos += 4;
+ }
+
+ if (len < (pos + sizeof(struct mpeg_metadata_pointer_descriptor_flags)))
+ return NULL;
+ flags = (struct mpeg_metadata_pointer_descriptor_flags*) (buf+pos);
+ pos += sizeof(struct mpeg_metadata_pointer_descriptor_flags);
+
+ if (flags->metadata_locator_record_flag == 1) {
+ if (len < (pos+1))
+ return NULL;
+ if (len < (pos+1+buf[pos]))
+ return NULL;
+ pos += 1 + buf[pos];
+ }
+
+ if (flags->mpeg_carriage_flags < 3) {
+ if (len < (pos + 2))
+ return NULL;
+ bswap16(buf+pos);
+ pos += 2;
+ }
+
+ if (flags->mpeg_carriage_flags == 1) {
+ if (len < (pos + 4))
+ return NULL;
+ bswap16(buf+pos);
+ bswap16(buf+pos+2);
+ pos += 4;
+ }
+
+ if (len < pos)
+ return NULL;
+
+ return (struct mpeg_metadata_pointer_descriptor*) d;
+}
+
+/**
+ * Accessor for pointer to appid field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_application_format_identifier*
+ mpeg_metadata_pointer_descriptor_appid(struct mpeg_metadata_pointer_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor);
+
+ if (d->metadata_application_format != 0xffff)
+ return NULL;
+ return (struct mpeg_metadata_pointer_descriptor_application_format_identifier*) buf;
+}
+
+/**
+ * Accessor for metadata_format field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline uint8_t
+ mpeg_metadata_pointer_descriptor_metadata_format(struct mpeg_metadata_pointer_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ return *buf;
+}
+
+/**
+ * Accessor for pointer to formid field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor structure.
+ * @return The pointer, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_format_identifier*
+ mpeg_metadata_pointer_descriptor_formid(struct mpeg_metadata_pointer_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ if (*buf != 0xff)
+ return NULL;
+
+ return (struct mpeg_metadata_pointer_descriptor_format_identifier*) (buf+1);
+}
+
+/**
+ * Accessor for flags field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor structure.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_flags*
+ mpeg_metadata_pointer_descriptor_flags(struct mpeg_metadata_pointer_descriptor *d)
+{
+ uint8_t *buf = (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor);
+
+ if (d->metadata_application_format == 0xffff)
+ buf+=4;
+ if (*buf == 0xff)
+ buf+=4;
+
+ return (struct mpeg_metadata_pointer_descriptor_flags*) buf;
+}
+
+
+/**
+ * Accessor for locator field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_locator*
+ mpeg_metadata_pointer_descriptor_locator(struct mpeg_metadata_pointer_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags);
+
+ if (flags->metadata_locator_record_flag!=1)
+ return NULL;
+
+ return (struct mpeg_metadata_pointer_descriptor_locator *) buf;
+}
+
+/**
+ * Accessor for data field of an mpeg_metadata_pointer_descriptor_locator.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor_locator structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_pointer_descriptor_locator_data(struct mpeg_metadata_pointer_descriptor_locator *d)
+{
+ return (uint8_t*) d + sizeof(struct mpeg_metadata_pointer_descriptor_locator);
+}
+
+
+/**
+ * Accessor for program_number field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_program_number*
+ mpeg_metadata_pointer_descriptor_program_number(struct mpeg_metadata_pointer_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags);
+
+ if (flags->mpeg_carriage_flags < 3)
+ return NULL;
+
+ if (flags->metadata_locator_record_flag==1)
+ buf += 1 + buf[1];
+
+ return (struct mpeg_metadata_pointer_descriptor_program_number*) buf;
+}
+
+/**
+ * Accessor for carriage field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags.
+ * @return Pointer to the field, or NULL on error.
+ */
+static inline struct mpeg_metadata_pointer_descriptor_carriage*
+ mpeg_metadata_pointer_descriptor_carriage(struct mpeg_metadata_pointer_descriptor_flags *flags)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags);
+
+ if (flags->mpeg_carriage_flags != 1)
+ return NULL;
+
+ if (flags->metadata_locator_record_flag==1)
+ buf += 1 + buf[1];
+ if (flags->mpeg_carriage_flags < 3)
+ buf += sizeof(struct mpeg_metadata_pointer_descriptor_program_number);
+
+ return (struct mpeg_metadata_pointer_descriptor_carriage *) buf;
+}
+
+/**
+ * Accessor for private_data field of an mpeg_metadata_pointer_descriptor.
+ *
+ * @param d The mpeg_metadata_pointer_descriptor structure.
+ * @param flags Pointer to the mpeg_metadata_pointer_descriptor_flags.
+ * @param length Where the number of bytes in the field should be stored.
+ * @return Pointer to the field.
+ */
+static inline uint8_t*
+ mpeg_metadata_pointer_descriptor_private_data(struct mpeg_metadata_pointer_descriptor *d,
+ struct mpeg_metadata_pointer_descriptor_flags *flags,
+ int *length)
+{
+ uint8_t *buf = (uint8_t*) flags + sizeof(struct mpeg_metadata_pointer_descriptor_flags);
+ uint8_t *end = (uint8_t*) d + d->d.len + 2;
+
+
+ if (flags->metadata_locator_record_flag==1)
+ buf += 1 + buf[1];
+ if (flags->mpeg_carriage_flags < 3)
+ buf += sizeof(struct mpeg_metadata_pointer_descriptor_program_number);
+ if (flags->mpeg_carriage_flags != 1)
+ buf += sizeof(struct mpeg_metadata_pointer_descriptor_carriage);
+
+ *length = end - buf;
+ return buf;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/metadata_section.c b/lib/libucsi/mpeg/metadata_section.c
new file mode 100644
index 0000000..c1ce019
--- /dev/null
+++ b/lib/libucsi/mpeg/metadata_section.c
@@ -0,0 +1,27 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/metadata_section.h>
+
+struct mpeg_metadata_section * mpeg_metadata_section_codec(struct section_ext * ext)
+{
+ return (struct mpeg_metadata_section *)ext;
+}
diff --git a/lib/libucsi/mpeg/metadata_section.h b/lib/libucsi/mpeg/metadata_section.h
new file mode 100644
index 0000000..62c4e03
--- /dev/null
+++ b/lib/libucsi/mpeg/metadata_section.h
@@ -0,0 +1,122 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_METADATA_SECTION_H
+#define _UCSI_MPEG_METADATA_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_metadata_section structure.
+ */
+struct mpeg_metadata_section {
+ struct section_ext head;
+
+ /* uint8_t data[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_metadata_section structure.
+ *
+ * @param section Pointer to the section_ext structure.
+ * @return Pointer to the mpeg_metadata_section structure, or NULL on error.
+ */
+extern struct mpeg_metadata_section *mpeg_metadata_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the random_access_indicator field of a metadata section.
+ *
+ * @param metadata metadata section pointer.
+ * @return The random_access_indicator.
+ */
+static inline uint8_t mpeg_metadata_section_random_access_indicator(struct mpeg_metadata_section *metadata)
+{
+ return metadata->head.reserved >> 1;
+}
+
+/**
+ * Accessor for the decoder_config_flag field of a metadata section.
+ *
+ * @param metadata metadata section pointer.
+ * @return The decoder_config_flag.
+ */
+static inline uint8_t mpeg_metadata_section_decoder_config_flag(struct mpeg_metadata_section *metadata)
+{
+ return metadata->head.reserved & 1;
+}
+
+/**
+ * Accessor for the fragment_indicator field of a metadata section.
+ *
+ * @param metadata metadata section pointer.
+ * @return The fragment_indicator.
+ */
+static inline uint8_t mpeg_metadata_section_fragment_indicator(struct mpeg_metadata_section *metadata)
+{
+ return metadata->head.reserved1;
+}
+
+/**
+ * Accessor for the service_id field of a metadata section.
+ *
+ * @param metadata metadata section pointer.
+ * @return The service_id.
+ */
+static inline uint16_t mpeg_metadata_section_service_id(struct mpeg_metadata_section *metadata)
+{
+ return metadata->head.table_id_ext >> 8;
+}
+
+/**
+ * Retrieve pointer to data field of an mpeg_metadata_section.
+ *
+ * @param s mpeg_metadata_section pointer.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ mpeg_metadata_section_data(struct mpeg_metadata_section *s)
+{
+ return (uint8_t *) s + sizeof(struct mpeg_metadata_section);
+}
+
+
+/**
+ * Determine length of the data field of an mpeg_copyright_descriptor.
+ *
+ * @param s mpeg_metadata_section_data pointer.
+ * @return Length of field in bytes.
+ */
+static inline int
+ mpeg_metadata_section_data_length(struct mpeg_metadata_section *s)
+{
+ return section_ext_length(&s->head) - sizeof(struct mpeg_metadata_section);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/metadata_std_descriptor.h b/lib/libucsi/mpeg/metadata_std_descriptor.h
new file mode 100644
index 0000000..fc83e6e
--- /dev/null
+++ b/lib/libucsi/mpeg/metadata_std_descriptor.h
@@ -0,0 +1,72 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_METADATA_STD_DESCRIPTOR
+#define _UCSI_MPEG_METADATA_STD_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_metadata_std_descriptor structure.
+ */
+struct mpeg_metadata_std_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint32_t reserved_1 : 2; ,
+ uint32_t metadata_input_leak_rate :22; );
+ EBIT2(uint32_t reserved_2 : 2; ,
+ uint32_t metadata_buffer_size :22; );
+ EBIT2(uint32_t reserved_3 : 2; ,
+ uint32_t metadata_output_leak_rate :22; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_metadata_std_descriptor.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_metadata_std_descriptor, or NULL on error.
+ */
+static inline struct mpeg_metadata_std_descriptor*
+ mpeg_metadata_std_descriptor_codec(struct descriptor* d)
+{
+ uint8_t *buf = (uint8_t*) d;
+
+ if (d->len != (sizeof(struct mpeg_metadata_std_descriptor) - 2))
+ return NULL;
+
+ bswap24(buf + 2);
+ bswap24(buf + 5);
+ bswap24(buf + 8);
+
+ return (struct mpeg_metadata_std_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/mpeg4_audio_descriptor.h b/lib/libucsi/mpeg/mpeg4_audio_descriptor.h
new file mode 100644
index 0000000..f876759
--- /dev/null
+++ b/lib/libucsi/mpeg/mpeg4_audio_descriptor.h
@@ -0,0 +1,61 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG4_AUDIO_DESCRIPTOR
+#define _UCSI_MPEG4_AUDIO_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg4_audio_descriptor structure.
+ */
+struct mpeg4_audio_descriptor {
+ struct descriptor d;
+
+ uint8_t mpeg4_audio_profile_and_level;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg4_audio_descriptor.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to an mpeg4_audio_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg4_audio_descriptor*
+ mpeg4_audio_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg4_audio_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg4_audio_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/mpeg4_video_descriptor.h b/lib/libucsi/mpeg/mpeg4_video_descriptor.h
new file mode 100644
index 0000000..b956b91
--- /dev/null
+++ b/lib/libucsi/mpeg/mpeg4_video_descriptor.h
@@ -0,0 +1,61 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG4_VIDEO_DESCRIPTOR
+#define _UCSI_MPEG4_VIDEO_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg4_video_descriptor structure.
+ */
+struct mpeg4_video_descriptor {
+ struct descriptor d;
+
+ uint8_t mpeg4_visual_profile_and_level;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg4_video_descriptor structure.
+ *
+ * @param d Pointer to generic descriptor structure.
+ * @return Pointer to mpeg4_video_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg4_video_descriptor*
+ mpeg4_video_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg4_video_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg4_video_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/multiplex_buffer_descriptor.h b/lib/libucsi/mpeg/multiplex_buffer_descriptor.h
new file mode 100644
index 0000000..d55ce3d
--- /dev/null
+++ b/lib/libucsi/mpeg/multiplex_buffer_descriptor.h
@@ -0,0 +1,65 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_MULTIPLEX_BUFFER_DESCRIPTOR
+#define _UCSI_MPEG_MULTIPLEX_BUFFER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_multiplex_buffer_descriptor descriptor.
+ */
+struct mpeg_multiplex_buffer_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint64_t mb_buffer_size : 24; ,
+ uint64_t tb_leak_rate : 24; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_multiplex_buffer_descriptor.
+ *
+ * @param d Pointer to generic descriptor structure.
+ * @return Pointer to an mpeg_multiplex_buffer_descriptor structure, or NULL on
+ * error.
+ */
+static inline struct mpeg_multiplex_buffer_descriptor*
+ mpeg_multiplex_buffer_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_multiplex_buffer_descriptor) - 2))
+ return NULL;
+
+ bswap48((uint8_t*) d + 2);
+
+ return (struct mpeg_multiplex_buffer_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h b/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h
new file mode 100644
index 0000000..16550ed
--- /dev/null
+++ b/lib/libucsi/mpeg/multiplex_buffer_utilization_descriptor.h
@@ -0,0 +1,67 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_MULTIPLEX_BUFFER_UTILIZATION_DESCRIPTOR
+#define _UCSI_MPEG_MULTIPLEX_BUFFER_UTILIZATION_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_multiplex_buffer_utilization_descriptor structure.
+ */
+struct mpeg_multiplex_buffer_utilization_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint16_t bound_valid_flag : 1; ,
+ uint16_t ltw_offset_lower_bound : 15; );
+ EBIT2(uint16_t reserved : 1; ,
+ uint16_t ltw_offset_upper_bound : 15; );
+} __ucsi_packed;
+
+/**
+ * Process a mpeg_multiplex_buffer_utilization_descriptor.
+ *
+ * @param d Generic descriptor pointer.
+ * @return mpeg_multiplex_buffer_utilization_descriptor pointer, or NULL on error.
+ */
+static inline struct mpeg_multiplex_buffer_utilization_descriptor*
+ mpeg_multiplex_buffer_utilization_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_multiplex_buffer_utilization_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+ bswap16((uint8_t*) d + 4);
+
+ return (struct mpeg_multiplex_buffer_utilization_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/muxcode_descriptor.h b/lib/libucsi/mpeg/muxcode_descriptor.h
new file mode 100644
index 0000000..6bed334
--- /dev/null
+++ b/lib/libucsi/mpeg/muxcode_descriptor.h
@@ -0,0 +1,82 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_MUXCODE_DESCRIPTOR
+#define _UCSI_MPEG_MUXCODE_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_muxcode_descriptor structure
+ */
+struct mpeg_muxcode_descriptor {
+ struct descriptor d;
+
+ /* uint8_t entries[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_muxcode_descriptor.
+ *
+ * @param d Pointer to a generic descriptor structure.
+ * @return Pointer to an mpeg_muxcode_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_muxcode_descriptor*
+ mpeg_muxcode_descriptor_codec(struct descriptor* d)
+{
+ return (struct mpeg_muxcode_descriptor*) d;
+}
+
+/**
+ * Retrieve pointer to entries field of an mpeg_muxcode_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @return Pointer to the entries field.
+ */
+static inline uint8_t *
+ mpeg_muxcode_descriptor_entries(struct mpeg_muxcode_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_muxcode_descriptor);
+}
+
+/**
+ * Determine length of entries field of an mpeg_muxcode_descriptor structure.
+ *
+ * @param d Generic descriptor structure.
+ * @return Number of bytes in the entries field.
+ */
+static inline int
+ mpeg_muxcode_descriptor_entries_length(struct mpeg_muxcode_descriptor *d)
+{
+ return d->d.len;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/odsmt_section.c b/lib/libucsi/mpeg/odsmt_section.c
new file mode 100644
index 0000000..07407f2
--- /dev/null
+++ b/lib/libucsi/mpeg/odsmt_section.c
@@ -0,0 +1,80 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/odsmt_section.h>
+
+struct mpeg_odsmt_section *mpeg_odsmt_section_codec(struct section_ext * ext)
+{
+ struct mpeg_odsmt_section * odsmt = (struct mpeg_odsmt_section *)ext;
+ uint8_t * buf = (uint8_t *)ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+ int i;
+
+ if (len < sizeof(struct mpeg_odsmt_section))
+ return NULL;
+
+ pos++;
+
+ if (odsmt->stream_count == 0) {
+ struct mpeg_odsmt_stream * stream =
+ (struct mpeg_odsmt_stream *) (buf + pos);
+
+ if ((pos + sizeof(struct mpeg_odsmt_stream_single)) > len)
+ return NULL;
+
+ bswap16(buf+pos);
+ pos+=3;
+
+ if ((pos + stream->u.single.es_info_length) >= len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, stream->u.single.es_info_length))
+ return NULL;
+
+ pos += stream->u.single.es_info_length;
+ } else {
+ for (i=0; i< odsmt->stream_count; i++) {
+ struct mpeg_odsmt_stream * stream =
+ (struct mpeg_odsmt_stream *)(buf + pos);
+
+ if ((pos + sizeof(struct mpeg_odsmt_stream_multi)) > len)
+ return NULL;
+
+ bswap16(buf+pos);
+ pos += sizeof(struct mpeg_odsmt_stream_multi);
+
+ if ((pos + stream->u.multi.es_info_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos,
+ stream->u.multi.es_info_length))
+ return NULL;
+
+ pos += stream->u.multi.es_info_length;
+ }
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct mpeg_odsmt_section *) ext;
+}
diff --git a/lib/libucsi/mpeg/odsmt_section.h b/lib/libucsi/mpeg/odsmt_section.h
new file mode 100644
index 0000000..4e01085
--- /dev/null
+++ b/lib/libucsi/mpeg/odsmt_section.h
@@ -0,0 +1,224 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_ODSMT_SECTION_H
+#define _UCSI_MPEG_ODSMT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_odsmt_section structure.
+ */
+struct mpeg_odsmt_section {
+ struct section_ext head;
+
+ uint8_t stream_count;
+ /* stream_count==0 => struct mpeg_odsmt_stream_single streams
+ stream_count>0 => struct mpeg_odsmt_stream_multi streams[] */
+ /* uint8_t object_descriptors[] */
+} __ucsi_packed;
+
+struct mpeg_odsmt_stream_single
+{
+ uint16_t esid;
+ uint8_t es_info_length;
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+struct mpeg_odsmt_stream_multi
+{
+ uint16_t esid;
+ uint8_t fmc;
+ uint8_t es_info_length;
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Structure describing the stream information held in an mpeg_odsmt_section.
+ */
+struct mpeg_odsmt_stream {
+ union {
+ struct mpeg_odsmt_stream_single single;
+ struct mpeg_odsmt_stream_multi multi;
+ } u;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_odsmt_section.
+ *
+ * @param section Pointer to the generic section_ext structure.
+ * @return Pointer to a mpeg_odsmt_section structure, or NULL on error.
+ */
+extern struct mpeg_odsmt_section *mpeg_odsmt_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the PID field of an ODSMT.
+ *
+ * @param odsmt odsmt pointer.
+ * @return The pid.
+ */
+static inline uint16_t mpeg_odsmt_section_pid(struct mpeg_odsmt_section *odsmt)
+{
+ return odsmt->head.table_id_ext & 0x1fff;
+}
+
+/**
+ * Convenience iterator for the streams field of an mpeg_odsmt_section.
+ *
+ * @param osdmt Pointer to the mpeg_odsmt_section structure.
+ * @param pos Variable holding pointer to the current mpeg_odsmt_stream structure.
+ * @param index Variable holding the stream index.
+ */
+#define mpeg_odsmt_section_streams_for_each(osdmt, pos, index) \
+ for (index=0, (pos) = mpeg_odsmt_section_streams_first(odsmt); \
+ (pos); \
+ (pos) = mpeg_odsmt_section_streams_next(odsmt, pos, ++index))
+
+/**
+ * Convenience iterator for the descriptors field of an mpeg_odsmt_stream.
+ *
+ * @param osdmt Pointer to the mpeg_odsmt_section structure.
+ * @param stream Pointer to the mpeg_odsmt_stream structure.
+ * @param pos Variable holding pointer to the current descriptor structure.
+ */
+#define mpeg_odsmt_stream_descriptors_for_each(osdmt, stream, pos) \
+ for ((pos) = mpeg_odsmt_stream_descriptors_first(odsmt, stream); \
+ (pos); \
+ (pos) = mpeg_odsmt_stream_descriptors_next(odsmt, stream, pos))
+
+/**
+ * Retrieve a pointer to the object_descriptors field of an mpeg_odsmt_section.
+ *
+ * @param osdmt Pointer to the mpeg_odsmt_section structure.
+ * @param len On return, will contain the number of bytes in the object descriptors field.
+ * @return Pointer to the object_descriptors field, or NULL on error.
+ */
+static inline uint8_t*
+ mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt,
+ size_t* len);
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct mpeg_odsmt_stream *
+ mpeg_odsmt_section_streams_first(struct mpeg_odsmt_section *odsmt)
+{
+ size_t pos = sizeof(struct mpeg_odsmt_section);
+
+ if (pos >= section_ext_length(&odsmt->head))
+ return NULL;
+
+ return (struct mpeg_odsmt_stream *) ((uint8_t *) odsmt + pos);
+}
+
+static inline struct mpeg_odsmt_stream *
+ mpeg_odsmt_section_streams_next(struct mpeg_odsmt_section *odsmt,
+ struct mpeg_odsmt_stream *pos,
+ int _index)
+{
+ uint8_t *end = (uint8_t*) odsmt + section_ext_length(&odsmt->head);
+ uint8_t *next;
+
+ if (_index > odsmt->stream_count)
+ return NULL;
+
+ next = (uint8_t *) pos + sizeof(struct mpeg_odsmt_stream_multi) +
+ pos->u.multi.es_info_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct mpeg_odsmt_stream *) next;
+}
+
+static inline struct descriptor *
+ mpeg_odsmt_stream_descriptors_first(struct mpeg_odsmt_section *odsmt,
+ struct mpeg_odsmt_stream *stream)
+{
+ if (odsmt->stream_count == 0) {
+ if (stream->u.single.es_info_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*) stream + sizeof(struct mpeg_odsmt_stream_single));
+ } else {
+ if (stream->u.multi.es_info_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*) stream + sizeof(struct mpeg_odsmt_stream_multi));
+ }
+}
+
+static inline struct descriptor *
+ mpeg_odsmt_stream_descriptors_next(struct mpeg_odsmt_section *odsmt,
+ struct mpeg_odsmt_stream *stream,
+ struct descriptor* pos)
+{
+ if (odsmt->stream_count == 0) {
+ return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_odsmt_stream_single),
+ stream->u.single.es_info_length,
+ pos);
+ } else {
+ return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_odsmt_stream_multi),
+ stream->u.multi.es_info_length,
+ pos);
+ }
+}
+
+static inline uint8_t*
+ mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt,
+ size_t* len)
+{
+ struct mpeg_odsmt_stream* pos;
+ size_t size = sizeof(struct mpeg_odsmt_section);
+ int _index;
+
+ mpeg_odsmt_section_streams_for_each(odsmt, pos, _index) {
+ if (odsmt->stream_count == 0)
+ size += sizeof(struct mpeg_odsmt_stream_single) +
+ pos->u.single.es_info_length;
+ else
+ size += sizeof(struct mpeg_odsmt_stream_multi) +
+ pos->u.multi.es_info_length;
+ }
+
+ *len = section_ext_length(&odsmt->head) - size;
+ return (uint8_t*) odsmt + size;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/pat_section.c b/lib/libucsi/mpeg/pat_section.c
new file mode 100644
index 0000000..2e4c2cc
--- /dev/null
+++ b/lib/libucsi/mpeg/pat_section.c
@@ -0,0 +1,46 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/pat_section.h>
+
+struct mpeg_pat_section *mpeg_pat_section_codec(struct section_ext * ext)
+{
+ uint8_t *buf = (uint8_t *)ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct mpeg_pat_section))
+ return NULL;
+
+ while (pos < len) {
+ if ((pos + 4) > len)
+ return NULL;
+
+ bswap16(buf + pos);
+ bswap16(buf + pos + 2);
+ pos += 4;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct mpeg_pat_section *)ext;
+}
diff --git a/lib/libucsi/mpeg/pat_section.h b/lib/libucsi/mpeg/pat_section.h
new file mode 100644
index 0000000..eadfe28
--- /dev/null
+++ b/lib/libucsi/mpeg/pat_section.h
@@ -0,0 +1,118 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_PAT_SECTION_H
+#define _UCSI_MPEG_PAT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_pat_section structure.
+ */
+struct mpeg_pat_section {
+ struct section_ext head; /* table_id_ext == transport_stream_id */
+
+ /* struct mpeg_pat_program programs[] */
+} __ucsi_packed;
+
+/**
+ * A program within an mpeg_pat_section.
+ */
+struct mpeg_pat_program {
+ uint16_t program_number;
+ EBIT2(uint16_t reserved : 3; ,
+ uint16_t pid :13; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_pat_section.
+ *
+ * @param section Pointer to the generic section_ext structure.
+ * @return Pointer to the mpeg_pat_section structure, or NULL on error.
+ */
+extern struct mpeg_pat_section *mpeg_pat_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for the transport_stream_id field of a PAT.
+ *
+ * @param pat PAT pointer.
+ * @return The transport_stream_id.
+ */
+static inline uint16_t mpeg_pat_section_transport_stream_id(struct mpeg_pat_section *pat)
+{
+ return pat->head.table_id_ext;
+}
+
+/**
+ * Conveience iterator for the programs field of an mpeg_pat_section.
+ *
+ * @param pat Pointer to the mpeg_pat_section structure.
+ * @param pos Variable holding a pointer to the current mpeg_pat_program structure.
+ */
+#define mpeg_pat_section_programs_for_each(pat, pos) \
+ for ((pos) = mpeg_pat_section_programs_first(pat); \
+ (pos); \
+ (pos) = mpeg_pat_section_programs_next(pat, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct mpeg_pat_program *
+ mpeg_pat_section_programs_first(struct mpeg_pat_section * pat)
+{
+ size_t pos = sizeof(struct mpeg_pat_section);
+
+ if (pos >= section_ext_length(&pat->head))
+ return NULL;
+
+ return (struct mpeg_pat_program*)((uint8_t *) pat + pos);
+}
+
+static inline
+ struct mpeg_pat_program *mpeg_pat_section_programs_next(struct mpeg_pat_section * pat,
+ struct mpeg_pat_program * pos)
+{
+ uint8_t *end = (uint8_t*) pat + section_ext_length(&pat->head);
+ uint8_t *next= (uint8_t *) pos + sizeof(struct mpeg_pat_program);
+
+ if (next >= end)
+ return NULL;
+
+ return (struct mpeg_pat_program *) next;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/pmt_section.c b/lib/libucsi/mpeg/pmt_section.c
new file mode 100644
index 0000000..e5aec6a
--- /dev/null
+++ b/lib/libucsi/mpeg/pmt_section.c
@@ -0,0 +1,71 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/pmt_section.h>
+
+struct mpeg_pmt_section * mpeg_pmt_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *) ext;
+ struct mpeg_pmt_section * pmt = (struct mpeg_pmt_section *) ext;
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
+ if (len < sizeof(struct mpeg_pmt_section))
+ return NULL;
+
+ bswap16(buf + pos);
+ pos += 2;
+ bswap16(buf + pos);
+ pos += 2;
+
+ if ((pos + pmt->program_info_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, pmt->program_info_length))
+ return NULL;
+
+ pos += pmt->program_info_length;
+
+ while (pos < len) {
+ struct mpeg_pmt_stream * stream =
+ (struct mpeg_pmt_stream *) (buf + pos);
+
+ if ((pos + sizeof(struct mpeg_pmt_stream)) > len)
+ return NULL;
+
+ bswap16(buf + pos + 1);
+ bswap16(buf + pos + 3);
+ pos += sizeof(struct mpeg_pmt_stream);
+
+ if ((pos + stream->es_info_length) > len)
+ return NULL;
+
+ if (verify_descriptors(buf + pos, stream->es_info_length))
+ return NULL;
+
+ pos += stream->es_info_length;
+ }
+
+ if (pos != len)
+ return NULL;
+
+ return (struct mpeg_pmt_section *) ext;
+}
diff --git a/lib/libucsi/mpeg/pmt_section.h b/lib/libucsi/mpeg/pmt_section.h
new file mode 100644
index 0000000..03dea1b
--- /dev/null
+++ b/lib/libucsi/mpeg/pmt_section.h
@@ -0,0 +1,188 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_PMT_SECTION_H
+#define _UCSI_MPEG_PMT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_pmt_section structure.
+ */
+struct mpeg_pmt_section {
+ struct section_ext head;
+
+ EBIT2(uint16_t reserved_1 : 3; ,
+ uint16_t pcr_pid :13; );
+ EBIT2(uint16_t reserved_2 : 4; ,
+ uint16_t program_info_length :12; );
+ /* struct descriptor descriptors[] */
+ /* struct mpeg_pmt_stream streams[] */
+} __ucsi_packed;
+
+/**
+ * A stream within an mpeg_pmt_section.
+ */
+struct mpeg_pmt_stream {
+ uint8_t stream_type;
+ EBIT2(uint16_t reserved_1 : 3; ,
+ uint16_t pid :13; );
+ EBIT2(uint16_t reserved_2 : 4; ,
+ uint16_t es_info_length :12; );
+
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_pmt_section section.
+ *
+ * @param section Pointer to the generic section header.
+ * @return Pointer to the mpeg_pmt_section structure, or NULL on error.
+ */
+extern struct mpeg_pmt_section *mpeg_pmt_section_codec(struct section_ext *section);
+
+/**
+ * Accessor for program_number field of a PMT.
+ *
+ * @param pmt PMT pointer.
+ * @return The program_number.
+ */
+static inline uint16_t mpeg_pmt_section_program_number(struct mpeg_pmt_section *pmt)
+{
+ return pmt->head.table_id_ext;
+}
+
+/**
+ * Convenience iterator for the descriptors field of the mpeg_pmt_section structure.
+ *
+ * @param pmt Pointer to the mpeg_pmt_section structure.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define mpeg_pmt_section_descriptors_for_each(pmt, pos) \
+ for ((pos) = mpeg_pmt_section_descriptors_first(pmt); \
+ (pos); \
+ (pos) = mpeg_pmt_section_descriptors_next(pmt, pos))
+
+/**
+ * Convenience iterator for the streams field of the mpeg_pmt_section structure.
+ *
+ * @param pmt Pointer to the mpeg_pmt_section structure.
+ * @param pos Variable holding a pointer to the current mpeg_pmt_stream.
+ */
+#define mpeg_pmt_section_streams_for_each(pmt, pos) \
+ for ((pos) = mpeg_pmt_section_streams_first(pmt); \
+ (pos); \
+ (pos) = mpeg_pmt_section_streams_next(pmt, pos))
+
+/**
+ * Convenience iterator for the descriptors field of an mpeg_pmt_stream structure.
+ *
+ * @param stream Pointer to the mpeg_pmt_stream structure.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define mpeg_pmt_stream_descriptors_for_each(stream, pos) \
+ for ((pos) = mpeg_pmt_stream_descriptors_first(stream); \
+ (pos); \
+ (pos) = mpeg_pmt_stream_descriptors_next(stream, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ mpeg_pmt_section_descriptors_first(struct mpeg_pmt_section * pmt)
+{
+ if (pmt->program_info_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t *) pmt + sizeof(struct mpeg_pmt_section));
+}
+
+static inline struct descriptor *
+ mpeg_pmt_section_descriptors_next(struct mpeg_pmt_section *pmt,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t *) pmt + sizeof(struct mpeg_pmt_section),
+ pmt->program_info_length,
+ pos);
+}
+
+static inline struct mpeg_pmt_stream *
+ mpeg_pmt_section_streams_first(struct mpeg_pmt_section * pmt)
+{
+ size_t pos = sizeof(struct mpeg_pmt_section) + pmt->program_info_length;
+
+ if (pos >= section_ext_length(&pmt->head))
+ return NULL;
+
+ return (struct mpeg_pmt_stream *)((uint8_t *)pmt + pos);
+}
+
+static inline struct mpeg_pmt_stream *
+ mpeg_pmt_section_streams_next(struct mpeg_pmt_section * pmt,
+ struct mpeg_pmt_stream * pos)
+{
+ uint8_t *end = (uint8_t*) pmt + section_ext_length(&pmt->head);
+ uint8_t *next = (uint8_t *) pos + sizeof(struct mpeg_pmt_stream) +
+ pos->es_info_length;
+
+ if (next >= end)
+ return NULL;
+
+ return (struct mpeg_pmt_stream *) next;
+}
+
+static inline struct descriptor *
+ mpeg_pmt_stream_descriptors_first(struct mpeg_pmt_stream *stream)
+{
+ if (stream->es_info_length == 0)
+ return NULL;
+
+ return (struct descriptor *)
+ ((uint8_t*) stream + sizeof(struct mpeg_pmt_stream));
+}
+
+static inline struct descriptor *
+ mpeg_pmt_stream_descriptors_next(struct mpeg_pmt_stream *stream,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t *) stream + sizeof(struct mpeg_pmt_stream),
+ stream->es_info_length,
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/private_data_indicator_descriptor.h b/lib/libucsi/mpeg/private_data_indicator_descriptor.h
new file mode 100644
index 0000000..80e8ef3
--- /dev/null
+++ b/lib/libucsi/mpeg/private_data_indicator_descriptor.h
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_PRIVATE_DATA_INDICATOR_DESCRIPTOR
+#define _UCSI_MPEG_PRIVATE_DATA_INDICATOR_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_private_data_indicator_descriptor structure
+ */
+struct mpeg_private_data_indicator_descriptor {
+ struct descriptor d;
+
+ uint32_t private_data_indicator;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_private_data_indicator_descriptor structure.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_private_data_indicator_descriptor, or NULL on error.
+ */
+static inline struct mpeg_private_data_indicator_descriptor*
+ mpeg_private_data_indicator_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_private_data_indicator_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct mpeg_private_data_indicator_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/registration_descriptor.h b/lib/libucsi/mpeg/registration_descriptor.h
new file mode 100644
index 0000000..df5c186
--- /dev/null
+++ b/lib/libucsi/mpeg/registration_descriptor.h
@@ -0,0 +1,91 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_REGISTRATION_DESCRIPTOR
+#define _UCSI_MPEG_REGISTRATION_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_registration_descriptor structure.
+ */
+struct mpeg_registration_descriptor {
+ struct descriptor d;
+
+ uint32_t format_identifier;
+ /* uint8_t additional_id_info[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_registration_descriptor.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_registration_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_registration_descriptor*
+ mpeg_registration_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < (sizeof(struct mpeg_registration_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct mpeg_registration_descriptor*) d;
+}
+
+/**
+ * Retrieve a pointer to the additional_id_info field of the
+ * mpeg_registration_descriptor structure.
+ *
+ * @param d Pointer to the mpeg_registration_descriptor structure.
+ * @return Pointer to the field.
+ */
+static inline uint8_t *
+ mpeg_registration_descriptor_additional_id_info(struct mpeg_registration_descriptor *d)
+{
+ return (uint8_t *) d + sizeof(struct mpeg_registration_descriptor);
+}
+
+/**
+ * Determine number of bytes in the additional_id_info field of the
+ * mpeg_registration_descriptor structure.
+ *
+ * @param d Pointer to the mpeg_registration_descriptor structure.
+ * @return Number of bytes.
+ */
+
+static inline int
+ mpeg_registration_descriptor_additional_id_info_length(struct mpeg_registration_descriptor *d)
+{
+ return d->d.len - 4;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/section.h b/lib/libucsi/mpeg/section.h
new file mode 100644
index 0000000..7dbff93
--- /dev/null
+++ b/lib/libucsi/mpeg/section.h
@@ -0,0 +1,58 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_SECTION_H
+#define _UCSI_MPEG_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/mpeg/cat_section.h>
+#include <libucsi/mpeg/odsmt_section.h>
+#include <libucsi/mpeg/pat_section.h>
+#include <libucsi/mpeg/pmt_section.h>
+#include <libucsi/mpeg/tsdt_section.h>
+#include <libucsi/mpeg/metadata_section.h>
+
+#define TRANSPORT_PAT_PID 0x00
+#define TRANSPORT_CAT_PID 0x01
+#define TRANSPORT_TSDT_PID 0x02
+
+/**
+ * Enumeration of MPEG section tags.
+ */
+enum mpeg_section_tag {
+ stag_mpeg_program_association = 0x00,
+ stag_mpeg_conditional_access = 0x01,
+ stag_mpeg_program_map = 0x02,
+ stag_mpeg_transport_stream_description = 0x03,
+ stag_mpeg_iso14496_scene_description = 0x04,
+ stag_mpeg_iso14496_object_description = 0x05,
+ stag_mpeg_metadata = 0x06,
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/sl_descriptor.h b/lib/libucsi/mpeg/sl_descriptor.h
new file mode 100644
index 0000000..ab086e3
--- /dev/null
+++ b/lib/libucsi/mpeg/sl_descriptor.h
@@ -0,0 +1,63 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_SL_DESCRIPTOR
+#define _UCSI_MPEG_SL_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_sl_descriptor structure.
+ */
+struct mpeg_sl_descriptor {
+ struct descriptor d;
+
+ uint16_t es_id;
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_sl_descriptor.
+ *
+ * @param d The generic descriptor structure.
+ * @return Pointer to an mpeg_sl_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_sl_descriptor*
+ mpeg_sl_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_sl_descriptor) - 2))
+ return NULL;
+
+ bswap16((uint8_t*) d + 2);
+
+ return (struct mpeg_sl_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/smoothing_buffer_descriptor.h b/lib/libucsi/mpeg/smoothing_buffer_descriptor.h
new file mode 100644
index 0000000..5e6ad33
--- /dev/null
+++ b/lib/libucsi/mpeg/smoothing_buffer_descriptor.h
@@ -0,0 +1,66 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_SMOOTHING_BUFFER_DESCRIPTOR
+#define _UCSI_MPEG_SMOOTHING_BUFFER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_smoothing_buffer_descriptor structure.
+ */
+struct mpeg_smoothing_buffer_descriptor {
+ struct descriptor d;
+
+ EBIT4(uint64_t reserved_1 : 2; ,
+ uint64_t sb_leak_rate :22; ,
+ uint64_t reserved_2 : 2; ,
+ uint64_t sb_size :22; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_smoothing_buffer_descriptor.
+ *
+ * @param d The generic descriptor structure.
+ * @return Pointer to mpeg_smoothing_buffer_descriptor, or NULL on error.
+ */
+static inline struct mpeg_smoothing_buffer_descriptor*
+ mpeg_smoothing_buffer_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_smoothing_buffer_descriptor) - 2))
+ return NULL;
+
+ bswap48((uint8_t*) d + 2);
+
+ return (struct mpeg_smoothing_buffer_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/std_descriptor.h b/lib/libucsi/mpeg/std_descriptor.h
new file mode 100644
index 0000000..2625a41
--- /dev/null
+++ b/lib/libucsi/mpeg/std_descriptor.h
@@ -0,0 +1,62 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_STD_DESCRIPTOR
+#define _UCSI_MPEG_STD_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_std_descriptor structure.
+ */
+struct mpeg_std_descriptor {
+ struct descriptor d;
+
+ EBIT2(uint8_t reserved : 7; ,
+ uint8_t leak_valid_flag : 1; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_std_descriptor.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_std_descriptor, or NULL on error.
+ */
+static inline struct mpeg_std_descriptor*
+ mpeg_std_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_std_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_std_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/system_clock_descriptor.h b/lib/libucsi/mpeg/system_clock_descriptor.h
new file mode 100644
index 0000000..681641f
--- /dev/null
+++ b/lib/libucsi/mpeg/system_clock_descriptor.h
@@ -0,0 +1,65 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_SYSTEM_CLOCK_DESCRIPTOR
+#define _UCSI_MPEG_SYSTEM_CLOCK_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_system_clock_descriptor structure.
+ */
+struct mpeg_system_clock_descriptor {
+ struct descriptor d;
+
+ EBIT3(uint8_t external_clock_reference_indicator : 1; ,
+ uint8_t reserved_1 : 1; ,
+ uint8_t clock_accuracy_integer : 6; );
+ EBIT2(uint8_t clock_accuracy_exponent : 3; ,
+ uint8_t reserved_2 : 5; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_system_clock_descriptor.
+ *
+ * @param d The generic descriptor structure.
+ * @return Pointer to a mpeg_system_clock_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_system_clock_descriptor*
+ mpeg_system_clock_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_system_clock_descriptor) - 2))
+ return NULL;
+
+ return (struct mpeg_system_clock_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/target_background_grid_descriptor.h b/lib/libucsi/mpeg/target_background_grid_descriptor.h
new file mode 100644
index 0000000..7394e82
--- /dev/null
+++ b/lib/libucsi/mpeg/target_background_grid_descriptor.h
@@ -0,0 +1,66 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_TARGET_BACKGROUND_GRID_DESCRIPTOR
+#define _UCSI_MPEG_TARGET_BACKGROUND_GRID_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * mpeg_target_background_grid_descriptor structure.
+ */
+struct mpeg_target_background_grid_descriptor {
+ struct descriptor d;
+
+ EBIT3(uint32_t horizontal_size : 14; ,
+ uint32_t vertical_size : 14; ,
+ uint32_t aspect_ratio_information : 4; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_target_background_grid_descriptor structure.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_target_background_grid_descriptor structure, or
+ * NULL on error.
+ */
+static inline struct mpeg_target_background_grid_descriptor*
+ mpeg_target_background_grid_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_target_background_grid_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct mpeg_target_background_grid_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/tsdt_section.c b/lib/libucsi/mpeg/tsdt_section.c
new file mode 100644
index 0000000..fec9dd7
--- /dev/null
+++ b/lib/libucsi/mpeg/tsdt_section.c
@@ -0,0 +1,34 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <libucsi/mpeg/tsdt_section.h>
+
+struct mpeg_tsdt_section * mpeg_tsdt_section_codec(struct section_ext * ext)
+{
+ uint8_t * buf = (uint8_t *)ext;
+ size_t pos = sizeof(struct section_ext);
+
+ if (verify_descriptors(buf + pos,
+ section_ext_length(ext) - sizeof(struct mpeg_tsdt_section)))
+ return NULL;
+
+ return (struct mpeg_tsdt_section *)ext;
+}
diff --git a/lib/libucsi/mpeg/tsdt_section.h b/lib/libucsi/mpeg/tsdt_section.h
new file mode 100644
index 0000000..2bbae02
--- /dev/null
+++ b/lib/libucsi/mpeg/tsdt_section.h
@@ -0,0 +1,94 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_TSDT_SECTION_H
+#define _UCSI_MPEG_TSDT_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * mpeg_tsdt_section structure.
+ */
+struct mpeg_tsdt_section {
+ struct section_ext head;
+
+ /* struct descriptor descriptors[] */
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_tsdt_section structure.
+ *
+ * @param section Pointer to the section_ext structure.
+ * @return Pointer to the mpeg_tsdt_section structure, or NULL on error.
+ */
+extern struct mpeg_tsdt_section *mpeg_tsdt_section_codec(struct section_ext *section);
+
+/**
+ * Convenience iterator for descriptors field.
+ *
+ * @param tsdt Pointer to the mpeg_tsdt_section structure.
+ * @param pos Variable holding a pointer to the current descriptor.
+ */
+#define mpeg_tsdt_section_descriptors_for_each(tsdt, pos) \
+ for ((pos) = mpeg_tsdt_section_descriptors_first(tsdt); \
+ (pos); \
+ (pos) = mpeg_tsdt_section_descriptors_next(tsdt, pos))
+
+
+
+
+
+
+
+
+
+
+/******************************** PRIVATE CODE ********************************/
+static inline struct descriptor *
+ mpeg_tsdt_section_descriptors_first(struct mpeg_tsdt_section * tsdt)
+{
+ size_t pos = sizeof(struct mpeg_tsdt_section);
+
+ if (pos >= section_ext_length(&tsdt->head))
+ return NULL;
+
+ return (struct descriptor*)((uint8_t *) tsdt + pos);
+}
+
+static inline struct descriptor *
+ mpeg_tsdt_section_descriptors_next(struct mpeg_tsdt_section *tsdt,
+ struct descriptor* pos)
+{
+ return next_descriptor((uint8_t *) tsdt + sizeof(struct mpeg_tsdt_section),
+ section_ext_length(&tsdt->head) - sizeof(struct mpeg_tsdt_section),
+ pos);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/types.h b/lib/libucsi/mpeg/types.h
new file mode 100644
index 0000000..300cb23
--- /dev/null
+++ b/lib/libucsi/mpeg/types.h
@@ -0,0 +1,127 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_TYPES_H
+#define _UCSI_MPEG_TYPES_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * Known stream types.
+ */
+enum {
+ MPEG_STREAM_TYPE_ISO11172_VIDEO = 0x01,
+ MPEG_STREAM_TYPE_ISO13818_2_VIDEO = 0x02,
+ MPEG_STREAM_TYPE_ISO11172_AUDIO = 0x03,
+ MPEG_STREAM_TYPE_ISO13818_3_AUDIO = 0x04,
+ MPEG_STREAM_TYPE_ISO13818_1_PRIVATE_SECTIONS = 0x05,
+ MPEG_STREAM_TYPE_ISO13818_1_PRIVATE_PES = 0x06,
+ MPEG_STREAM_TYPE_ISO13522_MHEG = 0x07,
+ MPEG_STREAM_TYPE_ISO13818_DSMCC = 0x08,
+ MPEG_STREAM_TYPE_ITUH222_1 = 0x09,
+ MPEG_STREAM_TYPE_ISO13818_6_A = 0x0a,
+ MPEG_STREAM_TYPE_ISO13818_6_B = 0x0b,
+ MPEG_STREAM_TYPE_ISO13818_6_C = 0x0c,
+ MPEG_STREAM_TYPE_ISO13818_6_D = 0x0d,
+ MPEG_STREAM_TYPE_ISO13818_1_AUX = 0x0e,
+ MPEG_STREAM_TYPE_ISO13818_7_AUDIO_ADTS = 0x0f,
+ MPEG_STREAM_TYPE_ISO14496_2_VISUAL = 0x10,
+ MPEG_STREAM_TYPE_ISO14496_3_AUDIO_LATM = 0x11,
+ MPEG_STREAM_TYPE_ISO14496_1_PES = 0x12,
+ MPEG_STREAM_TYPE_ISO14496_1_SECTIONS = 0x13,
+ MPEG_STREAM_TYPE_ISO14496_6_SYNCDOWNLOAD = 0x14,
+ MPEG_STREAM_TYPE_METADATA_PES = 0x15,
+ MPEG_STREAM_TYPE_METADATA_SECTIONS = 0x16,
+ MPEG_STREAM_TYPE_METADATA_DSMCC_DATA = 0x17,
+ MPEG_STREAM_TYPE_METADATA_DSMCC_OBJECT = 0x18,
+ MPEG_STREAM_TYPE_METADATA_SYNCDOWNLOAD = 0x19,
+};
+
+/**
+ * Metadata formats
+ */
+enum {
+ MPEG_METADATA_FORMAT_ISO15938_1_TEM = 0x01,
+ MPEG_METADATA_FORMAT_ISO15938_1_BIM = 0x02,
+ MPEG_METADATA_FORMAT_METADATA_APPLICATION_FORMAT = 0x3F,
+ MPEG_METADATA_FORMAT_METADATA_APPLICATION_FORMAT_ID = 0xFF,
+};
+
+/**
+ * MPEG 4 audio profile and levels.
+ */
+enum {
+ MPEG4_AUDIO_PROFILE_MAIN_LEVEL_1 = 0x10,
+ MPEG4_AUDIO_PROFILE_MAIN_LEVEL_2 = 0x11,
+ MPEG4_AUDIO_PROFILE_MAIN_LEVEL_3 = 0x12,
+ MPEG4_AUDIO_PROFILE_MAIN_LEVEL_4 = 0x13,
+
+ MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_1 = 0x18,
+ MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_2 = 0x19,
+ MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_3 = 0x1a,
+ MPEG4_AUDIO_PROFILE_SCALABLE_LEVEL_4 = 0x1b,
+
+ MPEG4_AUDIO_PROFILE_SPEECH_LEVEL_1 = 0x20,
+ MPEG4_AUDIO_PROFILE_SPEECH_LEVEL_2 = 0x21,
+
+ MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_1 = 0x28,
+ MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_2 = 0x29,
+ MPEG4_AUDIO_PROFILE_SYNTHESIS_LEVEL_3 = 0x2a,
+
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_1 = 0x30,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_2 = 0x31,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_3 = 0x32,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_4 = 0x33,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_5 = 0x34,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_6 = 0x35,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_7 = 0x36,
+ MPEG4_AUDIO_PROFILE_HQ_LEVEL_8 = 0x37,
+
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_1 = 0x38,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_2 = 0x39,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_3 = 0x3a,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_4 = 0x3b,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_5 = 0x3c,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_6 = 0x3d,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_7 = 0x3e,
+ MPEG4_AUDIO_PROFILE_LOW_DELAY_LEVEL_8 = 0x3f,
+
+ MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_1 = 0x40,
+ MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_2 = 0x41,
+ MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_3 = 0x42,
+ MPEG4_AUDIO_PROFILE_NATURAL_LEVEL_4 = 0x43,
+
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_1 = 0x48,
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_2 = 0x49,
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_3 = 0x4a,
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_4 = 0x4b,
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_5 = 0x4c,
+ MPEG4_AUDIO_PROFILE_MOBILE_LEVEL_6 = 0x4d,
+};
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/video_stream_descriptor.h b/lib/libucsi/mpeg/video_stream_descriptor.h
new file mode 100644
index 0000000..14e9196
--- /dev/null
+++ b/lib/libucsi/mpeg/video_stream_descriptor.h
@@ -0,0 +1,101 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_VIDEO_STREAM_DESCRIPTOR
+#define _UCSI_MPEG_VIDEO_STREAM_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/endianops.h>
+
+/**
+ * The mpeg_video_stream_descriptor structure
+ */
+struct mpeg_video_stream_descriptor {
+ struct descriptor d;
+
+ EBIT5(uint8_t multiple_frame_rate_flag : 1; ,
+ uint8_t frame_rate_code : 4; ,
+ uint8_t mpeg_1_only_flag : 1; ,
+ uint8_t constrained_parameter_flag : 1; ,
+ uint8_t still_picture_flag : 1; );
+ /* if (mpeg_1_only_flag == 0) struct mpeg_video_stream_extra extra */
+} __ucsi_packed;
+
+/**
+ * The mpeg_video_stream_extra - only present in non-MPEG1-only streams.
+ */
+struct mpeg_video_stream_extra {
+ uint8_t profile_and_level_indication;
+ EBIT3(uint8_t chroma_format : 2; ,
+ uint8_t frame_rate_extension : 1; ,
+ uint8_t reserved : 5; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_video_stream_descriptor structure.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_video_stream_descriptor, or NULL on error.
+ */
+static inline struct mpeg_video_stream_descriptor*
+ mpeg_video_stream_descriptor_codec(struct descriptor* d)
+{
+ struct mpeg_video_stream_descriptor* vsd =
+ (struct mpeg_video_stream_descriptor*) d;
+
+ if (d->len < (sizeof(struct mpeg_video_stream_descriptor) - 2))
+ return NULL;
+
+ if (!vsd->mpeg_1_only_flag) {
+ if (d->len != (sizeof(struct mpeg_video_stream_descriptor) +
+ sizeof(struct mpeg_video_stream_extra) - 2))
+ return NULL;
+ }
+
+ return (struct mpeg_video_stream_descriptor*) d;
+}
+
+/**
+ * Get a pointer to the mpeg_video_stream_extra structure.
+ *
+ * @param d Pointer to the mpeg_video_stream_descriptor structure.
+ * @return Pointer to the mpeg_video_stream_extra structure, or NULL on error.
+ */
+static inline struct mpeg_video_stream_extra*
+ mpeg_video_stream_descriptor_extra(struct mpeg_video_stream_descriptor* d)
+{
+ if (d->mpeg_1_only_flag != 0)
+ return NULL;
+
+ return (struct mpeg_video_stream_extra*)
+ ((uint8_t*) d + sizeof(struct mpeg_video_stream_descriptor));
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/mpeg/video_window_descriptor.h b/lib/libucsi/mpeg/video_window_descriptor.h
new file mode 100644
index 0000000..a9a63c7
--- /dev/null
+++ b/lib/libucsi/mpeg/video_window_descriptor.h
@@ -0,0 +1,64 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_MPEG_VIDEO_WINDOW_DESCRIPTOR
+#define _UCSI_MPEG_VIDEO_WINDOW_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+
+/**
+ * mpeg_video_window_descriptor structure.
+ */
+struct mpeg_video_window_descriptor {
+ struct descriptor d;
+
+ EBIT3(uint32_t horizontal_offset : 14; ,
+ uint32_t vertical_offset : 14; ,
+ uint32_t window_priority : 4; );
+} __ucsi_packed;
+
+/**
+ * Process an mpeg_video_window_descriptor.
+ *
+ * @param d Pointer to the generic descriptor structure.
+ * @return Pointer to the mpeg_video_window_descriptor structure, or NULL on error.
+ */
+static inline struct mpeg_video_window_descriptor*
+ mpeg_video_window_descriptor_codec(struct descriptor* d)
+{
+ if (d->len != (sizeof(struct mpeg_video_window_descriptor) - 2))
+ return NULL;
+
+ bswap32((uint8_t*) d + 2);
+
+ return (struct mpeg_video_window_descriptor*) d;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/section.h b/lib/libucsi/section.h
new file mode 100644
index 0000000..53ad07f
--- /dev/null
+++ b/lib/libucsi/section.h
@@ -0,0 +1,253 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Kenneth Aafloy (kenneth@linuxtv.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_SECTION_H
+#define _UCSI_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/endianops.h>
+#include <libucsi/descriptor.h>
+#include <libucsi/crc32.h>
+#include <stdint.h>
+#include <string.h>
+
+#define CRC_SIZE 4
+
+
+/**
+ * Generic section header.
+ */
+struct section {
+ uint8_t table_id;
+ EBIT4(uint16_t syntax_indicator : 1; ,
+ uint16_t private_indicator : 1; , /* 2.4.4.10 */
+ uint16_t reserved : 2; ,
+ uint16_t length :12; );
+} __ucsi_packed;
+
+/**
+ * Generic extended section header structure.
+ */
+struct section_ext {
+ uint8_t table_id;
+ EBIT4(uint16_t syntax_indicator : 1; ,
+ uint16_t private_indicator : 1; , /* 2.4.4.10 */
+ uint16_t reserved : 2; ,
+ uint16_t length :12; );
+
+ uint16_t table_id_ext;
+ EBIT3(uint8_t reserved1 : 2; ,
+ uint8_t version_number : 5; ,
+ uint8_t current_next_indicator : 1; );
+ uint8_t section_number;
+ uint8_t last_section_number;
+} __ucsi_packed;
+
+/**
+ * Structure for keeping track of sections of a PSI table.
+ */
+struct psi_table_state {
+ uint8_t version_number;
+ uint16_t next_section_number;
+ uint8_t complete:1;
+ uint8_t new_table:1;
+} __ucsi_packed;
+
+
+/**
+ * Determine the total length of a section, including the header.
+ *
+ * @param section The parsed section structure.
+ * @return The length.
+ */
+static inline size_t section_length(struct section *section)
+{
+ return section->length + sizeof(struct section);
+}
+
+/**
+ * Determine the total length of an extended section, including the header,
+ * but omitting the CRC.
+ *
+ * @param section The parsed section_ext structure.
+ * @return The length.
+ */
+static inline size_t section_ext_length(struct section_ext * section)
+{
+ return section->length + sizeof(struct section) - CRC_SIZE;
+}
+
+/**
+ * Process a section structure in-place.
+ *
+ * @param buf Pointer to the data.
+ * @param len Length of data.
+ * @return Pointer to the section structure, or NULL if invalid.
+ */
+static inline struct section * section_codec(uint8_t * buf, size_t len)
+{
+ struct section * ret = (struct section *)buf;
+
+ if (len < 3)
+ return NULL;
+
+ bswap16(buf+1);
+
+ if (len != ret->length + 3U)
+ return NULL;
+
+ return ret;
+}
+
+/**
+ * Some sections have a CRC even though they are not section_exts.
+ * This function is to allow checking of them.
+ *
+ * @param section Pointer to the processed section structure.
+ * @return Nonzero on error, or 0 if the CRC was correct.
+ */
+static inline int section_check_crc(struct section *section)
+{
+ uint8_t * buf = (uint8_t *) section;
+ size_t len = section_length(section);
+ uint32_t crc;
+
+ /* the crc check has to be performed on the unswapped data */
+ bswap16(buf+1);
+ crc = crc32(CRC32_INIT, buf, len);
+ bswap16(buf+1);
+
+ /* the crc check includes the crc value,
+ * the result should therefore be zero.
+ */
+ if (crc)
+ return -1;
+ return 0;
+}
+
+
+/**
+ * Decode an extended section structure.
+ *
+ * @param section Pointer to the processed section structure.
+ * @param check_crc If 1, the CRC of the section will also be checked.
+ * @return Pointer to the parsed section_ext structure, or NULL if invalid.
+ */
+static inline struct section_ext * section_ext_decode(struct section * section,
+ int check_crc)
+{
+ if (section->syntax_indicator == 0)
+ return NULL;
+
+ if (check_crc) {
+ if (section_check_crc(section))
+ return NULL;
+ }
+
+ bswap16((uint8_t *)section + sizeof(struct section));
+
+ return (struct section_ext *)section;
+}
+
+/**
+ * Encode an extended section structure for transmission.
+ *
+ * @param section Pointer to the section_ext structure.
+ * @param update_crc If 1, the CRC of the section will also be updated.
+ * @return Pointer to the encoded section_ext structure, or NULL if invalid.
+ */
+static inline struct section_ext * section_ext_encode(struct section_ext* section,
+ int update_crc)
+{
+ if (section->syntax_indicator == 0)
+ return NULL;
+
+ bswap16((uint8_t *)section + sizeof(struct section));
+
+ if (update_crc) {
+ uint8_t * buf = (uint8_t *) section;
+ int len = sizeof(struct section) + section->length;
+ uint32_t crc;
+
+ /* the crc has to be performed on the swapped data */
+ bswap16(buf+1);
+ crc = crc32(CRC32_INIT, buf, len-4);
+ bswap16(buf+1);
+
+ /* update the CRC */
+ *((uint32_t*) (buf+len-4)) = crc;
+ bswap32(buf+len-4);
+ }
+
+ return (struct section_ext *)section;
+}
+
+/**
+ * Reset a psi_table_state structure.
+ *
+ * @param tstate The structure to reset.
+ */
+static inline void psi_table_state_reset(struct psi_table_state *tstate)
+{
+ tstate->version_number = 0xff;
+}
+
+/**
+ * Check if a supplied section_ext is something we want to process.
+ *
+ * @param section The parsed section_ext structure.
+ * @param tstate The state structure for this PSI table.
+ * @return 0=> not useful. nonzero => useful.
+ */
+static inline int section_ext_useful(struct section_ext *section, struct psi_table_state *tstate)
+{
+ if ((section->version_number == tstate->version_number) && tstate->complete)
+ return 0;
+ if (section->version_number != tstate->version_number) {
+ if (section->section_number != 0)
+ return 0;
+
+ tstate->next_section_number = 0;
+ tstate->complete = 0;
+ tstate->version_number = section->version_number;
+ tstate->new_table = 1;
+ } else if (section->section_number == tstate->next_section_number) {
+ tstate->new_table = 0;
+ } else {
+ return 0;
+ }
+
+ tstate->next_section_number++;
+ if (section->last_section_number < tstate->next_section_number) {
+ tstate->complete = 1;
+ }
+
+ return 1;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/section_buf.c b/lib/libucsi/section_buf.c
new file mode 100644
index 0000000..35d465e
--- /dev/null
+++ b/lib/libucsi/section_buf.c
@@ -0,0 +1,173 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <errno.h>
+#include <string.h>
+#include "section_buf.h"
+
+#define SECTION_HDR_SIZE 3
+#define SECTION_PAD 0xff
+
+int section_buf_init(struct section_buf *section, int max)
+{
+ if (max < SECTION_HDR_SIZE)
+ return -EINVAL;
+
+ memset(section, 0, sizeof(struct section_buf));
+ section->max = max; /* max size of data */
+ section->len = SECTION_HDR_SIZE;
+ section->wait_pdu = 1;
+
+ return 0;
+}
+
+int section_buf_add(struct section_buf *section, uint8_t* frag, int len, int *section_status)
+{
+ int copy;
+ int used = 0;
+ uint8_t *data;
+ uint8_t *pos = (uint8_t*) section + sizeof(struct section_buf) + section->count;
+
+ /* have we finished? */
+ if (section->header && (section->len == section->count)) {
+ *section_status = 1;
+ return 0;
+ }
+
+ /* skip over section padding bytes */
+ *section_status = 0;
+ if (section->count == 0) {
+ while(len && (*frag == SECTION_PAD)) {
+ frag++;
+ len--;
+ used++;
+ }
+
+ if (len == 0)
+ return used;
+ }
+
+ /* grab the header to get the section length */
+ if (!section->header) {
+ /* copy the header frag */
+ copy = SECTION_HDR_SIZE - section->count;
+ if (copy > len)
+ copy = len;
+ memcpy(pos, frag, copy);
+ section->count += copy;
+ pos += copy;
+ frag += copy;
+ used += copy;
+ len -= copy;
+
+ /* we need 3 bytes for the section header */
+ if (section->count != SECTION_HDR_SIZE)
+ return used;
+
+ /* work out the length & check it isn't too big */
+ data = (uint8_t*) section + sizeof(struct section_buf);
+ section->len = SECTION_HDR_SIZE + (((data[1] & 0x0f) << 8) | data[2]);
+ if (section->len > section->max) {
+ *section_status = -ERANGE;
+ return len + used;
+ }
+
+ /* update fields */
+ section->header = 1;
+ }
+
+ /* accumulate frag */
+ copy = section->len - section->count;
+ if (copy > len)
+ copy = len;
+ memcpy(pos, frag, copy);
+ section->count += copy;
+ used += copy;
+
+ /* have we finished? */
+ if (section->header && (section->len == section->count))
+ *section_status = 1;
+
+ /* return number of bytes used */
+ return used;
+}
+
+int section_buf_add_transport_payload(struct section_buf *section,
+ uint8_t* payload, int len,
+ int pdu_start, int *section_status)
+{
+ int used = 0;
+ int tmp;
+
+ /* have we finished? */
+ if (section->header && (section->len == section->count)) {
+ *section_status = 1;
+ return 0;
+ }
+
+ /* don't bother if we're waiting for a PDU */
+ *section_status = 0;
+ if (section->wait_pdu && (!pdu_start))
+ return len;
+
+ /* if we're at a PDU start, we need extra handling for the extra first
+ * byte giving the offset to the start of the next section. */
+ if (pdu_start) {
+ /* we have received a pdu */
+ section->wait_pdu = 0;
+
+ /* work out the offset to the _next_ payload */
+ int offset = payload[0];
+ if ((offset+1) > len) {
+ section->wait_pdu = 1;
+ *section_status = -EINVAL;
+ return len;
+ }
+
+ /* accumulate the end if we need to */
+ if (section->count != 0) {
+ /* add the final fragment. */
+ tmp = section_buf_add(section, payload + 1, offset, section_status);
+
+ /* the stream said this was the final fragment
+ * (PDU START bit) - check that it really was! */
+ if ((tmp != offset) || section_buf_remaining(section) || (*section_status != 1)) {
+ *section_status = -ERANGE;
+ section->wait_pdu = 1;
+ return 1 + tmp;
+ }
+
+ /* it is complete - return the number of bytes we used */
+ return 1 + tmp;
+ }
+
+ /* otherwise, we skip the end of the previous section, and
+ * start accumulating the new data. */
+ used = 1 + offset;
+ }
+
+ /* ok, just accumulate the data as normal */
+ tmp = section_buf_add(section, payload+used, len - used, section_status);
+ if (*section_status < 0) {
+ section->wait_pdu = 1;
+ }
+
+ return used + tmp;
+}
diff --git a/lib/libucsi/section_buf.h b/lib/libucsi/section_buf.h
new file mode 100644
index 0000000..52d2f84
--- /dev/null
+++ b/lib/libucsi/section_buf.h
@@ -0,0 +1,124 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_SECTION_BUF_H
+#define _UCSI_SECTION_BUF_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+
+#define DVB_MAX_SECTION_BYTES 4096
+
+/**
+ * Buffer used to keep track of section fragments. You should allocate an
+ * area of memory of size (sizeof(section_buf) + <maxsectionsize>), and pass that area
+ * to section_buf_init() to set it up.
+ */
+struct section_buf {
+ uint32_t max; /* maximum size of section - setup by section_buf_init() */
+ uint32_t count; /* number of bytes currently accumulated */
+ uint32_t len; /* total number of bytes expected in the complete section */
+ uint8_t header:1; /* flag indicating the section header has been commpletely received */
+ uint8_t wait_pdu:1;/* flag indicating to wait till the next PDU start */
+ /* uint8_t data[] */
+};
+
+/**
+ * Initialise a section_buf structure.
+ *
+ * @param section The section_buf to initialise.
+ * @param max Maximum number of bytes in section (must be > 3)
+ * @return 0 on success, nonzero on error.
+ */
+extern int section_buf_init(struct section_buf *section, int max);
+
+/**
+ * Reset a section_buf structure (e.g. if a discontinuity occurred). The
+ * section_buf will wait for the first PDU start indicator.
+ *
+ * @param section The section_buf to reset.
+ */
+static inline void section_buf_reset(struct section_buf *section)
+{
+ int tmp = section->wait_pdu;
+ section_buf_init(section, section->max);
+ section->wait_pdu = tmp;
+}
+
+/**
+ * Add a data fragment to a section_buf.
+ *
+ * @param section section_buf to add to.
+ * @param frag Pointer to data fragment.
+ * @param len Number of bytes of data.
+ * @param section_status 0: nothing special. 1: section complete. -ERANGE indicates that the
+ * section is larger than section->max.
+ * @return Number of bytes which were consumed.
+ */
+extern int section_buf_add(struct section_buf *section, uint8_t* frag, int len, int *section_status);
+
+/**
+ * Add a transport packet PSI payload to a section_buf. This takes into account
+ * the extra byte present in PDU_START flagged packets.
+ *
+ * @param section section_buf to add to.
+ * @param payload Pointer to packet payload data.
+ * @param len Number of bytes of data.
+ * @param pdu_start True if the payload_unit_start_indicator flag was set in the
+ * TS packet.
+ * @param section_status 0: nothing special. 1: section complete. -ERANGE indicates that the
+ * section is larger than section->max. -EINVAL indicates the pointer_field was completely
+ * invalid (too large).
+ */
+extern int section_buf_add_transport_payload(struct section_buf *section,
+ uint8_t* payload, int len,
+ int pdu_start, int *section_status);
+
+/**
+ * Get the number of bytes left to be received in a section_buf.
+ *
+ * @param section The section_buf concerned.
+ * @return The number of bytes.
+ */
+static inline int section_buf_remaining(struct section_buf *section)
+{
+ return section->len - section->count;
+}
+
+/**
+ * Return a pointer to the start of the data in the section_buf.
+ *
+ * @param section The section_buf concerned.
+ * @return The data.
+ */
+static inline uint8_t* section_buf_data(struct section_buf *section)
+{
+ return (uint8_t*) section + sizeof(struct section_buf);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/testrecord.txt b/lib/libucsi/testrecord.txt
new file mode 100644
index 0000000..84d56aa
--- /dev/null
+++ b/lib/libucsi/testrecord.txt
@@ -0,0 +1,146 @@
+libucsi test record. Anything without PASS is either not tested, or is
+currently broken.
+
+Testing means (a) ensure there are no segfaults etc. (b) dump the raw hex,
+decode it by hand, and check it matches the output.
+
+Sections:
+PASS mpeg/cat_section.h
+ mpeg/odsmt_section.h
+PASS mpeg/pat_section.h
+PASS mpeg/pmt_section.h
+ mpeg/tsdt_section.h
+ mpeg/metadata_section.h
+
+PASS dvb/bat_section.h
+ dvb/dit_section.h
+PASS dvb/eit_section.h
+ dvb/int_section.h
+PASS dvb/nit_section.h
+ dvb/rst_section.h
+PASS dvb/sdt_section.h
+ dvb/sit_section.h
+PASS dvb/st_section.h
+PASS dvb/tdt_section.h
+PASS dvb/tot_section.h
+ dvb/tva_container_section.h
+
+PASS atsc/cvct_section.h
+ atsc/dccsct_section.h
+ atsc/dcct_section.h
+PASS atsc/eit_section.h
+PASS atsc/ett_section.h
+PASS atsc/mgt_section.h
+ atsc/rrt_section.h
+PASS atsc/stt_section.h
+PASS atsc/tvct_section.h
+
+Descriptors:
+PASS mpeg/audio_stream_descriptor.h
+PASS mpeg/ca_descriptor.h
+ mpeg/content_labelling_descriptor.h
+PASS mpeg/copyright_descriptor.h
+PASS mpeg/data_stream_alignment_descriptor.h
+PASS mpeg/external_es_id_descriptor.h
+ mpeg/fmc_descriptor.h
+PASS mpeg/fmxbuffer_size_descriptor.h
+ mpeg/hierarchy_descriptor.h
+ mpeg/ibp_descriptor.h
+ mpeg/iod_descriptor.h
+PASS mpeg/iso_639_language_descriptor.h
+PASS mpeg/maximum_bitrate_descriptor.h
+ mpeg/metadata_descriptor.h
+ mpeg/metadata_pointer_descriptor.h
+ mpeg/metadata_std_descriptor.h
+ mpeg/mpeg4_audio_descriptor.h
+ mpeg/mpeg4_video_descriptor.h
+ mpeg/multiplex_buffer_descriptor.h
+PASS mpeg/multiplex_buffer_utilization_descriptor.h
+ mpeg/muxcode_descriptor.h
+PASS mpeg/private_data_indicator_descriptor.h
+PASS mpeg/registration_descriptor.h
+ mpeg/sl_descriptor.h
+PASS mpeg/smoothing_buffer_descriptor.h
+PASS mpeg/std_descriptor.h
+PASS mpeg/system_clock_descriptor.h
+ mpeg/target_background_grid_descriptor.h
+PASS mpeg/video_stream_descriptor.h
+ mpeg/video_window_descriptor.h
+
+ dvb/ac3_descriptor.h
+ dvb/adaptation_field_data_descriptor.h
+ dvb/ait_application_descriptor.h
+ dvb/ait_application_icons_descriptor.h
+ dvb/ait_application_name_descriptor.h
+ dvb/ait_external_application_authorisation_descriptor.h
+ dvb/ancillary_data_descriptor.h
+ dvb/announcement_support_descriptor.h
+ dvb/application_signalling_descriptor.h
+PASS dvb/bouquet_name_descriptor.h
+PASS dvb/ca_identifier_descriptor.h
+ dvb/cable_delivery_descriptor.h
+ dvb/cell_frequency_link_descriptor.h
+ dvb/cell_list_descriptor.h
+PASS dvb/component_descriptor.h
+PASS dvb/content_descriptor.h
+ dvb/content_identifier_descriptor.h
+ dvb/country_availability_descriptor.h
+ dvb/data_broadcast_descriptor.h
+PASS dvb/data_broadcast_id_descriptor.h
+ dvb/default_authority_descriptor.h
+ dvb/dsng_descriptor.h
+ dvb/extended_event_descriptor.h
+PASS dvb/frequency_list_descriptor.h
+PASS dvb/linkage_descriptor.h
+PASS dvb/local_time_offset_descriptor.h
+ dvb/mhp_data_broadcast_id_descriptor.h
+ dvb/mosaic_descriptor.h
+ dvb/multilingual_bouquet_name_descriptor.h
+PASS dvb/multilingual_component_descriptor.h
+ dvb/multilingual_network_name_descriptor.h
+ dvb/multilingual_service_name_descriptor.h
+PASS dvb/network_name_descriptor.h
+ dvb/nvod_reference_descriptor.h
+PASS dvb/parental_rating_descriptor.h
+ dvb/partial_transport_stream_descriptor.h
+ dvb/pdc_descriptor.h
+PASS dvb/private_data_specifier_descriptor.h
+ dvb/related_content_descriptor.h
+ dvb/rnt_rar_over_dvb_stream_descriptor.h
+ dvb/rnt_rar_over_ip_descriptor.h
+ dvb/rnt_rnt_scan_descriptor.h
+ dvb/s2_satellite_delivery_descriptor.h
+PASS dvb/satellite_delivery_descriptor.h
+ dvb/scrambling_descriptor.h
+ dvb/service_availablility_descriptor.h
+PASS dvb/service_descriptor.h
+ dvb/service_identifier_descriptor.h
+PASS dvb/service_list_descriptor.h
+ dvb/service_move_descriptor.h
+PASS dvb/short_event_descriptor.h
+ dvb/short_smoothing_buffer_descriptor.h
+PASS dvb/stream_identifier_descriptor.h
+PASS dvb/stuffing_descriptor.h
+PASS dvb/subtitling_descriptor.h
+ dvb/telephone_descriptor.h
+ dvb/teletext_descriptor.h
+PASS dvb/terrestrial_delivery_descriptor.h
+ dvb/time_shifted_event_descriptor.h
+ dvb/time_shifted_service_descriptor.h
+ dvb/transport_stream_descriptor.h
+ dvb/tva_id_descriptor.h
+ dvb/vbi_data_descriptor.h
+ dvb/vbi_teletext_descriptor.h
+
+PASS atsc/ac3_descriptor.h
+PASS atsc/caption_service_descriptor.h
+ atsc/component_name_descriptor.h
+PASS atsc/content_advisory_descriptor.h
+ atsc/dcc_arriving_request_descriptor.h
+ atsc/dcc_departing_request_descriptor.h
+PASS atsc/extended_channel_name_descriptor.h
+ atsc/genre_descriptor.h
+ atsc/rc_descriptor.h
+PASS atsc/service_location_descriptor.h
+PASS atsc/stuffing_descriptor.h
+ atsc/time_shifted_service_descriptor.h
diff --git a/lib/libucsi/transport_packet.c b/lib/libucsi/transport_packet.c
new file mode 100644
index 0000000..ca6c2e1
--- /dev/null
+++ b/lib/libucsi/transport_packet.c
@@ -0,0 +1,256 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "transport_packet.h"
+
+#define CONTINUITY_VALID 0x80
+#define CONTINUITY_DUPESEEN 0x40
+
+int transport_packet_values_extract(struct transport_packet *pkt,
+ struct transport_values *out,
+ enum transport_value extract)
+{
+ uint8_t *end = (uint8_t*) pkt + TRANSPORT_PACKET_LENGTH;
+ uint8_t *adapend;
+ uint8_t *pos = (uint8_t*) pkt + sizeof(struct transport_packet);
+ enum transport_value extracted = 0;
+ enum transport_adaptation_flags adapflags = 0;
+ enum transport_adaptation_extension_flags adapextflags = 0;
+ int adaplength = 0;
+ int adapextlength = 0;
+
+ /* does the packet contain an adaptation field ? */
+ if ((pkt->adaptation_field_control & 2) == 0)
+ goto extract_payload;
+
+ /* get the adaptation field length and skip the byte */
+ adaplength = *pos++;
+
+ /* do we actually have any adaptation data? */
+ if (adaplength == 0)
+ goto extract_payload;
+
+ /* sanity check */
+ adapend = pos + adaplength;
+ if (adapend > end)
+ return -1;
+
+ /* extract the adaptation flags (we must have at least 1 byte to be here) */
+ adapflags = *pos++;
+
+ /* do we actually want anything else? */
+ if ((extract & 0xffff) == 0)
+ goto extract_payload;
+
+ /* PCR? */
+ if (adapflags & transport_adaptation_flag_pcr) {
+ if ((pos+6) > adapend)
+ return -1;
+
+ if (extract & transport_value_pcr) {
+ uint64_t base = ((uint64_t) pos[0] << 25) |
+ ((uint64_t) pos[1] << 17) |
+ ((uint64_t) pos[2] << 9) |
+ ((uint64_t) pos[3] << 1) |
+ ((uint64_t) pos[4] >> 7);
+ uint64_t ext = (((uint64_t) pos[4] & 1) << 8) |
+ (uint64_t) pos[5];
+ out->pcr= base * 300ULL + ext;
+ extracted |= transport_value_pcr;
+ }
+ pos += 6;
+ }
+
+ /* OPCR? */
+ if (adapflags & transport_adaptation_flag_opcr) {
+ if ((pos+6) > adapend)
+ return -1;
+
+ if (extract & transport_value_opcr) {
+ uint64_t base = ((uint64_t) pos[0] << 25) |
+ ((uint64_t) pos[1] << 17) |
+ ((uint64_t) pos[2] << 9) |
+ ((uint64_t) pos[3] << 1) |
+ ((uint64_t) pos[4] >> 7);
+ uint64_t ext = (((uint64_t) pos[4] & 1) << 8) |
+ (uint64_t) pos[5];
+ out->opcr= base * 300ULL + ext;
+ extracted |= transport_value_opcr;
+ }
+ pos += 6;
+ }
+
+ /* splice countdown? */
+ if (adapflags & transport_adaptation_flag_splicing_point) {
+ if ((pos+1) > adapend)
+ return -1;
+
+ if (extract & transport_value_splice_countdown) {
+ out->splice_countdown = *pos;
+ extracted |= transport_value_splice_countdown;
+ }
+ pos++;
+ }
+
+ /* private data? */
+ if (adapflags & transport_adaptation_flag_private_data) {
+ if ((pos+1) > adapend)
+ return -1;
+ if ((pos+1+*pos) > adapend)
+ return -1;
+
+ if (extract & transport_value_private_data) {
+ out->private_data_length = *pos;
+ out->private_data = pos + 1;
+ extracted |= transport_value_private_data;
+ }
+ pos += 1 + *pos;
+ }
+
+ /* is there an adaptation extension? */
+ if (!(adapflags & transport_adaptation_flag_extension))
+ goto extract_payload;
+
+ /* get/check the length */
+ if (pos >= adapend)
+ return -1;
+ adapextlength = *pos++;
+ if ((pos + adapextlength) > adapend)
+ return -1;
+
+ /* do we want/have anything in the adaptation extension? */
+ if (((extract & 0xff00) == 0) || (adapextlength == 0))
+ goto extract_payload;
+
+ /* extract the adaptation extension flags (we must have at least 1 byte
+ * to be here) */
+ adapextflags = *pos++;
+
+ /* LTW? */
+ if (adapextflags & transport_adaptation_extension_flag_ltw) {
+ if ((pos+2) > adapend)
+ return -1;
+
+ if (extract & transport_value_ltw) {
+ if (*pos & 0x80) {
+ out->ltw_offset = ((pos[0] & 0x7f) << 8) |
+ (pos[1]);
+ extracted |= transport_value_ltw;
+ }
+ }
+ pos += 2;
+ }
+
+ /* piecewise_rate? */
+ if (adapextflags & transport_adaptation_extension_flag_piecewise_rate) {
+ if ((pos+3) > adapend)
+ return -1;
+
+ if (extract & transport_value_piecewise_rate) {
+ out->piecewise_rate = ((pos[0] & 0x3f) << 16) |
+ (pos[1] << 8) |
+ pos[2];
+ extracted |= transport_value_piecewise_rate;
+ }
+ pos += 3;
+ }
+
+ /* seamless_splice? */
+ if (adapextflags & transport_adaptation_extension_flag_seamless_splice) {
+ if ((pos+5) > adapend)
+ return -1;
+
+ if (extract & transport_value_piecewise_rate) {
+ out->splice_type = pos[0] >> 4;
+ out->dts_next_au = ((pos[0] & 0x0e) << 29) |
+ (pos[1] << 22) |
+ ((pos[2] & 0xfe) << 14) |
+ (pos[3] << 7) |
+ ((pos[4] & 0xfe) >> 1);
+ extracted |= transport_value_seamless_splice;
+ }
+ pos += 5;
+ }
+
+
+
+extract_payload:
+ /* does the packet contain a payload? */
+ if (pkt->adaptation_field_control & 1) {
+ int off = sizeof(struct transport_packet);
+ if (pkt->adaptation_field_control & 2)
+ off++;
+ off += adaplength;
+
+ out->payload = (uint8_t*) pkt + off;
+ out->payload_length = TRANSPORT_PACKET_LENGTH - off;
+ } else {
+ out->payload = NULL;
+ out->payload_length = 0;
+ }
+
+ out->flags = adapflags;
+ return extracted;
+}
+
+int transport_packet_continuity_check(struct transport_packet *pkt,
+ int discontinuity_indicator, unsigned char *cstate)
+{
+ unsigned char pktcontinuity = pkt->continuity_counter;
+ unsigned char prevcontinuity = *cstate & 0x0f;
+ unsigned char nextcontinuity;
+
+ /* NULL packets have undefined continuity */
+ if (transport_packet_pid(pkt) == TRANSPORT_NULL_PID)
+ return 0;
+
+ /* is the state valid? */
+ if (!(*cstate & CONTINUITY_VALID)) {
+ *cstate = pktcontinuity | CONTINUITY_VALID;
+ return 0;
+ }
+
+ /* check for discontinuity_indicator */
+ if (discontinuity_indicator) {
+ *cstate = pktcontinuity | CONTINUITY_VALID;
+ return 0;
+ }
+
+ /* only packets with a payload should increment the counter */
+ if (pkt->adaptation_field_control & 1)
+ nextcontinuity = (prevcontinuity + 1) & 0xf;
+ else
+ nextcontinuity = prevcontinuity;
+
+ /* check for a normal continuity progression */
+ if (nextcontinuity == pktcontinuity) {
+ *cstate = pktcontinuity | CONTINUITY_VALID;
+ return 0;
+ }
+
+ /* one dupe is allowed */
+ if ((prevcontinuity == pktcontinuity) && (!(*cstate & CONTINUITY_DUPESEEN))) {
+ *cstate = pktcontinuity | (CONTINUITY_VALID|CONTINUITY_DUPESEEN);
+ return 0;
+ }
+
+ /* continuity error */
+ return -1;
+}
diff --git a/lib/libucsi/transport_packet.h b/lib/libucsi/transport_packet.h
new file mode 100644
index 0000000..6314eca
--- /dev/null
+++ b/lib/libucsi/transport_packet.h
@@ -0,0 +1,195 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_TRANSPORT_PACKET_H
+#define _UCSI_TRANSPORT_PACKET_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <stdint.h>
+#include "descriptor.h"
+
+#define TRANSPORT_PACKET_LENGTH 188
+#define TRANSPORT_PACKET_SYNC 0x47
+#define TRANSPORT_MAX_PIDS 0x2000
+#define TRANSPORT_NULL_PID 0x1fff
+
+
+/**
+ * Enumeration of adaptation field control values.
+ */
+enum transport_adaptation_field_control {
+ transport_adaptation_field_control_reserved = 0x00,
+ transport_adaptation_field_control_payload_only = 0x01,
+ transport_adaptation_field_control_adaptation_only = 0x02,
+ transport_adaptation_field_control_adaptation_payload = 0x03,
+};
+
+/**
+ * Enumeration of scrambling control values.
+ */
+enum transport_scrambling_control {
+ transport_scrambling_control_unscrambled = 0x00,
+ transport_scrambling_control_user_1 = 0x01,
+ transport_scrambling_control_user_2 = 0x02,
+ transport_scrambling_control_user_3 = 0x03,
+};
+
+/**
+ * Enumeration of adaptation flags.
+ */
+enum transport_adaptation_flags {
+ transport_adaptation_flag_discontinuity = 0x80,
+ transport_adaptation_flag_random_access = 0x40,
+ transport_adaptation_flag_es_priority = 0x20,
+ transport_adaptation_flag_pcr = 0x10,
+ transport_adaptation_flag_opcr = 0x08,
+ transport_adaptation_flag_splicing_point = 0x04,
+ transport_adaptation_flag_private_data = 0x02,
+ transport_adaptation_flag_extension = 0x01,
+};
+
+/**
+ * Enumeration of adaptation extension flags.
+ */
+enum transport_adaptation_extension_flags {
+ transport_adaptation_extension_flag_ltw = 0x80,
+ transport_adaptation_extension_flag_piecewise_rate = 0x40,
+ transport_adaptation_extension_flag_seamless_splice = 0x20,
+};
+
+/**
+ * Enumeration of flags controlling which values to extract using the
+ * transport_packet_values_extract() function.
+ */
+enum transport_value {
+ /* normal adaptation */
+ transport_value_pcr = 0x0001,
+ transport_value_opcr = 0x0002,
+ transport_value_splice_countdown = 0x0004,
+ transport_value_private_data = 0x0008,
+
+ /* extension adaptation */
+ transport_value_ltw = 0x0100,
+ transport_value_piecewise_rate = 0x0200,
+ transport_value_seamless_splice = 0x0400,
+};
+
+/**
+ * Structure describing a transport packet header.
+ */
+struct transport_packet {
+ uint8_t sync_byte;
+ EBIT4(uint8_t transport_error_indicator : 1; ,
+ uint8_t payload_unit_start_indicator : 1; ,
+ uint8_t transport_priority : 1; ,
+ uint8_t pid_hi : 5; );
+ uint8_t pid_lo;
+ EBIT3(uint8_t transport_scrambling_control : 2; ,
+ uint8_t adaptation_field_control : 2; ,
+ uint8_t continuity_counter : 4; );
+ /* values */
+} __ucsi_packed;
+
+/**
+ * Structure to extract values into using the transport_packet_values_extract()
+ * function.
+ */
+struct transport_values {
+ enum transport_adaptation_flags flags; /* always extracted */
+ uint8_t *payload; /* always extracted */
+ uint16_t payload_length; /* always extracted */
+
+ uint64_t pcr;
+ uint64_t opcr;
+ uint8_t splice_countdown;
+ uint8_t private_data_length;
+ uint8_t *private_data;
+ uint16_t ltw_offset;
+ uint32_t piecewise_rate;
+ uint8_t splice_type;
+ uint64_t dts_next_au;
+};
+
+/**
+ * Extract the PID from a transport packet.
+ *
+ * @param pkt The packet.
+ * @return The PID.
+ */
+static inline int transport_packet_pid(struct transport_packet *pkt)
+{
+ return (pkt->pid_hi << 8) | (pkt->pid_lo);
+}
+
+/**
+ * Process a buffer into a transport packet.
+ *
+ * @param buf Raw buffer. Note, this function assumes there are 188 bytes available.
+ * @return transport_packet pointer, or NULL on error.
+ */
+static inline struct transport_packet *transport_packet_init(unsigned char *buf)
+{
+ struct transport_packet *pkt = (struct transport_packet*) buf;
+
+ if (pkt->sync_byte != TRANSPORT_PACKET_SYNC)
+ return NULL;
+
+ if (transport_packet_pid(pkt) >= TRANSPORT_MAX_PIDS)
+ return NULL;
+
+ return pkt;
+}
+
+/**
+ * Check the continuity counter for a packet in a PID stream.
+ *
+ * @param pkt transport_packet to check.
+ * @param discontinuity_indicator Set to 1 if the packet's discontinuity_indicator flag is set.
+ * @param cstate Pointer to a single 8 bit character, used to store state for validating
+ * continuity. To initialise the state, simply set it to 0 before the first call.
+ * @return 0 if the continuity was correct, or nonzero on error. cstate will not be updated on error,
+ * it is up to the caller to clear it to accept the next packet.
+ */
+extern int transport_packet_continuity_check(struct transport_packet *pkt,
+ int discontinuity_indicator, unsigned char *cstate);
+
+/**
+ * Extract selected fields from a transport packet.
+ *
+ * @param pkt The packet.
+ * @param out Destination structure for values.
+ * @param extract Orred bitmask of enum transport_value - tells it what fields
+ * to extract if they are available.
+ * @return < 0 => error. Otherwise, an orred bitmask of enum transport_value
+ * telling you what fields were successfully extracted.
+ */
+extern int transport_packet_values_extract(struct transport_packet *pkt,
+ struct transport_values *out,
+ enum transport_value extract);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/lib/libucsi/types.h b/lib/libucsi/types.h
new file mode 100644
index 0000000..b01d79a
--- /dev/null
+++ b/lib/libucsi/types.h
@@ -0,0 +1,36 @@
+/*
+ * section and descriptor parser
+ *
+ * Copyright (C) 2005 Andrew de Quincey (adq_dvb@lidskialf.net)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _UCSI_TYPES_H
+#define _UCSI_TYPES_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef uint8_t iso639lang_t[3];
+typedef uint8_t iso639country_t[3];
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libdvb2/README b/libdvb2/README
deleted file mode 100644
index 049acd6..0000000
--- a/libdvb2/README
+++ /dev/null
@@ -1,23 +0,0 @@
-Late in 2003 the idea to create a simple DVB library from the code snippets
-in the test/utility programs was discussed on the linux-dvb mailing list.
-Hopefully someone will invest some time in this project to turn the idea into
-reality...
-
-Here is an outline of what libdvb2 should be, according to my recollection:
-(For first hand information search the linux-dvb list archives for "libdvb2".)
-
-- C
-- small: The goal is to make the library usable in *any* DVB project, which
- is easier if the library sticks to the basics. Advanced stuff can be
- done in a second library. What exacty "basic" and "advanced" means
- is subject of discussion, but I want avoid to impose a certain programming
- model (e.g. multi-threaded vw. event-loop) on users of the library.
-- a prime target is to establish a standard DVB config and service list
- format, to make this sharable between different applications
-- LGPL
-
-About the name: There already is a libdvb written by the Metzler Bros.,
-but the main drawback is that it is written in C++ and thus rejected
-by many projects.
-
-Johannes Stezenbach <js@convergence.de>