Commit 485e4dd6 authored by Jean-Paul Saman's avatar Jean-Paul Saman

Adding DVB module to support satellite, cable and terestrial DVB streaming....

Adding DVB module to support satellite, cable and terestrial DVB streaming. The status is that tuning works, but have had no success with video/audio yet. (Setting of filters does not seem to work perfectly yet.).
parent f5cfd128
SOURCES_dvb = \
qpsk.c \
access.c \
dvb.c \
dvb.h \
$(NULL)
/*****************************************************************************
* access.c: DVB card input v4l2 only
*****************************************************************************
* Copyright (C) 1998-2003 VideoLAN
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <saman@natlab.research.philips.com>
* Christopher Ross <ross@natlab.research.philips.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
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/input.h>
#include "../../demux/mpeg/system.h"
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <errno.h>
#ifdef STRNCASECMP_IN_STRINGS_H
# include <strings.h>
#endif
/* DVB Card Drivers */
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include "dvb.h"
#define SATELLITE_READ_ONCE 3
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len);
static int SatelliteSetArea ( input_thread_t *, input_area_t * );
static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
static void SatelliteSeek ( input_thread_t *, off_t );
/*****************************************************************************
* Open: open the frontend device
*****************************************************************************/
int E_(Open) ( vlc_object_t *p_this )
{
struct dvb_frontend_info frontend_info;
struct dvb_frontend_parameters fep;
input_thread_t * p_input = (input_thread_t *)p_this;
input_socket_t * p_satellite;
char * psz_parser;
char * psz_next;
int i_fd = 0;
unsigned int u_adapter = 1;
unsigned int u_device = 0;
unsigned int u_freq = 0;
unsigned int u_srate = 0;
vlc_bool_t b_polarisation = 0;
int i_fec = 0;
fe_code_rate_t fe_fec = FEC_NONE;
vlc_bool_t b_diseqc;
vlc_bool_t b_no_probe;
int i_lnb_lof1;
int i_lnb_lof2;
int i_lnb_slof;
char dvr[] = DVR;
char frontend[] = FRONTEND;
int i_len = 0;
/* parse the options passed in command line : */
psz_parser = strdup( p_input->psz_name );
if( !psz_parser )
{
return( -1 );
}
p_input->pf_read = SatelliteRead;
p_input->pf_set_program = SatelliteSetProgram;
p_input->pf_set_area = SatelliteSetArea;
p_input->pf_seek = SatelliteSeek;
// Get adapter and device number to use for this dvb card
u_adapter = config_GetInt( p_input, "adapter" );
u_device = config_GetInt( p_input, "device" );
/* Determine frontend device information and capabilities */
b_no_probe = config_GetInt( p_input, "no-probe" );
if (!b_no_probe)
{
if ( ioctl_InfoFrontend(&frontend_info, u_adapter, u_device) < 0 )
{
msg_Err( p_input, "(access) cannot determine frontend info" );
return -1;
}
if (frontend_info.type != FE_QPSK)
{
msg_Err( p_input, "frontend not of type satellite" );
return -1;
}
}
else /* no frontend probing is done so use default values. */
{
int i_len;
msg_Dbg( p_input, "Using default values for frontend info" );
i_len = sizeof(FRONTEND);
if (snprintf(frontend, sizeof(FRONTEND), FRONTEND, u_adapter, u_device) >= i_len)
{
printf( "error: snprintf() truncated string for FRONTEND" );
frontend[sizeof(FRONTEND)] = '\0';
}
frontend_info.name = frontend;
frontend_info.type = FE_QPSK;
frontend_info.frequency_max = 12999;
frontend_info.frequency_min = 10000;
frontend_info.symbol_rate_max = 30000;
frontend_info.symbol_rate_min = 1000;
/* b_polarisation */
}
u_freq = (int)strtol( psz_parser, &psz_next, 10 );
if( *psz_next )
{
psz_parser = psz_next + 1;
b_polarisation = (vlc_bool_t)strtol( psz_parser, &psz_next, 10 );
if( *psz_next )
{
psz_parser = psz_next + 1;
i_fec = (int)strtol( psz_parser, &psz_next, 10 );
if( *psz_next )
{
psz_parser = psz_next + 1;
u_srate = (int)strtol( psz_parser, &psz_next, 10 );
}
}
}
if ( ((u_freq) > frontend_info.frequency_max) ||
((u_freq) < frontend_info.frequency_min) )
{
msg_Warn( p_input, "invalid frequency %d, using default one", u_freq );
u_freq = config_GetInt( p_input, "frequency" );
if ( ((u_freq) > frontend_info.frequency_max) ||
((u_freq) < frontend_info.frequency_min) )
{
msg_Err( p_input, "invalid default frequency" );
return -1;
}
}
if ( ((u_srate) > frontend_info.symbol_rate_max) ||
((u_srate) < frontend_info.symbol_rate_min) )
{
msg_Warn( p_input, "invalid symbol rate, using default one" );
u_srate = config_GetInt( p_input, "symbol-rate" );
if ( ((u_srate) > frontend_info.symbol_rate_max) ||
((u_srate) < frontend_info.symbol_rate_min) )
{
msg_Err( p_input, "invalid default symbol rate" );
return -1;
}
}
if( b_polarisation && b_polarisation != 1 )
{
msg_Warn( p_input, "invalid polarization, using default one" );
b_polarisation = config_GetInt( p_input, "polarization" );
if( b_polarisation && b_polarisation != 1 )
{
msg_Err( p_input, "invalid default polarization" );
return -1;
}
}
if( (i_fec > 7) || (i_fec < 1) )
{
msg_Warn( p_input, "invalid FEC, using default one" );
i_fec = config_GetInt( p_input, "fec" );
if( (i_fec > 7) || (i_fec < 1) )
{
msg_Err( p_input, "invalid default FEC" );
return -1;
}
}
switch( i_fec )
{
case 1:
fe_fec = FEC_1_2;
break;
case 2:
fe_fec = FEC_2_3;
break;
case 3:
fe_fec = FEC_3_4;
break;
case 4:
fe_fec = FEC_4_5;
break;
case 5:
fe_fec = FEC_5_6;
break;
case 6:
fe_fec = FEC_6_7;
break;
case 7:
fe_fec = FEC_7_8;
break;
case 8:
fe_fec = FEC_8_9;
break;
case 9:
fe_fec = FEC_AUTO;
break;
default:
/* cannot happen */
fe_fec = FEC_NONE;
break;
}
switch( frontend_info.type )
{
case FE_QPSK:
fep.frequency = u_freq * 1000;
fep.inversion = INVERSION_AUTO;
fep.u.qpsk.symbol_rate = u_srate * 1000;
fep.u.qpsk.fec_inner = fe_fec;
msg_Dbg( p_input, "satellite frontend found on %s", frontend_info.name );
break;
case FE_QAM:
msg_Dbg( p_input, "cable frontend found on %s", frontend_info.name );
break;
case FE_OFDM:
msg_Dbg( p_input, "terrestrial frontend found on %s", frontend_info.name );
break;
default:
msg_Err( p_input, "Could not determine frontend type on %s", frontend_info.name );
return -1;
}
/* Initialise structure */
p_satellite = malloc( sizeof( input_socket_t ) );
if( p_satellite == NULL )
{
msg_Err( p_input, "out of memory" );
return -1;
}
p_input->p_access_data = (void *)p_satellite;
/* Open the DVR device */
i_len = sizeof(DVR);
if (snprintf(dvr, sizeof(DVR), DVR, u_adapter, u_device) >= i_len)
{
msg_Err( p_input, "error: snprintf() truncated string for DVR" );
dvr[sizeof(DVR)] = '\0';
}
msg_Dbg( p_input, "opening DVR device '%s'", dvr );
if( (p_satellite->i_handle = open( dvr,
/*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
{
msg_Warn( p_input, "cannot open `%s' (%s)", dvr, strerror(errno) );
free( p_satellite );
return -1;
}
/* Get antenna configuration options */
b_diseqc = config_GetInt( p_input, "diseqc" );
i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
i_lnb_lof2 = config_GetInt( p_input, "lnb-lof2" );
i_lnb_slof = config_GetInt( p_input, "lnb-slof" );
/* Initialize the Satellite Card */
msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
"FEC: %d, Srate: %d", u_freq, b_polarisation, fe_fec, u_srate );
msg_Dbg( p_input, "initializing frontend device" );
// switch (ioctl_SetQPSKFrontend ( u_freq * 1000, i_srate* 1000, fe_fec,
// i_lnb_lof1 * 1000, i_lnb_lof2 * 1000, i_lnb_slof * 1000))
switch (ioctl_SetQPSKFrontend ( fep, b_polarisation, u_adapter, u_device ))
{
case -2:
msg_Err( p_input, "frontend returned an unexpected event" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
case -3:
msg_Err( p_input, "frontend returned no event" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
case -4:
msg_Err( p_input, "frontend: timeout when polling for event" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
case -5:
msg_Err( p_input, "an error occured when polling frontend device" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
case -1:
msg_Err( p_input, "frontend returned a failure event" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
default:
break;
}
msg_Dbg( p_input, "setting filter on PAT\n" );
if ( ioctl_SetDMXFilter( 0, &i_fd, 3, u_adapter, u_device ) < 0 )
{
msg_Err( p_input, "an error occured when setting filter on PAT" );
close( p_satellite->i_handle );
free( p_satellite );
return -1;
}
msg_Dbg( p_input, "@@@ Initialising input stream\n" );
if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
{
msg_Err( p_input, "could not initialize stream structure" );
close( p_satellite->i_handle );
free( p_satellite );
return( -1 );
}
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.b_pace_control = 1;
p_input->stream.b_seekable = 0;
p_input->stream.p_selected_area->i_tell = 0;
vlc_mutex_unlock( &p_input->stream.stream_lock );
p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
p_input->stream.i_method = INPUT_METHOD_SATELLITE;
msg_Dbg( p_input, "@@@ Leaving E_(Open)\n" );
return 0;
}
/*****************************************************************************
* Close : Close the device
*****************************************************************************/
void E_(Close) ( vlc_object_t *p_this )
{
input_thread_t * p_input = (input_thread_t *)p_this;
input_socket_t * p_satellite;
unsigned int i_es_index;
if ( p_input->stream.p_selected_program )
{
for ( i_es_index = 1 ;
i_es_index < p_input->stream.p_selected_program->i_es_number;
i_es_index ++ )
{
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
if ( p_es->p_decoder_fifo )
{
ioctl_UnsetDMXFilter( p_es->i_demux_fd );
}
#undef p_es
}
}
p_satellite = (input_socket_t *)p_input;
close( p_satellite->i_handle );
}
/*****************************************************************************
* SatelliteRead: reads data from the satellite card
*****************************************************************************/
static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
size_t i_len )
{
input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
ssize_t i_ret;
unsigned int u_adapter = 1;
unsigned int u_device = 0;
unsigned int i;
msg_Dbg( p_input, "@@@ SatelliteRead seeking for %d program\n", p_input->stream.i_pgrm_number );
// Get adapter and device number to use for this dvb card
u_adapter = config_GetInt( p_input, "adapter" );
u_device = config_GetInt( p_input, "device" );
/* if not set, set filters to the PMTs */
for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
{
msg_Dbg( p_input, "@@@ trying to set filter on pmt pid %d",
p_input->stream.pp_programs[i]->pp_es[0]->i_id );
if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
{
msg_Dbg( p_input, "setting filter on pmt pid %d",
p_input->stream.pp_programs[i]->pp_es[0]->i_id );
ioctl_SetDMXFilter( p_input->stream.pp_programs[i]->pp_es[0]->i_id,
&p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
3, u_adapter, u_device );
}
}
i_ret = read( p_access_data->i_handle, p_buffer, i_len );
if( i_ret < 0 )
{
# ifdef HAVE_ERRNO_H
msg_Err( p_input, "read failed (%s)", strerror(errno) );
# else
msg_Err( p_input, "read failed" );
# endif
}
msg_Dbg( p_input, "@@@ Searched all, returning %d\n", i_ret );
return i_ret;
}
/*****************************************************************************
* SatelliteSetArea : Does nothing
*****************************************************************************/
static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
{
return -1;
}
/*****************************************************************************
* SatelliteSetProgram : Sets the card filters according to the
* selected program,
* and makes the appropriate changes to stream structure.
*****************************************************************************/
int SatelliteSetProgram( input_thread_t * p_input,
pgrm_descriptor_t * p_new_prg )
{
unsigned int i_es_index;
unsigned int u_adapter = 1;
unsigned int u_device = 0;
msg_Dbg( p_input, "@@@ SatelliteSetProgram enter\n" );
// Get adapter and device number to use for this dvb card
u_adapter = config_GetInt( p_input, "adapter" );
u_device = config_GetInt( p_input, "device" );
if ( p_input->stream.p_selected_program )
{
for ( i_es_index = 1 ; /* 0 should be the PMT */
i_es_index < p_input->stream.p_selected_program->i_es_number ;
i_es_index ++ )
{
#define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
if ( p_es->p_decoder_fifo )
{
input_UnselectES( p_input , p_es );
}
if ( p_es->i_demux_fd )
{
ioctl_UnsetDMXFilter( p_es->i_demux_fd );
p_es->i_demux_fd = 0;
}
#undef p_es
}
}
for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
{
#define p_es p_new_prg->pp_es[i_es_index]
switch( p_es->i_cat )
{
case MPEG1_VIDEO_ES:
case MPEG2_VIDEO_ES:
if ( input_SelectES( p_input , p_es ) == 0 )
{
ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 1, u_adapter, u_device);
}
break;
case MPEG1_AUDIO_ES:
case MPEG2_AUDIO_ES:
if ( input_SelectES( p_input , p_es ) == 0 )
{
ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 2, u_adapter, u_device);
input_SelectES( p_input , p_es );
}
break;
default:
ioctl_SetDMXFilter( p_es->i_id, &p_es->i_demux_fd, 3, u_adapter, u_device);
input_SelectES( p_input , p_es );
break;
#undef p_es
}
}
p_input->stream.p_selected_program = p_new_prg;
msg_Dbg( p_input, "@@@ SatelliteSetProgram exit\n" );
return 0;
}
/*****************************************************************************
* SatelliteSeek: does nothing (not a seekable stream
*****************************************************************************/
static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
{
;
}
/*****************************************************************************
* dvb.c : functions to control a DVB card under Linux with v4l2
*****************************************************************************
* Copyright (C) 1998-2003 VideoLAN
*
* Authors: Damien Lucas <nitrox@via.ecp.fr>
* Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <saman@natlab.research.philips.com>
* Christopher Ross <ross@natlab.research.philips.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
* 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.
*****************************************************************************/
#include <vlc/vlc.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#ifdef HAVE_INTTYPES_H
# include <inttypes.h> /* int16_t .. */
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/poll.h>
/* DVB Card Drivers */
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/errno.h>
#include "dvb.h"
static int ioctl_CheckQPSK( int );
/*****************************************************************************
* ioctl_FrontendControl : commands the SEC device
*****************************************************************************/
int ioctl_FrontendControl( int freq, int pol, int lnb_slof, int diseqc, unsigned int u_adapter, unsigned int u_device)
{
struct dvb_diseqc_master_cmd cmd;
fe_sec_tone_mode_t tone;
fe_sec_voltage_t voltage;
int frontend;
char front[] = FRONTEND;
int i_len;
printf("ioclt_FrontEndControl: enter\n");
i_len = sizeof(FRONTEND);
if (snprintf(front, sizeof(FRONTEND), FRONTEND, u_adapter, u_device) >= i_len)
{
printf( "error: snprintf() truncated string for FRONTEND" );
front[sizeof(FRONTEND)] = '\0';
}
printf("ioclt_FrontEndControl: Opening frontend %s\n",front);
if((frontend = open(front,O_RDWR)) < 0)
{
return -1;
}
/* Set the frequency of the transponder, taking into account the
local frequencies of the LNB */
tone = (freq<lnb_slof) ? SEC_TONE_OFF : SEC_TONE_ON;
/* Set the polarisation of the transponder by setting the correct
voltage on the universal LNB */
voltage = (pol) ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13;
/* In case we have a DiSEqC, set it to the correct address */
cmd.msg[0] =0x0; /* framing */
cmd.msg[1] =0x10; /* address */
cmd.msg[2] =0x38; /* command */
/* command parameters start at index 3 */
cmd.msg[3] = 0xF0 | ((diseqc * 4) & 0x0F);
cmd.msg_len = 4;
/* Reset everything before sending. */
#define CHECK_IOCTL(X) if(X<0) \
{ \
close(frontend); \
return -1; \
}
CHECK_IOCTL(ioctl(frontend, FE_SET_TONE, SEC_TONE_OFF));
CHECK_IOCTL(ioctl(frontend, FE_SET_VOLTAGE, voltage));
msleep(15);
/* Send the data to the SEC device to prepare the LNB for tuning */
/*intf_Msg("Sec: Sending data\n");*/
CHECK_IOCTL(ioctl(frontend, FE_DISEQC_SEND_MASTER_CMD, &cmd));
msleep(15);
CHECK_IOCTL(ioctl(frontend, FE_DISEQC_SEND_BURST, &cmd));
msleep(15);
CHECK_IOCTL(ioctl(frontend, FE_SET_TONE, tone));
#undef CHECK_IOCTL
close(frontend);
printf("ioclt_FrontEndControl: exit\n");
return 0;
}
/*****************************************************************************
* ioctl_InfoFrontend : return information about given frontend
*****************************************************************************/
int ioctl_InfoFrontend(struct dvb_frontend_info *info, unsigned int u_adapter, unsigned int u_device)
{
int front;
char frontend[] = FRONTEND;
int i_len;
printf("ioclt_InfoFrontEnd: enter\n");
i_len = sizeof(FRONTEND);
if (snprintf(frontend, sizeof(FRONTEND), FRONTEND, u_adapter, u_device) >= i_len)
{
printf( "error: snprintf() truncated string for FRONTEND" );
frontend[sizeof(FRONTEND)] = '\0';
}
printf("ioclt_InfoFrontEnd: Opening device %s\n", frontend);
if((front = open(frontend,O_RDWR)) < 0)
{
return -1;
}
/* Determine type of frontend */
if (ioctl(front, FE_GET_INFO, info) < 0)
{
close(front);
return -1;
}
#if 1
printf( "Frontend Info:\tname = %s\n\t\tfrequency_min = %d\n\t\tfrequency_max = %d\n\t\tfrequency_stepsize = %d\n\t\tfrequency_tolerance = %d\n\t\tsymbol_rate_min = %d\n\t\tsymbol_rate_max = %d\n\t\tsymbol_rate_tolerance (ppm) = %d\n\t\tnotifier_delay (ms)= %d\n",
info->name,
info->frequency_min,
info->frequency_max,
info->frequency_stepsize,
info->frequency_tolerance,
info->symbol_rate_min,
info->symbol_rate_max,
info->symbol_rate_tolerance,
info->notifier_delay );
#endif
close(front);
printf("ioclt_InfoFrontEnd: exit\n");
return 0;
}
// CPR ---> ===================================================================
struct diseqc_cmd {
struct dvb_diseqc_master_cmd cmd;
uint32_t wait;
};
struct diseqc_cmd switch_cmds[] = {
{ { { 0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf2, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf1, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf3, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf4, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf6, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf5, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf7, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf8, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xfa, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xf9, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xfb, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xfc, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xfe, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xfd, 0x00, 0x00 }, 4 }, 0 },
{ { { 0xe0, 0x10, 0x38, 0xff, 0x00, 0x00 }, 4 }, 0 }
};
int diseqc_send_msg (int fd, fe_sec_voltage_t v, struct diseqc_cmd **cmd,
fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
{
int err;
printf("diseqc_send_msg: enter\n");
if ((err = ioctl(fd, FE_SET_TONE, SEC_TONE_OFF)))
return err;
if ((err = ioctl(fd, FE_SET_VOLTAGE, v)))
return err;
msleep(15);
while (*cmd) {
printf("msg: %02x %02x %02x %02x %02x %02x\n",
(*cmd)->cmd.msg[0], (*cmd)->cmd.msg[1],
(*cmd)->cmd.msg[2], (*cmd)->cmd.msg[3],
(*cmd)->cmd.msg[4], (*cmd)->cmd.msg[5]);
if ((err = ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd)))
return err;
msleep((*cmd)->wait);
cmd++;
}
msleep(15);
if ((err = ioctl(fd, FE_DISEQC_SEND_BURST, b)))
return err;
msleep(15);
printf("diseqc_send_msg: exit\n");
return ioctl(fd, FE_SET_TONE, t);
}
int setup_switch (int frontend_fd, int switch_pos, int voltage_18, int hiband)
{
struct diseqc_cmd *cmd[2] = { NULL, NULL };
int i = 4 * switch_pos + 2 * hiband + (voltage_18 ? 1 : 0);
printf("setup_switch: enter\n");
printf("switch pos %i, %sV, %sband\n",
switch_pos, voltage_18 ? "18" : "13", hiband ? "hi" : "lo");
printf("index %i\n", i);
if (i < 0 || i >= (int)(sizeof(switch_cmds)/sizeof(struct diseqc_cmd)))
return -EINVAL;
cmd[0] = &switch_cmds[i];
printf("setup_switch: exit\n");
return diseqc_send_msg (frontend_fd,
i % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13,
cmd,
(i/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF,
(i/4) % 2 ? SEC_MINI_B : SEC_MINI_A);
}
// <--- CPR ===================================================================
#define SWITCHFREQ 11700000
#define LOF_HI 10600000
#define LOF_LO 9750000
/*****************************************************************************
* ioctl_SetQPSKFrontend : controls the FE device
*****************************************************************************/
int ioctl_SetQPSKFrontend ( struct dvb_frontend_parameters fep, int b_polarisation, unsigned int u_adapter, unsigned int u_device )
{
int front;
int rc;
int i;
int hiband;
char frontend[] = FRONTEND;
int i_len;
printf("ioctl_SetQPSKFrontend: enter\n");
i_len = sizeof(FRONTEND);
if (snprintf(frontend, sizeof(FRONTEND), FRONTEND, u_adapter, u_device) >= i_len)
{
printf( "error: snprintf() truncated string for FRONTEND" );
frontend[sizeof(FRONTEND)] = '\0';
}
printf("ioctl_SetQPSKFrontend: Opening frontend %s\n", frontend);
/* Open the frontend device */
if((front = open(frontend,O_RDWR)) < 0)
{
return -1;
}
/* Set the frequency of the transponder, taking into account the
local frequencies of the LNB */
hiband = (fep.frequency >= SWITCHFREQ);
setup_switch (front, 0, b_polarisation, hiband );
if (hiband)
fep.frequency -= LOF_HI;
else
fep.frequency -= LOF_LO;
/* Now send it all to the frontend device */
if (ioctl(front, FE_SET_FRONTEND, &fep) < 0)
{
printf("ioctl_SetQPSKFrontend: ioctl FE_SET_FRONTEND failed\n");
close(front);
return -1;
}
for (i=0; i<3; i++)
{
fe_status_t s;
ioctl(front, FE_READ_STATUS, &s);
printf("ioctl_SetQPSKFrontend: tuning status == 0x%02x!!! ...", s);
if (s & FE_HAS_LOCK)
{
printf( "tuning succeeded\n" );
rc = 0;
}
else
{
printf( "tuning failed\n");
rc = -1;
}
usleep( 500000 );
}
/* Close front end device */
close(front);
printf("ioctl_SetQPSKFrontend: exit\n");
return rc;
}
/******************************************************************
* Check completion of the frontend control sequence
******************************************************************/
static int ioctl_CheckQPSK(int front)
{
struct pollfd pfd[1];
struct dvb_frontend_event event;
/* poll for QPSK event to check if tuning worked */
pfd[0].fd = front;
pfd[0].events = POLLIN;
printf("ioctl_CheckQPSK: enter\n");
if (poll(pfd,1,3000))
{
if (pfd[0].revents & POLLIN)
{
if ( ioctl(front, FE_GET_EVENT, &event) < 0)
{
printf("ioctl_CheckQPSK: ioctl FE_GET_EVENT failed\n");
return -5;
}
switch(event.status)
{
case FE_HAS_SIGNAL: /* found something above the noise level */
printf("ioctl_CheckQPSK: FE_HAS_SIGNAL\n");
break;
case FE_HAS_CARRIER: /* found a DVB signal */
printf("ioctl_CheckQPSK: FE_HAS_CARRIER\n");
break;
case FE_HAS_VITERBI: /* FEC is stable */
printf("ioctl_CheckQPSK: FE_HAS_VITERBI\n");
break;
case FE_HAS_SYNC: /* found sync bytes */
printf("ioctl_CheckQPSK: FE_HAS_SYNC\n");
break;
case FE_HAS_LOCK: /* everything's working... */
printf("ioctl_CheckQPSK: FE_HAS_LOCK\n");
break;
case FE_TIMEDOUT: /* no lock within the last ~2 seconds */
printf("ioctl_CheckQPSK: FE_TIMEDOUT\n");
return -2;
case FE_REINIT: /* frontend was reinitialized, */
/* application is recommned to reset */
/* DiSEqC, tone and parameters */
printf("ioctl_CheckQPSK: FE_REINIT\n");
return -1;
}
}
else
{
/* should come here */
printf("ioctl_CheckQPSK: event() failed\n");
return -3;
}
}
else
{
printf("ioctl_CheckQPSK: poll() failed\n");
return -4;
}
printf("ioctl_CheckQPSK: exit\n");
return 0;
}
/*****************************************************************************
* ioctl_SetDMXFilter : controls the demux to add a filter
*****************************************************************************/
int ioctl_SetDMXFilter( int i_pid, int * pi_fd , int i_type, unsigned int u_adapter, unsigned int u_device )
{
struct dmx_pes_filter_params s_filter_params;
char dmx[] = DMX;
int i_len;
int result;
/* We first open the device */
printf("ioctl_SetDMXFIlter: enter\n");
i_len = sizeof(DMX);
if (snprintf( dmx, sizeof(DMX), DMX, u_adapter, u_device) >= i_len)
{
printf( "error: snprintf() truncated string for DMX" );
dmx[sizeof(DMX)] = '\0';
}
printf("ioctl_SetDMXFIlter: Opening demux device %s\n", dmx);
if ((*pi_fd = open(dmx, O_RDWR|O_NONBLOCK)) < 0)
{
return -1;
}
printf( "@@@ Trying to set PMT id to=%d for type %d\n", i_pid, i_type );
/* We fill the DEMUX structure : */
s_filter_params.pid = i_pid;
s_filter_params.input = DMX_IN_FRONTEND;
s_filter_params.output = DMX_OUT_TS_TAP;
switch ( i_type )
{
case 1:
printf("ioctl_SetDMXFIlter: DMX_PES_VIDEO\n");
s_filter_params.pes_type = DMX_PES_VIDEO;
break;
case 2:
printf("ioctl_SetDMXFIlter: DMX_PES_AUDIO\n");
s_filter_params.pes_type = DMX_PES_AUDIO;
break;
case 3:
printf("ioctl_SetDMXFIlter: DMX_PES_OTHER\n");
s_filter_params.pes_type = DMX_PES_OTHER;
break;
}
s_filter_params.flags = DMX_IMMEDIATE_START;
/* We then give the order to the device : */
if (result = ioctl(*pi_fd, DMX_SET_PES_FILTER, &s_filter_params) < 0)
{
printf("ioctl_SetDMXFIlter: ioctl failed with %d (%s)\n",result, strerror(errno));
return -1;
}
printf("ioctl_SetDMXFIlter: exit\n");
return 0;
}
/*****************************************************************************
* ioctl_UnsetDMXFilter : removes a filter
*****************************************************************************/
int ioctl_UnsetDMXFilter(int demux)
{
printf("ioctl_UnsetDMXFIlter: enter\n");
ioctl(demux, DMX_STOP);
close(demux);
printf("ioctl_UnsetDMXFIlter: exit\n");
return 0;
}
/*****************************************************************************
* dvb.h : functions to control a DVB card under Linux with v4l2
*****************************************************************************
* Copyright (C) 1998-2003 VideoLAN
*
* Authors: Johan Bilien <jobi@via.ecp.fr>
* Jean-Paul Saman <saman@natlab.research.philips.com>
* Christopher Ross <ross@natlab.research.philips.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
* 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.
*****************************************************************************/
/*****************************************************************************
* Devices location
*****************************************************************************/
/*
#define DMX "/dev/dvb/adapter1/demux0"
#define FRONTEND "/dev/dvb/adapter1/frontend0"
#define DVR "/dev/dvb/adapter1/dvr0"
*/
#define DMX "/dev/dvb/adapter%d/demux%d"
#define FRONTEND "/dev/dvb/adapter%d/frontend%d"
#define DVR "/dev/dvb/adapter%d/dvr%d"
/*****************************************************************************
* Prototypes
*****************************************************************************/
int ioctl_FrontendControl( int freq, int pol, int lnb_slof, int diseqc, unsigned int u_adapter, unsigned int u_device );
int ioctl_SetQPSKFrontend ( struct dvb_frontend_parameters fep, int b_polarisation, unsigned int u_adapter, unsigned int u_device );
int ioctl_SetDMXFilter( int i_pid, int *pi_fd, int i_type, unsigned int u_adapter, unsigned int u_device );
int ioctl_UnsetDMXFilter( int );
int ioctl_InfoFrontend(struct dvb_frontend_info *info, unsigned int u_adapter, unsigned int u_device );
/*****************************************************************************
* qpsk.c : Satellite input module for vlc
*****************************************************************************
* Copyright (C) 2003 VideoLAN
*
* Authors: Samuel Hocevar <sam@zoy.org>
* Jean-Paul Saman <saman@natlab.research.philips.com>
* Christopher Ross <ross@natlab.research.philips.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
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strdup() */
#include <vlc/vlc.h>
/*****************************************************************************
* External prototypes
*****************************************************************************/
int E_(Open) ( vlc_object_t * );
void E_(Close) ( vlc_object_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define ADAPTER_TEXT N_("adapter card to tune")
#define ADAPTER_LONGTEXT N_("")
#define DEVICE_TEXT N_("device nummer to use on adapter")
#define DEVICE_LONGTEXT N_("")
#define FREQ_TEXT N_("satellite default transponder frequency")
#define FREQ_LONGTEXT ""
#define POL_TEXT N_("satellite default transponder polarization")
#define POL_LONGTEXT ""
#define FEC_TEXT N_("satellite default transponder FEC")
#define FEC_LONGTEXT ""
#define SRATE_TEXT N_("satellite default transponder symbol rate")
#define SRATE_LONGTEXT ""
#define DISEQC_TEXT N_("use diseqc with antenna")
#define DISEQC_LONGTEXT ""
#define LNB_LOF1_TEXT N_("antenna lnb_lof1 (kHz)")
#define LNB_LOF1_LONGTEXT ""
#define LNB_LOF2_TEXT N_("antenna lnb_lof2 (kHz)")
#define LNB_LOF2_LONGTEXT ""
#define LNB_SLOF_TEXT N_("antenna lnb_slof (kHz)")
#define LNB_SLOF_LONGTEXT ""
#define NO_PROBE_TEXT N_("do not probe the dvb card for capabilities")
#define NO_PROBE_LONGTEXT N_("some dvb cards do not like to be probed for their capabilities")
vlc_module_begin();
add_category_hint( N_("Input"), NULL, VLC_FALSE );
add_integer( "adapter", 1, NULL, ADAPTER_TEXT, ADAPTER_LONGTEXT, VLC_FALSE );
add_integer( "device", 0, NULL, DEVICE_TEXT, DEVICE_LONGTEXT, VLC_FALSE );
add_integer( "frequency", 11954, NULL, FREQ_TEXT, FREQ_LONGTEXT, VLC_FALSE );
add_integer( "polarization", 0, NULL, POL_TEXT, POL_LONGTEXT, VLC_FALSE );
add_integer( "fec", 3, NULL, FEC_TEXT, FEC_LONGTEXT, VLC_FALSE );
add_integer( "symbol-rate", 27500, NULL, SRATE_TEXT, SRATE_LONGTEXT, VLC_FALSE );
add_bool( "diseqc", 0, NULL, DISEQC_TEXT, DISEQC_LONGTEXT, VLC_FALSE );
add_integer( "lnb-lof1", 10000, NULL,
LNB_LOF1_TEXT, LNB_LOF1_LONGTEXT, VLC_FALSE );
add_integer( "lnb-lof2", 10000, NULL,
LNB_LOF2_TEXT, LNB_LOF2_LONGTEXT, VLC_FALSE );
add_integer( "lnb-slof", 11700, NULL,
LNB_SLOF_TEXT, LNB_SLOF_LONGTEXT, VLC_FALSE );
add_bool( "no-probe", 1, NULL, NO_PROBE_TEXT, NO_PROBE_LONGTEXT, VLC_FALSE );
set_description( _("DVB input module with v4l2 support") );
set_capability( "access", 0 );
// add_shortcut( "satellite" );
add_shortcut( "qpsk" );
// add_shortcut( "cable" );
// add_shortcut( "terrestrial" );
add_shortcut( "dvb" );
set_callbacks( E_(Open), E_(Close) );
vlc_module_end();
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