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