#include "dvb.h"
#undef DEBUG_TPDU
+#define HLCI_WAIT_CAM_READY 0
+#define CAM_PROG_MAX MAX_PROGRAMS
static void ResourceManagerOpen( access_t * p_access, int i_session_id );
static void ApplicationInformationOpen( access_t * p_access, int i_session_id );
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 = p_apdu;
+ ca_msg_t ca_msg;
int i_ret;
*p++ = (i_tag >> 16);
p = SetLength( p, i_size );
if ( i_size )
memcpy( p, p_data, i_size );
-
- i_ret = SPDUSend( p_access, i_session_id, p_apdu, i_size + p - p_apdu );
+ if( p_sys->i_ca_type == CA_CI_LINK )
+ {
+ i_ret = SPDUSend( p_access, i_session_id, p_apdu, i_size + p - p_apdu );
+ }
+ else
+ {
+ if( i_size + p - p_apdu >256 )
+ {
+ msg_Err( p_access, "CAM: apdu overflow" );
+ i_ret = VLC_EGENERIC;
+ }
+ 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 )
+ {
+ msg_Err( p_access, "Error sending to CAM: %s", strerror(errno) );
+ i_ret = VLC_EGENERIC;
+ }
+ }
+ }
free( p_apdu );
return i_ret;
}
static vlc_bool_t CheckSystemID( system_ids_t *p_ids, uint16_t i_id )
{
int i = 0;
+ if( !p_ids ) return VLC_TRUE;
+
while ( p_ids->pi_system_ids[i] )
{
if ( p_ids->pi_system_ids[i] == i_id )
p_data[i] = 0x9;
p_data[i + 1] = p_dr->i_length;
memcpy( &p_data[i + 2], p_dr->p_data, p_dr->i_length );
+// p_data[i+4] &= 0x1f;
i += p_dr->i_length + 2;
}
}
uint8_t *p_capmt;
int i_capmt_size;
+ if( p_access->p_sys->i_selected_programs >= CAM_PROG_MAX )
+ {
+ msg_Warn( p_access, "Not adding CAPMT for SID %d, too many programs",
+ p_pmt->i_program_number );
+ return;
+ }
+ p_access->p_sys->i_selected_programs++;
+ if( p_access->p_sys->i_selected_programs == 1 )
+ {
+ CAPMTFirst( p_access, i_session_id, p_pmt );
+ return;
+ }
+
+
msg_Dbg( p_access, "adding CAPMT for SID %d on session %d",
p_pmt->i_program_number, i_session_id );
uint8_t *p_capmt;
int i_capmt_size;
+ p_access->p_sys->i_selected_programs++;
msg_Dbg( p_access, "deleting CAPMT for SID %d on session %d",
p_pmt->i_program_number, i_session_id );
{
case AOT_CA_INFO:
{
- vlc_bool_t b_inited = VLC_FALSE;
int i;
int l = 0;
uint8_t *d = APDUGetLength( p_apdu, &l );
{
if ( p_sys->pp_selected_programs[i] != NULL )
{
- if ( b_inited )
- CAPMTAdd( p_access, i_session_id,
- p_sys->pp_selected_programs[i] );
- else
- CAPMTFirst( p_access, i_session_id,
- p_sys->pp_selected_programs[i] );
- b_inited = VLC_TRUE;
+ CAPMTAdd( p_access, i_session_id,
+ p_sys->pp_selected_programs[i] );
}
}
break;
/*
* External entry points
*/
+/*****************************************************************************
+ * en50221_Init : Initialize the CAM for en50221
+ *****************************************************************************/
+int E_(en50221_Init)( access_t * p_access )
+{
+ access_sys_t *p_sys = p_access->p_sys;
+
+
+ if( p_sys->i_ca_type != CA_CI ) /* Link level init is done in Poll() */
+ {
+ return VLC_SUCCESS;
+ }
+ else
+ {
+ /* Allocate a dummy sessions */
+ p_sys->p_sessions[ 0 ].i_resource_id = RI_CONDITIONAL_ACCESS_SUPPORT;
+
+ /* Get application info to find out which cam we are using and make
+ sure everything is ready to play */
+ ca_msg_t ca_msg;
+ ca_msg.length=3;
+ ca_msg.msg[0] = ( AOT_APPLICATION_INFO & 0xFF0000 ) >> 16;
+ ca_msg.msg[1] = ( AOT_APPLICATION_INFO & 0x00FF00 ) >> 8;
+ ca_msg.msg[2] = ( AOT_APPLICATION_INFO & 0x0000FF ) >> 0;
+ memset( &ca_msg.msg[3], 0, 253 );
+ APDUSend( p_access, 1, AOT_APPLICATION_INFO_ENQ, NULL, 0 );
+ if ( ioctl( p_sys->i_ca_handle, CA_GET_MSG, &ca_msg ) < 0 )
+ {
+ msg_Err( p_access, "CAM: failed getting message" );
+ return VLC_EGENERIC;
+ }
+#if HLCI_WAIT_CAM_READY
+ while( ca_msg.msg[8] == 0xff && ca_msg.msg[9] == 0xff )
+ {
+ if( p_access->b_die ) return VLC_EGENERIC;
+ msleep(1);
+ msg_Dbg( p_access, "CAM: please wait" );
+ APDUSend( p_access, 1, AOT_APPLICATION_INFO_ENQ, NULL, 0 );
+ ca_msg.length=3;
+ ca_msg.msg[0] = ( AOT_APPLICATION_INFO & 0xFF0000 ) >> 16;
+ ca_msg.msg[1] = ( AOT_APPLICATION_INFO & 0x00FF00 ) >> 8;
+ ca_msg.msg[2] = ( AOT_APPLICATION_INFO & 0x0000FF ) >> 0;
+ memset( &ca_msg.msg[3], 0, 253 );
+ if ( ioctl( p_sys->i_ca_handle, CA_GET_MSG, &ca_msg ) < 0 )
+ {
+ msg_Err( p_access, "CAM: failed getting message" );
+ return VLC_EGENERIC;
+ }
+ msg_Dbg( p_access, "CAM: Got length: %d, tag: 0x%x", ca_msg.length, APDUGetTag( ca_msg.msg, ca_msg.length ) );
+ }
+#else
+ if( ca_msg.msg[8] == 0xff && ca_msg.msg[9] == 0xff )
+ {
+ msg_Err( p_access, "CAM returns garbage as application info!" );
+ return VLC_EGENERIC;
+ }
+#endif
+ msg_Dbg( p_access, "found CAM %s using id 0x%x", &ca_msg.msg[12],
+ (ca_msg.msg[8]<<8)|ca_msg.msg[9] );
+ return VLC_SUCCESS;
+
+ }
+}
/*****************************************************************************
* en50221_Poll : Poll the CAM for TPDUs
p_pmt = p_sys->pp_selected_programs[i];
p_sys->pp_selected_programs[i] = NULL;
}
- else
+ else if( p_pmt != p_sys->pp_selected_programs[i] )
{
dvbpsi_DeletePMT( p_sys->pp_selected_programs[i] );
p_sys->pp_selected_programs[i] = p_pmt;
#define FRONTEND_LOCK_TIMEOUT 10000000 /* 10 s */
+#define RESET_CAM_SLOTS 1 /* Do we want to reset cam upon opening */
+
/* Local prototypes */
static int FrontendInfo( access_t * );
static int FrontendSetQPSK( access_t * );
char ca[128];
int i_adapter, i_device, i_slot;
ca_caps_t caps;
+ struct ca_slot_info info;
i_adapter = var_GetInteger( p_access, "dvb-adapter" );
i_device = var_GetInteger( p_access, "dvb-device" );
msg_Err( p_access, "snprintf() truncated string for CA" );
ca[sizeof(ca) - 1] = '\0';
}
+ memset( &caps, 0, sizeof( ca_caps_t ));
msg_Dbg( p_access, "Opening device %s", ca );
if( (p_sys->i_ca_handle = open(ca, O_RDWR | O_NONBLOCK)) < 0 )
return VLC_EGENERIC;
}
- if ( !(caps.slot_type & CA_CI_LINK) )
+ p_sys->i_ca_type = caps.slot_type;
+ if( caps.slot_type != CA_CI_LINK &&
+ caps.slot_type != CA_CI )
{
- msg_Err( p_access, "CAMInit: no compatible CAM module" );
+ msg_Err( p_access, "CAMInit: incompatible CAM module" );
close( p_sys->i_ca_handle );
p_sys->i_ca_handle = 0;
return VLC_EGENERIC;
}
-
+ if( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &info ) < 0 )
+ {
+ msg_Err( p_access, "CAMInit: Couldn't get slot info" );
+ close( p_sys->i_ca_handle );
+ p_sys->i_ca_handle = 0;
+ return VLC_EGENERIC;
+ }
+ if( info.flags == 0 )
+ {
+ msg_Err( p_access, "CAMInit: No CAM inserted" );
+ close( p_sys->i_ca_handle );
+ p_sys->i_ca_handle = 0;
+ return VLC_EGENERIC;
+ }
+
p_sys->i_nb_slots = caps.slot_num;
memset( p_sys->pb_active_slot, 0, sizeof(vlc_bool_t) * MAX_CI_SLOTS );
-
+#if(RESET_CAM_SLOTS)
for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
{
if ( ioctl( p_sys->i_ca_handle, CA_RESET, 1 << i_slot) != 0 )
msg_Err( p_access, "CAMInit: couldn't reset slot %d", i_slot );
}
}
+#endif
p_sys->i_ca_timeout = 100000;
/* Wait a bit otherwise it doesn't initialize properly... */
msleep( 1000000 );
- return VLC_SUCCESS;
+ return E_(en50221_Init)( p_access );
}
/*****************************************************************************
int E_(CAMPoll)( access_t * p_access )
{
access_sys_t *p_sys = p_access->p_sys;
+ int i_ret = VLC_EGENERIC;
if ( p_sys->i_ca_handle == 0 )
{
return VLC_EGENERIC;
}
- return E_(en50221_Poll)( p_access );
+ switch( p_sys->i_ca_type )
+ {
+ case CA_CI_LINK:
+ i_ret = E_(en50221_Poll)( p_access );
+ break;
+ case CA_CI:
+ i_ret = VLC_SUCCESS;
+ break;
+ default:
+ msg_Err( p_access, "CAMPoll: This should not happen" );
+ break;
+ }
+
+ return i_ret;
}
/*****************************************************************************