]> git.sesse.net Git - vlc/blob - modules/access/dvb/access.c
Tuning succeeds, but have no audio yet. Major cleanup of code.
[vlc] / modules / access / dvb / access.c
1 /*****************************************************************************
2  * access.c: DVB card input v4l2 only
3  *****************************************************************************
4  * Copyright (C) 1998-2003 VideoLAN
5  *
6  * Authors: Johan Bilien <jobi@via.ecp.fr>
7  *          Jean-Paul Saman <saman@natlab.research.philips.com>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>
30
31 #include <vlc/vlc.h>
32 #include <vlc/input.h>
33
34 #include "../../demux/mpeg/system.h"
35
36 #ifdef HAVE_UNISTD_H
37 #   include <unistd.h>
38 #endif
39
40 #include <fcntl.h>
41 #include <sys/types.h>
42
43 #ifdef HAVE_ERRNO_H
44 #    include <string.h>
45 #    include <errno.h>
46 #endif
47
48 #ifdef STRNCASECMP_IN_STRINGS_H
49 #   include <strings.h>
50 #endif
51
52 /* DVB Card Drivers */
53 #include <linux/dvb/dmx.h>
54 #include <linux/dvb/frontend.h>
55
56 #include "dvb.h"
57
58 #define SATELLITE_READ_ONCE 3
59
60 /*****************************************************************************
61  * Local prototypes
62  *****************************************************************************/
63 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
64                               size_t i_len);
65 static int     SatelliteSetArea    ( input_thread_t *, input_area_t * );
66 static int     SatelliteSetProgram ( input_thread_t *, pgrm_descriptor_t * );
67 static void    SatelliteSeek       ( input_thread_t *, off_t );
68
69 /*****************************************************************************
70  * Open: open the frontend device
71  *****************************************************************************/
72 int E_(Open) ( vlc_object_t *p_this )
73 {
74     struct dvb_frontend_info frontend_info;
75     struct dvb_frontend_parameters fep;
76     input_thread_t *    p_input = (input_thread_t *)p_this;
77     input_socket_t *    p_satellite;
78     char *              psz_parser;
79     char *              psz_next;
80     int                 i_fd = 0;
81                 unsigned int                            u_adapter = 1;
82                 unsigned int                            u_device = 0;
83     unsigned int        u_freq = 0;
84     unsigned int        u_srate = 0;
85     vlc_bool_t          b_polarisation = 0;
86     int                 i_fec = 0;
87     fe_code_rate_t      fe_fec = FEC_NONE;
88     vlc_bool_t          b_diseqc;
89     vlc_bool_t                                  b_probe;
90     int                 i_lnb_lof1;
91     int                 i_lnb_lof2;
92     int                 i_lnb_slof;
93                 char                                                            dvr[] = DVR;
94                 char                                                            frontend[] = FRONTEND;
95                 int                                                                     i_len = 0;
96
97     /* parse the options passed in command line : */
98     psz_parser = strdup( p_input->psz_name );
99
100     if( !psz_parser )
101     {
102         return( -1 );
103     }
104
105     // Get adapter and device number to use for this dvb card
106     u_adapter = config_GetInt( p_input, "adapter" );
107     u_device  = config_GetInt( p_input, "device" );
108
109     /* Determine frontend device information and capabilities */
110     b_probe = config_GetInt( p_input, "probe" );
111     if (b_probe)
112           {
113         if ( ioctl_InfoFrontend(p_input, &frontend_info, u_adapter, u_device) < 0 )
114         {
115                 msg_Err( p_input, "(access) cannot determine frontend info" );
116             return -1;
117         }
118         if (frontend_info.type != FE_QPSK)
119         {
120             msg_Err( p_input, "frontend not of type satellite" );
121             return -1;
122         }
123     }
124           else /* no frontend probing is done so use default values. */
125                 {
126                           int i_len;
127                           
128                           msg_Dbg( p_input, "using default values for frontend info" );
129                   i_len = sizeof(FRONTEND);
130                 if (snprintf(frontend, sizeof(FRONTEND), FRONTEND, u_adapter, u_device) >= i_len)
131                 {
132                   msg_Err( p_input, "snprintf() truncated string for FRONTEND" );
133                         frontend[sizeof(FRONTEND)] = '\0';
134         }
135                           strncpy(frontend_info.name, frontend, 128);
136                           frontend_info.type = FE_QPSK;
137           frontend_info.frequency_max = 12999;
138         frontend_info.frequency_min = 10000;
139                                 frontend_info.symbol_rate_max = 30000;
140         frontend_info.symbol_rate_min = 1000;
141                                 /* b_polarisation */
142     }
143
144     /* Register Callback functions */
145     p_input->pf_read = SatelliteRead;
146     p_input->pf_set_program = SatelliteSetProgram;
147     p_input->pf_set_area = SatelliteSetArea;
148     p_input->pf_seek = SatelliteSeek;
149
150     u_freq = (unsigned int)strtol( psz_parser, &psz_next, 10 );
151     if( *psz_next )
152     {
153         psz_parser = psz_next + 1;
154         b_polarisation = (vlc_bool_t)strtol( psz_parser, &psz_next, 10 );
155         if( *psz_next )
156         {
157             psz_parser = psz_next + 1;
158             i_fec = (int)strtol( psz_parser, &psz_next, 10 );
159             if( *psz_next )
160             {
161                 psz_parser = psz_next + 1;
162                 u_srate = (unsigned int)strtol( psz_parser, &psz_next, 10 );
163             }
164         }
165     }
166
167     if ( ((u_freq) > frontend_info.frequency_max) ||
168          ((u_freq) < frontend_info.frequency_min) )
169     {
170         msg_Warn( p_input, "invalid frequency %d, using default one", u_freq );
171         u_freq = config_GetInt( p_input, "frequency" );
172         if ( ((u_freq) > frontend_info.frequency_max) ||
173              ((u_freq) < frontend_info.frequency_min) )
174         {
175             msg_Err( p_input, "invalid default frequency" );
176             return -1;
177         }
178     }
179
180     if ( ((u_srate) > frontend_info.symbol_rate_max) ||
181          ((u_srate) < frontend_info.symbol_rate_min) )
182     {
183         msg_Warn( p_input, "invalid symbol rate, using default one" );
184         u_srate = config_GetInt( p_input, "symbol-rate" );
185         if ( ((u_srate) > frontend_info.symbol_rate_max) ||
186              ((u_srate) < frontend_info.symbol_rate_min) )
187         {
188             msg_Err( p_input, "invalid default symbol rate" );
189             return -1;
190         }
191     }
192
193     if( b_polarisation && (b_polarisation != 1) )
194     {
195         msg_Warn( p_input, "invalid polarization, using default one" );
196         b_polarisation = config_GetInt( p_input, "polarization" );
197         if( b_polarisation && b_polarisation != 1 )
198         {
199             msg_Err( p_input, "invalid default polarization" );
200             return -1;
201         }
202     }
203
204     if( (i_fec > 9) || (i_fec < 1) )
205     {
206         msg_Warn( p_input, "invalid FEC, using default one" );
207         i_fec = config_GetInt( p_input, "fec" );
208         if( (i_fec > 9) || (i_fec < 1) )
209         {
210             msg_Err( p_input, "invalid default FEC" );
211             return -1;
212         }
213     }
214
215     switch( i_fec )
216     {
217         case 1:
218             fe_fec = FEC_1_2;
219             break;
220         case 2:
221             fe_fec = FEC_2_3;
222             break;
223         case 3:
224             fe_fec = FEC_3_4;
225             break;
226         case 4:
227             fe_fec = FEC_4_5;
228             break;
229         case 5:
230             fe_fec = FEC_5_6;
231             break;
232         case 6:
233             fe_fec = FEC_6_7;
234             break;
235         case 7:
236             fe_fec = FEC_7_8;
237             break;
238         case 8:
239             fe_fec = FEC_8_9;
240             break;
241         case 9:
242             fe_fec = FEC_AUTO;
243             break;
244         default:
245             /* cannot happen */
246             fe_fec = FEC_NONE;
247             msg_Err( p_input, "invalid FEC (unknown)" );
248             break;
249     }
250
251     switch( frontend_info.type )
252     {
253         case FE_QPSK:
254             fep.frequency = u_freq * 1000;
255             fep.inversion = INVERSION_AUTO;
256             fep.u.qpsk.symbol_rate = u_srate * 1000;
257             fep.u.qpsk.fec_inner = fe_fec;
258             msg_Dbg( p_input, "satellite frontend found on %s", frontend_info.name );
259             break;
260         case FE_QAM:
261             msg_Dbg( p_input, "cable frontend found on %s", frontend_info.name );
262             break;
263         case FE_OFDM:
264             msg_Dbg( p_input, "terrestrial frontend found on %s", frontend_info.name );
265             break;
266         default:
267             msg_Err( p_input, "Could not determine frontend type on %s", frontend_info.name );
268             return -1;
269     }
270
271     /* Initialise structure */
272     p_satellite = malloc( sizeof( input_socket_t ) );
273
274     if( p_satellite == NULL )
275     {
276         msg_Err( p_input, "out of memory" );
277         return -1;
278     }
279
280     p_input->p_access_data = (void *)p_satellite;
281
282     /* Open the DVR device */
283           i_len = sizeof(DVR);
284                 if (snprintf(dvr, sizeof(DVR), DVR, u_adapter, u_device) >= i_len)
285                 {
286                   msg_Err( p_input, "snprintf() truncated string for DVR" );
287                         dvr[sizeof(DVR)] = '\0';
288     }
289     msg_Dbg( p_input, "opening DVR device '%s'", dvr );
290
291     if( (p_satellite->i_handle = open( dvr,
292                                    /*O_NONBLOCK | O_LARGEFILE*/0 )) == (-1) )
293     {
294 #   ifdef HAVE_ERRNO_H
295         msg_Warn( p_input, "cannot open `%s' (%s)", dvr, strerror(errno) );
296 #   else
297         msg_Warn( p_input, "cannot open `%s'", dvr );
298 #   endif
299         free( p_satellite );
300         return -1;
301     }
302
303     /* Get antenna configuration options */
304     b_diseqc = config_GetInt( p_input, "diseqc" );
305     i_lnb_lof1 = config_GetInt( p_input, "lnb-lof1" );
306     i_lnb_lof2 = config_GetInt( p_input, "lnb-lof2" );
307     i_lnb_slof = config_GetInt( p_input, "lnb-slof" );
308
309     /* Initialize the Satellite Card */
310     msg_Dbg( p_input, "initializing Sat Card with Freq: %u, Pol: %d, "
311                       "FEC: %d, Srate: %u", u_freq, b_polarisation, fe_fec, u_srate );
312
313     switch (ioctl_SetQPSKFrontend (p_input, fep, b_polarisation, u_adapter, u_device ))
314     {
315         case -2:
316             msg_Err( p_input, "frontend returned an unexpected event" );
317             close( p_satellite->i_handle );
318             free( p_satellite );
319             return -1;
320         case -3:
321             msg_Err( p_input, "frontend returned no event" );
322             close( p_satellite->i_handle );
323             free( p_satellite );
324             return -1;
325         case -4:
326             msg_Err( p_input, "frontend: timeout when polling for event" );
327             close( p_satellite->i_handle );
328             free( p_satellite );
329             return -1;
330         case -5:
331             msg_Err( p_input, "an error occured when polling frontend device" );
332             close( p_satellite->i_handle );
333             free( p_satellite );
334             return -1;
335         case -1:
336             msg_Err( p_input, "frontend returned a failure event" );
337             close( p_satellite->i_handle );
338             free( p_satellite );
339             return -1;
340         default:
341             break;
342     }
343
344     msg_Dbg( p_input, "setting filter on PAT" );
345
346     if ( ioctl_SetDMXFilter(p_input, 0, &i_fd, 3, u_adapter, u_device ) < 0 )
347     {
348 #   ifdef HAVE_ERRNO_H
349         msg_Err( p_input, "an error occured when setting filter on PAT (%s)", strerror(errno) );
350 #   else
351         msg_Err( p_input, "an error occured when setting filter on PAT" );
352 #   endif        
353         close( p_satellite->i_handle );
354         free( p_satellite );
355         return -1;
356     }
357
358     if( input_InitStream( p_input, sizeof( stream_ts_data_t ) ) == -1 )
359     {
360         msg_Err( p_input, "could not initialize stream structure" );
361         close( p_satellite->i_handle );
362         free( p_satellite );
363         return( -1 );
364     }
365
366     vlc_mutex_lock( &p_input->stream.stream_lock );
367
368     p_input->stream.b_pace_control = 1;
369     p_input->stream.b_seekable = 0;
370     p_input->stream.p_selected_area->i_tell = 0;
371
372     vlc_mutex_unlock( &p_input->stream.stream_lock );
373
374     p_input->i_mtu = SATELLITE_READ_ONCE * TS_PACKET_SIZE;
375     p_input->stream.i_method = INPUT_METHOD_SATELLITE;
376
377     return 0;
378 }
379
380 /*****************************************************************************
381  * Close : Close the device
382  *****************************************************************************/
383 void E_(Close) ( vlc_object_t *p_this )
384 {
385     input_thread_t *    p_input = (input_thread_t *)p_this;
386     input_socket_t *    p_satellite;
387     unsigned int        i_es_index;
388
389     if ( p_input->stream.p_selected_program )
390     {
391         for ( i_es_index = 1 ;
392                 i_es_index < p_input->stream.p_selected_program->i_es_number;
393                 i_es_index ++ )
394         {
395 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
396             if ( p_es->p_decoder_fifo )
397             {
398                 ioctl_UnsetDMXFilter(p_input, p_es->i_demux_fd );
399             }
400 #undef p_es
401         }
402     }
403
404     p_satellite = (input_socket_t *)p_input;
405     close( p_satellite->i_handle );
406 }
407
408 /*****************************************************************************
409  * SatelliteRead: reads data from the satellite card
410  *****************************************************************************/
411 static ssize_t SatelliteRead( input_thread_t * p_input, byte_t * p_buffer,
412                               size_t i_len )
413 {
414     input_socket_t * p_access_data = (input_socket_t *)p_input->p_access_data;
415     ssize_t i_ret;
416                 unsigned int                            u_adapter = 1;
417                 unsigned int                      u_device = 0;
418     unsigned int i;
419
420     // Get adapter and device number to use for this dvb card
421     u_adapter = config_GetInt( p_input, "adapter" );
422     u_device  = config_GetInt( p_input, "device" );
423
424     /* if not set, set filters to the PMTs */
425     for( i = 0; i < p_input->stream.i_pgrm_number; i++ )
426     {
427         if ( p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd == 0 )
428         {
429             ioctl_SetDMXFilter(p_input, p_input->stream.pp_programs[i]->pp_es[0]->i_id,
430                        &p_input->stream.pp_programs[i]->pp_es[0]->i_demux_fd,
431                        3, u_adapter, u_device );
432         }
433     }
434
435     i_ret = read( p_access_data->i_handle, p_buffer, i_len );
436  
437     if( i_ret < 0 )
438     {
439 #   ifdef HAVE_ERRNO_H
440         msg_Err( p_input, "read failed (%s)", strerror(errno) );
441 #   else
442         msg_Err( p_input, "read failed" );
443 #   endif
444     }
445
446     return i_ret;
447 }
448
449 /*****************************************************************************
450  * SatelliteSetArea : Does nothing
451  *****************************************************************************/
452 static int SatelliteSetArea( input_thread_t * p_input, input_area_t * p_area )
453 {
454     return -1;
455 }
456
457 /*****************************************************************************
458  * SatelliteSetProgram : Sets the card filters according to the
459  *                 selected program,
460  *                 and makes the appropriate changes to stream structure.
461  *****************************************************************************/
462 int SatelliteSetProgram( input_thread_t    * p_input,
463                                                                                            pgrm_descriptor_t * p_new_prg )
464 {
465     unsigned int i_es_index;
466                 unsigned int u_adapter = 1;
467                 unsigned int u_device = 0;
468
469     // Get adapter and device number to use for this dvb card
470     u_adapter = config_GetInt( p_input, "adapter" );
471     u_device  = config_GetInt( p_input, "device" );
472
473     if ( p_input->stream.p_selected_program )
474     {
475         for ( i_es_index = 1 ; /* 0 should be the PMT */
476                 i_es_index < p_input->stream.p_selected_program->i_es_number ;
477                 i_es_index ++ )
478         {
479 #define p_es p_input->stream.p_selected_program->pp_es[i_es_index]
480             if ( p_es->p_decoder_fifo )
481             {
482                 input_UnselectES( p_input , p_es );
483             }
484             if ( p_es->i_demux_fd )
485             {
486                 ioctl_UnsetDMXFilter(p_input, p_es->i_demux_fd );
487                 p_es->i_demux_fd = 0;
488             }
489 #undef p_es
490         }
491     }
492
493     for (i_es_index = 1 ; i_es_index < p_new_prg->i_es_number ; i_es_index ++ )
494     {
495 #define p_es p_new_prg->pp_es[i_es_index]
496         switch( p_es->i_cat )
497         {
498             case MPEG1_VIDEO_ES:
499             case MPEG2_VIDEO_ES:
500                 if ( input_SelectES( p_input , p_es ) == 0 )
501                 {
502                     ioctl_SetDMXFilter(p_input, p_es->i_id, &p_es->i_demux_fd, 1, u_adapter, u_device);
503                 }
504                 break;
505             case MPEG1_AUDIO_ES:
506             case MPEG2_AUDIO_ES:
507                 if ( input_SelectES( p_input , p_es ) == 0 )
508                 {
509                     ioctl_SetDMXFilter(p_input, p_es->i_id, &p_es->i_demux_fd, 2, u_adapter, u_device);
510                     input_SelectES( p_input , p_es );
511                 }
512                 break;
513             default:
514                 ioctl_SetDMXFilter(p_input, p_es->i_id, &p_es->i_demux_fd, 3, u_adapter, u_device);
515                 input_SelectES( p_input , p_es );
516                 break;
517 #undef p_es
518         }
519     }
520
521     p_input->stream.p_selected_program = p_new_prg;
522
523     return 0;
524 }
525
526 /*****************************************************************************
527  * SatelliteSeek: does nothing (not a seekable stream
528  *****************************************************************************/
529 static void SatelliteSeek( input_thread_t * p_input, off_t i_off )
530 {
531     ;
532 }
533