Commit 3c83efbe authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

DVB: separate CA management

parent cc4cb782
SOURCES_dvb = \ SOURCES_dvb = \
access.c \ access.c \
scan.c \ scan.c scan.h \
scan.h \
linux_dvb.c \ linux_dvb.c \
en50221.c \ en50221.c en50221.h \
http.c \ http.c \
dvb.h \ dvb.h \
$(NULL) $(NULL)
...@@ -473,11 +473,7 @@ static block_t *Block( access_t *p_access ) ...@@ -473,11 +473,7 @@ static block_t *Block( access_t *p_access )
return NULL; return NULL;
} }
if ( p_sys->i_ca_handle && mdate() > p_sys->i_ca_next_event ) CAMPoll( p_access );
{
CAMPoll( p_access );
p_sys->i_ca_next_event = mdate() + p_sys->i_ca_timeout;
}
if ( ufds[1].revents ) if ( ufds[1].revents )
{ {
......
...@@ -51,113 +51,19 @@ typedef struct ...@@ -51,113 +51,19 @@ typedef struct
typedef struct scan_parameter_t scan_parameter_t; typedef struct scan_parameter_t scan_parameter_t;
typedef struct scan_t scan_t; typedef struct scan_t scan_t;
typedef struct en50221_session_t
{
int i_slot;
int i_resource_id;
void (* pf_handle)( access_t *, int, uint8_t *, int );
void (* pf_close)( access_t *, int );
void (* pf_manage)( access_t *, int );
void *p_sys;
} en50221_session_t;
#define EN50221_MMI_NONE 0
#define EN50221_MMI_ENQ 1
#define EN50221_MMI_ANSW 2
#define EN50221_MMI_MENU 3
#define EN50221_MMI_MENU_ANSW 4
#define EN50221_MMI_LIST 5
typedef struct en50221_mmi_object_t
{
int i_object_type;
union
{
struct
{
bool b_blind;
char *psz_text;
} enq;
struct
{
bool b_ok;
char *psz_answ;
} answ;
struct
{
char *psz_title, *psz_subtitle, *psz_bottom;
char **ppsz_choices;
int i_choices;
} menu; /* menu and list are the same */
struct
{
int i_choice;
} menu_answ;
} u;
} en50221_mmi_object_t;
static inline void en50221_MMIFree( en50221_mmi_object_t *p_object )
{
int i;
switch ( p_object->i_object_type )
{
case EN50221_MMI_ENQ:
FREENULL( p_object->u.enq.psz_text );
break;
case EN50221_MMI_ANSW:
if ( p_object->u.answ.b_ok )
{
FREENULL( p_object->u.answ.psz_answ );
}
break;
case EN50221_MMI_MENU:
case EN50221_MMI_LIST:
FREENULL( p_object->u.menu.psz_title );
FREENULL( p_object->u.menu.psz_subtitle );
FREENULL( p_object->u.menu.psz_bottom );
for ( i = 0; i < p_object->u.menu.i_choices; i++ )
{
free( p_object->u.menu.ppsz_choices[i] );
}
FREENULL( p_object->u.menu.ppsz_choices );
break;
default:
break;
}
}
#define MAX_DEMUX 256 #define MAX_DEMUX 256
#define MAX_CI_SLOTS 16
#define MAX_SESSIONS 32 #include "en50221.h"
#define MAX_PROGRAMS 24
struct access_sys_t struct access_sys_t
{ {
int i_handle, i_frontend_handle; int i_handle, i_frontend_handle;
demux_handle_t p_demux_handles[MAX_DEMUX]; demux_handle_t p_demux_handles[MAX_DEMUX];
frontend_t *p_frontend; frontend_t *p_frontend;
mtime_t i_frontend_timeout;
bool b_budget_mode; bool b_budget_mode;
/* CA management */ cam_t cam;
int i_ca_handle;
int i_ca_type;
int i_nb_slots;
bool pb_active_slot[MAX_CI_SLOTS];
bool pb_tc_has_data[MAX_CI_SLOTS];
bool pb_slot_mmi_expected[MAX_CI_SLOTS];
bool pb_slot_mmi_undisplayed[MAX_CI_SLOTS];
en50221_session_t p_sessions[MAX_SESSIONS];
mtime_t i_ca_timeout, i_ca_next_event, i_frontend_timeout;
dvbpsi_pmt_t *pp_selected_programs[MAX_PROGRAMS];
int i_selected_programs;
/* */ /* */
int i_read_once; int i_read_once;
...@@ -220,19 +126,6 @@ void CAMClose( access_t * ); ...@@ -220,19 +126,6 @@ void CAMClose( access_t * );
void CAMStatus( access_t * ); void CAMStatus( access_t * );
#endif #endif
int en50221_Init( access_t * );
int en50221_Poll( access_t * );
int en50221_SetCAPMT( access_t *, dvbpsi_pmt_t * );
int en50221_OpenMMI( access_t * p_access, int i_slot );
int en50221_CloseMMI( access_t * p_access, int i_slot );
en50221_mmi_object_t *en50221_GetMMIObject( access_t * p_access,
int i_slot );
void en50221_SendMMIObject( access_t * p_access, int i_slot,
en50221_mmi_object_t *p_object );
void en50221_End( access_t * );
char *dvbsi_to_utf8( const char *psz_instring, size_t i_length );
#ifdef ENABLE_HTTPD #ifdef ENABLE_HTTPD
int HTTPOpen( access_t *p_access ); int HTTPOpen( access_t *p_access );
void HTTPClose( access_t *p_access ); void HTTPClose( access_t *p_access );
......
This diff is collapsed.
/*****************************************************************************
* en50221.h:
*****************************************************************************
* Copyright (C) 1998-2010 the VideoLAN team
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
* Christopher Ross <chris@tebibyte.org>
* Christophe Massiot <massiot@via.ecp.fr>
*
* 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
* the Free Software Foundation; either version 2 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
typedef struct cam cam_t;
typedef struct en50221_session_t
{
unsigned i_slot;
int i_resource_id;
void (* pf_handle)( cam_t *, int, uint8_t *, int );
void (* pf_close)( cam_t *, int );
void (* pf_manage)( cam_t *, int );
void *p_sys;
} en50221_session_t;
#define EN50221_MMI_NONE 0
#define EN50221_MMI_ENQ 1
#define EN50221_MMI_ANSW 2
#define EN50221_MMI_MENU 3
#define EN50221_MMI_MENU_ANSW 4
#define EN50221_MMI_LIST 5
typedef struct en50221_mmi_object_t
{
int i_object_type;
union
{
struct
{
bool b_blind;
char *psz_text;
} enq;
struct
{
bool b_ok;
char *psz_answ;
} answ;
struct
{
char *psz_title, *psz_subtitle, *psz_bottom;
char **ppsz_choices;
int i_choices;
} menu; /* menu and list are the same */
struct
{
int i_choice;
} menu_answ;
} u;
} en50221_mmi_object_t;
static inline void en50221_MMIFree( en50221_mmi_object_t *p_object )
{
int i;
switch ( p_object->i_object_type )
{
case EN50221_MMI_ENQ:
FREENULL( p_object->u.enq.psz_text );
break;
case EN50221_MMI_ANSW:
if ( p_object->u.answ.b_ok )
{
FREENULL( p_object->u.answ.psz_answ );
}
break;
case EN50221_MMI_MENU:
case EN50221_MMI_LIST:
FREENULL( p_object->u.menu.psz_title );
FREENULL( p_object->u.menu.psz_subtitle );
FREENULL( p_object->u.menu.psz_bottom );
for ( i = 0; i < p_object->u.menu.i_choices; i++ )
{
free( p_object->u.menu.ppsz_choices[i] );
}
FREENULL( p_object->u.menu.ppsz_choices );
break;
default:
break;
}
}
/* CA management */
#define MAX_CI_SLOTS 16
#define MAX_SESSIONS 32
#define MAX_PROGRAMS 24
struct cam
{
vlc_object_t *obj;
int i_ca_type;
int fd;
mtime_t i_timeout, i_next_event;
unsigned i_nb_slots;
bool pb_active_slot[MAX_CI_SLOTS];
bool pb_tc_has_data[MAX_CI_SLOTS];
bool pb_slot_mmi_expected[MAX_CI_SLOTS];
bool pb_slot_mmi_undisplayed[MAX_CI_SLOTS];
en50221_session_t p_sessions[MAX_SESSIONS];
dvbpsi_pmt_t *pp_selected_programs[MAX_PROGRAMS];
int i_selected_programs;
};
int en50221_Init( cam_t * );
int en50221_Poll( cam_t * );
int en50221_SetCAPMT( cam_t *, dvbpsi_pmt_t * );
int en50221_OpenMMI( cam_t *, unsigned i_slot );
int en50221_CloseMMI( cam_t *, unsigned i_slot );
en50221_mmi_object_t *en50221_GetMMIObject( cam_t *, unsigned i_slot );
void en50221_SendMMIObject( cam_t *, unsigned i_slot, en50221_mmi_object_t * );
void en50221_End( cam_t * );
char *dvbsi_to_utf8( const char *psz_instring, size_t i_length );
...@@ -242,7 +242,7 @@ static int HttpCallback( httpd_file_sys_t *p_args, ...@@ -242,7 +242,7 @@ static int HttpCallback( httpd_file_sys_t *p_args,
p_sys->i_httpd_timeout = mdate() + INT64_C(3000000); /* 3 s */ p_sys->i_httpd_timeout = mdate() + INT64_C(3000000); /* 3 s */
p_sys->psz_request = psz_request; p_sys->psz_request = psz_request;
p_sys->b_request_frontend_info = true; p_sys->b_request_frontend_info = true;
if ( p_sys->i_ca_handle ) if ( p_sys->cam.fd != -1 )
{ {
p_sys->b_request_mmi_info = true; p_sys->b_request_mmi_info = true;
} }
......
...@@ -1462,11 +1462,13 @@ void DVRClose( access_t * p_access ) ...@@ -1462,11 +1462,13 @@ void DVRClose( access_t * p_access )
*****************************************************************************/ *****************************************************************************/
int CAMOpen( access_t *p_access ) int CAMOpen( access_t *p_access )
{ {
access_sys_t *p_sys = p_access->p_sys; cam_t *p_cam = &p_access->p_sys->cam;
char ca[128]; char ca[128];
int i_adapter, i_device; int i_adapter, i_device;
ca_caps_t caps; ca_caps_t caps;
p_cam->obj = VLC_OBJECT(p_access);
i_adapter = var_GetInteger( p_access, "dvb-adapter" ); i_adapter = var_GetInteger( p_access, "dvb-adapter" );
i_device = var_GetInteger( p_access, "dvb-device" ); i_device = var_GetInteger( p_access, "dvb-device" );
...@@ -1478,19 +1480,17 @@ int CAMOpen( access_t *p_access ) ...@@ -1478,19 +1480,17 @@ int CAMOpen( access_t *p_access )
memset( &caps, 0, sizeof( ca_caps_t )); memset( &caps, 0, sizeof( ca_caps_t ));
msg_Dbg( p_access, "Opening device %s", ca ); msg_Dbg( p_access, "Opening device %s", ca );
if( (p_sys->i_ca_handle = vlc_open(ca, O_RDWR | O_NONBLOCK)) < 0 ) p_cam->fd = vlc_open(ca, O_RDWR | O_NONBLOCK);
if( p_cam->fd == -1 )
{ {
msg_Warn( p_access, "CAMInit: opening CAM device failed (%m)" ); msg_Warn( p_access, "CAMInit: opening CAM device failed (%m)" );
p_sys->i_ca_handle = 0;
return VLC_EGENERIC; return VLC_EGENERIC;
} }
if ( ioctl( p_sys->i_ca_handle, CA_GET_CAP, &caps ) != 0 ) if ( ioctl( p_cam->fd, CA_GET_CAP, &caps ) < 0 )
{ {
msg_Err( p_access, "CAMInit: ioctl() error getting CAM capabilities" ); msg_Err( p_access, "CAMInit: ioctl() error getting CAM capabilities" );
close( p_sys->i_ca_handle ); goto error;
p_sys->i_ca_handle = 0;
return VLC_EGENERIC;
} }
/* Output CA capabilities */ /* Output CA capabilities */
...@@ -1519,35 +1519,35 @@ int CAMOpen( access_t *p_access ) ...@@ -1519,35 +1519,35 @@ int CAMOpen( access_t *p_access )
if ( caps.slot_num == 0 ) if ( caps.slot_num == 0 )
{ {
msg_Err( p_access, "CAMInit: CAM module with no slots" ); msg_Err( p_access, "CAMInit: CAM module with no slots" );
close( p_sys->i_ca_handle ); goto error;
p_sys->i_ca_handle = 0;
return VLC_EGENERIC;
} }
if( caps.slot_type & CA_CI_LINK ) if( caps.slot_type & CA_CI_LINK )
{ {
p_sys->i_ca_type = CA_CI_LINK; p_cam->i_ca_type = CA_CI_LINK;
} }
else if( caps.slot_type & CA_CI ) else if( caps.slot_type & CA_CI )
{ {
p_sys->i_ca_type = CA_CI; p_cam->i_ca_type = CA_CI;
} }
else else
{ {
p_sys->i_ca_type = -1; p_cam->i_ca_type = -1;
msg_Err( p_access, "CAMInit: incompatible CAM interface" ); msg_Err( p_access, "CAMInit: incompatible CAM interface" );
close( p_sys->i_ca_handle ); goto error;
p_sys->i_ca_handle = 0;
return VLC_EGENERIC;
} }
p_sys->i_nb_slots = caps.slot_num; p_cam->i_nb_slots = caps.slot_num;
memset( p_sys->pb_active_slot, 0, sizeof(bool) * MAX_CI_SLOTS ); memset( p_cam->pb_active_slot, 0, sizeof(bool) * MAX_CI_SLOTS );
memset( p_sys->pb_slot_mmi_expected, 0, sizeof(bool) * MAX_CI_SLOTS ); memset( p_cam->pb_slot_mmi_expected, 0, sizeof(bool) * MAX_CI_SLOTS );
memset( p_sys->pb_slot_mmi_undisplayed, 0, memset( p_cam->pb_slot_mmi_undisplayed, 0,
sizeof(bool) * MAX_CI_SLOTS ); sizeof(bool) * MAX_CI_SLOTS );
return en50221_Init( p_access ); return en50221_Init( p_cam );
error:
close( p_cam->fd );
p_cam->fd = -1;
return VLC_EGENERIC;
} }
/***************************************************************************** /*****************************************************************************
...@@ -1555,28 +1555,25 @@ int CAMOpen( access_t *p_access ) ...@@ -1555,28 +1555,25 @@ int CAMOpen( access_t *p_access )
*****************************************************************************/ *****************************************************************************/
int CAMPoll( access_t * p_access ) int CAMPoll( access_t * p_access )
{ {
access_sys_t *p_sys = p_access->p_sys; cam_t *p_cam = &p_access->p_sys->cam;
int i_ret = VLC_EGENERIC;
if ( p_sys->i_ca_handle == 0 ) if ( p_cam->fd == -1 )
{
return VLC_EGENERIC; return VLC_EGENERIC;
}
switch( p_sys->i_ca_type ) switch( p_cam->i_ca_type )
{ {
case CA_CI_LINK: case CA_CI_LINK:
i_ret = en50221_Poll( p_access ); if ( mdate() > p_cam->i_next_event )
break; {
int ret = en50221_Poll( p_cam );
p_cam->i_next_event = mdate() + p_cam->i_timeout;
return ret;
}
case CA_CI: case CA_CI:
i_ret = VLC_SUCCESS; return VLC_SUCCESS;
break;
default:
msg_Err( p_access, "CAMPoll: This should not happen" );
break;
} }
msg_Err( p_access, "CAMPoll: This should not happen" );
return i_ret; return VLC_EGENERIC;;
} }
#ifdef ENABLE_HTTPD #ifdef ENABLE_HTTPD
...@@ -1586,17 +1583,18 @@ int CAMPoll( access_t * p_access ) ...@@ -1586,17 +1583,18 @@ int CAMPoll( access_t * p_access )
void CAMStatus( access_t * p_access ) void CAMStatus( access_t * p_access )
{ {
access_sys_t *p_sys = p_access->p_sys; access_sys_t *p_sys = p_access->p_sys;
cam_t *p_cam = &p_sys->cam;
char *p; char *p;
ca_caps_t caps; ca_caps_t caps;
int i_slot, i; int i;
if ( p_sys->psz_request != NULL && *p_sys->psz_request ) if ( p_sys->psz_request != NULL && *p_sys->psz_request )
{ {
/* Check if we have an undisplayed MMI message : in that case we ignore /* Check if we have an undisplayed MMI message : in that case we ignore
* the user input to avoid confusing the CAM. */ * the user input to avoid confusing the CAM. */
for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ ) for ( unsigned i_slot = 0; i_slot < p_cam->i_nb_slots; i_slot++ )
{ {
if ( p_sys->pb_slot_mmi_undisplayed[i_slot] == true ) if ( p_cam->pb_slot_mmi_undisplayed[i_slot] == true )
{ {
p_sys->psz_request = NULL; p_sys->psz_request = NULL;
msg_Dbg( p_access, msg_Dbg( p_access,
...@@ -1628,14 +1626,14 @@ void CAMStatus( access_t * p_access ) ...@@ -1628,14 +1626,14 @@ void CAMStatus( access_t * p_access )
if ( HTTPExtractValue( psz_request, "open", psz_value, if ( HTTPExtractValue( psz_request, "open", psz_value,
sizeof(psz_value) ) != NULL ) sizeof(psz_value) ) != NULL )
{ {
en50221_OpenMMI( p_access, i_slot ); en50221_OpenMMI( p_cam, i_slot );
return; return;
} }
if ( HTTPExtractValue( psz_request, "close", psz_value, if ( HTTPExtractValue( psz_request, "close", psz_value,
sizeof(psz_value) ) != NULL ) sizeof(psz_value) ) != NULL )
{ {
en50221_CloseMMI( p_access, i_slot ); en50221_CloseMMI( p_cam, i_slot );
return; return;
} }
...@@ -1689,20 +1687,20 @@ void CAMStatus( access_t * p_access ) ...@@ -1689,20 +1687,20 @@ void CAMStatus( access_t * p_access )
} }
} }
en50221_SendMMIObject( p_access, i_slot, &mmi_object ); en50221_SendMMIObject( p_cam, i_slot, &mmi_object );
return; return;
} }
/* Check that we have all necessary MMI information. */ /* Check that we have all necessary MMI information. */
for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ ) for( unsigned i_slot = 0; i_slot < p_cam->i_nb_slots; i_slot++ )
{ {
if ( p_sys->pb_slot_mmi_expected[i_slot] == true ) if ( p_cam->pb_slot_mmi_expected[i_slot] == true )
return; return;
} }
p = p_sys->psz_mmi_info = malloc( 10000 ); p = p_sys->psz_mmi_info = malloc( 10000 );
if ( ioctl( p_sys->i_ca_handle, CA_GET_CAP, &caps ) != 0 ) if ( ioctl( p_cam->fd, CA_GET_CAP, &caps ) != 0 )
{ {
char buf[1000]; char buf[1000];
strerror_r( errno, buf, sizeof( buf ) ); strerror_r( errno, buf, sizeof( buf ) );
...@@ -1737,15 +1735,15 @@ void CAMStatus( access_t * p_access ) ...@@ -1737,15 +1735,15 @@ void CAMStatus( access_t * p_access )
p += sprintf( p, "</table>" ); p += sprintf( p, "</table>" );
for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ ) for( unsigned i_slot = 0; i_slot < p_cam->i_nb_slots; i_slot++ )
{ {
ca_slot_info_t sinfo; ca_slot_info_t sinfo;
p_sys->pb_slot_mmi_undisplayed[i_slot] = false; p_cam->pb_slot_mmi_undisplayed[i_slot] = false;
p += sprintf( p, "<p>CA slot #%d: ", i_slot ); p += sprintf( p, "<p>CA slot #%d: ", i_slot );
sinfo.num = i_slot; sinfo.num = i_slot;
if ( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &sinfo ) != 0 ) if ( ioctl( p_cam->fd, CA_GET_SLOT_INFO, &sinfo ) != 0 )
{ {
char buf[1000]; char buf[1000];
strerror_r( errno, buf, sizeof( buf ) ); strerror_r( errno, buf, sizeof( buf ) );
...@@ -1764,8 +1762,8 @@ void CAMStatus( access_t * p_access ) ...@@ -1764,8 +1762,8 @@ void CAMStatus( access_t * p_access )
if ( sinfo.flags & CA_CI_MODULE_READY ) if ( sinfo.flags & CA_CI_MODULE_READY )
{ {
en50221_mmi_object_t *p_object = en50221_GetMMIObject( p_access, en50221_mmi_object_t *p_object = en50221_GetMMIObject( p_cam,
i_slot ); i_slot );
p += sprintf( p, "module present and ready<p>\n" ); p += sprintf( p, "module present and ready<p>\n" );
p += sprintf( p, "<form action=index.html method=get>\n" ); p += sprintf( p, "<form action=index.html method=get>\n" );
...@@ -1845,15 +1843,15 @@ out: ...@@ -1845,15 +1843,15 @@ out:
*****************************************************************************/ *****************************************************************************/
int CAMSet( access_t * p_access, dvbpsi_pmt_t *p_pmt ) int CAMSet( access_t * p_access, dvbpsi_pmt_t *p_pmt )
{ {
access_sys_t *p_sys = p_access->p_sys; cam_t *p_cam = &p_access->p_sys->cam;
if( p_sys->i_ca_handle == 0 ) if( p_cam->fd == -1 )
{ {
dvbpsi_DeletePMT( p_pmt ); dvbpsi_DeletePMT( p_pmt );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
en50221_SetCAPMT( p_access, p_pmt ); en50221_SetCAPMT( p_cam, p_pmt );
return VLC_SUCCESS; return VLC_SUCCESS;
} }
...@@ -1863,13 +1861,11 @@ int CAMSet( access_t * p_access, dvbpsi_pmt_t *p_pmt ) ...@@ -1863,13 +1861,11 @@ int CAMSet( access_t * p_access, dvbpsi_pmt_t *p_pmt )
*****************************************************************************/ *****************************************************************************/
void CAMClose( access_t * p_access ) void CAMClose( access_t * p_access )
{ {
access_sys_t *p_sys = p_access->p_sys; cam_t *p_cam = &p_access->p_sys->cam;
en50221_End( p_access ); if ( p_cam->fd == -1 )
return;
if ( p_sys->i_ca_handle ) en50221_End( p_cam );
{ close( p_cam->fd );
close( p_sys->i_ca_handle );
}
} }
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