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