00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <vlc/vlc.h>
00028 #include <vlc/input.h>
00029
00030 #include <sys/ioctl.h>
00031 #include <errno.h>
00032
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <fcntl.h>
00036 #include <time.h>
00037 #include <unistd.h>
00038 #include <sys/stat.h>
00039 #include <sys/poll.h>
00040
00041
00042 #include <linux/dvb/version.h>
00043 #include <linux/dvb/dmx.h>
00044 #include <linux/dvb/frontend.h>
00045 #include <linux/dvb/ca.h>
00046
00047
00048 #ifdef HAVE_DVBPSI_DR_H
00049 # include <dvbpsi/dvbpsi.h>
00050 # include <dvbpsi/descriptor.h>
00051 # include <dvbpsi/pat.h>
00052 # include <dvbpsi/pmt.h>
00053 # include <dvbpsi/dr.h>
00054 # include <dvbpsi/psi.h>
00055 #else
00056 # include "dvbpsi.h"
00057 # include "descriptor.h"
00058 # include "tables/pat.h"
00059 # include "tables/pmt.h"
00060 # include "descriptors/dr.h"
00061 # include "psi.h"
00062 #endif
00063
00064 #include "dvb.h"
00065
00066
00067
00068
00069 struct frontend_t
00070 {
00071 fe_status_t i_last_status;
00072 struct dvb_frontend_info info;
00073 };
00074
00075 #define FRONTEND_LOCK_TIMEOUT 10000000
00076
00077
00078 static int FrontendInfo( access_t * );
00079 static int FrontendSetQPSK( access_t * );
00080 static int FrontendSetQAM( access_t * );
00081 static int FrontendSetOFDM( access_t * );
00082
00083
00084
00085
00086 int E_(FrontendOpen)( access_t *p_access )
00087 {
00088 access_sys_t *p_sys = p_access->p_sys;
00089 frontend_t * p_frontend;
00090 unsigned int i_adapter, i_device;
00091 vlc_bool_t b_probe;
00092 char frontend[128];
00093
00094 i_adapter = var_GetInteger( p_access, "dvb-adapter" );
00095 i_device = var_GetInteger( p_access, "dvb-device" );
00096 b_probe = var_GetBool( p_access, "dvb-probe" );
00097
00098 if( snprintf( frontend, sizeof(frontend), FRONTEND, i_adapter, i_device ) >= (int)sizeof(frontend) )
00099 {
00100 msg_Err( p_access, "snprintf() truncated string for FRONTEND" );
00101 frontend[sizeof(frontend) - 1] = '\0';
00102 }
00103
00104 p_sys->p_frontend = p_frontend = malloc( sizeof(frontend_t) );
00105
00106 msg_Dbg( p_access, "Opening device %s", frontend );
00107 if( (p_sys->i_frontend_handle = open(frontend, O_RDWR | O_NONBLOCK)) < 0 )
00108 {
00109 msg_Err( p_access, "FrontEndOpen: opening device failed (%s)",
00110 strerror(errno) );
00111 free( p_frontend );
00112 return VLC_EGENERIC;
00113 }
00114
00115 if( b_probe )
00116 {
00117 char * psz_expected = NULL;
00118 char * psz_real;
00119
00120 if( FrontendInfo( p_access ) < 0 )
00121 {
00122 close( p_sys->i_frontend_handle );
00123 free( p_frontend );
00124 return VLC_EGENERIC;
00125 }
00126
00127 switch( p_frontend->info.type )
00128 {
00129 case FE_OFDM:
00130 psz_real = "DVB-T";
00131 break;
00132 case FE_QAM:
00133 psz_real = "DVB-C";
00134 break;
00135 case FE_QPSK:
00136 psz_real = "DVB-S";
00137 break;
00138 default:
00139 psz_real = "unknown";
00140 }
00141
00142
00143 if( (!strncmp( p_access->psz_access, "qpsk", 4 ) ||
00144 !strncmp( p_access->psz_access, "dvb-s", 5 ) ||
00145 !strncmp( p_access->psz_access, "satellite", 9 ) ) &&
00146 (p_frontend->info.type != FE_QPSK) )
00147 {
00148 psz_expected = "DVB-S";
00149 }
00150 if( (!strncmp( p_access->psz_access, "cable", 5 ) ||
00151 !strncmp( p_access->psz_access, "dvb-c", 5 ) ) &&
00152 (p_frontend->info.type != FE_QAM) )
00153 {
00154 psz_expected = "DVB-C";
00155 }
00156 if( (!strncmp( p_access->psz_access, "terrestrial", 11 ) ||
00157 !strncmp( p_access->psz_access, "dvb-t", 5 ) ) &&
00158 (p_frontend->info.type != FE_OFDM) )
00159 {
00160 psz_expected = "DVB-T";
00161 }
00162
00163 if( psz_expected != NULL )
00164 {
00165 msg_Err( p_access, "the user asked for %s, and the tuner is %s",
00166 psz_expected, psz_real );
00167 close( p_sys->i_frontend_handle );
00168 free( p_frontend );
00169 return VLC_EGENERIC;
00170 }
00171 }
00172 else
00173 {
00174 msg_Dbg( p_access, "using default values for frontend info" );
00175
00176 msg_Dbg( p_access, "method of access is %s", p_access->psz_access );
00177 p_frontend->info.type = FE_QPSK;
00178 if( !strncmp( p_access->psz_access, "qpsk", 4 ) ||
00179 !strncmp( p_access->psz_access, "dvb-s", 5 ) )
00180 p_frontend->info.type = FE_QPSK;
00181 else if( !strncmp( p_access->psz_access, "cable", 5 ) ||
00182 !strncmp( p_access->psz_access, "dvb-c", 5 ) )
00183 p_frontend->info.type = FE_QAM;
00184 else if( !strncmp( p_access->psz_access, "terrestrial", 11 ) ||
00185 !strncmp( p_access->psz_access, "dvb-t", 5 ) )
00186 p_frontend->info.type = FE_OFDM;
00187 }
00188
00189 return VLC_SUCCESS;
00190 }
00191
00192
00193
00194
00195 void E_(FrontendClose)( access_t *p_access )
00196 {
00197 access_sys_t *p_sys = p_access->p_sys;
00198
00199 if( p_sys->p_frontend )
00200 {
00201 close( p_sys->i_frontend_handle );
00202 free( p_sys->p_frontend );
00203
00204 p_sys->p_frontend = NULL;
00205 }
00206 }
00207
00208
00209
00210
00211 int E_(FrontendSet)( access_t *p_access )
00212 {
00213 access_sys_t *p_sys = p_access->p_sys;
00214
00215 switch( p_sys->p_frontend->info.type )
00216 {
00217
00218 case FE_QPSK:
00219 if( FrontendSetQPSK( p_access ) < 0 )
00220 {
00221 msg_Err( p_access, "DVB-S: tuning failed" );
00222 return VLC_EGENERIC;
00223 }
00224 break;
00225
00226
00227 case FE_QAM:
00228 if( FrontendSetQAM( p_access ) < 0 )
00229 {
00230 msg_Err( p_access, "DVB-C: tuning failed" );
00231 return VLC_EGENERIC;
00232 }
00233 break;
00234
00235
00236 case FE_OFDM:
00237 if( FrontendSetOFDM( p_access ) < 0 )
00238 {
00239 msg_Err( p_access, "DVB-T: tuning failed" );
00240 return VLC_EGENERIC;
00241 }
00242 break;
00243
00244 default:
00245 msg_Err( p_access, "Could not determine frontend type on %s",
00246 p_sys->p_frontend->info.name );
00247 return VLC_EGENERIC;
00248 }
00249 p_sys->p_frontend->i_last_status = 0;
00250 p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
00251 return VLC_SUCCESS;
00252 }
00253
00254
00255
00256
00257 void E_(FrontendPoll)( access_t *p_access )
00258 {
00259 access_sys_t *p_sys = p_access->p_sys;
00260 frontend_t * p_frontend = p_sys->p_frontend;
00261 struct dvb_frontend_event event;
00262 fe_status_t i_status, i_diff;
00263
00264 for( ;; )
00265 {
00266 int i_ret = ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event );
00267
00268 if( i_ret < 0 )
00269 {
00270 if( errno == EWOULDBLOCK )
00271 return;
00272
00273 msg_Err( p_access, "reading frontend status failed (%d) %s",
00274 i_ret, strerror(errno) );
00275 continue;
00276 }
00277
00278 i_status = event.status;
00279 i_diff = i_status ^ p_frontend->i_last_status;
00280 p_frontend->i_last_status = i_status;
00281
00282 #define IF_UP( x ) \
00283 } \
00284 if ( i_diff & (x) ) \
00285 { \
00286 if ( i_status & (x) )
00287
00288 {
00289 IF_UP( FE_HAS_SIGNAL )
00290 msg_Dbg( p_access, "frontend has acquired signal" );
00291 else
00292 msg_Dbg( p_access, "frontend has lost signal" );
00293
00294 IF_UP( FE_HAS_CARRIER )
00295 msg_Dbg( p_access, "frontend has acquired carrier" );
00296 else
00297 msg_Dbg( p_access, "frontend has lost carrier" );
00298
00299 IF_UP( FE_HAS_VITERBI )
00300 msg_Dbg( p_access, "frontend has acquired stable FEC" );
00301 else
00302 msg_Dbg( p_access, "frontend has lost FEC" );
00303
00304 IF_UP( FE_HAS_SYNC )
00305 msg_Dbg( p_access, "frontend has acquired sync" );
00306 else
00307 msg_Dbg( p_access, "frontend has lost sync" );
00308
00309 IF_UP( FE_HAS_LOCK )
00310 {
00311 int32_t i_value;
00312 msg_Dbg( p_access, "frontend has acquired lock" );
00313 p_sys->i_frontend_timeout = 0;
00314
00315
00316 if( ioctl( p_sys->i_frontend_handle, FE_READ_BER, &i_value ) >= 0 )
00317 msg_Dbg( p_access, "- Bit error rate: %d", i_value );
00318 if( ioctl( p_sys->i_frontend_handle, FE_READ_SIGNAL_STRENGTH, &i_value ) >= 0 )
00319 msg_Dbg( p_access, "- Signal strength: %d", i_value );
00320 if( ioctl( p_sys->i_frontend_handle, FE_READ_SNR, &i_value ) >= 0 )
00321 msg_Dbg( p_access, "- SNR: %d", i_value );
00322 }
00323 else
00324 {
00325 msg_Dbg( p_access, "frontend has lost lock" );
00326 p_sys->i_frontend_timeout = mdate() + FRONTEND_LOCK_TIMEOUT;
00327 }
00328
00329 IF_UP( FE_REINIT )
00330 {
00331
00332 msg_Warn( p_access, "reiniting frontend");
00333 E_(FrontendSet)( p_access );
00334 }
00335 }
00336 }
00337 }
00338
00339
00340
00341 static int FrontendInfo( access_t *p_access )
00342 {
00343 access_sys_t *p_sys = p_access->p_sys;
00344 frontend_t *p_frontend = p_sys->p_frontend;
00345 int i_ret;
00346
00347
00348 if( (i_ret = ioctl( p_sys->i_frontend_handle, FE_GET_INFO,
00349 &p_frontend->info )) < 0 )
00350 {
00351 msg_Err( p_access, "ioctl FE_GET_INFO failed (%d) %s", i_ret,
00352 strerror(errno) );
00353 return VLC_EGENERIC;
00354 }
00355
00356
00357 msg_Dbg(p_access, "Frontend Info:" );
00358 msg_Dbg(p_access, " name = %s", p_frontend->info.name );
00359 switch( p_frontend->info.type )
00360 {
00361 case FE_QPSK:
00362 msg_Dbg( p_access, " type = QPSK (DVB-S)" );
00363 break;
00364 case FE_QAM:
00365 msg_Dbg( p_access, " type = QAM (DVB-C)" );
00366 break;
00367 case FE_OFDM:
00368 msg_Dbg( p_access, " type = OFDM (DVB-T)" );
00369 break;
00370 #if 0
00371 case FE_MEMORY:
00372 msg_Dbg(p_access, " type = MEMORY" );
00373 break;
00374 case FE_NET:
00375 msg_Dbg(p_access, " type = NETWORK" );
00376 break;
00377 #endif
00378 default:
00379 msg_Err( p_access, " unknown frontend type (%d)",
00380 p_frontend->info.type );
00381 return VLC_EGENERIC;
00382 }
00383 msg_Dbg(p_access, " frequency_min = %u (kHz)",
00384 p_frontend->info.frequency_min);
00385 msg_Dbg(p_access, " frequency_max = %u (kHz)",
00386 p_frontend->info.frequency_max);
00387 msg_Dbg(p_access, " frequency_stepsize = %u",
00388 p_frontend->info.frequency_stepsize);
00389 msg_Dbg(p_access, " frequency_tolerance = %u",
00390 p_frontend->info.frequency_tolerance);
00391 msg_Dbg(p_access, " symbol_rate_min = %u (kHz)",
00392 p_frontend->info.symbol_rate_min);
00393 msg_Dbg(p_access, " symbol_rate_max = %u (kHz)",
00394 p_frontend->info.symbol_rate_max);
00395 msg_Dbg(p_access, " symbol_rate_tolerance (ppm) = %u",
00396 p_frontend->info.symbol_rate_tolerance);
00397 msg_Dbg(p_access, " notifier_delay (ms) = %u",
00398 p_frontend->info.notifier_delay );
00399
00400 msg_Dbg(p_access, "Frontend Info capability list:");
00401 if( p_frontend->info.caps & FE_IS_STUPID)
00402 msg_Dbg(p_access, " no capabilities - frontend is stupid!");
00403 if( p_frontend->info.caps & FE_CAN_INVERSION_AUTO)
00404 msg_Dbg(p_access, " inversion auto");
00405 if( p_frontend->info.caps & FE_CAN_FEC_1_2)
00406 msg_Dbg(p_access, " forward error correction 1/2");
00407 if( p_frontend->info.caps & FE_CAN_FEC_2_3)
00408 msg_Dbg(p_access, " forward error correction 2/3");
00409 if( p_frontend->info.caps & FE_CAN_FEC_3_4)
00410 msg_Dbg(p_access, " forward error correction 3/4");
00411 if( p_frontend->info.caps & FE_CAN_FEC_4_5)
00412 msg_Dbg(p_access, " forward error correction 4/5");
00413 if( p_frontend->info.caps & FE_CAN_FEC_5_6)
00414 msg_Dbg(p_access, " forward error correction 5/6");
00415 if( p_frontend->info.caps & FE_CAN_FEC_6_7)
00416 msg_Dbg(p_access, " forward error correction 6/7");
00417 if( p_frontend->info.caps & FE_CAN_FEC_7_8)
00418 msg_Dbg(p_access, " forward error correction 7/8");
00419 if( p_frontend->info.caps & FE_CAN_FEC_8_9)
00420 msg_Dbg(p_access, " forward error correction 8/9");
00421 if( p_frontend->info.caps & FE_CAN_FEC_AUTO)
00422 msg_Dbg(p_access, " forward error correction auto");
00423 if( p_frontend->info.caps & FE_CAN_QPSK)
00424 msg_Dbg(p_access, " card can do QPSK");
00425 if( p_frontend->info.caps & FE_CAN_QAM_16)
00426 msg_Dbg(p_access, " card can do QAM 16");
00427 if( p_frontend->info.caps & FE_CAN_QAM_32)
00428 msg_Dbg(p_access, " card can do QAM 32");
00429 if( p_frontend->info.caps & FE_CAN_QAM_64)
00430 msg_Dbg(p_access, " card can do QAM 64");
00431 if( p_frontend->info.caps & FE_CAN_QAM_128)
00432 msg_Dbg(p_access, " card can do QAM 128");
00433 if( p_frontend->info.caps & FE_CAN_QAM_256)
00434 msg_Dbg(p_access, " card can do QAM 256");
00435 if( p_frontend->info.caps & FE_CAN_QAM_AUTO)
00436 msg_Dbg(p_access, " card can do QAM auto");
00437 if( p_frontend->info.caps & FE_CAN_TRANSMISSION_MODE_AUTO)
00438 msg_Dbg(p_access, " transmission mode auto");
00439 if( p_frontend->info.caps & FE_CAN_BANDWIDTH_AUTO)
00440 msg_Dbg(p_access, " bandwidth mode auto");
00441 if( p_frontend->info.caps & FE_CAN_GUARD_INTERVAL_AUTO)
00442 msg_Dbg(p_access, " guard interval mode auto");
00443 if( p_frontend->info.caps & FE_CAN_HIERARCHY_AUTO)
00444 msg_Dbg(p_access, " hierarchy mode auto");
00445 if( p_frontend->info.caps & FE_CAN_MUTE_TS)
00446 msg_Dbg(p_access, " card can mute TS");
00447 if( p_frontend->info.caps & FE_CAN_RECOVER)
00448 msg_Dbg(p_access, " card can recover from a cable unplug");
00449 msg_Dbg(p_access, "End of capability list");
00450
00451 return VLC_SUCCESS;
00452 }
00453
00454
00455
00456
00457 static fe_spectral_inversion_t DecodeInversion( access_t *p_access )
00458 {
00459 vlc_value_t val;
00460 fe_spectral_inversion_t fe_inversion = 0;
00461
00462 var_Get( p_access, "dvb-inversion", &val );
00463 msg_Dbg( p_access, "using inversion=%d", val.i_int );
00464
00465 switch( val.i_int )
00466 {
00467 case 0: fe_inversion = INVERSION_OFF; break;
00468 case 1: fe_inversion = INVERSION_ON; break;
00469 case 2: fe_inversion = INVERSION_AUTO; break;
00470 default:
00471 msg_Dbg( p_access, "dvb has inversion not set, using auto");
00472 fe_inversion = INVERSION_AUTO;
00473 break;
00474 }
00475 return fe_inversion;
00476 }
00477
00478 static fe_code_rate_t DecodeFEC( access_t *p_access, int i_val )
00479 {
00480 fe_code_rate_t fe_fec = FEC_NONE;
00481
00482 msg_Dbg( p_access, "using fec=%d", i_val );
00483
00484 switch( i_val )
00485 {
00486 case 0: fe_fec = FEC_NONE; break;
00487 case 1: fe_fec = FEC_1_2; break;
00488 case 2: fe_fec = FEC_2_3; break;
00489 case 3: fe_fec = FEC_3_4; break;
00490 case 4: fe_fec = FEC_4_5; break;
00491 case 5: fe_fec = FEC_5_6; break;
00492 case 6: fe_fec = FEC_6_7; break;
00493 case 7: fe_fec = FEC_7_8; break;
00494 case 8: fe_fec = FEC_8_9; break;
00495 case 9: fe_fec = FEC_AUTO; break;
00496 default:
00497
00498 fe_fec = FEC_NONE;
00499 msg_Err( p_access, "argument has invalid FEC (%d)", i_val);
00500 break;
00501 }
00502 return fe_fec;
00503 }
00504
00505 static fe_modulation_t DecodeModulation( access_t *p_access )
00506 {
00507 vlc_value_t val;
00508 fe_modulation_t fe_modulation = 0;
00509
00510 var_Get( p_access, "dvb-modulation", &val );
00511
00512 switch( val.i_int )
00513 {
00514 case -1: fe_modulation = QPSK; break;
00515 case 0: fe_modulation = QAM_AUTO; break;
00516 case 16: fe_modulation = QAM_16; break;
00517 case 32: fe_modulation = QAM_32; break;
00518 case 64: fe_modulation = QAM_64; break;
00519 case 128: fe_modulation = QAM_128; break;
00520 case 256: fe_modulation = QAM_256; break;
00521 default:
00522 msg_Dbg( p_access, "terrestrial/cable dvb has constellation/modulation not set, using auto");
00523 fe_modulation = QAM_AUTO;
00524 break;
00525 }
00526 return fe_modulation;
00527 }
00528
00529
00530
00531
00532 static fe_sec_voltage_t DecodeVoltage( access_t *p_access )
00533 {
00534 vlc_value_t val;
00535 fe_sec_voltage_t fe_voltage;
00536
00537 var_Get( p_access, "dvb-voltage", &val );
00538 msg_Dbg( p_access, "using voltage=%d", val.i_int );
00539
00540 switch( val.i_int )
00541 {
00542 case 0: fe_voltage = SEC_VOLTAGE_OFF; break;
00543 case 13: fe_voltage = SEC_VOLTAGE_13; break;
00544 case 18: fe_voltage = SEC_VOLTAGE_18; break;
00545 default:
00546 fe_voltage = SEC_VOLTAGE_OFF;
00547 msg_Err( p_access, "argument has invalid voltage (%d)", val.i_int );
00548 break;
00549 }
00550 return fe_voltage;
00551 }
00552
00553 static fe_sec_tone_mode_t DecodeTone( access_t *p_access )
00554 {
00555 vlc_value_t val;
00556 fe_sec_tone_mode_t fe_tone;
00557
00558 var_Get( p_access, "dvb-tone", &val );
00559 msg_Dbg( p_access, "using tone=%d", val.i_int );
00560
00561 switch( val.i_int )
00562 {
00563 case 0: fe_tone = SEC_TONE_OFF; break;
00564 case 1: fe_tone = SEC_TONE_ON; break;
00565 default:
00566 fe_tone = SEC_TONE_OFF;
00567 msg_Err( p_access, "argument has invalid tone mode (%d)", val.i_int);
00568 break;
00569 }
00570 return fe_tone;
00571 }
00572
00573 struct diseqc_cmd_t
00574 {
00575 struct dvb_diseqc_master_cmd cmd;
00576 uint32_t wait;
00577 };
00578
00579 static int DoDiseqc( access_t *p_access )
00580 {
00581 access_sys_t *p_sys = p_access->p_sys;
00582 vlc_value_t val;
00583 int i_frequency, i_lnb_slof;
00584 fe_sec_voltage_t fe_voltage;
00585 fe_sec_tone_mode_t fe_tone;
00586 int i_err;
00587
00588 var_Get( p_access, "dvb-frequency", &val );
00589 i_frequency = val.i_int;
00590 var_Get( p_access, "dvb-lnb-slof", &val );
00591 i_lnb_slof = val.i_int;
00592
00593 var_Get( p_access, "dvb-tone", &val );
00594 if( val.i_int == -1 )
00595 {
00596 if( i_frequency >= i_lnb_slof )
00597 val.i_int = 1;
00598 else
00599 val.i_int = 0;
00600 var_Set( p_access, "dvb-tone", val );
00601 }
00602
00603 fe_voltage = DecodeVoltage( p_access );
00604 fe_tone = DecodeTone( p_access );
00605
00606
00607 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_SET_TONE, SEC_TONE_OFF )) < 0 )
00608 {
00609 msg_Err( p_access, "ioctl FE_SET_TONE failed, tone=%s (%d) %s",
00610 fe_tone == SEC_TONE_ON ? "on" : "off", i_err,
00611 strerror(errno) );
00612 return i_err;
00613 }
00614
00615
00616 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_SET_VOLTAGE, fe_voltage )) < 0 )
00617 {
00618 msg_Err( p_access, "ioctl FE_SET_VOLTAGE failed, voltage=%d (%d) %s",
00619 fe_voltage, i_err, strerror(errno) );
00620 return i_err;
00621 }
00622
00623 var_Get( p_access, "dvb-high-voltage", &val );
00624 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_ENABLE_HIGH_LNB_VOLTAGE,
00625 val.b_bool )) < 0 && val.b_bool )
00626 {
00627 msg_Err( p_access,
00628 "ioctl FE_ENABLE_HIGH_LNB_VOLTAGE failed, val=%d (%d) %s",
00629 val.b_bool, i_err, strerror(errno) );
00630 }
00631
00632
00633 msleep(15000);
00634
00635 var_Get( p_access, "dvb-satno", &val );
00636 if( val.i_int > 0 && val.i_int < 5 )
00637 {
00638
00639
00640
00641
00642
00643 struct diseqc_cmd_t cmd = { {{0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00}, 4}, 0 };
00644
00645
00646
00647
00648 cmd.cmd.msg[3] = 0xf0
00649 | (((val.i_int - 1) * 4) & 0xc)
00650 | (fe_voltage == SEC_VOLTAGE_13 ? 0 : 2)
00651 | (fe_tone == SEC_TONE_ON ? 1 : 0);
00652
00653 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_DISEQC_SEND_MASTER_CMD,
00654 &cmd.cmd )) < 0 )
00655 {
00656 msg_Err( p_access, "ioctl FE_SEND_MASTER_CMD failed (%d) %s",
00657 i_err, strerror(errno) );
00658 return i_err;
00659 }
00660
00661 msleep(15000 + cmd.wait * 1000);
00662
00663
00664 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_DISEQC_SEND_BURST,
00665 ((val.i_int - 1) % 2) ? SEC_MINI_B : SEC_MINI_A )) < 0 )
00666 {
00667 msg_Err( p_access, "ioctl FE_SEND_BURST failed (%d) %s",
00668 i_err, strerror(errno) );
00669 return i_err;
00670 }
00671
00672 msleep(15000);
00673 }
00674
00675 if( (i_err = ioctl( p_sys->i_frontend_handle, FE_SET_TONE, fe_tone )) < 0 )
00676 {
00677 msg_Err( p_access, "ioctl FE_SET_TONE failed, tone=%s (%d) %s",
00678 fe_tone == SEC_TONE_ON ? "on" : "off", i_err,
00679 strerror(errno) );
00680 return i_err;
00681 }
00682
00683 msleep(50000);
00684 return 0;
00685 }
00686
00687 static int FrontendSetQPSK( access_t *p_access )
00688 {
00689 access_sys_t *p_sys = p_access->p_sys;
00690 struct dvb_frontend_parameters fep;
00691 int i_ret;
00692 vlc_value_t val;
00693 int i_frequency, i_lnb_slof = 0, i_lnb_lof1, i_lnb_lof2 = 0;
00694
00695
00696 var_Get( p_access, "dvb-frequency", &val );
00697 i_frequency = val.i_int;
00698
00699 var_Get( p_access, "dvb-lnb-lof1", &val );
00700 if ( val.i_int == 0 )
00701 {
00702
00703 if ( i_frequency >= 950000 && i_frequency <= 2150000 )
00704 {
00705 msg_Dbg( p_access, "frequency %d is in IF-band", i_frequency );
00706 i_lnb_lof1 = 0;
00707 }
00708 else if ( i_frequency >= 2500000 && i_frequency <= 2700000 )
00709 {
00710 msg_Dbg( p_access, "frequency %d is in S-band", i_frequency );
00711 i_lnb_lof1 = 3650000;
00712 }
00713 else if ( i_frequency >= 3400000 && i_frequency <= 4200000 )
00714 {
00715 msg_Dbg( p_access, "frequency %d is in C-band (lower)",
00716 i_frequency );
00717 i_lnb_lof1 = 5150000;
00718 }
00719 else if ( i_frequency >= 4500000 && i_frequency <= 4800000 )
00720 {
00721 msg_Dbg( p_access, "frequency %d is in C-band (higher)",
00722 i_frequency );
00723 i_lnb_lof1 = 5950000;
00724 }
00725 else if ( i_frequency >= 10700000 && i_frequency <= 13250000 )
00726 {
00727 msg_Dbg( p_access, "frequency %d is in Ku-band",
00728 i_frequency );
00729 i_lnb_lof1 = 9750000;
00730 i_lnb_lof2 = 10600000;
00731 i_lnb_slof = 11700000;
00732 }
00733 else
00734 {
00735 msg_Err( p_access, "frequency %d is out of any known band",
00736 i_frequency );
00737 msg_Err( p_access, "specify dvb-lnb-lof1 manually for the local "
00738 "oscillator frequency" );
00739 return VLC_EGENERIC;
00740 }
00741 val.i_int = i_lnb_lof1;
00742 var_Set( p_access, "dvb-lnb-lof1", val );
00743 val.i_int = i_lnb_lof2;
00744 var_Set( p_access, "dvb-lnb-lof2", val );
00745 val.i_int = i_lnb_slof;
00746 var_Set( p_access, "dvb-lnb-slof", val );
00747 }
00748 else
00749 {
00750 i_lnb_lof1 = val.i_int;
00751 var_Get( p_access, "dvb-lnb-lof2", &val );
00752 i_lnb_lof2 = val.i_int;
00753 var_Get( p_access, "dvb-lnb-slof", &val );
00754 i_lnb_slof = val.i_int;
00755 }
00756
00757 if( i_lnb_slof && i_frequency >= i_lnb_slof )
00758 {
00759 i_frequency -= i_lnb_lof2;
00760 }
00761 else
00762 {
00763 i_frequency -= i_lnb_lof1;
00764 }
00765 fep.frequency = i_frequency >= 0 ? i_frequency : -i_frequency;
00766
00767 fep.inversion = DecodeInversion( p_access );
00768
00769 var_Get( p_access, "dvb-srate", &val );
00770 fep.u.qpsk.symbol_rate = val.i_int;
00771
00772 var_Get( p_access, "dvb-fec", &val );
00773 fep.u.qpsk.fec_inner = DecodeFEC( p_access, val.i_int );
00774
00775 if( DoDiseqc( p_access ) < 0 )
00776 {
00777 return VLC_EGENERIC;
00778 }
00779
00780
00781 for( ; ; )
00782 {
00783 struct dvb_frontend_event event;
00784 if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
00785 && errno == EWOULDBLOCK )
00786 break;
00787 }
00788
00789
00790 if( (i_ret = ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep )) < 0 )
00791 {
00792 msg_Err( p_access, "DVB-S: setting frontend failed (%d) %s", i_ret,
00793 strerror(errno) );
00794 return VLC_EGENERIC;
00795 }
00796
00797 return VLC_SUCCESS;
00798 }
00799
00800
00801
00802
00803 static int FrontendSetQAM( access_t *p_access )
00804 {
00805 access_sys_t *p_sys = p_access->p_sys;
00806 struct dvb_frontend_parameters fep;
00807 vlc_value_t val;
00808 int i_ret;
00809
00810
00811
00812 var_Get( p_access, "dvb-frequency", &val );
00813 fep.frequency = val.i_int;
00814
00815 fep.inversion = DecodeInversion( p_access );
00816
00817 var_Get( p_access, "dvb-srate", &val );
00818 fep.u.qam.symbol_rate = val.i_int;
00819
00820 var_Get( p_access, "dvb-fec", &val );
00821 fep.u.qam.fec_inner = DecodeFEC( p_access, val.i_int );
00822
00823 fep.u.qam.modulation = DecodeModulation( p_access );
00824
00825
00826 for( ; ; )
00827 {
00828 struct dvb_frontend_event event;
00829 if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
00830 && errno == EWOULDBLOCK )
00831 break;
00832 }
00833
00834
00835 if( (i_ret = ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep )) < 0 )
00836 {
00837 msg_Err( p_access, "DVB-C: setting frontend failed (%d) %s", i_ret,
00838 strerror(errno) );
00839 return VLC_EGENERIC;
00840 }
00841
00842 return VLC_SUCCESS;
00843 }
00844
00845
00846
00847
00848 static fe_bandwidth_t DecodeBandwidth( access_t *p_access )
00849 {
00850 vlc_value_t val;
00851 fe_bandwidth_t fe_bandwidth = 0;
00852
00853 var_Get( p_access, "dvb-bandwidth", &val );
00854 msg_Dbg( p_access, "using bandwidth=%d", val.i_int );
00855
00856 switch( val.i_int )
00857 {
00858 case 0: fe_bandwidth = BANDWIDTH_AUTO; break;
00859 case 6: fe_bandwidth = BANDWIDTH_6_MHZ; break;
00860 case 7: fe_bandwidth = BANDWIDTH_7_MHZ; break;
00861 case 8: fe_bandwidth = BANDWIDTH_8_MHZ; break;
00862 default:
00863 msg_Dbg( p_access, "terrestrial dvb has bandwidth not set, using auto" );
00864 fe_bandwidth = BANDWIDTH_AUTO;
00865 break;
00866 }
00867 return fe_bandwidth;
00868 }
00869
00870 static fe_transmit_mode_t DecodeTransmission( access_t *p_access )
00871 {
00872 vlc_value_t val;
00873 fe_transmit_mode_t fe_transmission = 0;
00874
00875 var_Get( p_access, "dvb-transmission", &val );
00876 msg_Dbg( p_access, "using transmission=%d", val.i_int );
00877
00878 switch( val.i_int )
00879 {
00880 case 0: fe_transmission = TRANSMISSION_MODE_AUTO; break;
00881 case 2: fe_transmission = TRANSMISSION_MODE_2K; break;
00882 case 8: fe_transmission = TRANSMISSION_MODE_8K; break;
00883 default:
00884 msg_Dbg( p_access, "terrestrial dvb has transmission mode not set, using auto");
00885 fe_transmission = TRANSMISSION_MODE_AUTO;
00886 break;
00887 }
00888 return fe_transmission;
00889 }
00890
00891 static fe_guard_interval_t DecodeGuardInterval( access_t *p_access )
00892 {
00893 vlc_value_t val;
00894 fe_guard_interval_t fe_guard = 0;
00895
00896 var_Get( p_access, "dvb-guard", &val );
00897 msg_Dbg( p_access, "using guard=%d", val.i_int );
00898
00899 switch( val.i_int )
00900 {
00901 case 0: fe_guard = GUARD_INTERVAL_AUTO; break;
00902 case 4: fe_guard = GUARD_INTERVAL_1_4; break;
00903 case 8: fe_guard = GUARD_INTERVAL_1_8; break;
00904 case 16: fe_guard = GUARD_INTERVAL_1_16; break;
00905 case 32: fe_guard = GUARD_INTERVAL_1_32; break;
00906 default:
00907 msg_Dbg( p_access, "terrestrial dvb has guard interval not set, using auto");
00908 fe_guard = GUARD_INTERVAL_AUTO;
00909 break;
00910 }
00911 return fe_guard;
00912 }
00913
00914 static fe_hierarchy_t DecodeHierarchy( access_t *p_access )
00915 {
00916 vlc_value_t val;
00917 fe_hierarchy_t fe_hierarchy = 0;
00918
00919 var_Get( p_access, "dvb-hierarchy", &val );
00920 msg_Dbg( p_access, "using hierarchy=%d", val.i_int );
00921
00922 switch( val.i_int )
00923 {
00924 case -1: fe_hierarchy = HIERARCHY_NONE; break;
00925 case 0: fe_hierarchy = HIERARCHY_AUTO; break;
00926 case 1: fe_hierarchy = HIERARCHY_1; break;
00927 case 2: fe_hierarchy = HIERARCHY_2; break;
00928 case 4: fe_hierarchy = HIERARCHY_4; break;
00929 default:
00930 msg_Dbg( p_access, "terrestrial dvb has hierarchy not set, using auto");
00931 fe_hierarchy = HIERARCHY_AUTO;
00932 break;
00933 }
00934 return fe_hierarchy;
00935 }
00936
00937 static int FrontendSetOFDM( access_t * p_access )
00938 {
00939 access_sys_t *p_sys = p_access->p_sys;
00940 struct dvb_frontend_parameters fep;
00941 vlc_value_t val;
00942 int ret;
00943
00944
00945
00946 var_Get( p_access, "dvb-frequency", &val );
00947 fep.frequency = val.i_int;
00948
00949 fep.inversion = DecodeInversion( p_access );
00950
00951 fep.u.ofdm.bandwidth = DecodeBandwidth( p_access );
00952 var_Get( p_access, "dvb-code-rate-hp", &val );
00953 fep.u.ofdm.code_rate_HP = DecodeFEC( p_access, val.i_int );
00954 var_Get( p_access, "dvb-code-rate-lp", &val );
00955 fep.u.ofdm.code_rate_LP = DecodeFEC( p_access, val.i_int );
00956 fep.u.ofdm.constellation = DecodeModulation( p_access );
00957 fep.u.ofdm.transmission_mode = DecodeTransmission( p_access );
00958 fep.u.ofdm.guard_interval = DecodeGuardInterval( p_access );
00959 fep.u.ofdm.hierarchy_information = DecodeHierarchy( p_access );
00960
00961
00962 for( ; ; )
00963 {
00964 struct dvb_frontend_event event;
00965 if ( ioctl( p_sys->i_frontend_handle, FE_GET_EVENT, &event ) < 0
00966 && errno == EWOULDBLOCK )
00967 break;
00968 }
00969
00970
00971 if( (ret = ioctl( p_sys->i_frontend_handle, FE_SET_FRONTEND, &fep )) < 0 )
00972 {
00973 msg_Err( p_access, "DVB-T: setting frontend failed (%d) %s", ret,
00974 strerror(errno) );
00975 return -1;
00976 }
00977
00978 return VLC_SUCCESS;
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989 int E_(DMXSetFilter)( access_t * p_access, int i_pid, int * pi_fd, int i_type )
00990 {
00991 struct dmx_pes_filter_params s_filter_params;
00992 int i_ret;
00993 unsigned int i_adapter, i_device;
00994 char dmx[128];
00995 vlc_value_t val;
00996
00997 var_Get( p_access, "dvb-adapter", &val );
00998 i_adapter = val.i_int;
00999 var_Get( p_access, "dvb-device", &val );
01000 i_device = val.i_int;
01001
01002 if( snprintf( dmx, sizeof(dmx), DMX, i_adapter, i_device )
01003 >= (int)sizeof(dmx) )
01004 {
01005 msg_Err( p_access, "snprintf() truncated string for DMX" );
01006 dmx[sizeof(dmx) - 1] = '\0';
01007 }
01008
01009 msg_Dbg( p_access, "Opening device %s", dmx );
01010 if( (*pi_fd = open(dmx, O_RDWR)) < 0 )
01011 {
01012 msg_Err( p_access, "DMXSetFilter: opening device failed (%s)",
01013 strerror(errno) );
01014 return VLC_EGENERIC;
01015 }
01016
01017
01018 s_filter_params.pid = i_pid;
01019 s_filter_params.input = DMX_IN_FRONTEND;
01020 s_filter_params.output = DMX_OUT_TS_TAP;
01021 s_filter_params.flags = DMX_IMMEDIATE_START;
01022
01023 switch ( i_type )
01024 {
01025 case 1:
01026 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO0 for PID %d", i_pid);
01027 s_filter_params.pes_type = DMX_PES_VIDEO0;
01028 break;
01029 case 2:
01030 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO0 for PID %d", i_pid);
01031 s_filter_params.pes_type = DMX_PES_AUDIO0;
01032 break;
01033 case 3:
01034 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT0 for PID %d", i_pid);
01035 s_filter_params.pes_type = DMX_PES_TELETEXT0;
01036 break;
01037 case 4:
01038 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE0 for PID %d", i_pid);
01039 s_filter_params.pes_type = DMX_PES_SUBTITLE0;
01040 break;
01041 case 5:
01042 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR0 for PID %d", i_pid);
01043 s_filter_params.pes_type = DMX_PES_PCR0;
01044 break;
01045
01046 case 6:
01047 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO1 for PID %d", i_pid);
01048 s_filter_params.pes_type = DMX_PES_VIDEO1;
01049 break;
01050 case 7:
01051 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO1 for PID %d", i_pid);
01052 s_filter_params.pes_type = DMX_PES_AUDIO1;
01053 break;
01054 case 8:
01055 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT1 for PID %d", i_pid);
01056 s_filter_params.pes_type = DMX_PES_TELETEXT1;
01057 break;
01058 case 9:
01059 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE1 for PID %d", i_pid);
01060 s_filter_params.pes_type = DMX_PES_SUBTITLE1;
01061 break;
01062 case 10:
01063 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR1 for PID %d", i_pid);
01064 s_filter_params.pes_type = DMX_PES_PCR1;
01065 break;
01066
01067 case 11:
01068 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO2 for PID %d", i_pid);
01069 s_filter_params.pes_type = DMX_PES_VIDEO2;
01070 break;
01071 case 12:
01072 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO2 for PID %d", i_pid);
01073 s_filter_params.pes_type = DMX_PES_AUDIO2;
01074 break;
01075 case 13:
01076 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT2 for PID %d", i_pid);
01077 s_filter_params.pes_type = DMX_PES_TELETEXT2;
01078 break;
01079 case 14:
01080 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE2 for PID %d", i_pid);
01081 s_filter_params.pes_type = DMX_PES_SUBTITLE2;
01082 break;
01083 case 15:
01084 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR2 for PID %d", i_pid);
01085 s_filter_params.pes_type = DMX_PES_PCR2;
01086 break;
01087
01088 case 16:
01089 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_VIDEO3 for PID %d", i_pid);
01090 s_filter_params.pes_type = DMX_PES_VIDEO3;
01091 break;
01092 case 17:
01093 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_AUDIO3 for PID %d", i_pid);
01094 s_filter_params.pes_type = DMX_PES_AUDIO3;
01095 break;
01096 case 18:
01097 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_TELETEXT3 for PID %d", i_pid);
01098 s_filter_params.pes_type = DMX_PES_TELETEXT3;
01099 break;
01100 case 19:
01101 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_SUBTITLE3 for PID %d", i_pid);
01102 s_filter_params.pes_type = DMX_PES_SUBTITLE3;
01103 break;
01104 case 20:
01105 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_PCR3 for PID %d", i_pid);
01106 s_filter_params.pes_type = DMX_PES_PCR3;
01107 break;
01108
01109 case 21:
01110 default:
01111 msg_Dbg(p_access, "DMXSetFilter: DMX_PES_OTHER for PID %d", i_pid);
01112 s_filter_params.pes_type = DMX_PES_OTHER;
01113 break;
01114 }
01115
01116
01117 if( (i_ret = ioctl( *pi_fd, DMX_SET_PES_FILTER, &s_filter_params )) < 0 )
01118 {
01119 msg_Err( p_access, "DMXSetFilter: failed with %d (%s)", i_ret,
01120 strerror(errno) );
01121 return VLC_EGENERIC;
01122 }
01123 return VLC_SUCCESS;
01124 }
01125
01126
01127
01128
01129 int E_(DMXUnsetFilter)( access_t * p_access, int i_fd )
01130 {
01131 int i_ret;
01132
01133 if( (i_ret = ioctl( i_fd, DMX_STOP )) < 0 )
01134 {
01135 msg_Err( p_access, "DMX_STOP failed for demux (%d) %s",
01136 i_ret, strerror(errno) );
01137 return i_ret;
01138 }
01139
01140 msg_Dbg( p_access, "DMXUnsetFilter: closing demux %d", i_fd );
01141 close( i_fd );
01142 return VLC_SUCCESS;
01143 }
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153 int E_(DVROpen)( access_t * p_access )
01154 {
01155 access_sys_t *p_sys = p_access->p_sys;
01156 unsigned int i_adapter, i_device;
01157 char dvr[128];
01158 vlc_value_t val;
01159
01160 var_Get( p_access, "dvb-adapter", &val );
01161 i_adapter = val.i_int;
01162 var_Get( p_access, "dvb-device", &val );
01163 i_device = val.i_int;
01164
01165 if( snprintf( dvr, sizeof(dvr), DVR, i_adapter, i_device )
01166 >= (int)sizeof(dvr) )
01167 {
01168 msg_Err( p_access, "snprintf() truncated string for DVR" );
01169 dvr[sizeof(dvr) - 1] = '\0';
01170 }
01171
01172 msg_Dbg( p_access, "Opening device %s", dvr );
01173 if( (p_sys->i_handle = open(dvr, O_RDONLY)) < 0 )
01174 {
01175 msg_Err( p_access, "DVROpen: opening device failed (%s)",
01176 strerror(errno) );
01177 return VLC_EGENERIC;
01178 }
01179
01180 if( fcntl( p_sys->i_handle, F_SETFL, O_NONBLOCK ) == -1 )
01181 {
01182 msg_Warn( p_access, "DVROpen: couldn't set non-blocking mode (%s)",
01183 strerror(errno) );
01184 }
01185
01186 return VLC_SUCCESS;
01187 }
01188
01189
01190
01191
01192 void E_(DVRClose)( access_t * p_access )
01193 {
01194 access_sys_t *p_sys = p_access->p_sys;
01195
01196 close( p_sys->i_handle );
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207 int E_(CAMOpen)( access_t *p_access )
01208 {
01209 access_sys_t *p_sys = p_access->p_sys;
01210 char ca[128];
01211 int i_adapter, i_device, i_slot;
01212 ca_caps_t caps;
01213
01214 i_adapter = var_GetInteger( p_access, "dvb-adapter" );
01215 i_device = var_GetInteger( p_access, "dvb-device" );
01216
01217 if( snprintf( ca, sizeof(ca), CA, i_adapter, i_device ) >= (int)sizeof(ca) )
01218 {
01219 msg_Err( p_access, "snprintf() truncated string for CA" );
01220 ca[sizeof(ca) - 1] = '\0';
01221 }
01222
01223 msg_Dbg( p_access, "Opening device %s", ca );
01224 if( (p_sys->i_ca_handle = open(ca, O_RDWR | O_NONBLOCK)) < 0 )
01225 {
01226 msg_Warn( p_access, "CAMInit: opening CAM device failed (%s)",
01227 strerror(errno) );
01228 p_sys->i_ca_handle = 0;
01229 return VLC_EGENERIC;
01230 }
01231
01232 if ( ioctl( p_sys->i_ca_handle, CA_GET_CAP, &caps ) != 0 )
01233 {
01234 msg_Err( p_access, "CAMInit: ioctl() error getting CAM capabilities" );
01235 close( p_sys->i_ca_handle );
01236 p_sys->i_ca_handle = 0;
01237 return VLC_EGENERIC;
01238 }
01239
01240
01241 msg_Dbg( p_access, "CAMInit: CA interface with %d %s", caps.slot_num,
01242 caps.slot_num == 1 ? "slot" : "slots" );
01243 if ( caps.slot_type & CA_CI )
01244 msg_Dbg( p_access, "CAMInit: CI high level interface type (not supported)" );
01245 if ( caps.slot_type & CA_CI_LINK )
01246 msg_Dbg( p_access, "CAMInit: CI link layer level interface type" );
01247 if ( caps.slot_type & CA_CI_PHYS )
01248 msg_Dbg( p_access, "CAMInit: CI physical layer level interface type (not supported) " );
01249 if ( caps.slot_type & CA_DESCR )
01250 msg_Dbg( p_access, "CAMInit: built-in descrambler detected" );
01251 if ( caps.slot_type & CA_SC )
01252 msg_Dbg( p_access, "CAMInit: simple smart card interface" );
01253
01254 msg_Dbg( p_access, "CAMInit: %d available %s", caps.descr_num,
01255 caps.descr_num == 1 ? "descrambler (key)" : "descramblers (keys)" );
01256 if ( caps.descr_type & CA_ECD )
01257 msg_Dbg( p_access, "CAMInit: ECD scrambling system supported" );
01258 if ( caps.descr_type & CA_NDS )
01259 msg_Dbg( p_access, "CAMInit: NDS scrambling system supported" );
01260 if ( caps.descr_type & CA_DSS )
01261 msg_Dbg( p_access, "CAMInit: DSS scrambling system supported" );
01262
01263 if ( caps.slot_num == 0 )
01264 {
01265 msg_Err( p_access, "CAMInit: CAM module with no slots" );
01266 close( p_sys->i_ca_handle );
01267 p_sys->i_ca_handle = 0;
01268 return VLC_EGENERIC;
01269 }
01270
01271 if ( !(caps.slot_type & CA_CI_LINK) )
01272 {
01273 msg_Err( p_access, "CAMInit: no compatible CAM module" );
01274 close( p_sys->i_ca_handle );
01275 p_sys->i_ca_handle = 0;
01276 return VLC_EGENERIC;
01277 }
01278
01279 p_sys->i_nb_slots = caps.slot_num;
01280 memset( p_sys->pb_active_slot, 0, sizeof(vlc_bool_t) * MAX_CI_SLOTS );
01281
01282 for ( i_slot = 0; i_slot < p_sys->i_nb_slots; i_slot++ )
01283 {
01284 if ( ioctl( p_sys->i_ca_handle, CA_RESET, 1 << i_slot) != 0 )
01285 {
01286 msg_Err( p_access, "CAMInit: couldn't reset slot %d", i_slot );
01287 }
01288 }
01289
01290 p_sys->i_ca_timeout = 100000;
01291
01292 msleep( 1000000 );
01293
01294 return VLC_SUCCESS;
01295 }
01296
01297
01298
01299
01300 int E_(CAMPoll)( access_t * p_access )
01301 {
01302 access_sys_t *p_sys = p_access->p_sys;
01303
01304 if ( p_sys->i_ca_handle == 0 )
01305 {
01306 return VLC_EGENERIC;
01307 }
01308
01309 return E_(en50221_Poll)( p_access );
01310 }
01311
01312
01313
01314
01315 int E_(CAMSet)( access_t * p_access, dvbpsi_pmt_t *p_pmt )
01316 {
01317 access_sys_t *p_sys = p_access->p_sys;
01318
01319 if ( p_sys->i_ca_handle == 0 )
01320 {
01321 return VLC_EGENERIC;
01322 }
01323
01324 E_(en50221_SetCAPMT)( p_access, p_pmt );
01325
01326 return VLC_SUCCESS;
01327 }
01328
01329
01330
01331
01332 void E_(CAMClose)( access_t * p_access )
01333 {
01334 access_sys_t *p_sys = p_access->p_sys;
01335
01336 E_(en50221_End)( p_access );
01337
01338 if ( p_sys->i_ca_handle )
01339 {
01340 close( p_sys->i_ca_handle );
01341 }
01342 }
01343