1 /*****************************************************************************
2 * access.c: Satellite card input
3 *****************************************************************************
4 * Copyright (C) 1998-2003 VideoLAN
6 * Authors: Johan Bilien <jobi@via.ecp.fr>
7 * Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
22 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
32 #include <vlc/input.h>
34 #include "../../demux/mpeg/system.h"
41 #include <sys/types.h>
45 #ifdef STRNCASECMP_IN_STRINGS_H
51 /* These are for the Dreambox port. I have no idea whether they're correct
52 * for other DVB adapters. --Meuuh */
53 #define SATELLITE_READ_ONCE (64 * 1024)
54 #define DMX_BUFFER_SIZE (1024 * 1024)
56 /*****************************************************************************
58 *****************************************************************************/
59 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
61 static int SatelliteSetArea ( input_thread_t *, input_area_t * );
62 static int SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
63 static void SatelliteSeek ( input_thread_t *, off_t );
65 typedef struct demux_handle_t
78 typedef struct thread_sat_data_t
81 demux_handle_t p_demux_handles[MAX_DEMUX];
84 static void AllocateDemux( input_thread_t * p_input, int i_pid,
87 thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
90 i_demux = config_GetInt( p_input, "dvb-dmx" );
92 /* Find first free slot */
93 for ( i = 0; i < MAX_DEMUX; i++ )
95 if ( !p_satellite->p_demux_handles[i].i_type )
97 if (ioctl_SetDMXFilter( i_demux, i_pid, &p_satellite->p_demux_handles[i].i_handle, 3) < 0)
99 msg_Warn(p_input, "ioctl_SetDMXFilter failed (%d)", i_pid);
102 p_satellite->p_demux_handles[i].i_type = i_type;
103 p_satellite->p_demux_handles[i].i_pid = i_pid;
109 static void CloseProgram( input_thread_t * p_input )
111 thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
114 for ( i = 1; i < MAX_DEMUX; i++ )
116 if ( p_satellite->p_demux_handles[i].i_type )
118 ioctl_UnsetDMXFilter( p_satellite->p_demux_handles[i].i_handle );
119 p_satellite->p_demux_handles[i].i_type = 0;
124 /*****************************************************************************
125 * Open: open the dvr device
126 *****************************************************************************/
127 int E_(Open) ( vlc_object_t *p_this )
129 input_thread_t * p_input = (input_thread_t *)p_this;
130 thread_sat_data_t * p_satellite;
135 vlc_bool_t b_pol = 0;
144 i_demux = config_GetInt( p_input, "dvb-dmx" );
145 snprintf(psz_dvr, sizeof(psz_dvr), DVR "%d", i_demux);
147 /* parse the options passed in command line : */
149 psz_parser = strdup( p_input->psz_name );
156 p_input->pf_read = SatelliteRead;
157 p_input->pf_set_program = SatelliteSetProgram;
158 p_input->pf_set_area = SatelliteSetArea;
159 p_input->pf_seek = SatelliteSeek;
161 i_freq = (int)strtol( psz_parser, &psz_next, 10 );
165 psz_parser = psz_next + 1;
166 b_pol = (vlc_bool_t)strtol( psz_parser, &psz_next, 10 );
169 psz_parser = psz_next + 1;
170 i_fec = (int)strtol( psz_parser, &psz_next, 10 );
173 psz_parser = psz_next + 1;
174 i_srate = (int)strtol( psz_parser, &psz_next, 10 );
180 if( i_freq > (12999*1000) || i_freq < (10000*1000) )
182 msg_Warn( p_input, "invalid frequency, using default one" );
183 i_freq = config_GetInt( p_input, "frequency" );
184 if( i_freq && (i_freq > (12999*1000) || i_freq < (10000*1000)) )
186 msg_Err( p_input, "invalid default frequency" );
191 if( i_freq && (i_srate > (30000*1000) || i_srate < (1000*1000)) )
193 msg_Warn( p_input, "invalid symbol rate, using default one" );
194 i_srate = config_GetInt( p_input, "symbol-rate" );
195 if( i_srate > (30000*1000) || i_srate < (1000*1000) )
197 msg_Err( p_input, "invalid default symbol rate" );
202 if( i_freq && b_pol && b_pol != 1 )
204 msg_Warn( p_input, "invalid polarization, using default one" );
205 b_pol = config_GetInt( p_input, "polarization" );
206 if( b_pol && b_pol != 1 )
208 msg_Err( p_input, "invalid default polarization" );
213 if( i_freq && (i_fec > 7 || i_fec < 1) )
215 msg_Warn( p_input, "invalid FEC, using default one" );
216 i_fec = config_GetInt( p_input, "fec" );
217 if( i_fec > 7 || i_fec < 1 )
219 msg_Err( p_input, "invalid default FEC" );
256 /* Initialise structure */
257 p_satellite = malloc( sizeof( thread_sat_data_t ) );
259 if( p_satellite == NULL )
261 msg_Err( p_input, "out of memory" );
264 memset( p_satellite, 0, sizeof( thread_sat_data_t ) );
266 p_input->p_access_data = (void *)p_satellite;
268 /* Open the DVR device */
269 msg_Dbg( p_input, "opening DVR device `%s'", psz_dvr );
271 if( (p_satellite->i_handle = open( psz_dvr,
272 /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
274 msg_Warn( p_input, "cannot open `%s' (%s)", psz_dvr, strerror(errno) );
279 /* FIXME : this is from the Dreambox port. I have no idea whether it
280 * hurts or helps other DVB interfaces, so I just leave it here.
281 * Feel free to remove it if it breaks. --Meuuh */
282 ioctl_SetBufferSize( p_satellite->i_handle, DMX_BUFFER_SIZE );
284 /* Get antenna configuration options */
285 b_diseqc = config_GetInt( p_input, "diseqc" );
286 i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
287 i_lnb_lof2 = config_GetInt( p_input, "lnb-lof2" );
288 i_lnb_slof = config_GetInt( p_input, "lnb-slof" );
290 /* Initialize the Satellite Card */
294 int i_tuner = config_GetInt( p_input, "dvb-tuner" );
296 msg_Dbg( p_input, "initializing Sat Card with Freq: %d, Pol: %d, "
297 "FEC: %03f, Srate: %d", i_freq, b_pol, f_fec, i_srate );
299 if ( ioctl_SECControl( i_tuner, i_freq, b_pol, i_lnb_slof, b_diseqc ) < 0 )
301 msg_Err( p_input, "an error occured when controling SEC" );
302 close( p_satellite->i_handle );
307 msg_Dbg( p_input, "initializing frontend device" );
308 switch (ioctl_SetQPSKFrontend ( i_tuner, i_freq, i_srate, f_fec,
309 i_lnb_lof1, i_lnb_lof2, i_lnb_slof))
312 msg_Err( p_input, "frontend returned an unexpected event" );
313 close( p_satellite->i_handle );
318 msg_Err( p_input, "frontend returned no event" );
319 close( p_satellite->i_handle );
324 msg_Err( p_input, "frontend: timeout when polling for event" );
325 close( p_satellite->i_handle );
330 msg_Err( p_input, "an error occured when polling frontend device" );
331 close( p_satellite->i_handle );
336 msg_Err( p_input, "frontend returned a failure event" );
337 close( p_satellite->i_handle );
346 msg_Dbg( p_input, "setting filter on PAT" );
347 AllocateDemux( p_input, 0, PAT_TYPE );
349 if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
351 msg_Err( p_input, "could not initialize stream structure" );
352 close( p_satellite->i_handle );
357 vlc_mutex_lock( &p_input->stream.stream_lock );
359 p_input->stream.b_pace_control = 1;
360 p_input->stream.b_seekable = 0;
361 p_input->stream.p_selected_area->i_tell = 0;
363 vlc_mutex_unlock( &p_input->stream.stream_lock );
365 p_input->i_mtu = SATELLITE_READ_ONCE;
366 p_input->stream.i_method = INPUT_METHOD_SATELLITE;
371 /*****************************************************************************
372 * Close : Close the device
373 *****************************************************************************/
374 void E_(Close) ( vlc_object_t *p_this )
376 input_thread_t * p_input = (input_thread_t *)p_this;
377 thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
379 msg_Dbg( p_input, "unsetting filters on all pids" );
380 CloseProgram( p_input );
381 close( p_satellite->p_demux_handles[0].i_handle );
383 close( p_satellite->i_handle );
386 /*****************************************************************************
387 * SatelliteRead: reads data from the satellite card
388 *****************************************************************************/
389 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
392 thread_sat_data_t * p_satellite = (thread_sat_data_t *)p_input->p_access_data;
397 /* if not set, set filters to the PMTs */
398 /* This is kludgy and consumes way too much CPU power - the access
399 * module should have a callback from the demux when a new program
400 * is encountered. --Meuuh */
401 if ( !p_satellite->p_demux_handles[1].i_type )
403 int i_program = config_GetInt( p_input, "program" );
405 for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
407 /* Only set a filter on the selected program : some boards
408 * (read: Dreambox) only have 8 filters, so you don't want to
409 * spend them on unwanted PMTs. --Meuuh */
410 if ( (!i_program || p_input->stream.pp_programs[i]->i_number == i_program) )
412 msg_Dbg( p_input, "setting filter on PMT pid %d",
413 p_input->stream.pp_programs[i]->pp_es[0]->i_id );
414 AllocateDemux( p_input, p_input->stream.pp_programs[i]->pp_es[0]->i_id, PMT_TYPE );
419 i_ret = read( p_satellite->i_handle, p_buffer, i_len );
424 msg_Err( p_input, "read failed (%s)", strerror(errno) );
426 msg_Err( p_input, "read failed" );
433 /*****************************************************************************
434 * SatelliteSetArea : Does nothing
435 *****************************************************************************/
436 static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
441 /*****************************************************************************
442 * SatelliteSetProgram : Sets the card filters according to the
444 * and makes the appropriate changes to stream structure.
445 *****************************************************************************/
446 int SatelliteSetProgram( input_thread_t * p_input,
447 pgrm_descriptor_t * p_new_prg )
449 unsigned int i_es_index;
452 if ( p_input->stream.p_selected_program )
454 for ( i_es_index = 0 ; /* 0 should be the PMT */
455 i_es_index < p_input->stream.p_selected_program->
459 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
462 input_UnselectES( p_input , p_es );
468 msg_Dbg( p_input, "unsetting filters on all pids" );
469 CloseProgram( p_input );
470 msg_Dbg( p_input, "setting filter on PMT pid %d",
471 p_new_prg->pp_es[0]->i_id );
472 AllocateDemux( p_input, p_new_prg->pp_es[0]->i_id, PMT_TYPE );
474 for ( i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
476 #define p_es p_new_prg->pp_es[i_es_index]
477 switch( p_es->i_cat )
480 msg_Dbg(p_input, "setting filter on video ES 0x%x",
482 /* Always set the filter. This may seem a little odd, but
483 * it allows you to stream the video with demuxstream
484 * without having a decoder or a stream output behind.
485 * The result is you'll sometimes filter a PID which you
486 * don't really want, but in the most common cases it
487 * should be OK. --Meuuh */
488 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
489 input_SelectES( p_input , p_es );
493 msg_Dbg(p_input, "setting filter on audio ES 0x%x",
495 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
496 input_SelectES( p_input , p_es );
500 /* Do not select private streams. This is to avoid the
501 * limit of 8 filters on the Dreambox and possibly on
502 * other boards. We should probably change that to
503 * have the DVB subtitles, but filtering all private
504 * streams including DVB tables and padding seems
505 * nonsense to me. --Meuuh */
507 msg_Dbg(p_input, "setting filter on misc (0x%x) ES 0x%x",
510 AllocateDemux( p_input, p_es->i_id, ES_TYPE );
511 input_SelectES( p_input , p_es );
518 p_input->stream.p_selected_program = p_new_prg;
520 /* Update the navigation variables without triggering a callback */
521 val.i_int = p_new_prg->i_number;
522 var_Change( p_input, "program", VLC_VAR_SETVALUE, &val, NULL );
527 /*****************************************************************************
528 * SatelliteSeek: does nothing (not a seekable stream
529 *****************************************************************************/
530 static void SatelliteSeek( input_thread_t * p_input, off_t i_off )