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