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