]> git.sesse.net Git - vlc/blobdiff - modules/access/dvb/en50221.c
Update LGPL license blurb, choosing v2.1+.
[vlc] / modules / access / dvb / en50221.c
index e00db711a73fc5c090a6f39cb8bffdbff236e858..6a24fced5b9b69fced8cae8efe2bf34723c7e5df 100644 (file)
 #include <errno.h>
 
 #include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
 #include <time.h>
 #include <unistd.h>
-#include <sys/stat.h>
-#include <sys/poll.h>
+#include <poll.h>
 #include <netinet/in.h>
 
 /* DVB Card Drivers */
 #   include "descriptors/dr.h"
 #   include "psi.h"
 #   include "demux.h"
-#   include "sdt.h"
+#   include "tables/sdt.h"
 #endif
 
 #ifdef ENABLE_HTTPD
-#   include "vlc_httpd.h"
+#   include <vlc_httpd.h>
 #endif
 
 #include "dvb.h"
@@ -79,6 +76,7 @@
 #undef DEBUG_TPDU
 #define HLCI_WAIT_CAM_READY 0
 #define CAM_PROG_MAX MAX_PROGRAMS
+//#define CAPMT_WAIT 100             /* uncomment this for slow CAMs */
 
 static void ResourceManagerOpen( access_t * p_access, int i_session_id );
 static void ApplicationInformationOpen( access_t * p_access, int i_session_id );
@@ -151,7 +149,7 @@ static uint8_t *SetLength( uint8_t *p_data, int i_length )
  * Transport layer
  */
 
-#define MAX_TPDU_SIZE  2048
+#define MAX_TPDU_SIZE  4096
 #define MAX_TPDU_DATA  (MAX_TPDU_SIZE - 4)
 
 #define DATA_INDICATOR 0x80
@@ -271,7 +269,7 @@ static int TPDURecv( access_t * p_access, uint8_t i_slot, uint8_t *pi_tag,
 
     if ( pi_size == NULL )
     {
-        p_data = malloc( MAX_TPDU_SIZE );
+        p_data = xmalloc( MAX_TPDU_SIZE );
     }
 
     for ( ; ; )
@@ -285,6 +283,8 @@ static int TPDURecv( access_t * p_access, uint8_t i_slot, uint8_t *pi_tag,
     if ( i_size < 5 )
     {
         msg_Err( p_access, "cannot read from CAM device (%d:%m)", i_size );
+        if( pi_size == NULL )
+            free( p_data );
         return VLC_EGENERIC;
     }
 
@@ -292,6 +292,8 @@ static int TPDURecv( access_t * p_access, uint8_t i_slot, uint8_t *pi_tag,
     {
         msg_Err( p_access, "invalid read from CAM device (%d instead of %d)",
                  p_data[1], i_tcid );
+        if( pi_size == NULL )
+            free( p_data );
         return VLC_EGENERIC;
     }
 
@@ -348,7 +350,7 @@ static int SPDUSend( access_t * p_access, int i_session_id,
                      uint8_t *p_data, int i_size )
 {
     access_sys_t *p_sys = p_access->p_sys;
-    uint8_t *p_spdu = malloc( i_size + 4 );
+    uint8_t *p_spdu = xmalloc( i_size + 4 );
     uint8_t *p = p_spdu;
     uint8_t i_tag;
     uint8_t i_slot = p_sys->p_sessions[i_session_id - 1].i_slot;
@@ -411,6 +413,8 @@ static int SPDUSend( access_t * p_access, int i_session_id,
 static void SessionOpen( access_t * p_access, uint8_t i_slot,
                          uint8_t *p_spdu, int i_size )
 {
+    VLC_UNUSED( i_size );
+
     access_sys_t *p_sys = p_access->p_sys;
     int i_session_id;
     int i_resource_id = ResourceIdToInt( &p_spdu[2] );
@@ -423,7 +427,7 @@ static void SessionOpen( access_t * p_access, uint8_t i_slot,
         if ( !p_sys->p_sessions[i_session_id - 1].i_resource_id )
             break;
     }
-    if ( i_session_id == MAX_SESSIONS )
+    if ( i_session_id > MAX_SESSIONS )
     {
         msg_Err( p_access, "too many sessions !" );
         return;
@@ -545,6 +549,9 @@ static void SessionCreate( access_t * p_access, int i_slot, int i_resource_id )
 static void SessionCreateResponse( access_t * p_access, uint8_t i_slot,
                                    uint8_t *p_spdu, int i_size )
 {
+    VLC_UNUSED( i_size );
+    VLC_UNUSED( i_slot );
+
     access_sys_t *p_sys = p_access->p_sys;
     int i_status = p_spdu[2];
     int i_resource_id = ResourceIdToInt( &p_spdu[3] );
@@ -791,7 +798,7 @@ static int APDUSend( access_t * p_access, int i_session_id, int i_tag,
                      uint8_t *p_data, int i_size )
 {
     access_sys_t *p_sys = p_access->p_sys;
-    uint8_t *p_apdu = malloc( i_size + 12 );
+    uint8_t *p_apdu = xmalloc( i_size + 12 );
     uint8_t *p = p_apdu;
     ca_msg_t ca_msg;
     int i_ret;
@@ -815,10 +822,8 @@ static int APDUSend( access_t * p_access, int i_session_id, int i_tag,
         }
         else
         {
-            char *psz_hex;
             ca_msg.length = i_size + p - p_apdu;
             if ( i_size == 0 ) ca_msg.length=3;
-            psz_hex = (char*)malloc( ca_msg.length*3 + 1);
             memcpy( ca_msg.msg, p_apdu, i_size + p - p_apdu );
             i_ret = ioctl(p_sys->i_ca_handle, CA_SEND_MSG, &ca_msg );
             if ( i_ret < 0 )
@@ -906,6 +911,7 @@ static void ApplicationInformationEnterMenu( access_t * p_access,
 static void ApplicationInformationHandle( access_t * p_access, int i_session_id,
                                           uint8_t *p_apdu, int i_size )
 {
+    VLC_UNUSED(i_session_id);
     int i_tag = APDUGetTag( p_apdu, i_size );
 
     switch ( i_tag )
@@ -955,7 +961,7 @@ static void ApplicationInformationOpen( access_t * p_access, int i_session_id )
  * Conditional Access
  */
 
-#define MAX_CASYSTEM_IDS 16
+#define MAX_CASYSTEM_IDS 64
 
 typedef struct
 {
@@ -965,7 +971,7 @@ typedef struct
 static bool CheckSystemID( system_ids_t *p_ids, uint16_t i_id )
 {
     int i = 0;
-    if( !p_ids ) return true;
+    if( !p_ids ) return true;      /* dummy session for high-level CI intf */
 
     while ( p_ids->pi_system_ids[i] )
     {
@@ -1038,9 +1044,9 @@ static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt,
     uint8_t *p_data;
 
     if ( i_size )
-        p_data = malloc( 7 + i_size );
+        p_data = xmalloc( 7 + i_size );
     else
-        p_data = malloc( 6 );
+        p_data = xmalloc( 6 );
 
     p_data[0] = i_list_mgt;
     p_data[1] = i_program_number >> 8;
@@ -1092,9 +1098,9 @@ static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt,
     int i;
  
     if ( i_size )
-        p_data = realloc( p_capmt, i_capmt_size + 6 + i_size );
+        p_data = xrealloc( p_capmt, i_capmt_size + 6 + i_size );
     else
-        p_data = realloc( p_capmt, i_capmt_size + 5 );
+        p_data = xrealloc( p_capmt, i_capmt_size + 5 );
 
     i = i_capmt_size;
 
@@ -1206,8 +1212,11 @@ static void CAPMTFirst( access_t * p_access, int i_session_id,
                           0x3 /* only */, 0x1 /* ok_descrambling */,
                           &i_capmt_size );
 
-    if ( i_capmt_size )
+    if( i_capmt_size )
+    {
         APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
+        free( p_capmt );
+    }
 }
 
 /*****************************************************************************
@@ -1232,6 +1241,9 @@ static void CAPMTAdd( access_t * p_access, int i_session_id,
         return;
     }
  
+#ifdef CAPMT_WAIT
+    msleep( CAPMT_WAIT * 1000 );
+#endif
  
     msg_Dbg( p_access, "adding CAPMT for SID %d on session %d",
              p_pmt->i_program_number, i_session_id );
@@ -1240,8 +1252,11 @@ static void CAPMTAdd( access_t * p_access, int i_session_id,
                           0x4 /* add */, 0x1 /* ok_descrambling */,
                           &i_capmt_size );
 
-    if ( i_capmt_size )
+    if( i_capmt_size )
+    {
         APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
+        free( p_capmt );
+    }
 }
 
 /*****************************************************************************
@@ -1260,8 +1275,11 @@ static void CAPMTUpdate( access_t * p_access, int i_session_id,
                           0x5 /* update */, 0x1 /* ok_descrambling */,
                           &i_capmt_size );
 
-    if ( i_capmt_size )
+    if( i_capmt_size )
+    {
         APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
+        free( p_capmt );
+    }
 }
 
 /*****************************************************************************
@@ -1281,8 +1299,11 @@ static void CAPMTDelete( access_t * p_access, int i_session_id,
                           0x5 /* update */, 0x4 /* not selected */,
                           &i_capmt_size );
 
-    if ( i_capmt_size )
+    if( i_capmt_size )
+    {
         APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
+        free( p_capmt );
+    }
 }
 
 /*****************************************************************************
@@ -1354,9 +1375,7 @@ static void ConditionalAccessOpen( access_t * p_access, int i_session_id )
 
     p_sys->p_sessions[i_session_id - 1].pf_handle = ConditionalAccessHandle;
     p_sys->p_sessions[i_session_id - 1].pf_close = ConditionalAccessClose;
-    p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(system_ids_t));
-    memset( p_sys->p_sessions[i_session_id - 1].p_sys, 0,
-            sizeof(system_ids_t) );
+    p_sys->p_sessions[i_session_id - 1].p_sys = calloc( 1, sizeof(system_ids_t) );
 
     APDUSend( p_access, i_session_id, AOT_CA_INFO_ENQ, NULL, 0 );
 }
@@ -1486,8 +1505,7 @@ static void DateTimeOpen( access_t * p_access, int i_session_id )
     p_sys->p_sessions[i_session_id - 1].pf_handle = DateTimeHandle;
     p_sys->p_sessions[i_session_id - 1].pf_manage = DateTimeManage;
     p_sys->p_sessions[i_session_id - 1].pf_close = DateTimeClose;
-    p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(date_time_t));
-    memset( p_sys->p_sessions[i_session_id - 1].p_sys, 0, sizeof(date_time_t) );
+    p_sys->p_sessions[i_session_id - 1].p_sys = calloc( 1, sizeof(date_time_t) );
 
     DateTimeSend( p_access, i_session_id );
 }
@@ -1551,7 +1569,7 @@ static void MMISendObject( access_t *p_access, int i_session_id,
     case EN50221_MMI_ANSW:
         i_tag = AOT_ANSW;
         i_size = 1 + strlen( p_object->u.answ.psz_answ );
-        p_data = malloc( i_size );
+        p_data = xmalloc( i_size );
         p_data[0] = (p_object->u.answ.b_ok == true) ? 0x1 : 0x0;
         strncpy( (char *)&p_data[1], p_object->u.answ.psz_answ, i_size - 1 );
         break;
@@ -1559,7 +1577,7 @@ static void MMISendObject( access_t *p_access, int i_session_id,
     case EN50221_MMI_MENU_ANSW:
         i_tag = AOT_MENU_ANSW;
         i_size = 1;
-        p_data = malloc( i_size );
+        p_data = xmalloc( i_size );
         p_data[0] = p_object->u.menu_answ.i_choice;
         break;
 
@@ -1632,6 +1650,8 @@ static char *MMIGetText( access_t *p_access, uint8_t **pp_apdu, int *pi_size )
 static void MMIHandleEnq( access_t *p_access, int i_session_id,
                           uint8_t *p_apdu, int i_size )
 {
+    VLC_UNUSED( i_size );
+
     access_sys_t *p_sys = p_access->p_sys;
     mmi_t *p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys;
     int i_slot = p_sys->p_sessions[i_session_id - 1].i_slot;
@@ -1643,7 +1663,7 @@ static void MMIHandleEnq( access_t *p_access, int i_session_id,
     p_mmi->last_object.u.enq.b_blind = (*d & 0x1) ? true : false;
     d += 2; /* skip answer_text_length because it is not mandatory */
     l -= 2;
-    p_mmi->last_object.u.enq.psz_text = malloc( l + 1 );
+    p_mmi->last_object.u.enq.psz_text = xmalloc( l + 1 );
     strncpy( p_mmi->last_object.u.enq.psz_text, (char *)d, l );
     p_mmi->last_object.u.enq.psz_text[l] = '\0';
 
@@ -1659,6 +1679,7 @@ static void MMIHandleEnq( access_t *p_access, int i_session_id,
 static void MMIHandleMenu( access_t *p_access, int i_session_id, int i_tag,
                            uint8_t *p_apdu, int i_size )
 {
+    VLC_UNUSED(i_size);
     access_sys_t *p_sys = p_access->p_sys;
     mmi_t *p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys;
     int i_slot = p_sys->p_sessions[i_session_id - 1].i_slot;
@@ -1784,7 +1805,7 @@ static void MMIOpen( access_t *p_access, int i_session_id )
 
     p_sys->p_sessions[i_session_id - 1].pf_handle = MMIHandle;
     p_sys->p_sessions[i_session_id - 1].pf_close = MMIClose;
-    p_sys->p_sessions[i_session_id - 1].p_sys = malloc(sizeof(mmi_t));
+    p_sys->p_sessions[i_session_id - 1].p_sys = xmalloc(sizeof(mmi_t));
     p_mmi = (mmi_t *)p_sys->p_sessions[i_session_id - 1].p_sys;
     p_mmi->last_object.i_object_type = EN50221_MMI_NONE;
 }
@@ -2323,7 +2344,7 @@ static inline void *FixUTF8( char *p )
     return p;
 }
 
-char *dvbsi_to_utf8( char *psz_instring, size_t i_length )
+char *dvbsi_to_utf8( const char *psz_instring, size_t i_length )
 {
     const char *psz_encoding, *psz_stringstart;
     char *psz_outstring, *psz_tmp;
@@ -2415,7 +2436,7 @@ char *dvbsi_to_utf8( char *psz_instring, size_t i_length )
     iconv_handle = vlc_iconv_open( "UTF-8", psz_encoding );
     i_in = i_length - (psz_stringstart - psz_instring );
     i_out = i_in * 6;
-    psz_outstring = psz_tmp = (char*)malloc( i_out * sizeof(char) + 1 );
+    psz_outstring = psz_tmp = (char*)xmalloc( i_out + 1 );
     vlc_iconv( iconv_handle, &psz_stringstart, &i_in, &psz_tmp, &i_out );
     vlc_iconv_close( iconv_handle );
     *psz_tmp = '\0';