summaryrefslogtreecommitdiffstats
path: root/kaffeine/src/input
diff options
context:
space:
mode:
Diffstat (limited to 'kaffeine/src/input')
-rw-r--r--kaffeine/src/input/disc/Makefile.am2
-rw-r--r--kaffeine/src/input/disc/paranoia.cpp16
-rw-r--r--kaffeine/src/input/disc/paranoia.h8
-rw-r--r--kaffeine/src/input/disc/plugins/oggvorbis/Makefile.am2
-rw-r--r--kaffeine/src/input/dvb/Makefile.am2
-rw-r--r--kaffeine/src/input/dvb/camdialog.ui149
-rw-r--r--kaffeine/src/input/dvb/cammenudialog.ui67
-rw-r--r--kaffeine/src/input/dvb/channeldesc.cpp4
-rw-r--r--kaffeine/src/input/dvb/channeldesc.h2
-rw-r--r--kaffeine/src/input/dvb/channeleditor.cpp62
-rw-r--r--kaffeine/src/input/dvb/channeleditor.h3
-rw-r--r--kaffeine/src/input/dvb/channeleditorui.ui86
-rw-r--r--kaffeine/src/input/dvb/dvbcam.cpp1252
-rw-r--r--kaffeine/src/input/dvb/dvbcam.h175
-rw-r--r--kaffeine/src/input/dvb/dvbconfig.cpp174
-rw-r--r--kaffeine/src/input/dvb/dvbconfig.h69
-rw-r--r--kaffeine/src/input/dvb/dvbout.cpp57
-rw-r--r--kaffeine/src/input/dvb/dvbout.h3
-rw-r--r--kaffeine/src/input/dvb/dvbpanel.cpp129
-rw-r--r--kaffeine/src/input/dvb/dvbpanel.h3
-rw-r--r--kaffeine/src/input/dvb/dvbsi.cpp305
-rw-r--r--kaffeine/src/input/dvb/dvbsi.h9
-rw-r--r--kaffeine/src/input/dvb/dvbstream.cpp423
-rw-r--r--kaffeine/src/input/dvb/dvbstream.h9
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am5
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.c50
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.h55
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c12
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c580
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h233
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c11
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h10
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.c46
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.h46
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am5
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c90
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h16
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c242
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h47
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c247
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h48
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c1030
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h126
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c212
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h45
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c387
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h68
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c217
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h52
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c899
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h113
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c2397
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h307
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c451
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h67
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c447
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h79
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h24
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c174
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h39
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c23
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h59
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h37
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c1785
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h96
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.c54
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.h102
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_hlci.c216
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_llci.c437
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c2250
-rw-r--r--kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h85
-rw-r--r--kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/Makefile.am8
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/Makefile.am17
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/ac3_descriptor.h112
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/atsc_text.c743
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/caption_service_descriptor.h137
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/component_name_descriptor.h92
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/content_advisory_descriptor.h235
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.c77
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.h228
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_arriving_request_descriptor.h107
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_departing_request_descriptor.h108
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.c109
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.h327
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.c96
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.h380
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h30
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.c71
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.h191
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.c42
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.h91
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/extended_channel_name_descriptor.h92
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/genre_descriptor.h82
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.c76
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.h215
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/rc_descriptor.h83
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.c108
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.h379
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/section.h65
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/service_location_descriptor.h141
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.c42
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.h105
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/stuffing_descriptor.h82
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/time_shifted_service_descriptor.h136
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.c81
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.h227
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/types.c71
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/atsc/types.h227
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/crc32.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h8
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h17
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h131
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h38
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c10
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c7
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h87
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h87
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h73
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h14
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/mpe_fec_section.h73
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c5
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h3
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/section.h1
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h9
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c5
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_address_descriptor.h116
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_slash_descriptor.h116
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_source_slash_descriptor.h118
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_address_descriptor.h116
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_slash_descriptor.h116
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h118
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/time_slice_fec_identifier_descriptor.h94
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c6
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/types.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/datagram_section.h81
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c1
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h22
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h12
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h4
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c3
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h2
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/section.h68
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/section_buf.h7
-rw-r--r--kaffeine/src/input/dvb/lib/libucsi/transport_packet.h2
-rw-r--r--kaffeine/src/input/dvb/plugins/epg/kaffeinedvbsection.cpp3
-rw-r--r--kaffeine/src/input/dvb/scandialog.cpp58
-rw-r--r--kaffeine/src/input/dvb/scandialogui.ui376
-rw-r--r--kaffeine/src/input/dvb/ts2rtp.cpp7
200 files changed, 16876 insertions, 7763 deletions
diff --git a/kaffeine/src/input/disc/Makefile.am b/kaffeine/src/input/disc/Makefile.am
index b9827cc..fe91515 100644
--- a/kaffeine/src/input/disc/Makefile.am
+++ b/kaffeine/src/input/disc/Makefile.am
@@ -28,7 +28,7 @@ libkaffeinedisc_la_LDFLAGS = $(KDE_RPATH) \
libkaffeinedisc_la_LIBADD = $(top_builddir)/kaffeine/src/input/libkaffeineinput.la \
$(top_builddir)/kaffeine/src/player-parts/kaffeine-part/libkaffeinepart.la \
$(top_builddir)/kaffeine/src/input/disc/plugins/libkaffeineaudioencoder.la \
- -lcdda_interface -lcdda_paranoia
+ -lcdio_cdda -lcdio_paranoia
# this is where the XML-GUI resource file goes
shellrcdir = $(kde_datadir)/kaffeine
diff --git a/kaffeine/src/input/disc/paranoia.cpp b/kaffeine/src/input/disc/paranoia.cpp
index 60e2092..fad1729 100644
--- a/kaffeine/src/input/disc/paranoia.cpp
+++ b/kaffeine/src/input/disc/paranoia.cpp
@@ -120,7 +120,7 @@ KiloConfig::~KiloConfig()
{
}
-void paranoiaCallback( long, int )
+void paranoiaCallback( long int, paranoia_cb_mode_t )
{
}
@@ -396,7 +396,7 @@ void Paranoia::run()
curpos = currentSector;
endpos = endOfTrack;
if ( normalize ) {
- len = CD_FRAMESIZE_RAW;
+ len = CDIO_CD_FRAMESIZE_RAW;
fn.open( IO_ReadWrite | IO_Truncate );
do {
buf = paranoia_read_limited( p, paranoiaCallback, 3 );
@@ -419,7 +419,7 @@ void Paranoia::run()
while ( curpos<endpos && len!=0 );
factor = 32767.0/max;
- buf = new signed short[CD_FRAMESIZE_RAW];
+ buf = new signed short[CDIO_CD_FRAMESIZE_RAW];
fn.at( 0 );
f.open( IO_ReadWrite | IO_Truncate );
currentEncoder->start( encodingList[i].remove(0,3), encodingList[0], encodingList[1], encodingList[i].left(2) );
@@ -428,7 +428,7 @@ void Paranoia::run()
f.writeBlock( encoded, len );
do {
- len = fn.readBlock( (char*)buf, CD_FRAMESIZE_RAW );
+ len = fn.readBlock( (char*)buf, CDIO_CD_FRAMESIZE_RAW );
if ( len>0 ) {
if ( max<32760 )
for ( n=0; n<len/2; ++n )
@@ -455,7 +455,7 @@ void Paranoia::run()
encoded = currentEncoder->getHeader( len );
if ( encoded )
f.writeBlock( encoded, len );
- len = CD_FRAMESIZE_RAW;
+ len = CDIO_CD_FRAMESIZE_RAW;
do {
buf = paranoia_read_limited( p, paranoiaCallback, 3 );
if ( Q_BYTE_ORDER == Q_BIG_ENDIAN ) {
@@ -514,7 +514,7 @@ QString Paranoia::trackSize( int t )
QString s, c;
long total;
- total = CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) );
+ total = CDIO_CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) );
if ( total>(1048576 ) ) s = c.setNum(total/1048576.0, 'f', 2)+" "+i18n("MB");
else if ( total>1024 ) s = c.setNum(total/1024.0, 'f', 2)+" "+i18n("KB");
else s = c.setNum(total*1.0, 'f', 2)+" "+i18n("Bytes");
@@ -532,8 +532,8 @@ QString Paranoia::trackTime( int t )
long total, time;
int m, s;
- if ( t<0 ) total = CD_FRAMESIZE_RAW * (cdda_disc_lastsector( d )-cdda_disc_firstsector( d ) );
- else total = CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) );
+ if ( t<0 ) total = CDIO_CD_FRAMESIZE_RAW * (cdda_disc_lastsector( d )-cdda_disc_firstsector( d ) );
+ else total = CDIO_CD_FRAMESIZE_RAW * (cdda_track_lastsector( d, t+1 )-cdda_track_firstsector( d, t+1 ) );
time = (8 * total) / (44100 * 2 * 16);
m = time/60;
s = time%60;
diff --git a/kaffeine/src/input/disc/paranoia.h b/kaffeine/src/input/disc/paranoia.h
index 4864b06..ae269d4 100644
--- a/kaffeine/src/input/disc/paranoia.h
+++ b/kaffeine/src/input/disc/paranoia.h
@@ -32,8 +32,8 @@
extern "C"
{
-#include <cdda_interface.h>
-#include <cdda_paranoia.h>
+#include <cdio/cdda.h>
+#include <cdio/paranoia.h>
}
class KiloConfig : public ParanoiaSettings
@@ -91,8 +91,8 @@ private:
bool setPath( QString &path, const QString &artist, const QString &album );
long nTracks;
- cdrom_drive *d;
- cdrom_paranoia *p;
+ cdrom_drive_t *d;
+ cdrom_paranoia_t *p;
long currentSector, endOfTrack;
bool isRunning;
QStringList encodingList;
diff --git a/kaffeine/src/input/disc/plugins/oggvorbis/Makefile.am b/kaffeine/src/input/disc/plugins/oggvorbis/Makefile.am
index 91b63c1..7ac8f45 100644
--- a/kaffeine/src/input/disc/plugins/oggvorbis/Makefile.am
+++ b/kaffeine/src/input/disc/plugins/oggvorbis/Makefile.am
@@ -10,7 +10,7 @@ noinst_HEADERS = koggenc.h
libkaffeineoggvorbis_la_SOURCES = koggenc.cpp oggconfig.ui
libkaffeineoggvorbis_la_LIBADD = ../libkaffeineaudioencoder.la $(LIB_OGGVORBIS)
-libkaffeineoggvorbis_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) $(LIB_QT) -lDCOP $(KDE_PLUGIN) $(LIB_KPARTS) $(LIB_KDECORE) $(LIB_KDEUI) $(LIB_KIO) -avoid-version -no-undefined
+libkaffeineoggvorbis_la_LDFLAGS = -module $(KDE_PLUGIN) $(all_libraries) -avoid-version -no-undefined
# this is where the desktop file will go
partdesktopdir = $(kde_servicesdir)
diff --git a/kaffeine/src/input/dvb/Makefile.am b/kaffeine/src/input/dvb/Makefile.am
index 7b6c866..d5b1035 100644
--- a/kaffeine/src/input/dvb/Makefile.am
+++ b/kaffeine/src/input/dvb/Makefile.am
@@ -30,6 +30,8 @@ libkaffeinedvb_la_SOURCES = audioeditor.cpp \
dvbsection.h \
dvbsi.cpp \
dvbsi.h \
+ camdialog.ui \
+ cammenudialog.ui \
dvbstream.cpp \
dvbstream.h \
gdvb.h \
diff --git a/kaffeine/src/input/dvb/camdialog.ui b/kaffeine/src/input/dvb/camdialog.ui
new file mode 100644
index 0000000..b1c3032
--- /dev/null
+++ b/kaffeine/src/input/dvb/camdialog.ui
@@ -0,0 +1,149 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>CamDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>CamDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>330</width>
+ <height>198</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>CAM settings</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout5</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel9</cstring>
+ </property>
+ <property name="text">
+ <string>Maximum Concurrent Services:</string>
+ </property>
+ </widget>
+ <widget class="QSpinBox">
+ <property name="name">
+ <cstring>maxServiceSpin</cstring>
+ </property>
+ <property name="minValue">
+ <number>1</number>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox1</cstring>
+ </property>
+ <property name="title">
+ <string></string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Application Type:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>Manufacturer Code:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>Menu String:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="2" column="1">
+ <property name="name">
+ <cstring>manuCodeLab</cstring>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="1">
+ <property name="name">
+ <cstring>appManuLab</cstring>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>Application Manufacturer:</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="3" column="1">
+ <property name="name">
+ <cstring>menuStringLab</cstring>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ <widget class="QLabel" row="0" column="1">
+ <property name="name">
+ <cstring>appTypeLab</cstring>
+ </property>
+ <property name="text">
+ <string>_</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>camMenuBtn</cstring>
+ </property>
+ <property name="text">
+ <string>CAM Menu</string>
+ </property>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>maxServiceSpin</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kaffeine/src/input/dvb/cammenudialog.ui b/kaffeine/src/input/dvb/cammenudialog.ui
new file mode 100644
index 0000000..6eebfa4
--- /dev/null
+++ b/kaffeine/src/input/dvb/cammenudialog.ui
@@ -0,0 +1,67 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>CamMenuDialog</class>
+<widget class="QDialog">
+ <property name="name">
+ <cstring>CamMenuDialog</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>317</width>
+ <height>345</height>
+ </rect>
+ </property>
+ <property name="caption">
+ <string>CAM Menu</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout7</cstring>
+ </property>
+ <vbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QTextBrowser">
+ <property name="name">
+ <cstring>menuText</cstring>
+ </property>
+ </widget>
+ <widget class="QLayoutWidget">
+ <property name="name">
+ <cstring>layout6</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>Your choice (enter to validate):</string>
+ </property>
+ </widget>
+ <widget class="QLineEdit">
+ <property name="name">
+ <cstring>inputLine</cstring>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </vbox>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>inputLine</tabstop>
+ <tabstop>menuText</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kaffeine/src/input/dvb/channeldesc.cpp b/kaffeine/src/input/dvb/channeldesc.cpp
index 5ab4acf..7d96e48 100644
--- a/kaffeine/src/input/dvb/channeldesc.cpp
+++ b/kaffeine/src/input/dvb/channeldesc.cpp
@@ -115,6 +115,8 @@ Transponder::Transponder()
coderateH=FEC_AUTO;
bandwidth=BANDWIDTH_AUTO;
snr = 0;
+ rolloff = ROLLOFF_AUTO;
+ S2 = 0;
}
Transponder::Transponder( const Transponder &trans )
@@ -134,6 +136,8 @@ Transponder::Transponder( const Transponder &trans )
coderateL=trans.coderateL;
coderateH=trans.coderateH;
bandwidth=trans.bandwidth;
+ rolloff = trans.rolloff;
+ S2 = trans.S2;
}
bool Transponder::sameAs( Transponder *trans )
diff --git a/kaffeine/src/input/dvb/channeldesc.h b/kaffeine/src/input/dvb/channeldesc.h
index f4bc1ab..ef07011 100644
--- a/kaffeine/src/input/dvb/channeldesc.h
+++ b/kaffeine/src/input/dvb/channeldesc.h
@@ -101,6 +101,8 @@ public:
fe_code_rate_t coderateH;
fe_bandwidth_t bandwidth;
int snr;
+ fe_rolloff_t rolloff;
+ char S2;
};
class ChannelDesc
diff --git a/kaffeine/src/input/dvb/channeleditor.cpp b/kaffeine/src/input/dvb/channeleditor.cpp
index 6b04fe4..18ea8ce 100644
--- a/kaffeine/src/input/dvb/channeleditor.cpp
+++ b/kaffeine/src/input/dvb/channeleditor.cpp
@@ -143,6 +143,9 @@ void ChannelEditor::accept()
else channel->tp.pol = 'h';
channel->tp.coderateH = (fe_code_rate_t)(FEC_NONE+coderateHComb->currentItem());
channel->tp.inversion = (fe_spectral_inversion_t)(INVERSION_OFF+inversionComb->currentItem());
+ channel->tp.modulation = (fe_modulation_t)(QPSK+modulationComb->currentItem());
+ channel->tp.S2 = stypeComb->currentItem();
+ channel->tp.rolloff = (fe_rolloff_t)(ROLLOFF_35+rolloffComb->currentItem() );
}
else if ( channel->tp.type==FE_QAM ) {
channel->tp.freq = freqSpin->value();
@@ -165,13 +168,7 @@ void ChannelEditor::accept()
else {
channel->tp.freq = freqSpin->value();
channel->tp.inversion = (fe_spectral_inversion_t)(INVERSION_OFF+inversionComb->currentItem());
- switch (modulationComb->currentItem()) {
- case 0: channel->tp.modulation = QAM_64; break;
- case 1: channel->tp.modulation = QAM_256; break;
- case 2: channel->tp.modulation = VSB_8; break;
- case 3: channel->tp.modulation = VSB_16; break;
- default: channel->tp.modulation = QAM_AUTO; break;
- }
+ channel->tp.modulation = (fe_modulation_t)(QPSK+modulationComb->currentItem());
}
done( Accepted );
@@ -187,10 +184,15 @@ void ChannelEditor::initS()
inversionComb->setCurrentItem( INVERSION_OFF+channel->tp.inversion );
coderateHComb->insertStringList( coderateList() );
coderateHComb->setCurrentItem( FEC_NONE+channel->tp.coderateH );
+ modulationComb->insertStringList( modulationList() );
+ modulationComb->setCurrentItem( QPSK+channel->tp.modulation );
+ stypeComb->insertStringList( stypeList() );
+ stypeComb->setCurrentItem( channel->tp.S2 );
+ rolloffComb->insertStringList( rolloffList() );
+ rolloffComb->setCurrentItem( ROLLOFF_35+channel->tp.rolloff );
transmissionComb->setEnabled( false );
coderateLComb->setEnabled( false );
bandwidthComb->setEnabled( false );
- modulationComb->setEnabled( false );
hierarchyComb->setEnabled( false );
guardComb->setEnabled( false );
}
@@ -211,6 +213,8 @@ void ChannelEditor::initC()
bandwidthComb->setEnabled( false );
hierarchyComb->setEnabled( false );
guardComb->setEnabled( false );
+ stypeComb->setEnabled( false );
+ rolloffComb->setEnabled( false );
}
void ChannelEditor::initT()
@@ -234,6 +238,8 @@ void ChannelEditor::initT()
guardComb->setCurrentItem( GUARD_INTERVAL_1_32+channel->tp.guard );
srSpin->setEnabled( false );
polGroup->setEnabled( false );
+ stypeComb->setEnabled( false );
+ rolloffComb->setEnabled( false );
}
void ChannelEditor::initA()
@@ -241,14 +247,8 @@ void ChannelEditor::initA()
freqSpin->setValue( channel->tp.freq );
inversionComb->insertStringList( inversionList() );
inversionComb->setCurrentItem( INVERSION_OFF+channel->tp.inversion );
- modulationComb->insertStringList( modulationListAtsc() );
- switch (channel->tp.modulation) {
- case QAM_64: modulationComb->setCurrentItem(0); break;
- case QAM_256: modulationComb->setCurrentItem(1); break;
- case VSB_8: modulationComb->setCurrentItem(2); break;
- case VSB_16: modulationComb->setCurrentItem(3); break;
- default: modulationComb->setCurrentItem(4); break;
- }
+ modulationComb->insertStringList( modulationList() );
+ modulationComb->setCurrentItem( QPSK+channel->tp.modulation );
srSpin->setEnabled( false );
polGroup->setEnabled( false );
transmissionComb->setEnabled( false );
@@ -257,6 +257,8 @@ void ChannelEditor::initA()
bandwidthComb->setEnabled( false );
hierarchyComb->setEnabled( false );
guardComb->setEnabled( false );
+ stypeComb->setEnabled( false );
+ rolloffComb->setEnabled( false );
}
QStringList ChannelEditor::inversionList()
@@ -271,7 +273,7 @@ QStringList ChannelEditor::coderateList()
{
QStringList list;
- list<<"NONE"<<"1/2"<<"2/3"<<"3/4"<<"4/5"<<"5/6"<<"6/7"<<"7/8"<<"8/9"<<"AUTO";
+ list<<"NONE"<<"1/2"<<"2/3"<<"3/4"<<"4/5"<<"5/6"<<"6/7"<<"7/8"<<"8/9"<<"AUTO"<<"3/5"<<"9/10";
return list;
}
@@ -279,15 +281,7 @@ QStringList ChannelEditor::modulationList()
{
QStringList list;
- list<<"QPSK"<<"QAM 16"<<"QAM 32"<<"QAM 64"<<"QAM 128"<<"QAM 256"<<"AUTO";
- return list;
-}
-
-QStringList ChannelEditor::modulationListAtsc()
-{
- QStringList list;
-
- list<<"QAM 64"<<"QAM 256"<<"VSB 8"<<"VSB 16"<<"AUTO";
+ list<<"QPSK"<<"QAM 16"<<"QAM 32"<<"QAM 64"<<"QAM 128"<<"QAM 256"<<"AUTO"<<"VSB-8"<<"VSB-16"<<"8PSK"<<"16APSK"<<"DQPSK";
return list;
}
@@ -323,6 +317,22 @@ QStringList ChannelEditor::guardList()
return list;
}
+QStringList ChannelEditor::stypeList()
+{
+ QStringList list;
+
+ list<<"DVB-S"<<"DVB-S2";
+ return list;
+}
+
+QStringList ChannelEditor::rolloffList()
+{
+ QStringList list;
+
+ list<<"35"<<"20"<<"25"<<"AUTO";
+ return list;
+}
+
ChannelEditor::~ChannelEditor()
{
}
diff --git a/kaffeine/src/input/dvb/channeleditor.h b/kaffeine/src/input/dvb/channeleditor.h
index 6a3b3f8..586b9a3 100644
--- a/kaffeine/src/input/dvb/channeleditor.h
+++ b/kaffeine/src/input/dvb/channeleditor.h
@@ -53,11 +53,12 @@ private:
QStringList inversionList();
QStringList coderateList();
QStringList modulationList();
- QStringList modulationListAtsc();
QStringList transmissionList();
QStringList bandwidthList();
QStringList hierarchyList();
QStringList guardList();
+ QStringList stypeList();
+ QStringList rolloffList();
ChannelDesc *channel;
QPtrList<ChannelDesc> *chandesc;
diff --git a/kaffeine/src/input/dvb/channeleditorui.ui b/kaffeine/src/input/dvb/channeleditorui.ui
index 5b75f18..09bdad1 100644
--- a/kaffeine/src/input/dvb/channeleditorui.ui
+++ b/kaffeine/src/input/dvb/channeleditorui.ui
@@ -9,7 +9,7 @@
<x>0</x>
<y>0</y>
<width>477</width>
- <height>533</height>
+ <height>541</height>
</rect>
</property>
<property name="caption">
@@ -19,7 +19,7 @@
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="Line" row="1" column="0">
+ <widget class="Line" row="0" column="1">
<property name="name">
<cstring>line2</cstring>
</property>
@@ -35,7 +35,7 @@
</widget>
<widget class="QLayoutWidget" row="0" column="0">
<property name="name">
- <cstring>layout9</cstring>
+ <cstring>layout7</cstring>
</property>
<vbox>
<property name="name">
@@ -432,22 +432,6 @@
<cstring>transmissionComb</cstring>
</property>
</widget>
- <widget class="QLabel" row="3" column="0">
- <property name="name">
- <cstring>textLabel11</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>4</hsizetype>
- <vsizetype>5</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Bandwidth:</string>
- </property>
- </widget>
<widget class="QLabel" row="2" column="0">
<property name="name">
<cstring>textLabel10</cstring>
@@ -480,11 +464,6 @@
<string>Transmission:</string>
</property>
</widget>
- <widget class="QComboBox" row="3" column="1">
- <property name="name">
- <cstring>bandwidthComb</cstring>
- </property>
- </widget>
<widget class="QComboBox" row="2" column="1">
<property name="name">
<cstring>coderateHComb</cstring>
@@ -511,11 +490,6 @@
<string>FEC low:</string>
</property>
</widget>
- <widget class="QComboBox" row="3" column="3">
- <property name="name">
- <cstring>guardComb</cstring>
- </property>
- </widget>
<widget class="QLabel" row="3" column="2">
<property name="name">
<cstring>textLabel7</cstring>
@@ -595,6 +569,58 @@
<string>Inversion:</string>
</property>
</widget>
+ <widget class="QLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel11</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Bandwidth:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="3" column="1">
+ <property name="name">
+ <cstring>bandwidthComb</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel1_3</cstring>
+ </property>
+ <property name="text">
+ <string>Type:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="4" column="1">
+ <property name="name">
+ <cstring>stypeComb</cstring>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="4" column="3">
+ <property name="name">
+ <cstring>rolloffComb</cstring>
+ </property>
+ </widget>
+ <widget class="QLabel" row="4" column="2">
+ <property name="name">
+ <cstring>textLabel2_4</cstring>
+ </property>
+ <property name="text">
+ <string>Roll off:</string>
+ </property>
+ </widget>
+ <widget class="QComboBox" row="3" column="3">
+ <property name="name">
+ <cstring>guardComb</cstring>
+ </property>
+ </widget>
</grid>
</widget>
<spacer>
@@ -610,7 +636,7 @@
<property name="sizeHint">
<size>
<width>20</width>
- <height>98</height>
+ <height>166</height>
</size>
</property>
</spacer>
diff --git a/kaffeine/src/input/dvb/dvbcam.cpp b/kaffeine/src/input/dvb/dvbcam.cpp
index 1cb5b86..e525f6d 100644
--- a/kaffeine/src/input/dvb/dvbcam.cpp
+++ b/kaffeine/src/input/dvb/dvbcam.cpp
@@ -1,6 +1,7 @@
/*
* dvbcam.cpp
*
+ * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
* Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
*
* code based on ca_zap (LGPL)
@@ -29,173 +30,48 @@
#include <sys/poll.h>
#include <linux/dvb/ca.h>
-#include <libdvbapi/dvbca.h>
-#include <libdvbapi/dvbdemux.h>
-#include <libdvben50221/en50221_app_ai.h>
-#include <libdvben50221/en50221_app_ca.h>
-#include <libdvben50221/en50221_app_rm.h>
-#include <libdvben50221/en50221_app_tags.h>
-#include <libdvben50221/en50221_session.h>
-#include <libucsi/mpeg/section.h>
-
+#include <qapplication.h>
#include <qthread.h>
#include <qstring.h>
+#include <qspinbox.h>
+#include <qlabel.h>
+#include <qtextbrowser.h>
+#include <qlineedit.h>
+#include <qpushbutton.h>
#include "dvbcam.h"
-class DvbCamCamHandler
-{
-public:
- virtual ~DvbCamCamHandler();
-
- bool init();
-
- virtual void poll() = 0;
- virtual bool registerCam(int ca_fd, uint8_t slot) = 0;
-
- bool sendPmt(char *pmt_buffer, int size);
-
-protected:
- DvbCamCamHandler();
-
- static int infoCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids);
-
- virtual bool sub_init() = 0;
-
- void *AiResource;
- void *CaResource;
- en50221_app_send_functions SendFuncs;
-
- volatile int SessionNumber;
-};
-
-class DvbCamCamThread : protected QThread
-{
-public:
- DvbCamCamThread(int adapter, int ca_device, int ci_type);
- ~DvbCamCamThread();
-
- void start();
- void stop();
- void wait();
-
- bool processPmt(int demux_fd);
-
-private:
- void run();
-
- int Adapter;
- int CaDevice;
- int ciType;
-
- DvbCamCamHandler *CamHandler;
-
- char PmtBuffer[4096]; // we imply that processPmt is only once called
-
- volatile int PmtSize; // PmtSize <= 0 means PmtBuffer invalid
- volatile bool Stopped;
-};
-
-class DvbCamPmtThread : protected QThread
-{
-public:
- DvbCamPmtThread(DvbCamCamThread *cam_thread, int adapter, int demux_device, int service_id);
- ~DvbCamPmtThread();
-
- void start();
- void stop();
- void wait();
-
-private:
- int createSectionFilter(uint16_t pid, uint8_t table_id);
- int processPat(int demux_fd);
- void run();
+#define TIMER_EVENT_MMI_OPEN 500
+#define TIMER_EVENT_MMI_CLOSE 501
+#define TIMER_EVENT_CAM_READY 502
- DvbCamCamThread *CamThread;
- int Adapter;
- int DemuxDevice;
- int ServiceId;
- volatile bool Stopped;
-};
-class DvbCamCamHandlerLLCI : public DvbCamCamHandler
-{
-public:
- DvbCamCamHandlerLLCI();
- ~DvbCamCamHandlerLLCI();
-
-private:
- struct SlResource
- {
- en50221_app_public_resource_id resid;
- uint32_t binary_resource_id;
- en50221_sl_resource_callback callback;
- void *arg;
- };
-
- 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_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);
-
- void poll();
- bool registerCam(int ca_fd, uint8_t slot);
- bool sub_init();
-
- void *RmResource;
- void *SessionLayer;
- void *TransportLayer;
-
- SlResource Resources[3];
-};
-
-class DvbCamCamHandlerHLCI : public DvbCamCamHandler
-{
-public:
- DvbCamCamHandlerHLCI();
- ~DvbCamCamHandlerHLCI();
-
-private:
- 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, iovec *vector, int iov_count);
-
- void poll();
- bool registerCam(int ca_fd, uint8_t slot);
- bool sub_init();
-};
-
-// class DvbCam
-
-DvbCam::DvbCam(int adapter, int ca_device, int demux_device, int ci_type)
+DvbCam::DvbCam(int adapter, int ca_device, int demux_device, int ci_type, int maxService)
{
Adapter = adapter;
CaDevice = ca_device;
DemuxDevice = demux_device;
ciType = ci_type;
+ CamMaxService = maxService;
+ fprintf(stderr, "DvbCam: CamMaxService = %d\n", CamMaxService);
- isRunning = false;
+ stdcam = NULL;
+ menuDialog = NULL;
- CamThread = NULL;
- PmtThread = NULL;
-
- // at that time, we do reset in cam_thread
- /*if ( ciType!=CA_CI ) { //do not reset HLCI
- int ca_fd = dvbca_open( Adapter, CaDevice );
- if(ca_fd < 0) // should not happen
- fprintf(stderr, "CamThread: [error] opening ca device failed\n");
- else {
- if(dvbca_reset(ca_fd, 0))
- fprintf(stderr, "CamThread: [error] resetting cam slot failed\n");
- close(ca_fd);
- }
- }*/
+ sidList.setAutoDelete( true );
+
+ isRunning = true;
+ start();
}
DvbCam::~DvbCam()
{
- stop();
+ isRunning = false;
+ wait();
+ sidMutex.lock();
+ sidList.clear();
+ sidMutex.unlock();
}
int DvbCam::probe( int adapter, int ca_device )
@@ -251,676 +127,786 @@ int DvbCam::probe( int adapter, int ca_device )
return -1;
}
-void DvbCam::restart(int service_id)
+bool DvbCam::canPlay( ChannelDesc *chan )
{
- stop();
-
- isRunning = true;
- sid = service_id;
-
- CamThread = new DvbCamCamThread(Adapter, CaDevice, ciType);
- CamThread->start();
+ int i, n=0;
- PmtThread = new DvbCamPmtThread(CamThread, Adapter, DemuxDevice, service_id);
- PmtThread->start();
-}
-
-void DvbCam::stop()
-{
- if(PmtThread != NULL) {
- PmtThread->stop();
- }
- if(CamThread != NULL) {
- CamThread->stop();
- }
- if(PmtThread != NULL) {
- PmtThread->wait();
- delete PmtThread;
- PmtThread = NULL;
- }
- if(CamThread != NULL) {
- CamThread->wait();
- delete CamThread; // be careful about deletion: PmtThread uses CamThread internally
- CamThread = NULL;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getState()<CamService::Remove )
+ n++;
+ if ( sidList.at(i)->getChannel().name==chan->name )
+ return true;
}
- isRunning = false;
-}
-
-// class DvbCamCamThread
-
-DvbCamCamThread::DvbCamCamThread(int adapter, int ca_device, int ci_type)
-{
- Adapter = adapter;
- CaDevice = ca_device;
- ciType = ci_type;
-
- CamHandler = NULL;
-}
-
-DvbCamCamThread::~DvbCamCamThread()
-{
- wait(); // should never be necessary
+ return ( n<CamMaxService );
}
-void DvbCamCamThread::start()
+void DvbCam::startService( ChannelDesc *chan )
{
- PmtSize = 0;
- Stopped = false;
- QThread::start();
-}
-
-void DvbCamCamThread::stop()
-{
- Stopped = true;
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getChannel().name==chan->name ) {
+ sidList.at(i)->restart();
+ return;
+ }
+ }
+ sidList.append( new CamService( Adapter, DemuxDevice, chan, CamMaxService ) );
}
-void DvbCamCamThread::wait()
+void DvbCam::stopService( ChannelDesc *chan )
{
- QThread::wait();
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getChannel().name==chan->name ) {
+ sidList.at(i)->setState( CamService::Remove );
+ return;
+ }
+ }
}
-bool DvbCamCamThread::processPmt(int demux_fd)
+void DvbCam::resendPmts()
{
- // read section
- char si_buf[4096];
- int size = read(demux_fd, si_buf, sizeof(si_buf));
- if(size <= 0) {
- return false;
- }
-
- // parse section
- section *parsed_section = section_codec(reinterpret_cast<unsigned char *> (si_buf), size);
- if(parsed_section == NULL) {
- return false;
- }
-
- // parse section_ext
- section_ext *parsed_section_ext = section_ext_decode(parsed_section, 1); // crc check on
- if(parsed_section_ext == NULL) {
- return false;
- }
-
- // parse pmt
- mpeg_pmt_section *parsed_pmt = mpeg_pmt_section_codec(parsed_section_ext);
- if(parsed_pmt == NULL) {
- return false;
- }
-
- // translate it into a cam pmt
- PmtSize = en50221_ca_format_pmt(parsed_pmt, reinterpret_cast<unsigned char *> (PmtBuffer), sizeof(PmtBuffer), 0, CA_LIST_MANAGEMENT_ONLY, CA_PMT_CMD_ID_OK_DESCRAMBLING);
- if(PmtSize <= 0) {
- return false;
+ int i;
+ QMutexLocker locker( &sidMutex );
+ for ( i=0; i<sidList.count(); ++i ) {
+ if ( sidList.at(i)->getState()==CamService::Added ) {
+ sidList.at(i)->setState( CamService::Ready );
+ }
}
-
- // the DvbCamCamThread will send it to the cam
- return true;
}
-void DvbCamCamThread::run()
+void DvbCam::run()
{
+ int i, reset_loop, query_loop, state_loop;
+ bool cam_ready = false;
+
fprintf(stderr, "CamThread: started\n");
int ca_fd = dvbca_open(Adapter, CaDevice);
- if(ca_fd < 0) {
- fprintf(stderr, "CamThread: [error] opening ca device failed\n");
+ if ( ca_fd<0 ) {
+ fprintf( stderr, "CamThread: [error] opening ca device failed\n" );
return;
}
- fprintf(stderr, "CamThread: just using the first cam slot\n");
+ //fprintf(stderr, "CamThread: just using the first cam slot\n");
- if ( ciType!=CA_CI ) { // do not reset HLCI
- if(dvbca_reset(ca_fd, 0)) {
- fprintf(stderr, "CamThread: [error] resetting cam slot failed\n");
- close(ca_fd);
- return;
+ reset_loop=0;
+ while ( isRunning && reset_loop++<6 && !cam_ready ) {
+ if ( ciType!=CA_CI ) { // do not reset HLCI
+ if ( dvbca_reset(ca_fd, 0) ) {
+ fprintf( stderr, "CamThread: [error] resetting cam slot failed\n" );
+ //close( ca_fd );
+ //ca_fd = -1;
+ //return;
+ usleep(1000000);
+ continue;
+ }
+ fprintf( stderr, "CamThread: reset cam slot\n" );
}
- }
- while(!Stopped) {
- bool cam_ready = false;
- switch(dvbca_get_cam_state(ca_fd, 0)) {
- case DVBCA_CAMSTATE_MISSING: {
- /*fprintf(stderr, "CamThread: [error] no cam detected\n");
- close(ca_fd);
- return; */ // FIXME: find a more reliable solution
- break;
- }
- case DVBCA_CAMSTATE_READY: {
- fprintf(stderr, "CamThread: cam 0 is ready\n");
- cam_ready = true;
- break;
- }
- case DVBCA_CAMSTATE_INITIALISING: {
- if ( ciType==CA_CI ) { // workaround needed for hlci
- fprintf(stderr, "CamThread: cam 0 is ready [hlci workaround]\n");
+ state_loop=0;
+ query_loop=0;
+ while ( isRunning && state_loop++<30 ) {
+ switch( dvbca_get_cam_state(ca_fd, 0) ) {
+ case DVBCA_CAMSTATE_MISSING: {
+ //fprintf(stderr, "CamThread: [error] no cam detected\n");
+ //close(ca_fd);
+ //return; // FIXME: find a more reliable solution
+ break;
+ }
+ case DVBCA_CAMSTATE_READY: {
+ fprintf( stderr, "CamThread: cam 0 is ready\n" );
cam_ready = true;
+ break;
+ }
+ case DVBCA_CAMSTATE_INITIALISING: {
+ fprintf( stderr, "CamThread: cam is initialising\n" );
+ if ( ciType==CA_CI ) { // workaround needed for hlci
+ fprintf(stderr, "CamThread: cam 0 is ready [hlci workaround]\n");
+ cam_ready = true;
+ }
+ break;
+ }
+ default: {
+ if ( ++query_loop>3 ) {
+ fprintf(stderr, "CamThread: [error] querying the cam state failed\n");
+ close(ca_fd);
+ ca_fd = -1;
+ return;
+ }
}
- break;
}
- default: {
- fprintf(stderr, "CamThread: [error] querying the cam state failed\n");
- close(ca_fd);
- return;
+ if(cam_ready) {
+ break;
}
+ usleep(100000); // 100 ms
}
- if(cam_ready) {
- break;
- }
- usleep(100000); // 100 ms
}
- if(!Stopped) {
+ if ( isRunning ) {
switch(dvbca_get_interface_type(ca_fd, 0)) {
case DVBCA_INTERFACE_LINK: {
fprintf(stderr, "CamThread: LLCI cam slot detected\n");
- CamHandler = new DvbCamCamHandlerLLCI();
break;
}
case DVBCA_INTERFACE_HLCI: {
fprintf(stderr, "CamThread: HLCI cam slot detected\n");
- CamHandler = new DvbCamCamHandlerHLCI();
break;
}
default: {
fprintf(stderr, "CamThread: [error] unknown cam slot type\n");
close(ca_fd);
+ ca_fd = -1;
return;
}
}
}
- if(!Stopped) {
- if(!CamHandler->init()) {
- fprintf(stderr, "CamThread: [error] cam slot initialization failed\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
- return;
- }
- }
+ close(ca_fd);
+ ca_fd = -1;
- if(!Stopped) {
- if(!CamHandler->registerCam(ca_fd, 0)) {
- fprintf(stderr, "CamThread: [error] registering cam 0 failed\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
+ if ( isRunning ) {
+ if ( !init() ) {
+ fprintf(stderr, "CamThread: [error] cam slot initialisation failed\n");
return;
}
}
+ fprintf(stderr, "CamThread: cam slot initialised\n");
- while(!Stopped) {
- CamHandler->poll();
- if(PmtSize > 0) {
- if(CamHandler->sendPmt(PmtBuffer, PmtSize)) {
- fprintf(stderr, "CamThread: pmt sent to cam\n");
- PmtSize = 0;
+ CamService *cs;
+ while ( isRunning ) {
+ if ( stdcam->stdcam->poll( stdcam->stdcam )!=EN50221_STDCAM_CAM_OK ) {
+ usleep( 100000 );
+ continue;
+ }
+ sidMutex.lock();
+ for ( i=0; i<sidList.count(); ++i ) {
+ cs = sidList.at(i);
+ if ( cs->getState()==CamService::Remove ) {
+ if ( sendPmt( cs->caPmt, cs->caPmtSize ) ) {
+ fprintf( stderr, "CamThread: %s removed from camlist\n", cs->getChannel().name.ascii() );
+ sidList.remove( cs );
+ --i;
+ }
+ else
+ fprintf( stderr, "CamThread: %s failed removing from camlist\n", cs->getChannel().name.ascii() );
+ stdcam->stdcam->poll( stdcam->stdcam );
+ usleep(100000);
+ }
+ else if ( cs->getState()==CamService::Destroy ) {
+ fprintf( stderr, "CamThread: %s service deleted\n", cs->getChannel().name.ascii() );
+ sidList.remove( cs );
+ --i;
}
}
+ for ( i=0; i<sidList.count(); ++i ) {
+ cs = sidList.at(i);
+ if ( cs->getState()==CamService::Ready ) {
+ if ( sendPmt( cs->caPmt, cs->caPmtSize ) ) {
+ cs->setState( CamService::Added );
+ fprintf( stderr, "CamThread: %s pmt sent to cam\n", cs->getChannel().name.ascii() );
+ }
+ else
+ fprintf( stderr, "CamThread: %s pmt failed sending to cam\n", cs->getChannel().name.ascii() );
+ stdcam->stdcam->poll( stdcam->stdcam );
+ usleep(100000);
+ }
+ }
+ sidMutex.unlock();
+ usleep( 10000 ); //sleep a bit
}
fprintf(stderr, "CamThread: stopping requested\n");
- delete CamHandler;
- CamHandler = NULL;
- close(ca_fd);
+ if ( stdcam ) {
+ if (stdcam->stdcam->destroy)
+ stdcam->stdcam->destroy(stdcam->stdcam, 1);
+ en50221_sl_destroy( SessionLayer );
+ en50221_tl_destroy( TransportLayer );
+ delete stdcam;
+ }
fprintf(stderr, "CamThread: stopped\n");
return;
}
-// class DvbCamPmtThread
-
-DvbCamPmtThread::DvbCamPmtThread(DvbCamCamThread *cam_thread, int adapter, int demux_device, int service_id)
+bool DvbCam::init()
{
- CamThread = cam_thread;
- Adapter = adapter;
- DemuxDevice = demux_device;
- ServiceId = service_id;
+ TransportLayer = en50221_tl_create(1, 16);
+ if ( TransportLayer==NULL ) {
+ fprintf(stderr, "Failed to create transport layer\n");
+ return false;
+ }
+ SessionLayer = en50221_sl_create(TransportLayer, 16);
+ if ( SessionLayer==NULL ) {
+ fprintf(stderr, "Failed to create session layer\n");
+ en50221_tl_destroy( TransportLayer );
+ return false;
+ }
+ en50221_stdcam *sc = en50221_stdcam_create( Adapter, 0, TransportLayer, SessionLayer );
+ if ( sc==NULL ) {
+ en50221_sl_destroy( SessionLayer );
+ en50221_tl_destroy( TransportLayer );
+ fprintf(stderr, "Failed to create stdcam\n");
+ return false;
+ }
+
+ stdcam = new StandardCam( sc, this );
+
+ // hook up the AI callbacks
+ if ( stdcam->stdcam->ai_resource ) {
+ en50221_app_ai_register_callback( stdcam->stdcam->ai_resource, aiCallback, stdcam );
+ }
+
+ // hook up the CA callbacks
+ if ( stdcam->stdcam->ca_resource ) {
+ en50221_app_ca_register_info_callback( stdcam->stdcam->ca_resource, infoCallback, stdcam );
+ }
+
+ // hook up the MMI callbacks
+ if ( stdcam->stdcam->mmi_resource ) {
+ en50221_app_mmi_register_close_callback( stdcam->stdcam->mmi_resource, mmi_close_callback, stdcam );
+ en50221_app_mmi_register_display_control_callback( stdcam->stdcam->mmi_resource, mmi_display_control_callback, stdcam );
+ en50221_app_mmi_register_enq_callback( stdcam->stdcam->mmi_resource, mmi_enq_callback, stdcam );
+ en50221_app_mmi_register_menu_callback( stdcam->stdcam->mmi_resource, mmi_menu_callback, stdcam );
+ en50221_app_mmi_register_list_callback( stdcam->stdcam->mmi_resource, mmi_menu_callback, stdcam );
+ } else {
+ fprintf(stderr, "CAM Menus are not supported by this interface hardware\n");
+ }
+
+ return true;
}
-DvbCamPmtThread::~DvbCamPmtThread()
+bool DvbCam::sendPmt( unsigned char *pmt_buffer, int size )
{
- wait(); // should never be necessary
+ if ( !stdcam )
+ return false;
+ if ( en50221_app_ca_pmt( stdcam->stdcam->ca_resource, stdcam->stdcam->ca_session_number, pmt_buffer, size) )
+ return false;
+
+ return true;
}
-void DvbCamPmtThread::start()
+int DvbCam::infoCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids)
{
- Stopped = false;
- QThread::start();
+ StandardCam *std = (StandardCam*)arg;
+ (void)slot_id;
+ (void)session_number;
+
+ fprintf(stderr, "CAM supports the following ca system ids:\n");
+ uint32_t i;
+ for ( i=0; i<ca_id_count; i++ ) {
+ fprintf( stderr, " 0x%04x\n", ca_ids[i]);
+ }
+
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_CAM_READY ) );
+
+ return 0;
}
-void DvbCamPmtThread::stop()
+int DvbCam::aiCallback(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)
{
- Stopped = true;
+ StandardCam *std = (StandardCam*)arg;
+ (void)slot_id;
+ (void)session_number;
+
+ fprintf(stderr, "CAM Application type: %02x\n", application_type);
+ std->dvbcam->setAppType( QString("0x%1").arg(application_type, 0, 16 ) );
+ fprintf(stderr, "CAM Application manufacturer: %04x\n", application_manufacturer);
+ std->dvbcam->setAppManu( QString("0x%1").arg(application_manufacturer, 0, 16 ) );
+ fprintf(stderr, "CAM Manufacturer code: %04x\n", manufacturer_code);
+ std->dvbcam->setManuCode( QString("0x%1").arg(manufacturer_code, 0, 16 ) );
+ fprintf(stderr, "CAM Menu string: %.*s\n", menu_string_length, menu_string);
+ QString s = (const char*)menu_string;
+ s.truncate( menu_string_length );
+ std->dvbcam->setMenuString( s );
+ return 0;
}
-void DvbCamPmtThread::wait()
+int DvbCam::mmi_close_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t delay)
{
- QThread::wait();
+ fprintf( stderr,"mmi_close_callback, delay=%d\n",delay);
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
+ (void) cmd_id;
+ (void) delay;
+
+ // note: not entirely correct as its supposed to delay if asked
+ std->mmi_state = MMI_STATE_CLOSED;
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_MMI_CLOSE ) );
+ return 0;
}
-int DvbCamPmtThread::createSectionFilter(uint16_t pid, uint8_t table_id)
+int DvbCam::mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t mmi_mode)
{
- // open the demuxer
- int demux_fd = dvbdemux_open_demux(Adapter, DemuxDevice, 0);
- if(demux_fd < 0) {
- return -1;
+ fprintf( stderr,"mmi_display_control_callback\n");
+ struct en50221_app_mmi_display_reply_details reply;
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+
+ // don't support any commands but set mode
+ if ( cmd_id!=MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE ) {
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_CMD_ID, &reply );
+ return 0;
}
- // create a section filter
- uint8_t filter[18] = {table_id};
- uint8_t mask[18] = {0xff};
- if(dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { // crc check on
- close(demux_fd);
- return -1;
+ // we only support high level mode
+ if ( mmi_mode!=MMI_MODE_HIGH_LEVEL ) {
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_UNKNOWN_MMI_MODE, &reply );
+ return 0;
}
- return demux_fd;
+ // ack the high level open
+ reply.u.mode_ack.mmi_mode = mmi_mode;
+ en50221_app_mmi_display_reply( std->stdcam->mmi_resource, session_number, MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK, &reply );
+ std->mmi_state = MMI_STATE_OPEN;
+ return 0;
}
-int DvbCamPmtThread::processPat(int demux_fd)
+int DvbCam::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)
{
- // read section
- char si_buf[4096];
- int size = read(demux_fd, si_buf, sizeof(si_buf));
- if(size < 0) {
- return -1;
- }
+ fprintf( stderr,"mmi_enq_callback\n");
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
- // parse section
- section *parsed_section = section_codec(reinterpret_cast<unsigned char *> (si_buf), size);
- if(parsed_section == NULL) {
- return -1;
- }
+ QString s;
- // parse section_ext
- section_ext *parsed_section_ext = section_ext_decode(parsed_section, 1); // crc check on
- if(parsed_section_ext == NULL) {
- return -1;
- }
+ QMutexLocker locker( &std->mutex );
- // parse pat
- mpeg_pat_section *parsed_pat = mpeg_pat_section_codec(parsed_section_ext);
- if(parsed_pat == NULL) {
- return -1;
- }
+ std->menuList.clear();
+ fprintf(stderr, "%.*s: ", text_size, text);
+ s = (const char*)text;
+ s.truncate( text_size );
+ std->menuList.append( s );
+ fflush(stdout);
- // try and find the requested program
- mpeg_pat_program *cur_program;
- mpeg_pat_section_programs_for_each(parsed_pat, cur_program) {
- if(cur_program->program_number == ServiceId) {
- return cur_program->pid;
- }
- }
+ std->mmi_enq_blind = blind_answer;
+ std->mmi_enq_length = expected_answer_length;
+ std->mmi_state = MMI_STATE_ENQ;
+ std->menuType = MMI_MENU;
- fprintf(stderr, "PmtThread: [warning] the requested service id couldn't be found\n");
-
- return -1;
+ return 0;
}
-void DvbCamPmtThread::run()
+int DvbCam::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)
{
- fprintf(stderr, "PmtThread: started\n");
+ fprintf( stderr,"mmi_menu_callback, session=%d\n",session_number);
+ StandardCam *std = (StandardCam*)arg;
+ (void) slot_id;
+ (void) session_number;
+ (void) item_raw_length;
+ (void) items_raw;
- int demux_fd = createSectionFilter(TRANSPORT_PAT_PID, stag_mpeg_program_association);
- if(demux_fd < 0) {
- fprintf(stderr, "PmtThread: [error] opening demux device failed\n");
- return;
- }
+ QString s;
- pollfd poll_desc;
- poll_desc.fd = demux_fd;
- poll_desc.events = POLLIN | POLLPRI;
- while(!Stopped) {
- int ret = poll(&poll_desc, 1, 100); // 100 ms
- if(ret < 0) {
- fprintf(stderr, "PmtThread: [error] polling demux device failed\n");
- close(demux_fd);
- return;
- }
- if((ret > 0) && (poll_desc.revents != 0) && ((poll_desc.revents & ~(POLLIN | POLLPRI)) == 0)) {
- int processed_pat = processPat(demux_fd);
- if(processed_pat >= 0) {
- close(demux_fd);
- demux_fd = createSectionFilter(processed_pat, stag_mpeg_program_map);
- if(demux_fd < 0) {
- fprintf(stderr, "PmtThread: [error] opening demux device failed\n");
- return;
- }
- poll_desc.fd = demux_fd;
- break;
- }
- }
- }
+ QMutexLocker locker( &std->mutex );
+ std->menuList.clear();
- while(!Stopped) {
- int ret = poll(&poll_desc, 1, 100); // 100 ms
- if(ret < 0) {
- fprintf(stderr, "PmtThread: [error] polling demux device failed\n");
- close(demux_fd);
- return;
- }
- if((ret > 0) && (poll_desc.revents != 0) && ((poll_desc.revents & ~(POLLIN | POLLPRI)) == 0)) {
- if(CamThread->processPmt(demux_fd)) {
- fprintf(stderr, "PmtThread: new pmt received\n");
- close(demux_fd);
- fprintf(stderr, "PmtThread: stopped\n");
- return;
- }
- }
+ fprintf(stderr, "------------------------------\n");
+
+ if (title->text_length) {
+ fprintf(stderr, "%.*s\n", title->text_length, title->text);
+ s = (const char*)title->text;
+ s.truncate( title->text_length );
+ std->menuList.append( s );
+ }
+ if (sub_title->text_length) {
+ fprintf(stderr, "%.*s\n", sub_title->text_length, sub_title->text);
+ s = (const char*)sub_title->text;
+ s.truncate( sub_title->text_length );
+ std->menuList.append( s );
}
- fprintf(stderr, "PmtThread: stopping requested\n");
+ uint32_t i;
+ fprintf(stderr, "0. Quit menu\n");
+ std->menuList.append( "0. Quit menu" );
+ for(i=0; i< item_count; i++) {
+ fprintf(stderr, "%i. %.*s\n", i+1, items[i].text_length, items[i].text);
+ s = (const char*)items[i].text;
+ s.truncate( items[i].text_length );
+ std->menuList.append( QString("%1. %2").arg(i+1).arg(s) );
- close(demux_fd);
+ }
- fprintf(stderr, "PmtThread: stopped\n");
- return;
-}
+ if (bottom->text_length) {
+ fprintf(stderr, "%.*s\n", bottom->text_length, bottom->text);
+ s = (const char*)bottom->text;
+ s.truncate( bottom->text_length );
+ std->menuList.append( s );
+ }
+ fflush(stdout);
-// class DvbCamCamHandler
+ std->mmi_state = MMI_STATE_MENU;
+ std->menuType = MMI_MENU;
-DvbCamCamHandler::DvbCamCamHandler()
-{
- AiResource = NULL;
- CaResource = NULL;
+ QApplication::postEvent( std->dvbcam, new QTimerEvent(TIMER_EVENT_MMI_OPEN ) );
- SessionNumber = -1;
+ return 0;
}
-DvbCamCamHandler::~DvbCamCamHandler()
+void DvbCam::timerEvent( QTimerEvent *e )
{
- if(CaResource != NULL) {
- en50221_app_ca_destroy(CaResource);
- CaResource = NULL;
- }
- if(AiResource != NULL) {
- en50221_app_ai_destroy(AiResource);
- AiResource = NULL;
+ switch ( e->timerId() ) {
+ case TIMER_EVENT_MMI_OPEN:
+ showMMI();
+ break;
+ case TIMER_EVENT_MMI_CLOSE:
+ closeMMI();
+ break;
+ case TIMER_EVENT_CAM_READY:
+ resendPmts();
+ break;
}
}
-bool DvbCamCamHandler::init()
+void DvbCam::showMMI()
{
- AiResource = en50221_app_ai_create(&SendFuncs);
- CaResource = en50221_app_ca_create(&SendFuncs);
-
- if(CaResource != NULL) {
- en50221_app_ca_register_info_callback(CaResource, infoCallback, this);
+ if ( !menuDialog && stdcam ) {
+ menuDialog = new MCamMenuDialog( stdcam );
+ connect( menuDialog, SIGNAL(enteredResponse(QString)), this, SLOT(mmiResponse(QString)) );
+ menuDialog->exec();
+ closeMMI();
}
-
- return sub_init();
}
-bool DvbCamCamHandler::sendPmt(char *pmt_buffer, int size)
+void DvbCam::closeMMI()
{
- if((CaResource != NULL) && (SessionNumber >= 0)) {
- if(!en50221_app_ca_pmt(CaResource, SessionNumber, reinterpret_cast<unsigned char *> (pmt_buffer), size)) {
- return true;
+ if ( menuDialog ) {
+ delete menuDialog;
+ menuDialog = 0;
+ if ( stdcam && stdcam->stdcam->mmi_resource ) {
+ en50221_app_mmi_close( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_CLOSE_MMI_CMD_ID_IMMEDIATE, 0 );
+ stdcam->mmi_state = MMI_STATE_CLOSED;
}
}
-
- return false;
}
-int DvbCamCamHandler::infoCallback(void *arg, uint8_t /*slot_id*/, uint16_t session_number, uint32_t /*ca_id_count*/, uint16_t */*ca_ids*/)
+int DvbCam::showCamDialog()
{
- (static_cast<DvbCamCamHandler *> (arg))->SessionNumber = session_number;
- return 0;
-}
-// class DvbCamCamHandlerLLCI
-
-#define MAX_CARDS 1
-#define MAX_TC 16
-#define MAX_SESSIONS 16
+ CamDialog dlg;
+ dlg.maxServiceSpin->setValue( getCamMaxService() );
+ dlg.appTypeLab->setText( getAppType() );
+ dlg.appManuLab->setText( getAppManu() );
+ dlg.manuCodeLab->setText( getManuCode() );
+ dlg.menuStringLab->setText( getMenuString() );
+ connect( dlg.camMenuBtn, SIGNAL(clicked()), this, SLOT(enterMenu()) );
+ dlg.exec();
+ CamMaxService = dlg.maxServiceSpin->value();
+ return CamMaxService;
+}
-DvbCamCamHandlerLLCI::DvbCamCamHandlerLLCI()
+void DvbCam::enterMenu()
{
- RmResource = NULL;
- SessionLayer = NULL;
- TransportLayer = NULL;
+ if ( stdcam && stdcam->stdcam->ai_resource )
+ en50221_app_ai_entermenu( stdcam->stdcam->ai_resource, stdcam->stdcam->ai_session_number );
}
-DvbCamCamHandlerLLCI::~DvbCamCamHandlerLLCI()
+void DvbCam::mmiResponse( QString s )
{
- if(SessionLayer != NULL) {
- en50221_sl_destroy(SessionLayer);
- SessionLayer = NULL;
- }
- if(TransportLayer != NULL) {
- en50221_tl_destroy(TransportLayer);
- TransportLayer = NULL;
- }
- if(RmResource != NULL) {
- en50221_app_rm_destroy(RmResource);
- RmResource = NULL;
+ QString res = s.stripWhiteSpace();
+
+ switch( stdcam->mmi_state ) {
+ case MMI_STATE_CLOSED:
+ case MMI_STATE_OPEN: {
+ en50221_app_ai_entermenu(stdcam->stdcam->ai_resource, stdcam->stdcam->ai_session_number);
+ fprintf(stderr,"en50221_app_ai_entermenu 2\n");
+ break;
+ }
+ case MMI_STATE_ENQ: {
+ if ( res.isEmpty() ) {
+ en50221_app_mmi_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_ANSW_ID_CANCEL, NULL, 0);
+ }
+ else {
+ en50221_app_mmi_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, MMI_ANSW_ID_ANSWER, (uint8_t*)res.ascii(), res.length() );
+ }
+ stdcam->mmi_state = MMI_STATE_OPEN;
+ break;
+ }
+ case MMI_STATE_MENU: {
+ en50221_app_mmi_menu_answ( stdcam->stdcam->mmi_resource, stdcam->stdcam->mmi_session_number, res.toInt() );
+ stdcam->mmi_state = MMI_STATE_OPEN;
+ break;
+ }
}
}
-int DvbCamCamHandlerLLCI::llci_rm_enq_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number)
+
+
+
+MCamMenuDialog::MCamMenuDialog( StandardCam *sc )
{
- uint32_t resource_ids[] = {EN50221_APP_RM_RESOURCEID, EN50221_APP_AI_RESOURCEID, EN50221_APP_CA_RESOURCEID};
- en50221_app_rm_reply(arg, session_number, sizeof(resource_ids) / 4, resource_ids);
- return 0;
+ stdcam = sc;
+ connect( inputLine, SIGNAL(returnPressed()), this, SLOT(validateClicked()) );
+ connect( &readTimer, SIGNAL(timeout()), this, SLOT(setMenu()) );
+ readTimer.start( 500 );
}
-int DvbCamCamHandlerLLCI::llci_rm_reply_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number, uint32_t /*resource_id_count*/, uint32_t */*resource_ids*/)
+void MCamMenuDialog::setMenu()
{
- en50221_app_rm_changed(arg, session_number);
- return 0;
+ if ( !stdcam )
+ return;
+ QMutexLocker locker( &stdcam->mutex );
+ if ( stdcam->menuType==MMI_MENU )
+ menuText->setText( stdcam->menuList.join("\n") );
}
-int DvbCamCamHandlerLLCI::llci_rm_changed_callback(void *arg, uint8_t /*slot_id*/, uint16_t session_number)
+void MCamMenuDialog::validateClicked()
{
- en50221_app_rm_enq(arg, session_number);
- return 0;
+ emit enteredResponse( inputLine->text() );
+ inputLine->clear();
}
-int DvbCamCamHandlerLLCI::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)
+
+
+
+
+// class CamService
+CamService::CamService( int adapter, int demux_device, ChannelDesc *chan, int maxService )
{
- // decode the resource id
- en50221_app_public_resource_id resid;
- if(!en50221_app_decode_public_resource_id(&resid, requested_resource_id)) {
- return -1;
- }
+ Adapter = adapter;
+ DemuxDevice = demux_device;
+ CamMaxService = maxService;
+ channel = *chan;
+ parsedPmt = NULL;
+ state = NotReady;
+ isRunning = true;
+ start();
+}
- // try and find an instance of the resource
- const SlResource *Resources = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources;
- int i;
- for(i = 0; i < 3; ++i) {
- if((resid.resource_class == Resources[i].resid.resource_class) && (resid.resource_type == Resources[i].resid.resource_type)) {
- *callback_out = Resources[i].callback;
- *arg_out = Resources[i].arg;
- *connected_resource_id = Resources[i].binary_resource_id;
- return 0;
- }
- }
- return -1;
+CamService::~CamService()
+{
+ stop();
}
-int DvbCamCamHandlerLLCI::llci_session_callback(void *arg, int reason, uint8_t /*slot_id*/, uint16_t session_number, uint32_t resource_id)
+void CamService::restart()
{
- if(reason == S_SCALLBACK_REASON_CAMCONNECTED) {
- if(resource_id == EN50221_APP_RM_RESOURCEID) {
- void *RmResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[0].arg;
- en50221_app_rm_enq(RmResource, session_number);
- }
- else if(resource_id == EN50221_APP_AI_RESOURCEID) {
- void *AiResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[1].arg;
- en50221_app_ai_enquiry(AiResource, session_number);
- }
- else if(resource_id == EN50221_APP_CA_RESOURCEID) {
- void *CaResource = (static_cast<DvbCamCamHandlerLLCI *> (arg))->Resources[2].arg;
- en50221_app_ca_info_enq(CaResource, session_number);
- }
- }
- return 0;
+ setState( NotReady );
}
-void DvbCamCamHandlerLLCI::poll()
+void CamService::stop()
{
- if(en50221_tl_poll(TransportLayer)) {
- fprintf(stderr, "CamThread: [warning] polling the stack failed\n");
- usleep(10000); // wait 10 ms to not block
- }
+ isRunning = false;
+ wait();
}
-bool DvbCamCamHandlerLLCI::registerCam(int ca_fd, uint8_t slot)
+int CamService::createSectionFilter(uint16_t pid, uint8_t table_id)
{
- // register the slot
- int slot_id = en50221_tl_register_slot(TransportLayer, ca_fd, slot, 1000, 100);
- if(slot_id < 0) {
- return false;
+ // open the demuxer
+ int demux_fd = dvbdemux_open_demux(Adapter, DemuxDevice, 0);
+ if(demux_fd < 0) {
+ return -1;
}
- // create a new connection on the slot
- if(en50221_tl_new_tc(TransportLayer, slot_id) < 0) {
- return false;
+ // create a section filter
+ uint8_t filter[18] = {table_id};
+ uint8_t mask[18] = {0xff};
+ if(dvbdemux_set_section_filter(demux_fd, pid, filter, mask, 1, 1)) { // crc check on
+ close(demux_fd);
+ return -1;
}
- return true;
+ return demux_fd;
}
-bool DvbCamCamHandlerLLCI::sub_init()
+int CamService::processPat(int demux_fd)
{
- // create transport layer
- TransportLayer = en50221_tl_create(MAX_CARDS, MAX_TC);
- if(TransportLayer == NULL) {
- return false;
- }
+ // read section
+ unsigned char si_buf[4096];
+ int size = read( demux_fd, si_buf, sizeof(si_buf) );
+ if ( size<0 )
+ return -1;
- // create session layer
- SessionLayer = en50221_sl_create(TransportLayer, MAX_SESSIONS);
- if(SessionLayer == NULL) {
- en50221_tl_destroy(TransportLayer);
- TransportLayer = NULL;
- return false;
- }
+ // parse section
+ section *parsed_section = section_codec( si_buf, size );
+ if ( parsed_section==NULL )
+ return -1;
- // create sendfuncs
- SendFuncs.arg = SessionLayer;
- SendFuncs.send_data = en50221_sl_send_data;
- SendFuncs.send_datav = en50221_sl_send_datav;
-
- // create the resource manager resource
- RmResource = en50221_app_rm_create(&SendFuncs);
- en50221_app_decode_public_resource_id(&Resources[0].resid, EN50221_APP_RM_RESOURCEID);
- Resources[0].binary_resource_id = EN50221_APP_RM_RESOURCEID;
- Resources[0].callback = en50221_app_rm_message;
- Resources[0].arg = RmResource;
- en50221_app_rm_register_enq_callback(RmResource, llci_rm_enq_callback, RmResource);
- en50221_app_rm_register_reply_callback(RmResource, llci_rm_reply_callback, RmResource);
- en50221_app_rm_register_changed_callback(RmResource, llci_rm_changed_callback, RmResource);
-
- // integrate the application information resource
- en50221_app_decode_public_resource_id(&Resources[1].resid, EN50221_APP_AI_RESOURCEID);
- Resources[1].binary_resource_id = EN50221_APP_AI_RESOURCEID;
- Resources[1].callback = en50221_app_ai_message;
- Resources[1].arg = AiResource;
-
- // integrate the ca resource
- en50221_app_decode_public_resource_id(&Resources[2].resid, EN50221_APP_CA_RESOURCEID);
- Resources[2].binary_resource_id = EN50221_APP_CA_RESOURCEID;
- Resources[2].callback = en50221_app_ca_message;
- Resources[2].arg = CaResource;
-
- // register session layer callbacks
- en50221_sl_register_lookup_callback(SessionLayer, llci_lookup_callback, this);
- en50221_sl_register_session_callback(SessionLayer, llci_session_callback, this);
+ // parse section_ext
+ section_ext *parsed_section_ext = section_ext_decode( parsed_section, 1 ); // crc check on
+ if ( parsed_section_ext==NULL )
+ return -1;
- return true;
-}
+ // parse pat
+ mpeg_pat_section *parsed_pat = mpeg_pat_section_codec( parsed_section_ext );
+ if ( parsed_pat==NULL )
+ return -1;
-// class DvbCamCamHandlerHLCI
+ // try and find the requested program
+ mpeg_pat_program *cur_program;
+ mpeg_pat_section_programs_for_each( parsed_pat, cur_program ) {
+ if ( cur_program->program_number==channel.sid )
+ return cur_program->pid;
+ }
-DvbCamCamHandlerHLCI::DvbCamCamHandlerHLCI()
-{
-}
+ fprintf( stderr, "CamService (%s): [warning] channel couldn't be found in PAT\n", channel.name.ascii() );
-DvbCamCamHandlerHLCI::~DvbCamCamHandlerHLCI()
-{
+ return -1;
}
-int DvbCamCamHandlerHLCI::hlci_send_data(void *arg, uint16_t /*session_number*/, uint8_t *data, uint16_t data_length)
+int CamService::processPmt( int demux_fd )
{
- return dvbca_hlci_write(static_cast<int> (reinterpret_cast<intptr_t> (arg)), data, data_length);
-}
+ // read section
+ memset( pmtBuffer, 0, sizeof(pmtBuffer) );
+ int size = read( demux_fd, pmtBuffer, sizeof(pmtBuffer) );
+ if ( size<=0 )
+ return -1;
-int DvbCamCamHandlerHLCI::hlci_send_datav(void *arg, uint16_t /*session_number*/, iovec *vector, int iov_count)
-{
- // calculate the total length of the data to send
- uint32_t data_size = 0;
- for(int i = 0; i < iov_count; ++i) {
- data_size += vector[i].iov_len;
- }
+ // parse section
+ section *parsed_section = section_codec( pmtBuffer, size );
+ if ( parsed_section==NULL )
+ return -1;
- // allocate memory for it
- uint8_t *buf = new uint8_t[data_size];
+ // parse section_ext
+ section_ext *parsed_section_ext = section_ext_decode( parsed_section, 1 ); // crc check on
+ if ( parsed_section_ext==NULL )
+ return -1;
- // merge the iovecs
- uint8_t *pos = buf;
- for(int i = 0; i < iov_count; ++i) {
- memcpy(pos, vector[i].iov_base, vector[i].iov_len);
- pos += vector[i].iov_len;
- }
+ // parse pmt
+ struct mpeg_pmt_section *pmt = mpeg_pmt_section_codec( parsed_section_ext );
+ if ( pmt==NULL )
+ return -1;
- // send it
- int status = dvbca_hlci_write(static_cast<int> (reinterpret_cast<intptr_t> (arg)), buf, data_size);
- delete buf;
- return status;
+ parsedPmt = pmt;
+ return parsedPmt->head.version_number;
}
-void DvbCamCamHandlerHLCI::poll()
+void CamService::setState( PmtState st )
{
- // we do nothing here for the moment
- usleep(100000); // 100 ms
+ QMutexLocker locker( &mutex );
+ switch ( st ) {
+ case Ready: {
+ int listmgnt;
+ if ( CamMaxService==1 )
+ listmgnt = CA_LIST_MANAGEMENT_ONLY;
+ else
+ listmgnt = CA_LIST_MANAGEMENT_ADD;
+ if ( state>Ready )
+ listmgnt = CA_LIST_MANAGEMENT_UPDATE;
+ if ( setCaPmt( listmgnt, CA_PMT_CMD_ID_OK_DESCRAMBLING ) )
+ state = st;
+ break;
+ }
+ case Remove: {
+ if ( state!=Added )
+ state = Destroy;
+ else if ( setCaPmt( CA_LIST_MANAGEMENT_UPDATE, CA_PMT_CMD_ID_NOT_SELECTED ) )
+ state = st;
+ break;
+ }
+ default: {
+ state = st;
+ }
+ }
}
-bool DvbCamCamHandlerHLCI::registerCam(int ca_fd, uint8_t /*slot*/)
+int CamService::getState()
{
- SendFuncs.arg = reinterpret_cast<void *> (ca_fd);
-
- // get application information
- if(en50221_app_ai_enquiry(AiResource, 0)) {
- fprintf(stderr, "CamThread: [DEBUG #1]\n");
- return false;
- }
-
- uint8_t buf[256];
- int size = dvbca_hlci_read(ca_fd, TAG_APP_INFO, buf, sizeof(buf));
- if(size <= 0) {
- fprintf(stderr, "CamThread: [DEBUG #2]\n");
- return false;
- }
+ QMutexLocker locker( &mutex );
+ return state;
+}
- if(en50221_app_ai_message(AiResource, 0, 0, EN50221_APP_AI_RESOURCEID, buf, size)) {
- fprintf(stderr, "CamThread: [DEBUG #3]\n");
+bool CamService::setCaPmt( int list_management, int cmd_id )
+{
+ if ( !parsedPmt )
return false;
- }
- // FIXME: try to change this soon
- buf[0] = TAG_CA_INFO >> 16;
- buf[1] = TAG_CA_INFO >> 8;
- buf[2] = TAG_CA_INFO;
- buf[3] = 0;
- if(en50221_app_ca_message(CaResource, 0, 0, EN50221_APP_CA_RESOURCEID, buf, 4)) {
- fprintf(stderr, "CamThread: [DEBUG #4]\n");
+ caPmtSize = en50221_ca_format_pmt( parsedPmt, caPmt, sizeof(caPmt), 0, list_management, cmd_id );
+ if ( caPmtSize<=0 )
return false;
- }
-
- fprintf(stderr, "CamThread: [DEBUG #5]\n");
return true;
}
-bool DvbCamCamHandlerHLCI::sub_init()
+void CamService::run()
{
- // create sendfuncs
- SendFuncs.arg = NULL;
- SendFuncs.send_data = hlci_send_data;
- SendFuncs.send_datav = hlci_send_datav;
+ int i, pmtVersion=-1;
+ int demux_fd=-1;
- return true;
+ fprintf( stderr, "CamService (%s): started\n", channel.name.ascii() );
+
+ while ( isRunning ) {
+loopLabel:
+ demux_fd = createSectionFilter( TRANSPORT_PAT_PID, stag_mpeg_program_association );
+ if ( demux_fd<0 ) {
+ fprintf( stderr, "CamService (%s): [error] opening demux device failed\n", channel.name.ascii() );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+
+ pollfd poll_desc;
+ poll_desc.fd = demux_fd;
+ poll_desc.events = POLLIN | POLLPRI;
+ while ( isRunning ) {
+ int ret = poll( &poll_desc, 1, 1000 );
+ if ( ret<0 ) {
+ fprintf( stderr, "CamService (%s): [error] polling demux device failed\n", channel.name.ascii() );
+ close( demux_fd );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ if ( ret>0 ) {
+ int processed_pat = processPat( demux_fd );
+ if ( processed_pat>=0 ) {
+ close( demux_fd );
+ demux_fd = -1;
+ demux_fd = createSectionFilter( processed_pat, stag_mpeg_program_map );
+ if ( demux_fd<0 ) {
+ fprintf( stderr, "CamService (%s): [error] opening demux device failed\n", channel.name.ascii() );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ poll_desc.fd = demux_fd;
+ break;
+ }
+ else
+ usleep( 10000 );
+ }
+ else
+ usleep( 10000 );
+ }
+
+ while ( isRunning ) {
+ int ret = poll( &poll_desc, 1, 1000 );
+ if ( ret<0 ) {
+ fprintf( stderr, "CamService (%s): [error] polling demux device failed\n", channel.name.ascii() );
+ close( demux_fd );
+ demux_fd = -1;
+ usleep( 100000 );
+ goto loopLabel;
+ }
+ if ( ret>0 ) {
+ //fprintf( stderr, "CamService (%s): parsing pmt\n", channel.name.ascii() );
+ i = processPmt( demux_fd );
+ if ( i==-1 )
+ usleep( 10000 );
+ else {
+ if ( i!=pmtVersion || getState()<Ready ) {
+ fprintf( stderr, "CamService (%s): new pmt received\n", channel.name.ascii() );
+ setState( Ready );
+ pmtVersion = i;
+ }
+ i = 200;
+ while ( i-- && isRunning )
+ usleep( 10000 );
+ }
+ }
+ else
+ usleep( 10000 );
+ }
+ }
+
+ if ( demux_fd != -1 )
+ close( demux_fd );
+ fprintf( stderr, "CamService (%s): stopped\n", channel.name.ascii() );
}
diff --git a/kaffeine/src/input/dvb/dvbcam.h b/kaffeine/src/input/dvb/dvbcam.h
index 47a4012..ec9bf45 100644
--- a/kaffeine/src/input/dvb/dvbcam.h
+++ b/kaffeine/src/input/dvb/dvbcam.h
@@ -1,6 +1,7 @@
/*
* dvbcam.h
*
+ * Copyright (C) 2008 Christophe Thommeret <hftom@free.fr>
* Copyright (C) 2006 Christoph Pfister <christophpfister@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -21,32 +22,182 @@
#ifndef DVBCAM_H
#define DVBCAM_H
-class DvbCamCamThread;
-class DvbCamPmtThread;
+#include <libdvbapi/dvbca.h>
+#include <libdvbapi/dvbdemux.h>
+#include <libdvben50221/en50221_app_ai.h>
+#include <libdvben50221/en50221_app_ca.h>
+#include <libdvben50221/en50221_app_mmi.h>
+#include <libdvben50221/en50221_app_rm.h>
+#include <libdvben50221/en50221_app_tags.h>
+#include <libdvben50221/en50221_session.h>
+#include <libdvben50221/en50221_stdcam.h>
+#include <libucsi/mpeg/section.h>
-class DvbCam
+#include <qthread.h>
+#include <qmutex.h>
+#include <qptrlist.h>
+
+#include "channeldesc.h"
+#include "camdialog.h"
+#include "cammenudialog.h"
+
+#define MMI_STATE_CLOSED 0
+#define MMI_STATE_OPEN 1
+#define MMI_STATE_ENQ 2
+#define MMI_STATE_MENU 3
+
+#define MMI_NO_MENU 0
+#define MMI_MENU 1
+
+
+
+class CamService : protected QThread
{
public:
- DvbCam(int adapter, int ca_device, int demux_device, int ci_type);
- ~DvbCam();
+ enum PmtState{ NotReady=0, Ready, Added, Remove, Destroy };
+ CamService( int adapter, int demux_device, ChannelDesc *chan, int maxService );
+ ~CamService();
+ void setState( PmtState st );
+ int getState();
+ const ChannelDesc& getChannel() { return channel; }
+ void restart();
- void restart(int service_id);
+ unsigned char caPmt[4096];
+ int caPmtSize;
+
+protected:
+ void run();
+
+private:
+ int createSectionFilter( uint16_t pid, uint8_t table_id );
+ int processPat( int demux_fd );
+ int processPmt( int demux_fd );
+ bool setCaPmt( int list_management, int cmd_id );
void stop();
- bool running() { return isRunning; }
- int serviceId() { return sid; }
+ int Adapter;
+ int DemuxDevice;
+ ChannelDesc channel;
+ unsigned char pmtBuffer[4096];
+ struct mpeg_pmt_section *parsedPmt;
+ PmtState state;
+ bool isRunning;
+ QMutex mutex;
+ int CamMaxService;
+};
+
+
+
+class DvbCam;
+
+class StandardCam
+{
+public:
+ StandardCam( en50221_stdcam *sc, DvbCam *dc ) {
+ stdcam=sc;
+ dvbcam=dc;
+ mmi_state=MMI_STATE_CLOSED;
+ menuType=MMI_NO_MENU;
+ }
+
+ en50221_stdcam *stdcam;
+ DvbCam *dvbcam;
+ int mmi_state;
+ int mmi_enq_blind;
+ int mmi_enq_length;
+
+ int menuType;
+ QStringList menuList;
+
+ QMutex mutex;
+};
+
+
+
+class MCamMenuDialog : public CamMenuDialog
+{
+ Q_OBJECT
+public:
+ MCamMenuDialog( StandardCam *sc );
+private:
+ StandardCam *stdcam;
+ QTimer readTimer;
+private slots:
+ void setMenu();
+ void validateClicked();
+signals:
+ void enteredResponse( QString );
+};
+
+
+
+class DvbCam : public QObject, public QThread
+{
+ Q_OBJECT
+public:
+ DvbCam(int adapter, int ca_device, int demux_device, int ci_type, int maxService);
+ ~DvbCam();
+ void startService( ChannelDesc *chan );
+ void stopService( ChannelDesc *chan );
+ bool canPlay( ChannelDesc *chan );
static int probe( int adapter, int ca_device );
+ void setAppType( QString s ) { appType=s; }
+ void setAppManu( QString s ) { appManu=s; }
+ void setManuCode( QString s ) { manuCode=s; }
+ void setMenuString( QString s ) { menuString=s; }
+ QString getAppType() { return appType; }
+ QString getAppManu() { return appManu; }
+ QString getManuCode() { return manuCode; }
+ QString getMenuString() { return menuString; }
+ int getCamMaxService() { return CamMaxService; }
+
+ int showCamDialog();
+
+protected:
+ void run();
+ void timerEvent( QTimerEvent *e );
+
+private slots:
+ void mmiResponse( QString s );
+ void showMMI();
+ void closeMMI();
+ void enterMenu();
+
private:
+ bool init();
+ bool sendPmt( unsigned char *pmt_buffer, int size );
+ void resendPmts();
+
+ static int infoCallback(void *arg, uint8_t slot_id, uint16_t session_number, uint32_t ca_id_count, uint16_t *ca_ids);
+ static int aiCallback(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);
+ static int mmi_close_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t delay);
+ static int mmi_display_control_callback(void *arg, uint8_t slot_id, uint16_t session_number, uint8_t cmd_id, uint8_t mmi_mode);
+ static int 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);
+ static int 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);
+
int Adapter;
int CaDevice;
int DemuxDevice;
- bool isRunning;
- int sid;
int ciType;
+ int CamMaxService;
+
+ bool isRunning;
+
+ QPtrList<CamService> sidList;
+ QMutex sidMutex;
+
+ QString appType, appManu, manuCode, menuString;
+
+ StandardCam *stdcam;
+ en50221_session_layer *SessionLayer;
+ en50221_transport_layer *TransportLayer;
- DvbCamCamThread *CamThread;
- DvbCamPmtThread *PmtThread;
+ MCamMenuDialog *menuDialog;
};
#endif /* DVBCAM_H */
diff --git a/kaffeine/src/input/dvb/dvbconfig.cpp b/kaffeine/src/input/dvb/dvbconfig.cpp
index 746d745..90e0489 100644
--- a/kaffeine/src/input/dvb/dvbconfig.cpp
+++ b/kaffeine/src/input/dvb/dvbconfig.cpp
@@ -38,6 +38,7 @@
#include "dvbconfig.h"
#include "kaffeinedvbplugin.h"
+#include "dvbpanel.h"
@@ -72,6 +73,21 @@ void MPushButton::isClicked()
+MCAMButton::MCAMButton( QWidget *parent, int devNum ) : QPushButton( i18n("CAM"), parent )
+{
+ deviceNumber = devNum;
+ connect( this, SIGNAL(clicked()), this, SLOT(isClicked()) );
+}
+
+
+
+void MCAMButton::isClicked()
+{
+ emit clicked( deviceNumber );
+}
+
+
+
MComboBox::MComboBox( QWidget *parent, int devNum, int lnbNum ) : QComboBox( parent )
{
deviceNumber = devNum;
@@ -109,6 +125,12 @@ Device::Device( int anum, int tnum, fe_type_t t, const QString &n, bool as )
source = "";
canAutoscan= as;
tuningTimeout = 1500;
+ hasCAM = false;
+ camMaxService = 1;
+ secMini = 0;
+ secTwice = 0;
+ priority = 10;
+ doS2 = 0;
}
@@ -134,6 +156,7 @@ DVBconfig::DVBconfig( const QString &dvbConf )
sizeFile = 0;
categories.setAutoDelete( true );
devList.setAutoDelete( true );
+ readFirst();
startup();
readConfig();
}
@@ -187,6 +210,7 @@ void DVBconfig::startup()
int i=0, j=0, res, fdFrontend=0;
struct dvb_frontend_info info;
bool as;
+ QTime t1;
QStringList list, flist;
QString s, t;
@@ -200,6 +224,11 @@ void DVBconfig::startup()
for ( j=0; j<(int)flist.count(); j++ ) {
s = list[i];
t = flist[j];
+ if ( devList.count()==MAX_DEVICES )
+ break;
+ if ( !probeMfe && t!="frontend0" )
+ continue;
+ t1 = QTime::currentTime();
fdFrontend = open( QString("/dev/dvb/%1/%2").arg( s ).arg( t ).ascii(), O_RDWR);
if ( fdFrontend>0 ) {
if ( !(res = ioctl( fdFrontend, FE_GET_INFO, &info ) < 0) ) {
@@ -212,13 +241,14 @@ void DVBconfig::startup()
as = true;
else
as = false;
- fprintf(stderr,"/dev/dvb/%s/%s : opened ( %s )\n", s.ascii(), t.ascii(), info.name );
+ fprintf(stderr,"/dev/dvb/%s/%s : opened ( %s ) (%dms)\n", s.ascii(), t.ascii(), info.name, t1.msecsTo(QTime::currentTime()) );
devList.append( new Device( s.replace("adapter","").toInt(), t.replace("frontend","").toInt(), info.type, info.name, as ) );
}
close( fdFrontend );
}
- else
- perror( QString("/dev/dvb/%1/%2").arg( s ).arg( t ).ascii() );
+ else {
+ perror( QString("/dev/dvb/%1/%2 %3/%4").arg( s ).arg( t ).arg( errno ).arg( -EBUSY ).ascii() );
+ }
}
}
@@ -292,9 +322,9 @@ bool DVBconfig::localData()
bool DVBconfig::haveData()
{
- if ( !QDir( dvbConfigDir+"dvb-s" ).exists() || !QDir( dvbConfigDir+"dvb-c" ).exists() || !QDir( dvbConfigDir+"dvb-t" ).exists() ) {
+ if ( !QDir( dvbConfigDir+"dvb-s" ).exists() || !QDir( dvbConfigDir+"dvb-c" ).exists() || !QDir( dvbConfigDir+"dvb-t" ).exists() || !QDir( dvbConfigDir+"atsc" ).exists()) {
loadDvbData(0);
- if ( !QDir( dvbConfigDir+"dvb-s" ).exists() || !QDir( dvbConfigDir+"dvb-c" ).exists() || !QDir( dvbConfigDir+"dvb-t" ).exists() ) {
+ if ( !QDir( dvbConfigDir+"dvb-s" ).exists() || !QDir( dvbConfigDir+"dvb-c" ).exists() || !QDir( dvbConfigDir+"dvb-t" ).exists() || !QDir( dvbConfigDir+"atsc" ).exists() ) {
if ( !localData() )
return false;
}
@@ -313,6 +343,7 @@ QStringList DVBconfig::getSourcesList( fe_type_t type )
case FE_QPSK : s = "dvb-s"; break;
case FE_QAM : s = "dvb-c"; break;
case FE_OFDM : s = "dvb-t"; break;
+ case FE_ATSC : s = "atsc"; break;
default : return list;
}
list = QDir( dvbConfigDir+s ).entryList( QDir::Files, QDir::Name );
@@ -383,6 +414,14 @@ void DVBconfig::saveDvbChanOrder( int s, int col )
+void DVBconfig::readFirst()
+{
+ config->setGroup( "DVB Options" );
+ probeMfe = config->readNumEntry( "ProbeMFE", 1 );
+}
+
+
+
void DVBconfig::readConfig()
{
QSize size;
@@ -413,6 +452,8 @@ void DVBconfig::readConfig()
for ( i=0; i<(int)devList.count(); i++ ) {
devList.at(i)->source = config->readEntry( QString("DVB%1").arg(i), "" );
devList.at(i)->tuningTimeout = config->readNumEntry( QString("DVB%1_TIMEOUT").arg(i), 1500 );
+ devList.at(i)->camMaxService = config->readNumEntry( QString("DVB%1_CAM_MAX").arg(i), 1 );
+ devList.at(i)->priority = config->readNumEntry( QString("DVB%1_PRIORITY").arg(i), 10 );
if ( devList.at(i)->type!=FE_QPSK )
continue;
devList.at(i)->numLnb = config->readNumEntry( QString("DVB%1_NLNB").arg(i), 1 );
@@ -426,6 +467,9 @@ void DVBconfig::readConfig()
devList.at(i)->lnb[j].speed13v = config->readDoubleNumEntry( QString("DVB%1_LNB%2_speed13v").arg(i).arg(j), 2.5 );
devList.at(i)->lnb[j].speed18v = config->readDoubleNumEntry( QString("DVB%1_LNB%2_speed18v").arg(i).arg(j), 1.5 );
}
+ devList.at(i)->secMini = config->readNumEntry( QString("DVB%1_SEC_MINI").arg(i), 0 );
+ devList.at(i)->secTwice = config->readNumEntry( QString("DVB%1_SEC_TWICE").arg(i), 0 );
+ devList.at(i)->doS2 = config->readNumEntry( QString("DVB%1_DOS2").arg(i), 0 );
}
j = config->readNumEntry( "NumCategories", 0 );
for ( i=0; i<j; i++ )
@@ -442,6 +486,9 @@ void DVBconfig::readConfig()
devList.at(i)->usalsLatitude = usalsLatitude;
devList.at(i)->usalsLongitude = usalsLongitude;
}
+ ringBufSize = config->readNumEntry( "RingBufSize", 2 );
+ if ( ringBufSize<2 )
+ ringBufSize = 2;
}
@@ -463,9 +510,12 @@ void DVBconfig::saveConfig()
config->writeEntry( "BroadcastAddress", broadcastAddress );
config->writeEntry( "BroadcastPort", broadcastPort );
config->writeEntry( "SenderPort", senderPort );
+ config->writeEntry( "ProbeMFE", probeMfe );
for ( i=0; i<(int)devList.count(); i++ ) {
config->writeEntry( QString("DVB%1").arg(i), devList.at(i)->source );
config->writeEntry( QString("DVB%1_TIMEOUT").arg(i), devList.at(i)->tuningTimeout );
+ config->writeEntry( QString("DVB%1_PRIORITY").arg(i), devList.at(i)->priority );
+ config->writeEntry( QString("DVB%1_CAM_MAX").arg(i), devList.at(i)->camMaxService );
if ( devList.at(i)->type!=FE_QPSK )
continue;
config->writeEntry( QString("DVB%1_NLNB").arg(i), devList.at(i)->numLnb );
@@ -479,6 +529,9 @@ void DVBconfig::saveConfig()
config->writeEntry( QString("DVB%1_LNB%2_speed13v").arg(i).arg(j), devList.at(i)->lnb[j].speed13v );
config->writeEntry( QString("DVB%1_LNB%2_speed18v").arg(i).arg(j), devList.at(i)->lnb[j].speed18v );
}
+ config->writeEntry( QString("DVB%1_SEC_MINI").arg(i), devList.at(i)->secMini );
+ config->writeEntry( QString("DVB%1_SEC_TWICE").arg(i), devList.at(i)->secTwice );
+ config->writeEntry( QString("DVB%1_DOS2").arg(i), devList.at(i)->doS2 );
}
config->writeEntry( "NumCategories", categories.count() );
for ( i=0; i<(int)categories.count(); i++ ) {
@@ -494,6 +547,7 @@ void DVBconfig::saveConfig()
config->writeEntry( "UsalsLatitude", usalsLatitude );
config->writeEntry( "UsalsLongitude", usalsLongitude );
config->writeEntry( "SizeFile", sizeFile );
+ config->writeEntry( "RingBufSize", ringBufSize );
config->sync();
}
@@ -511,7 +565,7 @@ bool DVBconfig::firstRun()
-DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlugin *p ) :
+DvbConfigDialog::DvbConfigDialog( DvbPanel *pan, DVBconfig *dc, QWidget *parent, KaffeineDvbPlugin *p ) :
KDialogBase ( IconList, i18n("DVB Settings"), Ok|Cancel, Ok, parent, "dvbConfigDialog", true, true )
{
QLabel *lab;
@@ -529,7 +583,7 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
QSpinBox *spin;
KPushButton *usals;
QWidget *swidg;
- QStringList rotorList; rotorList<<i18n("No rotor")<<i18n("USALS rotor")<<i18n("Positions rotor");
+ QStringList rotorList; rotorList<<i18n("No rotor")<<i18n("USALS rotor")<<i18n("Positions rotor")<<i18n("External positionner");
dvbConfig = dc;
timeoutSpin.setAutoDelete( true );
@@ -558,7 +612,22 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
case FE_ATSC : dvbType->setText( i18n("Atsc") ); break;
default : dvbType->setText( i18n("Unknown") );
}
- grid->addMultiCellWidget( dvbType, gridLine, gridLine, 1, 3 );
+ if ( dvbConfig->devList.at(i)->hasCAM ) {
+ grid->addWidget( dvbType, gridLine, 1 );
+ MCAMButton *camb = new MCAMButton( gb, i );
+ connect( camb, SIGNAL(clicked(int)), pan, SLOT(camClicked(int)) );
+ grid->addWidget( camb, gridLine, 2 );
+ }
+ else
+ grid->addMultiCellWidget( dvbType, gridLine, gridLine, 1, 3 );
+ ++gridLine;
+
+ lab = new QLabel( i18n("Tuner priority (0=Don't use):"), gb );
+ grid->addWidget( lab, gridLine, 0 );
+ spin = new QSpinBox( 0, 99, 1, gb );
+ spin->setValue( dvbConfig->devList.at(i)->priority );
+ priority.append( spin );
+ grid->addWidget( spin, gridLine, 1 );
++gridLine;
lab = new QLabel( i18n("Tuner timeout :"), gb );
@@ -572,6 +641,11 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
++gridLine;
if ( dvbConfig->devList.at(i)->type==FE_QPSK ) {
+ doS2[i] = new QCheckBox( i18n("S2 capable device"), gb );
+ doS2[i]->setChecked( dvbConfig->devList.at(i)->doS2 );
+ grid->addWidget( doS2[i], gridLine, 0 );
+ ++gridLine;
+
lab = new QLabel( i18n("Number of LNBs:"), gb );
grid->addWidget( lab, gridLine, 0 );
satNumber[i] = new MSpinBox( gb, i );
@@ -583,6 +657,16 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
grid->addWidget( usals, gridLine, 2 );
++gridLine;
+
+ secMini[i] = new QCheckBox( i18n("Mini DiSEqC (A-B)."), gb );
+ secMini[i]->setChecked( dvbConfig->devList.at(i)->secMini );
+ secMini[i]->setEnabled( false );
+ grid->addWidget( secMini[i], gridLine, 1 );
+ secTwice[i] = new QCheckBox( i18n("Send DiSEqC commands twice."), gb );
+ secTwice[i]->setChecked( dvbConfig->devList.at(i)->secTwice );
+ grid->addWidget( secTwice[i], gridLine, 0 );
+
+ ++gridLine;
lnb0[i] = new MPushButton( gb, i, 0 );
lnb0[i]->setGuiItem( KGuiItem(i18n("LNB 1 settings..."), icon->loadIconSet("hwinfo", KIcon::Small) ) );
@@ -853,9 +937,19 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
vb = new QVBoxLayout( page, 6, 6 );
gb = new QGroupBox( "", page );
grid = new QGridLayout( gb, 1, 1, 20, 6 );
+
+ probeMfe = new QCheckBox( i18n("Probe Multiple-Frontends (Restart required)."), gb );
+ probeMfe->setChecked( dvbConfig->probeMfe );
+ grid->addWidget( probeMfe, 0, 0 );
+
+ lab = new QLabel( i18n("LiveShow ringbuffer size (MB) :"), gb );
+ grid->addWidget( lab, 1, 0 );
+ ringBufSize = new QSpinBox( 2, 99, 1, gb );
+ ringBufSize->setValue( dvbConfig->ringBufSize );
+ grid->addWidget( ringBufSize, 1, 1 );
lab = new QLabel( i18n("Default charset (restart needed):"), gb );
- grid->addWidget( lab, 0, 0 );
+ grid->addWidget( lab, 2, 0 );
charsetComb = new QComboBox( gb );
charsetComb->insertItem( "ISO8859-1" );
charsetComb->insertItem( "ISO6937" );
@@ -863,19 +957,19 @@ DvbConfigDialog::DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlu
charsetComb->setCurrentItem( 0 );
else if ( dvbConfig->defaultCharset=="ISO6937" )
charsetComb->setCurrentItem( 1 );
- grid->addWidget( charsetComb, 0, 1 );
+ grid->addWidget( charsetComb, 2, 1 );
lab = new QLabel( i18n("Update scan data:"), gb );
- grid->addWidget( lab, 1, 0 );
+ grid->addWidget( lab, 3, 0 );
updateBtn = new KPushButton( gb );
updateBtn->setGuiItem( KGuiItem(i18n("Download"), icon->loadIconSet("khtml_kget", KIcon::Small) ) );
- grid->addWidget( updateBtn, 1, 1 );
+ grid->addWidget( updateBtn, 3, 1 );
lab = new QLabel( i18n("Dump epg's events to \n~/kaffeine_dvb_events.tx:"), gb );
- grid->addWidget( lab, 2, 0 );
+ grid->addWidget( lab, 4, 0 );
dumpBtn = new KPushButton( gb );
dumpBtn->setGuiItem( KGuiItem(i18n("Dump"), icon->loadIconSet("filesave", KIcon::Small) ) );
- grid->addWidget( dumpBtn, 2, 1 );
+ grid->addWidget( dumpBtn, 4, 1 );
vb->addWidget( gb );
vb->addItem( new QSpacerItem( 20, 20, QSizePolicy::Ignored, QSizePolicy::Ignored ) );
@@ -1039,6 +1133,8 @@ void DvbConfigDialog::satNumberChanged( int value, int devNum )
rotor1[devNum]->setEnabled( value > 1 );
rotor2[devNum]->setEnabled( value > 2 );
rotor3[devNum]->setEnabled( value > 3 );
+
+ secMini[devNum]->setEnabled( value==2 );
}
@@ -1103,6 +1199,9 @@ void DvbConfigDialog::accept()
switch (dvbConfig->devList.at(i)->type) {
case FE_QPSK: {
dvbConfig->devList.at(i)->numLnb = satNumber[i]->value();
+ dvbConfig->devList.at(i)->secMini = secMini[i]->isChecked();
+ dvbConfig->devList.at(i)->secTwice = secTwice[i]->isChecked();
+ dvbConfig->devList.at(i)->doS2 = doS2[i]->isChecked();
if ( dvbConfig->devList.at(i)->lnb[3].rotorType==0 ) {
dvbConfig->devList.at(i)->lnb[3].source.clear();
dvbConfig->devList.at(i)->lnb[3].source.append(sat3[i]->currentText());
@@ -1140,6 +1239,7 @@ void DvbConfigDialog::accept()
}
dvbConfig->devList.at(i)->source = s;
dvbConfig->devList.at(i)->tuningTimeout = timeoutSpin.at(i)->value();
+ dvbConfig->devList.at(i)->priority = priority.at(i)->value();
}
dvbConfig->recordDir = recordDirLe->text();
@@ -1157,6 +1257,8 @@ void DvbConfigDialog::accept()
dvbConfig->broadcastAddress = broadcastLe->text().stripWhiteSpace();
dvbConfig->broadcastPort = bportSpin->value();
dvbConfig->senderPort = sportSpin->value();
+ dvbConfig->probeMfe = probeMfe->isChecked();
+ dvbConfig->ringBufSize = ringBufSize->value();
dvbConfig->saveConfig();
done( Accepted );
}
@@ -1403,22 +1505,24 @@ RotorConfig::RotorConfig( Device *d, DVBconfig *c, int lnb, QWidget *parent ) :
vb->addWidget( resetBtn );
vb->addItem( new QSpacerItem( 20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed ) );
- grid = new QGridLayout( 0, 1, 1 );
- lab = new QLabel( i18n("13V rotor speed:"), page );
- grid->addWidget( lab, 0, 0 );
- speed13 = new QLineEdit( page );
- speed13->setText( QString().setNum( dev->lnb[lnbNum].speed13v ) );
- grid->addWidget( speed13, 0, 1 );
- lab = new QLabel( i18n("sec./ °"), page );
- grid->addWidget( lab, 0, 2 );
- lab = new QLabel( i18n("18V rotor speed:"), page );
- grid->addWidget( lab, 1, 0 );
- speed18 = new QLineEdit( page );
- speed18->setText( QString().setNum( dev->lnb[lnbNum].speed18v ) );
- grid->addWidget( speed18, 1, 1 );
- lab = new QLabel( i18n("sec./ °"), page );
- grid->addWidget( lab, 1, 2 );
- vb->addLayout( grid );
+ if ( dev->lnb[lnbNum].rotorType!=3 ) {
+ grid = new QGridLayout( 0, 1, 1 );
+ lab = new QLabel( i18n("13V rotor speed:"), page );
+ grid->addWidget( lab, 0, 0 );
+ speed13 = new QLineEdit( page );
+ speed13->setText( QString().setNum( dev->lnb[lnbNum].speed13v ) );
+ grid->addWidget( speed13, 0, 1 );
+ lab = new QLabel( i18n("sec./ °"), page );
+ grid->addWidget( lab, 0, 2 );
+ lab = new QLabel( i18n("18V rotor speed:"), page );
+ grid->addWidget( lab, 1, 0 );
+ speed18 = new QLineEdit( page );
+ speed18->setText( QString().setNum( dev->lnb[lnbNum].speed18v ) );
+ grid->addWidget( speed18, 1, 1 );
+ lab = new QLabel( i18n("sec./ °"), page );
+ grid->addWidget( lab, 1, 2 );
+ vb->addLayout( grid );
+ }
vb->addItem( new QSpacerItem( 20, 20, QSizePolicy::Ignored, QSizePolicy::Ignored ) );
@@ -1462,8 +1566,14 @@ void RotorConfig::accept()
{
QListViewItem *it;
- dev->lnb[lnbNum].speed18v = speed18->text().toDouble();
- dev->lnb[lnbNum].speed13v = speed13->text().toDouble();
+ if ( dev->lnb[lnbNum].rotorType!=3 ) {
+ dev->lnb[lnbNum].speed18v = speed18->text().toDouble();
+ dev->lnb[lnbNum].speed13v = speed13->text().toDouble();
+ }
+ else {
+ dev->lnb[lnbNum].speed18v = 0;
+ dev->lnb[lnbNum].speed13v = 0;
+ }
dev->lnb[lnbNum].source.clear();
dev->lnb[lnbNum].position.clear();
for ( it=listView->firstChild(); it; it=it->nextSibling() ) {
diff --git a/kaffeine/src/input/dvb/dvbconfig.h b/kaffeine/src/input/dvb/dvbconfig.h
index f52b9cc..04f2bf1 100644
--- a/kaffeine/src/input/dvb/dvbconfig.h
+++ b/kaffeine/src/input/dvb/dvbconfig.h
@@ -28,6 +28,7 @@
#include <qtoolbutton.h>
#include <qbuttongroup.h>
#include <qlistview.h>
+#include <qcheckbox.h>
#include <kdialogbase.h>
#include <kpushbutton.h>
@@ -37,6 +38,8 @@
#include <linux/dvb/frontend.h>
+#define MAX_DEVICES 8
+
using namespace KIO;
class MSpinBox : public QSpinBox
@@ -70,6 +73,21 @@ private:
+class MCAMButton : public QPushButton
+{
+ Q_OBJECT
+public:
+ MCAMButton( QWidget *parent, int devNum );
+private slots:
+ void isClicked();
+signals:
+ void clicked( int devnum );
+private:
+ int deviceNumber;
+};
+
+
+
class MComboBox : public QComboBox
{
Q_OBJECT
@@ -116,6 +134,12 @@ public:
bool canAutoscan;
int tuningTimeout;
double usalsLatitude, usalsLongitude;
+ bool hasCAM;
+ int camMaxService;
+ int secMini;
+ int secTwice;
+ int priority;
+ int doS2;
};
@@ -138,6 +162,7 @@ public:
DVBconfig( const QString &dvbConf );
~DVBconfig();
+ void readFirst();
void readConfig();
void saveConfig();
int readDvbChanOrder();
@@ -168,6 +193,8 @@ public:
QValueList<int> splitSizes;
QString defaultCharset;
double usalsLatitude, usalsLongitude;
+ int probeMfe;
+ int ringBufSize;
private:
@@ -183,6 +210,7 @@ private slots:
class KaffeineDvbPlugin;
+class DvbPanel;
class DvbConfigDialog : public KDialogBase
{
@@ -190,34 +218,39 @@ class DvbConfigDialog : public KDialogBase
public:
- DvbConfigDialog( DVBconfig *dc, QWidget *parent, KaffeineDvbPlugin *p );
+ DvbConfigDialog( DvbPanel *pan, DVBconfig *dc, QWidget *parent, KaffeineDvbPlugin *p );
~DvbConfigDialog();
void setSource( QComboBox *box, QString s );
QLineEdit *recordDirLe, *shiftDirLe, *broadcastLe, *filenameFormatLe;
QSpinBox *beginSpin, *endSpin, *instantDurationSpin, *bportSpin, *sportSpin, *sizeFileSpin;
- MSpinBox *satNumber[8];
- QComboBox *sat0[8];
- QComboBox *sat1[8];
- QComboBox *sat2[8];
- QComboBox *sat3[8];
- MPushButton *src0[8];
- MPushButton *src1[8];
- MPushButton *src2[8];
- MPushButton *src3[8];
- MComboBox *rotor0[8];
- MComboBox *rotor1[8];
- MComboBox *rotor2[8];
- MComboBox *rotor3[8];
- MPushButton *lnb0[8];
- MPushButton *lnb1[8];
- MPushButton *lnb2[8];
- MPushButton *lnb3[8];
+ MSpinBox *satNumber[MAX_DEVICES];
+ QCheckBox *secMini[MAX_DEVICES], *secTwice[MAX_DEVICES];
+ QCheckBox *doS2[MAX_DEVICES];
+ QComboBox *sat0[MAX_DEVICES];
+ QComboBox *sat1[MAX_DEVICES];
+ QComboBox *sat2[MAX_DEVICES];
+ QComboBox *sat3[MAX_DEVICES];
+ MPushButton *src0[MAX_DEVICES];
+ MPushButton *src1[MAX_DEVICES];
+ MPushButton *src2[MAX_DEVICES];
+ MPushButton *src3[MAX_DEVICES];
+ MComboBox *rotor0[MAX_DEVICES];
+ MComboBox *rotor1[MAX_DEVICES];
+ MComboBox *rotor2[MAX_DEVICES];
+ MComboBox *rotor3[MAX_DEVICES];
+ MPushButton *lnb0[MAX_DEVICES];
+ MPushButton *lnb1[MAX_DEVICES];
+ MPushButton *lnb2[MAX_DEVICES];
+ MPushButton *lnb3[MAX_DEVICES];
KPushButton *updateBtn, *dumpBtn;
QToolButton *recordDirBtn, *shiftDirBtn, *helpNameBtn;
DVBconfig *dvbConfig;
QComboBox *charsetComb;
QPtrList<QSpinBox> timeoutSpin;
+ QPtrList<QSpinBox> priority;
+ QCheckBox *probeMfe;
+ QSpinBox *ringBufSize;
private slots:
diff --git a/kaffeine/src/input/dvb/dvbout.cpp b/kaffeine/src/input/dvb/dvbout.cpp
index 0ede057..c398707 100644
--- a/kaffeine/src/input/dvb/dvbout.cpp
+++ b/kaffeine/src/input/dvb/dvbout.cpp
@@ -136,19 +136,23 @@ void DVBout::writePmt()
tspmt[0x0a] = 0xc1;
// section # and last section #
tspmt[0x0b] = tspmt[0x0c] = 0x00;
- // PCR PID
- tspmt[0x0d] = channel.vpid>>8; tspmt[0x0e] = channel.vpid&0xff;
+ if ( channel.vpid ) {
+ // PCR PID
+ tspmt[0x0d] = channel.vpid>>8; tspmt[0x0e] = channel.vpid&0xff;
+ }
+ else if ( channel.napid )
+ tspmt[0x0d] = channel.apid[0].pid>>8; tspmt[0x0e] = channel.apid[0].pid&0xff;
// program_info_length == 0
tspmt[0x0f] = 0xf0; tspmt[0x10] = 0x00;
- // Program Map / Video PID
- tspmt[0x11] = channel.vType; // video stream type
- tspmt[0x12] = channel.vpid>>8; tspmt[0x13] = channel.vpid&0xff;
- tspmt[0x14] = 0xf0; tspmt[0x15] = 0x09; // es info length
- // useless info
- tspmt[0x16] = 0x07; tspmt[0x17] = 0x04; tspmt[0x18] = 0x08; tspmt[0x19] = 0x80;
- tspmt[0x1a] = 0x24; tspmt[0x1b] = 0x02; tspmt[0x1c] = 0x11; tspmt[0x1d] = 0x01;
- tspmt[0x1e] = 0xfe;
- off = 0x1e;
+ if ( channel.vpid ) {
+ // Program Map / Video PID
+ tspmt[0x11] = channel.vType; // video stream type
+ tspmt[0x12] = channel.vpid>>8; tspmt[0x13] = channel.vpid&0xff;
+ tspmt[0x14] = 0xf0; tspmt[0x15] = 0x00; // es info length
+ off = 0x15;
+ }
+ else
+ off = 0x10;
// audio pids
i = 0;
for ( i=0; i<channel.napid && i<MAX_AUDIO; i++ ) {
@@ -258,20 +262,19 @@ bool DVBout::doPause( const QString &name ) // called from dvbstream::run()
liveFile.writeBlock( (char*)tspmt, TS_SIZE );
mutex.lock();
haveLive = false;
- mutex.unlock();
- if ( !wait(100) ) {
+ if ( !wait(1000) ) {
terminate();
wait();
}
- mutex.lock();
- haveLive = true;
if ( close( fdPipe )<0 )
perror("close out pipe: ");
else
fprintf(stderr,"out pipe closed\n");
fdPipe = 0;
- mutex.unlock();
+ if ( wDist>0 )
+ liveFile.writeBlock( (char*)(wBuf+(wRead*TS_SIZE*NTS)), TS_SIZE*NTS*wDist );
timeShifting = true;
+ mutex.unlock();
//emit shifting( timeShifting );
}
return true;
@@ -286,7 +289,7 @@ void DVBout::setPatPmt()
-bool DVBout::goLive( const QString &name )
+bool DVBout::goLive( const QString &name, int ringBufSize )
{
if ( fdPipe ) return false;
@@ -299,7 +302,8 @@ bool DVBout::goLive( const QString &name )
writePmt();
if ( !pids.contains(8192) )
patpmt = wpatpmt = true;
- wBuf = new unsigned char[TS_SIZE*NTS*100];
+ wbufSize = ringBufSize*1024*1024/(TS_SIZE*NTS);
+ wBuf = new unsigned char[TS_SIZE*NTS*wbufSize];
if ( !wBuf ) fprintf( stderr, "\nNO WBUF !!!\n\n" );
wRead = wWrite = wDist = 0;
start();
@@ -326,7 +330,7 @@ void DVBout::stopLive()
emit shifting( timeShifting );
}
mutex.unlock();
- if ( !wait(500) ) {
+ if ( !wait(1000) ) {
terminate();
wait();
}
@@ -469,14 +473,16 @@ void DVBout::process( unsigned char *buf, int size )
beginLive = !beginLive;
start();
}
- if ( wDist<95 ) {
+ if ( wDist<wbufSize ) {
memcpy( wBuf+(wWrite*TS_SIZE*NTS), thBuf, TS_SIZE*NTS );
wpatpmt = patpmt;
++wDist;
++wWrite;
- if ( wWrite>99 )
+ if ( wWrite==wbufSize )
wWrite = 0;
- //fprintf(stderr,"WDIST = %d\n",wDist);
+ }
+ else {
+ fprintf(stderr,"Live ringbuffer full!! (%d)\n",wDist);
}
}
else if ( timeShifting ) {
@@ -531,7 +537,7 @@ void DVBout::run()
{
if ( haveLive && fdPipe ) {
while ( haveLive && fdPipe ) {
- if ( wDist>0 ) {
+ if ( wDist>5 ) {
if ( wpatpmt ) {
write( fdPipe, tspat, TS_SIZE );
write( fdPipe, tspmt, TS_SIZE );
@@ -540,11 +546,12 @@ void DVBout::run()
write( fdPipe, wBuf+(wRead*TS_SIZE*NTS), TS_SIZE*NTS );
--wDist;
++wRead;
- if ( wRead>99 )
+ if ( wRead==wbufSize )
wRead = 0;
}
- else
+ else {
usleep( 100 );
+ }
}
return;
}
diff --git a/kaffeine/src/input/dvb/dvbout.h b/kaffeine/src/input/dvb/dvbout.h
index bc97b47..a037c7d 100644
--- a/kaffeine/src/input/dvb/dvbout.h
+++ b/kaffeine/src/input/dvb/dvbout.h
@@ -44,7 +44,7 @@ public:
DVBout( ChannelDesc chan, int anum, int tnum, KaffeineDvbPlugin *p );
~DVBout();
void process( unsigned char *buf, int size );
- bool goLive( const QString &name );
+ bool goLive( const QString &name, int ringBufSize );
void preStopLive();
void stopLive();
bool goBroadcast( Ts2Rtp *r );
@@ -102,6 +102,7 @@ private:
int fileNumber;
QString fileName;
long long int fileMaxSize;
+ int wbufSize;
signals:
diff --git a/kaffeine/src/input/dvb/dvbpanel.cpp b/kaffeine/src/input/dvb/dvbpanel.cpp
index 4d70760..1b62aec 100644
--- a/kaffeine/src/input/dvb/dvbpanel.cpp
+++ b/kaffeine/src/input/dvb/dvbpanel.cpp
@@ -45,7 +45,6 @@
#include <kxmlguifactory.h>
#include <kparts/componentfactory.h>
-#include "kaffeineinput.h"
#include "kaffeinedvbplugin.h"
#include "dvbpanel.h"
#include "channeldesc.h"
@@ -56,6 +55,12 @@
#define CHANICONSIZE 28
+#define MODE_FREE 0
+#define MODE_LIVE 100
+#define MODE_BROADCAST 200
+#define MODE_RECORD 300
+#define MODE_CANTDO 400
+
DIconViewItem::DIconViewItem( DvbPanel *pan, QIconView *parent, const QString &text, const QPixmap &icon )
@@ -1091,7 +1096,7 @@ void DvbPanel::setConfig()
void DvbPanel::showConfigDialog()
{
- int ret;
+ int i, ret;
loop:
if ( !dvbConfig->haveData() ) {
@@ -1104,7 +1109,9 @@ loop:
return;
}
- DvbConfigDialog dlg( dvbConfig, mainWidget, plug );
+ for ( i=0; i<(int)dvb.count(); i++ )
+ dvb.at(i)->probeCam();
+ DvbConfigDialog dlg( this, dvbConfig, mainWidget, plug );
connect( dlg.dumpBtn, SIGNAL(clicked()), this, SLOT(dumpEvents()) );
ret = dlg.exec();
disconnect( dlg.dumpBtn, SIGNAL(clicked()), this, SLOT(dumpEvents()) );
@@ -1112,6 +1119,14 @@ loop:
return;
rtp->setSocket( dvbConfig->broadcastAddress, dvbConfig->broadcastPort, dvbConfig->senderPort );
cleaner->setPaths( dvbConfig->shiftDir, dvbConfig->recordDir );
+ fillChannelList();
+}
+
+
+
+void DvbPanel::camClicked( int devNum )
+{
+ dvb.at(devNum)->showCamDialog();
}
@@ -1124,6 +1139,8 @@ QPtrList<Transponder> DvbPanel::getSourcesStatus()
Transponder t;
for ( i=0; i<(int)dvb.count(); i++ ) {
+ if ( !dvb.at(i)->getPriority() ) // priority==0==don't use
+ continue;
list = dvb.at(i)->getSources();
for ( j=0; j<(int)list.count(); j++ ) {
if ( dvb.at(i)->hasRec() || dvb.at(i)->hasBroadcast() )
@@ -1176,7 +1193,7 @@ void DvbPanel::fillChannelList( ChannelDesc *ch )
}
else if ( currentCategory!="All" && chan->category!=currentCategory )
continue;
- it = new KListViewItem( channelsCb, QString().sprintf("%04d", chan->num), chan->name, chan->tp.source );
+ it = new KListViewItem( channelsCb, QString().sprintf("%05d", chan->num), chan->name, chan->tp.source );
if ( ch && ch==chan )
visible = it;
it->setDragEnabled( true );
@@ -1211,15 +1228,15 @@ void DvbPanel::fillChannelList( ChannelDesc *ch )
DvbStream* DvbPanel::getWorkingDvb( int mode, ChannelDesc *chan )
{
int i, ret;
- QValueList<int> working; // notTuned=0, hasLive=1, hasBroadcast=2, hasRec=3, can'tDoChannel=4
+ QValueList<int> working; // free=0, hasLive=100, hasBroadcast=200, hasRec=300, can'tDoChannel=400
for ( i=0; i<(int)dvb.count(); i++ )
- working.append( 0 );
+ working.append( 100-dvb.at(i)->getPriority() );
// fill in working status
for ( i=0; i<(int)dvb.count(); i++ ) {
- if ( !dvb.at(i)->canSource( chan ) ) {
- working[i] = 4;
+ if ( !dvb.at(i)->canSource( chan ) || working[i]==100 ) {
+ working[i] = MODE_CANTDO;
continue;
}
if ( dvb.at(i)->isTuned() ) {
@@ -1227,14 +1244,18 @@ DvbStream* DvbPanel::getWorkingDvb( int mode, ChannelDesc *chan )
return dvb.at(i); // use that one since it's already tuned on the good mplex
}
else if ( dvb.at(i)->hasRec() )
- working[i] = 3;
+ working[i] += MODE_RECORD;
else if ( dvb.at(i)->hasBroadcast() )
- working[i] = 2;
- else
- working[i] = 1;
+ working[i] += MODE_BROADCAST;
+ else {
+ if ( mode==MODE_LIVE )
+ working[i] += MODE_FREE;
+ else
+ working[i] += MODE_LIVE;
+ }
}
else
- working[i] = 0;
+ working[i] += MODE_FREE;
}
ret = 0;
// search for least working card
@@ -1272,7 +1293,7 @@ void DvbPanel::setBroadcast()
return;
}
- d = getWorkingDvb( 2, list.at(0) );
+ d = getWorkingDvb( MODE_BROADCAST, list.at(0) );
if ( d )
ret = d->canStartBroadcast( live, list.at(0) );
@@ -1316,7 +1337,7 @@ void DvbPanel::checkTimers()
}
if ( !chan )
continue;
- d = getWorkingDvb( 3, chan );
+ d = getWorkingDvb( MODE_RECORD, chan );
live = false;
if ( d )
ret = d->canStartTimer( live, chan );
@@ -1826,7 +1847,7 @@ void DvbPanel::playLastChannel()
QTimer::singleShot( 2000, this, SLOT(playLastChannel()) );
return;
}
- d = getWorkingDvb( 2, list.at(0) );
+ d = getWorkingDvb( MODE_BROADCAST, list.at(0) );
if ( d )
ret = d->canStartBroadcast( live, list.at(0) );
else
@@ -1880,7 +1901,7 @@ void DvbPanel::next()
QListViewItem* nextItem;
- QListViewItem* playingItem = channelsCb->findItem( QString().sprintf("%04d", dvbConfig->lastChannel), 0 );
+ QListViewItem* playingItem = channelsCb->findItem( QString().sprintf("%05d", dvbConfig->lastChannel), 0 );
if ( !playingItem == 0 ) // yes, it's in the current category
{
@@ -1906,7 +1927,7 @@ void DvbPanel::previous()
QListViewItem* prevItem;
- QListViewItem* playingItem = channelsCb->findItem( QString().sprintf("%04d", dvbConfig->lastChannel), 0 );
+ QListViewItem* playingItem = channelsCb->findItem( QString().sprintf("%05d", dvbConfig->lastChannel), 0 );
if ( !playingItem == 0 ) // yes, it's in the current category
{
@@ -1927,19 +1948,14 @@ void DvbPanel::previous()
void DvbPanel::dvbZap( ChannelDesc *chan )
{
int i;
- DvbStream *d=0;
+ DvbStream *d;
if ( currentFifo.isEmpty() || isTuning )
return;
isTuning = true;
emit setTimeShiftFilename( "" );
- for ( i=0; i<(int)dvb.count(); i++ ) {
- if ( dvb.at(i)->getCurrentTransponder()==chan->tp ) {
- d = dvb.at(i);
- break;
- }
- }
+ d = getWorkingDvb( MODE_LIVE, chan );
for ( i=0; i<(int)dvb.count(); i++ ) {
if ( dvb.at(i)->hasLive() ) {
dvb.at(i)->preStopLive();
@@ -1973,40 +1989,20 @@ void DvbPanel::finalZap( DvbStream *d, ChannelDesc *chan )
{
QString s, t;
int i;
- DvbStream *d1=d, *d2=0;
emit setCurrentPlugin( this );
fprintf( stderr, "Tuning to: %s / autocount: %lu\n", chan->name.latin1(), autocount );
QTime tm;
tm.start();
- if ( !d1 ) {
- for ( i=0; i<(int)dvb.count(); i++ ) {
- if ( !dvb.at(i)->canSource( chan ) )
- continue;
- if ( dvb.at(i)->isTuned() ) {
- if ( dvb.at(i)->getCurrentTransponder()==chan->tp ) {
- d1 = dvb.at(i);
- break;
- }
- else d2 = dvb.at(i);
- }
- else {
- d1 = dvb.at(i);
- break;
- }
- }
- if ( !d1 && d2 )
- d1 = d2;
- }
- if ( !d1 ) {
+ if ( !d ) {
emit dvbStop();
isTuning = false;
return;
}
- int ret = d1->goLive( chan, currentFifo );
+ int ret = d->goLive( chan, currentFifo, dvbConfig->ringBufSize );
switch ( ret ) {
case DvbStream::ErrIsRecording :
@@ -2045,7 +2041,7 @@ void DvbPanel::finalZap( DvbStream *d, ChannelDesc *chan )
resetSearch();
}
- if ( d1->liveIsRecording() )
+ if ( d->liveIsRecording() )
recordBtn->setOn( true );
else
recordBtn->setOn( false );
@@ -2255,6 +2251,8 @@ bool DvbPanel::getChannelList()
case 67 : chan->tp.coderateH = FEC_6_7; break;
case 78 : chan->tp.coderateH = FEC_7_8; break;
case 89 : chan->tp.coderateH = FEC_8_9; break;
+ case 35 : chan->tp.coderateH = FEC_3_5; break;
+ case 910 : chan->tp.coderateH = FEC_9_10; break;
case -1 : chan->tp.coderateH = FEC_AUTO;
}
s = s.right( s.length()-pos-1 );
@@ -2275,6 +2273,9 @@ bool DvbPanel::getChannelList()
case 256 : chan->tp.modulation = QAM_256; break;
case 108 : chan->tp.modulation = VSB_8; break;
case 116 : chan->tp.modulation = VSB_16; break;
+ case 1000 : chan->tp.modulation = PSK_8; break;
+ case 1001 : chan->tp.modulation = APSK_16; break;
+ case 1003 : chan->tp.modulation = DQPSK; break;
case -1 : chan->tp.modulation = QAM_AUTO;
}
s = s.right( s.length()-pos-1 );
@@ -2289,6 +2290,8 @@ bool DvbPanel::getChannelList()
case 67 : chan->tp.coderateL = FEC_6_7; break;
case 78 : chan->tp.coderateL = FEC_7_8; break;
case 89 : chan->tp.coderateL = FEC_8_9; break;
+ case 35 : chan->tp.coderateH = FEC_3_5; break;
+ case 910 : chan->tp.coderateH = FEC_9_10; break;
case -1 : chan->tp.coderateL = FEC_AUTO;
}
s = s.right( s.length()-pos-1 );
@@ -2356,6 +2359,17 @@ bool DvbPanel::getChannelList()
s = s.right( s.length()-pos-1 );
pos = s.find("|");
chan->tp.nid = s.left(pos).toUShort();
+ s = s.right( s.length()-pos-1 );
+ pos = s.find("|");
+ switch ( s.left(pos).toInt() ) {
+ case 20 : chan->tp.rolloff = ROLLOFF_20; break;
+ case 25 : chan->tp.rolloff = ROLLOFF_25; break;
+ case 35 : chan->tp.rolloff = ROLLOFF_35; break;
+ case -1 : chan->tp.rolloff = ROLLOFF_AUTO;
+ }
+ s = s.right( s.length()-pos-1 );
+ pos = s.find("|");
+ chan->tp.S2 = s.left(pos).toInt();
if ( chan->tp.source.isEmpty() ) {
delete chan;
@@ -2363,7 +2377,7 @@ bool DvbPanel::getChannelList()
}
chan->pix.load( dvbConfig->dvbConfigIconsDir+chan->name );
- it = new KListViewItem( channelsCb, QString().sprintf("%04d", chan->num), chan->name, chan->tp.source );
+ it = new KListViewItem( channelsCb, QString().sprintf("%05d", chan->num), chan->name, chan->tp.source );
it->setDragEnabled( true );
if ( !chan->pix.isNull() )
it->setPixmap( 1, chan->pix );
@@ -2467,6 +2481,8 @@ bool DvbPanel::saveChannelList()
case FEC_6_7 : tt<< "67|"; break;
case FEC_7_8 : tt<< "78|"; break;
case FEC_8_9 : tt<< "89|"; break;
+ case FEC_3_5 : tt<< "35|"; break;
+ case FEC_9_10 : tt<< "910|"; break;
case FEC_AUTO : tt<< "-1|";
}
switch ( chan->tp.inversion ) {
@@ -2483,6 +2499,9 @@ bool DvbPanel::saveChannelList()
case QAM_256 : tt<< "256|"; break;
case VSB_8 : tt<< "108|"; break;
case VSB_16 : tt<< "116|"; break;
+ case PSK_8 : tt<< "1000|"; break;
+ case APSK_16 : tt<< "1001|"; break;
+ case DQPSK : tt<< "1003|"; break;
case QAM_AUTO : tt<< "-1|";
}
switch ( chan->tp.coderateL ) {
@@ -2495,6 +2514,8 @@ bool DvbPanel::saveChannelList()
case FEC_6_7 : tt<< "67|"; break;
case FEC_7_8 : tt<< "78|"; break;
case FEC_8_9 : tt<< "89|"; break;
+ case FEC_3_5 : tt<< "35|"; break;
+ case FEC_9_10 : tt<< "910|"; break;
case FEC_AUTO : tt<< "-1|";
}
switch ( chan->tp.bandwidth ) {
@@ -2533,7 +2554,15 @@ bool DvbPanel::saveChannelList()
}
tt<< "|";
tt<< chan->category+"|";
- tt<< s.setNum(chan->tp.nid)+"|\n";
+ tt<< s.setNum(chan->tp.nid)+"|";
+ switch ( chan->tp.rolloff ) {
+ case ROLLOFF_20 : tt<< "20|"; break;
+ case ROLLOFF_25 : tt<< "25|"; break;
+ case ROLLOFF_35 : tt<< "35|"; break;
+ case ROLLOFF_AUTO : tt<< "-1|";
+ }
+ tt<< s.setNum(chan->tp.S2)+"|";
+ tt<< "\n";
}
ret = true;
f.close();
diff --git a/kaffeine/src/input/dvb/dvbpanel.h b/kaffeine/src/input/dvb/dvbpanel.h
index 5545040..444e641 100644
--- a/kaffeine/src/input/dvb/dvbpanel.h
+++ b/kaffeine/src/input/dvb/dvbpanel.h
@@ -42,13 +42,13 @@
#include "ts2rtp.h"
#include "cleaner.h"
#include "dvbevents.h"
+#include "kaffeineinput.h"
class ChannelDesc;
class DvbStream;
class DvbPanel;
-class KaffeineInput;
class KaffeineDvbPlugin;
@@ -153,6 +153,7 @@ public slots:
void dvbNewTimer( QString name, QString channel, QString datetime, QString duration );
int getSNR( int device );
void diskStatus();
+ void camClicked( int devNum );
private:
diff --git a/kaffeine/src/input/dvb/dvbsi.cpp b/kaffeine/src/input/dvb/dvbsi.cpp
index 395d796..db29091 100644
--- a/kaffeine/src/input/dvb/dvbsi.cpp
+++ b/kaffeine/src/input/dvb/dvbsi.cpp
@@ -2,6 +2,7 @@
* dvbsi.cpp
*
* Copyright (C) 2003-2007 Christophe Thommeret <hftom@free.fr>
+ * Copyright (C) 2008 Devin Heitmueller <devin.heitmueller@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -30,7 +31,22 @@
#define TIMER_EVENT_SCAN_END 100
+// These values are taken from ATSC A/65C Sec 5
+#define PSIP_BASE_PID 0x1ffb
+// This shouldn't be necessary, but at least the HVR-950 doesn't seem to
+// find them in the time specified in the spec (needs more investigation)
+#define CYCLE_TIME_FUDGEFACTOR 1000
+
+// These values are taken from ATSC A/65C Sec 7.1
+// (all values in ms)
+#define PSIP_MAX_CYCLE_TIME_MGT 150 + CYCLE_TIME_FUDGEFACTOR
+#define PSIP_MAX_CYCLE_TIME_VCT 400 + CYCLE_TIME_FUDGEFACTOR
+
+// These values are taken from ATSC A/65C Sec 4.1
+#define PSIP_TABLE_TYPE_MGT 0xc7
+#define PSIP_TABLE_TYPE_TVCT 0xc8
+#define PSIP_TABLE_TYPE_CVCT 0xc9
NitSection::NitSection( QPtrList<Transponder> *tp, bool *end, bool *ok, int anum, int tnum ) : KaffeineDVBsection( anum, tnum )
{
@@ -158,6 +174,9 @@ bool NitSection::tableNIT( unsigned char* buf )
fprintf(stderr," Found frequency list.\n");
freqListDesc( buf, trans );
break;
+ case 0x79 :
+ S2satelliteDesc( buf, trans );
+ break;
default :
break;
}
@@ -211,18 +230,53 @@ void NitSection::satelliteDesc( unsigned char* buf, Transponder *trans )
trans->pol = 'v';
else
trans->pol = 'h';
+ switch ( getBits(buf,70,2) ) {
+ case 0 : trans->modulation = QAM_AUTO; break;
+ case 1 : trans->modulation = QPSK; break;
+ case 2 : trans->modulation = PSK_8; break;
+ case 3 : trans->modulation = QAM_16; break;
+ }
s = t.setNum( getBits(buf,72,28), 16 );
trans->sr = s.toInt();
trans->sr /=10;
switch ( getBits(buf,100,4) ) {
+ case 0 : trans->coderateH = FEC_AUTO; break;
case 1 : trans->coderateH = FEC_1_2; break;
case 2 : trans->coderateH = FEC_2_3; break;
case 3 : trans->coderateH = FEC_3_4; break;
case 4 : trans->coderateH = FEC_5_6; break;
case 5 : trans->coderateH = FEC_7_8; break;
case 6 : trans->coderateH = FEC_8_9; break;
- case 7 : trans->coderateH = FEC_NONE; break;
+ case 7 : trans->coderateH = FEC_3_5; break;
+ case 8 : trans->coderateH = FEC_4_5; break;
+ case 9 : trans->coderateH = FEC_9_10; break;
+ case 15 : trans->coderateH = FEC_NONE; break;
}
+ if ( getBits(buf,69,1) ) {
+ fprintf(stderr,"!!!!!!!!!!!!!!!!!! Found S2 MODULATION SYSTEM !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ trans->S2 = 1;
+ switch ( getBits(buf,67,2) ) {
+ case 0 : trans->rolloff = ROLLOFF_35; break;
+ case 1 : trans->rolloff = ROLLOFF_25; break;
+ case 2 : trans->rolloff = ROLLOFF_20; break;
+ }
+ }
+}
+
+
+
+void NitSection::S2satelliteDesc( unsigned char* buf, Transponder *trans )
+{
+ fprintf(stderr,"!!!!!!!!!!!!!!!!!! Found S2 DESCRIPTOR !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ int scrambling_sequence_selector = getBits(buf,16,1);
+ int multiple_input_stream_flag = getBits(buf,17,1);
+ int backwards_compatibility_indicator = getBits(buf,18,1);
+ int scrambling_sequence_index = 0;
+ if ( scrambling_sequence_selector )
+ scrambling_sequence_index = getBits(buf,30,18);
+ int input_stream_identifier = 0;
+ if ( multiple_input_stream_flag )
+ input_stream_identifier = getBits(buf,48,8);
}
@@ -246,13 +300,17 @@ void NitSection::cableDesc( unsigned char* buf, Transponder *trans )
trans->sr = s.toInt();
trans->sr /=10;
switch ( getBits(buf,100,4) ) {
+ case 0 : trans->coderateH = FEC_AUTO; break;
case 1 : trans->coderateH = FEC_1_2; break;
case 2 : trans->coderateH = FEC_2_3; break;
case 3 : trans->coderateH = FEC_3_4; break;
case 4 : trans->coderateH = FEC_5_6; break;
case 5 : trans->coderateH = FEC_7_8; break;
case 6 : trans->coderateH = FEC_8_9; break;
- case 7 : trans->coderateH = FEC_NONE; break;
+ case 7 : trans->coderateH = FEC_3_5; break;
+ case 8 : trans->coderateH = FEC_4_5; break;
+ case 9 : trans->coderateH = FEC_9_10; break;
+ case 15 : trans->coderateH = FEC_NONE; break;
}
}
@@ -456,6 +514,7 @@ bool DVBsi::tablePMT( unsigned char* buf )
while ( length>4 ) {
audio=ac3=false;
+ lang="";
type = getBits(buf,0,8);
pid = getBits(buf,11,13);
if ( type==1/*mpeg1*/ || type==2/*mpeg2*/ || type==16/*mpeg4*/ || type==27/*h264*/ ) {
@@ -466,6 +525,11 @@ bool DVBsi::tablePMT( unsigned char* buf )
if ( type==3 || type==4 ) {
audio = true;
}
+ if (type == 0x81) {
+ // AC3 was added in ATSC A/52B (See A3.1 "Stream Type")
+ audio = true;
+ ac3 = true;
+ }
loop = getBits(buf,28,12);
buf +=5;
length -=(5+loop);
@@ -499,6 +563,7 @@ bool DVBsi::tablePMT( unsigned char* buf )
}
break;
case 0x6a :
+ case 0x81 :
audio = true;
ac3 = true;
break;
@@ -637,7 +702,204 @@ bool DVBsi::getSection( int pid, int tid, int timeout, int sid )
return true;
}
+bool DVBsi::parseMGT( int pid, int tid, int timeout, int sid )
+{
+ unsigned char buf[4096];
+ int n=0;
+ int skip=0;
+ bool vct_found = false;
+
+ fprintf(stderr, "parseMGT called for 0x%02x 0x%02x\n", pid, tid);
+ if ( !setFilter( pid, tid, timeout ) )
+ return false;
+
+ if ( poll(pf,1,timeout)>0 ){
+ if ( pf[0].revents & POLLIN ){
+ n = read( fdDemux, buf, 4096 );
+ skip = 0;
+ }
+ else
+ skip++;
+ }
+ else
+ skip++;
+
+ if ( skip || n<4 ) {
+ fprintf(stderr,"\nInvalid section length or timeout: pid=%d\n\n", pid);
+ stopFilter();
+ return false;
+ }
+
+ // Parse the Master Guide Table Section
+ unsigned int protocol_version = getBits(buf,64,8);
+ unsigned int tables_defined = getBits(buf,72,16);
+ fprintf(stderr, "protocol_version = %d\n", protocol_version);
+ fprintf(stderr, "tables_defined = %d\n", tables_defined);
+
+ // Now let's go through the table entries....
+ unsigned char *t_entry = &buf[88/8];
+ for (unsigned int t = 0; t < tables_defined; t++) {
+ unsigned int table_type;
+ unsigned int table_pid;
+ unsigned int table_version_number;
+ unsigned int table_number_bytes;
+ unsigned int table_number_des_length;
+ table_type = getBits(t_entry, 0, 16);
+ table_pid = getBits(t_entry, 19, 13);
+ table_version_number = getBits(t_entry, 35, 5);
+ table_number_bytes = getBits(t_entry, 40, 32);
+ table_number_des_length = getBits(t_entry, 76, 12);
+ fprintf(stderr,
+ "MGT entry type=0x%04x pid=0x%04x ver=%d sz=%d\n",
+ table_type, table_pid, table_version_number,
+ table_number_bytes);
+
+ if (table_type == 0x0000 || table_type == 0x0001) {
+ // TVCT table found
+ vct_table = PSIP_TABLE_TYPE_TVCT;
+ vct_found = true;
+ } else if (table_type == 0x0002 ||
+ table_type == 0x0003) {
+ // CVCT table found
+ vct_table = PSIP_TABLE_TYPE_CVCT;
+ vct_found = true;
+ }
+ t_entry += (11 + table_number_des_length);
+ }
+
+ stopFilter();
+ return vct_found;
+}
+
+bool DVBsi::parseVCT( int pid, int tid, int timeout, int sid )
+{
+ unsigned char buf[4096];
+ int n=0;
+ int skip=0;
+
+ fprintf(stderr, "parseVCT called for 0x%02x 0x%02x\n", pid, tid);
+ if ( !setFilter( pid, tid, timeout ) )
+ return false;
+
+ if ( poll(pf,1,timeout)>0 ){
+ if ( pf[0].revents & POLLIN ){
+ n = read( fdDemux, buf, 4096 );
+ skip = 0;
+ }
+ else
+ skip++;
+ }
+ else
+ skip++;
+
+ if ( skip || n<4 ) {
+ fprintf(stderr,"\nInvalid section length or timeout: pid=%d\n\n", pid);
+ stopFilter();
+ return false;
+ }
+
+ // Parse the Virtual Channel Table Section
+ unsigned int protocol_version = getBits(buf,64,8);
+ unsigned int num_channels = getBits(buf,72,8);
+ fprintf(stderr, "protocol_version = %d\n", protocol_version);
+ fprintf(stderr, "num_channels = %d\n", num_channels);
+
+ // Now let's go through the table entries....
+ unsigned char *t_entry = &buf[80/8];
+ for (unsigned int t = 0; t < num_channels; t++) {
+ char short_name[8];
+ unsigned int major_channel_num;
+ unsigned int minor_channel_num;
+ unsigned int modulation_mode;
+ unsigned int channel_tsid;
+ unsigned int program_number;
+ unsigned int access_controlled;
+ unsigned int hidden;
+ unsigned int service_type;
+ unsigned int source_id;
+ unsigned int reserved;
+ unsigned int descriptors_length;
+
+ // Short name
+ // Yes, I need a real UCS-2 to UTF-8 conversion here...
+ memset(short_name, 0, sizeof(short_name));
+ snprintf(short_name, sizeof(short_name), "%c%c%c%c%c%c%c",
+ t_entry[1],t_entry[3],t_entry[5],t_entry[7],
+ t_entry[9],t_entry[11],t_entry[13]);
+ reserved = getBits(t_entry, 112, 4);
+ major_channel_num = getBits(t_entry, 116, 10);
+ minor_channel_num = getBits(t_entry, 126, 10);
+ modulation_mode = getBits(t_entry, 136, 8);
+ channel_tsid = getBits(t_entry, 176, 16);
+ program_number = getBits(t_entry, 192, 16);
+ access_controlled = getBits(t_entry, 210, 1);
+ hidden = getBits(t_entry, 211, 1);
+ service_type = getBits(t_entry, 218, 6);
+ source_id = getBits(t_entry, 224, 16);
+ reserved = getBits(t_entry, 240, 6);
+ descriptors_length = getBits(t_entry, 246, 10);
+
+ fprintf(stderr, "short name=%s\n", short_name);
+ fprintf(stderr, "reserved=0x%04x\n", reserved);
+ fprintf(stderr, "major=%d\n", major_channel_num);
+ fprintf(stderr, "minor=%d\n", minor_channel_num);
+ fprintf(stderr, "modulation mode=0x%02x\n", modulation_mode);
+ fprintf(stderr, "channel_tsid=0x%04x\n", channel_tsid);
+ fprintf(stderr, "program_number=0x%04x\n", program_number);
+ fprintf(stderr, "access_controlled=0x%01x\n", access_controlled);
+ fprintf(stderr, "hidden=0x%01x\n", hidden);
+ fprintf(stderr, "service_type=0x%02x\n", service_type);
+ fprintf(stderr, "source_id=0x%04x\n", source_id);
+ fprintf(stderr, "des length=%d\n", descriptors_length);
+
+ ChannelDesc *desc = new ChannelDesc();
+ desc->tp.tsid = channel_tsid;
+ desc->name = QString("%1-%2 %3").arg(major_channel_num).arg(minor_channel_num).arg(short_name);
+ desc->sid = program_number;
+ if (access_controlled == 1)
+ desc->fta = 1;
+ else
+ desc->fta = 0; // 0 for free
+
+ // Algorithm taken from ATSC A/65C Sec 4.2
+ // However, the algorithm doesn't appear correct, as it
+ // truncates out data. For example, both 68-1 and 4-1 would
+ // yield the same one_part_number
+ desc->num = (major_channel_num << 10) + minor_channel_num;
+ fprintf(stderr, "channel num=%d\n", desc->num);
+
+ // ATSC A/65C Sec 6.3.1 Table 6.7
+ if (service_type == 0x01) {
+ // Analog television (not supported)
+ } else if (service_type == 0x02) {
+ // ATSC Video
+ desc->type = 1;
+ } else if (service_type == 0x03) {
+ // ATSC Audio
+ desc->type = 2;
+ } else if (service_type == 0x02) {
+ // ATSC Data only service (not supported)
+ } else if (service_type > 0x05 && service_type < 0x3f) {
+ // Reserved (not supported)
+ } else {
+ // Unknown
+ }
+
+ // Now add the new channel to the list (if supported)
+ if ((desc->type == 1 || desc->type == 2) && hidden == 0) {
+ channels.append( desc );
+ } else {
+ fprintf(stderr, "Not adding channel\n");
+ delete desc;
+ }
+
+ // Advance to the next entry
+ t_entry += (32 + descriptors_length);
+ }
+ stopFilter();
+ return true;
+}
void DVBsi::stop()
{
@@ -701,7 +963,24 @@ void DVBsi::timerEvent( QTimerEvent *e )
}
}
+// See ATSC standard A/65c for info on PSIP and what all these acronyms are...
+bool DVBsi::handle_atsc_transponder() {
+ // Loop through the MGT to get the list of PIDS for virtual channels
+ if (parseMGT(PSIP_BASE_PID, PSIP_TABLE_TYPE_MGT,
+ PSIP_MAX_CYCLE_TIME_MGT) == false) {
+ // We couldn't find the MGT
+ fprintf(stderr, "Could not find MGT in stream. Cannot continue\n");
+ return false;
+ };
+ // Now look at the TVCT for info on the individual channels found
+ if (parseVCT(PSIP_BASE_PID, vct_table,
+ PSIP_MAX_CYCLE_TIME_VCT) == false) {
+ fprintf(stderr, "Could not parse VCT in stream. Cannot continue\n");
+ return false;
+ }
+ return true;
+}
void DVBsi::run()
{
@@ -744,12 +1023,22 @@ void DVBsi::run()
indexChannels = j;
fprintf(stderr,"Transponders: %d/%d\n", i+1, transponders.count() );
- if ( scanMode ) {
- nitEnded = false;
- ns = new NitSection( &transponders, &nitEnded, &ok, adapter, tuner ); //NIT
+ fprintf(stderr,"scanMode=%d\n", scanMode);
+ if ( chan.tp.type == FE_ATSC ) {
+ // Separate out the ATSC scanning so that we
+ // don't interfere with existing DVB support
+ if (!handle_atsc_transponder())
+ continue;
+ }
+ else {
+ printf("it's dvb %d!\n", chan.tp.type);
+ if ( scanMode ) {
+ nitEnded = false;
+ ns = new NitSection( &transponders, &nitEnded, &ok, adapter, tuner ); //NIT
+ }
+
+ getSection( 0x11, 0x42 ); //SDT
}
- if ( !getSection( 0x11, 0x42 ) ) //SDT
- continue;
if ( !isRunning ) {
out();
return;
@@ -822,7 +1111,7 @@ void DVBsi::run()
}
-
+// !!!! only there for debugging !!!!!!!!!!
bool DVBsi::listChannels()
{
QString s,t;
diff --git a/kaffeine/src/input/dvb/dvbsi.h b/kaffeine/src/input/dvb/dvbsi.h
index df1f6e7..1146f85 100644
--- a/kaffeine/src/input/dvb/dvbsi.h
+++ b/kaffeine/src/input/dvb/dvbsi.h
@@ -36,6 +36,7 @@ public:
bool getSection( int pid, int tid, int timeout=5000 );
bool tableNIT( unsigned char* buf );
void satelliteDesc( unsigned char* buf, Transponder *trans );
+ void S2satelliteDesc( unsigned char* buf, Transponder *trans );
void cableDesc( unsigned char* buf, Transponder *trans );
void terrestrialDesc( unsigned char* buf, Transponder *trans );
void freqListDesc( unsigned char* buf, Transponder *trans );
@@ -66,6 +67,11 @@ public:
bool tablePMT( unsigned char* buf );
void serviceDesc( unsigned char* buf, ChannelDesc *desc );
+ // ATSC related methods
+ virtual bool handle_atsc_transponder();
+ virtual bool parseMGT( int pid, int tid, int timeout=5000, int sid=0 );
+ virtual bool parseVCT( int pid, int tid, int timeout=5000, int sid=0 );
+
QPtrList<ChannelDesc> channels;
QPtrList<Transponder> transponders;
DvbStream *dvb;
@@ -90,6 +96,9 @@ private:
int scanMode;
NitSection *ns;
+ /* ATSC related */
+ int vct_table;
+
signals:
void end( bool );
diff --git a/kaffeine/src/input/dvb/dvbstream.cpp b/kaffeine/src/input/dvb/dvbstream.cpp
index 302c0d0..77bee5c 100644
--- a/kaffeine/src/input/dvb/dvbstream.cpp
+++ b/kaffeine/src/input/dvb/dvbstream.cpp
@@ -43,6 +43,7 @@
#include <klocale.h>
#include <kapplication.h>
+#include <kmessagebox.h>
#include "dvbstream.h"
#include "dvbevents.h"
@@ -100,13 +101,23 @@ void DvbStream::probeCam()
int ci_type=0;
if ( camProbed )
return;
- if ( (ci_type=DvbCam::probe( dvbDevice->adapter, 0 ))>0 )
- cam = new DvbCam( dvbDevice->adapter, 0, dvbDevice->tuner, ci_type );
+ if ( (ci_type=DvbCam::probe( dvbDevice->adapter, 0 ))>0 ) {
+ cam = new DvbCam( dvbDevice->adapter, 0, dvbDevice->tuner, ci_type, dvbDevice->camMaxService );
+ dvbDevice->hasCAM = true;
+ }
camProbed = true;
}
+void DvbStream::showCamDialog()
+{
+ if ( cam )
+ dvbDevice->camMaxService = cam->showCamDialog();
+}
+
+
+
QStringList DvbStream::getSources( bool all )
{
if ( !all ) {
@@ -143,6 +154,8 @@ bool DvbStream::canSource( ChannelDesc *chan )
else
return false;
}
+ if ( chan->tp.S2 && !dvbDevice->doS2 )
+ return false;
int i;
for ( i=0; i<dvbDevice->numLnb; i++ ) {
if ( dvbDevice->lnb[i].source.contains(chan->tp.source) )
@@ -153,6 +166,13 @@ bool DvbStream::canSource( ChannelDesc *chan )
+int DvbStream::getPriority()
+{
+ return dvbDevice->priority;
+}
+
+
+
int DvbStream::getSatPos( const QString &src )
{
int i;
@@ -174,7 +194,7 @@ bool DvbStream::openFe()
fprintf(stderr,"openFe: fdFrontend != 0\n");
return false;
}
- fdFrontend = open( frontendName.ascii(), O_RDWR );
+ fdFrontend = open( frontendName.ascii(), O_RDWR /*| O_NONBLOCK*/ );
if ( fdFrontend<0 ) {
perror("openFe:");
fdFrontend = 0;
@@ -308,7 +328,6 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
{
unsigned long lof=0;
int res, hiband=0;
- struct dvb_frontend_parameters feparams;
struct dvb_frontend_info fe_info;
fe_status_t status;
unsigned long freq=chan->tp.freq;
@@ -317,6 +336,14 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
int rotorMove = 0;
int loop=0, i;
+ struct dtv_property cmdargs[20];
+ struct dtv_properties cmdseq;
+ int inversion;
+ int bandwidth;
+
+ if ( chan->tp.S2 && !dvbDevice->doS2 )
+ return false;
+
closeFe();
if ( !openFe() )
return false;
@@ -333,18 +360,45 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
freq*=1000;
srate*=1000;
+ QTime t1 = QTime::currentTime();
+
+ if ( chan->tp.inversion==INVERSION_AUTO ) {
+ if ( fe_info.caps & FE_CAN_INVERSION_AUTO )
+ inversion = chan->tp.inversion;
+ else {
+ fprintf(stderr,"Can NOT inversion_auto\n");
+ inversion = INVERSION_OFF;
+ }
+ }
+ else
+ inversion=chan->tp.inversion;
+
switch( fe_info.type ) {
case FE_OFDM : {
+ QString s = fe_info.name;
+ //if ( s.contains("TerraTec/qanu USB2.0 Highspeed DVB-T Receiver") ) // cinergyT2 hack
+ // freq+=167000;
if (freq < 1000000)
freq*=1000UL;
- feparams.frequency=freq;
- feparams.u.ofdm.bandwidth=chan->tp.bandwidth;
- feparams.u.ofdm.code_rate_HP=chan->tp.coderateH;
- feparams.u.ofdm.code_rate_LP=chan->tp.coderateL;
- feparams.u.ofdm.constellation=chan->tp.modulation;
- feparams.u.ofdm.transmission_mode=chan->tp.transmission;
- feparams.u.ofdm.guard_interval=chan->tp.guard;
- feparams.u.ofdm.hierarchy_information=chan->tp.hierarchy;
+ cmdargs[0].cmd = DTV_DELIVERY_SYSTEM; cmdargs[0].u.data = SYS_DVBT;
+ cmdargs[1].cmd = DTV_FREQUENCY; cmdargs[1].u.data = freq;
+ cmdargs[2].cmd = DTV_MODULATION; cmdargs[2].u.data = chan->tp.modulation;
+ cmdargs[3].cmd = DTV_CODE_RATE_HP; cmdargs[3].u.data = chan->tp.coderateH;
+ cmdargs[4].cmd = DTV_CODE_RATE_LP; cmdargs[4].u.data = chan->tp.coderateL;
+ cmdargs[5].cmd = DTV_GUARD_INTERVAL; cmdargs[5].u.data = chan->tp.guard;
+ cmdargs[6].cmd = DTV_TRANSMISSION_MODE; cmdargs[6].u.data = chan->tp.transmission;
+ cmdargs[7].cmd = DTV_HIERARCHY; cmdargs[7].u.data = chan->tp.hierarchy;
+ if ( chan->tp.bandwidth==BANDWIDTH_8_MHZ )
+ bandwidth = 8000000;
+ else if ( chan->tp.bandwidth==BANDWIDTH_7_MHZ )
+ bandwidth = 7000000;
+ else if ( chan->tp.bandwidth==BANDWIDTH_6_MHZ )
+ bandwidth = 6000000;
+ cmdargs[8].cmd = DTV_BANDWIDTH_HZ; cmdargs[8].u.data = bandwidth;
+ cmdargs[9].cmd = DTV_INVERSION; cmdargs[9].u.data = inversion;
+ cmdargs[10].cmd = DTV_TUNE;
+ cmdseq.num = 11;
+ cmdseq.props = cmdargs;
fprintf(stderr,"tuning DVB-T to %lu Hz\n", freq);
fprintf(stderr,"inv:%d bw:%d fecH:%d fecL:%d mod:%d tm:%d gi:%d hier:%d\n", chan->tp.inversion,
chan->tp.bandwidth, chan->tp.coderateH, chan->tp.coderateL, chan->tp.modulation,
@@ -352,11 +406,16 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
break;
}
case FE_QAM : {
+ cmdargs[0].cmd = DTV_DELIVERY_SYSTEM; cmdargs[0].u.data = SYS_DVBC_ANNEX_AC;
+ cmdargs[1].cmd = DTV_FREQUENCY; cmdargs[1].u.data = freq;
+ cmdargs[2].cmd = DTV_MODULATION; cmdargs[2].u.data = chan->tp.modulation;
+ cmdargs[3].cmd = DTV_SYMBOL_RATE; cmdargs[3].u.data = srate;
+ cmdargs[4].cmd = DTV_INNER_FEC; cmdargs[4].u.data = chan->tp.coderateH;
+ cmdargs[5].cmd = DTV_INVERSION; cmdargs[5].u.data = inversion;
+ cmdargs[6].cmd = DTV_TUNE;
+ cmdseq.num = 7;
+ cmdseq.props = cmdargs;
fprintf(stderr,"tuning DVB-C to %lu\n", freq);
- feparams.frequency=freq;
- feparams.u.qam.symbol_rate = srate;
- feparams.u.qam.fec_inner = chan->tp.coderateH;
- feparams.u.qam.modulation = chan->tp.modulation;
fprintf(stderr,"inv:%d sr:%lu fecH:%d mod:%d\n", chan->tp.inversion,
srate, chan->tp.coderateH, chan->tp.modulation );
break;
@@ -384,51 +443,78 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
lof = (dvbDevice->lnb[lnbPos].loFreq*1000);
}
if ( freq<lof )
- feparams.frequency = ( lof-freq );
+ freq = ( lof-freq );
else
- feparams.frequency = ( freq-lof );
+ freq = ( freq-lof );
}
- else
- feparams.frequency=freq;
-
- feparams.u.qpsk.symbol_rate=srate;
- feparams.u.qpsk.fec_inner=chan->tp.coderateH;
- fprintf(stderr,"inv:%d fecH:%d\n", chan->tp.inversion, chan->tp.coderateH );
+ fprintf(stderr,"inv:%d fecH:%d mod:%d\n", chan->tp.inversion, chan->tp.coderateH, chan->tp.modulation );
if ( setDiseqc( lnbPos, chan, hiband, rotorMove, dvr )!=0 ) {
closeFe();
return false;
}
+ fprintf( stderr, "Diseqc settings time = %d ms\n", t1.msecsTo( QTime::currentTime() ) );
+ t1 = QTime::currentTime();
+ if ( chan->tp.S2 ) {
+ fprintf(stderr,"\nTHIS IS DVB-S2 >>>>>>>>>>>>>>>>>>>\n");
+ cmdargs[0].cmd = DTV_DELIVERY_SYSTEM; cmdargs[0].u.data = SYS_DVBS2;
+ cmdargs[1].cmd = DTV_FREQUENCY; cmdargs[1].u.data = freq;
+ cmdargs[2].cmd = DTV_MODULATION; cmdargs[2].u.data = chan->tp.modulation;
+ cmdargs[3].cmd = DTV_SYMBOL_RATE; cmdargs[3].u.data = srate;
+ cmdargs[4].cmd = DTV_INNER_FEC; cmdargs[4].u.data = chan->tp.coderateH;
+ cmdargs[5].cmd = DTV_PILOT; cmdargs[5].u.data = PILOT_AUTO;
+ cmdargs[6].cmd = DTV_ROLLOFF; cmdargs[6].u.data = chan->tp.rolloff;
+ cmdargs[7].cmd = DTV_INVERSION; cmdargs[7].u.data = inversion;
+ cmdargs[8].cmd = DTV_TUNE;
+ cmdseq.num = 9;
+ cmdseq.props = cmdargs;
+ }
+ else {
+ cmdargs[0].cmd = DTV_DELIVERY_SYSTEM; cmdargs[0].u.data = SYS_DVBS;
+ cmdargs[1].cmd = DTV_FREQUENCY; cmdargs[1].u.data = freq;
+ cmdargs[2].cmd = DTV_MODULATION; cmdargs[2].u.data = chan->tp.modulation;
+ if ( chan->tp.modulation==QAM_AUTO )
+ cmdargs[2].u.data = QPSK;
+ cmdargs[3].cmd = DTV_SYMBOL_RATE; cmdargs[3].u.data = srate;
+ cmdargs[4].cmd = DTV_INNER_FEC; cmdargs[4].u.data = chan->tp.coderateH;
+ cmdargs[5].cmd = DTV_INVERSION; cmdargs[5].u.data = inversion;
+ cmdargs[6].cmd = DTV_TUNE;
+ cmdseq.num = 7;
+ cmdseq.props = cmdargs;
+ }
break;
}
case FE_ATSC : {
+ cmdargs[0].cmd = DTV_DELIVERY_SYSTEM; cmdargs[0].u.data = SYS_ATSC;
+ cmdargs[1].cmd = DTV_FREQUENCY; cmdargs[1].u.data = freq;
+ cmdargs[2].cmd = DTV_MODULATION; cmdargs[2].u.data = chan->tp.modulation;
+ cmdargs[3].cmd = DTV_INVERSION; cmdargs[3].u.data = inversion;
+ cmdargs[4].cmd = DTV_TUNE;
+ cmdseq.num = 5;
+ cmdseq.props = cmdargs;
fprintf(stderr,"tuning ATSC to %lu\n", freq);
- feparams.frequency=freq;
- feparams.u.vsb.modulation = chan->tp.modulation;
fprintf(stderr,"inv:%d mod:%d\n", chan->tp.inversion, chan->tp.modulation );
break;
}
}
- if ( chan->tp.inversion==INVERSION_AUTO ) {
- if ( fe_info.caps & FE_CAN_INVERSION_AUTO )
- feparams.inversion=chan->tp.inversion;
- else {
- fprintf(stderr,"Can NOT inversion_auto\n");
- feparams.inversion=INVERSION_OFF;
- }
- }
- else
- feparams.inversion=chan->tp.inversion;
- if ( rotorMove )
+ if ( rotorMove ) {
+ if ( ioctl( fdFrontend, FE_SET_PROPERTY, &cmdseq )<0 ) {
+ perror("ERROR tuning\n");
+ closeFe();
+ return false;
+ }
+ moveRotor( lnbPos, chan, hiband, dvr );
loop = 2;
+ }
while ( loop>-1 ) {
- if (ioctl(fdFrontend,FE_SET_FRONTEND,&feparams) < 0) {
- perror("ERROR tuning \n");
+ if ( ioctl( fdFrontend, FE_SET_PROPERTY, &cmdseq )<0 ) {
+ perror("ERROR tuning\n");
closeFe();
return false;
}
- for ( i=0; i<(dvbDevice->tuningTimeout/100); i++ ) {
+ QTime lockTime = QTime::currentTime();
+ do {
usleep( 100000 );
fprintf( stderr, "." );
if ( ioctl( fdFrontend, FE_READ_STATUS, &status )==-1 ) {
@@ -440,7 +526,7 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
loop = 0;
break;
}
- }
+ } while ( lockTime.msecsTo( QTime::currentTime() )<=dvbDevice->tuningTimeout );
fprintf(stderr,"\n");
--loop;
}
@@ -451,6 +537,8 @@ bool DvbStream::tuneDvb( ChannelDesc *chan, bool dvr )
return false;
}
+ fprintf( stderr, "Tuning time = %d ms\n", t1.msecsTo( QTime::currentTime() ) );
+
if ( rotorMove )
dvbDevice->lnb[lnbPos].currentSource = chan->tp.source;
@@ -496,6 +584,23 @@ int DvbStream::setDiseqc( int switchPos, ChannelDesc *chan, int hiband, int &rot
int i;
int voltage18 = ( (chan->tp.pol=='H')||(chan->tp.pol=='h') );
int ci = 4 * switchPos + 2 * hiband + (voltage18 ? 1 : 0);
+ bool secMini = false;
+ bool hasRotor = false;
+ bool hasSwitch = true;
+
+ if ( dvbDevice->numLnb<2 )
+ hasSwitch = false;
+
+ if ( dvbDevice->lnb[switchPos].rotorType!=0 && dvbDevice->lnb[switchPos].rotorType!=3 )
+ hasRotor = true;
+
+ if ( dvbDevice->numLnb==2 && dvbDevice->secMini )
+ secMini = true;
+
+ if ( dvbDevice->secTwice )
+ diseqcTwice = 2;
+ else
+ diseqcTwice = 1;
fprintf( stderr, "DiSEqC: switch pos %i, %sV, %sband (index %d)\n", switchPos, voltage18 ? "18" : "13", hiband ? "hi" : "lo", ci );
if ( ci < 0 || ci >= (int)(sizeof(switchCmd)/sizeof(struct dvb_diseqc_master_cmd)) )
@@ -507,85 +612,108 @@ int DvbStream::setDiseqc( int switchPos, ChannelDesc *chan, int hiband, int &rot
if ( ioctl(fdFrontend, FE_SET_VOLTAGE, ci%2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13) )
perror("FE_SET_VOLTAGE failed");
- fprintf( stderr, "DiSEqC: %02x %02x %02x %02x %02x %02x\n", switchCmd[ci].msg[0], switchCmd[ci].msg[1], switchCmd[ci].msg[2], switchCmd[ci].msg[3], switchCmd[ci].msg[4], switchCmd[ci].msg[5] );
- for ( i=0; i<2; ++i ) {
- usleep(15*1000);
- if ( ioctl(fdFrontend, FE_DISEQC_SEND_MASTER_CMD, &switchCmd[ci]) )
- perror("FE_DISEQC_SEND_MASTER_CMD failed");
- }
-
- QString msg;
- if ( dvbDevice->lnb[switchPos].rotorType!=0 && chan->tp.source!=dvbDevice->lnb[switchPos].currentSource ) {
- int i, index=-1;
- double angle=0.0, oldAngle=0.0;
- fprintf( stderr, "Driving rotor to %s\n", chan->tp.source.ascii() );
- for ( i=0; i<(int)dvbDevice->lnb[switchPos].source.count(); i++ ) {
- if ( dvbDevice->lnb[switchPos].source[i]==chan->tp.source ) {
- index = i;
- break;
+ if ( hasSwitch ) {
+ if ( !secMini ) {
+ fprintf( stderr, "DiSEqC: %02x %02x %02x %02x %02x %02x\n", switchCmd[ci].msg[0], switchCmd[ci].msg[1], switchCmd[ci].msg[2], switchCmd[ci].msg[3], switchCmd[ci].msg[4], switchCmd[ci].msg[5] );
+ for ( i=0; i<diseqcTwice; ++i ) {
+ usleep(15*1000);
+ if ( ioctl(fdFrontend, FE_DISEQC_SEND_MASTER_CMD, &switchCmd[ci]) )
+ perror("FE_DISEQC_SEND_MASTER_CMD failed");
}
}
- angle = getSourceAngle( chan->tp.source );
- if ( dvbDevice->lnb[switchPos].rotorType==1 ) {
- fprintf( stderr, "Rotor: gotoX=%f\n", angle );
- gotoX( angle );
- }
- else {
- int pos = dvbDevice->lnb[switchPos].position[index];
- fprintf( stderr, "Rotor: gotoN=%d\n", pos );
- rotorCommand( 9, pos );
- }
- if ( dvbDevice->lnb[switchPos].currentSource.isEmpty() ) {
- rotor = 10;
- msg = i18n("Moving rotor from unknown position...");
- }
else {
- oldAngle = getSourceAngle( dvbDevice->lnb[switchPos].currentSource );
- fprintf( stderr, "old rotor pos: %f °\n", oldAngle );
- fprintf( stderr, "new rotor pos: %f °\n", angle );
- angle = fabs(angle-oldAngle);
- fprintf( stderr, "Rotation angle: %f °\n", angle );
- if ( voltage18 )
- rotor = (int)(angle*dvbDevice->lnb[switchPos].speed18v)+1;
- else
- rotor = (int)(angle*dvbDevice->lnb[switchPos].speed13v)+1;
- msg = i18n("Moving rotor...");
+ fprintf( stderr, "DiSEqC: mini_diseqc\n" );
+ for ( i=0; i<diseqcTwice; ++i ) {
+ usleep(15*1000);
+ if ( ioctl(fdFrontend, FE_DISEQC_SEND_BURST, (ci/4)%2 ? SEC_MINI_B : SEC_MINI_A) )
+ perror("FE_DISEQC_SEND_BURST failed");
+ }
}
- fprintf( stderr, "Rotation time: %d sec.\n", rotor );
}
- if ( rotor ) {
- int j;
- if ( !dvr ) {
- for ( j=0; j<(rotor*2); j++ ) {
- usleep( 500000 );
- }
+ if ( hasRotor && chan->tp.source!=dvbDevice->lnb[switchPos].currentSource ) {
+ rotor = 1;
+ return 0;
+ }
+
+ if ( (ci/2)%2 ) {
+ usleep(15*1000);
+ if ( ioctl(fdFrontend, FE_SET_TONE, SEC_TONE_ON) )
+ perror("FE_SET_TONE failed");
+ }
+
+ return 0;
+}
+
+
+
+void DvbStream::moveRotor( int switchPos, ChannelDesc *chan, int hiband, bool dvr )
+{
+ int i, j, index=-1;
+ double angle=0.0, oldAngle=0.0;
+ int rotor=0;
+ int voltage18 = ( (chan->tp.pol=='H')||(chan->tp.pol=='h') );
+ int ci = 4 * switchPos + 2 * hiband + (voltage18 ? 1 : 0);
+ QString msg;
+
+ fprintf( stderr, "Driving rotor to %s\n", chan->tp.source.ascii() );
+ for ( i=0; i<(int)dvbDevice->lnb[switchPos].source.count(); i++ ) {
+ if ( dvbDevice->lnb[switchPos].source[i]==chan->tp.source ) {
+ index = i;
+ break;
}
- else {
- QProgressDialog progress( msg, i18n("Cancel"), rotor*2, 0, "progress", true );
- for ( j=0; j<(rotor*2); j++ ) {
- progress.setProgress( j );
- qApp->processEvents();
- if ( progress.wasCanceled() )
- break;
- usleep( 500000 );
- }
- progress.setProgress( rotor*2 );
+ }
+ angle = getSourceAngle( chan->tp.source );
+ if ( dvbDevice->lnb[switchPos].rotorType==1 ) {
+ fprintf( stderr, "Rotor: gotoX=%f\n", angle );
+ gotoX( angle );
+ }
+ else {
+ int pos = dvbDevice->lnb[switchPos].position[index];
+ fprintf( stderr, "Rotor: gotoN=%d\n", pos );
+ rotorCommand( 9, pos );
+ }
+ if ( dvbDevice->lnb[switchPos].currentSource.isEmpty() ) {
+ rotor = 10;
+ msg = i18n("Moving rotor from unknown position...");
+ }
+ else {
+ oldAngle = getSourceAngle( dvbDevice->lnb[switchPos].currentSource );
+ fprintf( stderr, "old rotor pos: %f °\n", oldAngle );
+ fprintf( stderr, "new rotor pos: %f °\n", angle );
+ angle = fabs(angle-oldAngle);
+ fprintf( stderr, "Rotation angle: %f °\n", angle );
+ if ( voltage18 )
+ rotor = (int)(angle*dvbDevice->lnb[switchPos].speed18v)+1;
+ else
+ rotor = (int)(angle*dvbDevice->lnb[switchPos].speed13v)+1;
+ msg = i18n("Moving rotor...");
+ }
+ fprintf( stderr, "Rotation time: %d sec.\n", rotor );
+
+ if ( !dvr ) {
+ for ( j=0; j<(rotor*2); j++ ) {
+ usleep( 500000 );
+ }
+ }
+ else {
+ QProgressDialog progress( msg, i18n("Cancel"), rotor*2, 0, "progress", true );
+ for ( j=0; j<(rotor*2); j++ ) {
+ progress.setProgress( j );
qApp->processEvents();
+ if ( progress.wasCanceled() )
+ break;
+ usleep( 500000 );
}
+ progress.setProgress( rotor*2 );
+ qApp->processEvents();
}
- for ( i=0; i<2; ++i ) {
+ if ( (ci/2)%2 ) {
usleep(15*1000);
- if ( ioctl(fdFrontend, FE_DISEQC_SEND_BURST, (ci/4)%2 ? SEC_MINI_B : SEC_MINI_A) )
- perror("FE_DISEQC_SEND_BURST failed");
+ if ( ioctl(fdFrontend, FE_SET_TONE, SEC_TONE_ON) )
+ perror("FE_SET_TONE failed");
}
-
- usleep(15*1000);
- if ( ioctl(fdFrontend, FE_SET_TONE, (ci/2)%2 ? SEC_TONE_ON : SEC_TONE_OFF) )
- perror("FE_SET_TONE failed");
-
- return 0;
}
@@ -681,7 +809,7 @@ void DvbStream::rotorCommand( int cmd, int n1, int n2, int n3 )
};
int i;
- for ( i=0; i<2; ++i ) {
+ for ( i=0; i<diseqcTwice; ++i ) {
usleep(15*1000);
if ( ioctl( fdFrontend, FE_DISEQC_SEND_MASTER_CMD, &cmds[cmd] ) )
perror("Rotor : FE_DISEQC_SEND_MASTER_CMD failed");
@@ -803,28 +931,33 @@ bool DvbStream::hasVideo()
void DvbStream::run()
{
- unsigned char buf[188];
+ int READSIZE = 188*20;
+ int BUFSIZE = 188*100;
+ int WSIZE = 188*64;
+ unsigned char buf[READSIZE];
+ unsigned char thBuf[BUFSIZE];
int n, i, thWrite=0;
- int WSIZE=188*8;
DVBout *o=0;
signal( SIGPIPE, SIG_IGN );
while ( isRunning ) {
if ( poll( &pfd, 1, 100 ) ) {
- n = read( fdDvr, buf, 188 );
- if ( n==188 ) {
+ n = read( fdDvr, buf, READSIZE );
+ if ( n && !(n%188) ) {
+ //fprintf( stderr, "DVR0: read : %d\n", n );
memcpy( thBuf+thWrite, buf, n );
thWrite+=n;
- if ( thWrite==WSIZE ) {
+ if ( thWrite>=WSIZE ) {
for ( i=0; i<(int)out.count(); i++ )
- out.at(i)->process( thBuf, WSIZE );
+ out.at(i)->process( thBuf, thWrite );
thWrite = 0;
}
}
+ else
+ fprintf( stderr, "DVR0: read failed : %d\n", n );
+
}
- else
- usleep(1000);
if ( waitPause>0 ) {
o = 0;
@@ -917,19 +1050,11 @@ void DvbStream::recordEnded( DVBout *o, RecTimer* t, bool kill )
if ( kill ) {
removePids( o );
+ if ( cam )
+ cam->stopService( &(o->channel) );
removeOut( o );
if ( out.count()==0 )
stop();
- else if ( cam ) {
- for ( i=0; i<(int)out.count(); i++ ) {
- if ( out.at(i)->channel.fta ) {
- i=-1;
- break;
- }
- }
- if ( i!=-1 )
- cam->stop();
- }
}
recordingState();
if ( t )
@@ -986,6 +1111,8 @@ void DvbStream::stopBroadcast()
}
for ( i=0; i<(int)p.count(); i++ ) {
removePids( p.at(i) );
+ if ( cam )
+ cam->stopService( &(p.at(i)->channel) );
removeOut( p.at(i) );
}
if ( out.count()==0 )
@@ -1002,7 +1129,7 @@ int DvbStream::canStartBroadcast( bool &live, ChannelDesc *chan )
for ( i=0; i<(int)out.count(); i++ ) {
if ( (chan->tp!=out.at(i)->channel.tp) && out.at(i)->hasRec() )
return ErrIsRecording;
- if ( cam && out.at(i)->hasRec() && out.at(i)->channel.fta && chan->fta && out.at(i)->channel.sid!=chan->sid )
+ if ( chan->fta && cam && !cam->canPlay( chan ) )
return ErrCamUsed;
if ( out.at(i)->hasLive() && chan->tp!=out.at(i)->channel.tp )
live = true;
@@ -1070,6 +1197,8 @@ bool DvbStream::startBroadcast( QPtrList<ChannelDesc> *list, Ts2Rtp *rtp )
else {
broadcastList.append( new ChannelDesc( *list->at(i) ) );
no++;
+ if ( list->at(i)->fta && cam )
+ cam->startService( list->at(i) );
}
}
}
@@ -1102,15 +1231,11 @@ int DvbStream::canStartTimer( bool &live, ChannelDesc *chan )
return ErrIsRecording;
if ( (o->channel.name==chan->name) && o->hasRec() )
return ErrIsRecording;
- if ( (chan->tp==o->channel.tp) && o->hasRec() ) {
- if ( chan->fta && cam && o->channel.fta )
- return ErrCamUsed;
- }
+ if ( chan->fta && cam && !cam->canPlay( chan ) )
+ return ErrCamUsed;
if ( o->hasLive() ) {
if ( chan->tp!=o->channel.tp )
live = true;
- else if ( cam && chan->fta && o->channel.fta )
- live = true;
}
}
return ret;
@@ -1194,8 +1319,8 @@ bool DvbStream::startTimer( ChannelDesc *chan, QString path, int maxsize, RecTim
}
fprintf(stderr,"NOUT: %d\n", out.count() );
- if ( chan->fta && cam && ( ((cam->running() && chan->sid!=cam->serviceId()) || !cam->running()) ) )
- cam->restart( chan->sid );
+ if ( chan->fta && cam )
+ cam->startService( chan );
startReading();
@@ -1205,7 +1330,7 @@ bool DvbStream::startTimer( ChannelDesc *chan, QString path, int maxsize, RecTim
-int DvbStream::goLive( ChannelDesc *chan, const QString &pipeName )
+int DvbStream::goLive( ChannelDesc *chan, const QString &pipeName, int ringBufSize )
{
int i;
bool stop=false;
@@ -1216,10 +1341,8 @@ int DvbStream::goLive( ChannelDesc *chan, const QString &pipeName )
return ErrIsRecording;
if ( (chan->tp!=out.at(i)->channel.tp) && out.at(i)->hasBroadcast() )
return ErrIsBroadcasting;
- if ( (chan->tp==out.at(i)->channel.tp) && (out.at(i)->hasBroadcast() || out.at(i)->hasRec())) {
- if ( chan->fta && cam && cam->running() && (cam->serviceId()!=chan->sid) )
- return ErrCamUsed;
- }
+ if ( chan->fta && cam && !cam->canPlay( chan ) )
+ return ErrCamUsed;
if ( out.at(i)->channel.name==chan->name )
o = out.at(i);
}
@@ -1259,11 +1382,11 @@ int DvbStream::goLive( ChannelDesc *chan, const QString &pipeName )
else
i = 0;
- o->goLive( pipeName );
+ o->goLive( pipeName, ringBufSize );
fprintf(stderr,"NOUT: %d\n", out.count() );
- if ( chan->fta && cam && !cam->running() )
- cam->restart( chan->sid );
+ if ( chan->fta && cam )
+ cam->startService( chan );
startReading();
return i;
@@ -1307,17 +1430,12 @@ void DvbStream::stopLive( ChannelDesc *chan )
}
for ( i=0; i<(int)p.count(); i++ ) {
removePids( p.at(i) );
+ if ( cam )
+ cam->stopService( &(p.at(i)->channel) );
removeOut( p.at(i) );
}
fprintf(stderr,"Live stopped\n");
- if ( cam ) {
- for ( i=0; i<(int)out.count(); i++ ) {
- if ( out.at(i)->channel.fta )
- camUsed = true;
- }
- }
- if ( cam && !camUsed )
- cam->stop();
+
if ( out.count()==0 && chan->tp!=currentTransponder )
stop();
}
@@ -1343,8 +1461,6 @@ void DvbStream::stop()
wait();
fprintf(stderr,"dvbstream::run() terminated\n");
}
- if ( cam )
- cam->stop();
dvbEvents->stop();
stopFrontend();
}
@@ -1381,7 +1497,6 @@ DvbStream::~DvbStream()
{
stop();
if ( cam ) {
- cam->stop();
delete cam;
}
delete dvbEvents;
diff --git a/kaffeine/src/input/dvb/dvbstream.h b/kaffeine/src/input/dvb/dvbstream.h
index a5deb52..fe85f04 100644
--- a/kaffeine/src/input/dvb/dvbstream.h
+++ b/kaffeine/src/input/dvb/dvbstream.h
@@ -62,10 +62,11 @@ public :
void setPlug( KaffeineDvbPlugin *p );
QStringList getSources( bool all=false );
bool canSource( ChannelDesc *chan );
+ int getPriority();
bool tuneDvb( ChannelDesc *chan, bool dvr=true );
void stopFrontend();
virtual void run();
- int goLive( ChannelDesc *chan, const QString &pipeName );
+ int goLive( ChannelDesc *chan, const QString &pipeName, int ringBufSize );
void preStopLive();
void stopLive( ChannelDesc *chan );
void stop();
@@ -89,8 +90,9 @@ public :
bool hasLive();
bool liveIsRecording();
int getSNR();
+ void probeCam();
+ void showCamDialog();
- unsigned char thBuf[188*10];
struct pollfd pfd;
DVBevents *dvbEvents;
@@ -109,6 +111,7 @@ protected:
private :
int setDiseqc( int switchPos, ChannelDesc *chan, int hiband, int &rotor, bool dvr );
+ void moveRotor( int switchPos, ChannelDesc *chan, int hiband, bool dvr );
void rotorCommand( int cmd, int n1=0, int n2=0, int n3=0 );
void gotoX( double azimuth );
double getAzimuth( double angle );
@@ -119,7 +122,6 @@ private :
void removeOut( DVBout *o );
void recordingState();
void startReading();
- void probeCam();
bool openFe();
bool closeFe();
void connectStatus( bool con );
@@ -143,6 +145,7 @@ private :
QString timeShiftFileName;
DvbCam *cam;
bool camProbed;
+ int diseqcTwice;
KaffeineDvbPlugin *plug;
signals:
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am b/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am
index 59f288b..9963cd4 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/Makefile.am
@@ -2,10 +2,11 @@ noinst_LTLIBRARIES = libdvbapi.la
INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib
-libdvbapi_la_SOURCES = diseqc.c \
+libdvbapi_la_SOURCES = dvbaudio.c \
dvbca.c \
dvbdemux.c \
dvbfe.c \
- dvbnet.c
+ dvbnet.c \
+ dvbvideo.c
CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.c
new file mode 100644
index 0000000..72b4d70
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbaudio.h
new file mode 100644
index 0000000..36f6a55
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c
index aebad34..a882af6 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.c
@@ -128,6 +128,12 @@ int dvbdemux_set_pes_filter(int fd, int pid,
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;
}
@@ -201,6 +207,12 @@ int dvbdemux_set_pid_filter(int fd, int pid,
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;
}
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h
index 3fe4a4b..808ee80 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbdemux.h
@@ -55,6 +55,7 @@ extern "C"
#define DVBDEMUX_OUTPUT_DECODER 0
#define DVBDEMUX_OUTPUT_DEMUX 1
#define DVBDEMUX_OUTPUT_DVR 2
+#define DVBDEMUX_OUTPUT_TS_DEMUX 3
/**
* PES types.
@@ -65,6 +66,7 @@ extern "C"
#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
@@ -78,8 +80,8 @@ extern "C"
extern int dvbdemux_open_demux(int adapter, int demuxdevice, int nonblocking);
/**
- * Open a DVR device. May be opened for writing once, or multiple times in readonly
- * mode. It is used to either write() transport stream data to be demuxed
+ * 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).
*
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c
index fc6ecf4..98104c9 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.c
@@ -2,6 +2,7 @@
* 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
@@ -26,14 +27,16 @@
#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"
-#define GET_INFO_MIN_DELAY_US 100000
+int verbose = 0;
static int dvbfe_spectral_inversion_to_kapi[][2] =
{
@@ -128,6 +131,7 @@ static int dvbfe_dvbt_hierarchy_to_kapi[][2] =
{ -1, -1 }
};
+
static int lookupval(int val, int reverse, int table[][2])
{
int i =0;
@@ -149,19 +153,16 @@ static int lookupval(int val, int reverse, int table[][2])
}
-struct dvbfe_handle_prv {
+struct dvbfe_handle {
int fd;
- dvbfe_type_t type;
+ enum dvbfe_type type;
char *name;
- struct timeval nextinfotime;
- struct dvbfe_info cachedinfo;
- int cachedreturnval;
};
-dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly)
+struct dvbfe_handle *dvbfe_open(int adapter, int frontend, int readonly)
{
char filename[PATH_MAX+1];
- struct dvbfe_handle_prv *fehandle;
+ struct dvbfe_handle *fehandle;
int fd;
struct dvb_frontend_info info;
@@ -188,8 +189,8 @@ dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly)
}
// setup structure
- fehandle = (struct dvbfe_handle_prv*) malloc(sizeof(struct dvbfe_handle_prv));
- memset(fehandle, 0, sizeof(struct dvbfe_handle_prv));
+ 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:
@@ -214,99 +215,118 @@ dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly)
return fehandle;
}
-void dvbfe_close(dvbfe_handle_t _fehandle)
+void dvbfe_close(struct dvbfe_handle *fehandle)
{
- struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle;
-
close(fehandle->fd);
free(fehandle->name);
free(fehandle);
}
-int dvbfe_get_info(dvbfe_handle_t _fehandle, dvbfe_info_mask_t querymask, struct dvbfe_info *result)
+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;
- fe_status_t status;
- struct dvb_frontend_parameters kparams;
- struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle;
- struct timeval curtime;
-
- // limit how often this is called to reduce bus traffic
- gettimeofday(&curtime, NULL);
- if ((curtime.tv_sec < fehandle->nextinfotime.tv_sec) ||
- ((curtime.tv_sec == fehandle->nextinfotime.tv_sec) && (curtime.tv_usec < fehandle->nextinfotime.tv_usec))) {
- memcpy(result, &fehandle->cachedinfo, sizeof(struct dvbfe_info));
- return fehandle->cachedreturnval;
- }
+ struct dvb_frontend_event kevent;
+ int ok = 0;
- // retrieve the requested values
- memset(result, 0, sizeof(result));
- result->type = fehandle->type;
result->name = fehandle->name;
- if (querymask & DVBFE_INFO_LOCKSTATUS) {
- if (!ioctl(fehandle->fd, FE_READ_STATUS, &status)) {
- returnval |= DVBFE_INFO_LOCKSTATUS;
- if (status & FE_HAS_SIGNAL)
- result->signal = 1;
-
- if (status & FE_HAS_CARRIER)
- result->carrier = 1;
+ result->type = fehandle->type;
- if (status & FE_HAS_VITERBI)
- result->viterbi = 1;
+ 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;
- if (status & FE_HAS_SYNC)
- result->sync = 1;
+ 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 (status & FE_HAS_LOCK)
- result->lock = 1;
+ 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 (querymask & DVBFE_INFO_FEPARAMS) {
- if (!ioctl(fehandle->fd, FE_GET_FRONTEND, &kparams)) {
- returnval |= DVBFE_INFO_FEPARAMS;
- result->feparams.frequency = kparams.frequency;
- result->feparams.inversion = lookupval(kparams.inversion, 1, dvbfe_spectral_inversion_to_kapi);
- switch(fehandle->type) {
- case FE_QPSK:
- result->feparams.u.dvbs.symbol_rate = kparams.u.qpsk.symbol_rate;
- result->feparams.u.dvbs.fec_inner =
- lookupval(kparams.u.qpsk.fec_inner, 1, dvbfe_code_rate_to_kapi);
- break;
- case FE_QAM:
- result->feparams.u.dvbc.symbol_rate = kparams.u.qam.symbol_rate;
- result->feparams.u.dvbc.fec_inner =
- lookupval(kparams.u.qam.fec_inner, 1, dvbfe_code_rate_to_kapi);
- result->feparams.u.dvbc.modulation =
- lookupval(kparams.u.qam.modulation, 1, dvbfe_dvbc_mod_to_kapi);
- 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;
+ }
- case FE_OFDM:
- result->feparams.u.dvbt.bandwidth =
- lookupval(kparams.u.ofdm.bandwidth, 1, dvbfe_dvbt_bandwidth_to_kapi);
- result->feparams.u.dvbt.code_rate_HP =
- lookupval(kparams.u.ofdm.code_rate_HP, 1, dvbfe_code_rate_to_kapi);
- result->feparams.u.dvbt.code_rate_LP =
- lookupval(kparams.u.ofdm.code_rate_LP, 1, dvbfe_code_rate_to_kapi);
- result->feparams.u.dvbt.constellation =
- lookupval(kparams.u.ofdm.constellation, 1, dvbfe_dvbt_const_to_kapi);
- result->feparams.u.dvbt.transmission_mode =
- lookupval(kparams.u.ofdm.transmission_mode, 1, dvbfe_dvbt_transmit_mode_to_kapi);
- result->feparams.u.dvbt.guard_interval =
- lookupval(kparams.u.ofdm.guard_interval, 1, dvbfe_dvbt_guard_interval_to_kapi);
- result->feparams.u.dvbt.hierarchy_information =
- lookupval(kparams.u.ofdm.hierarchy_information, 1, dvbfe_dvbt_hierarchy_to_kapi);
- break;
+ 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_ATSC:
- result->feparams.u.atsc.modulation =
- lookupval(kparams.u.vsb.modulation, 1, dvbfe_atsc_mod_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;
@@ -324,24 +344,15 @@ int dvbfe_get_info(dvbfe_handle_t _fehandle, dvbfe_info_mask_t querymask, struct
returnval |= DVBFE_INFO_UNCORRECTED_BLOCKS;
}
- // setup for next poll
- gettimeofday(&fehandle->nextinfotime, NULL);
- fehandle->nextinfotime.tv_usec += GET_INFO_MIN_DELAY_US;
- if (fehandle->nextinfotime.tv_usec >= 1000000) {
- fehandle->nextinfotime.tv_usec -= 1000000;
- fehandle->nextinfotime.tv_sec++;
- }
- memcpy(&fehandle->cachedinfo, result, sizeof(struct dvbfe_info));
- fehandle->cachedreturnval = returnval;
-
// done
return returnval;
}
-int dvbfe_set(dvbfe_handle_t _fehandle, struct dvbfe_parameters *params, int timeout)
+int dvbfe_set(struct dvbfe_handle *fehandle,
+ struct dvbfe_parameters *params,
+ int timeout)
{
struct dvb_frontend_parameters kparams;
- struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle;
int res;
struct timeval endtime;
fe_status_t status;
@@ -428,320 +439,123 @@ int dvbfe_set(dvbfe_handle_t _fehandle, struct dvbfe_parameters *params, int tim
return -ETIMEDOUT;
}
-void dvbfe_poll(dvbfe_handle_t fehandle)
+int dvbfe_get_pollfd(struct dvbfe_handle *handle)
{
- // no implementation required yet
+ 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_diseqc_command(dvbfe_handle_t _fehandle, char *command)
+int dvbfe_set_tone_data_burst(struct dvbfe_handle *fehandle, enum dvbfe_sec_mini_cmd minicmd)
{
- int i = 0;
- int waittime;
- int status;
- struct dvb_diseqc_master_cmd master_cmd;
- unsigned int tmpcmd[6];
- struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle;
- char value_s[20];
- int value_i;
- int addr;
-
- while(command[i]) {
- /* kill whitespace */
- if (isspace(command[i])) {
- i++;
- continue;
- }
+ int ret = 0;
- switch(command[i]) {
- case 't':
- if ((status = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_OFF)) != 0)
- return status;
- break;
-
- case 'T':
- if ((status = ioctl(fehandle->fd, FE_SET_TONE, SEC_TONE_ON)) != 0)
- return status;
- break;
-
- case '_':
- if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_OFF)) != 0)
- return status;
- break;
+ 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");
- case 'v':
- if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13)) != 0)
- return status;
- break;
+ return ret;
+}
- case 'V':
- if ((status = ioctl(fehandle->fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18)) != 0)
- return status;
- break;
+int dvbfe_set_voltage(struct dvbfe_handle *fehandle, enum dvbfe_sec_voltage voltage)
+{
+ int ret = 0;
- case 'A':
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_A)) != 0)
- return status;
- break;
+ 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");
- case 'B':
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_BURST, SEC_MINI_B)) != 0)
- return status;
- break;
+ return ret;
+}
- case '+':
- ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 1);
- /* don't care if this one is not supported */
- break;
+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;
+}
- case '-':
- ioctl(fehandle->fd, FE_ENABLE_HIGH_LNB_VOLTAGE, 0);
- /* don't care if this one is not supported */
- break;
+int dvbfe_do_dishnetworks_legacy_command(struct dvbfe_handle *fehandle, unsigned int cmd)
+{
+ int ret = 0;
- case 'W':
- waittime = atoi(command + i + 1);
- if (waittime == 0) {
- return -EINVAL;
- }
- usleep(waittime * 1000);
- while(command[i] && !isspace(command[i]))
- i++;
- break;
+ ret = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, cmd);
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
- case '.': // extended command
- {
- i++;
-
- if (!strncmp(command+i, "D(", 2)) {
- i += 2;
-
- master_cmd.msg_len =
- sscanf(command+i, "%x %x %x %x %x %x",
- tmpcmd, tmpcmd+1, tmpcmd+2, tmpcmd+3, tmpcmd+4, tmpcmd+5);
- if (master_cmd.msg_len == 0)
- return -EINVAL;
- master_cmd.msg[0] = tmpcmd[0];
- master_cmd.msg[1] = tmpcmd[1];
- master_cmd.msg[2] = tmpcmd[2];
- master_cmd.msg[3] = tmpcmd[3];
- master_cmd.msg[4] = tmpcmd[4];
- master_cmd.msg[5] = tmpcmd[5];
-
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
- } else if (!strncmp(command+i, "Dband(", 6)) {
- if (sscanf(command+i+6, "%i %2s", &addr, value_s) != 2)
- return -EINVAL;
- if (!strncmp(value_s, "lo", 2)) {
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x20;
- master_cmd.msg_len = 3;
- } else if (!strncmp(value_s, "hi", 2)) {
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x24;
- master_cmd.msg_len = 3;
- } else {
- return -EINVAL;
- }
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if ((!strncmp(command+i, "Dpolarisation(", 14) ||
- (!strncmp(command+i, "Dpolarization(", 14)))) {
- if (sscanf(command+i+14, "%i %1s", &addr, value_s) != 2)
- return -EINVAL;
- switch(*value_s) {
- case 'H':
- case 'L':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x25;
- master_cmd.msg_len = 3;
- break;
-
- case 'V':
- case 'R':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x21;
- master_cmd.msg_len = 3;
- break;
-
- default:
- return -EINVAL;
- }
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if (!strncmp(command+i, "Dsatellite_position(", 20)) {
- if (sscanf(command+i+20, "%i %1s", &addr, value_s) != 2)
- return -EINVAL;
- switch(*value_s) {
- case 'A':
- case 'C':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x22;
- master_cmd.msg_len = 3;
- break;
-
- case 'B':
- case 'D':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x26;
- master_cmd.msg_len = 3;
- break;
-
- default:
- return -EINVAL;
- }
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if (!strncmp(command+i, "Dswitch_option(", 15)) {
- if (sscanf(command+i+15, "%i %1s", &addr, value_s) != 2)
- return -EINVAL;
- switch(*value_s) {
- case 'A':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x23;
- master_cmd.msg_len = 3;
- break;
-
- case 'B':
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x27;
- master_cmd.msg_len = 3;
- break;
-
- default:
- return -EINVAL;
- }
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if (!strncmp(command+i, "Dport_pins(", 11)) {
- int mask;
- if (sscanf(command+i+11, "%i %i %i", &addr, &mask, &value_i) != 3)
- return -EINVAL;
-
- if (mask & 0x0f) {
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x38;
- master_cmd.msg[3] = ((mask & 0x0f) << 4) | (value_i & 0x0f);
- master_cmd.msg_len = 4;
-
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
- }
- if (mask & 0xf0) {
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x39;
- master_cmd.msg[3] = (mask & 0xf0) | ((value_i & 0xf0) >> 4);
- master_cmd.msg_len = 4;
-
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
- }
-
- } else if (!strncmp(command+i, "Dgoto_preset(", 13)) {
- if (sscanf(command+i+13, "%i %i", &addr, &value_i) != 2)
- return -EINVAL;
-
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x3b;
- master_cmd.msg[3] = value_i;
- master_cmd.msg_len = 4;
-
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if (!strncmp(command+i, "Dgoto_angle(", 12)) {
- int integer = 0;
- int fraction = 0;
- char *tmp;
-
- if (sscanf(command+i+12, "%i %s", &addr, value_s) != 2)
- return -EINVAL;
-
- // parse the integer and fractional parts using fixed point
- integer = atoi(value_s);
- tmp = strchr(value_s, '.');
- if (tmp != NULL) {
- tmp++;
- tmp[3] = 0;
- fraction = ((atoi(tmp) * 16000) / 1000000) & 0xf;
- }
-
- // generate the command
- master_cmd.msg[0] = 0xe0;
- master_cmd.msg[1] = addr;
- master_cmd.msg[2] = 0x6e;
- if (integer < -256) {
- return -EINVAL;
- } else if (integer < 0) {
- integer = -integer;
- master_cmd.msg[3] = 0xf0;
- } else if (integer < 256) {
- master_cmd.msg[3] = 0x00;
- } else if (integer < 512) {
- integer -= 256;
- master_cmd.msg[3] = 0x10;
- } else {
- return -EINVAL;
- }
- master_cmd.msg[3] |= ((integer / 16) & 0x0f);
- integer = integer % 16;
- master_cmd.msg[4] |= ((integer & 0x0f) << 4) | fraction;
- master_cmd.msg_len = 5;
-
- if ((status = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &master_cmd)) != 0)
- return status;
-
- } else if (!strncmp(command+i, "dishnetworks(", 13)) {
- if (sscanf(command+i+13, "%i", tmpcmd) != 1)
- return -EINVAL;
-
- if ((status = ioctl(fehandle->fd, FE_DISHNETWORK_SEND_LEGACY_CMD, tmpcmd)) != 0)
- return status;
- }
+ return ret;
+}
- /* skip to the end... */
- while(command[i] && (command[i] != ')'))
- i++;
- break;
- }
+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;
- default:
- return -EINVAL;
- }
+ diseqc_message.msg_len = len;
+ memcpy(diseqc_message.msg, data, len);
- i++;
- }
+ ret = ioctl(fehandle->fd, FE_DISEQC_SEND_MASTER_CMD, &diseqc_message);
+ if (ret == -1)
+ print(verbose, ERROR, 1, "IOCTL failed");
- return 0;
+ return ret;
}
-int dvbfe_diseqc_read(dvbfe_handle_t _fehandle, int timeout, unsigned char *buf, unsigned int len)
+int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len)
{
struct dvb_diseqc_slave_reply reply;
int result;
- struct dvbfe_handle_prv *fehandle = (struct dvbfe_handle_prv*) _fehandle;
if (len > 4)
len = 4;
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h
index 9eb03b7..69cb05b 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbfe.h
@@ -2,6 +2,7 @@
* 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
@@ -32,27 +33,20 @@ extern "C"
/**
* The types of frontend we support.
*/
-typedef enum dvbfe_type {
+enum dvbfe_type {
DVBFE_TYPE_DVBS,
DVBFE_TYPE_DVBC,
DVBFE_TYPE_DVBT,
DVBFE_TYPE_ATSC,
-} dvbfe_type_t;
-
-typedef enum dvbfe_polarization {
- DVBFE_POLARIZATION_H,
- DVBFE_POLARIZATION_V,
- DVBFE_POLARIZATION_L,
- DVBFE_POLARIZATION_R,
-} dvbfe_polarization_t;
+};
-typedef enum dvbfe_spectral_inversion {
+enum dvbfe_spectral_inversion {
DVBFE_INVERSION_OFF,
DVBFE_INVERSION_ON,
DVBFE_INVERSION_AUTO
-} dvbfe_spectral_inversion_t;
+};
-typedef enum dvbfe_code_rate {
+enum dvbfe_code_rate {
DVBFE_FEC_NONE,
DVBFE_FEC_1_2,
DVBFE_FEC_2_3,
@@ -63,9 +57,9 @@ typedef enum dvbfe_code_rate {
DVBFE_FEC_7_8,
DVBFE_FEC_8_9,
DVBFE_FEC_AUTO
-} dvbfe_code_rate_t;
+};
-typedef enum dvbfe_dvbt_const {
+enum dvbfe_dvbt_const {
DVBFE_DVBT_CONST_QPSK,
DVBFE_DVBT_CONST_QAM_16,
DVBFE_DVBT_CONST_QAM_32,
@@ -73,106 +67,121 @@ typedef enum dvbfe_dvbt_const {
DVBFE_DVBT_CONST_QAM_128,
DVBFE_DVBT_CONST_QAM_256,
DVBFE_DVBT_CONST_AUTO
-} dvbfe_dvbt_const_t;
+};
-typedef enum dvbfe_dvbc_mod {
+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,
-} dvbfe_dvbc_mod_t;
+};
-typedef enum dvbfe_atsc_mod {
+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
-} dvbfe_atsc_mod_t;
+};
-typedef enum dvbfe_dvbt_transmit_mode {
+enum dvbfe_dvbt_transmit_mode {
DVBFE_DVBT_TRANSMISSION_MODE_2K,
DVBFE_DVBT_TRANSMISSION_MODE_8K,
DVBFE_DVBT_TRANSMISSION_MODE_AUTO
-} dvbfe_dvbt_transmit_mode_t;
+};
-typedef enum dvbfe_dvbt_bandwidth {
+enum dvbfe_dvbt_bandwidth {
DVBFE_DVBT_BANDWIDTH_8_MHZ,
DVBFE_DVBT_BANDWIDTH_7_MHZ,
DVBFE_DVBT_BANDWIDTH_6_MHZ,
DVBFE_DVBT_BANDWIDTH_AUTO
-} dvbfe_dvbt_bandwidth_t;
+};
-typedef enum dvbfe_dvbt_guard_interval {
+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
-} dvbfe_dvbt_guard_interval_t;
+};
-typedef enum dvbfe_dvbt_hierarchy {
+enum dvbfe_dvbt_hierarchy {
DVBFE_DVBT_HIERARCHY_NONE,
DVBFE_DVBT_HIERARCHY_1,
DVBFE_DVBT_HIERARCHY_2,
DVBFE_DVBT_HIERARCHY_4,
DVBFE_DVBT_HIERARCHY_AUTO
-} dvbfe_dvbt_hierarchy_t;
+};
/**
* Structure used to store and communicate frontend parameters.
*/
struct dvbfe_parameters {
uint32_t frequency;
- dvbfe_spectral_inversion_t inversion;
+ enum dvbfe_spectral_inversion inversion;
union {
struct {
uint32_t symbol_rate;
- dvbfe_code_rate_t fec_inner;
- dvbfe_polarization_t polarization;
+ enum dvbfe_code_rate fec_inner;
} dvbs;
struct {
uint32_t symbol_rate;
- dvbfe_code_rate_t fec_inner;
- dvbfe_dvbc_mod_t modulation;
+ enum dvbfe_code_rate fec_inner;
+ enum dvbfe_dvbc_mod modulation;
} dvbc;
struct {
- dvbfe_dvbt_bandwidth_t bandwidth;
- dvbfe_code_rate_t code_rate_HP;
- dvbfe_code_rate_t code_rate_LP;
- dvbfe_dvbt_const_t constellation;
- dvbfe_dvbt_transmit_mode_t transmission_mode;
- dvbfe_dvbt_guard_interval_t guard_interval;
- dvbfe_dvbt_hierarchy_t hierarchy_information;
+ 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 {
- dvbfe_atsc_mod_t modulation;
+ 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.
*/
-typedef enum dvbfe_info_mask {
+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,
-} dvbfe_info_mask_t;
+};
/**
* Structure containing values used by the dvbfe_get_info() call.
*/
struct dvbfe_info {
- dvbfe_type_t type; /* always retrieved */
+ enum dvbfe_type type; /* always retrieved */
const char *name; /* always retrieved */
unsigned int signal : 1; /* } DVBFE_INFO_LOCKSTATUS */
unsigned int carrier : 1; /* } */
@@ -187,9 +196,23 @@ struct dvbfe_info {
};
/**
+ * 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.
*/
-typedef void *dvbfe_handle_t;
+struct dvbfe_handle;
/**
* Open a DVB frontend.
@@ -199,18 +222,21 @@ typedef void *dvbfe_handle_t;
* @param readonly If 1, frontend will be opened in readonly mode only.
* @return A handle on success, or NULL on failure.
*/
-extern dvbfe_handle_t dvbfe_open(int adapter, int frontend, int readonly);
+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(dvbfe_handle_t handle);
+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=>
@@ -218,14 +244,9 @@ extern void dvbfe_close(dvbfe_handle_t handle);
* @return 0 on locked (or if timeout==0 and everything else worked), or
* nonzero on failure (including no lock).
*/
-extern int dvbfe_set(dvbfe_handle_t fehandle, struct dvbfe_parameters *params, int timeout);
-
-/**
- * Call this function regularly from a loop to maintain the frontend lock.
- *
- * @param fehandle Handle opened with dvbfe_open().
- */
-extern void dvbfe_poll(dvbfe_handle_t fehandle);
+extern int dvbfe_set(struct dvbfe_handle *fehandle,
+ struct dvbfe_parameters *params,
+ int timeout);
/**
* Retrieve information about the frontend.
@@ -233,62 +254,66 @@ extern void dvbfe_poll(dvbfe_handle_t fehandle);
* @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(dvbfe_handle_t fehandle, dvbfe_info_mask_t querymask, struct dvbfe_info *result);
+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);
/**
- * Execute a DISEQC command string.
- *
- * A diseqc command consists of a sequence of the following codes, separated by
- * whitespace:
- * Simple commands:
- * t - turn 22kHz tone off.
- * T - turn 22kHz tone on.
- * _ - set voltage to 0v (i.e. off).
- * v - set voltage to 13v.
- * V - set voltage to 18v.
- * + - Enable high LNB voltage.
- * - - Disable high LNB voltage.
- * A - send DISEQC mini command A.
- * B - send DISEQC mini command B.
- * Wii - Delay for ii milliseconds.
- *
- * Extended commands:
- * .dishnetworks(<value>) - Send a dish networks legacy command <value>
- * .D(<value> ...) - Send a raw diseqc master command. The command may be up
- * to 6 bytes long.
- * .Dband(<addr> <lo|hi>) - Set frequency band hi or lo.
- * .Dpolarisation(<addr> <V|H|L|R>) - Set polarisation.
- * .Dsatellite_position(<addr> <A|B>) - Set "satellite position" input switch.
- * .Dswitch_option(<addr> <A|B>) - Set "switch option" input switch.
- * .Dport_pins(<addr> <mask> <value>) - Set all input switches. Mask and value
- * are hex-ascii 8 bit bytes. Only bits with a corresponding '1' in mask
- * will be changed.
- * .Dgoto_preset(<addr> <index>) - Set a positioner to a preset index (integer)
- * .Dgoto_angle(<addr> <angle>) - Set a positioner to a given angle
- * (e.g. 49.6). The angle may range between -180 to 496. It may include a
- * fractional part.
- *
- * All integer values use standard notation - no prefix=>decimal, 0x=>hex etc.
- *
- * Set <addr> to 0 if you just have a simple DISEQC setup (e.g. one switch). See
- * the DISEQC specification at http://www.eutelsat.org/ for full information.
- *
- * Comments begin with '#' - any characters after this will be ignored
- * to the end of the line.
- *
- * Examples:
- * S-19.2E 11700000 V 9750000 t v W15 .D(E0 10 38 F0) W15 A W15 t
- * S-19.2E 99999999 V 10600000 t v W15 .D(E0 10 38 F1) W15 A W15 T
- * S-19.2E 11700000 H 9750000 t V W15 .D(E0 10 38 F2) W15 A W15 t
- * S-19.2E 99999999 H 10600000 t V W15 .D(E0 10 38 F3) W15 A W15 T
+ * Get a file descriptor for polling for lock status changes.
*
* @param fehandle Handle opened with dvbfe_open().
- * @param command Command to execute.
- * @return 0 on success, nonzero on failure.
+ * @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_diseqc_command(dvbfe_handle_t fehandle, char *command);
+extern int dvbfe_do_diseqc_command(struct dvbfe_handle *handle, uint8_t *data, uint8_t len);
/**
* Read a DISEQC response from the frontend.
@@ -299,7 +324,7 @@ extern int dvbfe_diseqc_command(dvbfe_handle_t fehandle, char *command);
* @param len Number of bytes in buffer.
* @return >= 0 on success (number of received bytes), <0 on failure.
*/
-extern int dvbfe_diseqc_read(dvbfe_handle_t fehandle, int timeout, unsigned char *buf, unsigned int len);
+extern int dvbfe_diseqc_read(struct dvbfe_handle *fehandle, int timeout, unsigned char *buf, unsigned int len);
#ifdef __cplusplus
}
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c
index d6ee632..f0f08f9 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.c
@@ -44,9 +44,10 @@ int dvbnet_open(int adapter, int netdeviceid)
return fd;
}
-int dvbnet_add_interface(int fd, uint16_t pid, int encapsulation)
+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;
@@ -63,10 +64,14 @@ int dvbnet_add_interface(int fd, uint16_t pid, int encapsulation)
default:
return -EINVAL;
}
- return ioctl(fd, NET_ADD_IF, &params);
+
+ 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, int *encapsulation)
+int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation)
{
struct dvb_net_if info;
int res;
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h
index 426e540..287919f 100644
--- a/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h
+++ b/kaffeine/src/input/dvb/lib/libdvbapi/dvbnet.h
@@ -31,10 +31,10 @@ extern "C"
/**
* Possible encapsulations of data.
*/
-typedef enum dvbnet_encap {
+enum dvbnet_encap {
DVBNET_ENCAP_MPE,
DVBNET_ENCAP_ULE,
-} dvbnet_encap_t;
+};
/**
* The maximum allowed number of dvb network devices per adapter netdevice.
@@ -56,9 +56,9 @@ extern int dvbnet_open(int adapter, int netdeviceid);
* @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 0 on success, nonzero on failure.
+ * @return Index of new interface on success, < 0 on failure.
*/
-extern int dvbnet_add_interface(int fd, uint16_t pid, int encapsulation);
+extern int dvbnet_add_interface(int fd, uint16_t pid, enum dvbnet_encap encapsulation);
/**
* Get details of a DVBNET interface.
@@ -69,7 +69,7 @@ extern int dvbnet_add_interface(int fd, uint16_t pid, int encapsulation);
* @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, int *encapsulation);
+extern int dvbnet_get_interface(int fd, int ifnum, uint16_t *pid, enum dvbnet_encap *encapsulation);
/**
* Remove a DVBNET interface.
diff --git a/kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.c b/kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.c
new file mode 100644
index 0000000..f1ffbe8
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.h b/kaffeine/src/input/dvb/lib/libdvbapi/dvbvideo.h
new file mode 100644
index 0000000..cc49914
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am b/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am
index 7c9764a..6942c02 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/Makefile.am
@@ -16,6 +16,9 @@ libdvben50221_la_SOURCES = asn_1.c \
en50221_app_teletext.c \
en50221_app_utils.c \
en50221_session.c \
- en50221_transport.c
+ en50221_transport.c \
+ en50221_stdcam.c \
+ en50221_stdcam_llci.c \
+ en50221_stdcam_hlci.c
CFLAGS = -g -O2 -DLOG_LEVEL=1 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC
diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c
index 0c6ff5c..803eb60 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.c
@@ -2,8 +2,8 @@
ASN.1 routines, implementation for libdvben50221
an implementation for the High Level Common Interface
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
- Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+ 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
@@ -17,65 +17,67 @@
You should 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
+ 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)
+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;
+ if (asn_1_array_len < 1)
+ return -1;
length_field = asn_1_array[0];
- if (length_field < 0x80) {
+ 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;
+ 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)
+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;
+ if (length < 0x80) {
+ if (asn_1_array_len < 1)
+ return -1;
- asn_1_array[0] = length & 0x7f;
- 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;
+ 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
+ // never reached
}
diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h
index bae6da8..c8774db 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/asn_1.h
@@ -2,8 +2,8 @@
ASN.1 routines, implementation for libdvben50221
an implementation for the High Level Common Interface
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
- Copyright (C) 2006 Andrew de Quincey (adq_dvb@lidskialf.net)
+ 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
@@ -17,25 +17,25 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ASN_1_H__
#define __ASN_1_H__
#ifdef __cplusplus
-extern "C"
-{
+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);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c
index e3e73ab..b7ded66 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -28,106 +28,107 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_ai_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_ai {
+ struct en50221_app_send_functions *funcs;
- en50221_app_ai_callback callback;
- void *callback_arg;
+ en50221_app_ai_callback callback;
+ void *callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_ai_parse_app_info(struct en50221_app_ai_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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);
-en50221_app_ai en50221_app_ai_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_ai *en50221_app_ai_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_ai_private *private = NULL;
+ struct en50221_app_ai *ai = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_ai_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&ai->lock, NULL);
- // done
- return private;
+ // done
+ return ai;
}
-void en50221_app_ai_destroy(en50221_app_ai ai)
+void en50221_app_ai_destroy(struct en50221_app_ai *ai)
{
- struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&ai->lock);
+ free(ai);
}
-void en50221_app_ai_register_callback(en50221_app_ai ai, en50221_app_ai_callback callback, void *arg)
+void en50221_app_ai_register_callback(struct en50221_app_ai *ai,
+ en50221_app_ai_callback callback,
+ void *arg)
{
- struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai;
-
- pthread_mutex_lock(&private->lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&ai->lock);
+ ai->callback = callback;
+ ai->callback_arg = arg;
+ pthread_mutex_unlock(&ai->lock);
}
-int en50221_app_ai_enquiry(en50221_app_ai ai, uint16_t session_number)
+int en50221_app_ai_enquiry(struct en50221_app_ai *ai,
+ uint16_t session_number)
{
- struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai;
- uint8_t data[4];
+ 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;
+ 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4);
+ return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4);
}
-int en50221_app_ai_entermenu(en50221_app_ai ai, uint16_t session_number)
+int en50221_app_ai_entermenu(struct en50221_app_ai *ai,
+ uint16_t session_number)
{
- struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai;
- uint8_t data[4];
+ 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;
+ data[0] = (TAG_ENTER_MENU >> 16) & 0xFF;
+ data[1] = (TAG_ENTER_MENU >> 8) & 0xFF;
+ data[2] = TAG_ENTER_MENU & 0xFF;
+ data[3] = 0;
- return private->funcs->send_data(private->funcs->arg, session_number, data, 4);
+ return ai->funcs->send_data(ai->funcs->arg, session_number, data, 4);
}
-int en50221_app_ai_message(en50221_app_ai ai,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_ai_private *private = (struct en50221_app_ai_private *) ai;
- (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(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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;
}
@@ -136,50 +137,55 @@ int en50221_app_ai_message(en50221_app_ai ai,
-static int en50221_app_ai_parse_app_info(struct en50221_app_ai_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_ai_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, application_type,
- application_manufacturer, manufacturer_code, menu_string_length, menu_string);
- }
- return 0;
+ // 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h
index 32d6e07..18b5cd2 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ai.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -52,15 +51,19 @@ extern "C"
* @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);
+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.
*/
-typedef void *en50221_app_ai;
+struct en50221_app_ai;
/**
* Create an instance of an application information resource.
@@ -68,14 +71,14 @@ typedef void *en50221_app_ai;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_ai en50221_app_ai_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_ai ai);
+extern void en50221_app_ai_destroy(struct en50221_app_ai *ai);
/**
* Register a callback for reception of application_info objects.
@@ -84,7 +87,9 @@ extern void en50221_app_ai_destroy(en50221_app_ai ai);
* @param callback Callback function.
* @param arg Private argument passed during calls to the callback.
*/
-extern void en50221_app_ai_register_callback(en50221_app_ai ai, en50221_app_ai_callback, void *arg);
+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
@@ -93,7 +98,8 @@ extern void en50221_app_ai_register_callback(en50221_app_ai ai, en50221_app_ai_c
* @param session_number Session to send on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ai_enquiry(en50221_app_ai ai, uint16_t session_number);
+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
@@ -103,7 +109,8 @@ extern int en50221_app_ai_enquiry(en50221_app_ai ai, uint16_t session_number);
* @param session_number Session to send on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ai_entermenu(en50221_app_ai ai, uint16_t session_number);
+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.
@@ -116,14 +123,14 @@ extern int en50221_app_ai_entermenu(en50221_app_ai ai, uint16_t session_number);
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ai_message(en50221_app_ai ai,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c
index 8826c3b..a8902c1 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -28,152 +28,153 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_auth_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_auth {
+ struct en50221_app_send_functions *funcs;
- en50221_app_auth_request_callback callback;
- void *callback_arg;
+ en50221_app_auth_request_callback callback;
+ void *callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_auth_parse_request(struct en50221_app_auth_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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);
-en50221_app_auth en50221_app_auth_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_auth *en50221_app_auth_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_auth_private *private = NULL;
+ struct en50221_app_auth *auth = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_auth_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&auth->lock, NULL);
- // done
- return private;
+ // done
+ return auth;
}
-void en50221_app_auth_destroy(en50221_app_auth auth)
+void en50221_app_auth_destroy(struct en50221_app_auth *auth)
{
- struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&auth->lock);
+ free(auth);
}
-void en50221_app_auth_register_request_callback(en50221_app_auth auth,
- en50221_app_auth_request_callback callback, void *arg)
+void en50221_app_auth_register_request_callback(struct en50221_app_auth *auth,
+ en50221_app_auth_request_callback callback, void *arg)
{
- struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth;
-
- pthread_mutex_lock(&private->lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&auth->lock);
+ auth->callback = callback;
+ auth->callback_arg = arg;
+ pthread_mutex_unlock(&auth->lock);
}
-int en50221_app_auth_send(en50221_app_auth auth,
- uint16_t session_number,
- uint16_t auth_protocol_id, uint8_t *auth_data,
- uint32_t auth_data_length)
+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)
{
- struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2);
+ 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(en50221_app_auth auth,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_auth_private *private = (struct en50221_app_auth_private *) auth;
- (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(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_auth_request_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, auth_protocol_id, auth_data+2, asn_data_length-2);
- }
- return 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 < 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h
index c275089..2b1d2e7 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_auth.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -46,14 +45,17 @@ extern "C"
* @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);
+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.
*/
-typedef void *en50221_app_auth;
+struct en50221_app_auth;
/**
* Create an instance of the auth resource.
@@ -61,14 +63,14 @@ typedef void *en50221_app_auth;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_auth en50221_app_auth_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_auth auth);
+extern void en50221_app_auth_destroy(struct en50221_app_auth *auth);
/**
* Register the callback for when we receive a request.
@@ -77,8 +79,9 @@ extern void en50221_app_auth_destroy(en50221_app_auth auth);
* @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(en50221_app_auth auth,
- en50221_app_auth_request_callback callback, void *arg);
+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.
@@ -90,10 +93,11 @@ extern void en50221_app_auth_register_request_callback(en50221_app_auth auth,
* @param auth_data_length Number of bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_auth_send(en50221_app_auth auth,
- uint16_t session_number,
- uint16_t auth_protocol_id, uint8_t *auth_data,
- uint32_t auth_data_length);
+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.
@@ -106,14 +110,14 @@ extern int en50221_app_auth_send(en50221_app_auth auth,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_auth_message(en50221_app_auth auth,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c
index 0bdf74f..22d4499 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -34,272 +34,277 @@
#define TAG_CA_PMT 0x9f8032
#define TAG_CA_PMT_REPLY 0x9f8033
-struct en50221_app_ca_private {
- struct en50221_app_send_functions *funcs;
+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_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;
+ en50221_app_ca_pmt_reply_callback ca_pmt_reply_callback;
+ void *ca_pmt_reply_callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
struct ca_pmt_descriptor {
- uint8_t *descriptor;
- uint16_t length;
+ uint8_t *descriptor;
+ uint16_t length;
- struct ca_pmt_descriptor *next;
+ 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;
+ 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;
+ 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 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);
+ 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_private *private,
- 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+ 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);
-en50221_app_ca en50221_app_ca_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_ca *en50221_app_ca_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_ca_private *private = NULL;
+ struct en50221_app_ca *ca = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_ca_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->ca_info_callback = NULL;
- private->ca_pmt_reply_callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&ca->lock, NULL);
- // done
- return private;
+ // done
+ return ca;
}
-void en50221_app_ca_destroy(en50221_app_ca ca)
+void en50221_app_ca_destroy(struct en50221_app_ca *ca)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&ca->lock);
+ free(ca);
}
-void en50221_app_ca_register_info_callback(en50221_app_ca ca,
- en50221_app_ca_info_callback callback, void *arg)
+void en50221_app_ca_register_info_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_info_callback
+ callback, void *arg)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
-
- pthread_mutex_lock(&private->lock);
- private->ca_info_callback = callback;
- private->ca_info_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_ca ca,
- en50221_app_ca_pmt_reply_callback callback, void *arg)
+void en50221_app_ca_register_pmt_reply_callback(struct en50221_app_ca *ca,
+ en50221_app_ca_pmt_reply_callback
+ callback, void *arg)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
-
- pthread_mutex_lock(&private->lock);
- private->ca_pmt_reply_callback = callback;
- private->ca_pmt_reply_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_ca ca,
- uint16_t session_number)
+int en50221_app_ca_info_enq(struct en50221_app_ca *ca,
+ uint16_t session_number)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 4);
+ 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(en50221_app_ca ca,
- uint16_t session_number,
- uint8_t *ca_pmt,
- uint32_t ca_pmt_length)
+int en50221_app_ca_pmt(struct en50221_app_ca *ca,
+ uint16_t session_number,
+ uint8_t * ca_pmt, uint32_t ca_pmt_length)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2);
+ 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(en50221_app_ca ca,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_ca_private *private = (struct en50221_app_ca_private *) ca;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_CA_PMT_REPLY:
- return en50221_app_ca_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;
+ (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)
+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;
- struct ca_pmt_descriptor *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;
- struct ca_pmt_descriptor *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;
+ 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;
}
@@ -308,308 +313,319 @@ cleanup:
-static int en50221_ca_extract_pmt_descriptors(struct mpeg_pmt_section *pmt, struct ca_pmt_descriptor **outdescriptors)
+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;
+ 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;
+ 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)
+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;
+ 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;
+ // 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)
+ 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;
- }
+ // 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 *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;
+ 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_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(&private->lock);
- en50221_app_ca_info_callback cb = private->ca_info_callback;
- void *cb_arg = private->ca_info_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, ca_id_count, ids);
- }
- return 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;
+ }
+ 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_ca_pmt_reply_callback cb = private->ca_pmt_reply_callback;
- void *cb_arg = private->ca_pmt_reply_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, (struct en50221_app_pmt_reply*) data, asn_data_length);
- }
- return 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 < 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h
index 846312b..7405b06 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_ca.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -60,24 +59,24 @@ extern "C"
* 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));
+ 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));
+ 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.
@@ -102,9 +101,11 @@ struct en50221_app_pmt_stream {
* @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);
+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.
@@ -116,14 +117,16 @@ typedef int (*en50221_app_ca_info_callback)(void *arg, uint8_t slot_id, uint16_t
* @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);
+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.
*/
-typedef void *en50221_app_ca;
+struct en50221_app_ca;
/**
* Create an instance of the ca resource.
@@ -131,14 +134,14 @@ typedef void *en50221_app_ca;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_ca en50221_app_ca_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_ca ca);
+extern void en50221_app_ca_destroy(struct en50221_app_ca *ca);
/**
* Register the callback for when we receive a ca info.
@@ -147,8 +150,9 @@ extern void en50221_app_ca_destroy(en50221_app_ca ca);
* @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(en50221_app_ca ca,
- en50221_app_ca_info_callback callback, void *arg);
+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.
@@ -157,8 +161,9 @@ extern void en50221_app_ca_register_info_callback(en50221_app_ca ca,
* @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(en50221_app_ca ca,
- en50221_app_ca_pmt_reply_callback callback, void *arg);
+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.
@@ -167,8 +172,8 @@ extern void en50221_app_ca_register_pmt_reply_callback(en50221_app_ca ca,
* @param session_number Session number to send it on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ca_info_enq(en50221_app_ca ca,
- uint16_t session_number);
+extern int en50221_app_ca_info_enq(struct en50221_app_ca *ca,
+ uint16_t session_number);
/**
* Send a ca_pmt structure to the CAM.
@@ -179,10 +184,10 @@ extern int en50221_app_ca_info_enq(en50221_app_ca ca,
* @param ca_pmt_length Length of ca_pmt structure in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ca_pmt(en50221_app_ca ca,
- uint16_t session_number,
- uint8_t *ca_pmt,
- uint32_t ca_pmt_length);
+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.
@@ -197,10 +202,11 @@ extern int en50221_app_ca_pmt(en50221_app_ca ca,
* @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);
+ 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.
@@ -213,38 +219,42 @@ extern int en50221_ca_format_pmt(struct mpeg_pmt_section *pmt,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_ca_message(en50221_app_ca ca,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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)
+ 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);
+ uint32_t pos = sizeof(struct en50221_app_pmt_reply);
- if (pos >= reply_size)
- return NULL;
+ if (pos >= reply_size)
+ return NULL;
- return (struct en50221_app_pmt_stream *)((uint8_t *)reply+ pos);
+ 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)
+ 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);
+ 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;
+ if (next >= end)
+ return NULL;
- return (struct en50221_app_pmt_stream *) next;
+ return (struct en50221_app_pmt_stream *) next;
}
#ifdef __cplusplus
diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c
index e21304c..6777003 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -29,108 +29,109 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_datetime_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_datetime {
+ struct en50221_app_send_functions *funcs;
- en50221_app_datetime_enquiry_callback callback;
- void *callback_arg;
+ en50221_app_datetime_enquiry_callback callback;
+ void *callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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);
-en50221_app_datetime en50221_app_datetime_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_datetime *en50221_app_datetime_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_datetime_private *private = NULL;
+ struct en50221_app_datetime *datetime = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_datetime_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&datetime->lock, NULL);
- // done
- return private;
+ // done
+ return datetime;
}
-void en50221_app_datetime_destroy(en50221_app_datetime datetime)
+void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime)
{
- struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&datetime->lock);
+ free(datetime);
}
-void en50221_app_datetime_register_enquiry_callback(en50221_app_datetime datetime,
- en50221_app_datetime_enquiry_callback callback, void *arg)
+void en50221_app_datetime_register_enquiry_callback(struct en50221_app_datetime *datetime,
+ en50221_app_datetime_enquiry_callback callback,
+ void *arg)
{
- struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime;
-
- pthread_mutex_lock(&private->lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&datetime->lock);
+ datetime->callback = callback;
+ datetime->callback_arg = arg;
+ pthread_mutex_unlock(&datetime->lock);
}
-int en50221_app_datetime_send(en50221_app_datetime datetime,
- uint16_t session_number,
- time_t utc_time,
- int time_offset)
+int en50221_app_datetime_send(struct en50221_app_datetime *datetime,
+ uint16_t session_number,
+ time_t utc_time, int time_offset)
{
- struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, data_length);
+ 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(en50221_app_datetime datetime,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t 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)
{
- struct en50221_app_datetime_private *private = (struct en50221_app_datetime_private *) datetime;
- (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(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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;
}
@@ -142,28 +143,31 @@ int en50221_app_datetime_message(en50221_app_datetime datetime,
-static int en50221_app_datetime_parse_enquiry(struct en50221_app_datetime_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_datetime_enquiry_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, response_interval);
- }
- return 0;
+ // 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h
index df813e1..4660630 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_datetime.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -44,13 +43,15 @@ extern "C"
* @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);
+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.
*/
-typedef void *en50221_app_datetime;
+struct en50221_app_datetime;
/**
* Create an instance of the datetime resource.
@@ -58,14 +59,15 @@ typedef void *en50221_app_datetime;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_datetime en50221_app_datetime_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_datetime datetime);
+extern void en50221_app_datetime_destroy(struct en50221_app_datetime *datetime);
/**
* Register the callback for when we receive a enquiry request.
@@ -74,8 +76,9 @@ extern void en50221_app_datetime_destroy(en50221_app_datetime datetime);
* @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(en50221_app_datetime datetime,
- en50221_app_datetime_enquiry_callback callback, void *arg);
+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.
@@ -87,10 +90,10 @@ extern void en50221_app_datetime_register_enquiry_callback(en50221_app_datetime
* UTC and local time in minutes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_datetime_send(en50221_app_datetime datetime,
- uint16_t session_number,
- time_t utc_time,
- int time_offset);
+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.
@@ -103,14 +106,14 @@ extern int en50221_app_datetime_send(en50221_app_datetime datetime,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_datetime_message(en50221_app_datetime datetime,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c
index dfda1bf..21b2bec 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -28,137 +28,144 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_dvb_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_dvb {
+ struct en50221_app_send_functions *funcs;
- en50221_app_dvb_tune_callback tune_callback;
- void *tune_callback_arg;
+ 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_replace_callback replace_callback;
+ void *replace_callback_arg;
- en50221_app_dvb_clear_replace_callback clear_replace_callback;
- void *clear_replace_callback_arg;
+ en50221_app_dvb_clear_replace_callback clear_replace_callback;
+ void *clear_replace_callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_dvb_parse_tune(struct en50221_app_dvb_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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_private *private,
- 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_private *private,
- 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);
-en50221_app_dvb en50221_app_dvb_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_dvb *en50221_app_dvb_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_dvb_private *private = NULL;
-
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_dvb_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->tune_callback = NULL;
- private->replace_callback = NULL;
- private->clear_replace_callback = NULL;
-
- pthread_mutex_init(&private->lock, NULL);
-
- // done
- return private;
+ 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(en50221_app_dvb dvb)
+void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&dvb->lock);
+ free(dvb);
}
-void en50221_app_dvb_register_tune_callback(en50221_app_dvb dvb,
- en50221_app_dvb_tune_callback callback, void *arg)
+void en50221_app_dvb_register_tune_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_tune_callback callback,
+ void *arg)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
-
- pthread_mutex_lock(&private->lock);
- private->tune_callback = callback;
- private->tune_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_dvb dvb,
- en50221_app_dvb_replace_callback callback, void *arg)
+void en50221_app_dvb_register_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_replace_callback callback,
+ void *arg)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
-
- pthread_mutex_lock(&private->lock);
- private->replace_callback = callback;
- private->replace_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_dvb dvb,
- en50221_app_dvb_clear_replace_callback callback, void *arg)
+void en50221_app_dvb_register_clear_replace_callback(struct en50221_app_dvb *dvb,
+ en50221_app_dvb_clear_replace_callback callback,
+ void *arg)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
-
- pthread_mutex_lock(&private->lock);
- private->clear_replace_callback = callback;
- private->clear_replace_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_dvb dvb, uint16_t session_number)
+int en50221_app_dvb_ask_release(struct en50221_app_dvb *dvb,
+ uint16_t session_number)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
- uint8_t data[4];
+ 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;
+ data[0] = (TAG_ASK_RELEASE >> 16) & 0xFF;
+ data[1] = (TAG_ASK_RELEASE >> 8) & 0xFF;
+ data[2] = TAG_ASK_RELEASE & 0xFF;
+ data[3] = 0;
- return private->funcs->send_data(private->funcs->arg, session_number, data, 4);
+ return dvb->funcs->send_data(dvb->funcs->arg, session_number, data, 4);
}
-int en50221_app_dvb_message(en50221_app_dvb dvb,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_dvb_private *private = (struct en50221_app_dvb_private *) dvb;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_REPLACE:
- return en50221_app_dvb_parse_replace(private, slot_id, session_number, data+3, data_length-3);
- case TAG_CLEAR_REPLACE:
- return en50221_app_dvb_parse_clear_replace(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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;
}
@@ -170,94 +177,106 @@ int en50221_app_dvb_message(en50221_app_dvb dvb,
-static int en50221_app_dvb_parse_tune(struct en50221_app_dvb_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_dvb_tune_callback cb = private->tune_callback;
- void *cb_arg = private->tune_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, network_id, original_network_id, transport_stream_id, service_id);
- }
- return 0;
+ // 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_dvb_replace_callback cb = private->replace_callback;
- void *cb_arg = private->replace_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, replacement_ref, replace_pid, replacement_pid);
- }
- return 0;
+ // 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_dvb_clear_replace_callback cb = private->clear_replace_callback;
- void *cb_arg = private->clear_replace_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, replacement_ref);
- }
- return 0;
+ // 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h
index 7830942..be74e6b 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_dvb.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -48,9 +47,13 @@ extern "C"
* @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);
+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.
@@ -63,9 +66,12 @@ typedef int (*en50221_app_dvb_tune_callback)(void *arg, uint8_t slot_id, uint16_
* @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);
+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);
/**
@@ -77,14 +83,16 @@ typedef int (*en50221_app_dvb_replace_callback)(void *arg, uint8_t slot_id, uint
* @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);
+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.
*/
-typedef void *en50221_app_dvb;
+struct en50221_app_dvb;
/**
* Create an instance of the dvb resource.
@@ -92,14 +100,14 @@ typedef void *en50221_app_dvb;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_dvb en50221_app_dvb_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_dvb dvb);
+extern void en50221_app_dvb_destroy(struct en50221_app_dvb *dvb);
/**
* Register the callback for when we receive a tune request.
@@ -108,8 +116,9 @@ extern void en50221_app_dvb_destroy(en50221_app_dvb dvb);
* @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(en50221_app_dvb dvb,
- en50221_app_dvb_tune_callback callback, void *arg);
+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.
@@ -118,8 +127,9 @@ extern void en50221_app_dvb_register_tune_callback(en50221_app_dvb dvb,
* @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(en50221_app_dvb dvb,
- en50221_app_dvb_replace_callback callback, void *arg);
+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.
@@ -128,8 +138,9 @@ extern void en50221_app_dvb_register_replace_callback(en50221_app_dvb dvb,
* @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(en50221_app_dvb dvb,
- en50221_app_dvb_clear_replace_callback callback, void *arg);
+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.
@@ -138,7 +149,8 @@ extern void en50221_app_dvb_register_clear_replace_callback(en50221_app_dvb dvb,
* @param session_number Session number to send it on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_dvb_ask_release(en50221_app_dvb dvb, uint16_t session_number);
+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.
@@ -151,14 +163,14 @@ extern int en50221_app_dvb_ask_release(en50221_app_dvb dvb, uint16_t session_num
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_dvb_message(en50221_app_dvb dvb,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c
index 7237476..87b4743 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -29,138 +29,139 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_epg_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_epg {
+ struct en50221_app_send_functions *funcs;
- en50221_app_epg_reply_callback callback;
- void *callback_arg;
+ en50221_app_epg_reply_callback callback;
+ void *callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_epg_parse_reply(struct en50221_app_epg_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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);
-en50221_app_epg en50221_app_epg_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_epg *en50221_app_epg_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_epg_private *private = NULL;
+ struct en50221_app_epg *epg = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_epg_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&epg->lock, NULL);
- // done
- return private;
+ // done
+ return epg;
}
-void en50221_app_epg_destroy(en50221_app_epg epg)
+void en50221_app_epg_destroy(struct en50221_app_epg *epg)
{
- struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&epg->lock);
+ free(epg);
}
-void en50221_app_epg_register_enquiry_callback(en50221_app_epg epg,
- en50221_app_epg_reply_callback callback, void *arg)
+void en50221_app_epg_register_enquiry_callback(struct en50221_app_epg *epg,
+ en50221_app_epg_reply_callback callback,
+ void *arg)
{
- struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg;
-
- pthread_mutex_lock(&private->lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&epg->lock);
+ epg->callback = callback;
+ epg->callback_arg = arg;
+ pthread_mutex_unlock(&epg->lock);
}
-int en50221_app_epg_enquire(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)
+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)
{
- struct en50221_app_epg_private *private = (struct en50221_app_epg_private *) epg;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 15);
+ 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(en50221_app_epg epg,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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 *private = (struct en50221_app_epg_private *) 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;
+ 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_epg_reply_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, event_status);
- }
- return 0;
+ // 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h
index dcc65f1..dcfe9da 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_epg.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -57,13 +56,15 @@ extern "C"
* @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);
+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.
*/
-typedef void *en50221_app_epg;
+struct en50221_app_epg;
/**
* Create an instance of the epg resource.
@@ -71,14 +72,14 @@ typedef void *en50221_app_epg;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_epg en50221_app_epg_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_epg epg);
+extern void en50221_app_epg_destroy(struct en50221_app_epg *epg);
/**
* Register the callback for when we receive a enquiry response.
@@ -87,8 +88,9 @@ extern void en50221_app_epg_destroy(en50221_app_epg epg);
* @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(en50221_app_epg epg,
- en50221_app_epg_reply_callback callback, void *arg);
+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.
@@ -103,14 +105,14 @@ extern void en50221_app_epg_register_reply_callback(en50221_app_epg epg,
* @param event_id Event ID concerned.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_epg_enquire(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);
+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.
@@ -123,14 +125,14 @@ extern int en50221_app_epg_enquire(en50221_app_epg epg,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_epg_message(en50221_app_epg epg,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c
index 68d9774..a66598a 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -29,486 +29,505 @@
#include "asn_1.h"
struct en50221_app_lowspeed_session {
- uint16_t session_number;
- uint8_t *block_chain;
- uint32_t block_length;
+ uint16_t session_number;
+ uint8_t *block_chain;
+ uint32_t block_length;
- struct en50221_app_lowspeed_session *next;
+ struct en50221_app_lowspeed_session *next;
};
-struct en50221_app_lowspeed_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_lowspeed {
+ struct en50221_app_send_functions *funcs;
- en50221_app_lowspeed_command_callback command_callback;
- void *command_callback_arg;
+ en50221_app_lowspeed_command_callback command_callback;
+ void *command_callback_arg;
- en50221_app_lowspeed_send_callback send_callback;
- void *send_callback_arg;
+ en50221_app_lowspeed_send_callback send_callback;
+ void *send_callback_arg;
- struct en50221_app_lowspeed_session *sessions;
+ struct en50221_app_lowspeed_session *sessions;
- pthread_mutex_t lock;
+ 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_private *private,
- 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_private *private,
- uint8_t slot_id, uint16_t session_number, int more_last,
- uint8_t *data, uint32_t data_length);
-
-
-
-en50221_app_lowspeed en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs)
+ 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_private *private = NULL;
-
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_lowspeed_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->command_callback = NULL;
- private->send_callback = NULL;
- private->sessions = NULL;
-
- pthread_mutex_init(&private->lock, NULL);
-
- // done
- return private;
+ 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(en50221_app_lowspeed lowspeed)
+void en50221_app_lowspeed_destroy(struct en50221_app_lowspeed *lowspeed)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
-
- struct en50221_app_lowspeed_session *cur_s = private->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(&private->lock);
- free(private);
+ 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(en50221_app_lowspeed lowspeed, uint16_t session_number)
+void en50221_app_lowspeed_clear_session(struct en50221_app_lowspeed *lowspeed,
+ uint16_t session_number)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
-
- pthread_mutex_lock(&private->lock);
- struct en50221_app_lowspeed_session *cur_s = private->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 {
- private->sessions = cur_s->next;
- }
- free(cur_s);
- return;
- }
-
- prev_s = cur_s;
- cur_s=cur_s->next;
- }
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_lowspeed lowspeed,
- en50221_app_lowspeed_command_callback callback, void *arg)
+void en50221_app_lowspeed_register_command_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_command_callback callback,
+ void *arg)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
-
- pthread_mutex_lock(&private->lock);
- private->command_callback = callback;
- private->command_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_lowspeed lowspeed,
- en50221_app_lowspeed_send_callback callback, void *arg)
+void en50221_app_lowspeed_register_send_callback(struct en50221_app_lowspeed *lowspeed,
+ en50221_app_lowspeed_send_callback callback,
+ void *arg)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
-
- pthread_mutex_lock(&private->lock);
- private->send_callback = callback;
- private->send_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_lowspeed lowspeed,
- uint16_t session_number,
- uint8_t comms_reply_id,
- uint8_t return_value)
+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)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 6);
+ 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(en50221_app_lowspeed lowspeed,
- uint16_t session_number,
- uint8_t phase_id,
- uint32_t tx_data_length,
- uint8_t *tx_data)
+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)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2);
+ 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(en50221_app_lowspeed lowspeed,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_lowspeed_private *private = (struct en50221_app_lowspeed_private *) lowspeed;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_COMMS_SEND_LAST:
- return en50221_app_lowspeed_parse_send(private, slot_id, session_number, 1, data+3, data_length-3);
- case TAG_COMMS_SEND_MORE:
- return en50221_app_lowspeed_parse_send(private, slot_id, session_number, 0, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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)
+ 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;
+ 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t 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)
{
- // 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(&private->lock);
- en50221_app_lowspeed_command_callback cb = private->command_callback;
- void *cb_arg = private->command_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, command_id, &command);
- }
- return 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 < 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_private *private,
- uint8_t slot_id, uint16_t session_number, int more_last,
- 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)
{
- // 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(&private->lock);
- struct en50221_app_lowspeed_session *cur_s = private->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(&private->lock);
- return -1;
- }
- cur_s->session_number = session_number;
- cur_s->block_chain = NULL;
- cur_s->block_length = 0;
- cur_s->next = private->sessions;
- private->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(&private->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(&private->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(&private->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(&private->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 = private->send_callback;
- void *cb_arg = private->send_callback_arg;
- pthread_mutex_unlock(&private->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;
+ // 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h
index 4a3e554..0ef983c 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_lowspeed.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -57,26 +56,26 @@ extern "C"
* 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;
+ 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;
};
/**
@@ -89,9 +88,11 @@ struct en50221_app_lowspeed_command {
* @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);
+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
@@ -105,13 +106,17 @@ typedef int (*en50221_app_lowspeed_command_callback)(void *arg, uint8_t slot_id,
* @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);
+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.
*/
-typedef void *en50221_app_lowspeed;
+struct en50221_app_lowspeed;
/**
* Create an instance of the lowspeed resource.
@@ -119,14 +124,15 @@ typedef void *en50221_app_lowspeed;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_lowspeed en50221_app_lowspeed_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_lowspeed lowspeed);
+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.
@@ -134,7 +140,8 @@ extern void en50221_app_lowspeed_destroy(en50221_app_lowspeed lowspeed);
* @param lowspeed lowspeed resource instance.
* @param session_number The session concerned.
*/
-extern void en50221_app_lowspeed_clear_session(en50221_app_lowspeed lowspeed, uint16_t session_number);
+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.
@@ -143,8 +150,9 @@ extern void en50221_app_lowspeed_clear_session(en50221_app_lowspeed lowspeed, ui
* @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(en50221_app_lowspeed lowspeed,
- en50221_app_lowspeed_command_callback callback, void *arg);
+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.
@@ -153,8 +161,9 @@ extern void en50221_app_lowspeed_register_command_callback(en50221_app_lowspeed
* @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(en50221_app_lowspeed lowspeed,
- en50221_app_lowspeed_send_callback callback, void *arg);
+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.
@@ -165,10 +174,10 @@ extern void en50221_app_lowspeed_register_send_callback(en50221_app_lowspeed low
* @param return_value Comms reply specific value.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_lowspeed_send_comms_reply(en50221_app_lowspeed lowspeed,
- uint16_t session_number,
- uint8_t comms_reply_id,
- uint8_t return_value);
+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.
@@ -180,11 +189,11 @@ extern int en50221_app_lowspeed_send_comms_reply(en50221_app_lowspeed lowspeed,
* @param tx_data Data.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_lowspeed_send_comms_data(en50221_app_lowspeed lowspeed,
- uint16_t session_number,
- uint8_t phase_id,
- uint32_t tx_data_length,
- uint8_t *tx_data);
+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.
@@ -197,14 +206,14 @@ extern int en50221_app_lowspeed_send_comms_data(en50221_app_lowspeed lowspeed,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_lowspeed_message(en50221_app_lowspeed lowspeed,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c
index bb82678..830eaa3 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -30,1287 +30,1368 @@
#include "asn_1.h"
struct en50221_app_mmi_session {
- uint16_t session_number;
+ uint16_t session_number;
- uint8_t *menu_block_chain;
- uint32_t menu_block_length;
+ uint8_t *menu_block_chain;
+ uint32_t menu_block_length;
- uint8_t *list_block_chain;
- uint32_t list_block_length;
+ uint8_t *list_block_chain;
+ uint32_t list_block_length;
- uint8_t *subtitlesegment_block_chain;
- uint32_t subtitlesegment_block_length;
+ uint8_t *subtitlesegment_block_chain;
+ uint32_t subtitlesegment_block_length;
- uint8_t *subtitledownload_block_chain;
- uint32_t subtitledownload_block_length;
+ uint8_t *subtitledownload_block_chain;
+ uint32_t subtitledownload_block_length;
- struct en50221_app_mmi_session *next;
+ struct en50221_app_mmi_session *next;
};
-struct en50221_app_mmi_private {
- struct en50221_app_send_functions *funcs;
- struct en50221_app_mmi_session *sessions;
+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_close_callback closecallback;
+ void *closecallback_arg;
- en50221_app_mmi_display_control_callback displaycontrolcallback;
- void *displaycontrolcallback_arg;
+ en50221_app_mmi_display_control_callback displaycontrolcallback;
+ void *displaycontrolcallback_arg;
- en50221_app_mmi_keypad_control_callback keypadcontrolcallback;
- void *keypadcontrolcallback_arg;
+ en50221_app_mmi_keypad_control_callback keypadcontrolcallback;
+ void *keypadcontrolcallback_arg;
- en50221_app_mmi_subtitle_segment_callback subtitlesegmentcallback;
- void *subtitlesegmentcallback_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_end_mark_callback sceneendmarkcallback;
+ void *sceneendmarkcallback_arg;
- en50221_app_mmi_scene_control_callback scenecontrolcallback;
- void *scenecontrolcallback_arg;
+ en50221_app_mmi_scene_control_callback scenecontrolcallback;
+ void *scenecontrolcallback_arg;
- en50221_app_mmi_subtitle_download_callback subtitledownloadcallback;
- void *subtitledownloadcallback_arg;
+ en50221_app_mmi_subtitle_download_callback subtitledownloadcallback;
+ void *subtitledownloadcallback_arg;
- en50221_app_mmi_flush_download_callback flushdownloadcallback;
- void *flushdownloadcallback_arg;
+ en50221_app_mmi_flush_download_callback flushdownloadcallback;
+ void *flushdownloadcallback_arg;
- en50221_app_mmi_enq_callback enqcallback;
- void *enqcallback_arg;
+ en50221_app_mmi_enq_callback enqcallback;
+ void *enqcallback_arg;
- en50221_app_mmi_menu_callback menucallback;
- void *menucallback_arg;
+ en50221_app_mmi_menu_callback menucallback;
+ void *menucallback_arg;
- en50221_app_mmi_list_callback listcallback;
- void *listcallback_arg;
+ en50221_app_mmi_list_callback listcallback;
+ void *listcallback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_mmi_parse_close(struct en50221_app_mmi_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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_private *private,
- 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);
-
-
-
-en50221_app_mmi en50221_app_mmi_create(struct en50221_app_send_functions *funcs)
+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_private *private = NULL;
-
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_mmi_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->closecallback = NULL;
- private->displaycontrolcallback = NULL;
- private->keypadcontrolcallback = NULL;
- private->subtitlesegmentcallback = NULL;
- private->sceneendmarkcallback = NULL;
- private->scenecontrolcallback = NULL;
- private->subtitledownloadcallback = NULL;
- private->flushdownloadcallback = NULL;
- private->enqcallback = NULL;
- private->menucallback = NULL;
- private->listcallback = NULL;
- private->sessions = NULL;
-
- pthread_mutex_init(&private->lock, NULL);
-
- // done
- return private;
+ 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(en50221_app_mmi mmi)
+void en50221_app_mmi_destroy(struct en50221_app_mmi *mmi)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- struct en50221_app_mmi_session *cur_s = private->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(&private->lock);
- free(private);
+ 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(en50221_app_mmi mmi, uint16_t session_number)
+void en50221_app_mmi_clear_session(struct en50221_app_mmi *mmi,
+ uint16_t session_number)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- struct en50221_app_mmi_session *cur_s = private->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 {
- private->sessions = cur_s->next;
- }
- free(cur_s);
- return;
- }
-
- prev_s = cur_s;
- cur_s=cur_s->next;
- }
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_close_callback callback, void *arg)
+void en50221_app_mmi_register_close_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_close_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->closecallback = callback;
- private->closecallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_display_control_callback callback, void *arg)
+void en50221_app_mmi_register_display_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_display_control_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->displaycontrolcallback = callback;
- private->displaycontrolcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_keypad_control_callback callback, void *arg)
+void en50221_app_mmi_register_keypad_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_keypad_control_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->keypadcontrolcallback = callback;
- private->keypadcontrolcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_subtitle_segment_callback callback, void *arg)
+void en50221_app_mmi_register_subtitle_segment_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_segment_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->subtitlesegmentcallback = callback;
- private->subtitlesegmentcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_scene_end_mark_callback callback, void *arg)
+void en50221_app_mmi_register_scene_end_mark_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_end_mark_callback callback, void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->sceneendmarkcallback = callback;
- private->sceneendmarkcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_scene_control_callback callback, void *arg)
+void en50221_app_mmi_register_scene_control_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_scene_control_callback callback, void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->scenecontrolcallback = callback;
- private->scenecontrolcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_subtitle_download_callback callback, void *arg)
+void en50221_app_mmi_register_subtitle_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_subtitle_download_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->subtitledownloadcallback = callback;
- private->subtitledownloadcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_mmi mmi,
- en50221_app_mmi_flush_download_callback callback, void *arg)
+void en50221_app_mmi_register_flush_download_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_flush_download_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->flushdownloadcallback = callback;
- private->flushdownloadcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&mmi->lock);
+ mmi->flushdownloadcallback = callback;
+ mmi->flushdownloadcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
}
-void en50221_app_mmi_register_enq_callback(en50221_app_mmi mmi,
- en50221_app_mmi_enq_callback callback, void *arg)
+void en50221_app_mmi_register_enq_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_enq_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->enqcallback = callback;
- private->enqcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&mmi->lock);
+ mmi->enqcallback = callback;
+ mmi->enqcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
}
-void en50221_app_mmi_register_menu_callback(en50221_app_mmi mmi,
- en50221_app_mmi_menu_callback callback, void *arg)
+void en50221_app_mmi_register_menu_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_menu_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->menucallback = callback;
- private->menucallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&mmi->lock);
+ mmi->menucallback = callback;
+ mmi->menucallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
}
-void en50221_app_mmi_register_list_callback(en50221_app_mmi mmi,
- en50221_app_mmi_list_callback callback, void *arg)
+void en50221_app_mmi_register_list_callback(struct en50221_app_mmi *mmi,
+ en50221_app_mmi_list_callback callback,
+ void *arg)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
-
- pthread_mutex_lock(&private->lock);
- private->listcallback = callback;
- private->listcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&mmi->lock);
+ mmi->listcallback = callback;
+ mmi->listcallback_arg = arg;
+ pthread_mutex_unlock(&mmi->lock);
}
-int en50221_app_mmi_close(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t cmd_id,
- uint8_t delay)
+int en50221_app_mmi_close(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t cmd_id, uint8_t delay)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, data_length);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t reply_id,
- struct en502221_app_mmi_display_reply_details *details)
+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)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, iov_count);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t keycode)
+int en50221_app_mmi_keypress(struct en50221_app_mmi *mmi,
+ uint16_t session_number, uint8_t keycode)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t display_message_id)
+int en50221_app_mmi_display_message(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint8_t display_message_id)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t decoder_continue,
- uint8_t scene_reveal,
- uint8_t scene_tag)
+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)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint16_t object_id,
- uint8_t download_reply_id)
+int en50221_app_mmi_download_reply(struct en50221_app_mmi *mmi,
+ uint16_t session_number,
+ uint16_t object_id,
+ uint8_t download_reply_id)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 7);
+ 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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t answ_id,
- uint8_t *text,
- uint32_t text_count)
+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)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, iov_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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t choice_ref)
+int en50221_app_mmi_menu_answ(struct en50221_app_mmi *mmi,
+ uint16_t session_number, uint8_t choice_ref)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- 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 private->funcs->send_data(private->funcs->arg, session_number, data, 5);
+ 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(en50221_app_mmi mmi,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_mmi_private *private = (struct en50221_app_mmi_private *) mmi;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_DISPLAY_CONTROL:
- return en50221_app_mmi_parse_display_control(private, slot_id, session_number, data+3, data_length-3);
- case TAG_KEYPAD_CONTROL:
- return en50221_app_mmi_parse_keypad_control(private, slot_id, session_number, data+3, data_length-3);
- case TAG_ENQUIRY:
- return en50221_app_mmi_parse_enq(private, slot_id, session_number, data+3, data_length-3);
- case TAG_MENU_LAST:
- return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 1, data+3, data_length-3);
- case TAG_MENU_MORE:
- return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 0, data+3, data_length-3);
- case TAG_LIST_LAST:
- return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 1, data+3, data_length-3);
- case TAG_LIST_MORE:
- return en50221_app_mmi_parse_list_menu(private, slot_id, session_number, tag, 0, data+3, data_length-3);
- case TAG_SUBTITLE_SEGMENT_LAST:
- return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 1, data+3, data_length-3);
- case TAG_SUBTITLE_SEGMENT_MORE:
- return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 0, data+3, data_length-3);
- case TAG_SCENE_END_MARK:
- return en50221_app_mmi_parse_scene_end_mark(private, slot_id, session_number, data+3, data_length-3);
- case TAG_SCENE_CONTROL:
- return en50221_app_mmi_parse_scene_control(private, slot_id, session_number, data+3, data_length-3);
- case TAG_SUBTITLE_DOWNLOAD_LAST:
- return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 1, data+3, data_length-3);
- case TAG_SUBTITLE_DOWNLOAD_MORE:
- return en50221_app_mmi_parse_subtitle(private, slot_id, session_number, tag, 0, data+3, data_length-3);
- case TAG_FLUSH_DOWNLOAD:
- return en50221_app_mmi_parse_flush_download(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_mmi_close_callback cb = private->closecallback;
- void *cb_arg = private->closecallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, cmd_id, delay);
- }
- return 0;
+ // 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_display_control_callback cb = private->displaycontrolcallback;
- void *cb_arg = private->displaycontrolcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, cmd_id, mmi_mode);
- }
- return 0;
+ // 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_keypad_control_callback cb = private->keypadcontrolcallback;
- void *cb_arg = private->keypadcontrolcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, cmd_id, keycodes, asn_data_length-1);
- }
- return 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;
+ }
+ 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_enq_callback cb = private->enqcallback;
- void *cb_arg = private->enqcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, blind_answer, answer_length, text, asn_data_length - 2);
- }
- return 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;
+ }
+ 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_private *private,
- 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_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(&private->lock);
- uint8_t *outdata;
- uint32_t outdata_length;
- int dfstatus = en50221_app_mmi_defragment(private, session_number, tag_id, more_last,
- data, asn_data_length,
- &outdata, &outdata_length);
- if (dfstatus <= 0) {
- pthread_mutex_unlock(&private->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(&private->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(&private->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(&private->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(&private->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 = private->menucallback;
- void *cb_arg = private->menucallback_arg;
- pthread_mutex_unlock(&private->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 = private->listcallback;
- void *cb_arg = private->listcallback_arg;
- pthread_mutex_unlock(&private->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(&private->lock);
- break;
- }
+ 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;
+ 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_private *private,
- 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)
{
- // 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(&private->lock);
- uint8_t *outdata;
- uint32_t outdata_length;
- int dfstatus = en50221_app_mmi_defragment(private, session_number, tag_id, more_last,
- data, asn_data_length,
- &outdata, &outdata_length);
- if (dfstatus <= 0) {
- pthread_mutex_unlock(&private->lock);
- return dfstatus;
- }
-
- // do callback
- int cbstatus = 0;
- switch(tag_id) {
- case TAG_SUBTITLE_SEGMENT_LAST:
- {
- en50221_app_mmi_subtitle_segment_callback cb = private->subtitlesegmentcallback;
- void *cb_arg = private->subtitlesegmentcallback_arg;
- pthread_mutex_unlock(&private->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 = private->subtitledownloadcallback;
- void *cb_arg = private->subtitledownloadcallback_arg;
- pthread_mutex_unlock(&private->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;
+ // 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_scene_end_mark_callback cb = private->sceneendmarkcallback;
- void *cb_arg = private->sceneendmarkcallback_arg;
- pthread_mutex_unlock(&private->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;
+ // 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_scene_control_callback cb = private->scenecontrolcallback;
- void *cb_arg = private->scenecontrolcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number,
- (flags & 0x80) ? 1 : 0,
- (flags & 0x40) ? 1 : 0,
- flags & 0x0f);
- }
- return 0;
+ // 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- 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)
{
- // 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(&private->lock);
- en50221_app_mmi_flush_download_callback cb = private->flushdownloadcallback;
- void *cb_arg = private->flushdownloadcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number);
- }
- return 0;
+ // 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_private *private,
- 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(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 = private->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 = private->sessions;
- private->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;
+ 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)
+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;
- }
- }
+ 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h
index 486080f..5c5b727 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_mmi.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -88,48 +87,48 @@ extern "C"
* 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;
+ uint8_t display_depth;
+ uint8_t pixels_per_byte;
+ uint8_t region_overhead;
};
/**
* Details returned with a display_reply
*/
-struct en502221_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;
+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;
+ uint8_t *text;
+ uint32_t text_length;
};
/**
@@ -142,8 +141,11 @@ struct en50221_app_mmi_text {
* @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);
+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.
@@ -155,8 +157,11 @@ typedef int (*en50221_app_mmi_close_callback)(void *arg, uint8_t slot_id, uint16
* @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);
+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.
@@ -169,8 +174,12 @@ typedef int (*en50221_app_mmi_display_control_callback)(void *arg, uint8_t slot_
* @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);
+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.
@@ -182,8 +191,11 @@ typedef int (*en50221_app_mmi_keypad_control_callback)(void *arg, uint8_t slot_i
* @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);
+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.
@@ -197,9 +209,13 @@ typedef int (*en50221_app_mmi_subtitle_segment_callback)(void *arg, uint8_t slot
* @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);
+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.
@@ -212,9 +228,12 @@ typedef int (*en50221_app_mmi_scene_end_mark_callback)(void *arg, uint8_t slot_i
* @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);
+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.
@@ -226,8 +245,11 @@ typedef int (*en50221_app_mmi_scene_control_callback)(void *arg, uint8_t slot_id
* @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);
+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.
@@ -237,7 +259,9 @@ typedef int (*en50221_app_mmi_subtitle_download_callback)(void *arg, uint8_t slo
* @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);
+typedef int (*en50221_app_mmi_flush_download_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number);
/**
* Type definition for enq callback.
@@ -251,9 +275,13 @@ typedef int (*en50221_app_mmi_flush_download_callback)(void *arg, uint8_t slot_i
* @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);
+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.
@@ -270,12 +298,16 @@ typedef int (*en50221_app_mmi_enq_callback)(void *arg, uint8_t slot_id, uint16_t
* @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);
+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.
@@ -292,17 +324,21 @@ typedef int (*en50221_app_mmi_menu_callback)(void *arg, uint8_t slot_id, uint16_
* @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);
+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.
*/
-typedef void *en50221_app_mmi;
+struct en50221_app_mmi;
/**
* Create an instance of the mmi resource.
@@ -310,14 +346,14 @@ typedef void *en50221_app_mmi;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_mmi en50221_app_mmi_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_mmi mmi);
+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.
@@ -325,7 +361,8 @@ extern void en50221_app_mmi_destroy(en50221_app_mmi mmi);
* @param mmi mmi resource instance.
* @param session_number The session concerned.
*/
-extern void en50221_app_mmi_clear_session(en50221_app_mmi mmi, uint16_t session_number);
+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.
@@ -334,8 +371,9 @@ extern void en50221_app_mmi_clear_session(en50221_app_mmi mmi, uint16_t session_
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_close_callback callback, void *arg);
+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.
@@ -344,8 +382,9 @@ extern void en50221_app_mmi_register_close_callback(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_display_control_callback callback, void *arg);
+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.
@@ -354,8 +393,9 @@ extern void en50221_app_mmi_register_display_control_callback(en50221_app_mmi mm
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_keypad_control_callback callback, void *arg);
+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.
@@ -364,8 +404,9 @@ extern void en50221_app_mmi_register_keypad_control_callback(en50221_app_mmi mmi
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_subtitle_segment_callback callback, void *arg);
+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.
@@ -374,8 +415,9 @@ extern void en50221_app_mmi_register_subtitle_segment_callback(en50221_app_mmi m
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_scene_end_mark_callback callback, void *arg);
+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.
@@ -384,8 +426,9 @@ extern void en50221_app_mmi_register_scene_end_mark_callback(en50221_app_mmi mmi
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_scene_control_callback callback, void *arg);
+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.
@@ -394,8 +437,9 @@ extern void en50221_app_mmi_register_scene_control_callback(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_subtitle_download_callback callback, void *arg);
+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.
@@ -404,8 +448,9 @@ extern void en50221_app_mmi_register_subtitle_download_callback(en50221_app_mmi
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_flush_download_callback callback, void *arg);
+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.
@@ -414,8 +459,9 @@ extern void en50221_app_mmi_register_flush_download_callback(en50221_app_mmi mmi
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_enq_callback callback, void *arg);
+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.
@@ -424,8 +470,9 @@ extern void en50221_app_mmi_register_enq_callback(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_menu_callback callback, void *arg);
+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.
@@ -434,8 +481,9 @@ extern void en50221_app_mmi_register_menu_callback(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- en50221_app_mmi_list_callback callback, void *arg);
+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.
@@ -446,10 +494,9 @@ extern void en50221_app_mmi_register_list_callback(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t cmd_id,
- uint8_t delay);
+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.
@@ -460,10 +507,10 @@ extern int en50221_app_mmi_close(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t reply_id,
- struct en502221_app_mmi_display_reply_details *details);
+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.
@@ -473,9 +520,9 @@ extern int en50221_app_mmi_display_reply(en50221_app_mmi mmi,
* @param keycode The keycode.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_mmi_keypress(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t keycode);
+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.
@@ -485,9 +532,9 @@ extern int en50221_app_mmi_keypress(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t display_message_id);
+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.
@@ -499,11 +546,11 @@ extern int en50221_app_mmi_display_message(en50221_app_mmi mmi,
* @param scene_tag Scene tag this responds to.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_mmi_scene_done(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t decoder_continue,
- uint8_t scene_reveal,
- uint8_t scene_tag);
+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.
@@ -514,10 +561,10 @@ extern int en50221_app_mmi_scene_done(en50221_app_mmi mmi,
* @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(en50221_app_mmi mmi,
- uint16_t session_number,
- uint16_t object_id,
- uint8_t download_reply_id);
+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.
@@ -529,11 +576,11 @@ extern int en50221_app_mmi_download_reply(en50221_app_mmi mmi,
* @param text_count Length of text.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_mmi_answ(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t answ_id,
- uint8_t *text,
- uint32_t text_count);
+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.
@@ -543,9 +590,9 @@ extern int en50221_app_mmi_answ(en50221_app_mmi mmi,
* @param choice_ref Option chosen by user (0=>canceled).
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_mmi_menu_answ(en50221_app_mmi mmi,
- uint16_t session_number,
- uint8_t choice_ref);
+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.
@@ -558,14 +605,14 @@ extern int en50221_app_mmi_menu_answ(en50221_app_mmi mmi,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_mmi_message(en50221_app_mmi mmi,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c
index 71f2b19..7a5bc2f 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -29,266 +29,279 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_rm_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_rm {
+ struct en50221_app_send_functions *funcs;
- en50221_app_rm_enq_callback enqcallback;
- void *enqcallback_arg;
+ en50221_app_rm_enq_callback enqcallback;
+ void *enqcallback_arg;
- en50221_app_rm_reply_callback replycallback;
- void *replycallback_arg;
+ en50221_app_rm_reply_callback replycallback;
+ void *replycallback_arg;
- en50221_app_rm_changed_callback changedcallback;
- void *changedcallback_arg;
+ en50221_app_rm_changed_callback changedcallback;
+ void *changedcallback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_rm_parse_profile_enq(struct en50221_app_rm_private *private,
- 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_private *private,
- 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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
-
-
-en50221_app_rm en50221_app_rm_create(struct en50221_app_send_functions *funcs)
+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_private *private = NULL;
-
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_rm_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->enqcallback = NULL;
- private->replycallback = NULL;
- private->changedcallback = NULL;
-
- pthread_mutex_init(&private->lock, NULL);
-
- // done
- return private;
+ 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(en50221_app_rm rm)
+void en50221_app_rm_destroy(struct en50221_app_rm *rm)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&rm->lock);
+ free(rm);
}
-void en50221_app_rm_register_enq_callback(en50221_app_rm rm,
- en50221_app_rm_enq_callback callback, void *arg)
+void en50221_app_rm_register_enq_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_enq_callback
+ callback, void *arg)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
-
- pthread_mutex_lock(&private->lock);
- private->enqcallback = callback;
- private->enqcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&rm->lock);
+ rm->enqcallback = callback;
+ rm->enqcallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
}
-void en50221_app_rm_register_reply_callback(en50221_app_rm rm,
- en50221_app_rm_reply_callback callback, void *arg)
+void en50221_app_rm_register_reply_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_reply_callback
+ callback, void *arg)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
-
- pthread_mutex_lock(&private->lock);
- private->replycallback = callback;
- private->replycallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&rm->lock);
+ rm->replycallback = callback;
+ rm->replycallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
}
-void en50221_app_rm_register_changed_callback(en50221_app_rm rm,
- en50221_app_rm_changed_callback callback, void *arg)
+void en50221_app_rm_register_changed_callback(struct en50221_app_rm *rm,
+ en50221_app_rm_changed_callback
+ callback, void *arg)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
-
- pthread_mutex_lock(&private->lock);
- private->changedcallback = callback;
- private->changedcallback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&rm->lock);
+ rm->changedcallback = callback;
+ rm->changedcallback_arg = arg;
+ pthread_mutex_unlock(&rm->lock);
}
-int en50221_app_rm_enq(en50221_app_rm rm, uint16_t session_number)
+int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
- uint8_t buf[4];
+ 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;
+ // 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 private->funcs->send_data(private->funcs->arg, session_number, buf, 4);
+ // create the data and send it
+ return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4);
}
-int en50221_app_rm_reply(en50221_app_rm rm, uint16_t session_number,
- uint32_t resource_id_count,
- uint32_t *resource_ids)
+int en50221_app_rm_reply(struct en50221_app_rm *rm,
+ uint16_t session_number,
+ uint32_t resource_id_count,
+ uint32_t * resource_ids)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 2);
+ 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(en50221_app_rm rm, uint16_t session_number)
+int en50221_app_rm_changed(struct en50221_app_rm *rm,
+ uint16_t session_number)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
- uint8_t buf[4];
+ 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;
+ // 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 private->funcs->send_data(private->funcs->arg, session_number, buf, 4);
+ // create the data and send it
+ return rm->funcs->send_data(rm->funcs->arg, session_number, buf, 4);
}
-int en50221_app_rm_message(en50221_app_rm rm,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_rm_private *private = (struct en50221_app_rm_private *) rm;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_PROFILE:
- return en50221_app_rm_parse_profile_reply(private, slot_id, session_number, data+3, data_length-3);
- case TAG_PROFILE_CHANGE:
- return en50221_app_rm_parse_profile_change(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_rm_enq_callback cb = private->enqcallback;
- void *cb_arg = private->enqcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number);
- }
- return 0;
+ (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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_rm_reply_callback cb = private->replycallback;
- void *cb_arg = private->replycallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, resources_count, resource_ids);
- }
- return 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;
+ }
+ 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_private *private,
- 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)
{
- (void)data;
- (void)data_length;
-
- pthread_mutex_lock(&private->lock);
- en50221_app_rm_changed_callback cb = private->changedcallback;
- void *cb_arg = private->changedcallback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number);
- }
- return 0;
+ (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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h
index aa91ff5..ec97372 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_rm.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -44,7 +43,9 @@ extern "C"
* @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);
+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
@@ -57,9 +58,11 @@ typedef int (*en50221_app_rm_enq_callback)(void *arg, uint8_t slot_id, uint16_t
* @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);
+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.
@@ -69,14 +72,16 @@ typedef int (*en50221_app_rm_reply_callback)(void *arg, uint8_t slot_id, uint16_
* @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);
+typedef int (*en50221_app_rm_changed_callback) (void *arg,
+ uint8_t slot_id,
+ uint16_t session_number);
/**
* Opaque type representing a resource manager.
*/
-typedef void *en50221_app_rm;
+struct en50221_app_rm;
/**
* Create an instance of the resource manager.
@@ -84,14 +89,14 @@ typedef void *en50221_app_rm;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_rm en50221_app_rm_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_rm rm);
+extern void en50221_app_rm_destroy(struct en50221_app_rm *rm);
/**
* Register the callback for when we receive a profile_enq from a CAM.
@@ -100,8 +105,9 @@ extern void en50221_app_rm_destroy(en50221_app_rm rm);
* @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(en50221_app_rm rm,
- en50221_app_rm_enq_callback callback, void *arg);
+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.
@@ -110,8 +116,9 @@ extern void en50221_app_rm_register_enq_callback(en50221_app_rm rm,
* @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(en50221_app_rm rm,
- en50221_app_rm_reply_callback callback, void *arg);
+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.
@@ -120,8 +127,9 @@ extern void en50221_app_rm_register_reply_callback(en50221_app_rm rm,
* @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(en50221_app_rm rm,
- en50221_app_rm_changed_callback callback, void *arg);
+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.
@@ -130,7 +138,7 @@ extern void en50221_app_rm_register_changed_callback(en50221_app_rm rm,
* @param session_number Session number to send it on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_rm_enq(en50221_app_rm rm, uint16_t session_number);
+extern int en50221_app_rm_enq(struct en50221_app_rm *rm, uint16_t session_number);
/**
* Send a profile_reply to a CAM.
@@ -141,9 +149,10 @@ extern int en50221_app_rm_enq(en50221_app_rm rm, uint16_t session_number);
* @param resource_ids The resource IDs themselves
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_rm_reply(en50221_app_rm rm, uint16_t session_number,
- uint32_t resource_id_count,
- uint32_t *resource_ids);
+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.
@@ -152,7 +161,7 @@ extern int en50221_app_rm_reply(en50221_app_rm rm, uint16_t session_number,
* @param session_number Session number to send it on.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_rm_changed(en50221_app_rm rm, uint16_t session_number);
+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.
@@ -165,14 +174,14 @@ extern int en50221_app_rm_changed(en50221_app_rm rm, uint16_t session_number);
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_rm_message(en50221_app_rm rm,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c
index c0f6961..763c6c4 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -28,188 +28,186 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_smartcard_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_smartcard {
+ struct en50221_app_send_functions *funcs;
- en50221_app_smartcard_command_callback command_callback;
- void *command_callback_arg;
+ en50221_app_smartcard_command_callback command_callback;
+ void *command_callback_arg;
- en50221_app_smartcard_send_callback send_callback;
- void *send_callback_arg;
+ en50221_app_smartcard_send_callback send_callback;
+ void *send_callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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_private *private,
- 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);
-en50221_app_smartcard en50221_app_smartcard_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_smartcard *en50221_app_smartcard_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_smartcard_private *private = NULL;
+ struct en50221_app_smartcard *smartcard = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_smartcard_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->command_callback = NULL;
- private->send_callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&smartcard->lock, NULL);
- // done
- return private;
+ // done
+ return smartcard;
}
-void en50221_app_smartcard_destroy(en50221_app_smartcard smartcard)
+void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&smartcard->lock);
+ free(smartcard);
}
-void en50221_app_smartcard_register_command_callback(en50221_app_smartcard smartcard,
- en50221_app_smartcard_command_callback callback, void *arg)
+void en50221_app_smartcard_register_command_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_command_callback callback, void *arg)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
-
- pthread_mutex_lock(&private->lock);
- private->command_callback = callback;
- private->command_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_smartcard smartcard,
- en50221_app_smartcard_send_callback callback, void *arg)
+void en50221_app_smartcard_register_send_callback(struct en50221_app_smartcard *smartcard,
+ en50221_app_smartcard_send_callback callback, void *arg)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
-
- pthread_mutex_lock(&private->lock);
- private->send_callback = callback;
- private->send_callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ 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(en50221_app_smartcard smartcard,
- uint16_t session_number,
- uint8_t reply_id,
- uint8_t status,
- uint8_t *data,
- uint32_t data_length)
+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)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iovec, iov_count);
+ 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(en50221_app_smartcard smartcard,
- uint16_t session_number,
- uint8_t *data,
- uint32_t data_length,
- uint8_t SW1,
- uint8_t SW2)
+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)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
- 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 private->funcs->send_datav(private->funcs->arg, session_number, iov, 3);
+ 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(en50221_app_smartcard smartcard,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_smartcard_private *private = (struct en50221_app_smartcard_private *) smartcard;
- (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(private, slot_id, session_number, data+3, data_length-3);
- case TAG_SMARTCARD_SEND:
- return en50221_app_smartcard_parse_send(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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;
}
@@ -218,76 +216,81 @@ int en50221_app_smartcard_message(en50221_app_smartcard smartcard,
-static int en50221_app_smartcard_parse_command(struct en50221_app_smartcard_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_smartcard_command_callback cb = private->command_callback;
- void *cb_arg = private->command_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, command_id);
- }
- return 0;
+ 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_private *private,
- 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)
{
- // 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(&private->lock);
- en50221_app_smartcard_send_callback cb = private->send_callback;
- void *cb_arg = private->send_callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, CLA, INS, P1, P2, data_in, length_in, length_out);
- }
- return 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 < 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h
index 546e8be..bbad4a9 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_smartcard.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -68,8 +67,10 @@ extern "C"
* @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);
+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.
@@ -86,15 +87,21 @@ typedef int (*en50221_app_smartcard_command_callback)(void *arg, uint8_t slot_id
* @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);
+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.
*/
-typedef void *en50221_app_smartcard;
+struct en50221_app_smartcard;
/**
* Create an instance of the smartcard resource.
@@ -102,14 +109,15 @@ typedef void *en50221_app_smartcard;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_smartcard en50221_app_smartcard_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_smartcard smartcard);
+extern void en50221_app_smartcard_destroy(struct en50221_app_smartcard *smartcard);
/**
* Register the callback for when we receive a comms command.
@@ -118,8 +126,9 @@ extern void en50221_app_smartcard_destroy(en50221_app_smartcard smartcard);
* @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(en50221_app_smartcard smartcard,
- en50221_app_smartcard_command_callback callback, void *arg);
+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.
@@ -128,8 +137,9 @@ extern void en50221_app_smartcard_register_command_callback(en50221_app_smartcar
* @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(en50221_app_smartcard smartcard,
- en50221_app_smartcard_send_callback callback, void *arg);
+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.
@@ -142,12 +152,12 @@ extern void en50221_app_smartcard_register_send_callback(en50221_app_smartcard s
* @param data_length Length of data to send.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_smartcard_command_reply(en50221_app_smartcard smartcard,
- uint16_t session_number,
- uint8_t reply_id,
- uint8_t status,
- uint8_t *data,
- uint32_t data_length);
+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.
@@ -160,12 +170,11 @@ extern int en50221_app_smartcard_command_reply(en50221_app_smartcard smartcard,
* @param SW2 SW2 value.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_smartcard_receive(en50221_app_smartcard smartcard,
- uint16_t session_number,
- uint8_t *data,
- uint32_t data_length,
- uint8_t SW1,
- uint8_t SW2);
+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.
@@ -178,14 +187,14 @@ extern int en50221_app_smartcard_receive(en50221_app_smartcard smartcard,
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_smartcard_message(en50221_app_smartcard smartcard,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h
index 357999b..0f5c2fc 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_tags.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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
@@ -17,7 +17,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __EN50221_APP_TAGS_H__
@@ -25,7 +25,7 @@
/* Resource Manager */
#define TAG_PROFILE_ENQUIRY 0x9f8010
-#define TAG_PROFILE 0x9f8011
+#define TAG_PROFILE 0x9f8011
#define TAG_PROFILE_CHANGE 0x9f8012
/* Application Info */
@@ -85,20 +85,20 @@
#define TAG_COMMS_RECV_MORE 0x9f8c06
/* Authentication */
-#define TAG_AUTH_REQ 0x9f8200
-#define TAG_AUTH_RESP 0x9f8201
+#define TAG_AUTH_REQ 0x9f8200
+#define TAG_AUTH_RESP 0x9f8201
/* Teletext */
-#define TAG_TELETEXT_EBU 0x9f9000
+#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
+#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
+#define TAG_EPG_ENQUIRY 0x9f8f00
+#define TAG_EPG_REPLY 0x9f8f01
#endif
diff --git a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c
index 8e7f9d9..b839407 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
@@ -28,112 +28,114 @@
#include "en50221_app_tags.h"
#include "asn_1.h"
-struct en50221_app_teletext_private {
- struct en50221_app_send_functions *funcs;
+struct en50221_app_teletext {
+ struct en50221_app_send_functions *funcs;
- en50221_app_teletext_callback callback;
- void *callback_arg;
+ en50221_app_teletext_callback callback;
+ void *callback_arg;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
-static int en50221_app_teletext_parse_ebu(struct en50221_app_teletext_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length);
+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);
-en50221_app_teletext en50221_app_teletext_create(struct en50221_app_send_functions *funcs)
+struct en50221_app_teletext *
+ en50221_app_teletext_create(struct en50221_app_send_functions *funcs)
{
- struct en50221_app_teletext_private *private = NULL;
+ struct en50221_app_teletext *teletext = NULL;
- // create structure and set it up
- private = malloc(sizeof(struct en50221_app_teletext_private));
- if (private == NULL) {
- return NULL;
- }
- private->funcs = funcs;
- private->callback = 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(&private->lock, NULL);
+ pthread_mutex_init(&teletext->lock, NULL);
- // done
- return private;
+ // done
+ return teletext;
}
-void en50221_app_teletext_destroy(en50221_app_teletext teletext)
+void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext)
{
- struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext;
-
- pthread_mutex_destroy(&private->lock);
- free(private);
+ pthread_mutex_destroy(&teletext->lock);
+ free(teletext);
}
-void en50221_app_teletext_register_callback(en50221_app_teletext teletext,
- en50221_app_teletext_callback callback, void *arg)
+void en50221_app_teletext_register_callback(struct en50221_app_teletext *teletext,
+ en50221_app_teletext_callback callback, void *arg)
{
- struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext;
-
- pthread_mutex_lock(&private->lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->lock);
+ pthread_mutex_lock(&teletext->lock);
+ teletext->callback = callback;
+ teletext->callback_arg = arg;
+ pthread_mutex_unlock(&teletext->lock);
}
-int en50221_app_teletext_message(en50221_app_teletext teletext,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length)
+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)
{
- struct en50221_app_teletext_private *private = (struct en50221_app_teletext_private *) teletext;
- (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(private, slot_id, session_number, data+3, data_length-3);
- }
-
- print(LOG_LEVEL, ERROR, 1, "Received unexpected tag %x\n", tag);
- return -1;
+ (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_private *private,
- uint8_t slot_id, uint16_t session_number,
- uint8_t *data, uint32_t data_length)
+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(&private->lock);
- en50221_app_teletext_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->lock);
- if (cb) {
- return cb(cb_arg, slot_id, session_number, teletext_data, asn_data_length);
- }
- return 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;
+ }
+ 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h
index 3dced66..b5b85f1 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_teletext.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -46,14 +45,16 @@ extern "C"
* @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);
+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.
*/
-typedef void *en50221_app_teletext;
+struct en50221_app_teletext;
/**
* Create an instance of the teletext resource.
@@ -61,14 +62,15 @@ typedef void *en50221_app_teletext;
* @param funcs Send functions to use.
* @return Instance, or NULL on failure.
*/
-extern en50221_app_teletext en50221_app_teletext_create(struct en50221_app_send_functions *funcs);
+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(en50221_app_teletext teletext);
+extern void en50221_app_teletext_destroy(struct en50221_app_teletext *teletext);
/**
* Register the callback for when we receive a request.
@@ -77,8 +79,9 @@ extern void en50221_app_teletext_destroy(en50221_app_teletext teletext);
* @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(en50221_app_teletext teletext,
- en50221_app_teletext_callback callback, void *arg);
+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.
@@ -91,14 +94,14 @@ extern void en50221_app_teletext_register_callback(en50221_app_teletext teletext
* @param data_length Length of data in bytes.
* @return 0 on success, -1 on failure.
*/
-extern int en50221_app_teletext_message(en50221_app_teletext teletext,
- uint8_t slot_id,
- uint16_t session_number,
- uint32_t resource_id,
- uint8_t *data, uint32_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c
index cbbbe2e..df2632a 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,20 +18,21 @@
You should 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
+ 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)
+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;
+ // 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;
+ 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h
index d20c13b..5c64760 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_app_utils.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,15 +18,14 @@
You should 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
+ 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"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -41,30 +40,39 @@ extern "C"
* 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;
+ 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.
- */
- int (*send_data)(void *arg, uint16_t session_number, uint8_t *data, uint16_t data_length);
-
- /**
- * Send vector data.
- */
- int (*send_datav)(void *arg, uint16_t session_number, struct iovec *vector, int iov_count);
+ /**
+ * Argument to pass to these functions.
+ */
+ void *arg;
+
+ /**
+ * Send data.
+ */
+ en50221_send_data send_data;
+
+ /**
+ * Send vector data.
+ */
+ en50221_send_datav send_datav;
};
/**
@@ -85,7 +93,8 @@ struct en50221_app_send_functions {
* @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);
+ 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.
@@ -93,13 +102,11 @@ struct en50221_app_public_resource_id *
* @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);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h
index 5ac57fe..0b53087 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_errno.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 session layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,35 +18,32 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef EN50221_ERRNO
#define EN50221_ERRNO 1
#ifdef __cplusplus
-extern "C"
-{
+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. */
+#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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c
index 15cd52a..3fb9902 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
@@ -37,918 +37,1019 @@
// 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
+#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;
+ uint8_t state;
+ uint32_t resource_id;
+ uint8_t slot_id;
+ uint8_t connection_id;
- en50221_sl_resource_callback callback;
- void *callback_arg;
+ en50221_sl_resource_callback callback;
+ void *callback_arg;
- pthread_mutex_t session_lock;
+ pthread_mutex_t session_lock;
};
-struct en50221_session_layer_private
-{
- uint32_t max_sessions;
- en50221_transport_layer tl;
+struct en50221_session_layer {
+ uint32_t max_sessions;
+ struct en50221_transport_layer *tl;
- en50221_sl_lookup_callback lookup;
- void *lookup_arg;
+ en50221_sl_lookup_callback lookup;
+ void *lookup_arg;
- en50221_sl_session_callback session;
- void *session_arg;
+ en50221_sl_session_callback session;
+ void *session_arg;
- pthread_mutex_t global_lock;
- pthread_mutex_t setcallback_lock;
+ pthread_mutex_t global_lock;
+ pthread_mutex_t setcallback_lock;
- int error;
+ int error;
- struct en50221_session *sessions;
+ 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_private *private,
- uint32_t resource_id,
- uint8_t slot_id,
- uint8_t connection_id,
- en50221_sl_resource_callback callback, void* arg);
+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);
-en50221_session_layer en50221_sl_create(en50221_transport_layer tl,
- uint32_t max_sessions)
+struct en50221_session_layer *en50221_sl_create(struct en50221_transport_layer *tl,
+ uint32_t max_sessions)
{
- struct en50221_session_layer_private *private = NULL;
- uint32_t i;
-
- // setup structure
- private = (struct en50221_session_layer_private*) malloc(sizeof(struct en50221_session_layer_private));
- if (private == NULL)
- goto error_exit;
- private->max_sessions = max_sessions;
- private->lookup = NULL;
- private->session = NULL;
- private->tl = tl;
- private->error = 0;
-
- // init the mutex
- pthread_mutex_init(&private->global_lock, NULL);
- pthread_mutex_init(&private->setcallback_lock, NULL);
-
- // create the slots
- private->sessions = malloc(sizeof(struct en50221_session) * max_sessions);
- if (private->sessions == NULL)
- goto error_exit;
-
- // set them up
- for(i=0; i< max_sessions; i++) {
- private->sessions[i].state = S_STATE_IDLE;
- private->sessions[i].callback = NULL;
-
- pthread_mutex_init(&private->sessions[i].session_lock, NULL);
- }
-
- // register ourselves with the transport layer
- en50221_tl_register_callback(tl, en50221_sl_transport_callback, private);
-
- return private;
+ 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(private);
- return NULL;
+ en50221_sl_destroy(sl);
+ return NULL;
}
-void en50221_sl_destroy(en50221_session_layer sl)
+void en50221_sl_destroy(struct en50221_session_layer *sl)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
- uint32_t i;
-
- if (private) {
- if (private->sessions) {
- for(i=0; i< private->max_sessions; i++) {
- pthread_mutex_destroy(&private->sessions[i].session_lock);
- }
- free(private->sessions);
- }
-
- pthread_mutex_destroy(&private->setcallback_lock);
- pthread_mutex_destroy(&private->global_lock);
-
- free(private);
- }
+ 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(en50221_session_layer tl)
+int en50221_sl_get_error(struct en50221_session_layer *sl)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) tl;
- return private->error;
+ return sl->error;
}
-void en50221_sl_register_lookup_callback(en50221_session_layer sl, en50221_sl_lookup_callback callback, void *arg)
+void en50221_sl_register_lookup_callback(struct en50221_session_layer *sl,
+ en50221_sl_lookup_callback
+ callback, void *arg)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- pthread_mutex_lock(&private->setcallback_lock);
- private->lookup = callback;
- private->lookup_arg = arg;
- pthread_mutex_unlock(&private->setcallback_lock);
+ 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(en50221_session_layer sl,
- en50221_sl_session_callback callback, void *arg)
+void en50221_sl_register_session_callback(struct en50221_session_layer *sl,
+ en50221_sl_session_callback
+ callback, void *arg)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- pthread_mutex_lock(&private->setcallback_lock);
- private->session = callback;
- private->session_arg = arg;
- pthread_mutex_unlock(&private->setcallback_lock);
+ pthread_mutex_lock(&sl->setcallback_lock);
+ sl->session = callback;
+ sl->session_arg = arg;
+ pthread_mutex_unlock(&sl->setcallback_lock);
}
-int en50221_sl_create_session(en50221_session_layer sl, int slot_id, uint8_t connection_id, uint32_t resource_id,
- en50221_sl_resource_callback callback, void* arg)
+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)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- // lookup next free session_id:
- pthread_mutex_lock(&private->global_lock);
- int session_number = en50221_sl_alloc_new_session(private, resource_id, slot_id, connection_id, callback, arg);
- if (session_number == -1) {
- pthread_mutex_unlock(&private->global_lock);
- return -1;
- }
- pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 8)) {
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (private->sessions[session_number].state == S_STATE_IN_CREATION) {
- private->sessions[session_number].state = S_STATE_IDLE;
- }
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
-
- private->error = en50221_tl_get_error(private->tl);
- return -1;
- }
-
- // ok.
- return session_number;
+ // 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(en50221_session_layer sl, uint16_t session_number)
+int en50221_sl_destroy_session(struct en50221_session_layer *sl,
+ uint16_t session_number)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- if (session_number >= private->max_sessions) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- return -1;
- }
-
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (!(private->sessions[session_number].state & (S_STATE_ACTIVE|S_STATE_IN_DELETION))) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return -1;
- }
-
- // set the state
- private->sessions[session_number].state = S_STATE_IN_DELETION;
-
- // get essential details
- uint8_t slot_id = private->sessions[session_number].slot_id;
- uint8_t connection_id = private->sessions[session_number].connection_id;
- pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 4)) {
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (private->sessions[session_number].state == S_STATE_IN_DELETION) {
- private->sessions[session_number].state = S_STATE_IDLE;
- }
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
-
- private->error = en50221_tl_get_error(private->tl);
- return -1;
- }
-
- return 0;
+ 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(en50221_session_layer sl, uint16_t session_number, uint8_t *data, uint16_t data_length)
+int en50221_sl_send_data(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ uint8_t *data,
+ uint16_t data_length)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- if (session_number >= private->max_sessions) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- return -1;
- }
-
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (private->sessions[session_number].state != S_STATE_ACTIVE) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return -1;
- }
-
- // get essential details
- uint8_t slot_id = private->sessions[session_number].slot_id;
- uint8_t connection_id = private->sessions[session_number].connection_id;
- pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, iov, 2)) {
- private->error = en50221_tl_get_error(private->tl);
- return -1;
- }
-
- return 0;
+ 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(en50221_session_layer sl, uint16_t session_number,
- struct iovec *vector, int iov_count)
+int en50221_sl_send_datav(struct en50221_session_layer *sl,
+ uint16_t session_number,
+ struct iovec *vector,
+ int iov_count)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
-
- if (session_number >= private->max_sessions) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- return -1;
- }
-
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (private->sessions[session_number].state != S_STATE_ACTIVE) {
- private->error = EN50221ERR_BADSESSIONNUMBER;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return -1;
- }
- if (iov_count > 9) {
- private->error = EN50221ERR_IOVLIMIT;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return -1;
- }
- uint8_t slot_id = private->sessions[session_number].slot_id;
- uint8_t connection_id = private->sessions[session_number].connection_id;
- pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, out_iov, iov_count+1)) {
- private->error = en50221_tl_get_error(private->tl);
- return -1;
- }
- return 0;
+ 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(en50221_session_layer sl, int slot_id, uint32_t resource_id,
- uint8_t *data, uint16_t data_length)
+int en50221_sl_broadcast_data(struct en50221_session_layer *sl,
+ int slot_id, uint32_t resource_id,
+ uint8_t *data, uint16_t data_length)
{
- struct en50221_session_layer_private *private = (struct en50221_session_layer_private *) sl;
- uint32_t i;
-
- for(i = 0; i < private->max_sessions; i++)
- {
- pthread_mutex_lock(&private->sessions[i].session_lock);
-
- if (private->sessions[i].state != S_STATE_ACTIVE) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
- if ((slot_id != -1) && (slot_id != private->sessions[i].slot_id)) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
-
- if (private->sessions[i].resource_id == resource_id) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- en50221_sl_send_data(sl, i, data, data_length);
- } else {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- }
- }
-
- return 0;
+ 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_private *private,
- uint8_t *data, uint32_t data_length, uint8_t slot_id, uint8_t connection_id)
+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(&private->setcallback_lock);
- en50221_sl_lookup_callback lcb = private->lookup;
- void *lcb_arg = private->lookup_arg;
- pthread_mutex_unlock(&private->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(&private->global_lock);
- session_number = en50221_sl_alloc_new_session(private, connected_resource_id, slot_id, connection_id,
- resource_callback, resource_arg);
- pthread_mutex_unlock(&private->global_lock);
-
- if (session_number == -1) {
- status = S_STATUS_CLOSE_NO_RES;
- } else {
- // inform upper layers/ check availability
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->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(private->tl, slot_id, connection_id, hdr, 9)) {
- print(LOG_LEVEL, ERROR, 1, "Transport layer error %i occurred\n", en50221_tl_get_error(private->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(&private->sessions[session_number].session_lock);
- if (status != S_STATUS_OPEN) {
- private->sessions[session_number].state = S_STATE_IDLE;
- } else {
- private->sessions[session_number].state = S_STATE_ACTIVE;
- }
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
-
- // tell upper layers
- if (private->sessions[session_number].state == S_STATE_ACTIVE) {
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
-
- if (status == S_STATUS_OPEN) {
- if (cb)
- cb(cb_arg, S_SCALLBACK_REASON_CAMCONNECTED, slot_id, session_number, connected_resource_id);
- } else {
- private->sessions[session_number].state = S_STATE_IDLE;
- if (cb)
- cb(cb_arg, S_SCALLBACK_REASON_CAMCONNECTFAIL, slot_id, session_number, connected_resource_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_private *private,
- uint8_t *data, uint32_t data_length, uint8_t slot_id, uint8_t connection_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 >= private->max_sessions) {
- code = 0xF0; // session close error
- print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id);
- } else {
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (slot_id != private->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 != private->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 (!(private->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) {
- private->sessions[session_number].state = S_STATE_IDLE;
- code = 0x00; // close ok
- }
- resource_id = private->sessions[session_number].resource_id;
- pthread_mutex_unlock(&private->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(private->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(private->tl), slot_id);
- }
-
- // callback to announce destruction to resource if it was ok
- if (code == 0x00) {
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
-
- if (cb)
- cb(cb_arg, S_SCALLBACK_REASON_CLOSE, slot_id, session_number, resource_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_private *private,
- uint8_t *data, uint32_t data_length, uint8_t slot_id, uint8_t connection_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 >= private->max_sessions) {
- print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id);
- return;
- }
-
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (slot_id != private->sessions[session_number].slot_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (connection_id != private->sessions[session_number].connection_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (private->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(&private->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]);
- private->sessions[session_number].state = S_STATE_IDLE;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
-
- // inform upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
- if (cb)
- cb(cb_arg, S_SCALLBACK_REASON_CONNECTFAIL, slot_id, session_number,
- private->sessions[session_number].resource_id);
- return;
- }
-
- // set it active
- private->sessions[session_number].state = S_STATE_ACTIVE;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
-
- // inform upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
- if (cb)
- cb(cb_arg, S_SCALLBACK_REASON_CONNECTED, slot_id, session_number,
- private->sessions[session_number].resource_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_private *private,
- uint8_t *data, uint32_t data_length, uint8_t slot_id, uint8_t connection_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 >= private->max_sessions) {
- print(LOG_LEVEL, ERROR, 1, "Received bad session id %i\n", slot_id);
- return;
- }
-
- pthread_mutex_lock(&private->sessions[session_number].session_lock);
- if (slot_id != private->sessions[session_number].slot_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (connection_id != private->sessions[session_number].connection_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (private->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(&private->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
- private->sessions[session_number].state = S_STATE_IDLE;
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
+ // 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_private *private,
- uint8_t *data, uint32_t data_length,
- uint8_t slot_id, uint8_t connection_id)
+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 >= private->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(&private->sessions[session_number].session_lock);
- if (slot_id != private->sessions[session_number].slot_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (connection_id != private->sessions[session_number].connection_id) {
- print(LOG_LEVEL, ERROR, 1, "Received unexpected session on invalid slot %i\n", slot_id);
- pthread_mutex_unlock(&private->sessions[session_number].session_lock);
- return;
- }
- if (private->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(&private->sessions[session_number].session_lock);
- return;
- }
-
- en50221_sl_resource_callback cb = private->sessions[session_number].callback;
- void *cb_arg = private->sessions[session_number].callback_arg;
- uint32_t resource_id = private->sessions[session_number].resource_id;
- pthread_mutex_unlock(&private->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;
- }
+ // 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)
+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_private *private = (struct en50221_session_layer_private *) 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(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->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(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->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(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
-
- for(i=0; i< private->max_sessions; i++) {
- pthread_mutex_lock(&private->sessions[i].session_lock);
-
- if (private->sessions[i].state == S_STATE_IDLE) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
- if (private->sessions[i].connection_id != connection_id) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
-
- private->sessions[i].state = S_STATE_IDLE;
-
- uint8_t slot_id = private->sessions[i].slot_id;
- uint32_t resource_id = private->sessions[i].resource_id;
- pthread_mutex_unlock(&private->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(&private->setcallback_lock);
- en50221_sl_session_callback cb = private->session;
- void *cb_arg = private->session_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
-
- for(i=0; i< private->max_sessions; i++) {
- pthread_mutex_lock(&private->sessions[i].session_lock);
-
- if (private->sessions[i].state == S_STATE_IDLE) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
- if (private->sessions[i].slot_id != slot_id) {
- pthread_mutex_unlock(&private->sessions[i].session_lock);
- continue;
- }
- private->sessions[i].state = S_STATE_IDLE;
-
- uint32_t resource_id = private->sessions[i].resource_id;
- pthread_mutex_unlock(&private->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(private, data+1, data_length-1, slot_id, connection_id);
- break;
-
- case ST_CLOSE_SESSION_REQ:
- en50221_sl_handle_close_session_request(private, data+1, data_length-1, slot_id, connection_id);
- break;
-
- case ST_SESSION_NUMBER:
- en50221_sl_handle_session_package(private, data+1, data_length-1, slot_id, connection_id);
- break;
-
- case ST_CREATE_SESSION_RES:
- en50221_sl_handle_create_session_response(private, data+1, data_length-1, slot_id, connection_id);
- break;
-
- case ST_CLOSE_SESSION_RES:
- en50221_sl_handle_close_session_response(private, 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;
- }
+ 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_private *private,
- uint32_t resource_id,
- uint8_t slot_id,
- uint8_t connection_id,
- en50221_sl_resource_callback callback, void* arg)
+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 < private->max_sessions; i++) {
- if (private->sessions[i].state == S_STATE_IDLE) {
- session_number = i;
- break;
- }
- }
- if (session_number == -1) {
- private->error = EN50221ERR_OUTOFSESSIONS;
- return -1;
- }
-
- // setup the session
- private->sessions[session_number].state = S_STATE_IN_CREATION;
- private->sessions[session_number].resource_id = resource_id;
- private->sessions[session_number].slot_id = slot_id;
- private->sessions[session_number].connection_id = connection_id;
- private->sessions[session_number].callback = callback;
- private->sessions[session_number].callback_arg = arg;
-
- // ok
- return session_number;
+ 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h
index 67031d8..7b33518 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_session.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 session layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -26,28 +26,27 @@
#define __EN50221_SESSION_H__
#ifdef __cplusplus
-extern "C"
-{
+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.
+#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.
*/
-typedef void *en50221_session_layer;
+struct en50221_session_layer;
/**
* Type definition for resource callback function - called by session layer when data
@@ -61,9 +60,12 @@ typedef void *en50221_session_layer;
* @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);
+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
@@ -80,9 +82,12 @@ typedef int (*en50221_sl_resource_callback)(void *arg, uint8_t slot_id,
* -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);
+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);
/**
@@ -96,8 +101,10 @@ typedef int (*en50221_sl_lookup_callback)(void *arg, uint8_t slot_id, uint32_t r
* @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);
+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.
@@ -106,14 +113,15 @@ typedef int (*en50221_sl_session_callback)(void *arg, int reason,
* @param max_sessions Maximum number of sessions supported.
* @return The en50221_session_layer instance, or NULL on error.
*/
-extern en50221_session_layer en50221_sl_create(en50221_transport_layer tl, uint32_t max_sessions);
+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(en50221_session_layer sl);
+extern void en50221_sl_destroy(struct en50221_session_layer *sl);
/**
* Gets the last error.
@@ -121,7 +129,7 @@ extern void en50221_sl_destroy(en50221_session_layer sl);
* @param tl The en50221_session_layer instance.
* @return One of the EN50221ERR_* values.
*/
-extern int en50221_sl_get_error(en50221_session_layer tl);
+extern int en50221_sl_get_error(struct en50221_session_layer *tl);
/**
* Register the callback for resource lookup.
@@ -130,8 +138,9 @@ extern int en50221_sl_get_error(en50221_session_layer tl);
* @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(en50221_session_layer sl,
- en50221_sl_lookup_callback callback, void *arg);
+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.
@@ -140,8 +149,9 @@ extern void en50221_sl_register_lookup_callback(en50221_session_layer sl,
* @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(en50221_session_layer sl,
- en50221_sl_session_callback callback, void *arg);
+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.
@@ -153,9 +163,11 @@ extern void en50221_sl_register_session_callback(en50221_session_layer sl,
* @param arg Argument to pass to the callback.
* @return The new session_number, or -1 on error.
*/
-extern int en50221_sl_create_session(en50221_session_layer sl, int slot_id, uint8_t connection_id,
- uint32_t resource_id,
- en50221_sl_resource_callback callback, void* arg);
+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.
@@ -164,7 +176,8 @@ extern int en50221_sl_create_session(en50221_session_layer sl, int slot_id, uint
* @param session_number The session to destroy.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_sl_destroy_session(en50221_session_layer sl, uint16_t session_number);
+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
@@ -176,7 +189,10 @@ extern int en50221_sl_destroy_session(en50221_session_layer sl, uint16_t session
* @param data_length Length of data in bytes.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_sl_send_data(en50221_session_layer sl, uint16_t session_number, uint8_t *data, uint16_t data_length);
+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
@@ -188,8 +204,10 @@ extern int en50221_sl_send_data(en50221_session_layer sl, uint16_t session_numbe
* @param iov_count Number of elements in io vector.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_sl_send_datav(en50221_session_layer sl, uint16_t session_number,
- struct iovec *vector, int iov_count);
+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
@@ -202,11 +220,13 @@ extern int en50221_sl_send_datav(en50221_session_layer sl, uint16_t session_numb
* @param data_length Length of data in bytes.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_sl_broadcast_data(en50221_session_layer sl, int slot_id, uint32_t resource_id,
- uint8_t *data, uint16_t data_length);
+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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.c
new file mode 100644
index 0000000..a00a844
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam.h
new file mode 100644
index 0000000..154ff76
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_hlci.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_hlci.c
new file mode 100644
index 0000000..f21637b
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_llci.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_stdcam_llci.c
new file mode 100644
index 0000000..ceaa027
--- /dev/null
+++ b/kaffeine/src/input/dvb/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_INRESET;
+ 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c
index 015c127..f6f46db 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.c
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 transport layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdio.h>
@@ -37,1204 +37,1260 @@
// 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
+#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_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;
+ 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;
+ int ca_hndl;
+ uint8_t slot; // CAM slot
+ struct en50221_connection *connections;
- pthread_mutex_t slot_lock;
+ pthread_mutex_t slot_lock;
- uint32_t response_timeout;
- uint32_t poll_delay;
+ uint32_t response_timeout;
+ uint32_t poll_delay;
};
-struct en50221_transport_layer_private
-{
- uint8_t max_slots;
- uint8_t max_connections_per_slot;
- struct en50221_slot *slots;
- struct pollfd *slot_pollfds;
- int slots_changed;
+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;
+ pthread_mutex_t global_lock;
+ pthread_mutex_t setcallback_lock;
- int error;
- int error_slot;
+ int error;
+ int error_slot;
- en50221_tl_callback callback;
- void *callback_arg;
+ en50221_tl_callback callback;
+ void *callback_arg;
};
-static int en50221_tl_process_data(struct en50221_transport_layer_private *tl, uint8_t slot_id,
- uint8_t *data, uint32_t data_length);
-static int en50221_tl_poll_tc(struct en50221_transport_layer_private *tl, uint8_t slot_id, uint8_t connection_id);
-static int en50221_tl_alloc_new_tc(struct en50221_transport_layer_private *tl, uint8_t slot_id);
-static void queue_message(struct en50221_transport_layer_private *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_private *private,
- uint8_t slot_id, uint8_t connection_id);
-static int en50221_tl_handle_delete_tc(struct en50221_transport_layer_private *private,
- uint8_t slot_id, uint8_t connection_id);
-static int en50221_tl_handle_delete_tc_reply(struct en50221_transport_layer_private *private,
- uint8_t slot_id, uint8_t connection_id);
-static int en50221_tl_handle_request_tc(struct en50221_transport_layer_private *private,
- uint8_t slot_id, uint8_t connection_id);
-static int en50221_tl_handle_data_more(struct en50221_transport_layer_private *private,
- 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_private *private,
- 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_private *private,
- uint8_t slot_id, uint8_t connection_id,
- uint8_t *data, uint32_t data_length);
-
-
-en50221_transport_layer en50221_tl_create(uint8_t max_slots, uint8_t max_connections_per_slot)
+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_private *private = NULL;
- int i;
- int j;
-
- // setup structure
- private = (struct en50221_transport_layer_private*) malloc(sizeof(struct en50221_transport_layer_private));
- if (private == NULL)
- goto error_exit;
- private->max_slots = max_slots;
- private->max_connections_per_slot = max_connections_per_slot;
- private->slots = NULL;
- private->slot_pollfds = NULL;
- private->slots_changed = 1;
- private->callback = NULL;
- private->callback_arg = NULL;
- private->error_slot = 0;
- private->error = 0;
- pthread_mutex_init(&private->global_lock, NULL);
- pthread_mutex_init(&private->setcallback_lock, NULL);
-
- // create the slots
- private->slots = malloc(sizeof(struct en50221_slot) * max_slots);
- if (private->slots == NULL)
- goto error_exit;
-
- // set them up
- for(i=0; i< max_slots; i++) {
- private->slots[i].ca_hndl = -1;
-
- // create the connections for this slot
- private->slots[i].connections = malloc(sizeof(struct en50221_connection) * max_connections_per_slot);
- if (private->slots[i].connections == NULL)
- goto error_exit;
-
- // create a mutex for the slot
- pthread_mutex_init(&private->slots[i].slot_lock, NULL);
-
- // set them up
- for(j = 0; j < max_connections_per_slot; j++) {
- private->slots[i].connections[j].state = T_STATE_IDLE;
- private->slots[i].connections[j].tx_time.tv_sec = 0;
- private->slots[i].connections[j].last_poll_time.tv_sec = 0;
- private->slots[i].connections[j].last_poll_time.tv_usec = 0;
- private->slots[i].connections[j].chain_buffer = NULL;
- private->slots[i].connections[j].buffer_length = 0;
- private->slots[i].connections[j].send_queue = NULL;
- private->slots[i].connections[j].send_queue_tail = NULL;
- }
- }
-
- // create the pollfds
- private->slot_pollfds = malloc(sizeof(struct pollfd) * max_slots);
- if (private->slot_pollfds == NULL) {
- goto error_exit;
- }
- memset(private->slot_pollfds, 0, sizeof(struct pollfd) * max_slots);
-
- return private;
-
-error_exit:
- en50221_tl_destroy(private);
- return NULL;
+ 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(en50221_transport_layer tl)
+void en50221_tl_destroy(struct en50221_transport_layer *tl)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
- int i, j;
-
- if (private) {
- if (private->slots) {
- for(i=0; i< private->max_slots; i++) {
- if (private->slots[i].connections) {
- for(j=0; j<private->max_connections_per_slot; j++) {
- if (private->slots[i].connections[j].chain_buffer) {
- free(private->slots[i].connections[j].chain_buffer);
- }
-
- struct en50221_message *cur_msg = private->slots[i].connections[j].send_queue;
- while(cur_msg) {
- struct en50221_message *next_msg = cur_msg->next;
- free(cur_msg);
- cur_msg = next_msg;
- }
- private->slots[i].connections[j].send_queue = NULL;
- private->slots[i].connections[j].send_queue_tail = NULL;
- }
- free(private->slots[i].connections);
- pthread_mutex_destroy(&private->slots[i].slot_lock);
- }
- }
- free(private->slots);
- }
- if (private->slot_pollfds) {
- free(private->slot_pollfds);
- }
- pthread_mutex_destroy(&private->setcallback_lock);
- pthread_mutex_destroy(&private->global_lock);
- free(private);
- }
+ 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(en50221_transport_layer tl, int ca_hndl, uint8_t slot,
- uint32_t response_timeout, uint32_t poll_delay)
+int en50221_tl_register_slot(struct en50221_transport_layer *tl,
+ int ca_hndl, uint8_t slot,
+ uint32_t response_timeout,
+ uint32_t poll_delay)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
- // lock
- pthread_mutex_lock(&private->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 < private->max_slots; i++) {
- if (private->slots[i].ca_hndl == -1) {
- slot_id = i;
- break;
- }
- }
- if (slot_id == -1) {
- private->error = EN50221ERR_OUTOFSLOTS;
- pthread_mutex_unlock(&private->global_lock);
- return -1;
- }
-
- // set up the slot struct
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- private->slots[slot_id].ca_hndl = ca_hndl;
- private->slots[slot_id].slot = slot;
- private->slots[slot_id].response_timeout = response_timeout;
- private->slots[slot_id].poll_delay = poll_delay;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
-
- private->slots_changed = 1;
- pthread_mutex_unlock(&private->global_lock);
- return slot_id;
+ // 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(en50221_transport_layer tl, uint8_t slot_id)
+void en50221_tl_destroy_slot(struct en50221_transport_layer *tl,
+ uint8_t slot_id)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
- int i;
-
- if (slot_id >= private->max_slots)
- return;
-
- // lock
- pthread_mutex_lock(&private->global_lock);
-
- // clear the slot
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- private->slots[slot_id].ca_hndl = -1;
- for(i=0; i<private->max_connections_per_slot; i++) {
- private->slots[slot_id].connections[i].state = T_STATE_IDLE;
- private->slots[slot_id].connections[i].tx_time.tv_sec = 0;
- private->slots[slot_id].connections[i].last_poll_time.tv_sec = 0;
- private->slots[slot_id].connections[i].last_poll_time.tv_usec = 0;
- if (private->slots[slot_id].connections[i].chain_buffer) {
- free(private->slots[slot_id].connections[i].chain_buffer);
- }
- private->slots[slot_id].connections[i].chain_buffer = NULL;
- private->slots[slot_id].connections[i].buffer_length = 0;
-
- struct en50221_message *cur_msg = private->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;
- }
- private->slots[slot_id].connections[i].send_queue = NULL;
- private->slots[slot_id].connections[i].send_queue_tail = NULL;
- }
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
-
- // tell upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
- if (cb)
- cb(cb_arg, T_CALLBACK_REASON_SLOTCLOSE, NULL, 0, slot_id, 0);
-
- private->slots_changed = 1;
- pthread_mutex_unlock(&private->global_lock);
+ 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(en50221_transport_layer tl)
+int en50221_tl_poll(struct en50221_transport_layer *tl)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
- uint8_t data[4096];
- int slot_id;
- int j;
-
- // make up pollfds if the slots have changed
- pthread_mutex_lock(&private->global_lock);
- if (private->slots_changed) {
- for(slot_id = 0; slot_id < private->max_slots; slot_id++) {
- if (private->slots[slot_id].ca_hndl != -1) {
- private->slot_pollfds[slot_id].fd = private->slots[slot_id].ca_hndl;
- private->slot_pollfds[slot_id].events = POLLIN|POLLPRI|POLLERR;
- private->slot_pollfds[slot_id].revents = 0;
- } else {
- private->slot_pollfds[slot_id].fd = 0;
- private->slot_pollfds[slot_id].events = 0;
- private->slot_pollfds[slot_id].revents = 0;
- }
- }
- private->slots_changed = 0;
- }
- pthread_mutex_unlock(&private->global_lock);
-
- // anything happened?
- if (poll(private->slot_pollfds, private->max_slots, 10) < 0) {
- private->error_slot = -1;
- private->error = EN50221ERR_CAREAD;
- return -1;
- }
-
- // go through all slots (even though poll may not have reported any events
- for(slot_id = 0; slot_id < private->max_slots; slot_id++) {
-
- // check if this slot is still used and get its handle
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- continue;
- }
- int ca_hndl = private->slots[slot_id].ca_hndl;
-
- if (private->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) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAREAD;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
-
- // process it if we got some
- if (readcnt > 0) {
- if (private->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 < private->max_slots; new_slot_id++) {
- if ((private->slots[new_slot_id].ca_hndl == ca_hndl) && (private->slots[new_slot_id].slot == r_slot_id))
- break;
- }
- if (new_slot_id != private->max_slots) {
- // we found the requested CAM
- pthread_mutex_lock(&private->slots[new_slot_id].slot_lock);
- if (en50221_tl_process_data(private, new_slot_id, data, readcnt)) {
- pthread_mutex_unlock(&private->slots[new_slot_id].slot_lock);
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- pthread_mutex_unlock(&private->slots[new_slot_id].slot_lock);
- } else {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- }
- else if (en50221_tl_process_data(private, slot_id, data, readcnt)) {
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- }
- } else if (private->slot_pollfds[slot_id].revents & POLLERR) {
- // an error was reported
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAREAD;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
-
- // poll the connections on this slot + check for timeouts
- for(j=0; j < private->max_connections_per_slot; j++) {
- // ignore connection if idle
- if (private->slots[slot_id].connections[j].state == T_STATE_IDLE) {
- continue;
- }
-
- // send queued data
- if (private->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 (private->slots[slot_id].connections[j].send_queue &&
- (private->slots[slot_id].connections[j].tx_time.tv_sec == 0)) {
-
- // get the message
- struct en50221_message *msg = private->slots[slot_id].connections[j].send_queue;
- if (msg->next != NULL) {
- private->slots[slot_id].connections[j].send_queue = msg->next;
- } else {
- private->slots[slot_id].connections[j].send_queue = NULL;
- private->slots[slot_id].connections[j].send_queue_tail = NULL;
- }
-
- // send the message
- if (dvbca_link_write(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, j, msg->data, msg->length) < 0) {
- free(msg);
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- print(LOG_LEVEL, ERROR, 1, "CAWrite failed");
- return -1;
- }
- gettimeofday(&private->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)) {
- private->slots[slot_id].connections[j].state = T_STATE_IN_DELETION;
- if (private->slots[slot_id].connections[j].chain_buffer) {
- free(private->slots[slot_id].connections[j].chain_buffer);
- }
- private->slots[slot_id].connections[j].chain_buffer = NULL;
- private->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 (private->slots[slot_id].connections[j].state & T_STATE_ACTIVE) {
- if ((private->slots[slot_id].connections[j].tx_time.tv_sec == 0) &&
- (time_after(private->slots[slot_id].connections[j].last_poll_time, private->slots[slot_id].poll_delay))) {
-
- gettimeofday(&private->slots[slot_id].connections[j].last_poll_time, 0);
- if (en50221_tl_poll_tc(private, slot_id, j)) {
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- }
- }
-
- // check for timeouts - in any state
- if (private->slots[slot_id].connections[j].tx_time.tv_sec &&
- (time_after(private->slots[slot_id].connections[j].tx_time, private->slots[slot_id].response_timeout))) {
-
- if (private->slots[slot_id].connections[j].state & (T_STATE_IN_CREATION|T_STATE_IN_DELETION)) {
- private->slots[slot_id].connections[j].state = T_STATE_IDLE;
- } else if (private->slots[slot_id].connections[j].state & (T_STATE_ACTIVE|T_STATE_ACTIVE_DELETEQUEUED)) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_TIMEOUT;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- }
- }
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- }
-
- return 0;
+ 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(en50221_transport_layer tl, en50221_tl_callback callback, void *arg)
+void en50221_tl_register_callback(struct en50221_transport_layer *tl,
+ en50221_tl_callback callback, void *arg)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
- pthread_mutex_lock(&private->setcallback_lock);
- private->callback = callback;
- private->callback_arg = arg;
- pthread_mutex_unlock(&private->setcallback_lock);
+ 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(en50221_transport_layer tl)
+int en50221_tl_get_error_slot(struct en50221_transport_layer *tl)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
- return private->error_slot;
+ return tl->error_slot;
}
-int en50221_tl_get_error(en50221_transport_layer tl)
+int en50221_tl_get_error(struct en50221_transport_layer *tl)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
- return private->error;
+ return tl->error;
}
-int en50221_tl_send_data(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id,
- uint8_t *data, uint32_t data_size)
+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)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
#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");
+ 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 >= private->max_slots) {
- private->error = EN50221ERR_BADSLOTID;
- return -1;
- }
-
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (connection_id >= private->max_connections_per_slot) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (private->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->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) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- pthread_mutex_unlock(&private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_ASNENCODE;
- pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg);
-
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return 0;
+ 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(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id,
- struct iovec *vector, int iov_count)
+int en50221_tl_send_datav(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id,
+ struct iovec *vector, int iov_count)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
#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");
+ 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 >= private->max_slots) {
- private->error = EN50221ERR_BADSLOTID;
- return -1;
- }
-
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (connection_id >= private->max_connections_per_slot) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (private->slots[slot_id].connections[connection_id].state != T_STATE_ACTIVE) {
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->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) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- pthread_mutex_unlock(&private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_ASNENCODE;
- pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg);
-
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return 0;
+ 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(en50221_transport_layer tl, uint8_t slot_id)
+int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
- // check
- if (slot_id >= private->max_slots) {
- private->error = EN50221ERR_BADSLOTID;
- return -1;
- }
-
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
-
- // allocate a new connection if possible
- int conid = en50221_tl_alloc_new_tc(private, slot_id);
- if (conid == -1) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFCONNECTIONS;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
-
- // allocate msg structure
- struct en50221_message *msg = malloc(sizeof(struct en50221_message)+3);
- if (msg == NULL) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- pthread_mutex_unlock(&private->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(private, slot_id, conid, msg);
-
- // done
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return conid;
+ // 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(en50221_transport_layer tl, uint8_t slot_id, uint8_t connection_id)
+int en50221_tl_del_tc(struct en50221_transport_layer *tl, uint8_t slot_id,
+ uint8_t connection_id)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
- // check
- if (slot_id >= private->max_slots) {
- private->error = EN50221ERR_BADSLOTID;
- return -1;
- }
-
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (connection_id >= private->max_connections_per_slot) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (!(private->slots[slot_id].connections[connection_id].state &
- (T_STATE_ACTIVE|T_STATE_IN_DELETION))) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADSTATE;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
-
- // allocate msg structure
- struct en50221_message *msg = malloc(sizeof(struct en50221_message)+3);
- if (msg == NULL) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- pthread_mutex_unlock(&private->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(private, slot_id, connection_id, msg);
- private->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE_DELETEQUEUED;
-
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return 0;
+ // 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(en50221_transport_layer tl,
- uint8_t slot_id, uint8_t connection_id)
+int en50221_tl_get_connection_state(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id)
{
- struct en50221_transport_layer_private *private = (struct en50221_transport_layer_private *) tl;
-
- if (slot_id >= private->max_slots) {
- private->error = EN50221ERR_BADSLOTID;
- return -1;
- }
-
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- if (private->slots[slot_id].ca_hndl == -1) {
- private->error = EN50221ERR_BADSLOTID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- if (connection_id >= private->max_connections_per_slot) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCONNECTIONID;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- return -1;
- }
- int state = private->slots[slot_id].connections[connection_id].state;
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
-
- return state;
+ 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_private *private, uint8_t slot_id, uint8_t connection_id)
+static int en50221_tl_poll_tc(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t connection_id)
{
- gettimeofday(&private->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(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
- return 0;
+ 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_private *private, uint8_t slot_id,
- uint8_t *data, uint32_t data_length)
+static int en50221_tl_process_data(struct en50221_transport_layer *tl,
+ uint8_t slot_id, uint8_t * data,
+ uint32_t data_length)
{
- int result;
+ 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");
+ 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);
- private->error_slot = slot_id;
- private->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);
- private->error_slot = slot_id;
- private->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 >= private->max_connections_per_slot) {
- print(LOG_LEVEL, ERROR, 1, "Received bad connection id %02x from module on slot %02x\n", connection_id, slot_id);
- private->error_slot = slot_id;
- private->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(private, slot_id, connection_id)) < 0) {
- return -1;
- }
- break;
- case T_DELETE_T_C:
- if ((result = en50221_tl_handle_delete_tc(private, slot_id, connection_id)) < 0) {
- return -1;
- }
- break;
- case T_D_T_C_REPLY:
- if ((result = en50221_tl_handle_delete_tc_reply(private, slot_id, connection_id)) < 0) {
- return -1;
- }
- break;
- case T_REQUEST_T_C:
- if ((result = en50221_tl_handle_request_tc(private, slot_id, connection_id)) < 0) {
- return -1;
- }
- break;
- case T_DATA_MORE:
- if ((result = en50221_tl_handle_data_more(private, slot_id, connection_id, data, asn_data_length)) < 0) {
- return -1;
- }
- break;
- case T_DATA_LAST:
- if ((result = en50221_tl_handle_data_last(private, slot_id, connection_id, data, asn_data_length)) < 0) {
- return -1;
- }
- break;
- case T_SB:
- if ((result = en50221_tl_handle_sb(private, 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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- // skip over the consumed data
- data += asn_data_length;
- data_length -= asn_data_length;
- }
-
- return 0;
+ // 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_private *private,
- uint8_t slot_id, uint8_t connection_id)
+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 (private->slots[slot_id].connections[connection_id].state == T_STATE_IN_CREATION) {
- private->slots[slot_id].connections[connection_id].state = T_STATE_ACTIVE;
- private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
-
- // tell upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- return 0;
+ // 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_private *private,
- 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)
{
- // immediately delete this connection and send D_T_C_REPLY
- if (private->slots[slot_id].connections[connection_id].state & (T_STATE_ACTIVE|T_STATE_IN_DELETION))
- {
- // clear down the slot
- private->slots[slot_id].connections[connection_id].state = T_STATE_IDLE;
- if (private->slots[slot_id].connections[connection_id].chain_buffer) {
- free(private->slots[slot_id].connections[connection_id].chain_buffer);
- }
- private->slots[slot_id].connections[connection_id].chain_buffer = NULL;
- private->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(private->slots[slot_id].ca_hndl, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
-
- // tell upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- return 0;
+ // 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_private *private,
- 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)
{
- // delete this connection, should be in T_STATE_IN_DELETION already
- if (private->slots[slot_id].connections[connection_id].state == T_STATE_IN_DELETION) {
- private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- return 0;
+ // 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_private *private,
- 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)
{
- // allocate a new connection if possible
- int conid = en50221_tl_alloc_new_tc(private, slot_id);
- int ca_hndl = private->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, private->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
- private->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, private->slots[slot_id].slot, connection_id, hdr, 4) < 0) {
- private->slots[slot_id].connections[conid].state = T_STATE_IDLE;
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
- private->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, private->slots[slot_id].slot, conid, hdr, 3) < 0) {
- private->slots[slot_id].connections[conid].state = T_STATE_IDLE;
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
- gettimeofday(&private->slots[slot_id].connections[conid].tx_time, 0);
-
- // tell upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
- if (cb)
- cb(cb_arg, T_CALLBACK_REASON_CAMCONNECTIONOPEN, NULL, 0, slot_id, conid);
- }
-
- return 0;
+ // 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_private *private,
- uint8_t slot_id, uint8_t connection_id,
- uint8_t *data, uint32_t data_length)
+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 (private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- // a chained data packet is coming in, save
- // it to the buffer and wait for more
- private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
- int new_data_length =
- private->slots[slot_id].connections[connection_id].buffer_length + data_length;
- uint8_t *new_data_buffer =
- realloc(private->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
- if (new_data_buffer == NULL) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- return -1;
- }
- private->slots[slot_id].connections[connection_id].chain_buffer = new_data_buffer;
-
- memcpy(private->slots[slot_id].connections[connection_id].chain_buffer +
- private->slots[slot_id].connections[connection_id].buffer_length,
- data, data_length);
- private->slots[slot_id].connections[connection_id].buffer_length = new_data_length;
-
- return 0;
+ // 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_private *private,
- 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)
{
- // connection in correct state?
- if (private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- // last package of a chain or single package comes in
- private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
- if (private->slots[slot_id].connections[connection_id].chain_buffer == NULL)
- {
- // single package => dispatch immediately
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
-
- if (cb && data_length) {
- pthread_mutex_unlock(&private->slots[slot_id].slot_lock);
- cb(cb_arg, T_CALLBACK_REASON_DATA, data, data_length, slot_id, connection_id);
- pthread_mutex_lock(&private->slots[slot_id].slot_lock);
- }
- }
- else
- {
- int new_data_length = private->slots[slot_id].connections[connection_id].buffer_length + data_length;
- uint8_t *new_data_buffer =
- realloc(private->slots[slot_id].connections[connection_id].chain_buffer, new_data_length);
- if (new_data_buffer == NULL) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_OUTOFMEMORY;
- return -1;
- }
-
- memcpy(new_data_buffer + private->slots[slot_id].connections[connection_id].buffer_length, data, data_length);
-
- // clean the buffer position
- private->slots[slot_id].connections[connection_id].chain_buffer = NULL;
- private->slots[slot_id].connections[connection_id].buffer_length = 0;
-
- // tell the upper layers
- pthread_mutex_lock(&private->setcallback_lock);
- en50221_tl_callback cb = private->callback;
- void *cb_arg = private->callback_arg;
- pthread_mutex_unlock(&private->setcallback_lock);
- if (cb && data_length) {
- pthread_mutex_unlock(&private->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(&private->slots[slot_id].slot_lock);
- }
-
- free(new_data_buffer);
- }
-
- return 0;
+ // 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_private *private,
- 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)
{
- // is the connection id ok?
- if (private->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);
- private->error_slot = slot_id;
- private->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);
- private->error_slot = slot_id;
- private->error = EN50221ERR_BADCAMDATA;
- return -1;
- }
-
- // tell it to send the data if it says there is some
- if (data[0] & 0x80) {
- int ca_hndl = private->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, private->slots[slot_id].slot, connection_id, hdr, 3) < 0) {
- private->error_slot = slot_id;
- private->error = EN50221ERR_CAWRITE;
- return -1;
- }
- gettimeofday(&private->slots[slot_id].connections[connection_id].tx_time, 0);
-
- } else {
- // no data - indicate not waiting for anything now
- private->slots[slot_id].connections[connection_id].tx_time.tv_sec = 0;
- }
-
- return 0;
+ // 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_private *private, uint8_t slot_id)
+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 < private->max_connections_per_slot; i++) {
- if (private->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
- private->slots[slot_id].connections[conid].state = T_STATE_IN_CREATION;
- private->slots[slot_id].connections[conid].chain_buffer = NULL;
- private->slots[slot_id].connections[conid].buffer_length = 0;
-
- return conid;
+ // 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_private *private, uint8_t slot_id,
- uint8_t connection_id, struct en50221_message *msg)
+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 (private->slots[slot_id].connections[connection_id].send_queue_tail) {
- private->slots[slot_id].connections[connection_id].send_queue_tail->next = msg;
- } else {
- private->slots[slot_id].connections[connection_id].send_queue = msg;
- private->slots[slot_id].connections[connection_id].send_queue_tail = 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/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h
index e1dd1c5..7882060 100644
--- a/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h
+++ b/kaffeine/src/input/dvb/lib/libdvben50221/en50221_transport.h
@@ -2,7 +2,7 @@
en50221 encoder An implementation for libdvb
an implementation for the en50221 session layer
- Copyright (C) 2004, 2005 Manu Abraham (manu@kromtek.com)
+ 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)
@@ -18,7 +18,7 @@
You should 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
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
@@ -26,8 +26,7 @@
#define __EN50221_TRANSPORT_H__
#ifdef __cplusplus
-extern "C"
-{
+extern "C" {
#endif
#include <stdlib.h>
@@ -37,23 +36,23 @@ extern "C"
/**
* 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.
+#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
+#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.
*/
-typedef void *en50221_transport_layer;
+struct en50221_transport_layer;
/**
* Type definition for callback function - used when events are received from a module.
@@ -72,9 +71,11 @@ typedef void *en50221_transport_layer;
* @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);
+typedef void (*en50221_tl_callback) (void *arg, int reason,
+ uint8_t * data,
+ uint32_t data_length,
+ uint8_t slot_id,
+ uint8_t connection_id);
/**
@@ -84,14 +85,15 @@ typedef void (*en50221_tl_callback)(void *arg, int reason,
* @param max_connections_per_slot Maximum connections per slot.
* @return The en50221_transport_layer instance, or NULL on error.
*/
-extern en50221_transport_layer en50221_tl_create(uint8_t max_slots, uint8_t max_connections_per_slot);
+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(en50221_transport_layer tl);
+extern void en50221_tl_destroy(struct en50221_transport_layer *tl);
/**
* Register a new slot with the library.
@@ -103,9 +105,10 @@ extern void en50221_tl_destroy(en50221_transport_layer tl);
* @param poll_delay Interval between polls in ms.
* @return slot_id on sucess, or -1 on error.
*/
-extern int en50221_tl_register_slot(en50221_transport_layer tl, int ca_hndl,
- uint8_t slot, uint32_t response_timeout,
- uint32_t poll_delay);
+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
@@ -114,7 +117,7 @@ extern int en50221_tl_register_slot(en50221_transport_layer tl, int ca_hndl,
* @param tl The en50221_transport_layer instance.
* @param slot_id Slot to destroy.
*/
-extern void en50221_tl_destroy_slot(en50221_transport_layer tl, uint8_t slot_id);
+extern void en50221_tl_destroy_slot(struct en50221_transport_layer *tl, uint8_t slot_id);
/**
* Performs one iteration of the transport layer poll -
@@ -126,7 +129,7 @@ extern void en50221_tl_destroy_slot(en50221_transport_layer tl, uint8_t slot_id)
* @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(en50221_transport_layer tl);
+extern int en50221_tl_poll(struct en50221_transport_layer *tl);
/**
* Register the callback for data reception.
@@ -135,8 +138,8 @@ extern int en50221_tl_poll(en50221_transport_layer tl);
* @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(en50221_transport_layer tl,
- en50221_tl_callback callback, void *arg);
+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.
@@ -144,7 +147,7 @@ extern void en50221_tl_register_callback(en50221_transport_layer tl,
* @param tl The en50221_transport_layer instance.
* @return The offending slot id.
*/
-extern int en50221_tl_get_error_slot(en50221_transport_layer tl);
+extern int en50221_tl_get_error_slot(struct en50221_transport_layer *tl);
/**
* Gets the last error.
@@ -152,7 +155,7 @@ extern int en50221_tl_get_error_slot(en50221_transport_layer tl);
* @param tl The en50221_transport_layer instance.
* @return One of the EN50221ERR_* values.
*/
-extern int en50221_tl_get_error(en50221_transport_layer tl);
+extern int en50221_tl_get_error(struct en50221_transport_layer *tl);
/**
* This function is used to take a data-block, pack into
@@ -165,9 +168,11 @@ extern int en50221_tl_get_error(en50221_transport_layer tl);
* @param data_length Number of bytes to send.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_tl_send_data(en50221_transport_layer tl,
- uint8_t slot_id, uint8_t connection_id,
- uint8_t *data, uint32_t data_length);
+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
@@ -180,9 +185,9 @@ extern int en50221_tl_send_data(en50221_transport_layer tl,
* @param io_count Number of elements in vector.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_tl_send_datav(en50221_transport_layer tl, uint8_t slot_id,
- uint8_t connection_id, struct iovec *vector,
- int iov_count);
+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.
@@ -196,7 +201,7 @@ extern int en50221_tl_send_datav(en50221_transport_layer tl, uint8_t slot_id,
* @param slot_id ID of the slot.
* @return The allocated connection id on success, or -1 on error.
*/
-extern int en50221_tl_new_tc(en50221_transport_layer tl, uint8_t slot_id);
+extern int en50221_tl_new_tc(struct en50221_transport_layer *tl, uint8_t slot_id);
/**
* Deallocates a transport connection.
@@ -210,8 +215,7 @@ extern int en50221_tl_new_tc(en50221_transport_layer tl, uint8_t slot_id);
* @param connection_id Connection id to send the request _on_.
* @return 0 on success, or -1 on error.
*/
-extern int en50221_tl_del_tc(en50221_transport_layer tl, uint8_t slot_id,
- uint8_t connection_id);
+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.
@@ -221,11 +225,10 @@ extern int en50221_tl_del_tc(en50221_transport_layer tl, uint8_t slot_id,
* @param connection_id Connection id to send the request _on_.
* @return One of the T_STATE_* values.
*/
-extern int en50221_tl_get_connection_state(en50221_transport_layer tl,
- uint8_t slot_id, uint8_t connection_id);
+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/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h b/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h
index 75713f4..8ac6eee 100644
--- a/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h
+++ b/kaffeine/src/input/dvb/lib/libdvbmisc/dvbmisc.h
@@ -1,7 +1,7 @@
/*
libdvbmisc - DVB miscellaneous library
- Copyright (C) 2005 Manu Abraham <manu@kromtek.com>
+ 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
diff --git a/kaffeine/src/input/dvb/lib/libucsi/Makefile.am b/kaffeine/src/input/dvb/lib/libucsi/Makefile.am
index 071f310..36f905e 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/Makefile.am
+++ b/kaffeine/src/input/dvb/lib/libucsi/Makefile.am
@@ -1,6 +1,6 @@
noinst_LTLIBRARIES = libucsi.la
-SUBDIRS = dvb mpeg .
+SUBDIRS = dvb mpeg atsc .
INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib
@@ -9,9 +9,11 @@ libucsi_la_SOURCES = crc32.c \
transport_packet.c
libucsi_la_LDFLAGS = ./mpeg \
- ./dvb
+ ./dvb \
+ /atsc
libucsi_la_LIBADD = ./mpeg/libdvbmpeg.la \
- ./dvb/libdvbdvb.la
+ ./dvb/libdvbdvb.la \
+ ./atsc/libdvbatsc.la
CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC
diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/Makefile.am b/kaffeine/src/input/dvb/lib/libucsi/atsc/Makefile.am
new file mode 100644
index 0000000..2df5d3b
--- /dev/null
+++ b/kaffeine/src/input/dvb/lib/libucsi/atsc/Makefile.am
@@ -0,0 +1,17 @@
+noinst_LTLIBRARIES = libdvbatsc.la
+
+INCLUDES = -I$(top_srcdir)/kaffeine/src/input/dvb/lib
+
+libdvbatsc_la_SOURCES = atsc_text.c \
+ cvct_section.c \
+ dccsct_section.c \
+ dcct_section.c \
+ eit_section.c \
+ ett_section.c \
+ mgt_section.c \
+ rrt_section.c \
+ stt_section.c \
+ tvct_section.c \
+ types.c
+
+CFLAGS = -g -O2 -Wall -Wshadow -Wpointer-arith -Wstrict-prototypes -fPIC
diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/ac3_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/ac3_descriptor.h
new file mode 100644
index 0000000..489695b
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/atsc_text.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/atsc_text.c
new file mode 100644
index 0000000..d79c83f
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/caption_service_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/caption_service_descriptor.h
new file mode 100644
index 0000000..29d1794
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/component_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/component_name_descriptor.h
new file mode 100644
index 0000000..3b9cab7
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/content_advisory_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/content_advisory_descriptor.h
new file mode 100644
index 0000000..da19813
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.c
new file mode 100644
index 0000000..6edbc03
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/cvct_section.h
new file mode 100644
index 0000000..c3d418a
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_arriving_request_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_arriving_request_descriptor.h
new file mode 100644
index 0000000..af76eac
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_departing_request_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/dcc_departing_request_descriptor.h
new file mode 100644
index 0000000..851f0cc
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.c
new file mode 100644
index 0000000..59ad069
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/dccsct_section.h
new file mode 100644
index 0000000..f9f3522
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.c
new file mode 100644
index 0000000..7d0b83b
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/dcct_section.h
new file mode 100644
index 0000000..647bd4b
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h
index a18b29d..a57176a 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/atsc/descriptor.h
@@ -28,39 +28,37 @@ 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 {
-
-/* A 52/A describes a
- * dtag_atsc_ac3_registration = 0x05, */
-
-/* A90 describes a
- * dtag_atsc_association_tag = 0x14, */
-
dtag_atsc_stuffing = 0x80,
dtag_atsc_ac3_audio = 0x81,
dtag_atsc_caption_service = 0x86,
dtag_atsc_content_advisory = 0x87,
- dtag_atsc_ca = 0x88,
dtag_atsc_extended_channel_name = 0xa0,
dtag_atsc_service_location = 0xa1,
dtag_atsc_time_shifted_service = 0xa2,
dtag_atsc_component_name = 0xa3,
- dtag_atsc_data_service = 0xa4,
- dtag_atsc_pid_count = 0xa5,
- dtag_atsc_download = 0xa6,
- dtag_atsc_MPE = 0xa7,
dtag_atsc_dcc_departing_request = 0xa8,
dtag_atsc_dcc_arriving_request = 0xa9,
dtag_atsc_redistribution_control = 0xaa,
- dtag_atsc_dcc_location_code = 0xab,
dtag_atsc_private_information = 0xad,
- dtag_atsc_module_link = 0xb4,
- dtag_atsc_crc32 = 0xb5,
- dtag_atsc_group_link = 0xb8,
+ dtag_atsc_content_identifier = 0xb6,
+ dtag_atsc_genre = 0xab,
};
#ifdef __cplusplus
diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.c
new file mode 100644
index 0000000..48cdda6
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/eit_section.h
new file mode 100644
index 0000000..84bef16
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.c
new file mode 100644
index 0000000..ab2ff9c
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/ett_section.h
new file mode 100644
index 0000000..e2bb510
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/extended_channel_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/extended_channel_name_descriptor.h
new file mode 100644
index 0000000..d0b714b
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/genre_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/genre_descriptor.h
new file mode 100644
index 0000000..a6fc542
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.c
new file mode 100644
index 0000000..bc6b3f2
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/mgt_section.h
new file mode 100644
index 0000000..3102a54
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/rc_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/rc_descriptor.h
new file mode 100644
index 0000000..4fb0e8e
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.c
new file mode 100644
index 0000000..6e96c3a
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/rrt_section.h
new file mode 100644
index 0000000..fba4596
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h
index e693b9d..23d59ea 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/atsc/section.h
@@ -19,6 +19,17 @@
* 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
@@ -27,40 +38,44 @@ extern "C"
{
#endif
+#define ATSC_BASE_PID 0x1ffb
+
/**
* Enumeration of ATSC section tags.
*/
enum atsc_section_tag {
-/* 0xC0-0xC6 [ATSC coordinated values which are defined in other standards.] */
- stag_atsc_master_guide = 0xc7,
+ 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_informationen = 0xcb,
- stag_atsc_extended_text = 0xcc,
+ 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,
+};
- stag_atsc_data_event = 0xce,
- stag_atsc_data_service = 0xcf,
- stag_atsc_network_resources = 0xd1,
- stag_atsc_long_term_serivce = 0xd2,
-/* identical to DVB/ISO ?
- 0x3F DSM-CC Addressable Section Table
- 0x3B DSM-CC Section Table
- 0x3C DSM-CC Section Table */
-
- /* 0xCE-0xD2 [ATSC coordinated values which are defined in other standards.] */
- stag_atsc_directed_channel_change = 0xd3,
- stag_atsc_directed_channel_change_selection_code = 0xd4,
+/**
+ * ATSC specific PSIP section structure.
+ */
+struct atsc_section_psip {
+ struct section_ext ext_head;
+ uint8_t protocol_version;
+} __ucsi_packed;
- /* 0xD5-0xDF [ATSC coordinated values which are defined in other standards.] */
- stag_atsc_aggregate_event_information = 0xd6,
- stag_atsc_aggregate_extended_text = 0xd7,
- stag_atsc_satellite_virtual_channel = 0xda,
+/**
+ * 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;
+ }
- /* 0xE0-0xE5 [Used in other systems] */
- /* 0xE6-0xFE [Reserved for future ATSC use] */
-};
+ return (struct atsc_section_psip *) section_ext;
+}
#ifdef __cplusplus
}
diff --git a/kaffeine/src/input/dvb/lib/libucsi/atsc/service_location_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/service_location_descriptor.h
new file mode 100644
index 0000000..aad5b4a
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.c
new file mode 100644
index 0000000..23ddd76
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/stt_section.h
new file mode 100644
index 0000000..79db5a1
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/stuffing_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/stuffing_descriptor.h
new file mode 100644
index 0000000..777c282
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/time_shifted_service_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/time_shifted_service_descriptor.h
new file mode 100644
index 0000000..599e66d
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.c
new file mode 100644
index 0000000..d187414
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/tvct_section.h
new file mode 100644
index 0000000..77bc5f4
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/types.c b/kaffeine/src/input/dvb/lib/libucsi/atsc/types.c
new file mode 100644
index 0000000..8f4b7ea
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/atsc/types.h b/kaffeine/src/input/dvb/lib/libucsi/atsc/types.h
new file mode 100644
index 0000000..4d4b802
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/crc32.h b/kaffeine/src/input/dvb/lib/libucsi/crc32.h
index 5d77e84..7d781ce 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/crc32.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/crc32.h
@@ -40,9 +40,9 @@ extern uint32_t crc32tbl[];
* @param len Number of bytes.
* @return Calculated CRC.
*/
-static inline uint32_t crc32(uint32_t crc, uint8_t* buf, int len)
+static inline uint32_t crc32(uint32_t crc, uint8_t* buf, size_t len)
{
- int i;
+ size_t i;
for (i=0; i< len; i++) {
crc = (crc << 8) ^ crc32tbl[((crc >> 24) ^ buf[i]) & 0xff];
diff --git a/kaffeine/src/input/dvb/lib/libucsi/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/descriptor.h
index 809936d..606e45d 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/descriptor.h
@@ -47,7 +47,7 @@ struct descriptor {
* @return Pointer to next descriptor, or NULL if there are none.
*/
static inline struct descriptor *
- next_descriptor(uint8_t * buf, int len, struct descriptor * pos)
+ next_descriptor(uint8_t * buf, size_t len, struct descriptor * pos)
{
uint8_t* next;
@@ -105,9 +105,9 @@ static inline int
/******************************** PRIVATE CODE ********************************/
-static inline int verify_descriptors(uint8_t * buf, int len)
+static inline int verify_descriptors(uint8_t * buf, size_t len)
{
- int pos = 0;
+ size_t pos = 0;
while (pos < len) {
if ((pos + 2) > len)
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h
index d60e37b..0a2a5cd 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/ac3_descriptor.h
@@ -40,7 +40,7 @@ struct dvb_ac3_descriptor {
uint8_t bsid_flag : 1; ,
uint8_t mainid_flag : 1; ,
uint8_t asvc_flag : 1; ,
- uint8_t reserved : 4; )
+ uint8_t reserved : 4; );
/* uint8_t additional_info[] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h
index 69a21b8..b207054 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/adaptation_field_data_descriptor.h
@@ -37,7 +37,7 @@ struct dvb_adaptation_field_data_descriptor {
struct descriptor d;
EBIT2(uint8_t reserved : 7; ,
- uint8_t announcement_switching_data : 1; )
+ uint8_t announcement_switching_data : 1; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h
index 877d9c0..95fb7e3 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_descriptor.h
@@ -36,7 +36,7 @@ extern "C"
enum {
AVB_AIT_APPLICATION_VISIBILITY_HIDDEN = 0x00,
AVB_AIT_APPLICATION_VISIBILITY_APPSONLY = 0x01,
- AVB_AIT_APPLICATION_VISIBILITY_VISIBLE = 0x03
+ AVB_AIT_APPLICATION_VISIBILITY_VISIBLE = 0x03,
};
/**
@@ -66,7 +66,7 @@ struct dvb_ait_application_profile {
struct dvb_ait_application_descriptor_part2 {
EBIT3(uint8_t service_bound_flag : 1; ,
uint8_t visibility : 2; ,
- uint8_t reserved : 5; )
+ uint8_t reserved : 5; );
uint8_t application_priority;
/* uint8_t transport_protocol_label[] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h
index 5ea5932..431cd6c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/ait_application_icons_descriptor.h
@@ -45,7 +45,7 @@ enum {
AIT_APPLICATION_ICON_FLAG_128_128 = 0x040,
AIT_APPLICATION_ICON_FLAG_128_128_43 = 0x080,
- AIT_APPLICATION_ICON_FLAG_96_128_169 = 0x100
+ AIT_APPLICATION_ICON_FLAG_96_128_169 = 0x100,
};
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h
index 7a0280d..04b2f59 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/ancillary_data_descriptor.h
@@ -42,7 +42,7 @@ struct dvb_ancillary_data_descriptor {
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; )
+ uint8_t dvd_video_ancillary_data : 1; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h
index 55a570b..9eb20c4 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/announcement_support_descriptor.h
@@ -41,7 +41,7 @@ enum {
DVB_ANNOUNCEMENT_SUPPORT_NEWS_FLASH = 0x10,
DVB_ANNOUNCEMENT_SUPPORT_WEATHER_FLASH = 0x20,
DVB_ANNOUNCEMENT_SUPPORT_EVENT_ANNOUNCEMENT = 0x40,
- DVB_ANNOUNCEMENT_SUPPORT_PERSONAL_CALL = 0x80
+ DVB_ANNOUNCEMENT_SUPPORT_PERSONAL_CALL = 0x80,
};
/**
@@ -55,7 +55,7 @@ enum {
DVB_ANNOUNCEMENT_TYPE_NEWS_FLASH = 0x04,
DVB_ANNOUNCEMENT_TYPE_WEATHER_FLASH = 0x05,
DVB_ANNOUNCEMENT_TYPE_EVENT_ANNOUNCEMENT = 0x06,
- DVB_ANNOUNCEMENT_TYPE_PERSONAL_CALL = 0x07
+ DVB_ANNOUNCEMENT_TYPE_PERSONAL_CALL = 0x07,
};
/**
@@ -65,7 +65,7 @@ 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_REFERENCE_TYPE_OTHER_TS = 0x03,
};
/**
@@ -83,7 +83,7 @@ struct dvb_announcement_support_descriptor {
struct dvb_announcement_support_entry {
EBIT3(uint8_t announcement_type : 4; ,
uint8_t reserved : 1; ,
- uint8_t reference_type : 3; )
+ uint8_t reference_type : 3; );
/* Only if reference_type == 1, 2 or 3:
* struct dvb_announcement_support_reference reference */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h
index c1d50ff..78211cf 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/application_signalling_descriptor.h
@@ -45,7 +45,7 @@ struct dvb_application_signalling_descriptor {
struct dvb_application_signalling_entry {
uint16_t application_type;
EBIT2(uint8_t reserved : 3; ,
- uint8_t AIT_version_number : 5; )
+ uint8_t AIT_version_number : 5; );
} __ucsi_packed;
/**
@@ -105,8 +105,8 @@ static inline struct dvb_application_signalling_entry*
}
static inline struct dvb_application_signalling_entry*
- dvb_application_signalling_descriptor_countries_next(struct dvb_application_signalling_descriptor *d,
- struct dvb_application_signalling_entry *pos)
+ 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);
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c
index afbeb0f..99e5cf6 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.c
@@ -24,8 +24,8 @@
struct dvb_bat_section * dvb_bat_section_codec(struct section_ext * ext)
{
uint8_t * buf = (uint8_t *) ext;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(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))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h
index 277d5ab..94ed8a4 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/bat_section.h
@@ -71,7 +71,7 @@ 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.
*/
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h
index 70b0c98..f0f92f3 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/cable_delivery_descriptor.h
@@ -38,10 +38,10 @@ struct dvb_cable_delivery_descriptor {
uint32_t frequency; // BCD, units 100Hz
EBIT2(uint16_t reserved : 12; ,
- uint16_t fec_outer : 4; )
+ uint16_t fec_outer : 4; );
uint8_t modulation;
EBIT2(uint32_t symbol_rate : 28; , // BCD, units 100Hz
- uint32_t fec_inner : 4; )
+ uint32_t fec_inner : 4; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h
index b6285bd..63f7fd2 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_frequency_link_descriptor.h
@@ -160,7 +160,7 @@ static inline struct dvb_cell_frequency_link_cell*
}
static inline struct dvb_cell_frequency_link_cell_subcell*
- dvb_cell_frequency_cell_subcells_first(struct dvb_cell_frequency_link_cell *d)
+ dvb_cell_frequency_link_cell_subcells_first(struct dvb_cell_frequency_link_cell *d)
{
if (d->subcell_loop_info_length == 0)
return NULL;
@@ -170,7 +170,7 @@ static inline struct dvb_cell_frequency_link_cell_subcell*
}
static inline struct dvb_cell_frequency_link_cell_subcell*
- dvb_cell_frequency_cell_subcells_next(struct dvb_cell_frequency_link_cell *cell,
+ 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;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h
index 6a42ce4..ddbaf2c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/cell_list_descriptor.h
@@ -48,7 +48,7 @@ struct dvb_cell_list_entry {
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; )
+ uint32_t subcell_info_loop_length : 8; );
/* struct dvb_subcell_list_entry subcells[] */
} __ucsi_packed;
@@ -60,7 +60,7 @@ struct dvb_subcell_list_entry {
uint16_t subcell_latitude;
uint16_t subcell_longitude;
EBIT2(uint32_t subcell_extend_of_latitude :12; ,
- uint32_t subcell_extend_of_longitude :12; )
+ uint32_t subcell_extend_of_longitude :12; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h
index 154e235..31d38e1 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/component_descriptor.h
@@ -38,7 +38,7 @@ enum {
DVB_STREAM_CONTENT_VIDEO = 0x01,
DVB_STREAM_CONTENT_AUDIO = 0x02,
DVB_STREAM_CONTENT_SUBTITLE = 0x03,
- DVB_STREAM_CONTENT_AC3 = 0x04
+ DVB_STREAM_CONTENT_AC3 = 0x04,
};
/**
@@ -84,7 +84,7 @@ enum {
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_TYPE_SUBTITLE_DVB_HARDHEAR_2211 = 0x23,
};
/**
@@ -94,7 +94,7 @@ struct dvb_component_descriptor {
struct descriptor d;
EBIT2(uint8_t reserved : 4; ,
- uint8_t stream_content : 4; )
+ uint8_t stream_content : 4; );
uint8_t component_type;
uint8_t component_tag;
iso639lang_t language_code;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h
index 5cc16dc..d2a63a0 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_descriptor.h
@@ -46,9 +46,9 @@ struct dvb_content_descriptor {
*/
struct dvb_content_nibble {
EBIT2(uint8_t content_nibble_level_1 : 4; ,
- uint8_t content_nibble_level_2 : 4; )
+ uint8_t content_nibble_level_2 : 4; );
EBIT2(uint8_t user_nibble_1 : 4; ,
- uint8_t user_nibble_2 : 4; )
+ uint8_t user_nibble_2 : 4; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h
index 63d24a1..c2cf9ea 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/content_identifier_descriptor.h
@@ -39,7 +39,7 @@ enum {
DVB_CRID_TYPE_NONE = 0x00,
DVB_CRID_TYPE_ITEM = 0x01,
DVB_CRID_TYPE_SERIES = 0x02,
- DVB_CRID_TYPE_RECOMMENDATION = 0x03
+ DVB_CRID_TYPE_RECOMMENDATION = 0x03,
};
/**
@@ -47,7 +47,7 @@ enum {
*/
enum {
DVB_CRID_LOCATION_THIS_DESCRIPTOR = 0x00,
- DVB_CRID_LOCATION_CIT = 0x01
+ DVB_CRID_LOCATION_CIT = 0x01,
};
/**
@@ -64,7 +64,7 @@ struct dvb_content_identifier_descriptor {
*/
struct dvb_content_identifier_entry {
EBIT2(uint8_t crid_type : 6; ,
- uint8_t crid_location : 2; )
+ uint8_t crid_location : 2; );
/* struct dvb_content_identifier_data_00 data0 */
/* struct dvb_content_identifier_data_01 data1 */
} __ucsi_packed;
@@ -154,6 +154,17 @@ static inline struct dvb_content_identifier_entry_data_0*
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.
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h
index 29a6b9a..65b1661 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/country_availability_descriptor.h
@@ -38,7 +38,7 @@ struct dvb_country_availability_descriptor {
struct descriptor d;
EBIT2(uint8_t country_availability_flag : 1; ,
- uint8_t reserved : 7; )
+ uint8_t reserved : 7; );
/* struct dvb_country_availability_entry countries[] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h
index 8547d8f..446927c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/data_broadcast_id_descriptor.h
@@ -31,6 +31,23 @@ extern "C"
#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 {
@@ -41,6 +58,26 @@ struct dvb_data_broadcast_id_descriptor {
} __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.
@@ -81,6 +118,100 @@ static inline int
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
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h
index 0772601..345f6f0 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/descriptor.h
@@ -47,6 +47,9 @@ extern "C"
#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>
@@ -74,15 +77,28 @@ extern "C"
#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/time_slice_fec_identifier_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>
@@ -90,7 +106,7 @@ extern "C"
#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>
-#include <libucsi/endianops.h>
+*/
/**
* The following are not implemented just now
@@ -169,6 +185,10 @@ enum dvb_descriptor_tag {
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,
@@ -188,8 +208,20 @@ enum dvb_descriptor_tag {
dtag_dvb_ait_application_icons = 0x0b,
dtag_dvb_ait_prefetch = 0x0c,
dtag_dvb_ait_dii_location = 0x0d,
- dtag_dvb_ait_ip_signalling = 0x11
-};/*__ucsi_packed;*/
+ 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
}
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c
index ce22a58..97b0261 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.c
@@ -24,9 +24,9 @@
struct dvb_eit_section *dvb_eit_section_codec(struct section_ext * ext)
{
uint8_t * buf = (uint8_t *) ext;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(ext);
-
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
+
if (len < sizeof(struct dvb_eit_section))
return NULL;
@@ -34,14 +34,14 @@ struct dvb_eit_section *dvb_eit_section_codec(struct section_ext * ext)
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);
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h
index 9064224..a2f3e4f 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/eit_section.h
@@ -67,7 +67,7 @@ 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.
*/
@@ -111,7 +111,7 @@ static inline uint16_t dvb_eit_section_service_id(struct dvb_eit_section *eit)
static inline struct dvb_eit_event *
dvb_eit_section_events_first(struct dvb_eit_section *eit)
{
- int pos = sizeof(struct dvb_eit_section);
+ size_t pos = sizeof(struct dvb_eit_section);
if (pos >= section_ext_length(&eit->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h
index 82d580b..bba04b0 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/extended_event_descriptor.h
@@ -38,7 +38,7 @@ struct dvb_extended_event_descriptor {
struct descriptor d;
EBIT2(uint8_t descriptor_number : 4; ,
- uint8_t last_descriptor_number : 4; )
+ uint8_t last_descriptor_number : 4; );
iso639lang_t language_code;
uint8_t length_of_items;
/* struct dvb_extended_event_item items[] */
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h
index 4fca751..4c18cec 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/frequency_list_descriptor.h
@@ -36,7 +36,7 @@ extern "C"
enum {
DVB_CODING_TYPE_SATELLITE = 0x01,
DVB_CODING_TYPE_CABLE = 0x02,
- DVB_CODING_TYPE_TERRESTRIAL = 0x03
+ DVB_CODING_TYPE_TERRESTRIAL = 0x03,
};
/**
@@ -46,7 +46,7 @@ struct dvb_frequency_list_descriptor {
struct descriptor d;
EBIT2(uint8_t reserved : 6; ,
- uint8_t coding_type : 2; )
+ uint8_t coding_type : 2; );
/* uint32_t centre_frequencies [] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c
index a6ddd6e..c2bb15f 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.c
@@ -26,16 +26,15 @@ 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;
-
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(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 += 9;
+ pos += 6;
if (len - pos < in->platform_descriptors_length)
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h
index 71ba1e8..932c0e8 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/int_section.h
@@ -72,7 +72,7 @@ extern struct dvb_int_section * dvb_int_section_codec(struct section_ext *sectio
/**
* Accessor for the action_type field of an INT.
- *
+ *
* @param intp INT pointer.
* @return The action_type.
*/
@@ -83,7 +83,7 @@ static inline uint8_t dvb_int_section_action_type(struct dvb_int_section *intp)
/**
* Accessor for the platform_id_hash field of an INT.
- *
+ *
* @param intp INT pointer.
* @return The platform_id_hash.
*/
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_name_descriptor.h
new file mode 100644
index 0000000..c470e89
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_platform_provider_name_descriptor.h
new file mode 100644
index 0000000..ba95b8f
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/ip_mac_stream_location_descriptor.h
new file mode 100644
index 0000000..36216d6
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h
index f3370c8..d2be789 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/linkage_descriptor.h
@@ -46,7 +46,7 @@ enum {
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
+ DVB_LINKAGE_TYPE_TS_WITH_INT_BAT_NIT = 0x0c,
};
/**
@@ -55,7 +55,7 @@ enum {
enum {
DVB_HAND_OVER_TYPE_IDENTICAL_NEIGHBOURING_COUNTRY = 0x01,
DVB_HAND_OVER_TYPE_LOCAL_VARIATION = 0x02,
- DVB_HAND_OVER_TYPE_ASSOCIATED_SERVICE = 0x03
+ DVB_HAND_OVER_TYPE_ASSOCIATED_SERVICE = 0x03,
};
/**
@@ -63,7 +63,7 @@ enum {
*/
enum {
DVB_ORIGIN_TYPE_NIT = 0x00,
- DVB_ORIGIN_TYPE_SDT = 0x01
+ DVB_ORIGIN_TYPE_SDT = 0x01,
};
/**
@@ -85,7 +85,7 @@ struct dvb_linkage_descriptor {
struct dvb_linkage_data_08 {
EBIT3(uint8_t hand_over_type : 4; ,
uint8_t reserved : 3; ,
- uint8_t origin_type : 1; )
+ 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[] */
@@ -104,7 +104,7 @@ struct dvb_linkage_data_0b {
*/
struct dvb_platform_id {
EBIT2(uint32_t platform_id : 24; ,
- uint32_t platform_name_loop_length : 8; )
+ uint8_t platform_name_loop_length : 8; );
/* struct platform_name names[] */
} __ucsi_packed;
@@ -187,6 +187,8 @@ static inline struct dvb_linkage_descriptor*
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;
@@ -359,7 +361,7 @@ static inline struct 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_dvb_linkage_data_0b_platform_id_for_each(linkage, pos) \
+#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))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h
index 94932ff..d0eebb3 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/local_time_offset_descriptor.h
@@ -48,7 +48,7 @@ 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; )
+ uint8_t local_time_offset_polarity : 1; );
dvbhhmm_t local_time_offset;
dvbdate_t time_of_change;
dvbhhmm_t next_time_offset;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h
index d5cf435..d79b48c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/mhp_data_broadcast_id_descriptor.h
@@ -36,7 +36,7 @@ extern "C"
*/
enum {
DVB_BROADCAST_ID_MHP_OBJECT_CAROUSEL = 0x00f0,
- DVB_BROADCAST_ID_MHP_MPE = 0x00f1
+ DVB_BROADCAST_ID_MHP_MPE = 0x00f1,
};
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h
index 28838de..6da1e95 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/mosaic_descriptor.h
@@ -39,7 +39,7 @@ struct dvb_mosaic_descriptor {
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; )
+ uint8_t number_of_vert_elementary_cells : 3; );
/* struct dvb_mosaic_info infos[] */
} __ucsi_packed;
@@ -49,7 +49,7 @@ struct 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; )
+ 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 */
@@ -61,7 +61,7 @@ struct dvb_mosaic_info {
*/
struct dvb_mosaic_elementary_cell_field {
EBIT2(uint8_t reserved : 2; ,
- uint8_t elementary_cell_id : 6; )
+ uint8_t elementary_cell_id : 6; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/mpe_fec_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/mpe_fec_section.h
new file mode 100644
index 0000000..6db0a47
--- /dev/null
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/mpe_fec_section.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) 2008 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_MPE_FEC_SECTION_H
+#define _UCSI_DVB_MPE_FEC_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/mpeg/section.h>
+
+/**
+ * mpe_fec_section structure. TODO
+ */
+struct mpe_fec_section {
+ struct section head;
+};
+
+
+/**
+ * real_time_paramters
+ * can also be found in datagram_section in MAC4-1-bytes */
+struct real_time_parameters {
+ EBIT4(uint32_t delta_t : 12; ,
+ uint32_t table_boundary : 1; ,
+ uint32_t frame_boundary : 1; ,
+ uint32_t address : 18; )
+};
+
+
+static inline struct real_time_parameters * datagram_section_real_time_parameters_codec(struct datagram_section *d)
+{
+ struct real_time_parameters *rt = (struct real_time_parameters *) &d->MAC_address_4;
+ uint8_t b[4];
+ b[0] = d->MAC_address_4;
+ b[1] = d->MAC_address_3;
+ b[2] = d->MAC_address_2;
+ b[3] = d->MAC_address_1;
+
+ rt->delta_t = (b[0] << 4) | ((b[1] >> 4) & 0x0f);
+ rt->table_boundary = (b[1] >> 3) & 0x1;
+ rt->frame_boundary = (b[1] >> 2) & 0x1;
+ rt->address = ((b[1] & 0x3) << 16) | (b[2] << 8) | b[3];
+
+ return rt;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c
index d931926..664a0cb 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/nit_section.c
@@ -25,8 +25,8 @@ 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;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
if (len < sizeof(struct dvb_nit_section))
return NULL;
@@ -76,4 +76,3 @@ struct dvb_nit_section *dvb_nit_section_codec(struct section_ext * ext)
return ret;
}
-
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h
index 9acbcb0..72ecd0a 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/parental_rating_descriptor.h
@@ -49,7 +49,7 @@ enum {
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_MIN_17YEARS = 0x0f,
};
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h
index c8ba441..6e3aa96 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/partial_transport_stream_descriptor.h
@@ -41,7 +41,7 @@ struct dvb_partial_transport_stream_descriptor {
uint64_t reserved_2 : 2; ,
uint64_t minimum_overall_smoothing_rate :22; ,
uint64_t reserved_3 : 2; ,
- uint64_t maximum_overall_smoothing_rate :14; )
+ uint64_t maximum_overall_smoothing_rate :14; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h
index 49cc187..68190be 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/pdc_descriptor.h
@@ -37,7 +37,7 @@ struct dvb_pdc_descriptor {
struct descriptor d;
EBIT2(uint32_t reserved : 4; ,
- uint32_t programme_id_label :20; )
+ uint32_t programme_id_label :20; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h
index b67b0d9..ba42d12 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_dvb_stream_descriptor.h
@@ -40,7 +40,7 @@ struct dvb_rnt_rar_over_dvb_stream_descriptor {
dvbdate_t last_valid_date;
EBIT3(uint8_t weighting : 6; ,
uint8_t complete_flag : 1; ,
- uint8_t scheduled_flag : 1; )
+ uint8_t scheduled_flag : 1; );
uint16_t transport_stream_id;
uint16_t original_network_id;
uint16_t service_id;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h
index cc0ed58..b1f2da4 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/rnt_rar_over_ip_descriptor.h
@@ -40,7 +40,7 @@ struct dvb_rnt_rar_over_ip_descriptor {
dvbdate_t last_valid_date;
EBIT3(uint8_t weighting : 6; ,
uint8_t complete_flag : 1; ,
- uint8_t reserved : 1; )
+ uint8_t reserved : 1; );
uint8_t url_length;
/* uint8_t url[] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c
index 67fa0d3..259d2b0 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.c
@@ -24,8 +24,8 @@
struct dvb_rst_section * dvb_rst_section_codec(struct section *section)
{
uint8_t * buf = (uint8_t *) section;
- int pos = sizeof(struct section);
- int len = section_length(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) {
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h
index b4269b8..4b3360b 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/rst_section.h
@@ -82,7 +82,7 @@ struct dvb_rst_section *dvb_rst_section_codec(struct section *section);
static inline struct dvb_rst_status *
dvb_rst_section_statuses_first(struct dvb_rst_section *rst)
{
- int pos = sizeof(struct dvb_rst_section);
+ size_t pos = sizeof(struct dvb_rst_section);
if (pos >= section_length(&rst->head))
return NULL;
@@ -108,4 +108,3 @@ static inline struct dvb_rst_status *
#endif
#endif
-
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h
index 66c9288..8f9fea8 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/s2_satellite_delivery_descriptor.h
@@ -39,7 +39,7 @@ struct dvb_s2_satellite_delivery_descriptor {
EBIT4(uint8_t scrambling_sequence_selector : 1; ,
uint8_t multiple_input_stream : 1; ,
uint8_t backwards_compatability : 1; ,
- uint8_t reserved : 5; )
+ 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;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h
index 23be76e..b93d052 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/satellite_delivery_descriptor.h
@@ -42,9 +42,9 @@ struct dvb_satellite_delivery_descriptor {
uint8_t polarization : 2; ,
uint8_t roll_off : 2; ,
uint8_t modulation_system : 1; ,
- uint8_t modulation_type : 2; )
+ uint8_t modulation_type : 2; );
EBIT2(uint32_t symbol_rate : 28; , // BCD, units 100Hz
- uint32_t fec_inner : 4; )
+ uint32_t fec_inner : 4; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c
index bdc8ce1..4c7824c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.c
@@ -24,8 +24,8 @@
struct dvb_sdt_section * dvb_sdt_section_codec(struct section_ext * ext)
{
uint8_t * buf = (uint8_t *) ext;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
if (len < sizeof(struct dvb_sdt_section))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h
index 0130fe7..03a8569 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/sdt_section.h
@@ -109,7 +109,7 @@ static inline uint16_t dvb_sdt_section_transport_stream_id(struct dvb_sdt_sectio
static inline struct dvb_sdt_service *
dvb_sdt_section_services_first(struct dvb_sdt_section * sdt)
{
- int pos = sizeof(struct dvb_sdt_section);
+ size_t pos = sizeof(struct dvb_sdt_section);
if (pos >= section_ext_length(&sdt->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h
index 8488d71..70e0880 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/section.h
@@ -39,6 +39,7 @@ extern "C"
#include <libucsi/dvb/tot_section.h>
#include <libucsi/dvb/tva_container_section.h>
#include <libucsi/dvb/int_section.h>
+#include <libucsi/dvb/mpe_fec_section.h>
/**
* The following are not implemented just now.
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h
index f16781b..64def75 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_availability_descriptor.h
@@ -37,7 +37,7 @@ struct dvb_service_availability_descriptor {
struct descriptor d;
EBIT2(uint8_t availability_flag : 1; ,
- uint8_t reserved : 7; )
+ uint8_t reserved : 7; );
/* uint16_t cell_ids[] */
} __ucsi_packed;
@@ -73,10 +73,10 @@ static inline struct dvb_service_availability_descriptor*
* @param d dvb_service_availability_descriptor pointer.
* @return Pointer to the field.
*/
-static inline uint32_t *
+static inline uint16_t *
dvb_service_availability_descriptor_cell_ids(struct dvb_service_availability_descriptor *d)
{
- return (uint32_t *) ((uint8_t *) d + sizeof(struct dvb_service_availability_descriptor));
+ return (uint16_t *) ((uint8_t *) d + sizeof(struct dvb_service_availability_descriptor));
}
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h
index e116ffc..dd0f0ec 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/service_descriptor.h
@@ -49,7 +49,14 @@ enum {
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_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,
};
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h
index 7deab9b..e52d20a 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/short_smoothing_buffer_descriptor.h
@@ -37,7 +37,7 @@ struct dvb_short_smoothing_buffer_descriptor {
struct descriptor d;
EBIT2(uint8_t sb_size : 2; ,
- uint8_t sb_leak_rate : 6; )
+ uint8_t sb_leak_rate : 6; );
/* uint8_t reserved [] */
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c
index 61134d0..06c228c 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.c
@@ -25,8 +25,8 @@ 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;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
if (len < sizeof(struct dvb_sit_section))
return NULL;
@@ -67,4 +67,3 @@ struct dvb_sit_section * dvb_sit_section_codec(struct section_ext * ext)
return ret;
}
-
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h
index d05989f..e06d596 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/sit_section.h
@@ -125,7 +125,7 @@ static inline struct descriptor *
static inline struct dvb_sit_service *
dvb_sit_section_services_first(struct dvb_sit_section *sit)
{
- int pos = sizeof(struct dvb_sit_section) + sit->transmission_info_loop_length;
+ size_t pos = sizeof(struct dvb_sit_section) + sit->transmission_info_loop_length;
if (pos >= section_ext_length(&sit->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_address_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_address_descriptor.h
new file mode 100644
index 0000000..c08b60e
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_slash_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_slash_descriptor.h
new file mode 100644
index 0000000..e5bc76a
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_source_slash_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ip_source_slash_descriptor.h
new file mode 100644
index 0000000..8cade48
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_address_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_address_descriptor.h
new file mode 100644
index 0000000..1b28b48
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_slash_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_slash_descriptor.h
new file mode 100644
index 0000000..3dc6d75
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/target_ipv6_source_slash_descriptor.h
new file mode 100644
index 0000000..3a4b38e
--- /dev/null
+++ b/kaffeine/src/input/dvb/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/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c
index 30a23cf..ba64fe9 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/tdt_section.c
@@ -23,7 +23,7 @@
struct dvb_tdt_section * dvb_tdt_section_codec(struct section * section)
{
- int len = section->length + sizeof(struct section);
+ size_t len = section_length(section);
struct dvb_tdt_section * ret = (struct dvb_tdt_section *) section;
if (len != sizeof(struct dvb_tdt_section))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h
index 46b39e4..3dc43a1 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/telephone_descriptor.h
@@ -38,14 +38,14 @@ struct dvb_telephone_descriptor {
EBIT3(uint8_t reserved_1 : 2; ,
uint8_t foreign_availability : 1; ,
- uint8_t connection_type : 5; )
+ 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; )
+ 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 core_number_length : 4; );
/* uint8_t country_prefix[] */
/* uint8_t international_area_code[] */
/* uint8_t operator_code[] */
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h
index 280b6eb..424c1cb 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/teletext_descriptor.h
@@ -39,7 +39,7 @@ enum {
DVB_TELETEXT_TYPE_SUBTITLE = 0x02,
DVB_TELETEXT_TYPE_ADDITIONAL = 0x03,
DVB_TELETEXT_TYPE_SCHEDULE = 0x04,
- DVB_TELETEXT_TYPE_SUBTITLE_HEARING_IMPAIRED= 0x05
+ DVB_TELETEXT_TYPE_SUBTITLE_HEARING_IMPAIRED= 0x05,
};
/**
@@ -57,7 +57,7 @@ struct dvb_teletext_descriptor {
struct dvb_teletext_entry {
iso639lang_t language_code;
EBIT2(uint8_t type : 5; ,
- uint8_t magazine_number: 3; )
+ uint8_t magazine_number: 3; );
uint8_t page_number;
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h
index b890178..c624dab 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/terrestrial_delivery_descriptor.h
@@ -41,14 +41,14 @@ struct dvb_terrestrial_delivery_descriptor {
uint8_t priority : 1; ,
uint8_t time_slicing_indicator : 1; ,
uint8_t mpe_fec_indicator : 1; ,
- uint8_t reserved_1 : 2; )
+ uint8_t reserved_1 : 2; );
EBIT3(uint8_t constellation : 2; ,
uint8_t hierarchy_information : 3; ,
- uint8_t code_rate_hp_stream : 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; )
+ uint8_t other_frequency_flag : 1; );
uint32_t reserved_2;
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/time_slice_fec_identifier_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/time_slice_fec_identifier_descriptor.h
new file mode 100644
index 0000000..00f3048
--- /dev/null
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/time_slice_fec_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)
+ * Copyright (C) 2008 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_TIME_SLICE_FEC_IDENTIFIER_DESCRIPTOR
+#define _UCSI_DVB_TIME_SLICE_FEC_IDENTIFIER_DESCRIPTOR 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/descriptor.h>
+#include <libucsi/types.h>
+
+/*
+ * dvb_time_slice_fec_identifier_descriptor structure.
+ */
+struct dvb_time_slice_fec_identifier_descriptor {
+ struct descriptor d;
+
+ EBIT4(uint8_t time_slicing :1; ,
+ uint8_t mpe_fec :2; ,
+ uint8_t reserved :2; ,
+ uint8_t frame_size :3; );
+
+ uint8_t max_burst_duration;
+
+ EBIT2(uint8_t max_average_rate :4; ,
+ uint8_t time_slice_fec_id :4; );
+ /* id_selector_bytes[] */
+};
+
+static inline struct dvb_time_slice_fec_identifier_descriptor *
+ dvb_time_slice_fec_identifier_descriptor_codec(struct descriptor* d)
+{
+ if (d->len < 3)
+ return NULL;
+ return (struct dvb_time_slice_fec_identifier_descriptor *) d;
+}
+
+static inline uint8_t dvb_time_slice_fec_identifier_selector_byte_length(struct dvb_time_slice_fec_identifier_descriptor *d)
+{
+ return d->d.len - 3;
+}
+
+static inline uint8_t * dvb_time_slice_fec_identifier_selector_bytes(struct dvb_time_slice_fec_identifier_descriptor *d)
+{
+ if (d->d.len < 3)
+ return NULL;
+ else
+ return ((uint8_t *) d) + 2 + 3;
+}
+
+static inline uint16_t dvb_time_slice_fec_identifier_max_burst_duration_msec(struct dvb_time_slice_fec_identifier_descriptor *d)
+{
+ return (d->max_burst_duration + 1) * 20;
+}
+
+static inline uint16_t dvb_time_slice_fec_identifier_frame_size_kbits(struct dvb_time_slice_fec_identifier_descriptor *d)
+{
+ if (d->frame_size > 3)
+ return 0;
+ return (d->frame_size+1) * 512;
+}
+
+static inline uint16_t dvb_time_slice_fec_identifier_frame_size_rows(struct dvb_time_slice_fec_identifier_descriptor *d)
+{
+ return dvb_time_slice_fec_identifier_frame_size_kbits(d) / 2;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c
index 3ce2c6d..5dc7890 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/tot_section.c
@@ -24,8 +24,8 @@
struct dvb_tot_section *dvb_tot_section_codec(struct section *section)
{
uint8_t * buf = (uint8_t *)section;
- int pos = sizeof(struct section);
- int len = section->length + sizeof(struct section) - CRC_SIZE;
+ 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))
@@ -34,7 +34,7 @@ struct dvb_tot_section *dvb_tot_section_codec(struct section *section)
pos += 5;
bswap16(buf + pos);
pos += 2;
-
+
if ((pos + ret->descriptors_loop_length) > len)
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c
index 32a5795..f526efc 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.c
@@ -23,7 +23,7 @@
struct dvb_tva_container_section *dvb_tva_container_section_codec(struct section_ext *ext)
{
- int len = section_ext_length(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))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h
index 6519ded..7d0abb1 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_container_section.h
@@ -59,7 +59,7 @@ static inline uint16_t dvb_tva_container_section_container_id(struct dvb_tva_con
}
/**
- * Accessor for the selector_byte field of a dvb_data_broadcast_id_descriptor.
+ * 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.
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h
index c830259..3b4f3e8 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/tva_id_descriptor.h
@@ -45,7 +45,7 @@ struct dvb_tva_id_descriptor {
struct dvb_tva_id_entry {
uint16_t tva_id;
EBIT2(uint8_t reserved : 5; ,
- uint8_t running_status : 3; )
+ uint8_t running_status : 3; );
} __ucsi_packed;
/**
@@ -105,7 +105,7 @@ static inline struct dvb_tva_id_entry*
}
static inline struct dvb_tva_id_entry*
- dvb_tva_id_descriptor_countries_next(struct dvb_tva_id_descriptor *d,
+ 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;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h
index f26ea6b..437c7c3 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/types.h
@@ -40,7 +40,7 @@ enum {
DVB_RUNNING_STATUS_NOT_RUNNING = 0x01,
DVB_RUNNING_STATUS_FEW_SECONDS = 0x02,
DVB_RUNNING_STATUS_PAUSING = 0x03,
- DVB_RUNNING_STATUS_RUNNING = 0x04
+ DVB_RUNNING_STATUS_RUNNING = 0x04,
};
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h
index 9d41e0c..b1d8703 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_data_descriptor.h
@@ -39,7 +39,7 @@ enum {
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_SERVICE_ID_MONO_422 = 0x07,
};
/**
@@ -66,7 +66,7 @@ struct dvb_vbi_data_entry {
struct dvb_vbi_data_x {
EBIT3(uint8_t reserved : 2; ,
uint8_t field_parity : 1; ,
- uint8_t line_offset : 5; )
+ uint8_t line_offset : 5; );
} __ucsi_packed;
/**
diff --git a/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h
index 6ae9791..fd779d7 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/dvb/vbi_teletext_descriptor.h
@@ -46,7 +46,7 @@ struct dvb_vbi_teletext_descriptor {
struct dvb_vbi_teletext_entry {
iso639lang_t language_code;
EBIT2(uint8_t type : 5; ,
- uint8_t magazine_number: 3; )
+ uint8_t magazine_number: 3; );
uint8_t page_number;
} __ucsi_packed;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c
index c72973e..8c974b8 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.c
@@ -24,7 +24,7 @@
struct mpeg_cat_section * mpeg_cat_section_codec(struct section_ext * ext)
{
uint8_t * buf = (uint8_t *)ext;
- int pos = sizeof(struct section_ext);
+ size_t pos = sizeof(struct section_ext);
if (verify_descriptors(buf + pos,
section_ext_length(ext) - sizeof(struct mpeg_cat_section)))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h
index 864b19e..7ed34a3 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/cat_section.h
@@ -69,7 +69,7 @@ extern struct mpeg_cat_section *mpeg_cat_section_codec(struct section_ext *secti
static inline struct descriptor *
mpeg_cat_section_descriptors_first(struct mpeg_cat_section *cat)
{
- int pos = sizeof(struct mpeg_cat_section);
+ size_t pos = sizeof(struct mpeg_cat_section);
if (pos >= section_ext_length(&cat->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/datagram_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/datagram_section.h
new file mode 100644
index 0000000..769773a
--- /dev/null
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/datagram_section.h
@@ -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)
+ * Copyright (C) 2008 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_MPEG_DATAGRAM_SECTION_H
+#define _UCSI_MPEG_DATAGRAM_SECTION_H 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#include <libucsi/section.h>
+
+/**
+ * datagram_section structure.
+ */
+struct datagram_section {
+ struct section head;
+
+ uint8_t MAC_address_6;
+ uint8_t MAC_address_5;
+ EBIT5(uint8_t reserved : 2; ,
+ uint8_t payload_scrambling_control : 2; ,
+ uint8_t address_scrambling_control : 2; ,
+ uint8_t LLC_SNAP_flag : 1; ,
+ uint8_t current_next_indicator : 1; );
+ uint8_t section_number;
+ uint8_t last_section_number;
+ uint8_t MAC_address_4;
+ uint8_t MAC_address_3;
+ uint8_t MAC_address_2;
+ uint8_t MAC_address_1;
+
+ /* LLC_SNAP or IP-data */
+ /* if last section stuffing */
+ /* CRC */
+} __ucsi_packed;
+
+/**
+ */
+static inline struct datagram_section *datagram_section_codec(struct section *section)
+{
+ /* something to do here ? */
+ return (struct datagram_section *) section;
+}
+
+static inline uint8_t *datagram_section_ip_data(struct datagram_section *d)
+{
+ return (uint8_t *) d + sizeof(struct section) + 2 + 1 + 1 + 1 + 4;
+}
+
+static inline size_t datagram_section_ip_data_length(struct datagram_section *d)
+{
+ return section_length(&d->head) - (sizeof(struct section) + 2 + 1 + 1 + 1 + 4) - CRC_SIZE;
+}
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c
index 9af1d96..c1ce019 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/metadata_section.c
@@ -25,4 +25,3 @@ struct mpeg_metadata_section * mpeg_metadata_section_codec(struct section_ext *
{
return (struct mpeg_metadata_section *)ext;
}
-
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c
index c56ccb1..07407f2 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.c
@@ -25,8 +25,8 @@ 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;
- int pos = sizeof(struct section_ext);
- int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
int i;
if (len < sizeof(struct mpeg_odsmt_section))
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h
index 2e5302d..4e01085 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/odsmt_section.h
@@ -61,9 +61,9 @@ struct mpeg_odsmt_stream_multi
*/
struct mpeg_odsmt_stream {
union {
- struct mpeg_odsmt_stream_single single __ucsi_packed;
- struct mpeg_odsmt_stream_multi multi __ucsi_packed;
- } u __ucsi_packed;
+ struct mpeg_odsmt_stream_single single;
+ struct mpeg_odsmt_stream_multi multi;
+ } u;
} __ucsi_packed;
/**
@@ -118,7 +118,7 @@ static inline uint16_t mpeg_odsmt_section_pid(struct mpeg_odsmt_section *odsmt)
*/
static inline uint8_t*
mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt,
- uint32_t* len);
+ size_t* len);
@@ -133,7 +133,7 @@ static inline uint8_t*
static inline struct mpeg_odsmt_stream *
mpeg_odsmt_section_streams_first(struct mpeg_odsmt_section *odsmt)
{
- int pos = sizeof(struct mpeg_odsmt_section);
+ size_t pos = sizeof(struct mpeg_odsmt_section);
if (pos >= section_ext_length(&odsmt->head))
return NULL;
@@ -144,12 +144,12 @@ static inline struct mpeg_odsmt_stream *
static inline struct mpeg_odsmt_stream *
mpeg_odsmt_section_streams_next(struct mpeg_odsmt_section *odsmt,
struct mpeg_odsmt_stream *pos,
- int index)
+ int _index)
{
uint8_t *end = (uint8_t*) odsmt + section_ext_length(&odsmt->head);
uint8_t *next;
- if (index > odsmt->stream_count)
+ if (_index > odsmt->stream_count)
return NULL;
next = (uint8_t *) pos + sizeof(struct mpeg_odsmt_stream_multi) +
@@ -198,13 +198,13 @@ static inline struct descriptor *
static inline uint8_t*
mpeg_odsmt_section_object_descriptors(struct mpeg_odsmt_section * odsmt,
- uint32_t* len)
+ size_t* len)
{
struct mpeg_odsmt_stream* pos;
- int size = sizeof(struct mpeg_odsmt_section);
- int index;
+ size_t size = sizeof(struct mpeg_odsmt_section);
+ int _index;
- mpeg_odsmt_section_streams_for_each(odsmt, pos, 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;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c
index 80b28d5..2e4c2cc 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.c
@@ -24,8 +24,8 @@
struct mpeg_pat_section *mpeg_pat_section_codec(struct section_ext * ext)
{
uint8_t *buf = (uint8_t *)ext;
- int pos = sizeof(struct section_ext);
- int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
if (len < sizeof(struct mpeg_pat_section))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h
index 20b3f7a..eadfe28 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pat_section.h
@@ -44,7 +44,7 @@ struct mpeg_pat_section {
struct mpeg_pat_program {
uint16_t program_number;
EBIT2(uint16_t reserved : 3; ,
- uint16_t pid :13; )
+ uint16_t pid :13; );
} __ucsi_packed;
/**
@@ -90,7 +90,7 @@ static inline uint16_t mpeg_pat_section_transport_stream_id(struct mpeg_pat_sect
static inline struct mpeg_pat_program *
mpeg_pat_section_programs_first(struct mpeg_pat_section * pat)
{
- int pos = sizeof(struct mpeg_pat_section);
+ size_t pos = sizeof(struct mpeg_pat_section);
if (pos >= section_ext_length(&pat->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c
index 6ff4fac..e5aec6a 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.c
@@ -25,8 +25,8 @@ 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;
- unsigned int pos = sizeof(struct section_ext);
- unsigned int len = section_ext_length(ext);
+ size_t pos = sizeof(struct section_ext);
+ size_t len = section_ext_length(ext);
if (len < sizeof(struct mpeg_pmt_section))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h
index 73bba1d..03dea1b 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/pmt_section.h
@@ -36,9 +36,9 @@ struct mpeg_pmt_section {
struct section_ext head;
EBIT2(uint16_t reserved_1 : 3; ,
- uint16_t pcr_pid :13; )
+ uint16_t pcr_pid :13; );
EBIT2(uint16_t reserved_2 : 4; ,
- uint16_t program_info_length :12; )
+ uint16_t program_info_length :12; );
/* struct descriptor descriptors[] */
/* struct mpeg_pmt_stream streams[] */
} __ucsi_packed;
@@ -49,9 +49,9 @@ struct mpeg_pmt_section {
struct mpeg_pmt_stream {
uint8_t stream_type;
EBIT2(uint16_t reserved_1 : 3; ,
- uint16_t pid :13; )
+ uint16_t pid :13; );
EBIT2(uint16_t reserved_2 : 4; ,
- uint16_t es_info_length :12; )
+ uint16_t es_info_length :12; );
/* struct descriptor descriptors[] */
} __ucsi_packed;
@@ -66,7 +66,7 @@ extern struct mpeg_pmt_section *mpeg_pmt_section_codec(struct section_ext *secti
/**
* Accessor for program_number field of a PMT.
- *
+ *
* @param pmt PMT pointer.
* @return The program_number.
*/
@@ -140,7 +140,7 @@ static inline struct descriptor *
static inline struct mpeg_pmt_stream *
mpeg_pmt_section_streams_first(struct mpeg_pmt_section * pmt)
{
- int pos = sizeof(struct mpeg_pmt_section) + pmt->program_info_length;
+ size_t pos = sizeof(struct mpeg_pmt_section) + pmt->program_info_length;
if (pos >= section_ext_length(&pmt->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h
index 6215e95..f71f95e 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/section.h
@@ -33,6 +33,7 @@ extern "C"
#include <libucsi/mpeg/pmt_section.h>
#include <libucsi/mpeg/tsdt_section.h>
#include <libucsi/mpeg/metadata_section.h>
+#include <libucsi/mpeg/datagram_section.h>
#define TRANSPORT_PAT_PID 0x00
#define TRANSPORT_CAT_PID 0x01
@@ -48,7 +49,8 @@ enum mpeg_section_tag {
stag_mpeg_transport_stream_description = 0x03,
stag_mpeg_iso14496_scene_description = 0x04,
stag_mpeg_iso14496_object_description = 0x05,
- stag_mpeg_metadata = 0x06
+ stag_mpeg_metadata = 0x06,
+ stag_mpeg_datagram = 0x3e,
};
#ifdef __cplusplus
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c
index fbbbe3c..fec9dd7 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.c
@@ -24,7 +24,7 @@
struct mpeg_tsdt_section * mpeg_tsdt_section_codec(struct section_ext * ext)
{
uint8_t * buf = (uint8_t *)ext;
- int pos = sizeof(struct section_ext);
+ size_t pos = sizeof(struct section_ext);
if (verify_descriptors(buf + pos,
section_ext_length(ext) - sizeof(struct mpeg_tsdt_section)))
@@ -32,4 +32,3 @@ struct mpeg_tsdt_section * mpeg_tsdt_section_codec(struct section_ext * ext)
return (struct mpeg_tsdt_section *)ext;
}
-
diff --git a/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h
index 9039278..2bbae02 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/mpeg/tsdt_section.h
@@ -70,7 +70,7 @@ extern struct mpeg_tsdt_section *mpeg_tsdt_section_codec(struct section_ext *sec
static inline struct descriptor *
mpeg_tsdt_section_descriptors_first(struct mpeg_tsdt_section * tsdt)
{
- int pos = sizeof(struct mpeg_tsdt_section);
+ size_t pos = sizeof(struct mpeg_tsdt_section);
if (pos >= section_ext_length(&tsdt->head))
return NULL;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/section.h b/kaffeine/src/input/dvb/lib/libucsi/section.h
index e2f7551..53ad07f 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/section.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/section.h
@@ -43,7 +43,7 @@ struct section {
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 length :12; );
} __ucsi_packed;
/**
@@ -54,12 +54,12 @@ struct section_ext {
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 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 current_next_indicator : 1; );
uint8_t section_number;
uint8_t last_section_number;
} __ucsi_packed;
@@ -76,13 +76,36 @@ struct psi_table_state {
/**
+ * 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, int len)
+static inline struct section * section_codec(uint8_t * buf, size_t len)
{
struct section * ret = (struct section *)buf;
@@ -91,7 +114,7 @@ static inline struct section * section_codec(uint8_t * buf, int len)
bswap16(buf+1);
- if (len != ret->length + 3)
+ if (len != ret->length + 3U)
return NULL;
return ret;
@@ -107,7 +130,7 @@ static inline struct section * section_codec(uint8_t * buf, int len)
static inline int section_check_crc(struct section *section)
{
uint8_t * buf = (uint8_t *) section;
- int len = sizeof(struct section) + section->length;
+ size_t len = section_length(section);
uint32_t crc;
/* the crc check has to be performed on the unswapped data */
@@ -167,12 +190,9 @@ static inline struct section_ext * section_ext_encode(struct section_ext* sectio
int len = sizeof(struct section) + section->length;
uint32_t crc;
- /* zap the current CRC value */
- memset(buf+len-4, 0, 4);
-
/* the crc has to be performed on the swapped data */
bswap16(buf+1);
- crc = crc32(CRC32_INIT, buf, len);
+ crc = crc32(CRC32_INIT, buf, len-4);
bswap16(buf+1);
/* update the CRC */
@@ -184,29 +204,6 @@ static inline struct section_ext * section_ext_encode(struct section_ext* sectio
}
/**
- * Determine the total length of a section, including the header.
- *
- * @param section The parsed section structure.
- * @return The length.
- */
-static inline int 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 int section_ext_length(struct section_ext * section)
-{
- return section->length + sizeof(struct section) - CRC_SIZE;
-}
-
-/**
* Reset a psi_table_state structure.
*
* @param tstate The structure to reset.
@@ -227,7 +224,10 @@ static inline int section_ext_useful(struct section_ext *section, struct psi_tab
{
if ((section->version_number == tstate->version_number) && tstate->complete)
return 0;
- if ((section->version_number != tstate->version_number) && (section->section_number == 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;
diff --git a/kaffeine/src/input/dvb/lib/libucsi/section_buf.h b/kaffeine/src/input/dvb/lib/libucsi/section_buf.h
index e15cc1d..52d2f84 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/section_buf.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/section_buf.h
@@ -54,11 +54,10 @@ struct section_buf {
extern int section_buf_init(struct section_buf *section, int max);
/**
- * Initialise a section_buf structure.
+ * 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 initialise.
- * @param max Maximum number of bytes in section (must be > 3)
- * @return 0 on success, nonzero on error.
+ * @param section The section_buf to reset.
*/
static inline void section_buf_reset(struct section_buf *section)
{
diff --git a/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h b/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h
index 7dfbd78..6314eca 100644
--- a/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h
+++ b/kaffeine/src/input/dvb/lib/libucsi/transport_packet.h
@@ -145,7 +145,7 @@ static inline int transport_packet_pid(struct transport_packet *pkt)
/**
* Process a buffer into a transport packet.
*
- * @param buf Raw buffer.
+ * @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)
diff --git a/kaffeine/src/input/dvb/plugins/epg/kaffeinedvbsection.cpp b/kaffeine/src/input/dvb/plugins/epg/kaffeinedvbsection.cpp
index d6170e8..54c912e 100644
--- a/kaffeine/src/input/dvb/plugins/epg/kaffeinedvbsection.cpp
+++ b/kaffeine/src/input/dvb/plugins/epg/kaffeinedvbsection.cpp
@@ -141,6 +141,9 @@ bool KaffeineDVBsection::doIconv( QCString &s, QCString table, char *buffer, int
if ( inSize<1 )
return false;
cd = iconv_open( "UTF8", table );
+ //check if charset unknown
+ if( cd == (iconv_t)(-1) )
+ return false;
inBuf = s.data();
outBuf = buffer;
outBuf[0] = 0;
diff --git a/kaffeine/src/input/dvb/scandialog.cpp b/kaffeine/src/input/dvb/scandialog.cpp
index 2399c74..4e1a14c 100644
--- a/kaffeine/src/input/dvb/scandialog.cpp
+++ b/kaffeine/src/input/dvb/scandialog.cpp
@@ -109,13 +109,15 @@ ScanDialog::ScanDialog( QPtrList<DvbStream> *d, QPtrList<ChannelDesc> *ch, QSize
foundList->clear();
foundList->setAllColumnsShowFocus( true );
foundList->setSelectionMode( QListView::Extended );
- channelsList->setSorting( 0 );
+ channelsList->setSorting( 1 ); // sort by source 1st than channel name
+ channelsList->setAllColumnsShowFocus( true );
+ channelsList->setSelectionMode( QListView::Extended );
ChannelDesc *chan;
QListViewItem *it;
for ( int i=0; i<(int)chandesc->count(); i++ ) {
chan = chandesc->at(i);
- it = new QListViewItem( channelsList, chan->name );
+ it = new QListViewItem( channelsList, chan->name, chan->tp.source );
if ( !chan->pix.isNull() )
it->setPixmap( 0, chan->pix );
else {
@@ -425,7 +427,11 @@ void ScanDialog::parseTp( QString s, fe_type_t type, QString src )
trans->type=FE_QAM;
trans->source = "Cable";
}
- else {
+ else if ( s.left(pos)=="A" ) {
+ trans->type=FE_ATSC;
+ trans->source = "ATSC Terrestrial";
+ }
+ else if ( s.left(pos)=="S" ) {
trans->type=FE_QPSK;
trans->source = src;
}
@@ -439,14 +445,15 @@ void ScanDialog::parseTp( QString s, fe_type_t type, QString src )
trans->freq = s.left(pos).toULong()/1000;
s = s.right( s.length()-pos-1 );
s = s.stripWhiteSpace();
- pos = s.find(" ");
+ if ( trans->type!=FE_ATSC )
+ pos = s.find(" ");
if ( trans->type==FE_QPSK ) {
trans->pol = s.left(pos).lower()[0].latin1();
s = s.right( s.length()-pos-1 );
s = s.stripWhiteSpace();
pos = s.find(" ");
}
- if ( trans->type!=FE_OFDM ) {
+ if ( trans->type!=FE_OFDM && trans->type!=FE_ATSC ) {
trans->sr = s.left(pos).toULong()/1000;
}
else {
@@ -459,6 +466,27 @@ void ScanDialog::parseTp( QString s, fe_type_t type, QString src )
else
trans->bandwidth = BANDWIDTH_AUTO;
}
+ if ( trans->type==FE_ATSC ) {
+ if ( s.left(pos)=="8VSB" )
+ trans->modulation = VSB_8;
+ else if ( s.left(pos)=="16VSB" )
+ trans->modulation = VSB_16;
+ else if ( s.left(pos)=="QAM16" )
+ trans->modulation = QAM_16;
+ else if ( s.left(pos)=="QAM32" )
+ trans->modulation = QAM_32;
+ else if ( s.left(pos)=="QAM64" )
+ trans->modulation = QAM_64;
+ else if ( s.left(pos)=="QAM128" )
+ trans->modulation = QAM_128;
+ else if ( s.left(pos)=="QAM256" )
+ trans->modulation = QAM_256;
+ else
+ trans->modulation = QAM_AUTO;
+ transponders.append( trans );
+ return;
+ }
+
s = s.right( s.length()-pos-1 );
s = s.stripWhiteSpace();
pos = s.find(" ");
@@ -584,7 +612,17 @@ bool ScanDialog::getTransData()
if ( searchComb->currentText().startsWith("AUTO") ) {
int i;
- for ( i=402; i<900; i+=8 ) {
+ for ( i=177; i<227; i+=7 ) {
+ if ( offset07->isChecked() ) {
+ s = QString("T %1 7MHz AUTO AUTO AUTO AUTO AUTO AUTO").arg( (i*1000000)+500000 );
+ parseTp( s, ds->getType(), "" );
+ }
+ if ( offset125p->isChecked() ) {
+ s = QString("T %1 7MHz AUTO AUTO AUTO AUTO AUTO AUTO").arg( (i*1000000)+500000+125000 );
+ parseTp( s, ds->getType(), "" );
+ }
+ }
+ for ( i=474; i<859; i+=8 ) {
if ( offset167m->isChecked() ) {
s = QString("T %1 8MHz AUTO AUTO AUTO AUTO AUTO AUTO").arg( (i*1000000)-167000 );
parseTp( s, ds->getType(), "" );
@@ -605,7 +643,9 @@ bool ScanDialog::getTransData()
case FE_QPSK : s += "dvb-s/"; break;
case FE_QAM : s += "dvb-c/"; break;
case FE_OFDM : s += "dvb-t/"; break;
- case FE_ATSC : return false;
+ case FE_ATSC : s += "atsc/"; break;
+ default:
+ return false;
}
s += searchComb->currentText();
QFile f( s );
@@ -713,7 +753,9 @@ void ScanDialog::addSelected()
if(checkChannUpdate(chan)){
checkDuplicateName( chan );
- chan->num = chandesc->count()+1;
+ if (chan->num == 0) {
+ chan->num = chandesc->count()+1;
+ }
chandesc->append( new ChannelDesc( *chan ) );
it = new QListViewItem( channelsList, chan->name );
if ( chan->type==1 ) {
diff --git a/kaffeine/src/input/dvb/scandialogui.ui b/kaffeine/src/input/dvb/scandialogui.ui
index 04cbdd1..cdc1059 100644
--- a/kaffeine/src/input/dvb/scandialogui.ui
+++ b/kaffeine/src/input/dvb/scandialogui.ui
@@ -8,8 +8,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>725</width>
- <height>560</height>
+ <width>790</width>
+ <height>578</height>
</rect>
</property>
<property name="caption">
@@ -21,7 +21,7 @@
</property>
<widget class="QLayoutWidget" row="0" column="0">
<property name="name">
- <cstring>layout10</cstring>
+ <cstring>layout9</cstring>
</property>
<vbox>
<property name="name">
@@ -29,7 +29,7 @@
</property>
<widget class="QLayoutWidget">
<property name="name">
- <cstring>layout9</cstring>
+ <cstring>layout8</cstring>
</property>
<hbox>
<property name="name">
@@ -66,9 +66,28 @@
<bool>true</bool>
</property>
</column>
+ <column>
+ <property name="text">
+ <string>Source</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
<property name="name">
<cstring>channelsList</cstring>
</property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
@@ -123,38 +142,51 @@
<property name="title">
<string>Search On</string>
</property>
- <vbox>
+ <grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="QComboBox">
+ <widget class="QComboBox" row="0" column="0">
<property name="name">
<cstring>searchComb</cstring>
</property>
</widget>
- <widget class="QGroupBox">
+ <widget class="QGroupBox" row="1" column="0">
<property name="name">
<cstring>offsetGroup</cstring>
</property>
<property name="title">
<string>Offset (KHz)</string>
</property>
- <hbox>
+ <grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="QCheckBox">
+ <widget class="QCheckBox" row="1" column="3">
<property name="name">
- <cstring>offset0</cstring>
+ <cstring>offset167m</cstring>
</property>
<property name="text">
- <string>0</string>
+ <string>-167</string>
</property>
- <property name="checked">
- <bool>true</bool>
+ </widget>
+ <widget class="QLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>(7MHz)</string>
</property>
</widget>
- <widget class="QCheckBox">
+ <widget class="QLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>(8MHz)</string>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="1" column="2">
<property name="name">
<cstring>offset167p</cstring>
</property>
@@ -162,17 +194,39 @@
<string>+167</string>
</property>
</widget>
- <widget class="QCheckBox">
+ <widget class="QCheckBox" row="0" column="2" rowspan="1" colspan="2">
<property name="name">
- <cstring>offset167m</cstring>
+ <cstring>offset125p</cstring>
</property>
<property name="text">
- <string>-167</string>
+ <string>+125</string>
</property>
</widget>
- </hbox>
+ <widget class="QCheckBox" row="1" column="1">
+ <property name="name">
+ <cstring>offset0</cstring>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ <widget class="QCheckBox" row="0" column="1">
+ <property name="name">
+ <cstring>offset07</cstring>
+ </property>
+ <property name="text">
+ <string>0</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </grid>
</widget>
- </vbox>
+ </grid>
</widget>
<widget class="QPushButton">
<property name="name">
@@ -206,7 +260,7 @@
<property name="sizeHint">
<size>
<width>20</width>
- <height>20</height>
+ <height>18</height>
</size>
</property>
</spacer>
@@ -231,210 +285,190 @@
<property name="sizeHint">
<size>
<width>21</width>
- <height>20</height>
+ <height>19</height>
</size>
</property>
</spacer>
- <widget class="QLayoutWidget">
+ <widget class="QGroupBox">
<property name="name">
- <cstring>layout38</cstring>
+ <cstring>filtersGroup</cstring>
+ </property>
+ <property name="title">
+ <string>Filters</string>
</property>
- <vbox>
+ <grid>
<property name="name">
<cstring>unnamed</cstring>
</property>
- <widget class="QGroupBox">
+ <widget class="QCheckBox" row="2" column="0">
<property name="name">
- <cstring>filtersGroup</cstring>
+ <cstring>radioCb</cstring>
</property>
- <property name="title">
- <string>Filters</string>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>Radio</string>
</property>
- <grid>
- <property name="name">
- <cstring>unnamed</cstring>
- </property>
- <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
- <property name="name">
- <cstring>ftaCb</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>4</hsizetype>
- <vsizetype>0</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Free to air</string>
- </property>
- </widget>
- <widget class="QCheckBox" row="2" column="0" rowspan="1" colspan="2">
- <property name="name">
- <cstring>radioCb</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>4</hsizetype>
- <vsizetype>0</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Radio</string>
- </property>
- </widget>
- <widget class="QCheckBox" row="1" column="0" rowspan="1" colspan="2">
- <property name="name">
- <cstring>tvCb</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>4</hsizetype>
- <vsizetype>0</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>TV</string>
- </property>
- </widget>
- <widget class="QCheckBox" row="3" column="0">
- <property name="name">
- <cstring>providerCb</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>0</hsizetype>
- <vsizetype>0</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Provider:</string>
- </property>
- </widget>
- <widget class="QComboBox" row="3" column="1">
- <property name="name">
- <cstring>providerComb</cstring>
- </property>
- <property name="sizePolicy">
- <sizepolicy>
- <hsizetype>3</hsizetype>
- <vsizetype>0</vsizetype>
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </grid>
</widget>
- <widget class="QPushButton">
+ <widget class="QCheckBox" row="1" column="0">
<property name="name">
- <cstring>addselectedBtn</cstring>
+ <cstring>tvCb</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
- <hsizetype>1</hsizetype>
+ <hsizetype>4</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
- <string>&lt;&lt; Add Selected</string>
+ <string>TV</string>
</property>
</widget>
- <widget class="QPushButton">
+ <widget class="QCheckBox" row="3" column="0">
<property name="name">
- <cstring>addfilteredBtn</cstring>
+ <cstring>providerCb</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
- <hsizetype>1</hsizetype>
+ <hsizetype>0</hsizetype>
<vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
- <string>&lt;&lt; Add Filtered</string>
+ <string>Provider:</string>
</property>
</widget>
- </vbox>
- </widget>
- </vbox>
- </widget>
- <widget class="QGroupBox">
- <property name="name">
- <cstring>groupBox11</cstring>
- </property>
- <property name="title">
- <string>Found</string>
- </property>
- <vbox>
- <property name="name">
- <cstring>unnamed</cstring>
- </property>
- <widget class="QLayoutWidget">
- <property name="name">
- <cstring>layout8</cstring>
- </property>
- <vbox>
- <property name="name">
- <cstring>unnamed</cstring>
- </property>
- <widget class="QListView">
- <column>
- <property name="text">
- <string>SNR</string>
- </property>
- <property name="clickable">
- <bool>true</bool>
- </property>
- <property name="resizable">
- <bool>true</bool>
- </property>
- </column>
- <column>
- <property name="text">
- <string>Name</string>
- </property>
- <property name="clickable">
- <bool>true</bool>
- </property>
- <property name="resizable">
- <bool>true</bool>
- </property>
- </column>
+ <widget class="QComboBox" row="3" column="1">
<property name="name">
- <cstring>foundList</cstring>
+ <cstring>providerComb</cstring>
</property>
<property name="sizePolicy">
<sizepolicy>
- <hsizetype>7</hsizetype>
- <vsizetype>3</vsizetype>
+ <hsizetype>3</hsizetype>
+ <vsizetype>0</vsizetype>
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
- <widget class="QPushButton">
+ <widget class="QCheckBox" row="0" column="0" rowspan="1" colspan="2">
<property name="name">
- <cstring>selectallBtn</cstring>
+ <cstring>ftaCb</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>4</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
</property>
<property name="text">
- <string>Select All</string>
+ <string>Free to air</string>
</property>
</widget>
- </vbox>
+ </grid>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>addselectedBtn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;&lt; Add Selected</string>
+ </property>
+ </widget>
+ <widget class="QPushButton">
+ <property name="name">
+ <cstring>addfilteredBtn</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>1</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="text">
+ <string>&lt;&lt; Add Filtered</string>
+ </property>
</widget>
</vbox>
</widget>
+ <widget class="QGroupBox">
+ <property name="name">
+ <cstring>groupBox11</cstring>
+ </property>
+ <property name="title">
+ <string>Found</string>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="QListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>SNR</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <column>
+ <property name="text">
+ <string>Name</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>true</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>foundList</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ </widget>
+ <widget class="QPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>selectallBtn</cstring>
+ </property>
+ <property name="text">
+ <string>Select All</string>
+ </property>
+ </widget>
+ </grid>
+ </widget>
</hbox>
</widget>
<widget class="Line">
diff --git a/kaffeine/src/input/dvb/ts2rtp.cpp b/kaffeine/src/input/dvb/ts2rtp.cpp
index 9f87a84..4784122 100644
--- a/kaffeine/src/input/dvb/ts2rtp.cpp
+++ b/kaffeine/src/input/dvb/ts2rtp.cpp
@@ -345,7 +345,12 @@ void Ts2Rtp::psiTables( QPtrList<ChannelDesc> *channels )
buf[off++] = 0x01; // current_next_indicator
buf[off++] = 0x00; // section_number
buf[off++] = 0x00; // last_section_number
- buf[off++] = desc->vpid>>8; buf[off++] = desc->vpid&0xff; // PCR pid
+ if ( desc->vpid ) {
+ buf[off++] = desc->vpid>>8; buf[off++] = desc->vpid&0xff; // PCR pid
+ }
+ else if ( desc->napid ) {
+ buf[off++] = desc->apid[0].pid>>8; buf[off++] = desc->apid[0].pid&0xff; // PCR pid
+ }
buf[off++] = 0x00; buf[off++] = 0x00; // infos_length
if ( desc->vpid ) {
buf[off++] = desc->vType; // stream_type