]> git.sesse.net Git - vlc/blob - modules/access/dvb/linux_dvb.c
old dvb access: remove unused includes
[vlc] / modules / access / dvb / linux_dvb.c
1 /*****************************************************************************
2  * linux_dvb.c : functions to control a DVB card under Linux with v4l2
3  *****************************************************************************
4  * Copyright (C) 1998-2010 the VideoLAN team
5  *
6  * Authors: Damien Lucas <nitrox@via.ecp.fr>
7  *          Johan Bilien <jobi@via.ecp.fr>
8  *          Jean-Paul Saman <jpsaman _at_ videolan _dot_ org>
9  *          Christopher Ross <chris@tebibyte.org>
10  *          Christophe Massiot <massiot@via.ecp.fr>
11  *          David Kaplan <david@of1.org>
12  *
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 2 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.    See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software
25  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA    02111, USA.
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc_common.h>
33 #include <vlc_access.h>
34 #include <vlc_fs.h>
35
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/ioctl.h>
39 #include <fcntl.h>
40 #include <unistd.h>
41 #include <poll.h>
42
43 /* DVB Card Drivers */
44 #include <linux/dvb/version.h>
45 #include <linux/dvb/dmx.h>
46 #include <linux/dvb/frontend.h>
47
48 #include "dvb.h"
49 #include "scan.h"
50
51 #define DMX      "/dev/dvb/adapter%d/demux%d"
52 #define FRONTEND "/dev/dvb/adapter%d/frontend%d"
53 #define DVR      "/dev/dvb/adapter%d/dvr%d"
54
55 /*
56  * Frontends
57  */
58 struct frontend_t
59 {
60     fe_status_t i_last_status;
61     struct dvb_frontend_info info;
62 };
63
64 #define FRONTEND_LOCK_TIMEOUT 10000000 /* 10 s */
65
66 /* Local prototypes */
67 static int FrontendInfo( access_t * );
68 static int FrontendSetQPSK( access_t * );
69 static int FrontendSetQAM( access_t * );
70 static int FrontendSetOFDM( access_t * );
71 static int FrontendSetATSC( access_t * );
72
73 /*****************************************************************************
74  * FrontendOpen : Determine frontend device information and capabilities
75  *****************************************************************************/
76 int FrontendOpen( access_t *p_access )
77 {
78     access_sys_t *p_sys = p_access->p_sys;
79     frontend_t * p_frontend;
80     unsigned int i_adapter, i_device;
81     bool b_probe;
82     char frontend[128];
83
84     i_adapter = var_GetInteger( p_access, "dvb-adapter" );
85     i_device = var_GetInteger( p_access, "dvb-device" );
86     b_probe = var_GetBool( p_access, "dvb-probe" );
87
88     if( snprintf( frontend, sizeof(frontend), FRONTEND, i_adapter, i_device ) >= (int)sizeof(frontend) )
89     {
90         msg_Err( p_access, "snprintf() truncated string for FRONTEND" );
91         frontend[sizeof(frontend) - 1] = '\0';
92     }
93
94     p_sys->p_frontend = p_frontend = malloc( sizeof(frontend_t) );
95     if( !p_frontend )
96         return VLC_ENOMEM;
97
98     msg_Dbg( p_access, "Opening device %s", frontend );
99     if( (p_sys->i_frontend_handle = vlc_open(frontend, O_RDWR | O_NONBLOCK)) < 0 )
100     {
101         msg_Err( p_access, "FrontEndOpen: opening device failed (%m)" );
102         free( p_frontend );
103         return VLC_EGENERIC;
104     }
105
106     if( b_probe )
107     {
108         const char * psz_expected = NULL;
109         const char * psz_real;
110
111         if( FrontendInfo( p_access ) < 0 )
112         {
113             close( p_sys->i_frontend_handle );
114             free( p_frontend );
115             return VLC_EGENERIC;
116         }
117
118         switch( p_frontend->info.type )
119         {
120         case FE_OFDM:
121             psz_real = "DVB-T";
122             break;
123         case FE_QAM:
124             psz_real = "DVB-C";
125             break;
126         case FE_QPSK:
127             psz_real = "DVB-S";
128             break;
129         case FE_ATSC:
130             psz_real = "ATSC";
131             break;
132         default:
133             psz_real = "unknown";
134         }
135
136         /* Sanity checks */
137         if( (!strncmp( p_access->psz_access, "qpsk", 4 ) ||
138              !strncmp( p_access->psz_access, "dvb-s", 5 ) ||
139              !strncmp( p_access->psz_access, "satellite", 9 ) ) &&
140              (p_frontend->info.type != FE_QPSK) )
141         {
142             psz_expected = "DVB-S";
143         }
144         if( (!strncmp( p_access->psz_access, "cable", 5 ) ||
145              !strncmp( p_access->psz_access, "dvb-c", 5 ) ) &&
146              (p_frontend->info.type != FE_QAM) )
147         {
148             psz_expected = "DVB-C";
149         }
150         if( (!strncmp( p_access->psz_access, "terrestrial", 11 ) ||
151              !strncmp( p_access->psz_access, "dvb-t", 5 ) ) &&
152              (p_frontend->info.type != FE_OFDM) )
153         {
154             psz_expected = "DVB-T";
155         }
156
157         if( (!strncmp( p_access->psz_access, "usdigital", 9 ) ||
158              !strncmp( p_access->psz_access, "atsc", 4 ) ) &&
159              (p_frontend->info.type != FE_ATSC) )
160         {
161             psz_expected = "ATSC";
162         }
163
164         if( psz_expected != NULL )
165         {
166             msg_Err( p_access, "requested type %s not supported by %s tuner",
167                      psz_expected, psz_real );
168             close( p_sys->i_frontend_handle );
169             free( p_frontend );
170             return VLC_EGENERIC;
171         }
172     }
173     else /* no frontend probing is done so use default border values. */
174     {
175         msg_Dbg( p_access, "using default values for frontend info" );
176
177         msg_Dbg( p_access, "method of access is %s", p_access->psz_access );
178         p_frontend->info.type = FE_QPSK;
179         if( !strncmp( p_access->psz_access, "qpsk", 4 ) ||
180             !strncmp( p_access->psz_access, "dvb-s", 5 ) )
181             p_frontend->info.type = FE_QPSK;
182         else if( !strncmp( p_access->psz_access, "cable", 5 ) ||
183                  !strncmp( p_access->psz_access, "dvb-c", 5 ) )
184             p_frontend->info.type = FE_QAM;
185         else if( !strncmp( p_access->psz_access, "terrestrial", 11 ) ||
186                  !strncmp( p_access->psz_access, "dvb-t", 5 ) )
187             p_frontend->info.type = FE_OFDM;
188         else if( !strncmp( p_access->psz_access, "usdigital", 9 ) ||
189                  !strncmp( p_access->psz_access, "atsc", 4 ) )
190             p_frontend->info.type = FE_ATSC;
191     }
192
193     return VLC_SUCCESS;
194 }
195
196 /*****************************************************************************
197  * FrontendClose : Close the frontend
198  *****************************************************************************/
199 void FrontendClose( access_t *p_access )
200 {
201     access_sys_t *p_sys = p_access->p_sys;
202
203     if( p_sys->p_frontend )
204     {
205         close( p_sys->i_frontend_handle );
206         free( p_sys->p_frontend );
207
208         p_sys->p_frontend = NULL;
209     }
210 }
211
212 /*****************************************************************************
213  * FrontendSet : Tune !
214  *****************************************************************************/
215 int FrontendSet( access_t *p_access )
216 {
217     access_sys_t *p_sys = p_access->p_sys;
218
219     switch( p_sys->p_frontend->info.type )
220     {
221     /* DVB-S */
222     case FE_QPSK:
223         if( FrontendSetQPSK( p_access ) )
224         {
225             msg_Err( p_access, "DVB-S tuning error" );
226             return VLC_EGENERIC;
227         }
228         break;
229
230     /* DVB-C */
231     case FE_QAM:
232         if( FrontendSetQAM( p_access ) )
233         {
234             msg_Err( p_access, "DVB-C tuning error" );
235             return VLC_EGENERIC;
236         }
237         break;
238
239     /* DVB-T */
240     case FE_OFDM:
241         if( FrontendSetOFDM( p_access ) )
242         {
243             msg_Err( p_access, "DVB-T tuning error" );
244             return VLC_EGENERIC;
245         }
246         break;
247
248     /* ATSC */
249     case FE_ATSC:
250         if( FrontendSetATSC( p_access ) )
251         {
252             msg_Err( p_access, "ATSC tuning error" );
253             return VLC_EGENERIC;
254         }
255         break;
256
257     default:
258         msg_Err( p_access, "tuner type %s not supported",
259                  p_sys->p_frontend->info.name );
260         return VLC_EGENERIC;
261     }
262     p_sys->p_frontend->i_last_status = 0;
263     p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
264     return VLC_SUCCESS;
265 }
266
267 /*****************************************************************************
268  * FrontendPoll : Poll for frontend events
269  *****************************************************************************/
270 void FrontendPoll( access_t *p_access )
271 {
272     access_sys_t *p_sys = p_access->p_sys;
273     frontend_t * p_frontend = p_sys->p_frontend;
274     struct dvb_frontend_event event;
275     fe_status_t i_status, i_diff;
276
277     for( ;; )
278     {
279         if( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0 )
280         {
281             if( errno != EWOULDBLOCK )
282                 msg_Err( p_access, "frontend event error: %m" );
283             return;
284         }
285
286         i_status = event.status;
287         i_diff = i_status ^ p_frontend->i_last_status;
288         p_frontend->i_last_status = i_status;
289
290         {
291 #define IF_UP( x )                                                          \
292         }                                                                   \
293         if ( i_diff & (x) )                                                 \
294         {                                                                   \
295             if ( i_status & (x) )
296
297             IF_UP( FE_HAS_SIGNAL )
298                 msg_Dbg( p_access, "frontend has acquired signal" );
299             else
300                 msg_Dbg( p_access, "frontend has lost signal" );
301
302             IF_UP( FE_HAS_CARRIER )
303                 msg_Dbg( p_access, "frontend has acquired carrier" );
304             else
305                 msg_Dbg( p_access, "frontend has lost carrier" );
306
307             IF_UP( FE_HAS_VITERBI )
308                 msg_Dbg( p_access, "frontend has acquired stable FEC" );
309             else
310                 msg_Dbg( p_access, "frontend has lost FEC" );
311
312             IF_UP( FE_HAS_SYNC )
313                 msg_Dbg( p_access, "frontend has acquired sync" );
314             else
315                 msg_Dbg( p_access, "frontend has lost sync" );
316
317             IF_UP( FE_HAS_LOCK )
318             {
319                 frontend_statistic_t stat;
320
321                 msg_Dbg( p_access, "frontend has acquired lock" );
322                 p_sys->i_frontend_timeout = 0;
323
324                 /* Read some statistics */
325                 if( !FrontendGetStatistic( p_access, &stat ) )
326                 {
327                     if( stat.i_ber >= 0 )
328                         msg_Dbg( p_access, "- Bit error rate: %d", stat.i_ber );
329                     if( stat.i_signal_strenth >= 0 )
330                         msg_Dbg( p_access, "- Signal strength: %d", stat.i_signal_strenth );
331                     if( stat.i_snr >= 0 )
332                         msg_Dbg( p_access, "- SNR: %d", stat.i_snr );
333                 }
334             }
335             else
336             {
337                 msg_Dbg( p_access, "frontend has lost lock" );
338                 p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
339             }
340
341             IF_UP( FE_REINIT )
342             {
343                 /* The frontend was reinited. */
344                 msg_Warn( p_access, "reiniting frontend");
345                 FrontendSet( p_access );
346             }
347         }
348 #undef IF_UP
349     }
350 }
351
352 int FrontendGetStatistic( access_t *p_access, frontend_statistic_t *p_stat )
353 {
354     access_sys_t *p_sys = p_access->p_sys;
355     frontend_t * p_frontend = p_sys->p_frontend;
356
357     if( (p_frontend->i_last_status & FE_HAS_LOCK) == 0 )
358         return VLC_EGENERIC;
359
360     memset( p_stat, 0, sizeof(*p_stat) );
361     if( ioctl( p_sys->i_frontend_handle, FE_READ_BER, &p_stat->i_ber ) < 0 )
362         p_stat->i_ber = -1;
363     if( ioctl( p_sys->i_frontend_handle, FE_READ_SIGNAL_STRENGTH, &p_stat->i_signal_strenth ) < 0 )
364         p_stat->i_signal_strenth = -1;
365     if( ioctl( p_sys->i_frontend_handle, FE_READ_SNR, &p_stat->i_snr ) < 0 )
366         p_stat->i_snr = -1;
367
368     return VLC_SUCCESS;
369 }
370
371 void FrontendGetStatus( access_t *p_access, frontend_status_t *p_status )
372 {
373     access_sys_t *p_sys = p_access->p_sys;
374     frontend_t * p_frontend = p_sys->p_frontend;
375
376     p_status->b_has_signal = (p_frontend->i_last_status & FE_HAS_SIGNAL) != 0;
377     p_status->b_has_carrier = (p_frontend->i_last_status & FE_HAS_CARRIER) != 0;
378     p_status->b_has_lock = (p_frontend->i_last_status & FE_HAS_LOCK) != 0;
379 }
380
381 static int ScanParametersDvbS( access_t *p_access, scan_parameter_t *p_scan )
382 {
383     const frontend_t *p_frontend = p_access->p_sys->p_frontend;
384
385     memset( p_scan, 0, sizeof(*p_scan) );
386     p_scan->type = SCAN_DVB_S;
387
388     p_scan->frequency.i_min = p_frontend->info.frequency_min;
389     p_scan->frequency.i_max = p_frontend->info.frequency_max;
390     /* set satellite config file path */
391     p_scan->sat_info.psz_name = var_InheritString( p_access, "dvb-satellite" );
392
393     return VLC_SUCCESS;
394 }
395
396 static int ScanParametersDvbC( access_t *p_access, scan_parameter_t *p_scan )
397 {
398     const frontend_t *p_frontend = p_access->p_sys->p_frontend;
399
400     memset( p_scan, 0, sizeof(*p_scan) );
401     p_scan->type = SCAN_DVB_C;
402     p_scan->b_exhaustive = false;
403
404     /* */
405     p_scan->frequency.i_min = p_frontend->info.frequency_min;
406     p_scan->frequency.i_max = p_frontend->info.frequency_max;
407     p_scan->frequency.i_step = p_frontend->info.frequency_stepsize
408         ? p_frontend->info.frequency_stepsize : 166667;
409     p_scan->frequency.i_count = (p_scan->frequency.i_max-p_scan->frequency.i_min)/p_scan->frequency.i_step;
410
411     /* if user supplies modulation or frontend can do auto, don't scan them */
412     if( var_GetInteger( p_access, "dvb-modulation" ) ||
413         p_frontend->info.caps & FE_CAN_QAM_AUTO )
414     {
415         p_scan->b_modulation_set = true;
416     } else {
417         p_scan->b_modulation_set = false;
418         /* our scanning code flips modulation from 16..256 automaticly*/
419         p_scan->i_modulation = 0;
420     }
421
422     /* if user supplies symbolrate, don't scan those */
423     if( var_GetInteger( p_access, "dvb-srate" ) )
424         p_scan->b_symbolrate_set = true;
425     else
426         p_scan->b_symbolrate_set = false;
427
428     /* */
429     p_scan->bandwidth.i_min  = 6;
430     p_scan->bandwidth.i_max  = 8;
431     p_scan->bandwidth.i_step = 1;
432     p_scan->bandwidth.i_count = 3;
433     return VLC_SUCCESS;
434 }
435
436 static int ScanParametersDvbT( access_t *p_access, scan_parameter_t *p_scan )
437 {
438     const frontend_t *p_frontend = p_access->p_sys->p_frontend;
439
440     memset( p_scan, 0, sizeof(*p_scan) );
441     p_scan->type = SCAN_DVB_T;
442     p_scan->b_exhaustive = false;
443
444     /* */
445     p_scan->frequency.i_min = p_frontend->info.frequency_min;
446     p_scan->frequency.i_max = p_frontend->info.frequency_max;
447     p_scan->frequency.i_step = p_frontend->info.frequency_stepsize
448         ? p_frontend->info.frequency_stepsize : 166667;
449     p_scan->frequency.i_count = (p_scan->frequency.i_max-p_scan->frequency.i_min)/p_scan->frequency.i_step;
450
451     /* */
452     p_scan->bandwidth.i_min  = 6;
453     p_scan->bandwidth.i_max  = 8;
454     p_scan->bandwidth.i_step = 1;
455     p_scan->bandwidth.i_count = 3;
456     return VLC_SUCCESS;
457 }
458
459 int  FrontendGetScanParameter( access_t *p_access, scan_parameter_t *p_scan )
460 {
461     access_sys_t *p_sys = p_access->p_sys;
462     const frontend_t *p_frontend = p_sys->p_frontend;
463
464     if( p_frontend->info.type == FE_OFDM )              /* DVB-T */
465         return ScanParametersDvbT( p_access, p_scan );
466     else if( p_frontend->info.type == FE_QAM )          /* DVB-C */
467         return ScanParametersDvbC( p_access, p_scan );
468     else if( p_frontend->info.type == FE_QPSK )
469         return ScanParametersDvbS( p_access, p_scan );  /* DVB-S */
470
471     msg_Err( p_access, "frontend scanning not supported" );
472     return VLC_EGENERIC;
473 }
474
475 /*****************************************************************************
476  * FrontendInfo : Return information about given frontend
477  *****************************************************************************/
478 static int FrontendInfo( access_t *p_access )
479 {
480     access_sys_t *p_sys = p_access->p_sys;
481     frontend_t *p_frontend = p_sys->p_frontend;
482
483     /* Determine type of frontend */
484     if( ioctl( p_sys->i_frontend_handle, FE_GET_INFO, &p_frontend->info ) < 0 )
485     {
486         msg_Err( p_access, "frontend info request error: %m" );
487         return VLC_EGENERIC;
488     }
489
490     /* Print out frontend capabilities. */
491     msg_Dbg(p_access, "Frontend Info:" );
492     msg_Dbg(p_access, "  name = %s", p_frontend->info.name );
493     switch( p_frontend->info.type )
494     {
495         case FE_QPSK:
496             msg_Dbg( p_access, "  type = QPSK (DVB-S)" );
497             break;
498         case FE_QAM:
499             msg_Dbg( p_access, "  type = QAM (DVB-C)" );
500             break;
501         case FE_OFDM:
502             msg_Dbg( p_access, "  type = OFDM (DVB-T)" );
503             break;
504         case FE_ATSC:
505             msg_Dbg( p_access, "  type = ATSC (USA)" );
506             break;
507 #if 0 /* DVB_API_VERSION == 3 */
508         case FE_MEMORY:
509             msg_Dbg(p_access, "  type = MEMORY" );
510             break;
511         case FE_NET:
512             msg_Dbg(p_access, "  type = NETWORK" );
513             break;
514 #endif
515         default:
516             msg_Err( p_access, "  unknown frontend type (%d)",
517                      p_frontend->info.type );
518             return VLC_EGENERIC;
519     }
520     msg_Dbg(p_access, "  frequency_min = %u (kHz)",
521             p_frontend->info.frequency_min);
522     msg_Dbg(p_access, "  frequency_max = %u (kHz)",
523             p_frontend->info.frequency_max);
524     msg_Dbg(p_access, "  frequency_stepsize = %u",
525             p_frontend->info.frequency_stepsize);
526     msg_Dbg(p_access, "  frequency_tolerance = %u",
527             p_frontend->info.frequency_tolerance);
528     msg_Dbg(p_access, "  symbol_rate_min = %u (kHz)",
529             p_frontend->info.symbol_rate_min);
530     msg_Dbg(p_access, "  symbol_rate_max = %u (kHz)",
531             p_frontend->info.symbol_rate_max);
532     msg_Dbg(p_access, "  symbol_rate_tolerance (ppm) = %u",
533             p_frontend->info.symbol_rate_tolerance);
534     msg_Dbg(p_access, "  notifier_delay (ms) = %u",
535             p_frontend->info.notifier_delay );
536
537     msg_Dbg(p_access, "Frontend Info capability list:");
538     if( p_frontend->info.caps == FE_IS_STUPID)
539         msg_Dbg(p_access, "  no capabilities - frontend is stupid!");
540     if( p_frontend->info.caps & FE_CAN_INVERSION_AUTO)
541         msg_Dbg(p_access, "  inversion auto");
542     if( p_frontend->info.caps & FE_CAN_FEC_1_2)
543         msg_Dbg(p_access, "  forward error correction 1/2");
544     if( p_frontend->info.caps & FE_CAN_FEC_2_3)
545         msg_Dbg(p_access, "  forward error correction 2/3");
546     if( p_frontend->info.caps & FE_CAN_FEC_3_4)
547         msg_Dbg(p_access, "  forward error correction 3/4");
548     if( p_frontend->info.caps & FE_CAN_FEC_4_5)
549         msg_Dbg(p_access, "  forward error correction 4/5");
550     if( p_frontend->info.caps & FE_CAN_FEC_5_6)
551         msg_Dbg(p_access, "  forward error correction 5/6");
552     if( p_frontend->info.caps & FE_CAN_FEC_6_7)
553         msg_Dbg(p_access, "  forward error correction 6/7");
554     if( p_frontend->info.caps & FE_CAN_FEC_7_8)
555         msg_Dbg(p_access, "  forward error correction 7/8");
556     if( p_frontend->info.caps & FE_CAN_FEC_8_9)
557         msg_Dbg(p_access, "  forward error correction 8/9");
558     if( p_frontend->info.caps & FE_CAN_FEC_AUTO)
559         msg_Dbg(p_access, "  forward error correction auto");
560     if( p_frontend->info.caps & FE_CAN_QPSK)
561         msg_Dbg(p_access, "  QPSK modulation");
562     if( p_frontend->info.caps & FE_CAN_QAM_16)
563         msg_Dbg(p_access, "  QAM 16 modulation");
564     if( p_frontend->info.caps & FE_CAN_QAM_32)
565         msg_Dbg(p_access, "  QAM 32 modulation");
566     if( p_frontend->info.caps & FE_CAN_QAM_64)
567         msg_Dbg(p_access, "  QAM 64 modulation");
568     if( p_frontend->info.caps & FE_CAN_QAM_128)
569         msg_Dbg(p_access, "  QAM 128 modulation");
570     if( p_frontend->info.caps & FE_CAN_QAM_256)
571         msg_Dbg(p_access, "  QAM 256 modulation");
572     if( p_frontend->info.caps & FE_CAN_QAM_AUTO)
573         msg_Dbg(p_access, "  QAM auto modulation");
574     if( p_frontend->info.caps & FE_CAN_TRANSMISSION_MODE_AUTO)
575         msg_Dbg(p_access, "  transmission mode auto");
576     if( p_frontend->info.caps & FE_CAN_BANDWIDTH_AUTO)
577         msg_Dbg(p_access, "  bandwidth mode auto");
578     if( p_frontend->info.caps & FE_CAN_GUARD_INTERVAL_AUTO)
579         msg_Dbg(p_access, "  guard interval mode auto");
580     if( p_frontend->info.caps & FE_CAN_HIERARCHY_AUTO)
581         msg_Dbg(p_access, "  hierarchy mode auto");
582     if( p_frontend->info.caps & FE_CAN_8VSB)
583         msg_Dbg(p_access, "  8-level VSB modulation");
584     if( p_frontend->info.caps & FE_CAN_16VSB)
585         msg_Dbg(p_access, "  16-level VSB modulation");
586     if( p_frontend->info.caps & FE_HAS_EXTENDED_CAPS)
587         msg_Dbg(p_access, "  extended capabilities");
588     /* 3 capabilities that don't exist yet HERE */
589 #if (DVB_API_VERSION > 5) \
590  || ((DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 2))
591     if( p_frontend->info.caps & FE_CAN_TURBO_FEC)
592         msg_Dbg(p_access, "  Turbo FEC modulation");
593 #else
594 # warning Please update your Linux kernel headers!
595 #endif
596     if( p_frontend->info.caps & FE_CAN_2G_MODULATION)
597         msg_Dbg(p_access, "  2nd generation modulation (DVB-S2)");
598     /* FE_NEEDS_BENDING is deprecated */
599     if( p_frontend->info.caps & FE_CAN_RECOVER)
600         msg_Dbg(p_access, "  cable unplug recovery");
601     if( p_frontend->info.caps & FE_CAN_MUTE_TS)
602         msg_Dbg(p_access, "  spurious TS muting");
603    msg_Dbg(p_access, "End of capability list");
604
605     return VLC_SUCCESS;
606 }
607
608 /*****************************************************************************
609  * Decoding the DVB parameters (common)
610  *****************************************************************************/
611 static fe_spectral_inversion_t DecodeInversion( access_t *p_access )
612 {
613     int i_val;
614     fe_spectral_inversion_t fe_inversion = 0;
615
616     i_val = var_GetInteger( p_access, "dvb-inversion" );
617     msg_Dbg( p_access, "using inversion=%d", i_val );
618
619     switch( i_val )
620     {
621         case 0: fe_inversion = INVERSION_OFF; break;
622         case 1: fe_inversion = INVERSION_ON; break;
623         case 2: fe_inversion = INVERSION_AUTO; break;
624         default:
625             msg_Dbg( p_access, "dvb has inversion not set, using auto");
626             fe_inversion = INVERSION_AUTO;
627             break;
628     }
629     return fe_inversion;
630 }
631
632 static fe_code_rate_t DecodeFEC( access_t *p_access, const char *varname )
633 {
634     switch( var_GetInteger(p_access, varname) )
635     {
636         case 0:  return FEC_NONE;
637         case 1:  return FEC_1_2;
638         case 2:  return FEC_2_3;
639         case 3:  return FEC_3_4;
640         case 4:  return FEC_4_5;
641         case 5:  return FEC_5_6;
642         case 6:  return FEC_6_7;
643         case 7:  return FEC_7_8;
644         case 8:  return FEC_8_9;
645         case 9:  return FEC_AUTO;
646         default: return FEC_NONE;
647     }
648 }
649
650 static fe_modulation_t DecodeModulation( access_t *p_access,
651                                          fe_modulation_t def )
652 {
653     switch( var_GetInteger( p_access, "dvb-modulation" ) )
654     {
655         case -1:    return QPSK;
656         case 0:     return QAM_AUTO;
657         case 8:     return VSB_8;
658         case 16:    return QAM_16;
659         case 32:    return QAM_32;
660         case 64:    return QAM_64;
661         case 128:   return QAM_128;
662         case 256:   return QAM_256;
663         default:    return def;
664     }
665 }
666
667 /*****************************************************************************
668  * FrontendSetQPSK : controls the FE device
669  *****************************************************************************/
670 static fe_sec_voltage_t DecodeVoltage( access_t *p_access )
671 {
672     switch( var_GetInteger( p_access, "dvb-voltage" ) )
673     {
674         case 0:  return SEC_VOLTAGE_OFF;
675         case 13: return SEC_VOLTAGE_13;
676         case 18: return SEC_VOLTAGE_18;
677         default: return SEC_VOLTAGE_OFF;
678     }
679 }
680
681 static fe_sec_tone_mode_t DecodeTone( access_t *p_access )
682 {
683     switch( var_GetInteger( p_access, "dvb-tone" ) )
684     {
685         case 0:  return SEC_TONE_OFF;
686         case 1:  return SEC_TONE_ON;
687         default: return SEC_TONE_OFF;
688     }
689 }
690
691 struct diseqc_cmd_t
692 {
693     struct dvb_diseqc_master_cmd cmd;
694     uint32_t wait;
695 };
696
697 static int DoDiseqc( access_t *p_access )
698 {
699     access_sys_t *p_sys = p_access->p_sys;
700     int i_val;
701     bool b_val;
702     int i_frequency, i_lnb_slof;
703     fe_sec_voltage_t fe_voltage;
704     fe_sec_tone_mode_t fe_tone;
705
706     i_frequency = var_GetInteger( p_access, "dvb-frequency" );
707     i_lnb_slof = var_GetInteger( p_access, "dvb-lnb-slof" );
708
709     i_val = var_GetInteger( p_access, "dvb-tone" );
710     if( i_val == -1 /* auto */ )
711     {
712         if( i_frequency >= i_lnb_slof )
713             i_val = 1;
714         else
715             i_val = 0;
716         var_SetInteger( p_access, "dvb-tone", i_val );
717     }
718
719     fe_voltage = DecodeVoltage( p_access );
720     fe_tone = DecodeTone( p_access );
721
722     /* Switch off continuous tone. */
723     if( ioctl( p_sys->i_frontend_handle, FE_SET_TONE, SEC_TONE_OFF ) < 0 )
724     {
725         msg_Err( p_access, "switching tone %s error: %m", "off" );
726         return VLC_EGENERIC;
727     }
728
729     /* Configure LNB voltage. */
730     if( ioctl( p_sys->i_frontend_handle, FE_SET_VOLTAGE, fe_voltage ) < 0 )
731     {
732         msg_Err( p_access, "voltage error: %m" );
733         return VLC_EGENERIC;
734     }
735
736     b_val = var_GetBool( p_access, "dvb-high-voltage" );
737     if( ioctl( p_sys->i_frontend_handle,
738                FE_ENABLE_HIGH_LNB_VOLTAGE, b_val ) < 0 && b_val )
739     {
740         msg_Err( p_access, "high LNB voltage error: %m" );
741     }
742
743     /* Wait for at least 15 ms. */
744     msleep(15000);
745
746     i_val = var_GetInteger( p_access, "dvb-satno" );
747     if( i_val > 0 && i_val < 5 )
748     {
749         /* digital satellite equipment control,
750          * specification is available from http://www.eutelsat.com/
751          */
752
753         /* 1.x compatible equipment */
754         struct diseqc_cmd_t cmd =  { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
755
756         /* param: high nibble: reset bits, low nibble set bits,
757          * bits are: option, position, polarization, band
758          */
759         cmd.cmd.msg[3] = 0xf0 /* reset bits */
760                           | (((i_val - 1) * 4) & 0xc)
761                           | (fe_voltage == SEC_VOLTAGE_13 ? 0 : 2)
762                           | (fe_tone == SEC_TONE_ON ? 1 : 0);
763
764         if( ioctl( p_sys->i_frontend_handle, FE_DISEQC_SEND_MASTER_CMD,
765                    &cmd.cmd ) )
766         {
767             msg_Err( p_access, "master command sending error: %m" );
768             return VLC_EGENERIC;
769         }
770
771         msleep(15000 + cmd.wait * 1000);
772
773         /* A or B simple diseqc ("diseqc-compatible") */
774         if( ioctl( p_sys->i_frontend_handle, FE_DISEQC_SEND_BURST,
775                   ((i_val - 1) % 2) ? SEC_MINI_B : SEC_MINI_A ) )
776         {
777             msg_Err( p_access, "burst sending error: %m" );
778             return VLC_EGENERIC;
779         }
780
781         msleep(15000);
782     }
783
784     if( ioctl( p_sys->i_frontend_handle, FE_SET_TONE, fe_tone ) )
785     {
786         msg_Err( p_access, "switching tone %s error: %m",
787                  (fe_tone == SEC_TONE_ON) ? "on" : "off" );
788         return VLC_EGENERIC;
789     }
790
791     msleep(50000);
792     return 0;
793 }
794
795 static int FrontendSetQPSK( access_t *p_access )
796 {
797     access_sys_t *p_sys = p_access->p_sys;
798     struct dvb_frontend_parameters fep;
799     int i_val;
800     int i_frequency, i_lnb_slof = 0, i_lnb_lof1, i_lnb_lof2 = 0;
801
802     /* Prepare the fep structure */
803     i_frequency = var_GetInteger( p_access, "dvb-frequency" );
804
805     i_val = var_GetInteger( p_access, "dvb-lnb-lof1" );
806     if( i_val == 0 )
807     {
808         /* Automatic mode. */
809         if ( i_frequency >= 950000 && i_frequency <= 2150000 )
810         {
811             msg_Dbg( p_access, "frequency %d is in IF-band", i_frequency );
812             i_lnb_lof1 = 0;
813         }
814         else if ( i_frequency >= 2500000 && i_frequency <= 2700000 )
815         {
816             msg_Dbg( p_access, "frequency %d is in S-band", i_frequency );
817             i_lnb_lof1 = 3650000;
818         }
819         else if ( i_frequency >= 3400000 && i_frequency <= 4200000 )
820         {
821             msg_Dbg( p_access, "frequency %d is in C-band (lower)",
822                      i_frequency );
823             i_lnb_lof1 = 5150000;
824         }
825         else if ( i_frequency >= 4500000 && i_frequency <= 4800000 )
826         {
827             msg_Dbg( p_access, "frequency %d is in C-band (higher)",
828                      i_frequency );
829             i_lnb_lof1 = 5950000;
830         }
831         else if ( i_frequency >= 10700000 && i_frequency <= 13250000 )
832         {
833             msg_Dbg( p_access, "frequency %d is in Ku-band",
834                      i_frequency );
835             i_lnb_lof1 = 9750000;
836             i_lnb_lof2 = 10600000;
837             i_lnb_slof = 11700000;
838         }
839         else
840         {
841             msg_Err( p_access, "frequency %d is out of any known band",
842                      i_frequency );
843             msg_Err( p_access, "specify dvb-lnb-lof1 manually for the local "
844                      "oscillator frequency" );
845             return VLC_EGENERIC;
846         }
847         var_SetInteger( p_access, "dvb-lnb-lof1", i_lnb_lof1 );
848         var_SetInteger( p_access, "dvb-lnb-lof2", i_lnb_lof2 );
849         var_SetInteger( p_access, "dvb-lnb-slof", i_lnb_slof );
850     }
851     else
852     {
853         i_lnb_lof1 = i_val;
854         i_lnb_lof2 = var_GetInteger( p_access, "dvb-lnb-lof2" );
855         i_lnb_slof = var_GetInteger( p_access, "dvb-lnb-slof" );
856     }
857
858     if( i_lnb_slof && i_frequency >= i_lnb_slof )
859     {
860         i_frequency -= i_lnb_lof2;
861     }
862     else
863     {
864         i_frequency -= i_lnb_lof1;
865     }
866     fep.frequency = i_frequency >= 0 ? i_frequency : -i_frequency;
867
868     fep.inversion = DecodeInversion( p_access );
869
870     fep.u.qpsk.symbol_rate = var_GetInteger( p_access, "dvb-srate" );
871
872     fep.u.qpsk.fec_inner = DecodeFEC( p_access, "dvb-fec" );
873
874     if( DoDiseqc( p_access ) < 0 )
875     {
876         return VLC_EGENERIC;
877     }
878
879     /* Empty the event queue */
880     for( ; ; )
881     {
882         struct dvb_frontend_event event;
883         if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
884               && errno == EWOULDBLOCK )
885             break;
886     }
887
888     /* Now send it all to the frontend device */
889     if( ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep ) < 0 )
890     {
891         msg_Err( p_access, "frontend error: %m" );
892         return VLC_EGENERIC;
893     }
894
895     return VLC_SUCCESS;
896 }
897
898 /*****************************************************************************
899  * FrontendSetQAM : controls the FE device
900  *****************************************************************************/
901 static int FrontendSetQAM( access_t *p_access )
902 {
903     access_sys_t *p_sys = p_access->p_sys;
904     frontend_t *p_frontend = p_sys->p_frontend;
905     struct dvb_frontend_parameters fep;
906     unsigned int i_val;
907
908     /* Prepare the fep structure */
909
910     fep.frequency = var_GetInteger( p_access, "dvb-frequency" );
911
912     fep.inversion = DecodeInversion( p_access );
913
914     /* Default symbol-rate is for dvb-s, and doesn't fit
915      * for dvb-c, so if it's over the limit of frontend, default to
916      * somewhat common value
917      */
918     i_val = var_GetInteger( p_access, "dvb-srate" );
919     if( i_val < p_frontend->info.symbol_rate_max &&
920         i_val > p_frontend->info.symbol_rate_min )
921         fep.u.qam.symbol_rate = i_val;
922
923     fep.u.qam.fec_inner = DecodeFEC( p_access, "dvb-fec" );
924
925     fep.u.qam.modulation = DecodeModulation( p_access, QAM_AUTO );
926
927     /* Empty the event queue */
928     for( ; ; )
929     {
930         struct dvb_frontend_event event;
931         if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
932               && errno == EWOULDBLOCK )
933             break;
934     }
935
936     /* Now send it all to the frontend device */
937     if( ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep ) < 0 )
938     {
939         msg_Err( p_access, "frontend error: %m" );
940         return VLC_EGENERIC;
941     }
942
943     return VLC_SUCCESS;
944 }
945
946 /*****************************************************************************
947  * FrontendSetOFDM : controls the FE device
948  *****************************************************************************/
949 static fe_bandwidth_t DecodeBandwidth( access_t *p_access )
950 {
951     fe_bandwidth_t      fe_bandwidth = 0;
952     int i_bandwidth = var_GetInteger( p_access, "dvb-bandwidth" );
953
954     msg_Dbg( p_access, "using bandwidth=%d", i_bandwidth );
955
956     switch( i_bandwidth )
957     {
958         case 0: fe_bandwidth = BANDWIDTH_AUTO; break;
959         case 6: fe_bandwidth = BANDWIDTH_6_MHZ; break;
960         case 7: fe_bandwidth = BANDWIDTH_7_MHZ; break;
961         case 8: fe_bandwidth = BANDWIDTH_8_MHZ; break;
962         default:
963             msg_Dbg( p_access, "terrestrial dvb has bandwidth not set, using auto" );
964             fe_bandwidth = BANDWIDTH_AUTO;
965             break;
966     }
967     return fe_bandwidth;
968 }
969
970 static fe_transmit_mode_t DecodeTransmission( access_t *p_access )
971 {
972     fe_transmit_mode_t  fe_transmission = 0;
973     int i_transmission = var_GetInteger( p_access, "dvb-transmission" );
974
975     msg_Dbg( p_access, "using transmission=%d", i_transmission );
976
977     switch( i_transmission )
978     {
979         case 0: fe_transmission = TRANSMISSION_MODE_AUTO; break;
980         case 2: fe_transmission = TRANSMISSION_MODE_2K; break;
981         case 8: fe_transmission = TRANSMISSION_MODE_8K; break;
982         default:
983             msg_Dbg( p_access, "terrestrial dvb has transmission mode not set, using auto");
984             fe_transmission = TRANSMISSION_MODE_AUTO;
985             break;
986     }
987     return fe_transmission;
988 }
989
990 static fe_guard_interval_t DecodeGuardInterval( access_t *p_access )
991 {
992     fe_guard_interval_t fe_guard = 0;
993     int i_guard = var_GetInteger( p_access, "dvb-guard" );
994
995     msg_Dbg( p_access, "using guard=%d", i_guard );
996
997     switch( i_guard )
998     {
999         case 0: fe_guard = GUARD_INTERVAL_AUTO; break;
1000         case 4: fe_guard = GUARD_INTERVAL_1_4; break;
1001         case 8: fe_guard = GUARD_INTERVAL_1_8; break;
1002         case 16: fe_guard = GUARD_INTERVAL_1_16; break;
1003         case 32: fe_guard = GUARD_INTERVAL_1_32; break;
1004         default:
1005             msg_Dbg( p_access, "terrestrial dvb has guard interval not set, using auto");
1006             fe_guard = GUARD_INTERVAL_AUTO;
1007             break;
1008     }
1009     return fe_guard;
1010 }
1011
1012 static fe_hierarchy_t DecodeHierarchy( access_t *p_access )
1013 {
1014     fe_hierarchy_t      fe_hierarchy = 0;
1015     int i_hierarchy = var_GetInteger( p_access, "dvb-hierarchy" );
1016
1017     msg_Dbg( p_access, "using hierarchy=%d", i_hierarchy );
1018
1019     switch( i_hierarchy )
1020     {
1021         case -1: fe_hierarchy = HIERARCHY_NONE; break;
1022         case 0: fe_hierarchy = HIERARCHY_AUTO; break;
1023         case 1: fe_hierarchy = HIERARCHY_1; break;
1024         case 2: fe_hierarchy = HIERARCHY_2; break;
1025         case 4: fe_hierarchy = HIERARCHY_4; break;
1026         default:
1027             msg_Dbg( p_access, "terrestrial dvb has hierarchy not set, using auto");
1028             fe_hierarchy = HIERARCHY_AUTO;
1029             break;
1030     }
1031     return fe_hierarchy;
1032 }
1033
1034 static int FrontendSetOFDM( access_t * p_access )
1035 {
1036     access_sys_t *p_sys = p_access->p_sys;
1037     struct dvb_frontend_parameters fep;
1038
1039     /* Prepare the fep structure */
1040
1041     fep.frequency = var_GetInteger( p_access, "dvb-frequency" );
1042
1043     fep.inversion = DecodeInversion( p_access );
1044
1045     fep.u.ofdm.bandwidth = DecodeBandwidth( p_access );
1046     fep.u.ofdm.code_rate_HP = DecodeFEC( p_access, "dvb-code-rate-hp" );
1047     fep.u.ofdm.code_rate_LP = DecodeFEC( p_access, "dvb-code-rate-lp" );
1048     fep.u.ofdm.constellation = DecodeModulation( p_access, QAM_AUTO );
1049     fep.u.ofdm.transmission_mode = DecodeTransmission( p_access );
1050     fep.u.ofdm.guard_interval = DecodeGuardInterval( p_access );
1051     fep.u.ofdm.hierarchy_information = DecodeHierarchy( p_access );
1052
1053     /* Empty the event queue */
1054     for( ; ; )
1055     {
1056         struct dvb_frontend_event event;
1057         if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
1058               && errno == EWOULDBLOCK )
1059             break;
1060     }
1061
1062     /* Now send it all to the frontend device */
1063     if( ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep ) < 0 )
1064     {
1065         msg_Err( p_access, "frontend error: %m" );
1066         return VLC_EGENERIC;
1067     }
1068
1069     return VLC_SUCCESS;
1070 }
1071
1072 /*****************************************************************************
1073  * FrontendSetATSC : controls the FE device
1074  *****************************************************************************/
1075 static int FrontendSetATSC( access_t *p_access )
1076 {
1077     access_sys_t *p_sys = p_access->p_sys;
1078     struct dvb_frontend_parameters fep;
1079
1080     /* Prepare the fep structure */
1081
1082     fep.frequency = var_GetInteger( p_access, "dvb-frequency" );
1083
1084     fep.u.vsb.modulation = DecodeModulation( p_access, VSB_8 );
1085
1086     /* Empty the event queue */
1087     for( ; ; )
1088     {
1089         struct dvb_frontend_event event;
1090         if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
1091               && errno == EWOULDBLOCK )
1092             break;
1093     }
1094
1095     /* Now send it all to the frontend device */
1096     if( ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep ) < 0 )
1097     {
1098         msg_Err( p_access, "frontend error: %m" );
1099         return VLC_EGENERIC;
1100     }
1101
1102     return VLC_SUCCESS;
1103 }
1104
1105
1106 /*
1107  * Demux
1108  */
1109
1110 /*****************************************************************************
1111  * DMXSetFilter : controls the demux to add a filter
1112  *****************************************************************************/
1113 int DMXSetFilter( access_t * p_access, int i_pid, int * pi_fd, int i_type )
1114 {
1115     struct dmx_pes_filter_params s_filter_params;
1116     unsigned int i_adapter, i_device;
1117     char dmx[128];
1118
1119     i_adapter = var_GetInteger( p_access, "dvb-adapter" );
1120     i_device = var_GetInteger( p_access, "dvb-device" );
1121
1122     if( snprintf( dmx, sizeof(dmx), DMX, i_adapter, i_device )
1123             >= (int)sizeof(dmx) )
1124     {
1125         msg_Err( p_access, "snprintf() truncated string for DMX" );
1126         dmx[sizeof(dmx) - 1] = '\0';
1127     }
1128
1129     msg_Dbg( p_access, "Opening device %s", dmx );
1130     if( (*pi_fd = vlc_open(dmx, O_RDWR)) < 0 )
1131     {
1132         msg_Err( p_access, "DMXSetFilter: opening device failed (%m)" );
1133         return VLC_EGENERIC;
1134     }
1135
1136     /* We fill the DEMUX structure : */
1137     s_filter_params.pid     =   i_pid;
1138     s_filter_params.input   =   DMX_IN_FRONTEND;
1139     s_filter_params.output  =   DMX_OUT_TS_TAP;
1140     s_filter_params.flags   =   DMX_IMMEDIATE_START;
1141
1142     switch ( i_type )
1143     {   /* First device */
1144         case 1:
1145             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO0 for PID %d", i_pid);
1146             s_filter_params.pes_type = DMX_PES_VIDEO0;
1147             break;
1148         case 2:
1149             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO0 for PID %d", i_pid);
1150             s_filter_params.pes_type = DMX_PES_AUDIO0;
1151             break;
1152         case 3:
1153             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT0 for PID %d", i_pid);
1154             s_filter_params.pes_type = DMX_PES_TELETEXT0;
1155             break;
1156         case 4:
1157             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE0 for PID %d", i_pid);
1158             s_filter_params.pes_type = DMX_PES_SUBTITLE0;
1159             break;
1160         case 5:
1161             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR0 for PID %d", i_pid);
1162             s_filter_params.pes_type = DMX_PES_PCR0;
1163             break;
1164         /* Second device */
1165         case 6:
1166             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO1 for PID %d", i_pid);
1167             s_filter_params.pes_type = DMX_PES_VIDEO1;
1168             break;
1169         case 7:
1170             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO1 for PID %d", i_pid);
1171             s_filter_params.pes_type = DMX_PES_AUDIO1;
1172             break;
1173         case 8:
1174             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT1 for PID %d", i_pid);
1175             s_filter_params.pes_type = DMX_PES_TELETEXT1;
1176             break;
1177         case 9:
1178             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE1 for PID %d", i_pid);
1179             s_filter_params.pes_type = DMX_PES_SUBTITLE1;
1180             break;
1181         case 10:
1182             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR1 for PID %d", i_pid);
1183             s_filter_params.pes_type = DMX_PES_PCR1;
1184             break;
1185         /* Third device */
1186         case 11:
1187             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO2 for PID %d", i_pid);
1188             s_filter_params.pes_type = DMX_PES_VIDEO2;
1189             break;
1190         case 12:
1191             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO2 for PID %d", i_pid);
1192             s_filter_params.pes_type = DMX_PES_AUDIO2;
1193             break;
1194         case 13:
1195             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT2 for PID %d", i_pid);
1196             s_filter_params.pes_type = DMX_PES_TELETEXT2;
1197             break;
1198         case 14:
1199             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE2 for PID %d", i_pid);
1200             s_filter_params.pes_type = DMX_PES_SUBTITLE2;
1201             break;
1202         case 15:
1203             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR2 for PID %d", i_pid);
1204             s_filter_params.pes_type = DMX_PES_PCR2;
1205             break;
1206         /* Forth device */
1207         case 16:
1208             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO3 for PID %d", i_pid);
1209             s_filter_params.pes_type = DMX_PES_VIDEO3;
1210             break;
1211         case 17:
1212             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO3 for PID %d", i_pid);
1213             s_filter_params.pes_type = DMX_PES_AUDIO3;
1214             break;
1215         case 18:
1216             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT3 for PID %d", i_pid);
1217             s_filter_params.pes_type = DMX_PES_TELETEXT3;
1218             break;
1219         case 19:
1220             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE3 for PID %d", i_pid);
1221             s_filter_params.pes_type = DMX_PES_SUBTITLE3;
1222             break;
1223         case 20:
1224             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR3 for PID %d", i_pid);
1225             s_filter_params.pes_type = DMX_PES_PCR3;
1226             break;
1227         /* Usually used by Nova cards */
1228         case 21:
1229         default:
1230             msg_Dbg(p_access, "DMXSetFilter: DMX_PES_OTHER for PID %d", i_pid);
1231             s_filter_params.pes_type = DMX_PES_OTHER;
1232             break;
1233     }
1234
1235     /* We then give the order to the device : */
1236     if( ioctl( *pi_fd, DMX_SET_PES_FILTER, &s_filter_params ) )
1237     {
1238         msg_Err( p_access, "setting demux PES filter failed: %m" );
1239         return VLC_EGENERIC;
1240     }
1241     return VLC_SUCCESS;
1242 }
1243
1244 /*****************************************************************************
1245  * DMXUnsetFilter : removes a filter
1246  *****************************************************************************/
1247 int DMXUnsetFilter( access_t * p_access, int i_fd )
1248 {
1249     if( ioctl( i_fd, DMX_STOP ) < 0 )
1250     {
1251         msg_Err( p_access, "stopping demux failed: %m" );
1252         return VLC_EGENERIC;
1253     }
1254
1255     msg_Dbg( p_access, "DMXUnsetFilter: closing demux %d", i_fd );
1256     close( i_fd );
1257     return VLC_SUCCESS;
1258 }
1259
1260
1261 /*
1262  * DVR device
1263  */
1264
1265 /*****************************************************************************
1266  * DVROpen :
1267  *****************************************************************************/
1268 int DVROpen( access_t * p_access )
1269 {
1270     access_sys_t *p_sys = p_access->p_sys;
1271     unsigned int i_adapter, i_device;
1272     char dvr[128];
1273
1274     i_adapter = var_GetInteger( p_access, "dvb-adapter" );
1275     i_device = var_GetInteger( p_access, "dvb-device" );
1276
1277     if( snprintf( dvr, sizeof(dvr), DVR, i_adapter, i_device )
1278             >= (int)sizeof(dvr) )
1279     {
1280         msg_Err( p_access, "snprintf() truncated string for DVR" );
1281         dvr[sizeof(dvr) - 1] = '\0';
1282     }
1283
1284     msg_Dbg( p_access, "Opening device %s", dvr );
1285     if( (p_sys->i_handle = vlc_open(dvr, O_RDONLY)) < 0 )
1286     {
1287         msg_Err( p_access, "DVROpen: opening device failed (%m)" );
1288         return VLC_EGENERIC;
1289     }
1290
1291     if( fcntl( p_sys->i_handle, F_SETFL, O_NONBLOCK ) == -1 )
1292     {
1293         msg_Warn( p_access, "DVROpen: couldn't set non-blocking mode (%m)" );
1294     }
1295
1296     return VLC_SUCCESS;
1297 }
1298
1299 /*****************************************************************************
1300  * DVRClose :
1301  *****************************************************************************/
1302 void DVRClose( access_t * p_access )
1303 {
1304     access_sys_t *p_sys = p_access->p_sys;
1305
1306     close( p_sys->i_handle );
1307 }