Commit e34c291f authored by Christophe Massiot's avatar Christophe Massiot

* modules/access/dvb: Fixed numerous bugs related to the CAM configuration.

  Reconfigure the frontend if no lock is acquired in 10s.
parent edbd1a8d
...@@ -370,6 +370,12 @@ static block_t *Block( access_t *p_access ) ...@@ -370,6 +370,12 @@ static block_t *Block( access_t *p_access )
E_(FrontendPoll)( p_access ); E_(FrontendPoll)( p_access );
} }
if ( p_sys->i_frontend_timeout && mdate() > p_sys->i_frontend_timeout )
{
msg_Warn( p_access, "no lock, tuning again" );
E_(FrontendSet)( p_access );
}
if ( FD_ISSET( p_sys->i_handle, &fds ) ) if ( FD_ISSET( p_sys->i_handle, &fds ) )
{ {
break; break;
......
...@@ -72,7 +72,7 @@ struct access_sys_t ...@@ -72,7 +72,7 @@ struct access_sys_t
vlc_bool_t pb_active_slot[MAX_CI_SLOTS]; vlc_bool_t pb_active_slot[MAX_CI_SLOTS];
vlc_bool_t pb_tc_has_data[MAX_CI_SLOTS]; vlc_bool_t pb_tc_has_data[MAX_CI_SLOTS];
en50221_session_t p_sessions[MAX_SESSIONS]; en50221_session_t p_sessions[MAX_SESSIONS];
mtime_t i_ca_timeout, i_ca_next_event; mtime_t i_ca_timeout, i_ca_next_event, i_frontend_timeout;
dvbpsi_pmt_t *pp_selected_programs[MAX_PROGRAMS]; dvbpsi_pmt_t *pp_selected_programs[MAX_PROGRAMS];
}; };
......
...@@ -823,7 +823,8 @@ static int GetCADSize( system_ids_t *p_ids, dvbpsi_descriptor_t *p_dr ) ...@@ -823,7 +823,8 @@ static int GetCADSize( system_ids_t *p_ids, dvbpsi_descriptor_t *p_dr )
static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt, static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt,
uint16_t i_program_number, uint8_t i_version, uint16_t i_program_number, uint8_t i_version,
int i_size, dvbpsi_descriptor_t *p_dr ) int i_size, dvbpsi_descriptor_t *p_dr,
uint8_t i_cmd )
{ {
uint8_t *p_data; uint8_t *p_data;
...@@ -843,7 +844,7 @@ static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt, ...@@ -843,7 +844,7 @@ static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt,
p_data[4] = (i_size + 1) >> 8; p_data[4] = (i_size + 1) >> 8;
p_data[5] = (i_size + 1) & 0xff; p_data[5] = (i_size + 1) & 0xff;
p_data[6] = 0x1; /* ok_descrambling */ p_data[6] = i_cmd;
i = 7; i = 7;
while ( p_dr != NULL ) while ( p_dr != NULL )
...@@ -874,7 +875,8 @@ static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt, ...@@ -874,7 +875,8 @@ static uint8_t *CAPMTHeader( system_ids_t *p_ids, uint8_t i_list_mgt,
static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt, static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt,
int i_capmt_size, uint8_t i_type, uint16_t i_pid, int i_capmt_size, uint8_t i_type, uint16_t i_pid,
int i_size, dvbpsi_descriptor_t *p_dr ) int i_size, dvbpsi_descriptor_t *p_dr,
uint8_t i_cmd )
{ {
uint8_t *p_data; uint8_t *p_data;
int i; int i;
...@@ -894,7 +896,7 @@ static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt, ...@@ -894,7 +896,7 @@ static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt,
{ {
p_data[i + 3] = (i_size + 1) >> 8; p_data[i + 3] = (i_size + 1) >> 8;
p_data[i + 4] = (i_size + 1) & 0xff; p_data[i + 4] = (i_size + 1) & 0xff;
p_data[i + 5] = 0x1; /* ok_descrambling */ p_data[i + 5] = i_cmd;
i += 6; i += 6;
while ( p_dr != NULL ) while ( p_dr != NULL )
...@@ -925,7 +927,7 @@ static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt, ...@@ -925,7 +927,7 @@ static uint8_t *CAPMTES( system_ids_t *p_ids, uint8_t *p_capmt,
static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id, static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id,
dvbpsi_pmt_t *p_pmt, uint8_t i_list_mgt, dvbpsi_pmt_t *p_pmt, uint8_t i_list_mgt,
int *pi_capmt_size ) uint8_t i_cmd, int *pi_capmt_size )
{ {
access_sys_t *p_sys = p_access->p_sys; access_sys_t *p_sys = p_access->p_sys;
system_ids_t *p_ids = system_ids_t *p_ids =
...@@ -946,11 +948,13 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id, ...@@ -946,11 +948,13 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id,
msg_Warn( p_access, msg_Warn( p_access,
"no compatible scrambling system for SID %d on session %d", "no compatible scrambling system for SID %d on session %d",
p_pmt->i_program_number, i_session_id ); p_pmt->i_program_number, i_session_id );
*pi_capmt_size = 0;
return NULL;
} }
p_capmt = CAPMTHeader( p_ids, i_list_mgt, p_pmt->i_program_number, p_capmt = CAPMTHeader( p_ids, i_list_mgt, p_pmt->i_program_number,
p_pmt->i_version, i_cad_program_size, p_pmt->i_version, i_cad_program_size,
p_pmt->p_first_descriptor ); p_pmt->p_first_descriptor, i_cmd );
if ( i_cad_program_size ) if ( i_cad_program_size )
*pi_capmt_size = 7 + i_cad_program_size; *pi_capmt_size = 7 + i_cad_program_size;
...@@ -965,7 +969,7 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id, ...@@ -965,7 +969,7 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id,
{ {
p_capmt = CAPMTES( p_ids, p_capmt, *pi_capmt_size, p_es->i_type, p_capmt = CAPMTES( p_ids, p_capmt, *pi_capmt_size, p_es->i_type,
p_es->i_pid, i_cad_size, p_es->i_pid, i_cad_size,
p_es->p_first_descriptor ); p_es->p_first_descriptor, i_cmd );
if ( i_cad_size ) if ( i_cad_size )
*pi_capmt_size += 6 + i_cad_size; *pi_capmt_size += 6 + i_cad_size;
else else
...@@ -976,6 +980,26 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id, ...@@ -976,6 +980,26 @@ static uint8_t *CAPMTBuild( access_t * p_access, int i_session_id,
return p_capmt; return p_capmt;
} }
/*****************************************************************************
* CAPMTFirst
*****************************************************************************/
static void CAPMTFirst( access_t * p_access, int i_session_id,
dvbpsi_pmt_t *p_pmt )
{
uint8_t *p_capmt;
int i_capmt_size;
msg_Dbg( p_access, "adding first CAPMT for SID %d on session %d",
p_pmt->i_program_number, i_session_id );
p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt,
0x3 /* only */, 0x1 /* ok_descrambling */,
&i_capmt_size );
if ( i_capmt_size )
APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
}
/***************************************************************************** /*****************************************************************************
* CAPMTAdd * CAPMTAdd
*****************************************************************************/ *****************************************************************************/
...@@ -989,8 +1013,10 @@ static void CAPMTAdd( access_t * p_access, int i_session_id, ...@@ -989,8 +1013,10 @@ static void CAPMTAdd( access_t * p_access, int i_session_id,
p_pmt->i_program_number, i_session_id ); p_pmt->i_program_number, i_session_id );
p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt, p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt,
0x4 /* add */, &i_capmt_size ); 0x4 /* add */, 0x1 /* ok_descrambling */,
&i_capmt_size );
if ( i_capmt_size )
APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size ); APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
} }
...@@ -1007,8 +1033,30 @@ static void CAPMTUpdate( access_t * p_access, int i_session_id, ...@@ -1007,8 +1033,30 @@ static void CAPMTUpdate( access_t * p_access, int i_session_id,
p_pmt->i_program_number, i_session_id ); p_pmt->i_program_number, i_session_id );
p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt, p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt,
0x5 /* update */, &i_capmt_size ); 0x5 /* update */, 0x1 /* ok_descrambling */,
&i_capmt_size );
if ( i_capmt_size )
APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
}
/*****************************************************************************
* CAPMTDelete
*****************************************************************************/
static void CAPMTDelete( access_t * p_access, int i_session_id,
dvbpsi_pmt_t *p_pmt )
{
uint8_t *p_capmt;
int i_capmt_size;
msg_Dbg( p_access, "deleting CAPMT for SID %d on session %d",
p_pmt->i_program_number, i_session_id );
p_capmt = CAPMTBuild( p_access, i_session_id, p_pmt,
0x5 /* update */, 0x4 /* not selected */,
&i_capmt_size );
if ( i_capmt_size )
APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size ); APDUSend( p_access, i_session_id, AOT_CA_PMT, p_capmt, i_capmt_size );
} }
...@@ -1027,6 +1075,7 @@ static void ConditionalAccessHandle( access_t * p_access, int i_session_id, ...@@ -1027,6 +1075,7 @@ static void ConditionalAccessHandle( access_t * p_access, int i_session_id,
{ {
case AOT_CA_INFO: case AOT_CA_INFO:
{ {
vlc_bool_t b_inited = VLC_FALSE;
int i; int i;
int l = 0; int l = 0;
uint8_t *d = APDUGetLength( p_apdu, &l ); uint8_t *d = APDUGetLength( p_apdu, &l );
...@@ -1044,8 +1093,13 @@ static void ConditionalAccessHandle( access_t * p_access, int i_session_id, ...@@ -1044,8 +1093,13 @@ static void ConditionalAccessHandle( access_t * p_access, int i_session_id,
{ {
if ( p_sys->pp_selected_programs[i] != NULL ) if ( p_sys->pp_selected_programs[i] != NULL )
{ {
if ( b_inited )
CAPMTAdd( p_access, i_session_id, CAPMTAdd( p_access, i_session_id,
p_sys->pp_selected_programs[i] ); p_sys->pp_selected_programs[i] );
else
CAPMTFirst( p_access, i_session_id,
p_sys->pp_selected_programs[i] );
b_inited = VLC_TRUE;
} }
} }
break; break;
...@@ -1408,11 +1462,19 @@ int E_(en50221_SetCAPMT)( access_t * p_access, dvbpsi_pmt_t *p_pmt ) ...@@ -1408,11 +1462,19 @@ int E_(en50221_SetCAPMT)( access_t * p_access, dvbpsi_pmt_t *p_pmt )
== p_pmt->i_program_number ) == p_pmt->i_program_number )
{ {
b_update = VLC_TRUE; b_update = VLC_TRUE;
if ( !b_needs_descrambling )
{
dvbpsi_DeletePMT( p_pmt );
p_pmt = p_sys->pp_selected_programs[i];
p_sys->pp_selected_programs[i] = NULL;
}
else
{
dvbpsi_DeletePMT( p_sys->pp_selected_programs[i] ); dvbpsi_DeletePMT( p_sys->pp_selected_programs[i] );
if ( b_needs_descrambling )
p_sys->pp_selected_programs[i] = p_pmt; p_sys->pp_selected_programs[i] = p_pmt;
else }
p_sys->pp_selected_programs[i] = NULL;
break; break;
} }
} }
...@@ -1429,17 +1491,27 @@ int E_(en50221_SetCAPMT)( access_t * p_access, dvbpsi_pmt_t *p_pmt ) ...@@ -1429,17 +1491,27 @@ int E_(en50221_SetCAPMT)( access_t * p_access, dvbpsi_pmt_t *p_pmt )
} }
} }
if ( b_update || b_needs_descrambling )
{
for ( i_session_id = 1; i_session_id <= MAX_SESSIONS; i_session_id++ ) for ( i_session_id = 1; i_session_id <= MAX_SESSIONS; i_session_id++ )
{ {
if ( p_sys->p_sessions[i_session_id - 1].i_resource_id if ( p_sys->p_sessions[i_session_id - 1].i_resource_id
== RI_CONDITIONAL_ACCESS_SUPPORT ) == RI_CONDITIONAL_ACCESS_SUPPORT )
{ {
if ( b_update ) if ( b_update && b_needs_descrambling )
CAPMTUpdate( p_access, i_session_id, p_pmt ); CAPMTUpdate( p_access, i_session_id, p_pmt );
else if ( b_update )
CAPMTDelete( p_access, i_session_id, p_pmt );
else else
CAPMTAdd( p_access, i_session_id, p_pmt ); CAPMTAdd( p_access, i_session_id, p_pmt );
} }
} }
}
if ( !b_needs_descrambling )
{
dvbpsi_DeletePMT( p_pmt );
}
return VLC_SUCCESS; return VLC_SUCCESS;
} }
......
...@@ -72,6 +72,8 @@ struct frontend_t ...@@ -72,6 +72,8 @@ struct frontend_t
struct dvb_frontend_info info; struct dvb_frontend_info info;
}; };
#define FRONTEND_LOCK_TIMEOUT 10000000 /* 10 s */
/* Local prototypes */ /* Local prototypes */
static int FrontendInfo( access_t * ); static int FrontendInfo( access_t * );
static int FrontendSetQPSK( access_t * ); static int FrontendSetQPSK( access_t * );
...@@ -245,6 +247,7 @@ int E_(FrontendSet)( access_t *p_access ) ...@@ -245,6 +247,7 @@ int E_(FrontendSet)( access_t *p_access )
return VLC_EGENERIC; return VLC_EGENERIC;
} }
p_sys->p_frontend->i_last_status = 0; p_sys->p_frontend->i_last_status = 0;
p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -302,6 +305,7 @@ void E_(FrontendPoll)( access_t *p_access ) ...@@ -302,6 +305,7 @@ void E_(FrontendPoll)( access_t *p_access )
{ {
int32_t i_value; int32_t i_value;
msg_Dbg( p_access, "frontend has acquired lock" ); msg_Dbg( p_access, "frontend has acquired lock" );
p_sys->i_frontend_timeout = 0;
/* Read some statistics */ /* Read some statistics */
if( ioctl( p_sys->i_frontend_handle, FE_READ_BER, &i_value ) >= 0 ) if( ioctl( p_sys->i_frontend_handle, FE_READ_BER, &i_value ) >= 0 )
...@@ -314,6 +318,7 @@ void E_(FrontendPoll)( access_t *p_access ) ...@@ -314,6 +318,7 @@ void E_(FrontendPoll)( access_t *p_access )
else else
{ {
msg_Dbg( p_access, "frontend has lost lock" ); msg_Dbg( p_access, "frontend has lost lock" );
p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
} }
IF_UP( FE_REINIT ) IF_UP( FE_REINIT )
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment