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