1 /*****************************************************************************
2 * linux_dvb.c : functions to control a DVB card under Linux with v4l2
3 *****************************************************************************
4 * Copyright (C) 1998-2004 VideoLAN
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>
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.
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.
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 *****************************************************************************/
28 #include <vlc/input.h>
30 #include <sys/ioctl.h>
33 #include <sys/types.h>
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>
49 #define DMX_BUFFER_SIZE (1024 * 1024)
50 #define CA_MAX_STATE_RETRY 5
58 struct dvb_frontend_info info;
61 /* Local prototypes */
62 static int FrontendInfo( access_t * );
63 static int FrontendSetQPSK( access_t * );
64 static int FrontendSetQAM( access_t * );
65 static int FrontendSetOFDM( access_t * );
66 static int FrontendCheck( access_t * );
68 /*****************************************************************************
69 * FrontendOpen : Determine frontend device information and capabilities
70 *****************************************************************************/
71 int E_(FrontendOpen)( access_t *p_access )
73 access_sys_t *p_sys = p_access->p_sys;
74 frontend_t * p_frontend;
75 unsigned int i_adapter, i_device;
79 i_adapter = var_GetInteger( p_access, "dvb-adapter" );
80 i_device = var_GetInteger( p_access, "dvb-device" );
81 b_probe = var_GetBool( p_access, "dvb-probe" );
83 if( snprintf( frontend, sizeof(frontend), FRONTEND, i_adapter, i_device ) >= (int)sizeof(frontend) )
85 msg_Err( p_access, "snprintf() truncated string for FRONTEND" );
86 frontend[sizeof(frontend) - 1] = '\0';
89 p_sys->p_frontend = p_frontend = malloc( sizeof(frontend_t) );
91 msg_Dbg( p_access, "Opening device %s", frontend );
92 if( (p_frontend->i_handle = open(frontend, O_RDWR | O_NONBLOCK)) < 0 )
94 msg_Err( p_access, "FrontEndOpen: opening device failed (%s)",
102 char * psz_expected = NULL;
105 if( FrontendInfo( p_access ) < 0 )
107 close( p_frontend->i_handle );
112 switch( p_frontend->info.type )
124 psz_real = "unknown";
128 if( (!strncmp( p_access->psz_access, "qpsk", 4 ) ||
129 !strncmp( p_access->psz_access, "dvb-s", 5 ) ||
130 !strncmp( p_access->psz_access, "satellite", 9 ) ) &&
131 (p_frontend->info.type != FE_QPSK) )
133 psz_expected = "DVB-S";
135 if( (!strncmp( p_access->psz_access, "cable", 5 ) ||
136 !strncmp( p_access->psz_access, "dvb-c", 5 ) ) &&
137 (p_frontend->info.type != FE_QAM) )
139 psz_expected = "DVB-C";
141 if( (!strncmp( p_access->psz_access, "terrestrial", 11 ) ||
142 !strncmp( p_access->psz_access, "dvb-t", 5 ) ) &&
143 (p_frontend->info.type != FE_OFDM) )
145 psz_expected = "DVB-T";
148 if( psz_expected != NULL )
150 msg_Err( p_access, "the user asked for %s, and the tuner is %s",
151 psz_expected, psz_real );
152 close( p_frontend->i_handle );
157 else /* no frontend probing is done so use default border values. */
159 msg_Dbg( p_access, "using default values for frontend info" );
161 msg_Dbg( p_access, "method of access is %s", p_access->psz_access );
162 p_frontend->info.type = FE_QPSK;
163 if( !strncmp( p_access->psz_access, "qpsk", 4 ) ||
164 !strncmp( p_access->psz_access, "dvb-s", 5 ) )
165 p_frontend->info.type = FE_QPSK;
166 else if( !strncmp( p_access->psz_access, "cable", 5 ) ||
167 !strncmp( p_access->psz_access, "dvb-c", 5 ) )
168 p_frontend->info.type = FE_QAM;
169 else if( !strncmp( p_access->psz_access, "terrestrial", 11 ) ||
170 !strncmp( p_access->psz_access, "dvb-t", 5 ) )
171 p_frontend->info.type = FE_OFDM;
177 /*****************************************************************************
178 * FrontendClose : Close the frontend
179 *****************************************************************************/
180 void E_(FrontendClose)( access_t *p_access )
182 access_sys_t *p_sys = p_access->p_sys;
184 if( p_sys->p_frontend )
186 close( p_sys->p_frontend->i_handle );
187 free( p_sys->p_frontend );
189 p_sys->p_frontend = NULL;
193 /*****************************************************************************
194 * FrontendSet : Tune !
195 *****************************************************************************/
196 int E_(FrontendSet)( access_t *p_access )
198 access_sys_t *p_sys = p_access->p_sys;
200 switch( p_sys->p_frontend->info.type )
202 /* DVB-S: satellite and budget cards (nova) */
204 if( FrontendSetQPSK( p_access ) < 0 )
206 msg_Err( p_access, "DVB-S: tuning failed" );
213 if( FrontendSetQAM( p_access ) < 0 )
215 msg_Err( p_access, "DVB-C: tuning failed" );
222 if( FrontendSetOFDM( p_access ) < 0 )
224 msg_Err( p_access, "DVB-T: tuning failed" );
230 msg_Err( p_access, "Could not determine frontend type on %s",
231 p_sys->p_frontend->info.name );
237 /*****************************************************************************
238 * FrontendInfo : Return information about given frontend
239 *****************************************************************************/
240 static int FrontendInfo( access_t *p_access )
242 access_sys_t *p_sys = p_access->p_sys;
243 frontend_t *p_frontend = p_sys->p_frontend;
246 /* Determine type of frontend */
247 if( (i_ret = ioctl( p_frontend->i_handle, FE_GET_INFO,
248 &p_frontend->info )) < 0 )
250 msg_Err( p_access, "ioctl FE_GET_INFO failed (%d) %s", i_ret,
255 /* Print out frontend capabilities. */
256 msg_Dbg(p_access, "Frontend Info:" );
257 msg_Dbg(p_access, " name = %s", p_frontend->info.name );
258 switch( p_frontend->info.type )
261 msg_Dbg( p_access, " type = QPSK (DVB-S)" );
264 msg_Dbg( p_access, " type = QAM (DVB-C)" );
267 msg_Dbg( p_access, " type = OFDM (DVB-T)" );
269 #if 0 /* DVB_API_VERSION == 3 */
271 msg_Dbg(p_access, " type = MEMORY" );
274 msg_Dbg(p_access, " type = NETWORK" );
278 msg_Err( p_access, " unknown frontend type (%d)",
279 p_frontend->info.type );
282 msg_Dbg(p_access, " frequency_min = %u (kHz)",
283 p_frontend->info.frequency_min);
284 msg_Dbg(p_access, " frequency_max = %u (kHz)",
285 p_frontend->info.frequency_max);
286 msg_Dbg(p_access, " frequency_stepsize = %u",
287 p_frontend->info.frequency_stepsize);
288 msg_Dbg(p_access, " frequency_tolerance = %u",
289 p_frontend->info.frequency_tolerance);
290 msg_Dbg(p_access, " symbol_rate_min = %u (kHz)",
291 p_frontend->info.symbol_rate_min);
292 msg_Dbg(p_access, " symbol_rate_max = %u (kHz)",
293 p_frontend->info.symbol_rate_max);
294 msg_Dbg(p_access, " symbol_rate_tolerance (ppm) = %u",
295 p_frontend->info.symbol_rate_tolerance);
296 msg_Dbg(p_access, " notifier_delay (ms) = %u",
297 p_frontend->info.notifier_delay );
299 msg_Dbg(p_access, "Frontend Info capability list:");
300 if( p_frontend->info.caps & FE_IS_STUPID)
301 msg_Dbg(p_access, " no capabilities - frontend is stupid!");
302 if( p_frontend->info.caps & FE_CAN_INVERSION_AUTO)
303 msg_Dbg(p_access, " inversion auto");
304 if( p_frontend->info.caps & FE_CAN_FEC_1_2)
305 msg_Dbg(p_access, " forward error correction 1/2");
306 if( p_frontend->info.caps & FE_CAN_FEC_2_3)
307 msg_Dbg(p_access, " forward error correction 2/3");
308 if( p_frontend->info.caps & FE_CAN_FEC_3_4)
309 msg_Dbg(p_access, " forward error correction 3/4");
310 if( p_frontend->info.caps & FE_CAN_FEC_4_5)
311 msg_Dbg(p_access, " forward error correction 4/5");
312 if( p_frontend->info.caps & FE_CAN_FEC_5_6)
313 msg_Dbg(p_access, " forward error correction 5/6");
314 if( p_frontend->info.caps & FE_CAN_FEC_6_7)
315 msg_Dbg(p_access, " forward error correction 6/7");
316 if( p_frontend->info.caps & FE_CAN_FEC_7_8)
317 msg_Dbg(p_access, " forward error correction 7/8");
318 if( p_frontend->info.caps & FE_CAN_FEC_8_9)
319 msg_Dbg(p_access, " forward error correction 8/9");
320 if( p_frontend->info.caps & FE_CAN_FEC_AUTO)
321 msg_Dbg(p_access, " forward error correction auto");
322 if( p_frontend->info.caps & FE_CAN_QPSK)
323 msg_Dbg(p_access, " card can do QPSK");
324 if( p_frontend->info.caps & FE_CAN_QAM_16)
325 msg_Dbg(p_access, " card can do QAM 16");
326 if( p_frontend->info.caps & FE_CAN_QAM_32)
327 msg_Dbg(p_access, " card can do QAM 32");
328 if( p_frontend->info.caps & FE_CAN_QAM_64)
329 msg_Dbg(p_access, " card can do QAM 64");
330 if( p_frontend->info.caps & FE_CAN_QAM_128)
331 msg_Dbg(p_access, " card can do QAM 128");
332 if( p_frontend->info.caps & FE_CAN_QAM_256)
333 msg_Dbg(p_access, " card can do QAM 256");
334 if( p_frontend->info.caps & FE_CAN_QAM_AUTO)
335 msg_Dbg(p_access, " card can do QAM auto");
336 if( p_frontend->info.caps & FE_CAN_TRANSMISSION_MODE_AUTO)
337 msg_Dbg(p_access, " transmission mode auto");
338 if( p_frontend->info.caps & FE_CAN_BANDWIDTH_AUTO)
339 msg_Dbg(p_access, " bandwidth mode auto");
340 if( p_frontend->info.caps & FE_CAN_GUARD_INTERVAL_AUTO)
341 msg_Dbg(p_access, " guard interval mode auto");
342 if( p_frontend->info.caps & FE_CAN_HIERARCHY_AUTO)
343 msg_Dbg(p_access, " hierarchy mode auto");
344 if( p_frontend->info.caps & FE_CAN_MUTE_TS)
345 msg_Dbg(p_access, " card can mute TS");
346 if( p_frontend->info.caps & FE_CAN_CLEAN_SETUP)
347 msg_Dbg(p_access, " clean setup");
348 msg_Dbg(p_access, "End of capability list");
353 /*****************************************************************************
354 * Decoding the DVB parameters (common)
355 *****************************************************************************/
356 static fe_spectral_inversion_t DecodeInversion( access_t *p_access )
359 fe_spectral_inversion_t fe_inversion = 0;
361 var_Get( p_access, "dvb-inversion", &val );
362 msg_Dbg( p_access, "using inversion=%d", val.i_int );
366 case 0: fe_inversion = INVERSION_OFF; break;
367 case 1: fe_inversion = INVERSION_ON; break;
368 case 2: fe_inversion = INVERSION_AUTO; break;
370 msg_Dbg( p_access, "dvb has inversion not set, using auto");
371 fe_inversion = INVERSION_AUTO;
377 static fe_code_rate_t DecodeFEC( access_t *p_access, int i_val )
379 fe_code_rate_t fe_fec = FEC_NONE;
381 msg_Dbg( p_access, "using fec=%d", i_val );
385 case 0: fe_fec = FEC_NONE; break;
386 case 1: fe_fec = FEC_1_2; break;
387 case 2: fe_fec = FEC_2_3; break;
388 case 3: fe_fec = FEC_3_4; break;
389 case 4: fe_fec = FEC_4_5; break;
390 case 5: fe_fec = FEC_5_6; break;
391 case 6: fe_fec = FEC_6_7; break;
392 case 7: fe_fec = FEC_7_8; break;
393 case 8: fe_fec = FEC_8_9; break;
394 case 9: fe_fec = FEC_AUTO; break;
398 msg_Err( p_access, "argument has invalid FEC (%d)", i_val);
404 static fe_modulation_t DecodeModulation( access_t *p_access )
407 fe_modulation_t fe_modulation = 0;
409 var_Get( p_access, "dvb-modulation", &val );
413 case -1: fe_modulation = QPSK; break;
414 case 0: fe_modulation = QAM_AUTO; break;
415 case 16: fe_modulation = QAM_16; break;
416 case 32: fe_modulation = QAM_32; break;
417 case 64: fe_modulation = QAM_64; break;
418 case 128: fe_modulation = QAM_128; break;
419 case 256: fe_modulation = QAM_256; break;
421 msg_Dbg( p_access, "terrestrial/cable dvb has constellation/modulation not set, using auto");
422 fe_modulation = QAM_AUTO;
425 return fe_modulation;
428 /*****************************************************************************
429 * FrontendSetQPSK : controls the FE device
430 *****************************************************************************/
431 static fe_sec_voltage_t DecodeVoltage( access_t *p_access )
434 fe_sec_voltage_t fe_voltage;
436 var_Get( p_access, "dvb-voltage", &val );
437 msg_Dbg( p_access, "using voltage=%d", val.i_int );
441 case 0: fe_voltage = SEC_VOLTAGE_OFF; break;
442 case 13: fe_voltage = SEC_VOLTAGE_13; break;
443 case 18: fe_voltage = SEC_VOLTAGE_18; break;
445 fe_voltage = SEC_VOLTAGE_OFF;
446 msg_Err( p_access, "argument has invalid voltage (%d)", val.i_int );
452 static fe_sec_tone_mode_t DecodeTone( access_t *p_access )
455 fe_sec_tone_mode_t fe_tone;
457 var_Get( p_access, "dvb-tone", &val );
458 msg_Dbg( p_access, "using tone=%d", val.i_int );
462 case 0: fe_tone = SEC_TONE_OFF; break;
463 case 1: fe_tone = SEC_TONE_ON; break;
465 fe_tone = SEC_TONE_OFF;
466 msg_Err( p_access, "argument has invalid tone mode (%d)", val.i_int);
474 struct dvb_diseqc_master_cmd cmd;
478 static int DoDiseqc( access_t *p_access )
480 access_sys_t *p_sys = p_access->p_sys;
481 frontend_t * p_frontend = p_sys->p_frontend;
483 int i_frequency, i_lnb_slof;
484 fe_sec_voltage_t fe_voltage;
485 fe_sec_tone_mode_t fe_tone;
488 var_Get( p_access, "dvb-frequency", &val );
489 i_frequency = val.i_int;
490 var_Get( p_access, "dvb-lnb-slof", &val );
491 i_lnb_slof = val.i_int;
493 var_Get( p_access, "dvb-tone", &val );
494 if( val.i_int == -1 /* auto */ )
496 if( i_frequency >= i_lnb_slof )
500 var_Set( p_access, "dvb-tone", val );
503 fe_voltage = DecodeVoltage( p_access );
504 fe_tone = DecodeTone( p_access );
506 if( (i_err = ioctl( p_frontend->i_handle, FE_SET_VOLTAGE, fe_voltage )) < 0 )
508 msg_Err( p_access, "ioctl FE_SET_VOLTAGE failed, voltage=%d (%d) %s",
509 fe_voltage, i_err, strerror(errno) );
513 var_Get( p_access, "dvb-satno", &val );
516 /* digital satellite equipment control,
517 * specification is available from http://www.eutelsat.com/
519 if( (i_err = ioctl( p_frontend->i_handle, FE_SET_TONE,
520 SEC_TONE_OFF )) < 0 )
522 msg_Err( p_access, "ioctl FE_SET_TONE failed, tone=off (%d) %s",
523 i_err, strerror(errno) );
529 if( val.i_int >= 1 && val.i_int <= 4 )
531 /* 1.x compatible equipment */
532 struct diseqc_cmd_t cmd = { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
534 /* param: high nibble: reset bits, low nibble set bits,
535 * bits are: option, position, polarization, band
537 cmd.cmd.msg[3] = 0xf0 /* reset bits */
538 | (((val.i_int - 1) * 4) & 0xc)
539 | (fe_voltage == SEC_VOLTAGE_13 ? 0 : 2)
540 | (fe_tone == SEC_TONE_ON ? 1 : 0);
542 if( (i_err = ioctl( p_frontend->i_handle, FE_DISEQC_SEND_MASTER_CMD,
545 msg_Err( p_access, "ioctl FE_SEND_MASTER_CMD failed (%d) %s",
546 i_err, strerror(errno) );
550 msleep(cmd.wait * 1000);
554 /* A or B simple diseqc */
555 if( (i_err = ioctl( p_frontend->i_handle, FE_DISEQC_SEND_BURST,
556 val.i_int == -1 ? SEC_MINI_A : SEC_MINI_B )) < 0 )
558 msg_Err( p_access, "ioctl FE_SEND_BURST failed (%d) %s",
559 i_err, strerror(errno) );
567 if( (i_err = ioctl( p_frontend->i_handle, FE_SET_TONE, fe_tone )) < 0 )
569 msg_Err( p_access, "ioctl FE_SET_TONE failed, tone=%s (%d) %s",
570 fe_tone == SEC_TONE_ON ? "on" : "off", i_err,
579 static int FrontendSetQPSK( access_t *p_access )
581 access_sys_t *p_sys = p_access->p_sys;
582 frontend_t * p_frontend = p_sys->p_frontend;
583 struct dvb_frontend_parameters fep;
586 int i_frequency, i_lnb_slof;
588 /* Prepare the fep structure */
589 var_Get( p_access, "dvb-frequency", &val );
590 i_frequency = val.i_int;
591 var_Get( p_access, "dvb-lnb-slof", &val );
592 i_lnb_slof = val.i_int;
594 if( i_frequency >= i_lnb_slof )
595 var_Get( p_access, "dvb-lnb-lof2", &val );
597 var_Get( p_access, "dvb-lnb-lof1", &val );
598 fep.frequency = i_frequency - val.i_int;
600 fep.inversion = DecodeInversion( p_access );
602 var_Get( p_access, "dvb-srate", &val );
603 fep.u.qpsk.symbol_rate = val.i_int;
605 var_Get( p_access, "dvb-fec", &val );
606 fep.u.qpsk.fec_inner = DecodeFEC( p_access, val.i_int );
608 if( DoDiseqc( p_access ) < 0 )
615 /* Empty the event queue */
618 struct dvb_frontend_event event;
619 if( ioctl( p_frontend->i_handle, FE_GET_EVENT, &event ) < 0 )
623 /* Now send it all to the frontend device */
624 if( (i_ret = ioctl( p_frontend->i_handle, FE_SET_FRONTEND, &fep )) < 0 )
626 msg_Err( p_access, "DVB-S: setting frontend failed (%d) %s", i_ret,
631 return FrontendCheck( p_access );
634 /*****************************************************************************
635 * FrontendSetQAM : controls the FE device
636 *****************************************************************************/
637 static int FrontendSetQAM( access_t *p_access )
639 access_sys_t *p_sys = p_access->p_sys;
640 frontend_t * p_frontend = p_sys->p_frontend;
641 struct dvb_frontend_parameters fep;
645 /* Prepare the fep structure */
647 var_Get( p_access, "dvb-frequency", &val );
648 fep.frequency = val.i_int;
650 fep.inversion = DecodeInversion( p_access );
652 var_Get( p_access, "dvb-srate", &val );
653 fep.u.qam.symbol_rate = val.i_int;
655 var_Get( p_access, "dvb-fec", &val );
656 fep.u.qam.fec_inner = DecodeFEC( p_access, val.i_int );
658 fep.u.qam.modulation = DecodeModulation( p_access );
660 /* Empty the event queue */
663 struct dvb_frontend_event event;
664 if( ioctl( p_frontend->i_handle, FE_GET_EVENT, &event ) < 0 )
668 /* Now send it all to the frontend device */
669 if( (i_ret = ioctl( p_frontend->i_handle, FE_SET_FRONTEND, &fep )) < 0 )
671 msg_Err( p_access, "DVB-C: setting frontend failed (%d) %s", i_ret,
676 return FrontendCheck( p_access );
679 /*****************************************************************************
680 * FrontendSetOFDM : controls the FE device
681 *****************************************************************************/
682 static fe_bandwidth_t DecodeBandwidth( access_t *p_access )
685 fe_bandwidth_t fe_bandwidth = 0;
687 var_Get( p_access, "dvb-bandwidth", &val );
688 msg_Dbg( p_access, "using bandwidth=%d", val.i_int );
692 case 0: fe_bandwidth = BANDWIDTH_AUTO; break;
693 case 6: fe_bandwidth = BANDWIDTH_6_MHZ; break;
694 case 7: fe_bandwidth = BANDWIDTH_7_MHZ; break;
695 case 8: fe_bandwidth = BANDWIDTH_8_MHZ; break;
697 msg_Dbg( p_access, "terrestrial dvb has bandwidth not set, using auto" );
698 fe_bandwidth = BANDWIDTH_AUTO;
704 static fe_transmit_mode_t DecodeTransmission( access_t *p_access )
707 fe_transmit_mode_t fe_transmission = 0;
709 var_Get( p_access, "dvb-transmission", &val );
710 msg_Dbg( p_access, "using transmission=%d", val.i_int );
714 case 0: fe_transmission = TRANSMISSION_MODE_AUTO; break;
715 case 2: fe_transmission = TRANSMISSION_MODE_2K; break;
716 case 8: fe_transmission = TRANSMISSION_MODE_8K; break;
718 msg_Dbg( p_access, "terrestrial dvb has transmission mode not set, using auto");
719 fe_transmission = TRANSMISSION_MODE_AUTO;
722 return fe_transmission;
725 static fe_guard_interval_t DecodeGuardInterval( access_t *p_access )
728 fe_guard_interval_t fe_guard = 0;
730 var_Get( p_access, "dvb-guard", &val );
731 msg_Dbg( p_access, "using guard=%d", val.i_int );
735 case 0: fe_guard = GUARD_INTERVAL_AUTO; break;
736 case 4: fe_guard = GUARD_INTERVAL_1_4; break;
737 case 8: fe_guard = GUARD_INTERVAL_1_8; break;
738 case 16: fe_guard = GUARD_INTERVAL_1_16; break;
739 case 32: fe_guard = GUARD_INTERVAL_1_32; break;
741 msg_Dbg( p_access, "terrestrial dvb has guard interval not set, using auto");
742 fe_guard = GUARD_INTERVAL_AUTO;
748 static fe_hierarchy_t DecodeHierarchy( access_t *p_access )
751 fe_hierarchy_t fe_hierarchy = 0;
753 var_Get( p_access, "dvb-hierarchy", &val );
754 msg_Dbg( p_access, "using hierarchy=%d", val.i_int );
758 case -1: fe_hierarchy = HIERARCHY_NONE; break;
759 case 0: fe_hierarchy = HIERARCHY_AUTO; break;
760 case 1: fe_hierarchy = HIERARCHY_1; break;
761 case 2: fe_hierarchy = HIERARCHY_2; break;
762 case 4: fe_hierarchy = HIERARCHY_4; break;
764 msg_Dbg( p_access, "terrestrial dvb has hierarchy not set, using auto");
765 fe_hierarchy = HIERARCHY_AUTO;
771 static int FrontendSetOFDM( access_t * p_access )
773 access_sys_t *p_sys = p_access->p_sys;
774 frontend_t * p_frontend = p_sys->p_frontend;
775 struct dvb_frontend_parameters fep;
779 /* Prepare the fep structure */
781 var_Get( p_access, "dvb-frequency", &val );
782 fep.frequency = val.i_int;
784 fep.inversion = DecodeInversion( p_access );
786 fep.u.ofdm.bandwidth = DecodeBandwidth( p_access );
787 var_Get( p_access, "dvb-code-rate-hp", &val );
788 fep.u.ofdm.code_rate_HP = DecodeFEC( p_access, val.i_int );
789 var_Get( p_access, "dvb-code-rate-lp", &val );
790 fep.u.ofdm.code_rate_LP = DecodeFEC( p_access, val.i_int );
791 fep.u.ofdm.constellation = DecodeModulation( p_access );
792 fep.u.ofdm.transmission_mode = DecodeTransmission( p_access );
793 fep.u.ofdm.guard_interval = DecodeGuardInterval( p_access );
794 fep.u.ofdm.hierarchy_information = DecodeHierarchy( p_access );
796 /* Empty the event queue */
799 struct dvb_frontend_event event;
800 if( ioctl( p_frontend->i_handle, FE_GET_EVENT, &event ) < 0 )
804 /* Now send it all to the frontend device */
805 if( (ret = ioctl( p_frontend->i_handle, FE_SET_FRONTEND, &fep )) < 0 )
807 msg_Err( p_access, "DVB-T: setting frontend failed (%d) %s", ret,
812 return FrontendCheck( p_access );
815 /******************************************************************
816 * FrontendCheck: Check completion of the frontend control sequence
817 ******************************************************************/
818 static int FrontendCheck( access_t * p_access )
820 access_sys_t *p_sys = p_access->p_sys;
821 frontend_t * p_frontend = p_sys->p_frontend;
824 while ( !p_access->b_die && !p_access->b_error )
827 if( (i_ret = ioctl( p_frontend->i_handle, FE_READ_STATUS,
830 msg_Err( p_access, "reading frontend status failed (%d) %s",
831 i_ret, strerror(errno) );
835 if(status & FE_HAS_SIGNAL) /* found something above the noise level */
836 msg_Dbg(p_access, "check frontend ... has signal");
838 if(status & FE_HAS_CARRIER) /* found a DVB signal */
839 msg_Dbg(p_access, "check frontend ... has carrier");
841 if(status & FE_HAS_VITERBI) /* FEC is stable */
842 msg_Dbg(p_access, "check frontend ... has stable forward error correction");
844 if(status & FE_HAS_SYNC) /* found sync bytes */
845 msg_Dbg(p_access, "check frontend ... has sync");
847 if(status & FE_HAS_LOCK) /* everything's working... */
850 msg_Dbg(p_access, "check frontend ... has lock");
851 msg_Dbg(p_access, "tuning succeeded");
853 /* Read some statistics */
855 if( ioctl( p_frontend->i_handle, FE_READ_BER, &value ) >= 0 )
856 msg_Dbg( p_access, "Bit error rate: %d", value );
859 if( ioctl( p_frontend->i_handle, FE_READ_SIGNAL_STRENGTH, &value ) >= 0 )
860 msg_Dbg( p_access, "Signal strength: %d", value );
863 if( ioctl( p_frontend->i_handle, FE_READ_SNR, &value ) >= 0 )
864 msg_Dbg( p_access, "SNR: %d", value );
869 if(status & FE_TIMEDOUT) /* no lock within the last ~2 seconds */
871 msg_Err(p_access, "tuning failed ... timed out");
875 if(status & FE_REINIT)
877 /* frontend was reinitialized, */
878 /* application is recommended to reset */
879 /* DiSEqC, tone and parameters */
880 msg_Err(p_access, "tuning failed ... resend frontend parameters");
894 /*****************************************************************************
895 * DMXSetFilter : controls the demux to add a filter
896 *****************************************************************************/
897 int E_(DMXSetFilter)( access_t * p_access, int i_pid, int * pi_fd, int i_type )
899 struct dmx_pes_filter_params s_filter_params;
901 unsigned int i_adapter, i_device;
905 var_Get( p_access, "dvb-adapter", &val );
906 i_adapter = val.i_int;
907 var_Get( p_access, "dvb-device", &val );
908 i_device = val.i_int;
910 if( snprintf( dmx, sizeof(dmx), DMX, i_adapter, i_device )
911 >= (int)sizeof(dmx) )
913 msg_Err( p_access, "snprintf() truncated string for DMX" );
914 dmx[sizeof(dmx) - 1] = '\0';
917 msg_Dbg( p_access, "Opening device %s", dmx );
918 if( (*pi_fd = open(dmx, O_RDWR)) < 0 )
920 msg_Err( p_access, "DMXSetFilter: opening device failed (%s)",
925 /* We fill the DEMUX structure : */
926 s_filter_params.pid = i_pid;
927 s_filter_params.input = DMX_IN_FRONTEND;
928 s_filter_params.output = DMX_OUT_TS_TAP;
929 s_filter_params.flags = DMX_IMMEDIATE_START;
934 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO0 for PID %d", i_pid);
935 s_filter_params.pes_type = DMX_PES_VIDEO0;
938 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO0 for PID %d", i_pid);
939 s_filter_params.pes_type = DMX_PES_AUDIO0;
942 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT0 for PID %d", i_pid);
943 s_filter_params.pes_type = DMX_PES_TELETEXT0;
946 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE0 for PID %d", i_pid);
947 s_filter_params.pes_type = DMX_PES_SUBTITLE0;
950 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR0 for PID %d", i_pid);
951 s_filter_params.pes_type = DMX_PES_PCR0;
955 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO1 for PID %d", i_pid);
956 s_filter_params.pes_type = DMX_PES_VIDEO1;
959 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO1 for PID %d", i_pid);
960 s_filter_params.pes_type = DMX_PES_AUDIO1;
963 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT1 for PID %d", i_pid);
964 s_filter_params.pes_type = DMX_PES_TELETEXT1;
967 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE1 for PID %d", i_pid);
968 s_filter_params.pes_type = DMX_PES_SUBTITLE1;
971 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR1 for PID %d", i_pid);
972 s_filter_params.pes_type = DMX_PES_PCR1;
976 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO2 for PID %d", i_pid);
977 s_filter_params.pes_type = DMX_PES_VIDEO2;
980 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO2 for PID %d", i_pid);
981 s_filter_params.pes_type = DMX_PES_AUDIO2;
984 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT2 for PID %d", i_pid);
985 s_filter_params.pes_type = DMX_PES_TELETEXT2;
988 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE2 for PID %d", i_pid);
989 s_filter_params.pes_type = DMX_PES_SUBTITLE2;
992 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR2 for PID %d", i_pid);
993 s_filter_params.pes_type = DMX_PES_PCR2;
997 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO3 for PID %d", i_pid);
998 s_filter_params.pes_type = DMX_PES_VIDEO3;
1001 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO3 for PID %d", i_pid);
1002 s_filter_params.pes_type = DMX_PES_AUDIO3;
1005 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT3 for PID %d", i_pid);
1006 s_filter_params.pes_type = DMX_PES_TELETEXT3;
1009 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE3 for PID %d", i_pid);
1010 s_filter_params.pes_type = DMX_PES_SUBTITLE3;
1013 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR3 for PID %d", i_pid);
1014 s_filter_params.pes_type = DMX_PES_PCR3;
1016 /* Usually used by Nova cards */
1019 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_OTHER for PID %d", i_pid);
1020 s_filter_params.pes_type = DMX_PES_OTHER;
1024 /* We then give the order to the device : */
1025 if( (i_ret = ioctl( *pi_fd, DMX_SET_PES_FILTER, &s_filter_params )) < 0 )
1027 msg_Err( p_access, "DMXSetFilter: failed with %d (%s)", i_ret,
1029 return VLC_EGENERIC;
1034 /*****************************************************************************
1035 * DMXUnsetFilter : removes a filter
1036 *****************************************************************************/
1037 int E_(DMXUnsetFilter)( access_t * p_access, int i_fd )
1041 if( (i_ret = ioctl( i_fd, DMX_STOP )) < 0 )
1043 msg_Err( p_access, "DMX_STOP failed for demux (%d) %s",
1044 i_ret, strerror(errno) );
1048 msg_Dbg( p_access, "DMXUnsetFilter: closing demux %d", i_fd );
1058 /*****************************************************************************
1060 *****************************************************************************/
1061 int E_(DVROpen)( access_t * p_access )
1063 access_sys_t *p_sys = p_access->p_sys;
1064 unsigned int i_adapter, i_device;
1068 var_Get( p_access, "dvb-adapter", &val );
1069 i_adapter = val.i_int;
1070 var_Get( p_access, "dvb-device", &val );
1071 i_device = val.i_int;
1073 if( snprintf( dvr, sizeof(dvr), DVR, i_adapter, i_device )
1074 >= (int)sizeof(dvr) )
1076 msg_Err( p_access, "snprintf() truncated string for DVR" );
1077 dvr[sizeof(dvr) - 1] = '\0';
1080 msg_Dbg( p_access, "Opening device %s", dvr );
1081 if( (p_sys->i_handle = open(dvr, O_RDONLY)) < 0 )
1083 msg_Err( p_access, "DVROpen: opening device failed (%s)",
1085 return VLC_EGENERIC;
1088 if ( ioctl( p_sys->i_handle, DMX_SET_BUFFER_SIZE, DMX_BUFFER_SIZE ) < 0 )
1090 msg_Warn( p_access, "couldn't set DMX_BUFFER_SIZE (%s)",
1097 /*****************************************************************************
1099 *****************************************************************************/
1100 void E_(DVRClose)( access_t * p_access )
1102 access_sys_t *p_sys = p_access->p_sys;
1104 close( p_sys->i_handle );
1112 /*****************************************************************************
1114 *****************************************************************************/
1115 int E_(CAMOpen)( access_t *p_access )
1117 access_sys_t *p_sys = p_access->p_sys;
1119 int i_adapter, i_device, i_slot, i_active_slots = 0;
1122 i_adapter = var_GetInteger( p_access, "dvb-adapter" );
1123 i_device = var_GetInteger( p_access, "dvb-device" );
1125 if( snprintf( ca, sizeof(ca), CA, i_adapter, i_device ) >= (int)sizeof(ca) )
1127 msg_Err( p_access, "snprintf() truncated string for CA" );
1128 ca[sizeof(ca) - 1] = '\0';
1131 msg_Dbg( p_access, "Opening device %s", ca );
1132 if( (p_sys->i_ca_handle = open(ca, O_RDWR | O_NONBLOCK)) < 0 )
1134 msg_Err( p_access, "CAMInit: opening device failed (%s)",
1136 return VLC_EGENERIC;
1139 if ( ioctl( p_sys->i_ca_handle, CA_GET_CAP, &caps ) != 0
1140 || caps.slot_num == 0 || caps.slot_type != CA_CI_LINK )
1142 msg_Err( p_access, "CAMInit: no compatible CAM module" );
1143 close( p_sys->i_ca_handle );
1144 p_sys->i_ca_handle = 0;
1145 return VLC_EGENERIC;
1148 p_sys->i_nb_slots = caps.slot_num;
1149 memset( p_sys->pb_active_slot, 0, sizeof(vlc_bool_t) * MAX_CI_SLOTS );
1151 for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
1153 ca_slot_info_t sinfo;
1156 if ( ioctl( p_sys->i_ca_handle, CA_RESET, 1 << i_slot) != 0 )
1158 msg_Err( p_access, "CAMInit: couldn't reset slot %d", i_slot );
1162 for ( i = 0; i < CA_MAX_STATE_RETRY; i++ )
1167 if ( ioctl( p_sys->i_ca_handle, CA_GET_SLOT_INFO, &sinfo ) != 0 )
1169 msg_Err( p_access, "CAMInit: couldn't get info on slot %d",
1174 if ( sinfo.flags & CA_CI_MODULE_READY )
1176 p_sys->pb_active_slot[i_slot] = VLC_TRUE;
1181 i_active_slots = E_(en50221_Init)( p_access );
1183 msg_Dbg( p_access, "CAMInit: found a CI handler with %d slots, %d active",
1184 p_sys->i_nb_slots, i_active_slots );
1186 if ( !i_active_slots )
1188 close( p_sys->i_ca_handle );
1189 p_sys->i_ca_handle = 0;
1190 return VLC_EGENERIC;
1196 /*****************************************************************************
1198 *****************************************************************************/
1199 int E_(CAMPoll)( access_t * p_access )
1201 access_sys_t *p_sys = p_access->p_sys;
1203 if ( p_sys->i_ca_handle == 0 )
1205 return VLC_EGENERIC;
1208 return E_(en50221_Poll)( p_access );
1211 /*****************************************************************************
1213 *****************************************************************************/
1214 int E_(CAMSet)( access_t * p_access, uint8_t **pp_capmts, int i_nb_capmts )
1216 access_sys_t *p_sys = p_access->p_sys;
1218 if ( p_sys->i_ca_handle == 0 )
1220 return VLC_EGENERIC;
1223 E_(en50221_SetCAPMT)( p_access, pp_capmts, i_nb_capmts );
1228 /*****************************************************************************
1230 *****************************************************************************/
1231 void E_(CAMClose)( access_t * p_access )
1233 access_sys_t *p_sys = p_access->p_sys;
1235 E_(en50221_End)( p_access );
1237 if ( p_sys->i_ca_handle )
1239 close( p_sys->i_ca_handle );