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