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